summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/sqlite/sqlite3.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/sqlite/sqlite3.c')
-rw-r--r--src/3rdparty/sqlite/sqlite3.c26239
1 files changed, 15539 insertions, 10700 deletions
diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c
index 03fa649610..9c73927982 100644
--- a/src/3rdparty/sqlite/sqlite3.c
+++ b/src/3rdparty/sqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.7.17. By combining all the individual C code files into this
+** version 3.8.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -25,549 +25,6 @@
#ifndef SQLITE_API
# define SQLITE_API
#endif
-/************** Begin file sqliteInt.h ***************************************/
-/*
-** 2001 September 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** Internal interface definitions for SQLite.
-**
-*/
-#ifndef _SQLITEINT_H_
-#define _SQLITEINT_H_
-
-/*
-** These #defines should enable >2GB file support on POSIX if the
-** underlying operating system supports it. If the OS lacks
-** large file support, or if the OS is windows, these should be no-ops.
-**
-** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
-** system #includes. Hence, this block of code must be the very first
-** code in all source files.
-**
-** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
-** on the compiler command line. This is necessary if you are compiling
-** on a recent machine (ex: Red Hat 7.2) but you want your code to work
-** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
-** without this option, LFS is enable. But LFS does not exist in the kernel
-** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
-** portability you should omit LFS.
-**
-** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
-*/
-#ifndef SQLITE_DISABLE_LFS
-# define _LARGE_FILE 1
-# ifndef _FILE_OFFSET_BITS
-# define _FILE_OFFSET_BITS 64
-# endif
-# define _LARGEFILE_SOURCE 1
-#endif
-
-/*
-** Include the configuration header output by 'configure' if we're using the
-** autoconf-based build
-*/
-#ifdef _HAVE_SQLITE_CONFIG_H
-#include "config.h"
-#endif
-
-/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
-/************** Begin file sqliteLimit.h *************************************/
-/*
-** 2007 May 7
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file defines various limits of what SQLite can process.
-*/
-
-/*
-** The maximum length of a TEXT or BLOB in bytes. This also
-** limits the size of a row in a table or index.
-**
-** The hard limit is the ability of a 32-bit signed integer
-** to count the size: 2^31-1 or 2147483647.
-*/
-#ifndef SQLITE_MAX_LENGTH
-# define SQLITE_MAX_LENGTH 1000000000
-#endif
-
-/*
-** This is the maximum number of
-**
-** * Columns in a table
-** * Columns in an index
-** * Columns in a view
-** * Terms in the SET clause of an UPDATE statement
-** * Terms in the result set of a SELECT statement
-** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
-** * Terms in the VALUES clause of an INSERT statement
-**
-** The hard upper limit here is 32676. Most database people will
-** tell you that in a well-normalized database, you usually should
-** not have more than a dozen or so columns in any table. And if
-** that is the case, there is no point in having more than a few
-** dozen values in any of the other situations described above.
-*/
-#ifndef SQLITE_MAX_COLUMN
-# define SQLITE_MAX_COLUMN 2000
-#endif
-
-/*
-** The maximum length of a single SQL statement in bytes.
-**
-** It used to be the case that setting this value to zero would
-** turn the limit off. That is no longer true. It is not possible
-** to turn this limit off.
-*/
-#ifndef SQLITE_MAX_SQL_LENGTH
-# define SQLITE_MAX_SQL_LENGTH 1000000000
-#endif
-
-/*
-** The maximum depth of an expression tree. This is limited to
-** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
-** want to place more severe limits on the complexity of an
-** expression.
-**
-** A value of 0 used to mean that the limit was not enforced.
-** But that is no longer true. The limit is now strictly enforced
-** at all times.
-*/
-#ifndef SQLITE_MAX_EXPR_DEPTH
-# define SQLITE_MAX_EXPR_DEPTH 1000
-#endif
-
-/*
-** The maximum number of terms in a compound SELECT statement.
-** The code generator for compound SELECT statements does one
-** level of recursion for each term. A stack overflow can result
-** if the number of terms is too large. In practice, most SQL
-** never has more than 3 or 4 terms. Use a value of 0 to disable
-** any limit on the number of terms in a compount SELECT.
-*/
-#ifndef SQLITE_MAX_COMPOUND_SELECT
-# define SQLITE_MAX_COMPOUND_SELECT 500
-#endif
-
-/*
-** The maximum number of opcodes in a VDBE program.
-** Not currently enforced.
-*/
-#ifndef SQLITE_MAX_VDBE_OP
-# define SQLITE_MAX_VDBE_OP 25000
-#endif
-
-/*
-** The maximum number of arguments to an SQL function.
-*/
-#ifndef SQLITE_MAX_FUNCTION_ARG
-# define SQLITE_MAX_FUNCTION_ARG 127
-#endif
-
-/*
-** The maximum number of in-memory pages to use for the main database
-** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
-*/
-#ifndef SQLITE_DEFAULT_CACHE_SIZE
-# define SQLITE_DEFAULT_CACHE_SIZE 2000
-#endif
-#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
-# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
-#endif
-
-/*
-** The default number of frames to accumulate in the log file before
-** checkpointing the database in WAL mode.
-*/
-#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
-# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
-#endif
-
-/*
-** The maximum number of attached databases. This must be between 0
-** and 62. The upper bound on 62 is because a 64-bit integer bitmap
-** is used internally to track attached databases.
-*/
-#ifndef SQLITE_MAX_ATTACHED
-# define SQLITE_MAX_ATTACHED 10
-#endif
-
-
-/*
-** The maximum value of a ?nnn wildcard that the parser will accept.
-*/
-#ifndef SQLITE_MAX_VARIABLE_NUMBER
-# define SQLITE_MAX_VARIABLE_NUMBER 999
-#endif
-
-/* Maximum page size. The upper bound on this value is 65536. This a limit
-** imposed by the use of 16-bit offsets within each page.
-**
-** Earlier versions of SQLite allowed the user to change this value at
-** compile time. This is no longer permitted, on the grounds that it creates
-** a library that is technically incompatible with an SQLite library
-** compiled with a different limit. If a process operating on a database
-** with a page-size of 65536 bytes crashes, then an instance of SQLite
-** compiled with the default page-size limit will not be able to rollback
-** the aborted transaction. This could lead to database corruption.
-*/
-#ifdef SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_MAX_PAGE_SIZE
-#endif
-#define SQLITE_MAX_PAGE_SIZE 65536
-
-
-/*
-** The default size of a database page.
-*/
-#ifndef SQLITE_DEFAULT_PAGE_SIZE
-# define SQLITE_DEFAULT_PAGE_SIZE 1024
-#endif
-#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_DEFAULT_PAGE_SIZE
-# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
-#endif
-
-/*
-** Ordinarily, if no value is explicitly provided, SQLite creates databases
-** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
-** device characteristics (sector-size and atomic write() support),
-** SQLite may choose a larger value. This constant is the maximum value
-** SQLite will choose on its own.
-*/
-#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
-# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
-#endif
-#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
-# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
-# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
-#endif
-
-
-/*
-** Maximum number of pages in one database file.
-**
-** This is really just the default value for the max_page_count pragma.
-** This value can be lowered (or raised) at run-time using that the
-** max_page_count macro.
-*/
-#ifndef SQLITE_MAX_PAGE_COUNT
-# define SQLITE_MAX_PAGE_COUNT 1073741823
-#endif
-
-/*
-** Maximum length (in bytes) of the pattern in a LIKE or GLOB
-** operator.
-*/
-#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
-# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
-#endif
-
-/*
-** Maximum depth of recursion for triggers.
-**
-** A value of 1 means that a trigger program will not be able to itself
-** fire any triggers. A value of 0 means that no trigger programs at all
-** may be executed.
-*/
-#ifndef SQLITE_MAX_TRIGGER_DEPTH
-# define SQLITE_MAX_TRIGGER_DEPTH 1000
-#endif
-
-/************** End of sqliteLimit.h *****************************************/
-/************** Continuing where we left off in sqliteInt.h ******************/
-
-/* Disable nuisance warnings on Borland compilers */
-#if defined(__BORLANDC__)
-#pragma warn -rch /* unreachable code */
-#pragma warn -ccc /* Condition is always true or false */
-#pragma warn -aus /* Assigned value is never used */
-#pragma warn -csu /* Comparing signed and unsigned */
-#pragma warn -spa /* Suspicious pointer arithmetic */
-#endif
-
-/* Needed for various definitions... */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
-#endif
-
-#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
-# define _BSD_SOURCE
-#endif
-
-/*
-** Include standard header files as necessary
-*/
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-
-/*
-** The following macros are used to cast pointers to integers and
-** integers to pointers. The way you do this varies from one compiler
-** to the next, so we have developed the following set of #if statements
-** to generate appropriate macros for a wide range of compilers.
-**
-** The correct "ANSI" way to do this is to use the intptr_t type.
-** Unfortunately, that typedef is not available on all compilers, or
-** if it is available, it requires an #include of specific headers
-** that vary from one machine to the next.
-**
-** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
-** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
-** So we have to define the macros in different ways depending on the
-** compiler.
-*/
-#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
-# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
-#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
-# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
-# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
-#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
-# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
-#else /* Generates a warning - but it always works */
-# define SQLITE_INT_TO_PTR(X) ((void*)(X))
-# define SQLITE_PTR_TO_INT(X) ((int)(X))
-#endif
-
-/*
-** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
-** 0 means mutexes are permanently disable and the library is never
-** threadsafe. 1 means the library is serialized which is the highest
-** level of threadsafety. 2 means the libary is multithreaded - multiple
-** threads can use SQLite as long as no two threads try to use the same
-** database connection at the same time.
-**
-** Older versions of SQLite used an optional THREADSAFE macro.
-** We support that for legacy.
-*/
-#if !defined(SQLITE_THREADSAFE)
-# if defined(THREADSAFE)
-# define SQLITE_THREADSAFE THREADSAFE
-# else
-# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
-# endif
-#endif
-
-/*
-** Powersafe overwrite is on by default. But can be turned off using
-** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
-*/
-#ifndef SQLITE_POWERSAFE_OVERWRITE
-# define SQLITE_POWERSAFE_OVERWRITE 1
-#endif
-
-/*
-** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
-** It determines whether or not the features related to
-** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
-** be overridden at runtime using the sqlite3_config() API.
-*/
-#if !defined(SQLITE_DEFAULT_MEMSTATUS)
-# define SQLITE_DEFAULT_MEMSTATUS 1
-#endif
-
-/*
-** Exactly one of the following macros must be defined in order to
-** specify which memory allocation subsystem to use.
-**
-** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
-** SQLITE_WIN32_MALLOC // Use Win32 native heap API
-** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
-** SQLITE_MEMDEBUG // Debugging version of system malloc()
-**
-** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
-** assert() macro is enabled, each call into the Win32 native heap subsystem
-** will cause HeapValidate to be called. If heap validation should fail, an
-** assertion will be triggered.
-**
-** (Historical note: There used to be several other options, but we've
-** pared it down to just these three.)
-**
-** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
-** the default.
-*/
-#if defined(SQLITE_SYSTEM_MALLOC) \
- + defined(SQLITE_WIN32_MALLOC) \
- + defined(SQLITE_ZERO_MALLOC) \
- + defined(SQLITE_MEMDEBUG)>1
-# error "Two or more of the following compile-time configuration options\
- are defined but at most one is allowed:\
- SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
- SQLITE_ZERO_MALLOC"
-#endif
-#if defined(SQLITE_SYSTEM_MALLOC) \
- + defined(SQLITE_WIN32_MALLOC) \
- + defined(SQLITE_ZERO_MALLOC) \
- + defined(SQLITE_MEMDEBUG)==0
-# define SQLITE_SYSTEM_MALLOC 1
-#endif
-
-/*
-** 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_MALLOC_SOFT_LIMIT)
-# define SQLITE_MALLOC_SOFT_LIMIT 1024
-#endif
-
-/*
-** We need to define _XOPEN_SOURCE as follows in order to enable
-** recursive mutexes on most Unix systems. But Mac OS X is different.
-** The _XOPEN_SOURCE define causes problems for Mac OS X we are told,
-** so it is omitted there. See ticket #2673.
-**
-** Later we learn that _XOPEN_SOURCE is poorly or incorrectly
-** implemented on some systems. So we avoid defining it at all
-** if it is already defined or if it is unneeded because we are
-** not doing a threadsafe build. Ticket #2681.
-**
-** See also ticket #2741.
-*/
-#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \
- && !defined(__APPLE__) && SQLITE_THREADSAFE
-# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */
-#endif
-
-/*
-** The TCL headers are only needed when compiling the TCL bindings.
-*/
-#if defined(SQLITE_TCL) || defined(TCLSH)
-# include <tcl.h>
-#endif
-
-/*
-** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
-** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
-** make it true by defining or undefining NDEBUG.
-**
-** Setting NDEBUG makes the code smaller and run faster by disabling the
-** number assert() statements in the code. So we want the default action
-** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
-** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
-** feature.
-*/
-#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
-# define NDEBUG 1
-#endif
-#if defined(NDEBUG) && defined(SQLITE_DEBUG)
-# undef NDEBUG
-#endif
-
-/*
-** The testcase() macro is used to aid in coverage testing. When
-** doing coverage testing, the condition inside the argument to
-** testcase() must be evaluated both true and false in order to
-** get full branch coverage. The testcase() macro is inserted
-** to help ensure adequate test coverage in places where simple
-** condition/decision coverage is inadequate. For example, testcase()
-** can be used to make sure boundary values are tested. For
-** bitmask tests, testcase() can be used to make sure each bit
-** is significant and used at least once. On switch statements
-** where multiple cases go to the same block of code, testcase()
-** can insure that all cases are evaluated.
-**
-*/
-#ifdef SQLITE_COVERAGE_TEST
-SQLITE_PRIVATE void sqlite3Coverage(int);
-# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
-#else
-# define testcase(X)
-#endif
-
-/*
-** The TESTONLY macro is used to enclose variable declarations or
-** other bits of code that are needed to support the arguments
-** within testcase() and assert() macros.
-*/
-#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
-# define TESTONLY(X) X
-#else
-# define TESTONLY(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
-
-/*
-** 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
-** are included in a few cases in order to enhance the resilience
-** of SQLite to unexpected behavior - to make the code "self-healing"
-** or "ductile" rather than being "brittle" and crashing at the first
-** hint of unplanned behavior.
-**
-** In other words, ALWAYS and NEVER are added for defensive code.
-**
-** When doing coverage testing ALWAYS and NEVER are hard-coded to
-** be true and false so that the unreachable code then specify will
-** not be counted as untested code.
-*/
-#if defined(SQLITE_COVERAGE_TEST)
-# define ALWAYS(X) (1)
-# define NEVER(X) (0)
-#elif !defined(NDEBUG)
-# define ALWAYS(X) ((X)?1:(assert(0),0))
-# define NEVER(X) ((X)?(assert(0),1):0)
-#else
-# define ALWAYS(X) (X)
-# define NEVER(X) (X)
-#endif
-
-/*
-** Return true (non-zero) if the input is a integer that is too large
-** to fit in 32-bits. This macro is used inside of various testcase()
-** macros to verify that we have tested SQLite for large-file support.
-*/
-#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
-
-/*
-** The macro unlikely() is a hint that surrounds a boolean
-** expression that is usually false. Macro likely() surrounds
-** a boolean expression that is usually true. GCC is able to
-** use these hints to generate better code, sometimes.
-*/
-#if defined(__GNUC__) && 0
-# define likely(X) __builtin_expect((X),1)
-# define unlikely(X) __builtin_expect((X),0)
-#else
-# define likely(X) !!(X)
-# define unlikely(X) !!(X)
-#endif
-
-/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
/************** Begin file sqlite3.h *****************************************/
/*
** 2001 September 15
@@ -678,9 +135,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.7.17"
-#define SQLITE_VERSION_NUMBER 3007017
-#define SQLITE_SOURCE_ID "2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668"
+#define SQLITE_VERSION "3.8.2"
+#define SQLITE_VERSION_NUMBER 3008002
+#define SQLITE_SOURCE_ID "2013-12-06 14:53:30 27392118af4c38c5203a04b8013e1afdb1cebd0d"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -941,7 +398,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** <ul>
** <li> The application must insure that the 1st parameter to sqlite3_exec()
** is a valid and open [database connection].
-** <li> The application must not close [database connection] specified by
+** <li> The application must not close the [database connection] specified by
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
** <li> The application must not modify the SQL statement text passed into
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
@@ -1018,7 +475,7 @@ SQLITE_API int sqlite3_exec(
** [sqlite3_extended_result_codes()] API.
**
** Some of the available extended result codes are listed here.
-** One may expect the number of extended result codes will be expand
+** One may expect the number of extended result codes will increase
** over time. Software that uses extended result codes should expect
** to see new result codes in future releases of SQLite.
**
@@ -1049,11 +506,15 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8))
+#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
+#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
+#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
+#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
@@ -1068,8 +529,10 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8))
#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
+#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
+#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
/*
** CAPI3REF: Flags For File Open Operations
@@ -1478,6 +941,14 @@ struct sqlite3_io_methods {
** can be queried by passing in a pointer to a negative number. This
** file-control is used internally to implement [PRAGMA mmap_size].
**
+** <li>[[SQLITE_FCNTL_TRACE]]
+** The [SQLITE_FCNTL_TRACE] file control provides advisory information
+** to the VFS about what the higher layers of the SQLite stack are doing.
+** This file control is used by some VFS activity tracing [shims].
+** The argument is a zero-terminated string. Higher layers in the
+** SQLite stack may generate instances of this file control if
+** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
+**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -1497,6 +968,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_BUSYHANDLER 15
#define SQLITE_FCNTL_TEMPFILENAME 16
#define SQLITE_FCNTL_MMAP_SIZE 18
+#define SQLITE_FCNTL_TRACE 19
/*
** CAPI3REF: Mutex Handle
@@ -1941,7 +1413,7 @@ SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
** that causes the corresponding memory allocation to fail.
**
-** The xInit method initializes the memory allocator. (For example,
+** The xInit method initializes the memory allocator. For example,
** it might allocate any require mutexes or initialize internal data
** structures. The xShutdown method is invoked (indirectly) by
** [sqlite3_shutdown()] and should deallocate any resources acquired
@@ -2183,27 +1655,27 @@ struct sqlite3_mem_methods {
** function must be threadsafe. </dd>
**
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
-** <dd> This option takes a single argument of type int. If non-zero, then
+** <dd>^(This option takes a single argument of type int. If non-zero, then
** URI handling is globally enabled. If the parameter is zero, then URI handling
-** is globally disabled. If URI handling is globally enabled, all filenames
+** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
-** connection is opened. If it is globally disabled, filenames are
+** connection is opened. ^If it is globally disabled, filenames are
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
-** database connection is opened. By default, URI handling is globally
+** database connection is opened. ^(By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
-** [SQLITE_USE_URI] symbol defined.
+** [SQLITE_USE_URI] symbol defined.)^
**
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
-** <dd> This option takes a single integer argument which is interpreted as
+** <dd>^This option takes a single integer argument which is interpreted as
** a boolean in order to enable or disable the use of covering indices for
-** full table scans in the query optimizer. The default setting is determined
+** full table scans in the query optimizer. ^The default setting is determined
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
** if that compile-time option is omitted.
** The ability to disable the use of covering indices for full table scans
** is because some incorrectly coded legacy applications might malfunction
-** malfunction when the optimization is enabled. Providing the ability to
+** when the optimization is enabled. Providing the ability to
** disable the optimization allows the older, buggy application code to work
** without change even with newer versions of SQLite.
**
@@ -2232,17 +1704,24 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_CONFIG_MMAP_SIZE]]
** <dt>SQLITE_CONFIG_MMAP_SIZE
-** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
+** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
** that are the default mmap size limit (the default setting for
** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
-** The default setting can be overridden by each database connection using
+** ^The default setting can be overridden by each database connection using
** either the [PRAGMA mmap_size] command, or by using the
-** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size
+** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
** cannot be changed at run-time. Nor may the maximum allowed mmap size
** exceed the compile-time maximum mmap size set by the
-** [SQLITE_MAX_MMAP_SIZE] compile-time option.
-** If either argument to this option is negative, then that argument is
+** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
+** ^If either argument to this option is negative, then that argument is
** changed to its compile-time default.
+**
+** [[SQLITE_CONFIG_WIN32_HEAPSIZE]]
+** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
+** <dd>^This option is only available if SQLite is compiled for Windows
+** with the [SQLITE_WIN32_MALLOC] pre-processor macro defined.
+** SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
+** that specifies the maximum size of the created heap.
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -2267,6 +1746,7 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
+#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
/*
** CAPI3REF: Database Connection Configuration Options
@@ -2343,19 +1823,21 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
/*
** CAPI3REF: Last Insert Rowid
**
-** ^Each entry in an SQLite table has a unique 64-bit signed
+** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
+** has a unique 64-bit signed
** integer key called the [ROWID | "rowid"]. ^The rowid is always available
** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
** names are not also used by explicitly declared columns. ^If
** the table has a column of type [INTEGER PRIMARY KEY] then that column
** is another alias for the rowid.
**
-** ^This routine returns the [rowid] of the most recent
-** successful [INSERT] into the database from the [database connection]
-** in the first argument. ^As of SQLite version 3.7.7, this routines
-** records the last insert rowid of both ordinary tables and [virtual tables].
-** ^If no successful [INSERT]s
-** have ever occurred on that database connection, zero is returned.
+** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the
+** most recent successful [INSERT] into a rowid table or [virtual table]
+** on database connection D.
+** ^Inserts into [WITHOUT ROWID] tables are not recorded.
+** ^If no successful [INSERT]s into rowid tables
+** have ever occurred on the database connection D,
+** then sqlite3_last_insert_rowid(D) returns zero.
**
** ^(If an [INSERT] occurs within a trigger or within a [virtual table]
** method, then this routine will return the [rowid] of the inserted
@@ -3128,9 +2610,10 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
** interface is to keep a GUI updated during a large query.
**
** ^The parameter P is passed through as the only parameter to the
-** callback function X. ^The parameter N is the number of
+** callback function X. ^The parameter N is the approximate number of
** [virtual machine instructions] that are evaluated between successive
-** invocations of the callback X.
+** invocations of the callback X. ^If N is less than one then the progress
+** handler is disabled.
**
** ^Only a single progress handler may be defined at one time per
** [database connection]; setting a new progress handler cancels the
@@ -3664,7 +3147,6 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** choice of query plan if the parameter is the left-hand side of a [LIKE]
** or [GLOB] operator or if the parameter is compared to an indexed column
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
-** the
** </li>
** </ol>
*/
@@ -4326,19 +3808,19 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
**
** <tr><td> NULL <td> INTEGER <td> Result is 0
** <tr><td> NULL <td> FLOAT <td> Result is 0.0
-** <tr><td> NULL <td> TEXT <td> Result is NULL pointer
-** <tr><td> NULL <td> BLOB <td> Result is NULL pointer
+** <tr><td> NULL <td> TEXT <td> Result is a NULL pointer
+** <tr><td> NULL <td> BLOB <td> Result is a NULL pointer
** <tr><td> INTEGER <td> FLOAT <td> Convert from integer to float
** <tr><td> INTEGER <td> TEXT <td> ASCII rendering of the integer
** <tr><td> INTEGER <td> BLOB <td> Same as INTEGER->TEXT
-** <tr><td> FLOAT <td> INTEGER <td> Convert from float to integer
+** <tr><td> FLOAT <td> INTEGER <td> [CAST] to INTEGER
** <tr><td> FLOAT <td> TEXT <td> ASCII rendering of the float
-** <tr><td> FLOAT <td> BLOB <td> Same as FLOAT->TEXT
-** <tr><td> TEXT <td> INTEGER <td> Use atoi()
-** <tr><td> TEXT <td> FLOAT <td> Use atof()
+** <tr><td> FLOAT <td> BLOB <td> [CAST] to BLOB
+** <tr><td> TEXT <td> INTEGER <td> [CAST] to INTEGER
+** <tr><td> TEXT <td> FLOAT <td> [CAST] to REAL
** <tr><td> TEXT <td> BLOB <td> No change
-** <tr><td> BLOB <td> INTEGER <td> Convert to TEXT then use atoi()
-** <tr><td> BLOB <td> FLOAT <td> Convert to TEXT then use atof()
+** <tr><td> BLOB <td> INTEGER <td> [CAST] to INTEGER
+** <tr><td> BLOB <td> FLOAT <td> [CAST] to REAL
** <tr><td> BLOB <td> TEXT <td> Add a zero terminator if needed
** </table>
** </blockquote>)^
@@ -4394,7 +3876,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
** [sqlite3_finalize()] is called. ^The memory space used to hold strings
** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned
-** [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
+** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
** [sqlite3_free()].
**
** ^(If a memory allocation error occurs during the evaluation of any
@@ -4750,41 +4232,49 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
/*
** CAPI3REF: Function Auxiliary Data
**
-** The following two functions may be used by scalar SQL functions to
+** These functions may be used by (non-aggregate) SQL functions to
** associate metadata with argument values. If the same value is passed to
** multiple invocations of the same SQL function during query execution, under
-** some circumstances the associated metadata may be preserved. This may
-** be used, for example, to add a regular-expression matching scalar
-** function. The compiled version of the regular expression is stored as
-** metadata associated with the SQL value passed as the regular expression
-** pattern. The compiled regular expression can be reused on multiple
-** invocations of the same function so that the original pattern string
-** does not need to be recompiled on each invocation.
+** some circumstances the associated metadata may be preserved. An example
+** of where this might be useful is in a regular-expression matching
+** function. The compiled version of the regular expression can be stored as
+** metadata associated with the pattern string.
+** Then as long as the pattern string remains the same,
+** the compiled regular expression can be reused on multiple
+** invocations of the same function.
**
** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If no metadata has been ever
-** been set for the Nth argument of the function, or if the corresponding
-** function parameter has changed since the meta-data was set,
-** then sqlite3_get_auxdata() returns a NULL pointer.
-**
-** ^The sqlite3_set_auxdata() interface saves the metadata
-** pointed to by its 3rd parameter as the metadata for the N-th
-** argument of the application-defined function. Subsequent
-** calls to sqlite3_get_auxdata() might return this data, if it has
-** not been destroyed.
-** ^If it is not NULL, SQLite will invoke the destructor
-** function given by the 4th parameter to sqlite3_set_auxdata() on
-** the metadata when the corresponding function parameter changes
-** or when the SQL statement completes, whichever comes first.
-**
-** SQLite is free to call the destructor and drop metadata on any
-** parameter of any function at any time. ^The only guarantee is that
-** the destructor will be called before the metadata is dropped.
+** value to the application-defined function. ^If there is no metadata
+** associated with the function argument, this sqlite3_get_auxdata() interface
+** returns a NULL pointer.
+**
+** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
+** argument of the application-defined function. ^Subsequent
+** calls to sqlite3_get_auxdata(C,N) return P from the most recent
+** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
+** NULL if the metadata has been discarded.
+** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
+** SQLite will invoke the destructor function X with parameter P exactly
+** once, when the metadata is discarded.
+** SQLite is free to discard the metadata at any time, including: <ul>
+** <li> when the corresponding function parameter changes, or
+** <li> when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
+** SQL statement, or
+** <li> when sqlite3_set_auxdata() is invoked again on the same parameter, or
+** <li> during the original sqlite3_set_auxdata() call when a memory
+** allocation error occurs. </ul>)^
+**
+** Note the last bullet in particular. The destructor X in
+** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
+** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
+** should be called near the end of the function implementation and the
+** function implementation should not make any use of P after
+** sqlite3_set_auxdata() has been called.
**
** ^(In practice, metadata is preserved between function calls for
-** expressions that are constant at compile time. This includes literal
-** values and [parameters].)^
+** function parameters that are compile-time constants, including literal
+** values and [parameters] and expressions composed from the same.)^
**
** These routines must be called from the same thread in which
** the SQL function is running.
@@ -5089,6 +4579,11 @@ SQLITE_API int sqlite3_key(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The key */
);
+SQLITE_API int sqlite3_key_v2(
+ sqlite3 *db, /* Database to be rekeyed */
+ const char *zDbName, /* Name of the database */
+ const void *pKey, int nKey /* The key */
+);
/*
** Change the key on an open database. If the current database is not
@@ -5102,6 +4597,11 @@ SQLITE_API int sqlite3_rekey(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
);
+SQLITE_API int sqlite3_rekey_v2(
+ sqlite3 *db, /* Database to be rekeyed */
+ const char *zDbName, /* Name of the database */
+ const void *pKey, int nKey /* The new key */
+);
/*
** Specify the activation key for a SEE database. Unless
@@ -5353,12 +4853,13 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
**
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
-** to be invoked whenever a row is updated, inserted or deleted.
+** to be invoked whenever a row is updated, inserted or deleted in
+** a rowid table.
** ^Any callback set by a previous call to this function
** for the same database connection is overridden.
**
** ^The second argument is a pointer to the function to invoke when a
-** row is updated, inserted or deleted.
+** row is updated, inserted or deleted in a rowid table.
** ^The first argument to the callback is a copy of the third argument
** to sqlite3_update_hook().
** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
@@ -5371,6 +4872,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
**
** ^(The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).)^
+** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
**
** ^In the current implementation, the update hook
** is not invoked when duplication rows are deleted because of an
@@ -5452,8 +4954,8 @@ SQLITE_API int sqlite3_release_memory(int);
**
** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
** memory as possible from database connection D. Unlike the
-** [sqlite3_release_memory()] interface, this interface is effect even
-** when then [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
+** [sqlite3_release_memory()] interface, this interface is in effect even
+** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
** omitted.
**
** See also: [sqlite3_release_memory()]
@@ -5687,11 +5189,24 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** on the list of automatic extensions is a harmless no-op. ^No entry point
** will be called more than once for each database connection that is opened.
**
-** See also: [sqlite3_reset_auto_extension()].
+** See also: [sqlite3_reset_auto_extension()]
+** and [sqlite3_cancel_auto_extension()]
*/
SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
/*
+** CAPI3REF: Cancel Automatic Extension Loading
+**
+** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
+** initialization routine X that was registered using a prior call to
+** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
+** routine returns 1 if initialization routine X was successfully
+** unregistered and it returns 0 if X was not on the list of initialization
+** routines.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
+
+/*
** CAPI3REF: Reset Automatic Extension Loading
**
** ^This interface disables all automatic extensions previously
@@ -5815,10 +5330,22 @@ struct sqlite3_module {
** the correct order to satisfy the ORDER BY clause so that no separate
** sorting step is required.
**
-** ^The estimatedCost value is an estimate of the cost of doing the
-** 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).
+** ^The estimatedCost value is an estimate of the cost of a particular
+** strategy. A cost of N indicates that the cost of the strategy is similar
+** to a linear scan of an SQLite table with N rows. A cost of log(N)
+** indicates that the expense of the operation is similar to that of a
+** binary search on a unique indexed field of an SQLite table with N rows.
+**
+** ^The estimatedRows value is an estimate of the number of rows that
+** will be returned by the strategy.
+**
+** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
+** structure for SQLite version 3.8.2. If a virtual table extension is
+** used with an SQLite version earlier than 3.8.2, the results of attempting
+** to read or write the estimatedRows field are undefined (but are likely
+** to included crashing the application). The estimatedRows field should
+** therefore only be used if [sqlite3_libversion_number()] returns a
+** value greater than or equal to 3008002.
*/
struct sqlite3_index_info {
/* Inputs */
@@ -5843,7 +5370,9 @@ struct sqlite3_index_info {
char *idxStr; /* String, possibly obtained from sqlite3_malloc */
int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
int orderByConsumed; /* True if output is already ordered */
- double estimatedCost; /* Estimated cost of using this index */
+ double estimatedCost; /* Estimated cost of using this index */
+ /* Fields below are only available in SQLite 3.8.2 and later */
+ sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
};
/*
@@ -6047,6 +5576,9 @@ typedef struct sqlite3_blob sqlite3_blob;
** interface. Use the [UPDATE] SQL command to change the size of a
** blob.
**
+** ^The [sqlite3_blob_open()] interface will fail for a [WITHOUT ROWID]
+** table. Incremental BLOB I/O is not possible on [WITHOUT ROWID] tables.
+**
** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
** and the built-in [zeroblob] SQL function can be used, if desired,
** to create an empty, zero-filled blob in which to read or write using
@@ -6570,7 +6102,8 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
-#define SQLITE_TESTCTRL_LAST 19
+#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
+#define SQLITE_TESTCTRL_LAST 20
/*
** CAPI3REF: SQLite Runtime Status
@@ -6803,6 +6336,12 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
** </dd>
+**
+** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
+** <dd>This parameter returns zero for the current value if and only if
+** all foreign key constraints (deferred or immediate) have been
+** resolved.)^ ^The highwater mark is always 0.
+** </dd>
** </dl>
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
@@ -6815,7 +6354,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_CACHE_HIT 7
#define SQLITE_DBSTATUS_CACHE_MISS 8
#define SQLITE_DBSTATUS_CACHE_WRITE 9
-#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_DEFERRED_FKS 10
+#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */
/*
@@ -6869,11 +6409,21 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** A non-zero value in this counter may indicate an opportunity to
** improvement performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.</dd>
+**
+** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
+** <dd>^This is the number of virtual machine operations executed
+** by the prepared statement if that number is less than or equal
+** to 2147483647. The number of virtual machine operations can be
+** used as a proxy for the total work done by the prepared statement.
+** If the number of virtual machine operations exceeds 2147483647
+** then the value returned by this statement status code is undefined.
+** </dd>
** </dl>
*/
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
#define SQLITE_STMTSTATUS_SORT 2
#define SQLITE_STMTSTATUS_AUTOINDEX 3
+#define SQLITE_STMTSTATUS_VM_STEP 4
/*
** CAPI3REF: Custom Page Cache Object
@@ -7752,7 +7302,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
#if 0
} /* End of the 'extern "C"' block */
#endif
-#endif
+#endif /* _SQLITE3_H_ */
/*
** 2010 August 30
@@ -7816,7 +7366,533 @@ struct sqlite3_rtree_geometry {
/************** End of sqlite3.h *********************************************/
+/************** Begin file sqliteInt.h ***************************************/
+/*
+** 2001 September 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Internal interface definitions for SQLite.
+**
+*/
+#ifndef _SQLITEINT_H_
+#define _SQLITEINT_H_
+
+/*
+** These #defines should enable >2GB file support on POSIX if the
+** underlying operating system supports it. If the OS lacks
+** large file support, or if the OS is windows, these should be no-ops.
+**
+** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
+** system #includes. Hence, this block of code must be the very first
+** code in all source files.
+**
+** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
+** on the compiler command line. This is necessary if you are compiling
+** on a recent machine (ex: Red Hat 7.2) but you want your code to work
+** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
+** without this option, LFS is enable. But LFS does not exist in the kernel
+** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
+** portability you should omit LFS.
+**
+** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
+*/
+#ifndef SQLITE_DISABLE_LFS
+# define _LARGE_FILE 1
+# ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+# endif
+# define _LARGEFILE_SOURCE 1
+#endif
+
+/*
+** Include the configuration header output by 'configure' if we're using the
+** autoconf-based build
+*/
+#ifdef _HAVE_SQLITE_CONFIG_H
+#include "config.h"
+#endif
+
+/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
+/************** Begin file sqliteLimit.h *************************************/
+/*
+** 2007 May 7
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file defines various limits of what SQLite can process.
+*/
+
+/*
+** The maximum length of a TEXT or BLOB in bytes. This also
+** limits the size of a row in a table or index.
+**
+** The hard limit is the ability of a 32-bit signed integer
+** to count the size: 2^31-1 or 2147483647.
+*/
+#ifndef SQLITE_MAX_LENGTH
+# define SQLITE_MAX_LENGTH 1000000000
+#endif
+
+/*
+** This is the maximum number of
+**
+** * Columns in a table
+** * Columns in an index
+** * Columns in a view
+** * Terms in the SET clause of an UPDATE statement
+** * Terms in the result set of a SELECT statement
+** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
+** * Terms in the VALUES clause of an INSERT statement
+**
+** The hard upper limit here is 32676. Most database people will
+** tell you that in a well-normalized database, you usually should
+** not have more than a dozen or so columns in any table. And if
+** that is the case, there is no point in having more than a few
+** dozen values in any of the other situations described above.
+*/
+#ifndef SQLITE_MAX_COLUMN
+# define SQLITE_MAX_COLUMN 2000
+#endif
+
+/*
+** The maximum length of a single SQL statement in bytes.
+**
+** It used to be the case that setting this value to zero would
+** turn the limit off. That is no longer true. It is not possible
+** to turn this limit off.
+*/
+#ifndef SQLITE_MAX_SQL_LENGTH
+# define SQLITE_MAX_SQL_LENGTH 1000000000
+#endif
+
+/*
+** The maximum depth of an expression tree. This is limited to
+** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
+** want to place more severe limits on the complexity of an
+** expression.
+**
+** A value of 0 used to mean that the limit was not enforced.
+** But that is no longer true. The limit is now strictly enforced
+** at all times.
+*/
+#ifndef SQLITE_MAX_EXPR_DEPTH
+# define SQLITE_MAX_EXPR_DEPTH 1000
+#endif
+
+/*
+** The maximum number of terms in a compound SELECT statement.
+** The code generator for compound SELECT statements does one
+** level of recursion for each term. A stack overflow can result
+** if the number of terms is too large. In practice, most SQL
+** never has more than 3 or 4 terms. Use a value of 0 to disable
+** any limit on the number of terms in a compount SELECT.
+*/
+#ifndef SQLITE_MAX_COMPOUND_SELECT
+# define SQLITE_MAX_COMPOUND_SELECT 500
+#endif
+
+/*
+** The maximum number of opcodes in a VDBE program.
+** Not currently enforced.
+*/
+#ifndef SQLITE_MAX_VDBE_OP
+# define SQLITE_MAX_VDBE_OP 25000
+#endif
+
+/*
+** The maximum number of arguments to an SQL function.
+*/
+#ifndef SQLITE_MAX_FUNCTION_ARG
+# define SQLITE_MAX_FUNCTION_ARG 127
+#endif
+
+/*
+** The maximum number of in-memory pages to use for the main database
+** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
+*/
+#ifndef SQLITE_DEFAULT_CACHE_SIZE
+# define SQLITE_DEFAULT_CACHE_SIZE 2000
+#endif
+#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
+# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
+#endif
+
+/*
+** The default number of frames to accumulate in the log file before
+** checkpointing the database in WAL mode.
+*/
+#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
+# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
+#endif
+
+/*
+** The maximum number of attached databases. This must be between 0
+** and 62. The upper bound on 62 is because a 64-bit integer bitmap
+** is used internally to track attached databases.
+*/
+#ifndef SQLITE_MAX_ATTACHED
+# define SQLITE_MAX_ATTACHED 10
+#endif
+
+
+/*
+** The maximum value of a ?nnn wildcard that the parser will accept.
+*/
+#ifndef SQLITE_MAX_VARIABLE_NUMBER
+# define SQLITE_MAX_VARIABLE_NUMBER 999
+#endif
+
+/* Maximum page size. The upper bound on this value is 65536. This a limit
+** imposed by the use of 16-bit offsets within each page.
+**
+** Earlier versions of SQLite allowed the user to change this value at
+** compile time. This is no longer permitted, on the grounds that it creates
+** a library that is technically incompatible with an SQLite library
+** compiled with a different limit. If a process operating on a database
+** with a page-size of 65536 bytes crashes, then an instance of SQLite
+** compiled with the default page-size limit will not be able to rollback
+** the aborted transaction. This could lead to database corruption.
+*/
+#ifdef SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_MAX_PAGE_SIZE
+#endif
+#define SQLITE_MAX_PAGE_SIZE 65536
+
+
+/*
+** The default size of a database page.
+*/
+#ifndef SQLITE_DEFAULT_PAGE_SIZE
+# define SQLITE_DEFAULT_PAGE_SIZE 1024
+#endif
+#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_DEFAULT_PAGE_SIZE
+# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
+#endif
+
+/*
+** Ordinarily, if no value is explicitly provided, SQLite creates databases
+** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
+** device characteristics (sector-size and atomic write() support),
+** SQLite may choose a larger value. This constant is the maximum value
+** SQLite will choose on its own.
+*/
+#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
+# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
+#endif
+#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
+# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
+# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
+#endif
+
+
+/*
+** Maximum number of pages in one database file.
+**
+** This is really just the default value for the max_page_count pragma.
+** This value can be lowered (or raised) at run-time using that the
+** max_page_count macro.
+*/
+#ifndef SQLITE_MAX_PAGE_COUNT
+# define SQLITE_MAX_PAGE_COUNT 1073741823
+#endif
+
+/*
+** Maximum length (in bytes) of the pattern in a LIKE or GLOB
+** operator.
+*/
+#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
+# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
+#endif
+
+/*
+** Maximum depth of recursion for triggers.
+**
+** A value of 1 means that a trigger program will not be able to itself
+** fire any triggers. A value of 0 means that no trigger programs at all
+** may be executed.
+*/
+#ifndef SQLITE_MAX_TRIGGER_DEPTH
+# define SQLITE_MAX_TRIGGER_DEPTH 1000
+#endif
+
+/************** End of sqliteLimit.h *****************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
+
+/* Disable nuisance warnings on Borland compilers */
+#if defined(__BORLANDC__)
+#pragma warn -rch /* unreachable code */
+#pragma warn -ccc /* Condition is always true or false */
+#pragma warn -aus /* Assigned value is never used */
+#pragma warn -csu /* Comparing signed and unsigned */
+#pragma warn -spa /* Suspicious pointer arithmetic */
+#endif
+
+/* Needed for various definitions... */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
+# define _BSD_SOURCE
+#endif
+
+/*
+** Include standard header files as necessary
+*/
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+/*
+** The following macros are used to cast pointers to integers and
+** integers to pointers. The way you do this varies from one compiler
+** to the next, so we have developed the following set of #if statements
+** to generate appropriate macros for a wide range of compilers.
+**
+** The correct "ANSI" way to do this is to use the intptr_t type.
+** Unfortunately, that typedef is not available on all compilers, or
+** if it is available, it requires an #include of specific headers
+** that vary from one machine to the next.
+**
+** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
+** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
+** So we have to define the macros in different ways depending on the
+** compiler.
+*/
+#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
+# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
+# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
+#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
+# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
+# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
+#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
+# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
+# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
+#else /* Generates a warning - but it always works */
+# define SQLITE_INT_TO_PTR(X) ((void*)(X))
+# define SQLITE_PTR_TO_INT(X) ((int)(X))
+#endif
+
+/*
+** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
+** 0 means mutexes are permanently disable and the library is never
+** threadsafe. 1 means the library is serialized which is the highest
+** level of threadsafety. 2 means the library is multithreaded - multiple
+** threads can use SQLite as long as no two threads try to use the same
+** database connection at the same time.
+**
+** Older versions of SQLite used an optional THREADSAFE macro.
+** We support that for legacy.
+*/
+#if !defined(SQLITE_THREADSAFE)
+# if defined(THREADSAFE)
+# define SQLITE_THREADSAFE THREADSAFE
+# else
+# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
+# endif
+#endif
+
+/*
+** Powersafe overwrite is on by default. But can be turned off using
+** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
+*/
+#ifndef SQLITE_POWERSAFE_OVERWRITE
+# define SQLITE_POWERSAFE_OVERWRITE 1
+#endif
+
+/*
+** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
+** It determines whether or not the features related to
+** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
+** be overridden at runtime using the sqlite3_config() API.
+*/
+#if !defined(SQLITE_DEFAULT_MEMSTATUS)
+# define SQLITE_DEFAULT_MEMSTATUS 1
+#endif
+
+/*
+** Exactly one of the following macros must be defined in order to
+** specify which memory allocation subsystem to use.
+**
+** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
+** SQLITE_WIN32_MALLOC // Use Win32 native heap API
+** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
+** SQLITE_MEMDEBUG // Debugging version of system malloc()
+**
+** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
+** assert() macro is enabled, each call into the Win32 native heap subsystem
+** will cause HeapValidate to be called. If heap validation should fail, an
+** assertion will be triggered.
+**
+** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
+** the default.
+*/
+#if defined(SQLITE_SYSTEM_MALLOC) \
+ + defined(SQLITE_WIN32_MALLOC) \
+ + defined(SQLITE_ZERO_MALLOC) \
+ + defined(SQLITE_MEMDEBUG)>1
+# error "Two or more of the following compile-time configuration options\
+ are defined but at most one is allowed:\
+ SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
+ SQLITE_ZERO_MALLOC"
+#endif
+#if defined(SQLITE_SYSTEM_MALLOC) \
+ + defined(SQLITE_WIN32_MALLOC) \
+ + defined(SQLITE_ZERO_MALLOC) \
+ + defined(SQLITE_MEMDEBUG)==0
+# define SQLITE_SYSTEM_MALLOC 1
+#endif
+
+/*
+** 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_MALLOC_SOFT_LIMIT)
+# define SQLITE_MALLOC_SOFT_LIMIT 1024
+#endif
+
+/*
+** We need to define _XOPEN_SOURCE as follows in order to enable
+** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
+** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
+** it.
+*/
+#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
+# define _XOPEN_SOURCE 600
+#endif
+
+/*
+** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
+** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
+** make it true by defining or undefining NDEBUG.
+**
+** Setting NDEBUG makes the code smaller and faster by disabling the
+** assert() statements in the code. So we want the default action
+** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
+** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
+** feature.
+*/
+#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
+# define NDEBUG 1
+#endif
+#if defined(NDEBUG) && defined(SQLITE_DEBUG)
+# undef NDEBUG
+#endif
+
+/*
+** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on.
+*/
+#if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG)
+# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1
+#endif
+
+/*
+** The testcase() macro is used to aid in coverage testing. When
+** doing coverage testing, the condition inside the argument to
+** testcase() must be evaluated both true and false in order to
+** get full branch coverage. The testcase() macro is inserted
+** to help ensure adequate test coverage in places where simple
+** condition/decision coverage is inadequate. For example, testcase()
+** can be used to make sure boundary values are tested. For
+** bitmask tests, testcase() can be used to make sure each bit
+** is significant and used at least once. On switch statements
+** where multiple cases go to the same block of code, testcase()
+** can insure that all cases are evaluated.
+**
+*/
+#ifdef SQLITE_COVERAGE_TEST
+SQLITE_PRIVATE void sqlite3Coverage(int);
+# define testcase(X) if( X ){ sqlite3Coverage(__LINE__); }
+#else
+# define testcase(X)
+#endif
+
+/*
+** The TESTONLY macro is used to enclose variable declarations or
+** other bits of code that are needed to support the arguments
+** within testcase() and assert() macros.
+*/
+#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
+# define TESTONLY(X) X
+#else
+# define TESTONLY(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
+
+/*
+** 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
+** are included in a few cases in order to enhance the resilience
+** of SQLite to unexpected behavior - to make the code "self-healing"
+** or "ductile" rather than being "brittle" and crashing at the first
+** hint of unplanned behavior.
+**
+** In other words, ALWAYS and NEVER are added for defensive code.
+**
+** When doing coverage testing ALWAYS and NEVER are hard-coded to
+** be true and false so that the unreachable code they specify will
+** not be counted as untested code.
+*/
+#if defined(SQLITE_COVERAGE_TEST)
+# define ALWAYS(X) (1)
+# define NEVER(X) (0)
+#elif !defined(NDEBUG)
+# define ALWAYS(X) ((X)?1:(assert(0),0))
+# define NEVER(X) ((X)?(assert(0),1):0)
+#else
+# define ALWAYS(X) (X)
+# define NEVER(X) (X)
+#endif
+
+/*
+** Return true (non-zero) if the input is a integer that is too large
+** to fit in 32-bits. This macro is used inside of various testcase()
+** macros to verify that we have tested SQLite for large-file support.
+*/
+#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
+
+/*
+** The macro unlikely() is a hint that surrounds a boolean
+** expression that is usually false. Macro likely() surrounds
+** a boolean expression that is usually true. These hints could,
+** in theory, be used by the compiler to generate better code, but
+** currently they are just comments for human readers.
+*/
+#define likely(X) (X)
+#define unlikely(X) (X)
+
/************** Include hash.h in the middle of sqliteInt.h ******************/
/************** Begin file hash.h ********************************************/
/*
@@ -7944,137 +8020,137 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_LP 22
#define TK_RP 23
#define TK_AS 24
-#define TK_COMMA 25
-#define TK_ID 26
-#define TK_INDEXED 27
-#define TK_ABORT 28
-#define TK_ACTION 29
-#define TK_AFTER 30
-#define TK_ANALYZE 31
-#define TK_ASC 32
-#define TK_ATTACH 33
-#define TK_BEFORE 34
-#define TK_BY 35
-#define TK_CASCADE 36
-#define TK_CAST 37
-#define TK_COLUMNKW 38
-#define TK_CONFLICT 39
-#define TK_DATABASE 40
-#define TK_DESC 41
-#define TK_DETACH 42
-#define TK_EACH 43
-#define TK_FAIL 44
-#define TK_FOR 45
-#define TK_IGNORE 46
-#define TK_INITIALLY 47
-#define TK_INSTEAD 48
-#define TK_LIKE_KW 49
-#define TK_MATCH 50
-#define TK_NO 51
-#define TK_KEY 52
-#define TK_OF 53
-#define TK_OFFSET 54
-#define TK_PRAGMA 55
-#define TK_RAISE 56
-#define TK_REPLACE 57
-#define TK_RESTRICT 58
-#define TK_ROW 59
-#define TK_TRIGGER 60
-#define TK_VACUUM 61
-#define TK_VIEW 62
-#define TK_VIRTUAL 63
-#define TK_REINDEX 64
-#define TK_RENAME 65
-#define TK_CTIME_KW 66
-#define TK_ANY 67
-#define TK_OR 68
-#define TK_AND 69
-#define TK_IS 70
-#define TK_BETWEEN 71
-#define TK_IN 72
-#define TK_ISNULL 73
-#define TK_NOTNULL 74
-#define TK_NE 75
-#define TK_EQ 76
-#define TK_GT 77
-#define TK_LE 78
-#define TK_LT 79
-#define TK_GE 80
-#define TK_ESCAPE 81
-#define TK_BITAND 82
-#define TK_BITOR 83
-#define TK_LSHIFT 84
-#define TK_RSHIFT 85
-#define TK_PLUS 86
-#define TK_MINUS 87
-#define TK_STAR 88
-#define TK_SLASH 89
-#define TK_REM 90
-#define TK_CONCAT 91
-#define TK_COLLATE 92
-#define TK_BITNOT 93
-#define TK_STRING 94
-#define TK_JOIN_KW 95
-#define TK_CONSTRAINT 96
-#define TK_DEFAULT 97
-#define TK_NULL 98
-#define TK_PRIMARY 99
-#define TK_UNIQUE 100
-#define TK_CHECK 101
-#define TK_REFERENCES 102
-#define TK_AUTOINCR 103
-#define TK_ON 104
-#define TK_INSERT 105
-#define TK_DELETE 106
-#define TK_UPDATE 107
-#define TK_SET 108
-#define TK_DEFERRABLE 109
-#define TK_FOREIGN 110
-#define TK_DROP 111
-#define TK_UNION 112
-#define TK_ALL 113
-#define TK_EXCEPT 114
-#define TK_INTERSECT 115
-#define TK_SELECT 116
-#define TK_DISTINCT 117
-#define TK_DOT 118
-#define TK_FROM 119
-#define TK_JOIN 120
-#define TK_USING 121
-#define TK_ORDER 122
-#define TK_GROUP 123
-#define TK_HAVING 124
-#define TK_LIMIT 125
-#define TK_WHERE 126
-#define TK_INTO 127
-#define TK_VALUES 128
-#define TK_INTEGER 129
-#define TK_FLOAT 130
-#define TK_BLOB 131
-#define TK_REGISTER 132
-#define TK_VARIABLE 133
-#define TK_CASE 134
-#define TK_WHEN 135
-#define TK_THEN 136
-#define TK_ELSE 137
-#define TK_INDEX 138
-#define TK_ALTER 139
-#define TK_ADD 140
-#define TK_TO_TEXT 141
-#define TK_TO_BLOB 142
-#define TK_TO_NUMERIC 143
-#define TK_TO_INT 144
-#define TK_TO_REAL 145
-#define TK_ISNOT 146
-#define TK_END_OF_FILE 147
-#define TK_ILLEGAL 148
-#define TK_SPACE 149
-#define TK_UNCLOSED_STRING 150
-#define TK_FUNCTION 151
-#define TK_COLUMN 152
-#define TK_AGG_FUNCTION 153
-#define TK_AGG_COLUMN 154
-#define TK_CONST_FUNC 155
+#define TK_WITHOUT 25
+#define TK_COMMA 26
+#define TK_ID 27
+#define TK_INDEXED 28
+#define TK_ABORT 29
+#define TK_ACTION 30
+#define TK_AFTER 31
+#define TK_ANALYZE 32
+#define TK_ASC 33
+#define TK_ATTACH 34
+#define TK_BEFORE 35
+#define TK_BY 36
+#define TK_CASCADE 37
+#define TK_CAST 38
+#define TK_COLUMNKW 39
+#define TK_CONFLICT 40
+#define TK_DATABASE 41
+#define TK_DESC 42
+#define TK_DETACH 43
+#define TK_EACH 44
+#define TK_FAIL 45
+#define TK_FOR 46
+#define TK_IGNORE 47
+#define TK_INITIALLY 48
+#define TK_INSTEAD 49
+#define TK_LIKE_KW 50
+#define TK_MATCH 51
+#define TK_NO 52
+#define TK_KEY 53
+#define TK_OF 54
+#define TK_OFFSET 55
+#define TK_PRAGMA 56
+#define TK_RAISE 57
+#define TK_REPLACE 58
+#define TK_RESTRICT 59
+#define TK_ROW 60
+#define TK_TRIGGER 61
+#define TK_VACUUM 62
+#define TK_VIEW 63
+#define TK_VIRTUAL 64
+#define TK_REINDEX 65
+#define TK_RENAME 66
+#define TK_CTIME_KW 67
+#define TK_ANY 68
+#define TK_OR 69
+#define TK_AND 70
+#define TK_IS 71
+#define TK_BETWEEN 72
+#define TK_IN 73
+#define TK_ISNULL 74
+#define TK_NOTNULL 75
+#define TK_NE 76
+#define TK_EQ 77
+#define TK_GT 78
+#define TK_LE 79
+#define TK_LT 80
+#define TK_GE 81
+#define TK_ESCAPE 82
+#define TK_BITAND 83
+#define TK_BITOR 84
+#define TK_LSHIFT 85
+#define TK_RSHIFT 86
+#define TK_PLUS 87
+#define TK_MINUS 88
+#define TK_STAR 89
+#define TK_SLASH 90
+#define TK_REM 91
+#define TK_CONCAT 92
+#define TK_COLLATE 93
+#define TK_BITNOT 94
+#define TK_STRING 95
+#define TK_JOIN_KW 96
+#define TK_CONSTRAINT 97
+#define TK_DEFAULT 98
+#define TK_NULL 99
+#define TK_PRIMARY 100
+#define TK_UNIQUE 101
+#define TK_CHECK 102
+#define TK_REFERENCES 103
+#define TK_AUTOINCR 104
+#define TK_ON 105
+#define TK_INSERT 106
+#define TK_DELETE 107
+#define TK_UPDATE 108
+#define TK_SET 109
+#define TK_DEFERRABLE 110
+#define TK_FOREIGN 111
+#define TK_DROP 112
+#define TK_UNION 113
+#define TK_ALL 114
+#define TK_EXCEPT 115
+#define TK_INTERSECT 116
+#define TK_SELECT 117
+#define TK_DISTINCT 118
+#define TK_DOT 119
+#define TK_FROM 120
+#define TK_JOIN 121
+#define TK_USING 122
+#define TK_ORDER 123
+#define TK_GROUP 124
+#define TK_HAVING 125
+#define TK_LIMIT 126
+#define TK_WHERE 127
+#define TK_INTO 128
+#define TK_VALUES 129
+#define TK_INTEGER 130
+#define TK_FLOAT 131
+#define TK_BLOB 132
+#define TK_REGISTER 133
+#define TK_VARIABLE 134
+#define TK_CASE 135
+#define TK_WHEN 136
+#define TK_THEN 137
+#define TK_ELSE 138
+#define TK_INDEX 139
+#define TK_ALTER 140
+#define TK_ADD 141
+#define TK_TO_TEXT 142
+#define TK_TO_BLOB 143
+#define TK_TO_NUMERIC 144
+#define TK_TO_INT 145
+#define TK_TO_REAL 146
+#define TK_ISNOT 147
+#define TK_END_OF_FILE 148
+#define TK_ILLEGAL 149
+#define TK_SPACE 150
+#define TK_UNCLOSED_STRING 151
+#define TK_FUNCTION 152
+#define TK_COLUMN 153
+#define TK_AGG_FUNCTION 154
+#define TK_AGG_COLUMN 155
#define TK_UMINUS 156
#define TK_UPLUS 157
@@ -8154,6 +8230,12 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#endif
/*
+** Macros to compute minimum and maximum of two numbers.
+*/
+#define MIN(A,B) ((A)<(B)?(A):(B))
+#define MAX(A,B) ((A)>(B)?(A):(B))
+
+/*
** Check to see if this machine uses EBCDIC. (Yes, believe it or
** not, there are still machines out there that use EBCDIC.)
*/
@@ -8237,6 +8319,31 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
#endif
/*
+** Estimated quantities used for query planning are stored as 16-bit
+** logarithms. For quantity X, the value stored is 10*log2(X). This
+** gives a possible range of values of approximately 1.0e986 to 1e-986.
+** But the allowed values are "grainy". Not every value is representable.
+** For example, quantities 16 and 17 are both represented by a LogEst
+** of 40. However, since LogEst quantatites are suppose to be estimates,
+** not exact values, this imprecision is not a problem.
+**
+** "LogEst" is short for "Logarithimic Estimate".
+**
+** Examples:
+** 1 -> 0 20 -> 43 10000 -> 132
+** 2 -> 10 25 -> 46 25000 -> 146
+** 3 -> 16 100 -> 66 1000000 -> 199
+** 4 -> 20 1000 -> 99 1048576 -> 200
+** 10 -> 33 1024 -> 100 4294967296 -> 320
+**
+** The LogEst can be negative to indicate fractional values.
+** Examples:
+**
+** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
+*/
+typedef INT16_TYPE LogEst;
+
+/*
** Macros to determine whether the machine is big or little endian,
** evaluated at runtime.
*/
@@ -8335,6 +8442,20 @@ SQLITE_PRIVATE const int sqlite3one;
#endif
/*
+** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined.
+** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also
+** define SQLITE_ENABLE_STAT3_OR_STAT4
+*/
+#ifdef SQLITE_ENABLE_STAT4
+# undef SQLITE_ENABLE_STAT3
+# define SQLITE_ENABLE_STAT3_OR_STAT4 1
+#elif SQLITE_ENABLE_STAT3
+# define SQLITE_ENABLE_STAT3_OR_STAT4 1
+#elif SQLITE_ENABLE_STAT3_OR_STAT4
+# undef SQLITE_ENABLE_STAT3_OR_STAT4
+#endif
+
+/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
**
@@ -8478,9 +8599,7 @@ typedef struct UnpackedRecord UnpackedRecord;
typedef struct VTable VTable;
typedef struct VtabCtx VtabCtx;
typedef struct Walker Walker;
-typedef struct WherePlan WherePlan;
typedef struct WhereInfo WhereInfo;
-typedef struct WhereLevel WhereLevel;
/*
** Defer sourcing vdbe.h and btree.h until after the "u8" and
@@ -8555,7 +8674,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
-SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree*,int,int,int);
+SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
@@ -8669,8 +8788,8 @@ SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor*, i64 *pSize);
SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
-SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt);
-SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
+SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor*, u32 *pAmt);
+SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor*, u32 *pAmt);
SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
SQLITE_PRIVATE int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE void sqlite3BtreeSetCachedRowid(BtCursor*, sqlite3_int64);
@@ -8779,7 +8898,6 @@ typedef struct Vdbe Vdbe;
** The names of the following types declared in vdbeInt.h are required
** for the VdbeOp definition.
*/
-typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
typedef struct SubProgram SubProgram;
@@ -8803,7 +8921,6 @@ struct VdbeOp {
i64 *pI64; /* Used when p4type is P4_INT64 */
double *pReal; /* Used when p4type is P4_REAL */
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
- VdbeFunc *pVdbeFunc; /* Used when p4type is P4_VDBEFUNC */
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
Mem *pMem; /* Used when p4type is P4_MEM */
VTable *pVtab; /* Used when p4type is P4_VTAB */
@@ -8812,7 +8929,7 @@ struct VdbeOp {
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
int (*xAdvance)(BtCursor *, int *);
} p4;
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
char *zComment; /* Comment to improve readability */
#endif
#ifdef VDBE_PROFILE
@@ -8857,7 +8974,6 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
-#define P4_VDBEFUNC (-7) /* P4 is a pointer to a VdbeFunc structure */
#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
@@ -8869,15 +8985,11 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
-/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
-** is made. That copy is freed when the Vdbe is finalized. But if the
-** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used. It still
-** gets freed when the Vdbe is finalized so it still should be obtained
-** from a single sqliteMalloc(). But no copy is made and the calling
-** function should *not* try to free the KeyInfo.
-*/
-#define P4_KEYINFO_HANDOFF (-16)
-#define P4_KEYINFO_STATIC (-17)
+/* Error message codes for OP_Halt */
+#define P5_ConstraintNotNull 1
+#define P5_ConstraintUnique 2
+#define P5_ConstraintCheck 3
+#define P5_ConstraintFK 4
/*
** The Vdbe.aColName array contains 5n Mem structures, where n is the
@@ -8914,156 +9026,158 @@ typedef struct VdbeOpList VdbeOpList;
/************** Begin file opcodes.h *****************************************/
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
-#define OP_Goto 1
-#define OP_Gosub 2
-#define OP_Return 3
-#define OP_Yield 4
-#define OP_HaltIfNull 5
-#define OP_Halt 6
-#define OP_Integer 7
-#define OP_Int64 8
-#define OP_Real 130 /* same as TK_FLOAT */
-#define OP_String8 94 /* same as TK_STRING */
-#define OP_String 9
-#define OP_Null 10
-#define OP_Blob 11
-#define OP_Variable 12
-#define OP_Move 13
-#define OP_Copy 14
-#define OP_SCopy 15
-#define OP_ResultRow 16
-#define OP_Concat 91 /* same as TK_CONCAT */
-#define OP_Add 86 /* same as TK_PLUS */
-#define OP_Subtract 87 /* same as TK_MINUS */
-#define OP_Multiply 88 /* same as TK_STAR */
-#define OP_Divide 89 /* same as TK_SLASH */
-#define OP_Remainder 90 /* same as TK_REM */
-#define OP_CollSeq 17
-#define OP_Function 18
-#define OP_BitAnd 82 /* same as TK_BITAND */
-#define OP_BitOr 83 /* same as TK_BITOR */
-#define OP_ShiftLeft 84 /* same as TK_LSHIFT */
-#define OP_ShiftRight 85 /* same as TK_RSHIFT */
-#define OP_AddImm 20
-#define OP_MustBeInt 21
-#define OP_RealAffinity 22
-#define OP_ToText 141 /* same as TK_TO_TEXT */
-#define OP_ToBlob 142 /* same as TK_TO_BLOB */
-#define OP_ToNumeric 143 /* same as TK_TO_NUMERIC*/
-#define OP_ToInt 144 /* same as TK_TO_INT */
-#define OP_ToReal 145 /* same as TK_TO_REAL */
-#define OP_Eq 76 /* same as TK_EQ */
-#define OP_Ne 75 /* same as TK_NE */
-#define OP_Lt 79 /* same as TK_LT */
-#define OP_Le 78 /* same as TK_LE */
-#define OP_Gt 77 /* same as TK_GT */
-#define OP_Ge 80 /* same as TK_GE */
-#define OP_Permutation 23
-#define OP_Compare 24
-#define OP_Jump 25
-#define OP_And 69 /* same as TK_AND */
-#define OP_Or 68 /* same as TK_OR */
-#define OP_Not 19 /* same as TK_NOT */
-#define OP_BitNot 93 /* same as TK_BITNOT */
-#define OP_Once 26
-#define OP_If 27
-#define OP_IfNot 28
-#define OP_IsNull 73 /* same as TK_ISNULL */
-#define OP_NotNull 74 /* same as TK_NOTNULL */
-#define OP_Column 29
-#define OP_Affinity 30
-#define OP_MakeRecord 31
-#define OP_Count 32
-#define OP_Savepoint 33
-#define OP_AutoCommit 34
-#define OP_Transaction 35
-#define OP_ReadCookie 36
-#define OP_SetCookie 37
-#define OP_VerifyCookie 38
-#define OP_OpenRead 39
-#define OP_OpenWrite 40
-#define OP_OpenAutoindex 41
-#define OP_OpenEphemeral 42
-#define OP_SorterOpen 43
-#define OP_OpenPseudo 44
-#define OP_Close 45
-#define OP_SeekLt 46
-#define OP_SeekLe 47
-#define OP_SeekGe 48
-#define OP_SeekGt 49
-#define OP_Seek 50
-#define OP_NotFound 51
-#define OP_Found 52
-#define OP_IsUnique 53
-#define OP_NotExists 54
-#define OP_Sequence 55
-#define OP_NewRowid 56
-#define OP_Insert 57
-#define OP_InsertInt 58
-#define OP_Delete 59
-#define OP_ResetCount 60
-#define OP_SorterCompare 61
-#define OP_SorterData 62
-#define OP_RowKey 63
-#define OP_RowData 64
-#define OP_Rowid 65
-#define OP_NullRow 66
-#define OP_Last 67
-#define OP_SorterSort 70
-#define OP_Sort 71
-#define OP_Rewind 72
-#define OP_SorterNext 81
-#define OP_Prev 92
-#define OP_Next 95
-#define OP_SorterInsert 96
-#define OP_IdxInsert 97
-#define OP_IdxDelete 98
-#define OP_IdxRowid 99
-#define OP_IdxLT 100
-#define OP_IdxGE 101
-#define OP_Destroy 102
-#define OP_Clear 103
-#define OP_CreateIndex 104
-#define OP_CreateTable 105
-#define OP_ParseSchema 106
-#define OP_LoadAnalysis 107
-#define OP_DropTable 108
-#define OP_DropIndex 109
-#define OP_DropTrigger 110
-#define OP_IntegrityCk 111
-#define OP_RowSetAdd 112
-#define OP_RowSetRead 113
-#define OP_RowSetTest 114
-#define OP_Program 115
-#define OP_Param 116
-#define OP_FkCounter 117
-#define OP_FkIfZero 118
-#define OP_MemMax 119
-#define OP_IfPos 120
-#define OP_IfNeg 121
-#define OP_IfZero 122
-#define OP_AggStep 123
-#define OP_AggFinal 124
-#define OP_Checkpoint 125
-#define OP_JournalMode 126
-#define OP_Vacuum 127
-#define OP_IncrVacuum 128
-#define OP_Expire 129
-#define OP_TableLock 131
-#define OP_VBegin 132
-#define OP_VCreate 133
-#define OP_VDestroy 134
-#define OP_VOpen 135
-#define OP_VFilter 136
-#define OP_VColumn 137
-#define OP_VNext 138
-#define OP_VRename 139
-#define OP_VUpdate 140
-#define OP_Pagecount 146
-#define OP_MaxPgcnt 147
-#define OP_Trace 148
-#define OP_Noop 149
-#define OP_Explain 150
+#define OP_Function 1 /* synopsis: r[P3]=func(r[P2@P5]) */
+#define OP_Savepoint 2
+#define OP_AutoCommit 3
+#define OP_Transaction 4
+#define OP_SorterNext 5
+#define OP_PrevIfOpen 6
+#define OP_NextIfOpen 7
+#define OP_Prev 8
+#define OP_Next 9
+#define OP_AggStep 10 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_Checkpoint 11
+#define OP_JournalMode 12
+#define OP_Vacuum 13
+#define OP_VFilter 14 /* synopsis: iPlan=r[P3] zPlan='P4' */
+#define OP_VUpdate 15 /* synopsis: data=r[P3@P2] */
+#define OP_Goto 16
+#define OP_Gosub 17
+#define OP_Return 18
+#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
+#define OP_Yield 20
+#define OP_HaltIfNull 21 /* synopsis: if r[P3] null then halt */
+#define OP_Halt 22
+#define OP_Integer 23 /* synopsis: r[P2]=P1 */
+#define OP_Int64 24 /* synopsis: r[P2]=P4 */
+#define OP_String 25 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_Null 26 /* synopsis: r[P2..P3]=NULL */
+#define OP_Blob 27 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 28 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Move 29 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 30 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_SCopy 31 /* synopsis: r[P2]=r[P1] */
+#define OP_ResultRow 32 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 33
+#define OP_AddImm 34 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_MustBeInt 35
+#define OP_RealAffinity 36
+#define OP_Permutation 37
+#define OP_Compare 38
+#define OP_Jump 39
+#define OP_Once 40
+#define OP_If 41
+#define OP_IfNot 42
+#define OP_Column 43 /* synopsis: r[P3]=PX */
+#define OP_Affinity 44 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 45 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 46 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 47
+#define OP_SetCookie 48
+#define OP_VerifyCookie 49
+#define OP_OpenRead 50 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 51 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenAutoindex 52 /* synopsis: nColumn=P2 */
+#define OP_OpenEphemeral 53 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 54
+#define OP_OpenPseudo 55 /* synopsis: content in r[P2@P3] */
+#define OP_Close 56
+#define OP_SeekLt 57 /* synopsis: key=r[P3@P4] */
+#define OP_SeekLe 58 /* synopsis: key=r[P3@P4] */
+#define OP_SeekGe 59 /* synopsis: key=r[P3@P4] */
+#define OP_SeekGt 60 /* synopsis: key=r[P3@P4] */
+#define OP_Seek 61 /* synopsis: intkey=r[P2] */
+#define OP_NoConflict 62 /* synopsis: key=r[P3@P4] */
+#define OP_NotFound 63 /* synopsis: key=r[P3@P4] */
+#define OP_Found 64 /* synopsis: key=r[P3@P4] */
+#define OP_NotExists 65 /* synopsis: intkey=r[P3] */
+#define OP_Sequence 66 /* synopsis: r[P2]=rowid */
+#define OP_NewRowid 67 /* synopsis: r[P2]=rowid */
+#define OP_Insert 68 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_Or 69 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
+#define OP_And 70 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
+#define OP_InsertInt 71 /* synopsis: intkey=P3 data=r[P2] */
+#define OP_Delete 72
+#define OP_ResetCount 73
+#define OP_IsNull 74 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull 75 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne 76 /* same as TK_NE, synopsis: if r[P1]!=r[P3] goto P2 */
+#define OP_Eq 77 /* same as TK_EQ, synopsis: if r[P1]==r[P3] goto P2 */
+#define OP_Gt 78 /* same as TK_GT, synopsis: if r[P1]>r[P3] goto P2 */
+#define OP_Le 79 /* same as TK_LE, synopsis: if r[P1]<=r[P3] goto P2 */
+#define OP_Lt 80 /* same as TK_LT, synopsis: if r[P1]<r[P3] goto P2 */
+#define OP_Ge 81 /* same as TK_GE, synopsis: if r[P1]>=r[P3] goto P2 */
+#define OP_SorterCompare 82 /* synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2 */
+#define OP_BitAnd 83 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 84 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 85 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight 86 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add 87 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 88 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 89 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 90 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 91 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 92 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_SorterData 93 /* synopsis: r[P2]=data */
+#define OP_BitNot 94 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
+#define OP_String8 95 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_RowKey 96 /* synopsis: r[P2]=key */
+#define OP_RowData 97 /* synopsis: r[P2]=data */
+#define OP_Rowid 98 /* synopsis: r[P2]=rowid */
+#define OP_NullRow 99
+#define OP_Last 100
+#define OP_SorterSort 101
+#define OP_Sort 102
+#define OP_Rewind 103
+#define OP_SorterInsert 104
+#define OP_IdxInsert 105 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 106 /* synopsis: key=r[P2@P3] */
+#define OP_IdxRowid 107 /* synopsis: r[P2]=rowid */
+#define OP_IdxLT 108 /* synopsis: key=r[P3@P4] */
+#define OP_IdxGE 109 /* synopsis: key=r[P3@P4] */
+#define OP_Destroy 110
+#define OP_Clear 111
+#define OP_CreateIndex 112 /* synopsis: r[P2]=root iDb=P1 */
+#define OP_CreateTable 113 /* synopsis: r[P2]=root iDb=P1 */
+#define OP_ParseSchema 114
+#define OP_LoadAnalysis 115
+#define OP_DropTable 116
+#define OP_DropIndex 117
+#define OP_DropTrigger 118
+#define OP_IntegrityCk 119
+#define OP_RowSetAdd 120 /* synopsis: rowset(P1)=r[P2] */
+#define OP_RowSetRead 121 /* synopsis: r[P3]=rowset(P1) */
+#define OP_RowSetTest 122 /* synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 123
+#define OP_Param 124
+#define OP_FkCounter 125 /* synopsis: fkctr[P1]+=P2 */
+#define OP_FkIfZero 126 /* synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_MemMax 127 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_IfPos 128 /* synopsis: if r[P1]>0 goto P2 */
+#define OP_IfNeg 129 /* synopsis: if r[P1]<0 goto P2 */
+#define OP_IfZero 130 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
+#define OP_Real 131 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_AggFinal 132 /* synopsis: accum=r[P1] N=P2 */
+#define OP_IncrVacuum 133
+#define OP_Expire 134
+#define OP_TableLock 135 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 136
+#define OP_VCreate 137
+#define OP_VDestroy 138
+#define OP_VOpen 139
+#define OP_VColumn 140 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VNext 141
+#define OP_ToText 142 /* same as TK_TO_TEXT */
+#define OP_ToBlob 143 /* same as TK_TO_BLOB */
+#define OP_ToNumeric 144 /* same as TK_TO_NUMERIC */
+#define OP_ToInt 145 /* same as TK_TO_INT */
+#define OP_ToReal 146 /* same as TK_TO_REAL */
+#define OP_VRename 147
+#define OP_Pagecount 148
+#define OP_MaxPgcnt 149
+#define OP_Trace 150
+#define OP_Noop 151
+#define OP_Explain 152
/* Properties such as "out2" or "jump" that are specified in
@@ -9078,25 +9192,26 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */
#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
-/* 0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\
-/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\
-/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
-/* 24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\
-/* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
-/* 40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
-/* 48 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x02,\
-/* 56 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 64 */ 0x00, 0x02, 0x00, 0x01, 0x4c, 0x4c, 0x01, 0x01,\
-/* 72 */ 0x01, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
-/* 80 */ 0x15, 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
-/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01,\
-/* 96 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
-/* 104 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
-/* 120 */ 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00,\
-/* 128 */ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 136 */ 0x01, 0x00, 0x01, 0x00, 0x00, 0x04, 0x04, 0x04,\
-/* 144 */ 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,}
+/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\
+/* 8 */ 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,\
+/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x04, 0x10, 0x00, 0x02,\
+/* 24 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x20,\
+/* 32 */ 0x00, 0x00, 0x04, 0x05, 0x04, 0x00, 0x00, 0x01,\
+/* 40 */ 0x01, 0x05, 0x05, 0x00, 0x00, 0x00, 0x02, 0x02,\
+/* 48 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 56 */ 0x00, 0x11, 0x11, 0x11, 0x11, 0x08, 0x11, 0x11,\
+/* 64 */ 0x11, 0x11, 0x02, 0x02, 0x00, 0x4c, 0x4c, 0x00,\
+/* 72 */ 0x00, 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15,\
+/* 80 */ 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
+/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00, 0x24, 0x02,\
+/* 96 */ 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,\
+/* 104 */ 0x08, 0x08, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
+/* 112 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 120 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x00, 0x01, 0x08,\
+/* 128 */ 0x05, 0x05, 0x05, 0x02, 0x00, 0x01, 0x00, 0x00,\
+/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x04,\
+/* 144 */ 0x04, 0x04, 0x04, 0x00, 0x02, 0x02, 0x00, 0x00,\
+/* 152 */ 0x00,}
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -9121,6 +9236,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
+SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
@@ -9133,7 +9249,6 @@ SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int);
-SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*);
#endif
SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*);
@@ -9145,7 +9260,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
-SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8);
+SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE_OMIT_TRACE
SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
@@ -9159,15 +9274,27 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *,
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif
-
-#ifndef NDEBUG
+/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
+** each VDBE opcode.
+**
+** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
+** comments in VDBE programs that show key decision points in the code
+** generator.
+*/
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...);
# define VdbeComment(X) sqlite3VdbeComment X
SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
# define VdbeNoopComment(X) sqlite3VdbeNoopComment X
+# ifdef SQLITE_ENABLE_MODULE_COMMENTS
+# define VdbeModuleComment(X) sqlite3VdbeNoopComment X
+# else
+# define VdbeModuleComment(X)
+# endif
#else
# define VdbeComment(X)
# define VdbeNoopComment(X)
+# define VdbeModuleComment(X)
#endif
#endif
@@ -9259,8 +9386,20 @@ typedef struct PgHdr DbPage;
/*
** Flags that make up the mask passed to sqlite3PagerAcquire().
*/
-#define PAGER_ACQUIRE_NOCONTENT 0x01 /* Do not load data from disk */
-#define PAGER_ACQUIRE_READONLY 0x02 /* Read-only page is acceptable */
+#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */
+#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */
+
+/*
+** Flags for sqlite3PagerSetFlags()
+*/
+#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
+#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
+#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */
+#define PAGER_SYNCHRONOUS_MASK 0x03 /* Mask for three values above */
+#define PAGER_FULLFSYNC 0x04 /* PRAGMA fullfsync=ON */
+#define PAGER_CKPT_FULLFSYNC 0x08 /* PRAGMA checkpoint_fullfsync=ON */
+#define PAGER_CACHESPILL 0x10 /* PRAGMA cache_spill=ON */
+#define PAGER_FLAGS_MASK 0x1c /* All above except SYNCHRONOUS */
/*
** The remainder of this file contains the declarations of the functions
@@ -9288,7 +9427,7 @@ SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int,int);
+SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned);
SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int);
SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*);
@@ -9917,7 +10056,6 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
struct Db {
char *zName; /* Name of this database */
Btree *pBt; /* The B*Tree structure for this database file */
- u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */
u8 safety_level; /* How aggressive at syncing data to disk */
Schema *pSchema; /* Pointer to database schema (possibly shared) */
};
@@ -10063,9 +10201,10 @@ struct sqlite3 {
u8 busy; /* TRUE if currently initializing */
u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */
} init;
- int activeVdbeCnt; /* Number of VDBEs currently executing */
- int writeVdbeCnt; /* Number of active VDBEs that are writing */
- int vdbeExecCnt; /* Number of nested calls to VdbeExec() */
+ int nVdbeActive; /* Number of VDBEs currently running */
+ int nVdbeRead; /* Number of active VDBEs that read or write */
+ int nVdbeWrite; /* Number of active VDBEs that read and write */
+ int nVdbeExec; /* Number of nested calls to VdbeExec() */
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
void (*xTrace)(void*,const char*); /* Trace function */
@@ -10086,8 +10225,6 @@ struct sqlite3 {
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
void *pCollNeededArg;
sqlite3_value *pErr; /* Most recent error message */
- char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
- char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
union {
volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
double notUsed1; /* Spacer */
@@ -10101,7 +10238,7 @@ struct sqlite3 {
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int (*xProgress)(void *); /* The progress callback */
void *pProgressArg; /* Argument to the progress callback */
- int nProgressOps; /* Number of opcodes for progress callback */
+ unsigned nProgressOps; /* Number of opcodes for progress callback */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
int nVTrans; /* Allocated size of aVTrans */
@@ -10119,6 +10256,7 @@ struct sqlite3 {
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
i64 nDeferredCons; /* Net deferred constraints this transaction. */
+ i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
@@ -10150,30 +10288,35 @@ struct sqlite3 {
*/
#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
-#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
-#define SQLITE_ShortColNames 0x00000008 /* Show short columns names */
-#define SQLITE_CountRows 0x00000010 /* Count rows changed by INSERT, */
+#define SQLITE_FullFSync 0x00000004 /* Use full fsync on the backend */
+#define SQLITE_CkptFullFSync 0x00000008 /* Use full fsync for checkpoint */
+#define SQLITE_CacheSpill 0x00000010 /* OK to spill pager cache */
+#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */
+#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
+#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */
/* the count using a callback. */
-#define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */
+#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
/* result set is empty */
-#define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */
-#define SQLITE_VdbeAddopTrace 0x00000200 /* Trace sqlite3VdbeAddOp() calls */
-#define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */
-#define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */
-#define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */
-#define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */
-#define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */
-#define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */
-#define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */
-#define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */
-#define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */
+#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */
+#define SQLITE_VdbeAddopTrace 0x00001000 /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */
+#define SQLITE_ReadUncommitted 0x0004000 /* For shared-cache mode */
+#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */
+#define SQLITE_RecoveryMode 0x00010000 /* Ignore schema errors */
+#define SQLITE_ReverseOrder 0x00020000 /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers 0x00040000 /* Enable recursive triggers */
+#define SQLITE_ForeignKeys 0x00080000 /* Enforce foreign key constraints */
+#define SQLITE_AutoIndex 0x00100000 /* Enable automatic indexes */
+#define SQLITE_PreferBuiltin 0x00200000 /* Preference to built-in funcs */
+#define SQLITE_LoadExtension 0x00400000 /* Enable load_extension */
+#define SQLITE_EnableTrigger 0x00800000 /* True to enable triggers */
+#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
+#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
+#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
+
/*
** Bits of the sqlite3.dbOptFlags field that are used by the
@@ -10190,6 +10333,9 @@ struct sqlite3 {
#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
#define SQLITE_Transitive 0x0200 /* Transitive constraints */
+#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
+#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */
+#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */
#define SQLITE_AllOpts 0xffff /* All optimizations */
/*
@@ -10204,6 +10350,13 @@ struct sqlite3 {
#endif
/*
+** Return true if it OK to factor constant expressions into the initialization
+** code. The argument is a Parse object for the code generator.
+*/
+#define ConstFactorOk(P) \
+ ((P)->cookieGoto>0 && OptimizationEnabled((P)->db,SQLITE_FactorOutConst))
+
+/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
** than being distinct from one another.
@@ -10223,8 +10376,7 @@ struct sqlite3 {
*/
struct FuncDef {
i16 nArg; /* Number of arguments. -1 means unlimited */
- u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
- u8 flags; /* Some combination of SQLITE_FUNC_* */
+ u16 funcFlags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
@@ -10260,14 +10412,17 @@ struct FuncDestructor {
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
** are assert() statements in the code to verify this.
*/
-#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
-#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
-#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */
-#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
-#define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */
-#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */
-#define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */
-#define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */
+#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
+#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */
+#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */
+#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */
+#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */
+#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */
+#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */
+#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */
+#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */
+#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -10280,6 +10435,9 @@ struct FuncDestructor {
** as the user-data (sqlite3_user_data()) for the function. If
** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
**
+** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
+** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
+**
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
** Used to create an aggregate function definition implemented by
** the C functions xStep and xFinal. The first four parameters
@@ -10295,18 +10453,22 @@ struct FuncDestructor {
** parameter.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \
+ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
+#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
+ {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
- {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
+ {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
- {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \
+ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
pArg, 0, xFunc, 0, 0, #zName, 0, 0}
#define LIKEFUNC(zName, nArg, arg, flags) \
- {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0}
+ {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
+ (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0}
#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
- {nArg, SQLITE_UTF8, nc*SQLITE_FUNC_NEEDCOLL, \
+ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}
/*
@@ -10318,6 +10480,7 @@ struct FuncDestructor {
struct Savepoint {
char *zName; /* Savepoint name (nul-terminated) */
i64 nDeferredCons; /* Number of deferred fk violations */
+ i64 nDeferredImmCons; /* Number of deferred imm fk. */
Savepoint *pNext; /* Parent savepoint (if any) */
};
@@ -10354,7 +10517,8 @@ struct Column {
char *zColl; /* Collating sequence. If NULL, use the default */
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
char affinity; /* One of the SQLITE_AFF_... values */
- u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
+ u8 szEst; /* Estimated size of this column. INT==1 */
+ u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
/* Allowed values for Column.colFlags:
@@ -10518,6 +10682,7 @@ struct Table {
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
i16 nCol; /* Number of columns in this table */
u16 nRef; /* Number of pointers to this Table */
+ LogEst szTabRow; /* Estimated size of each table row in bytes */
u8 tabFlags; /* Mask of TF_* values */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
#ifndef SQLITE_OMIT_ALTERTABLE
@@ -10541,6 +10706,7 @@ struct Table {
#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
#define TF_Virtual 0x10 /* Is a virtual table */
+#define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */
/*
@@ -10556,6 +10722,9 @@ struct Table {
# define IsHiddenColumn(X) 0
#endif
+/* Does the table have a rowid */
+#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
+
/*
** Each foreign key constraint is an instance of the following structure.
**
@@ -10570,26 +10739,35 @@ struct Table {
** );
**
** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2".
+** Equivalent names:
+**
+** from-table == child-table
+** to-table == parent-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.
+**
+** The list of all parents for child Table X is held at X.pFKey.
+**
+** A list of all children for a table named Z (which might not even exist)
+** is held in Schema.fkeyHash with a hash key of Z.
*/
struct FKey {
Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */
- FKey *pNextFrom; /* Next foreign key in pFrom */
+ FKey *pNextFrom; /* Next FKey with the same in pFrom. Next parent of pFrom */
char *zTo; /* Name of table that the key points to (aka: Parent) */
- FKey *pNextTo; /* Next foreign key on table named zTo */
- FKey *pPrevTo; /* Previous foreign key on table named zTo */
+ FKey *pNextTo; /* Next with the same zTo. Next child of zTo. */
+ FKey *pPrevTo; /* Previous with the same zTo */
int nCol; /* Number of columns in this key */
/* EV: R-30323-21917 */
- u8 isDeferred; /* True if constraint checking is deferred till COMMIT */
- u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */
- Trigger *apTrigger[2]; /* Triggers for aAction[] actions */
- 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 */
+ u8 isDeferred; /* True if constraint checking is deferred till COMMIT */
+ u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */
+ Trigger *apTrigger[2];/* Triggers for aAction[] actions */
+ struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
+ int iFrom; /* Index of column in pFrom */
+ char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
+ } aCol[1]; /* One entry for each of nCol columns */
};
/*
@@ -10629,19 +10807,25 @@ struct FKey {
#define OE_SetDflt 8 /* Set the foreign key value to its default */
#define OE_Cascade 9 /* Cascade the changes */
-#define OE_Default 99 /* Do whatever the default action is */
+#define OE_Default 10 /* Do whatever the default action is */
/*
** An instance of the following structure is passed as the first
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
+**
+** Note that aSortOrder[] and aColl[] have nField+1 slots. There
+** are nField slots for the columns of an index then one extra slot
+** for the rowid at the end.
*/
struct KeyInfo {
- sqlite3 *db; /* The database connection */
+ u32 nRef; /* Number of references to this KeyInfo object */
u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
- u16 nField; /* Number of entries in aColl[] */
- u8 *aSortOrder; /* Sort order for each column. May be NULL */
+ u16 nField; /* Number of key columns in the index */
+ u16 nXField; /* Number of columns beyond the key columns */
+ sqlite3 *db; /* The database connection */
+ u8 *aSortOrder; /* Sort order for each column. */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
};
@@ -10663,7 +10847,6 @@ struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
u16 nField; /* Number of entries in apMem[] */
u8 flags; /* Boolean settings. UNPACKED_... below */
- i64 rowid; /* Used by UNPACKED_PREFIX_SEARCH */
Mem *aMem; /* Values */
};
@@ -10672,7 +10855,6 @@ struct UnpackedRecord {
*/
#define UNPACKED_INCRKEY 0x01 /* Make this key an epsilon larger */
#define UNPACKED_PREFIX_MATCH 0x02 /* A prefix match is considered OK */
-#define UNPACKED_PREFIX_SEARCH 0x04 /* Ignore final (rowid) field */
/*
** Each SQL index is represented in memory by an
@@ -10702,7 +10884,7 @@ struct UnpackedRecord {
*/
struct Index {
char *zName; /* Name of this index */
- int *aiColumn; /* Which columns are used by this index. 1st is 0 */
+ i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */
tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
Table *pTable; /* The SQL table being indexed */
char *zColAff; /* String defining the affinity of each column */
@@ -10710,14 +10892,22 @@ struct Index {
Schema *pSchema; /* Schema containing this index */
u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
char **azColl; /* Array of collation sequence names for index */
+ Expr *pPartIdxWhere; /* WHERE clause for partial indices */
+ KeyInfo *pKeyInfo; /* A KeyInfo object suitable for this index */
int tnum; /* DB Page containing root of this index */
- u16 nColumn; /* Number of columns in table used by this index */
+ LogEst szIdxRow; /* Estimated average row size in bytes */
+ u16 nKeyCol; /* Number of columns forming the key */
+ u16 nColumn; /* Number of columns stored in the index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
-#ifdef SQLITE_ENABLE_STAT3
+ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
+ unsigned isResized:1; /* True if resizeIndexObject() has been called */
+ unsigned isCovering:1; /* True if this is a covering index */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
int nSample; /* Number of elements in aSample[] */
- tRowcnt avgEq; /* Average nEq value for key values not in aSample */
+ int nSampleCol; /* Size of IndexSample.anEq[] and so on */
+ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
IndexSample *aSample; /* Samples of the left-most key */
#endif
};
@@ -10728,16 +10918,11 @@ struct Index {
** analyze.c source file for additional information.
*/
struct IndexSample {
- union {
- char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */
- double r; /* Value if eType is SQLITE_FLOAT */
- i64 i; /* Value if eType is SQLITE_INTEGER */
- } u;
- u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */
- int nByte; /* Size in byte of text or blob. */
- tRowcnt nEq; /* Est. number of rows where the key equals this sample */
- tRowcnt nLt; /* Est. number of rows where key is less than this sample */
- tRowcnt nDLt; /* Est. number of distinct keys less than this sample */
+ void *p; /* Pointer to sampled record */
+ int n; /* Size of record in bytes */
+ tRowcnt *anEq; /* Est. number of rows where the key equals this sample */
+ tRowcnt *anLt; /* Est. number of rows where key is less than this sample */
+ tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */
};
/*
@@ -10878,7 +11063,7 @@ typedef int ynVar;
struct Expr {
u8 op; /* Operation performed by this node */
char affinity; /* The affinity of the column or 0 if not a column */
- u16 flags; /* Various flags. EP_* See below */
+ u32 flags; /* Various flags. EP_* See below */
union {
char *zToken; /* Token value. Zero terminated and dequoted */
int iValue; /* Non-negative integer value if EP_IntValue */
@@ -10892,8 +11077,8 @@ struct Expr {
Expr *pLeft; /* Left subnode */
Expr *pRight; /* Right subnode */
union {
- ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
- Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
+ ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
+ Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
} x;
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
@@ -10906,12 +11091,12 @@ struct Expr {
#endif
int iTable; /* TK_COLUMN: cursor number of table holding column
** TK_REGISTER: register number
- ** TK_TRIGGER: 1 -> new, 0 -> old */
+ ** TK_TRIGGER: 1 -> new, 0 -> old
+ ** EP_Unlikely: 1000 times likelihood */
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
** TK_VARIABLE: variable number (always >= 1). */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
- u8 flags2; /* Second set of flags. EP2_... */
u8 op2; /* TK_REGISTER: original value of Expr.op
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth */
@@ -10922,51 +11107,47 @@ struct Expr {
/*
** The following are the meanings of bits in the Expr.flags field.
*/
-#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
-#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
-#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
-#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_DblQuoted 0x0040 /* token.z was originally in "..." */
-#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
-#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */
-#define EP_FixedDest 0x0200 /* Result needed in a specific register */
-#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
-#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
-#define EP_Hint 0x1000 /* Not used */
-#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
-#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
-#define EP_Static 0x8000 /* Held in memory not obtained from malloc() */
+#define EP_FromJoin 0x000001 /* Originated in ON or USING clause of a join */
+#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
+#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
+#define EP_Error 0x000008 /* Expression contains one or more errors */
+#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
+#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
+#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
+#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE opeartor */
+ /* unused 0x000200 */
+#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
+#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
+#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
+#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
+#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
+#define EP_Static 0x008000 /* Held in memory not obtained from malloc() */
+#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
+#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
+#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
+#define EP_Constant 0x080000 /* Node is a constant */
/*
-** The following are the meanings of bits in the Expr.flags2 field.
+** These macros can be used to test, set, or clear bits in the
+** Expr.flags field.
*/
-#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */
-#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */
+#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
+#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
+#define ExprSetProperty(E,P) (E)->flags|=(P)
+#define ExprClearProperty(E,P) (E)->flags&=~(P)
-/*
-** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible
-** flag on an expression structure. This flag is used for VV&A only. The
-** routine is implemented as a macro that only works when in debugging mode,
-** so as not to burden production code.
+/* The ExprSetVVAProperty() macro is used for Verification, Validation,
+** and Accreditation only. It works like ExprSetProperty() during VVA
+** processes but is a no-op for delivery.
*/
#ifdef SQLITE_DEBUG
-# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible
+# define ExprSetVVAProperty(E,P) (E)->flags|=(P)
#else
-# define ExprSetIrreducible(X)
+# define ExprSetVVAProperty(E,P)
#endif
/*
-** These macros can be used to test, set, or clear bits in the
-** Expr.flags field.
-*/
-#define ExprHasProperty(E,P) (((E)->flags&(P))==(P))
-#define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0)
-#define ExprSetProperty(E,P) (E)->flags|=(P)
-#define ExprClearProperty(E,P) (E)->flags&=~(P)
-
-/*
** Macros to determine the number of bytes required by a normal Expr
** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
** and an Expr struct with the EP_TokenOnly flag set.
@@ -11007,8 +11188,14 @@ struct ExprList {
u8 sortOrder; /* 1 for DESC or 0 for ASC */
unsigned done :1; /* A flag to indicate when processing is finished */
unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
- u16 iOrderByCol; /* For ORDER BY, column number in result set */
- u16 iAlias; /* Index into Parse.aAlias[] for zName */
+ unsigned reusable :1; /* Constant expression is reusable */
+ union {
+ struct {
+ u16 iOrderByCol; /* For ORDER BY, column number in result set */
+ u16 iAlias; /* Index into Parse.aAlias[] for zName */
+ } x;
+ int iConstExprReg; /* Register in which Expr value is cached */
+ } u;
} *a; /* Alloc a power of two greater or equal to nExpr */
};
@@ -11061,6 +11248,11 @@ typedef u64 Bitmask;
#define BMS ((int)(sizeof(Bitmask)*8))
/*
+** A bit in a Bitmask
+*/
+#define MASKBIT(n) (((Bitmask)1)<<(n))
+
+/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
@@ -11080,8 +11272,8 @@ typedef u64 Bitmask;
** contains more than 63 columns and the 64-th or later column is used.
*/
struct SrcList {
- i16 nSrc; /* Number of tables or subqueries in the FROM clause */
- i16 nAlloc; /* Number of entries allocated in a[] below */
+ u8 nSrc; /* Number of tables or subqueries in the FROM clause */
+ u8 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
@@ -11120,79 +11312,6 @@ struct SrcList {
/*
-** A WherePlan object holds information that describes a lookup
-** strategy.
-**
-** This object is intended to be opaque outside of the where.c module.
-** It is included here only so that that compiler will know how big it
-** is. None of the fields in this object should be used outside of
-** the where.c module.
-**
-** Within the union, pIdx is only used when wsFlags&WHERE_INDEXED is true.
-** pTerm is only used when wsFlags&WHERE_MULTI_OR is true. And pVtabIdx
-** is only used when wsFlags&WHERE_VIRTUALTABLE is true. It is never the
-** case that more than one of these conditions is true.
-*/
-struct WherePlan {
- u32 wsFlags; /* WHERE_* flags that describe the strategy */
- u16 nEq; /* Number of == constraints */
- u16 nOBSat; /* Number of ORDER BY terms satisfied */
- double nRow; /* Estimated number of rows (for EQP) */
- union {
- Index *pIdx; /* Index when WHERE_INDEXED is true */
- struct WhereTerm *pTerm; /* WHERE clause term for OR-search */
- sqlite3_index_info *pVtabIdx; /* Virtual table index to use */
- } u;
-};
-
-/*
-** For each nested loop in a WHERE clause implementation, the WhereInfo
-** structure contains a single instance of this structure. This structure
-** is intended to be private to the where.c module and should not be
-** access or modified by other modules.
-**
-** The pIdxInfo field is used to help pick the best index on a
-** virtual table. The pIdxInfo pointer contains indexing
-** information for the i-th table in the FROM clause before reordering.
-** All the pIdxInfo pointers are freed by whereInfoFree() in where.c.
-** All other information in the i-th WhereLevel object for the i-th table
-** after FROM clause ordering.
-*/
-struct WhereLevel {
- WherePlan plan; /* query plan for this element of the FROM clause */
- int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
- int iTabCur; /* The VDBE cursor used to access the table */
- int iIdxCur; /* The VDBE cursor used to access pIdx */
- int addrBrk; /* Jump here to break out of the loop */
- int addrNxt; /* Jump here to start the next IN combination */
- int addrCont; /* Jump here to continue with the next loop cycle */
- int addrFirst; /* First instruction of interior of the loop */
- u8 iFrom; /* Which entry in the FROM clause */
- u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */
- int p1, p2; /* Operands of the opcode used to ends the loop */
- union { /* Information that depends on plan.wsFlags */
- struct {
- int nIn; /* Number of entries in aInLoop[] */
- struct InLoop {
- int iCur; /* The VDBE cursor used by this IN operator */
- int addrInTop; /* Top of the IN loop */
- u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
- } *aInLoop; /* Information about each nested IN operator */
- } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
- Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
- } u;
- double rOptCost; /* "Optimal" cost for this level */
-
- /* The following field is really not part of the current level. But
- ** we need a place to cache virtual table index information for each
- ** virtual table in the FROM clause and the WhereLevel structure is
- ** a convenient place since there is one WhereLevel for each FROM clause
- ** element.
- */
- sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */
-};
-
-/*
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
** and the WhereInfo.wctrlFlags member.
*/
@@ -11205,33 +11324,12 @@ struct WhereLevel {
#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
#define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */
+#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
+#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
+#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
-/*
-** The WHERE clause processing routine has two halves. The
-** first part does the start of the WHERE loop and the second
-** half does the tail of the WHERE loop. An instance of
-** this structure is returned by the first half and passed
-** into the second half to give some continuity.
+/* Allowed return values from sqlite3WhereIsDistinct()
*/
-struct WhereInfo {
- Parse *pParse; /* Parsing and code generating context */
- SrcList *pTabList; /* List of tables in the join */
- u16 nOBSat; /* Number of ORDER BY terms satisfied by indices */
- u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
- u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
- u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
- u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
- int iTop; /* The very beginning of the WHERE loop */
- int iContinue; /* Jump here to continue with next record */
- int iBreak; /* Jump here to break out of the loop */
- int nLevel; /* Number of nested loop */
- struct WhereClause *pWC; /* Decomposition of the WHERE clause */
- double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
- double nRowOut; /* Estimated number of output rows */
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
-};
-
-/* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */
#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
#define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */
@@ -11261,7 +11359,7 @@ struct WhereInfo {
struct NameContext {
Parse *pParse; /* The parser */
SrcList *pSrcList; /* One or more tables used to resolve names */
- ExprList *pEList; /* Optional list of named expressions */
+ ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
@@ -11276,8 +11374,7 @@ struct NameContext {
#define NC_HasAgg 0x02 /* One or more aggregate functions seen */
#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
-#define NC_AsMaybe 0x10 /* Resolve to AS terms of the result set only
- ** if no other resolution is available */
+#define NC_PartIdx 0x10 /* True if resolving a partial index WHERE */
/*
** An instance of the following structure contains all information
@@ -11305,7 +11402,7 @@ struct Select {
u16 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
- double nSelectRow; /* Estimated number of result rows */
+ u64 nSelectRow; /* Estimated number of result rows */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
@@ -11332,6 +11429,7 @@ struct Select {
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
#define SF_Materialize 0x0100 /* Force materialization of views */
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
+#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
/*
@@ -11453,6 +11551,7 @@ struct Parse {
u8 iColCache; /* Next entry in aColCache[] to replace */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
+ u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
int aTempReg[8]; /* Holding area for temporary registers */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
@@ -11462,6 +11561,7 @@ struct Parse {
int nSet; /* Number of sets used so far */
int nOnce; /* Number of OP_Once instructions so far */
int ckBase; /* Base register of data during check constraints */
+ int iPartIdxTab; /* Table corresponding to a partial index */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
struct yColCache {
@@ -11472,6 +11572,7 @@ struct Parse {
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 */
+ ExprList *pConstExpr;/* Constant expressions */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
@@ -11489,7 +11590,9 @@ struct Parse {
/* Information used while coding trigger programs. */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
- double nQueryLoop; /* Estimated number of iterations of a query */
+ int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */
+ int addrSkipPK; /* Address of instruction to skip PRIMARY KEY index */
+ u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u32 oldmask; /* Mask of old.* columns referenced */
u32 newmask; /* Mask of new.* columns referenced */
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
@@ -11501,6 +11604,7 @@ struct Parse {
int nVar; /* Number of '?' variables seen in the SQL so far */
int nzVar; /* Number of available slots in azVar[] */
+ u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
@@ -11514,7 +11618,6 @@ struct Parse {
#endif
char **azVar; /* Pointers to names of parameters */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
- int *aAlias; /* Register used to hold aliased result */
const char *zTail; /* All SQL text past the last semicolon parsed */
Table *pNewTable; /* A table being constructed by CREATE TABLE */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
@@ -11661,6 +11764,7 @@ typedef struct DbFixer DbFixer;
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
Schema *pSchema; /* Fix items to this schema */
+ int bVarOnly; /* Check for variable references only */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
@@ -11677,10 +11781,11 @@ struct StrAccum {
int nChar; /* Length of the string so far */
int nAlloc; /* Amount of space allocated in zText */
int mxAlloc; /* Maximum allowed string length */
- u8 mallocFailed; /* Becomes true if any memory allocation fails */
u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */
- u8 tooBig; /* Becomes true if string size exceeds limits */
+ u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
};
+#define STRACCUM_NOMEM 1
+#define STRACCUM_TOOBIG 2
/*
** A pointer to this structure is used to communicate information
@@ -11705,6 +11810,7 @@ struct Sqlite3Config {
int bOpenUri; /* True to interpret filenames as URIs */
int bUseCis; /* Use covering indices for full-scans */
int mxStrlen; /* Maximum string length */
+ int neverCorrupt; /* Database is always well-formed */
int szLookaside; /* Default lookaside buffer size */
int nLookaside; /* Default lookaside buffer count */
sqlite3_mem_methods m; /* Low-level memory allocation interface */
@@ -11742,6 +11848,24 @@ struct Sqlite3Config {
};
/*
+** This macro is used inside of assert() statements to indicate that
+** the assert is only valid on a well-formed database. Instead of:
+**
+** assert( X );
+**
+** One writes:
+**
+** assert( X || CORRUPT_DB );
+**
+** CORRUPT_DB is true during normal operation. CORRUPT_DB does not indicate
+** that the database is definitely corrupt, only that it might be corrupt.
+** For most test cases, CORRUPT_DB is set to false using a special
+** sqlite3_test_control(). This enables assert() statements to prove
+** things that are always true for well-formed databases.
+*/
+#define CORRUPT_DB (sqlite3Config.neverCorrupt==0)
+
+/*
** Context pointer passed down through the tree-walk.
*/
struct Walker {
@@ -11981,6 +12105,8 @@ SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
+SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
+SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16);
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
@@ -11989,7 +12115,7 @@ SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
SQLITE_PRIVATE void sqlite3AddColumnType(Parse*,Token*);
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,ExprSpan*);
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
-SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*);
+SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlite3_vfs**,char**,char **);
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
@@ -12042,8 +12168,9 @@ SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*);
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
+SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
- Token*, int, int);
+ Expr*, int, int);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
@@ -12059,6 +12186,12 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
+SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
+SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
@@ -12069,11 +12202,13 @@ SQLITE_PRIVATE void sqlite3ExprCacheRemove(Parse*, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheClear(Parse*);
SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse*, int, int);
SQLITE_PRIVATE int sqlite3ExprCode(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprCodeAtInit(Parse*, Expr*, int, u8);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
-SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse*, Expr*);
-SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int);
+SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8);
+#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
+#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
@@ -12085,8 +12220,9 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3Vacuum(Parse*);
SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*);
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*);
-SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*);
+SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*, int);
+SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList*, ExprList*, int);
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
@@ -12111,17 +12247,19 @@ SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
-SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, 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,int*);
-SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
-SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
+SQLITE_PRIVATE void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
+SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
+SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*);
+SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
+ u8,u8,int,int*);
+SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
+SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int, u8*, int*, int*);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
-SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, int);
+SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
+SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*);
+SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*);
SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
@@ -12191,7 +12329,7 @@ SQLITE_PRIVATE int sqlite3AuthReadCol(Parse*, const char *, const char *, int)
#endif
SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
-SQLITE_PRIVATE int sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
+SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
@@ -12203,6 +12341,12 @@ SQLITE_PRIVATE int sqlite3Atoi(const char*);
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
+SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
+SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
+#endif
+SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
/*
** Routines to read and write variable-length integers. These used to
@@ -12288,9 +12432,6 @@ SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
-#ifdef SQLITE_ENABLE_STAT3
-SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
-#endif
SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
@@ -12316,12 +12457,13 @@ SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE void sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
-SQLITE_PRIVATE char sqlite3AffinityType(const char*);
+SQLITE_PRIVATE char sqlite3AffinityType(const char*, u8*);
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
@@ -12335,7 +12477,13 @@ SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int);
SQLITE_PRIVATE void sqlite3SchemaClear(void *);
SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
-SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
+SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*);
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*);
+#endif
SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
void (*)(sqlite3_context*,int,sqlite3_value **),
void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
@@ -12355,6 +12503,12 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *);
SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void);
+SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*);
+SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*);
+#endif
+
/*
** The interface to the LEMON-generated parser
*/
@@ -12396,13 +12550,14 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
#else
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*);
SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
-SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **);
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe*);
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
+SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*);
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
@@ -12417,8 +12572,10 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
+SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
+SQLITE_PRIVATE void sqlite3ParserReset(Parse*);
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
@@ -12437,18 +12594,18 @@ SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
** provided (enforcement of FK constraints requires the triggers sub-system).
*/
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
-SQLITE_PRIVATE void sqlite3FkCheck(Parse*, Table*, int, int);
+SQLITE_PRIVATE void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
SQLITE_PRIVATE void sqlite3FkDropTable(Parse*, SrcList *, Table*);
-SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int);
+SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int);
SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*);
SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
#else
- #define sqlite3FkActions(a,b,c,d)
- #define sqlite3FkCheck(a,b,c,d)
+ #define sqlite3FkActions(a,b,c,d,e,f)
+ #define sqlite3FkCheck(a,b,c,d,e,f)
#define sqlite3FkDropTable(a,b,c)
- #define sqlite3FkOldmask(a,b) 0
- #define sqlite3FkRequired(a,b,c,d) 0
+ #define sqlite3FkOldmask(a,b) 0
+ #define sqlite3FkRequired(a,b,c,d) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
@@ -12735,6 +12892,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_USE_URI, /* bOpenUri */
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
+ 0, /* neverCorrupt */
128, /* szLookaside */
500, /* nLookaside */
{0,0,0,0,0,0,0,0}, /* m */
@@ -12770,7 +12928,6 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
#endif
};
-
/*
** Hash table for global functions - functions common to all
** database connections. After initialization, this table is
@@ -12937,7 +13094,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_ENABLE_RTREE
"ENABLE_RTREE",
#endif
-#ifdef SQLITE_ENABLE_STAT3
+#if defined(SQLITE_ENABLE_STAT4)
+ "ENABLE_STAT4",
+#elif defined(SQLITE_ENABLE_STAT3)
"ENABLE_STAT3",
#endif
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
@@ -13165,6 +13324,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_SOUNDEX
"SOUNDEX",
#endif
+#ifdef SQLITE_SYSTEM_MALLOC
+ "SYSTEM_MALLOC",
+#endif
#ifdef SQLITE_TCL
"TCL",
#endif
@@ -13180,6 +13342,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
+#ifdef SQLITE_WIN32_MALLOC
+ "WIN32_MALLOC",
+#endif
#ifdef SQLITE_ZERO_MALLOC
"ZERO_MALLOC"
#endif
@@ -13279,7 +13444,7 @@ typedef struct VdbeOp Op;
/*
** Boolean values
*/
-typedef unsigned char Bool;
+typedef unsigned Bool;
/* Opaque type used by code in vdbesort.c */
typedef struct VdbeSorter VdbeSorter;
@@ -13287,12 +13452,18 @@ typedef struct VdbeSorter VdbeSorter;
/* Opaque type used by the explainer */
typedef struct Explain Explain;
+/* Elements of the linked list at Vdbe.pAuxData */
+typedef struct AuxData AuxData;
+
/*
** A cursor is a pointer into a single BTree within a database file.
** The cursor can seek to a BTree entry with a particular key, or
** loop over all entries of the Btree. You can also insert new BTree
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
+**
+** Cursors can also point to virtual tables, sorters, or "pseudo-tables".
+** A pseudo-table is a single-row table implemented by registers.
**
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
@@ -13301,31 +13472,24 @@ struct VdbeCursor {
BtCursor *pCursor; /* The cursor structure of the backend */
Btree *pBt; /* Separate file holding temporary table */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
- int iDb; /* Index of cursor database in db->aDb[] (or -1) */
+ int seekResult; /* Result of previous sqlite3BtreeMoveto() */
int pseudoTableReg; /* Register holding pseudotable content. */
- int nField; /* Number of fields in the header */
- Bool zeroed; /* True if zeroed out and ready for reuse */
- Bool rowidIsValid; /* True if lastRowid is valid */
- Bool atFirst; /* True if pointing to first entry */
- Bool useRandomRowid; /* Generate new record numbers semi-randomly */
- Bool nullRow; /* True if pointing to a row with no data */
- Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
- Bool isTable; /* True if a table requiring integer keys */
- Bool isIndex; /* True if an index containing keys only - no data */
- Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
- Bool isSorter; /* True if a new-style sorter */
- Bool multiPseudo; /* Multi-register pseudo-cursor */
+ i16 nField; /* Number of fields in the header */
+ u16 nHdrParsed; /* Number of header fields parsed so far */
+ i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
+ u8 nullRow; /* True if pointing to a row with no data */
+ u8 rowidIsValid; /* True if lastRowid is valid */
+ u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
+ Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
+ Bool isTable:1; /* True if a table requiring integer keys */
+ Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
+ Bool multiPseudo:1; /* Multi-register pseudo-cursor */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
- const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
- i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
+ i64 lastRowid; /* Rowid being deleted by OP_Delete */
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
- /* 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 cacheStatus matches
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
@@ -13336,10 +13500,14 @@ struct VdbeCursor {
** be NULL.
*/
u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
- int payloadSize; /* Total number of bytes in the record */
- u32 *aType; /* Type values for all entries in the record */
- u32 *aOffset; /* Cached offsets to the start of each columns data */
- u8 *aRow; /* Data for the current row, if all on one page */
+ u32 payloadSize; /* Total number of bytes in the record */
+ u32 szRow; /* Byte available in aRow */
+ u32 iHdrOffset; /* Offset to next unparsed byte of the header */
+ const u8 *aRow; /* Data for the current row, if all on one page */
+ u32 aType[1]; /* Type values for all entries in the record */
+ /* 2*nField extra array elements allocated for aType[], beyond the one
+ ** static element declared in the structure. nField total array slots for
+ ** aType[] and nField+1 array slots for aOffset[] */
};
typedef struct VdbeCursor VdbeCursor;
@@ -13473,23 +13641,19 @@ struct Mem {
#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
#endif
-
-/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
-** additional information about auxiliary information bound to arguments
-** of the function. This is used to implement the sqlite3_get_auxdata()
-** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
-** that can be associated with a constant argument to a function. This
-** allows functions such as "regexp" to compile their constant regular
-** expression argument once and reused the compiled code for multiple
-** invocations.
+/*
+** Each auxilliary data pointer stored by a user defined function
+** implementation calling sqlite3_set_auxdata() is stored in an instance
+** of this structure. All such structures associated with a single VM
+** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
+** when the VM is halted (if not before).
*/
-struct VdbeFunc {
- FuncDef *pFunc; /* The definition of the function */
- int nAux; /* Number of entries allocated for apAux[] */
- struct AuxData {
- void *pAux; /* Aux data for the i-th argument */
- void (*xDelete)(void *); /* Destructor for the aux data */
- } apAux[1]; /* One slot for each function argument */
+struct AuxData {
+ int iOp; /* Instruction number of OP_Function opcode */
+ int iArg; /* Index of function argument. */
+ void *pAux; /* Aux data pointer */
+ void (*xDelete)(void *); /* Destructor for the aux data */
+ AuxData *pNext; /* Next element in list */
};
/*
@@ -13507,12 +13671,14 @@ struct VdbeFunc {
*/
struct sqlite3_context {
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
- VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
Mem s; /* The return value is stored here */
Mem *pMem; /* Memory cell used to store aggregate context */
CollSeq *pColl; /* Collating sequence */
+ Vdbe *pVdbe; /* The VM that owns this context */
+ int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
- int skipFlag; /* Skip skip accumulator loading if true */
+ u8 skipFlag; /* Skip skip accumulator loading if true */
+ u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
};
/*
@@ -13580,24 +13746,24 @@ struct Vdbe {
bft expired:1; /* True if the VM needs to be recompiled */
bft runOnlyOnce:1; /* Automatically expire on reset */
bft usesStmtJournal:1; /* True if uses a statement journal */
- bft readOnly:1; /* True for read-only statements */
+ bft readOnly:1; /* True for statements that do not write */
+ bft bIsReader:1; /* True for statements that read */
bft isPrepareV2:1; /* True if prepared with prepare_v2() */
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
int nChange; /* Number of db changes made since last reset */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
int iStatement; /* Statement number (or 0 if has not opened stmt) */
- int aCounter[3]; /* Counters used by sqlite3_stmt_status() */
+ u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
#ifndef SQLITE_OMIT_TRACE
i64 startTime; /* Time when query started - used for profiling */
#endif
+ i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
+ i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
char *zSql; /* Text of the SQL statement that generated this */
void *pFree; /* Free this when deleting the vdbe */
-#ifdef SQLITE_DEBUG
- FILE *trace; /* Write an execution trace here, if not NULL */
-#endif
#ifdef SQLITE_ENABLE_TREE_EXPLAIN
Explain *pExplain; /* The explainer */
char *zExplain; /* Explanation of data structures */
@@ -13609,6 +13775,7 @@ struct Vdbe {
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
int nOnceFlag; /* Size of array aOnceFlag[] */
u8 *aOnceFlag; /* Flags for OP_Once */
+ AuxData *pAuxData; /* Linked list of auxdata allocations */
};
/*
@@ -13632,7 +13799,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int);
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
-SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
@@ -13665,7 +13832,7 @@ SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
-SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p);
#define VdbeMemRelease(X) \
@@ -13686,7 +13853,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
-SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
+SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
@@ -13953,6 +14120,16 @@ SQLITE_API int sqlite3_db_status(
break;
}
+ /* Set *pCurrent to non-zero if there are unresolved deferred foreign
+ ** key constraints. Set *pCurrent to zero if all foreign key constraints
+ ** have been satisfied. The *pHighwater is always set to zero.
+ */
+ case SQLITE_DBSTATUS_DEFERRED_FKS: {
+ *pHighwater = 0;
+ *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
+ break;
+ }
+
default: {
rc = SQLITE_ERROR;
}
@@ -14258,8 +14435,8 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
** Return the number of errors.
*/
static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
- sqlite3 *db = sqlite3_context_db_handle(context);
- if( sqlite3OsCurrentTimeInt64(db->pVfs, &p->iJD)==SQLITE_OK ){
+ p->iJD = sqlite3StmtCurrentTime(context);
+ if( p->iJD>0 ){
p->validJD = 1;
return 0;
}else{
@@ -14394,6 +14571,10 @@ struct tm *__cdecl localtime(const time_t *t);
**
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
** routine will always fail.
+**
+** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
+** library function localtime_r() is used to assist in the calculation of
+** local time.
*/
static int osLocaltime(time_t *t, struct tm *pTm){
int rc;
@@ -14450,6 +14631,11 @@ static sqlite3_int64 localtimeOffset(
x = *p;
computeYMD_HMS(&x);
if( x.Y<1971 || x.Y>=2038 ){
+ /* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
+ ** works for years between 1970 and 2037. For dates outside this range,
+ ** SQLite attempts to map the year into an equivalent year within this
+ ** range, do the calculation, then map the year back.
+ */
x.Y = 2000;
x.M = 1;
x.D = 1;
@@ -15046,8 +15232,8 @@ static void currentTimeFunc(
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
- db = sqlite3_context_db_handle(context);
- if( sqlite3OsCurrentTimeInt64(db->pVfs, &iT) ) return;
+ iT = sqlite3StmtCurrentTime(context);
+ if( iT<=0 ) return;
t = iT/1000 - 10000*(sqlite3_int64)21086676;
#ifdef HAVE_GMTIME_R
pTm = gmtime_r(&t, &sNow);
@@ -15675,16 +15861,6 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
** macros.
*/
#ifdef SQLITE_SYSTEM_MALLOC
-
-/*
-** The MSVCRT has malloc_usable_size() but it is called _msize().
-** The use of _msize() is automatic, but can be disabled by compiling
-** with -DSQLITE_WITHOUT_MSIZE
-*/
-#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
-# define SQLITE_MALLOCSIZE _msize
-#endif
-
#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
/*
@@ -15707,22 +15883,48 @@ static malloc_zone_t* _sqliteZone_;
** Use standard C library malloc and free on non-Apple systems.
** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
*/
-#define SQLITE_MALLOC(x) malloc(x)
-#define SQLITE_FREE(x) free(x)
-#define SQLITE_REALLOC(x,y) realloc((x),(y))
+#define SQLITE_MALLOC(x) malloc(x)
+#define SQLITE_FREE(x) free(x)
+#define SQLITE_REALLOC(x,y) realloc((x),(y))
-#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \
- || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE))
-# include <malloc.h> /* Needed for malloc_usable_size on linux */
-#endif
-#ifdef HAVE_MALLOC_USABLE_SIZE
-# ifndef SQLITE_MALLOCSIZE
-# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
-# endif
-#else
-# undef SQLITE_MALLOCSIZE
+/*
+** The malloc.h header file is needed for malloc_usable_size() function
+** on some systems (e.g. Linux).
+*/
+#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE)
+# define SQLITE_USE_MALLOC_H
+# define SQLITE_USE_MALLOC_USABLE_SIZE
+/*
+** The MSVCRT has malloc_usable_size(), but it is called _msize(). The
+** use of _msize() is automatic, but can be disabled by compiling with
+** -DSQLITE_WITHOUT_MSIZE. Using the _msize() function also requires
+** the malloc.h header file.
+*/
+#elif defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
+# define SQLITE_USE_MALLOC_H
+# define SQLITE_USE_MSIZE
#endif
+/*
+** Include the malloc.h header file, if necessary. Also set define macro
+** SQLITE_MALLOCSIZE to the appropriate function name, which is _msize()
+** for MSVC and malloc_usable_size() for most other systems (e.g. Linux).
+** The memory size function can always be overridden manually by defining
+** the macro SQLITE_MALLOCSIZE to the desired function name.
+*/
+#if defined(SQLITE_USE_MALLOC_H)
+# include <malloc.h>
+# if defined(SQLITE_USE_MALLOC_USABLE_SIZE)
+# if !defined(SQLITE_MALLOCSIZE)
+# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
+# endif
+# elif defined(SQLITE_USE_MSIZE)
+# if !defined(SQLITE_MALLOCSIZE)
+# define SQLITE_MALLOCSIZE _msize
+# endif
+# endif
+#endif /* defined(SQLITE_USE_MALLOC_H) */
+
#endif /* __APPLE__ or not __APPLE__ */
/*
@@ -16086,7 +16288,7 @@ static int sqlite3MemSize(void *p){
return 0;
}
pHdr = sqlite3MemsysGetHeader(p);
- return pHdr->iSize;
+ return (int)pHdr->iSize;
}
/*
@@ -16128,7 +16330,7 @@ static void randomFill(char *pBuf, int nByte){
x = SQLITE_PTR_TO_INT(pBuf);
y = nByte | 1;
while( nByte >= 4 ){
- x = (x>>1) ^ (-(x&1) & 0xd0000001);
+ x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
y = y*1103515245 + 12345;
r = x ^ y;
*(int*)pBuf = r;
@@ -16136,7 +16338,7 @@ static void randomFill(char *pBuf, int nByte){
nByte -= 4;
}
while( nByte-- > 0 ){
- x = (x>>1) ^ (-(x&1) & 0xd0000001);
+ x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
y = y*1103515245 + 12345;
r = x ^ y;
*(pBuf++) = r & 0xff;
@@ -16231,9 +16433,9 @@ static void sqlite3MemFree(void *pPrior){
}
z = (char*)pBt;
z -= pHdr->nTitle;
- adjustStats(pHdr->iSize, -1);
+ adjustStats((int)pHdr->iSize, -1);
randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
- pHdr->iSize + sizeof(int) + pHdr->nTitle);
+ (int)pHdr->iSize + sizeof(int) + pHdr->nTitle);
free(z);
sqlite3_mutex_leave(mem.mutex);
}
@@ -16255,9 +16457,9 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
pOldHdr = sqlite3MemsysGetHeader(pPrior);
pNew = sqlite3MemMalloc(nByte);
if( pNew ){
- memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
+ memcpy(pNew, pPrior, (int)(nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize));
if( nByte>pOldHdr->iSize ){
- randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
+ randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize);
}
sqlite3MemFree(pPrior);
}
@@ -16372,7 +16574,7 @@ SQLITE_PRIVATE void sqlite3MemdebugSync(){
for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
void **pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
- mem.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
+ mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
}
}
@@ -17256,13 +17458,13 @@ static SQLITE_WSD struct Mem5Global {
} mem5;
/*
-** Access the static variable through a macro for SQLITE_OMIT_WSD
+** Access the static variable through a macro for SQLITE_OMIT_WSD.
*/
#define mem5 GLOBAL(struct Mem5Global, mem5)
/*
** Assuming mem5.zPool is divided up into an array of Mem5Link
-** structures, return a pointer to the idx-th such lik.
+** structures, return a pointer to the idx-th such link.
*/
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
@@ -17328,7 +17530,7 @@ static void memsys5Leave(void){
static int memsys5Size(void *p){
int iSize = 0;
if( p ){
- int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
+ int i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom);
assert( i>=0 && i<mem5.nBlock );
iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
}
@@ -17336,29 +17538,10 @@ static int memsys5Size(void *p){
}
/*
-** Find the first entry on the freelist iLogsize. Unlink that
-** entry and return its index.
-*/
-static int memsys5UnlinkFirst(int iLogsize){
- int i;
- int iFirst;
-
- assert( iLogsize>=0 && iLogsize<=LOGMAX );
- i = iFirst = mem5.aiFreelist[iLogsize];
- assert( iFirst>=0 );
- while( i>0 ){
- if( i<iFirst ) iFirst = i;
- i = MEM5LINK(i)->next;
- }
- memsys5Unlink(iFirst, iLogsize);
- return iFirst;
-}
-
-/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable. Return NULL if nBytes==0.
**
-** The caller guarantees that nByte positive.
+** The caller guarantees that nByte is positive.
**
** The caller has obtained a mutex prior to invoking this
** routine so there is never any chance that two or more
@@ -17399,7 +17582,8 @@ static void *memsys5MallocUnsafe(int nByte){
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
return 0;
}
- i = memsys5UnlinkFirst(iBin);
+ i = mem5.aiFreelist[iBin];
+ memsys5Unlink(i, iBin);
while( iBin>iLogsize ){
int newSize;
@@ -17433,7 +17617,7 @@ static void memsys5FreeUnsafe(void *pOld){
/* Set iBlock to the index of the block pointed to by pOld in
** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
*/
- iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;
+ iBlock = (int)(((u8 *)pOld-mem5.zPool)/mem5.szAtom);
/* Check that the pointer pOld points to a valid, non-free block. */
assert( iBlock>=0 && iBlock<mem5.nBlock );
@@ -17480,7 +17664,7 @@ static void memsys5FreeUnsafe(void *pOld){
}
/*
-** Allocate nBytes of memory
+** Allocate nBytes of memory.
*/
static void *memsys5Malloc(int nBytes){
sqlite3_int64 *p = 0;
@@ -18494,7 +18678,7 @@ struct sqlite3_mutex {
}
return osType==2;
}
-#endif /* SQLITE_OS_WINCE */
+#endif /* SQLITE_OS_WINCE || SQLITE_OS_WINRT */
#endif
#ifdef SQLITE_DEBUG
@@ -18532,7 +18716,7 @@ static int winMutex_isInit = 0;
** processing, the "interlocked" magic is probably not
** strictly necessary.
*/
-static long winMutex_lock = 0;
+static LONG winMutex_lock = 0;
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
@@ -19253,6 +19437,7 @@ SQLITE_API void sqlite3_free(void *p){
*/
SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
+ if( p==0 ) return;
if( db ){
if( db->pnBytesFreed ){
*db->pnBytesFreed += sqlite3DbMallocSize(db, p);
@@ -19912,7 +20097,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
nOut = precision + 10;
zOut = zExtra = sqlite3Malloc( nOut );
if( zOut==0 ){
- pAccum->mallocFailed = 1;
+ pAccum->accError = STRACCUM_NOMEM;
return;
}
}
@@ -19966,13 +20151,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
else prefix = 0;
}
if( xtype==etGENERIC && precision>0 ) precision--;
-#if 0
- /* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
- for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
-#else
- /* It makes more sense to use 0.5 */
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
-#endif
if( xtype==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
@@ -20027,10 +20206,10 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}else{
e2 = exp;
}
- if( e2+precision+width > etBUFSIZE - 15 ){
- bufpt = zExtra = sqlite3Malloc( e2+precision+width+15 );
+ if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
+ bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
if( bufpt==0 ){
- pAccum->mallocFailed = 1;
+ pAccum->accError = STRACCUM_NOMEM;
return;
}
}
@@ -20165,7 +20344,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( n>etBUFSIZE ){
bufpt = zExtra = sqlite3Malloc( n );
if( bufpt==0 ){
- pAccum->mallocFailed = 1;
+ pAccum->accError = STRACCUM_NOMEM;
return;
}
}else{
@@ -20243,22 +20422,20 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
*/
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
assert( z!=0 || N==0 );
- if( p->tooBig | p->mallocFailed ){
- testcase(p->tooBig);
- testcase(p->mallocFailed);
+ if( p->accError ){
+ testcase(p->accError==STRACCUM_TOOBIG);
+ testcase(p->accError==STRACCUM_NOMEM);
return;
}
assert( p->zText!=0 || p->nChar==0 );
- if( N<0 ){
+ if( N<=0 ){
+ if( N==0 || z[0]==0 ) return;
N = sqlite3Strlen30(z);
}
- if( N==0 || NEVER(z==0) ){
- return;
- }
if( p->nChar+N >= p->nAlloc ){
char *zNew;
if( !p->useMalloc ){
- p->tooBig = 1;
+ p->accError = STRACCUM_TOOBIG;
N = p->nAlloc - p->nChar - 1;
if( N<=0 ){
return;
@@ -20269,7 +20446,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
szNew += N + 1;
if( szNew > p->mxAlloc ){
sqlite3StrAccumReset(p);
- p->tooBig = 1;
+ p->accError = STRACCUM_TOOBIG;
return;
}else{
p->nAlloc = (int)szNew;
@@ -20283,7 +20460,7 @@ SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
p->zText = zNew;
}else{
- p->mallocFailed = 1;
+ p->accError = STRACCUM_NOMEM;
sqlite3StrAccumReset(p);
return;
}
@@ -20311,7 +20488,7 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
- p->mallocFailed = 1;
+ p->accError = STRACCUM_NOMEM;
}
}
}
@@ -20342,8 +20519,7 @@ SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx)
p->nAlloc = n;
p->mxAlloc = mx;
p->useMalloc = 1;
- p->tooBig = 0;
- p->mallocFailed = 0;
+ p->accError = 0;
}
/*
@@ -20360,7 +20536,7 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a
acc.db = db;
sqlite3VXPrintf(&acc, 1, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
- if( acc.mallocFailed ){
+ if( acc.accError==STRACCUM_NOMEM ){
db->mallocFailed = 1;
}
return z;
@@ -20557,24 +20733,11 @@ static SQLITE_WSD struct sqlite3PrngType {
} sqlite3Prng;
/*
-** Get a single 8-bit random value from the RC4 PRNG. The Mutex
-** must be held while executing this routine.
-**
-** Why not just use a library random generator like lrand48() for this?
-** Because the OP_NewRowid opcode in the VDBE depends on having a very
-** good source of random numbers. The lrand48() library function may
-** well be good enough. But maybe not. Or maybe lrand48() has some
-** subtle problems on some systems that could cause problems. It is hard
-** to know. To minimize the risk of problems due to bad lrand48()
-** implementations, SQLite uses this random number generator based
-** on RC4, which we know works very well.
-**
-** (Later): Actually, OP_NewRowid does not depend on a good source of
-** randomness any more. But we will leave this code in all the same.
+** Return N random bytes.
*/
-static u8 randomByte(void){
+SQLITE_API void sqlite3_randomness(int N, void *pBuf){
unsigned char t;
-
+ unsigned char *zBuf = pBuf;
/* The "wsdPrng" macro will resolve to the pseudo-random number generator
** state vector. If writable static data is unsupported on the target,
@@ -20589,6 +20752,10 @@ static u8 randomByte(void){
# define wsdPrng sqlite3Prng
#endif
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
+ sqlite3_mutex_enter(mutex);
+#endif
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
@@ -20617,28 +20784,14 @@ static u8 randomByte(void){
wsdPrng.isInit = 1;
}
- /* Generate and return single random byte
- */
- wsdPrng.i++;
- t = wsdPrng.s[wsdPrng.i];
- wsdPrng.j += t;
- wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
- wsdPrng.s[wsdPrng.j] = t;
- t += wsdPrng.s[wsdPrng.i];
- return wsdPrng.s[t];
-}
-
-/*
-** Return N random bytes.
-*/
-SQLITE_API void sqlite3_randomness(int N, void *pBuf){
- unsigned char *zBuf = pBuf;
-#if SQLITE_THREADSAFE
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
-#endif
- sqlite3_mutex_enter(mutex);
while( N-- ){
- *(zBuf++) = randomByte();
+ wsdPrng.i++;
+ t = wsdPrng.s[wsdPrng.i];
+ wsdPrng.j += t;
+ wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = t;
+ t += wsdPrng.s[wsdPrng.i];
+ *(zBuf++) = wsdPrng.s[t];
}
sqlite3_mutex_leave(mutex);
}
@@ -21126,32 +21279,6 @@ SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 e
}
/*
-** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
-** enc. A pointer to the new string is returned, and the value of *pnOut
-** is set to the length of the returned string in bytes. The call should
-** arrange to call sqlite3DbFree() on the returned pointer when it is
-** no longer required.
-**
-** If a malloc failure occurs, NULL is returned and the db.mallocFailed
-** flag set.
-*/
-#ifdef SQLITE_ENABLE_STAT3
-SQLITE_PRIVATE char *sqlite3Utf8to16(sqlite3 *db, u8 enc, char *z, int n, int *pnOut){
- Mem m;
- memset(&m, 0, sizeof(m));
- m.db = db;
- sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC);
- if( sqlite3VdbeMemTranslate(&m, enc) ){
- assert( db->mallocFailed );
- return 0;
- }
- assert( m.z==m.zMalloc );
- *pnOut = m.n;
- return m.z;
-}
-#endif
-
-/*
** zIn is a UTF-16 encoded unicode string at least nChar characters long.
** Return the number of bytes in the first nChar unicode characters
** in pZ. nChar must be non-negative.
@@ -21426,7 +21553,8 @@ SQLITE_PRIVATE int sqlite3Dequote(char *z){
case '[': quote = ']'; break; /* For MS SqlServer compatibility */
default: return -1;
}
- for(i=1, j=0; ALWAYS(z[i]); i++){
+ for(i=1, j=0;; i++){
+ assert( z[i] );
if( z[i]==quote ){
if( z[i+1]==quote ){
z[j++] = quote;
@@ -21697,12 +21825,12 @@ static int compare2pow63(const char *zNum, int incr){
** If the zNum value is representable as a 64-bit twos-complement
** integer, then write that value into *pNum and return 0.
**
-** If zNum is exactly 9223372036854665808, return 2. This special
-** case is broken out because while 9223372036854665808 cannot be a
-** signed 64-bit integer, its negative -9223372036854665808 can be.
+** If zNum is exactly 9223372036854775808, return 2. This special
+** case is broken out because while 9223372036854775808 cannot be a
+** signed 64-bit integer, its negative -9223372036854775808 can be.
**
** If zNum is too big for a 64-bit integer and is not
-** 9223372036854665808 or if zNum contains any non-numeric text,
+** 9223372036854775808 or if zNum contains any non-numeric text,
** then return 1.
**
** length is the number of bytes in the string (bytes, not characters).
@@ -21744,7 +21872,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
u = u*10 + c - '0';
}
if( u>LARGEST_INT64 ){
- *pNum = SMALLEST_INT64;
+ *pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
}else if( neg ){
*pNum = -(i64)u;
}else{
@@ -21775,7 +21903,6 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
/* zNum is exactly 9223372036854775808. Fits if negative. The
** special case 2 overflow if positive */
assert( u-1==LARGEST_INT64 );
- assert( (*pNum)==SMALLEST_INT64 );
return neg ? 0 : 2;
}
}
@@ -22441,6 +22568,85 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
}
#endif
+/*
+** Find (an approximate) sum of two LogEst values. This computation is
+** not a simple "+" operator because LogEst is stored as a logarithmic
+** value.
+**
+*/
+SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
+ static const unsigned char x[] = {
+ 10, 10, /* 0,1 */
+ 9, 9, /* 2,3 */
+ 8, 8, /* 4,5 */
+ 7, 7, 7, /* 6,7,8 */
+ 6, 6, 6, /* 9,10,11 */
+ 5, 5, 5, /* 12-14 */
+ 4, 4, 4, 4, /* 15-18 */
+ 3, 3, 3, 3, 3, 3, /* 19-24 */
+ 2, 2, 2, 2, 2, 2, 2, /* 25-31 */
+ };
+ if( a>=b ){
+ if( a>b+49 ) return a;
+ if( a>b+31 ) return a+1;
+ return a+x[a-b];
+ }else{
+ if( b>a+49 ) return b;
+ if( b>a+31 ) return b+1;
+ return b+x[b-a];
+ }
+}
+
+/*
+** Convert an integer into a LogEst. In other words, compute a
+** good approximatation for 10*log2(x).
+*/
+SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
+ static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
+ LogEst y = 40;
+ if( x<8 ){
+ if( x<2 ) return 0;
+ while( x<8 ){ y -= 10; x <<= 1; }
+ }else{
+ while( x>255 ){ y += 40; x >>= 4; }
+ while( x>15 ){ y += 10; x >>= 1; }
+ }
+ return a[x&7] + y - 10;
+}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Convert a double into a LogEst
+** In other words, compute an approximation for 10*log2(x).
+*/
+SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
+ u64 a;
+ LogEst e;
+ assert( sizeof(x)==8 && sizeof(a)==8 );
+ if( x<=1 ) return 0;
+ if( x<=2000000000 ) return sqlite3LogEst((u64)x);
+ memcpy(&a, &x, 8);
+ e = (a>>52) - 1022;
+ return e*10;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/*
+** Convert a LogEst into an integer.
+*/
+SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
+ u64 n;
+ if( x<10 ) return 1;
+ n = x%10;
+ x /= 10;
+ if( n>=5 ) n -= 2;
+ else if( n>=1 ) n -= 1;
+ if( x>=3 ){
+ return x>60 ? (u64)LARGEST_INT64 : (n+8)<<(x-3);
+ }
+ return (n+8)>>(3-x);
+}
+
/************** End of util.c ************************************************/
/************** Begin file hash.c ********************************************/
/*
@@ -22728,159 +22934,166 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, voi
/************** Begin file opcodes.c *****************************************/
/* Automatically generated. Do not edit */
/* See the mkopcodec.awk script for details. */
-#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+#if !defined(SQLITE_OMIT_EXPLAIN) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG)
+# define OpHelp(X) "\0" X
+#else
+# define OpHelp(X)
+#endif
SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
static const char *const azName[] = { "?",
- /* 1 */ "Goto",
- /* 2 */ "Gosub",
- /* 3 */ "Return",
- /* 4 */ "Yield",
- /* 5 */ "HaltIfNull",
- /* 6 */ "Halt",
- /* 7 */ "Integer",
- /* 8 */ "Int64",
- /* 9 */ "String",
- /* 10 */ "Null",
- /* 11 */ "Blob",
- /* 12 */ "Variable",
- /* 13 */ "Move",
- /* 14 */ "Copy",
- /* 15 */ "SCopy",
- /* 16 */ "ResultRow",
- /* 17 */ "CollSeq",
- /* 18 */ "Function",
- /* 19 */ "Not",
- /* 20 */ "AddImm",
- /* 21 */ "MustBeInt",
- /* 22 */ "RealAffinity",
- /* 23 */ "Permutation",
- /* 24 */ "Compare",
- /* 25 */ "Jump",
- /* 26 */ "Once",
- /* 27 */ "If",
- /* 28 */ "IfNot",
- /* 29 */ "Column",
- /* 30 */ "Affinity",
- /* 31 */ "MakeRecord",
- /* 32 */ "Count",
- /* 33 */ "Savepoint",
- /* 34 */ "AutoCommit",
- /* 35 */ "Transaction",
- /* 36 */ "ReadCookie",
- /* 37 */ "SetCookie",
- /* 38 */ "VerifyCookie",
- /* 39 */ "OpenRead",
- /* 40 */ "OpenWrite",
- /* 41 */ "OpenAutoindex",
- /* 42 */ "OpenEphemeral",
- /* 43 */ "SorterOpen",
- /* 44 */ "OpenPseudo",
- /* 45 */ "Close",
- /* 46 */ "SeekLt",
- /* 47 */ "SeekLe",
- /* 48 */ "SeekGe",
- /* 49 */ "SeekGt",
- /* 50 */ "Seek",
- /* 51 */ "NotFound",
- /* 52 */ "Found",
- /* 53 */ "IsUnique",
- /* 54 */ "NotExists",
- /* 55 */ "Sequence",
- /* 56 */ "NewRowid",
- /* 57 */ "Insert",
- /* 58 */ "InsertInt",
- /* 59 */ "Delete",
- /* 60 */ "ResetCount",
- /* 61 */ "SorterCompare",
- /* 62 */ "SorterData",
- /* 63 */ "RowKey",
- /* 64 */ "RowData",
- /* 65 */ "Rowid",
- /* 66 */ "NullRow",
- /* 67 */ "Last",
- /* 68 */ "Or",
- /* 69 */ "And",
- /* 70 */ "SorterSort",
- /* 71 */ "Sort",
- /* 72 */ "Rewind",
- /* 73 */ "IsNull",
- /* 74 */ "NotNull",
- /* 75 */ "Ne",
- /* 76 */ "Eq",
- /* 77 */ "Gt",
- /* 78 */ "Le",
- /* 79 */ "Lt",
- /* 80 */ "Ge",
- /* 81 */ "SorterNext",
- /* 82 */ "BitAnd",
- /* 83 */ "BitOr",
- /* 84 */ "ShiftLeft",
- /* 85 */ "ShiftRight",
- /* 86 */ "Add",
- /* 87 */ "Subtract",
- /* 88 */ "Multiply",
- /* 89 */ "Divide",
- /* 90 */ "Remainder",
- /* 91 */ "Concat",
- /* 92 */ "Prev",
- /* 93 */ "BitNot",
- /* 94 */ "String8",
- /* 95 */ "Next",
- /* 96 */ "SorterInsert",
- /* 97 */ "IdxInsert",
- /* 98 */ "IdxDelete",
- /* 99 */ "IdxRowid",
- /* 100 */ "IdxLT",
- /* 101 */ "IdxGE",
- /* 102 */ "Destroy",
- /* 103 */ "Clear",
- /* 104 */ "CreateIndex",
- /* 105 */ "CreateTable",
- /* 106 */ "ParseSchema",
- /* 107 */ "LoadAnalysis",
- /* 108 */ "DropTable",
- /* 109 */ "DropIndex",
- /* 110 */ "DropTrigger",
- /* 111 */ "IntegrityCk",
- /* 112 */ "RowSetAdd",
- /* 113 */ "RowSetRead",
- /* 114 */ "RowSetTest",
- /* 115 */ "Program",
- /* 116 */ "Param",
- /* 117 */ "FkCounter",
- /* 118 */ "FkIfZero",
- /* 119 */ "MemMax",
- /* 120 */ "IfPos",
- /* 121 */ "IfNeg",
- /* 122 */ "IfZero",
- /* 123 */ "AggStep",
- /* 124 */ "AggFinal",
- /* 125 */ "Checkpoint",
- /* 126 */ "JournalMode",
- /* 127 */ "Vacuum",
- /* 128 */ "IncrVacuum",
- /* 129 */ "Expire",
- /* 130 */ "Real",
- /* 131 */ "TableLock",
- /* 132 */ "VBegin",
- /* 133 */ "VCreate",
- /* 134 */ "VDestroy",
- /* 135 */ "VOpen",
- /* 136 */ "VFilter",
- /* 137 */ "VColumn",
- /* 138 */ "VNext",
- /* 139 */ "VRename",
- /* 140 */ "VUpdate",
- /* 141 */ "ToText",
- /* 142 */ "ToBlob",
- /* 143 */ "ToNumeric",
- /* 144 */ "ToInt",
- /* 145 */ "ToReal",
- /* 146 */ "Pagecount",
- /* 147 */ "MaxPgcnt",
- /* 148 */ "Trace",
- /* 149 */ "Noop",
- /* 150 */ "Explain",
+ /* 1 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
+ /* 2 */ "Savepoint" OpHelp(""),
+ /* 3 */ "AutoCommit" OpHelp(""),
+ /* 4 */ "Transaction" OpHelp(""),
+ /* 5 */ "SorterNext" OpHelp(""),
+ /* 6 */ "PrevIfOpen" OpHelp(""),
+ /* 7 */ "NextIfOpen" OpHelp(""),
+ /* 8 */ "Prev" OpHelp(""),
+ /* 9 */ "Next" OpHelp(""),
+ /* 10 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 11 */ "Checkpoint" OpHelp(""),
+ /* 12 */ "JournalMode" OpHelp(""),
+ /* 13 */ "Vacuum" OpHelp(""),
+ /* 14 */ "VFilter" OpHelp("iPlan=r[P3] zPlan='P4'"),
+ /* 15 */ "VUpdate" OpHelp("data=r[P3@P2]"),
+ /* 16 */ "Goto" OpHelp(""),
+ /* 17 */ "Gosub" OpHelp(""),
+ /* 18 */ "Return" OpHelp(""),
+ /* 19 */ "Not" OpHelp("r[P2]= !r[P1]"),
+ /* 20 */ "Yield" OpHelp(""),
+ /* 21 */ "HaltIfNull" OpHelp("if r[P3] null then halt"),
+ /* 22 */ "Halt" OpHelp(""),
+ /* 23 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 24 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 25 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 26 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 27 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 28 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 29 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 30 */ "Copy" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 31 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 32 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 33 */ "CollSeq" OpHelp(""),
+ /* 34 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 35 */ "MustBeInt" OpHelp(""),
+ /* 36 */ "RealAffinity" OpHelp(""),
+ /* 37 */ "Permutation" OpHelp(""),
+ /* 38 */ "Compare" OpHelp(""),
+ /* 39 */ "Jump" OpHelp(""),
+ /* 40 */ "Once" OpHelp(""),
+ /* 41 */ "If" OpHelp(""),
+ /* 42 */ "IfNot" OpHelp(""),
+ /* 43 */ "Column" OpHelp("r[P3]=PX"),
+ /* 44 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 45 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 46 */ "Count" OpHelp("r[P2]=count()"),
+ /* 47 */ "ReadCookie" OpHelp(""),
+ /* 48 */ "SetCookie" OpHelp(""),
+ /* 49 */ "VerifyCookie" OpHelp(""),
+ /* 50 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 51 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 52 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 53 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 54 */ "SorterOpen" OpHelp(""),
+ /* 55 */ "OpenPseudo" OpHelp("content in r[P2@P3]"),
+ /* 56 */ "Close" OpHelp(""),
+ /* 57 */ "SeekLt" OpHelp("key=r[P3@P4]"),
+ /* 58 */ "SeekLe" OpHelp("key=r[P3@P4]"),
+ /* 59 */ "SeekGe" OpHelp("key=r[P3@P4]"),
+ /* 60 */ "SeekGt" OpHelp("key=r[P3@P4]"),
+ /* 61 */ "Seek" OpHelp("intkey=r[P2]"),
+ /* 62 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 63 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 64 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 65 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 66 */ "Sequence" OpHelp("r[P2]=rowid"),
+ /* 67 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 68 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 69 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
+ /* 70 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
+ /* 71 */ "InsertInt" OpHelp("intkey=P3 data=r[P2]"),
+ /* 72 */ "Delete" OpHelp(""),
+ /* 73 */ "ResetCount" OpHelp(""),
+ /* 74 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
+ /* 75 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
+ /* 76 */ "Ne" OpHelp("if r[P1]!=r[P3] goto P2"),
+ /* 77 */ "Eq" OpHelp("if r[P1]==r[P3] goto P2"),
+ /* 78 */ "Gt" OpHelp("if r[P1]>r[P3] goto P2"),
+ /* 79 */ "Le" OpHelp("if r[P1]<=r[P3] goto P2"),
+ /* 80 */ "Lt" OpHelp("if r[P1]<r[P3] goto P2"),
+ /* 81 */ "Ge" OpHelp("if r[P1]>=r[P3] goto P2"),
+ /* 82 */ "SorterCompare" OpHelp("if key(P1)!=rtrim(r[P3],P4) goto P2"),
+ /* 83 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 84 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 85 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
+ /* 86 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
+ /* 87 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 88 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 89 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 90 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 91 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 92 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 93 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 94 */ "BitNot" OpHelp("r[P1]= ~r[P1]"),
+ /* 95 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 96 */ "RowKey" OpHelp("r[P2]=key"),
+ /* 97 */ "RowData" OpHelp("r[P2]=data"),
+ /* 98 */ "Rowid" OpHelp("r[P2]=rowid"),
+ /* 99 */ "NullRow" OpHelp(""),
+ /* 100 */ "Last" OpHelp(""),
+ /* 101 */ "SorterSort" OpHelp(""),
+ /* 102 */ "Sort" OpHelp(""),
+ /* 103 */ "Rewind" OpHelp(""),
+ /* 104 */ "SorterInsert" OpHelp(""),
+ /* 105 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 106 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 107 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 108 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 109 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 110 */ "Destroy" OpHelp(""),
+ /* 111 */ "Clear" OpHelp(""),
+ /* 112 */ "CreateIndex" OpHelp("r[P2]=root iDb=P1"),
+ /* 113 */ "CreateTable" OpHelp("r[P2]=root iDb=P1"),
+ /* 114 */ "ParseSchema" OpHelp(""),
+ /* 115 */ "LoadAnalysis" OpHelp(""),
+ /* 116 */ "DropTable" OpHelp(""),
+ /* 117 */ "DropIndex" OpHelp(""),
+ /* 118 */ "DropTrigger" OpHelp(""),
+ /* 119 */ "IntegrityCk" OpHelp(""),
+ /* 120 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 121 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 122 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 123 */ "Program" OpHelp(""),
+ /* 124 */ "Param" OpHelp(""),
+ /* 125 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 126 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 127 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 128 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
+ /* 129 */ "IfNeg" OpHelp("if r[P1]<0 goto P2"),
+ /* 130 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
+ /* 131 */ "Real" OpHelp("r[P2]=P4"),
+ /* 132 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 133 */ "IncrVacuum" OpHelp(""),
+ /* 134 */ "Expire" OpHelp(""),
+ /* 135 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 136 */ "VBegin" OpHelp(""),
+ /* 137 */ "VCreate" OpHelp(""),
+ /* 138 */ "VDestroy" OpHelp(""),
+ /* 139 */ "VOpen" OpHelp(""),
+ /* 140 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 141 */ "VNext" OpHelp(""),
+ /* 142 */ "ToText" OpHelp(""),
+ /* 143 */ "ToBlob" OpHelp(""),
+ /* 144 */ "ToNumeric" OpHelp(""),
+ /* 145 */ "ToInt" OpHelp(""),
+ /* 146 */ "ToReal" OpHelp(""),
+ /* 147 */ "VRename" OpHelp(""),
+ /* 148 */ "Pagecount" OpHelp(""),
+ /* 149 */ "MaxPgcnt" OpHelp(""),
+ /* 150 */ "Trace" OpHelp(""),
+ /* 151 */ "Noop" OpHelp(""),
+ /* 152 */ "Explain" OpHelp(""),
};
return azName[i];
}
@@ -22935,13 +23148,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
*/
#if SQLITE_OS_UNIX /* This file is used on unix only */
-/* Use posix_fallocate() if it is available
-*/
-#if !defined(HAVE_POSIX_FALLOCATE) \
- && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
-# define HAVE_POSIX_FALLOCATE 1
-#endif
-
/*
** There are various methods for file locking used for concurrency
** control:
@@ -23114,11 +23320,13 @@ struct unixFile {
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
+#if SQLITE_MAX_MMAP_SIZE>0
int nFetchOut; /* Number of outstanding xFetch refs */
sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */
sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
void *pMapRegion; /* Memory mapped region */
+#endif
#ifdef __QNXNTO__
int sectorSize; /* Device sector size */
int deviceCharacteristics; /* Precomputed device characteristics */
@@ -23553,6 +23761,7 @@ static struct unix_syscall {
{ "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
+#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
{ "mmap", (sqlite3_syscall_ptr)mmap, 0 },
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[21].pCurrent)
@@ -23565,6 +23774,7 @@ static struct unix_syscall {
{ "mremap", (sqlite3_syscall_ptr)0, 0 },
#endif
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[23].pCurrent)
+#endif
}; /* End of the overrideable system calls */
@@ -23652,6 +23862,15 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
}
/*
+** Do not accept any file descriptor less than this value, in order to avoid
+** opening database file using file descriptors that are commonly used for
+** standard input, output, and error.
+*/
+#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
+# define SQLITE_MINIMUM_FILE_DESCRIPTOR 3
+#endif
+
+/*
** Invoke open(). Do so multiple times, until it either succeeds or
** fails for some reason other than EINTR.
**
@@ -23671,13 +23890,23 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
static int robust_open(const char *z, int f, mode_t m){
int fd;
mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
- do{
+ while(1){
#if defined(O_CLOEXEC)
fd = osOpen(z,f|O_CLOEXEC,m2);
#else
fd = osOpen(z,f,m2);
#endif
- }while( fd<0 && errno==EINTR );
+ if( fd<0 ){
+ if( errno==EINTR ) continue;
+ break;
+ }
+ if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
+ osClose(fd);
+ sqlite3_log(SQLITE_WARNING,
+ "attempt to open \"%s\" as file descriptor %d", z, fd);
+ fd = -1;
+ if( osOpen("/dev/null", f, m)<0 ) break;
+ }
if( fd>=0 ){
if( m!=0 ){
struct stat statbuf;
@@ -24971,12 +25200,16 @@ end_unlock:
** the requested locking level, this routine is a no-op.
*/
static int unixUnlock(sqlite3_file *id, int eFileLock){
+#if SQLITE_MAX_MMAP_SIZE>0
assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
+#endif
return posixUnlock(id, eFileLock, 0);
}
+#if SQLITE_MAX_MMAP_SIZE>0
static int unixMapfile(unixFile *pFd, i64 nByte);
static void unixUnmapfile(unixFile *pFd);
+#endif
/*
** This function performs the parts of the "close file" operation
@@ -24990,7 +25223,9 @@ static void unixUnmapfile(unixFile *pFd);
*/
static int closeUnixFile(sqlite3_file *id){
unixFile *pFile = (unixFile*)id;
+#if SQLITE_MAX_MMAP_SIZE>0
unixUnmapfile(pFile);
+#endif
if( pFile->h>=0 ){
robust_close(pFile, pFile->h, __LINE__);
pFile->h = -1;
@@ -26195,6 +26430,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
#endif
TIMER_START;
assert( cnt==(cnt&0x1ffff) );
+ assert( id->h>2 );
cnt &= 0x1ffff;
do{
#if defined(USE_PREAD)
@@ -26309,6 +26545,7 @@ static int seekAndWriteFd(
int rc = 0; /* Value returned by system call */
assert( nBuf==(nBuf&0x1ffff) );
+ assert( fd>2 );
nBuf &= 0x1ffff;
TIMER_START;
@@ -26694,6 +26931,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
}
#endif
+#if SQLITE_MAX_MMAP_SIZE>0
/* If the file was just truncated to a size smaller than the currently
** mapped region, reduce the effective mapping size as well. SQLite will
** use read() and write() to access data beyond this point from now on.
@@ -26701,6 +26939,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
if( nByte<pFile->mmapSize ){
pFile->mmapSize = nByte;
}
+#endif
return SQLITE_OK;
}
@@ -26790,6 +27029,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
}
}
+#if SQLITE_MAX_MMAP_SIZE>0
if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
int rc;
if( pFile->szChunk<=0 ){
@@ -26802,6 +27042,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
rc = unixMapfile(pFile, nByte);
return rc;
}
+#endif
return SQLITE_OK;
}
@@ -26870,18 +27111,24 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
return SQLITE_OK;
}
+#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
+ int rc = SQLITE_OK;
if( newLimit>sqlite3GlobalConfig.mxMmap ){
newLimit = sqlite3GlobalConfig.mxMmap;
}
*(i64*)pArg = pFile->mmapSizeMax;
- if( newLimit>=0 ){
+ if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
pFile->mmapSizeMax = newLimit;
- if( newLimit<pFile->mmapSize ) pFile->mmapSize = newLimit;
+ if( pFile->mmapSize>0 ){
+ unixUnmapfile(pFile);
+ rc = unixMapfile(pFile, -1);
+ }
}
- return SQLITE_OK;
+ return rc;
}
+#endif
#ifdef SQLITE_DEBUG
/* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and
@@ -27144,7 +27391,7 @@ static int unixShmSystemLock(
#ifdef SQLITE_DEBUG
{ u16 mask;
OSTRACE(("SHM-LOCK "));
- mask = (1<<(ofst+n)) - (1<<ofst);
+ mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
if( rc==SQLITE_OK ){
if( lockType==F_UNLCK ){
OSTRACE(("unlock %d ok", ofst));
@@ -27692,22 +27939,20 @@ static int unixShmUnmap(
# define unixShmUnmap 0
#endif /* #ifndef SQLITE_OMIT_WAL */
+#if SQLITE_MAX_MMAP_SIZE>0
/*
** If it is currently memory mapped, unmap file pFd.
*/
static void unixUnmapfile(unixFile *pFd){
assert( pFd->nFetchOut==0 );
-#if SQLITE_MAX_MMAP_SIZE>0
if( pFd->pMapRegion ){
osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
pFd->pMapRegion = 0;
pFd->mmapSize = 0;
pFd->mmapSizeActual = 0;
}
-#endif
}
-#if SQLITE_MAX_MMAP_SIZE>0
/*
** Return the system page size.
*/
@@ -27720,9 +27965,7 @@ static int unixGetPagesize(void){
return (int)sysconf(_SC_PAGESIZE);
#endif
}
-#endif /* SQLITE_MAX_MMAP_SIZE>0 */
-#if SQLITE_MAX_MMAP_SIZE>0
/*
** Attempt to set the size of the memory mapping maintained by file
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
@@ -27807,7 +28050,6 @@ static void unixRemapfile(
pFd->pMapRegion = (void *)pNew;
pFd->mmapSize = pFd->mmapSizeActual = nNew;
}
-#endif
/*
** Memory map or remap the file opened by file-descriptor pFd (if the file
@@ -27826,7 +28068,6 @@ static void unixRemapfile(
** code otherwise.
*/
static int unixMapfile(unixFile *pFd, i64 nByte){
-#if SQLITE_MAX_MMAP_SIZE>0
i64 nMap = nByte;
int rc;
@@ -27852,10 +28093,10 @@ static int unixMapfile(unixFile *pFd, i64 nByte){
unixUnmapfile(pFd);
}
}
-#endif
return SQLITE_OK;
}
+#endif /* SQLITE_MAX_MMAP_SIZE>0 */
/*
** If possible, return a pointer to a mapping of file fd starting at offset
@@ -27904,6 +28145,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
unixFile *pFd = (unixFile *)fd; /* The underlying database file */
UNUSED_PARAMETER(iOff);
+#if SQLITE_MAX_MMAP_SIZE>0
/* If p==0 (unmap the entire file) then there must be no outstanding
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
** then there must be at least one outstanding. */
@@ -27919,6 +28161,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
}
assert( pFd->nFetchOut>=0 );
+#endif
return SQLITE_OK;
}
@@ -28250,7 +28493,9 @@ static int fillInUnixFile(
pNew->pVfs = pVfs;
pNew->zPath = zFilename;
pNew->ctrlFlags = (u8)ctrlFlags;
+#if SQLITE_MAX_MMAP_SIZE>0
pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
+#endif
if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
"psow", SQLITE_POWERSAFE_OVERWRITE) ){
pNew->ctrlFlags |= UNIXFILE_PSOW;
@@ -28407,6 +28652,7 @@ static const char *unixTempFileDir(void){
static const char *azDirs[] = {
0,
0,
+ 0,
"/var/tmp",
"/usr/tmp",
"/tmp",
@@ -28417,7 +28663,8 @@ static const char *unixTempFileDir(void){
const char *zDir = 0;
azDirs[0] = sqlite3_temp_directory;
- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
+ if( !azDirs[1] ) azDirs[1] = getenv("SQLITE_TMPDIR");
+ if( !azDirs[2] ) azDirs[2] = getenv("TMPDIR");
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
if( zDir==0 ) continue;
if( osStat(zDir, &buf) ) continue;
@@ -30530,6 +30777,7 @@ SQLITE_API int sqlite3_os_end(void){
#ifdef __CYGWIN__
# include <sys/cygwin.h>
+# include <errno.h> /* amalgamator: keep */
#endif
/*
@@ -30750,7 +30998,7 @@ SQLITE_API int sqlite3_open_file_count = 0;
** available in Windows platforms based on the NT kernel.
*/
#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
-# error "WAL mode requires support from the Windows NT kernel, compile\
+# error "WAL mode requires support from the Windows NT kernel, compile\
with SQLITE_OMIT_WAL."
#endif
@@ -30758,7 +31006,7 @@ SQLITE_API int sqlite3_open_file_count = 0;
** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
** based on the sub-platform)?
*/
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI)
# define SQLITE_WIN32_HAS_ANSI
#endif
@@ -30766,11 +31014,126 @@ SQLITE_API int sqlite3_open_file_count = 0;
** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
** based on the sub-platform)?
*/
-#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
+#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \
+ !defined(SQLITE_WIN32_NO_WIDE)
# define SQLITE_WIN32_HAS_WIDE
#endif
/*
+** Make sure at least one set of Win32 APIs is available.
+*/
+#if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE)
+# error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\
+ must be defined."
+#endif
+
+/*
+** Define the required Windows SDK version constants if they are not
+** already available.
+*/
+#ifndef NTDDI_WIN8
+# define NTDDI_WIN8 0x06020000
+#endif
+
+#ifndef NTDDI_WINBLUE
+# define NTDDI_WINBLUE 0x06030000
+#endif
+
+/*
+** Check if the GetVersionEx[AW] functions should be considered deprecated
+** and avoid using them in that case. It should be noted here that if the
+** value of the SQLITE_WIN32_GETVERSIONEX pre-processor macro is zero
+** (whether via this block or via being manually specified), that implies
+** the underlying operating system will always be based on the Windows NT
+** Kernel.
+*/
+#ifndef SQLITE_WIN32_GETVERSIONEX
+# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
+# define SQLITE_WIN32_GETVERSIONEX 0
+# else
+# define SQLITE_WIN32_GETVERSIONEX 1
+# endif
+#endif
+
+/*
+** This constant should already be defined (in the "WinDef.h" SDK file).
+*/
+#ifndef MAX_PATH
+# define MAX_PATH (260)
+#endif
+
+/*
+** Maximum pathname length (in chars) for Win32. This should normally be
+** MAX_PATH.
+*/
+#ifndef SQLITE_WIN32_MAX_PATH_CHARS
+# define SQLITE_WIN32_MAX_PATH_CHARS (MAX_PATH)
+#endif
+
+/*
+** This constant should already be defined (in the "WinNT.h" SDK file).
+*/
+#ifndef UNICODE_STRING_MAX_CHARS
+# define UNICODE_STRING_MAX_CHARS (32767)
+#endif
+
+/*
+** Maximum pathname length (in chars) for WinNT. This should normally be
+** UNICODE_STRING_MAX_CHARS.
+*/
+#ifndef SQLITE_WINNT_MAX_PATH_CHARS
+# define SQLITE_WINNT_MAX_PATH_CHARS (UNICODE_STRING_MAX_CHARS)
+#endif
+
+/*
+** Maximum pathname length (in bytes) for Win32. The MAX_PATH macro is in
+** characters, so we allocate 4 bytes per character assuming worst-case of
+** 4-bytes-per-character for UTF8.
+*/
+#ifndef SQLITE_WIN32_MAX_PATH_BYTES
+# define SQLITE_WIN32_MAX_PATH_BYTES (SQLITE_WIN32_MAX_PATH_CHARS*4)
+#endif
+
+/*
+** Maximum pathname length (in bytes) for WinNT. This should normally be
+** UNICODE_STRING_MAX_CHARS * sizeof(WCHAR).
+*/
+#ifndef SQLITE_WINNT_MAX_PATH_BYTES
+# define SQLITE_WINNT_MAX_PATH_BYTES \
+ (sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS)
+#endif
+
+/*
+** Maximum error message length (in chars) for WinRT.
+*/
+#ifndef SQLITE_WIN32_MAX_ERRMSG_CHARS
+# define SQLITE_WIN32_MAX_ERRMSG_CHARS (1024)
+#endif
+
+/*
+** Returns non-zero if the character should be treated as a directory
+** separator.
+*/
+#ifndef winIsDirSep
+# define winIsDirSep(a) (((a) == '/') || ((a) == '\\'))
+#endif
+
+/*
+** This macro is used when a local variable is set to a value that is
+** [sometimes] not used by the code (e.g. via conditional compilation).
+*/
+#ifndef UNUSED_VARIABLE_VALUE
+# define UNUSED_VARIABLE_VALUE(x) (void)(x)
+#endif
+
+/*
+** Returns the character that should be used as the directory separator.
+*/
+#ifndef winGetDirSep
+# define winGetDirSep() '\\'
+#endif
+
+/*
** Do we need to manually define the Win32 file mapping APIs for use with WAL
** mode (e.g. these APIs are available in the Windows CE SDK; however, they
** are not present in the header file)?
@@ -30806,13 +31169,6 @@ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
/*
-** Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
-/*
** Some Microsoft compilers lack this definition.
*/
#ifndef INVALID_FILE_ATTRIBUTES
@@ -30828,7 +31184,7 @@ WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
#endif
#ifndef SQLITE_OMIT_WAL
-/* Forward references */
+/* Forward references to structures used for WAL */
typedef struct winShm winShm; /* A connection to shared-memory */
typedef struct winShmNode winShmNode; /* A region of shared-memory */
#endif
@@ -30958,6 +31314,7 @@ struct winFile {
# define SQLITE_WIN32_HEAP_FLAGS (0)
#endif
+
/*
** The winMemData structure stores information required by the Win32-specific
** sqlite3_mem_methods implementation.
@@ -30965,30 +31322,41 @@ struct winFile {
typedef struct winMemData winMemData;
struct winMemData {
#ifndef NDEBUG
- u32 magic; /* Magic number to detect structure corruption. */
+ u32 magic1; /* Magic number to detect structure corruption. */
#endif
HANDLE hHeap; /* The handle to our heap. */
BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
+#ifndef NDEBUG
+ u32 magic2; /* Magic number to detect structure corruption. */
+#endif
};
#ifndef NDEBUG
-#define WINMEM_MAGIC 0x42b2830b
+#define WINMEM_MAGIC1 0x42b2830b
+#define WINMEM_MAGIC2 0xbd4d7cf4
#endif
static struct winMemData win_mem_data = {
#ifndef NDEBUG
- WINMEM_MAGIC,
+ WINMEM_MAGIC1,
#endif
NULL, FALSE
+#ifndef NDEBUG
+ ,WINMEM_MAGIC2
+#endif
};
#ifndef NDEBUG
-#define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
+#define winMemAssertMagic1() assert( win_mem_data.magic1==WINMEM_MAGIC1 )
+#define winMemAssertMagic2() assert( win_mem_data.magic2==WINMEM_MAGIC2 )
+#define winMemAssertMagic() winMemAssertMagic1(); winMemAssertMagic2();
#else
#define winMemAssertMagic()
#endif
-#define winMemGetHeap() win_mem_data.hHeap
+#define winMemGetDataPtr() &win_mem_data
+#define winMemGetHeap() win_mem_data.hHeap
+#define winMemGetOwned() win_mem_data.bOwned
static void *winMemMalloc(int nBytes);
static void winMemFree(void *pPrior);
@@ -31015,7 +31383,8 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_os_type = 0;
-#else
+#elif !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
+ defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_HAS_WIDE)
static int sqlite3_os_type = 0;
#endif
@@ -31321,7 +31690,8 @@ static struct win_syscall {
#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
-#if defined(SQLITE_WIN32_HAS_ANSI)
+#if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \
+ SQLITE_WIN32_GETVERSIONEX
{ "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
#else
{ "GetVersionExA", (SYSCALL)0, 0 },
@@ -31330,10 +31700,20 @@ static struct win_syscall {
#define osGetVersionExA ((BOOL(WINAPI*)( \
LPOSVERSIONINFOA))aSyscall[34].pCurrent)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+ defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX
+ { "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
+#else
+ { "GetVersionExW", (SYSCALL)0, 0 },
+#endif
+
+#define osGetVersionExW ((BOOL(WINAPI*)( \
+ LPOSVERSIONINFOW))aSyscall[35].pCurrent)
+
{ "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
- SIZE_T))aSyscall[35].pCurrent)
+ SIZE_T))aSyscall[36].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapCreate", (SYSCALL)HeapCreate, 0 },
@@ -31342,7 +31722,7 @@ static struct win_syscall {
#endif
#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
- SIZE_T))aSyscall[36].pCurrent)
+ SIZE_T))aSyscall[37].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
@@ -31350,21 +31730,21 @@ static struct win_syscall {
{ "HeapDestroy", (SYSCALL)0, 0 },
#endif
-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent)
{ "HeapFree", (SYSCALL)HeapFree, 0 },
-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent)
{ "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
- SIZE_T))aSyscall[39].pCurrent)
+ SIZE_T))aSyscall[40].pCurrent)
{ "HeapSize", (SYSCALL)HeapSize, 0 },
#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
- LPCVOID))aSyscall[40].pCurrent)
+ LPCVOID))aSyscall[41].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapValidate", (SYSCALL)HeapValidate, 0 },
@@ -31373,7 +31753,15 @@ static struct win_syscall {
#endif
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
- LPCVOID))aSyscall[41].pCurrent)
+ LPCVOID))aSyscall[42].pCurrent)
+
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+ { "HeapCompact", (SYSCALL)HeapCompact, 0 },
+#else
+ { "HeapCompact", (SYSCALL)0, 0 },
+#endif
+
+#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[43].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
@@ -31381,7 +31769,7 @@ static struct win_syscall {
{ "LoadLibraryA", (SYSCALL)0, 0 },
#endif
-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
+#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent)
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
!defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -31390,7 +31778,7 @@ static struct win_syscall {
{ "LoadLibraryW", (SYSCALL)0, 0 },
#endif
-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent)
#if !SQLITE_OS_WINRT
{ "LocalFree", (SYSCALL)LocalFree, 0 },
@@ -31398,7 +31786,7 @@ static struct win_syscall {
{ "LocalFree", (SYSCALL)0, 0 },
#endif
-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
{ "LockFile", (SYSCALL)LockFile, 0 },
@@ -31408,7 +31796,7 @@ static struct win_syscall {
#ifndef osLockFile
#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- DWORD))aSyscall[45].pCurrent)
+ DWORD))aSyscall[47].pCurrent)
#endif
#if !SQLITE_OS_WINCE
@@ -31419,7 +31807,7 @@ static struct win_syscall {
#ifndef osLockFileEx
#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
- LPOVERLAPPED))aSyscall[46].pCurrent)
+ LPOVERLAPPED))aSyscall[48].pCurrent)
#endif
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
@@ -31429,26 +31817,26 @@ static struct win_syscall {
#endif
#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- SIZE_T))aSyscall[47].pCurrent)
+ SIZE_T))aSyscall[49].pCurrent)
{ "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
- int))aSyscall[48].pCurrent)
+ int))aSyscall[50].pCurrent)
{ "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
- LARGE_INTEGER*))aSyscall[49].pCurrent)
+ LARGE_INTEGER*))aSyscall[51].pCurrent)
{ "ReadFile", (SYSCALL)ReadFile, 0 },
#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
- LPOVERLAPPED))aSyscall[50].pCurrent)
+ LPOVERLAPPED))aSyscall[52].pCurrent)
{ "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent)
#if !SQLITE_OS_WINRT
{ "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
@@ -31457,7 +31845,7 @@ static struct win_syscall {
#endif
#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
- DWORD))aSyscall[52].pCurrent)
+ DWORD))aSyscall[54].pCurrent)
#if !SQLITE_OS_WINRT
{ "Sleep", (SYSCALL)Sleep, 0 },
@@ -31465,12 +31853,12 @@ static struct win_syscall {
{ "Sleep", (SYSCALL)0, 0 },
#endif
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent)
{ "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
- LPFILETIME))aSyscall[54].pCurrent)
+ LPFILETIME))aSyscall[56].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
{ "UnlockFile", (SYSCALL)UnlockFile, 0 },
@@ -31480,7 +31868,7 @@ static struct win_syscall {
#ifndef osUnlockFile
#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- DWORD))aSyscall[55].pCurrent)
+ DWORD))aSyscall[57].pCurrent)
#endif
#if !SQLITE_OS_WINCE
@@ -31490,7 +31878,7 @@ static struct win_syscall {
#endif
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- LPOVERLAPPED))aSyscall[56].pCurrent)
+ LPOVERLAPPED))aSyscall[58].pCurrent)
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
@@ -31498,17 +31886,17 @@ static struct win_syscall {
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
#endif
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent)
{ "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
- LPCSTR,LPBOOL))aSyscall[58].pCurrent)
+ LPCSTR,LPBOOL))aSyscall[60].pCurrent)
{ "WriteFile", (SYSCALL)WriteFile, 0 },
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
- LPOVERLAPPED))aSyscall[59].pCurrent)
+ LPOVERLAPPED))aSyscall[61].pCurrent)
#if SQLITE_OS_WINRT
{ "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
@@ -31517,7 +31905,7 @@ static struct win_syscall {
#endif
#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
- DWORD,DWORD))aSyscall[60].pCurrent)
+ DWORD,DWORD))aSyscall[62].pCurrent)
#if !SQLITE_OS_WINRT
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
@@ -31526,7 +31914,7 @@ static struct win_syscall {
#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
- DWORD))aSyscall[61].pCurrent)
+ DWORD))aSyscall[63].pCurrent)
#if SQLITE_OS_WINRT
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
@@ -31535,7 +31923,7 @@ static struct win_syscall {
#endif
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
- BOOL))aSyscall[62].pCurrent)
+ BOOL))aSyscall[64].pCurrent)
#if SQLITE_OS_WINRT
{ "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
@@ -31544,7 +31932,7 @@ static struct win_syscall {
#endif
#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
- PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
+ PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
#if SQLITE_OS_WINRT
{ "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
@@ -31553,7 +31941,7 @@ static struct win_syscall {
#endif
#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
- FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
+ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
{ "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
@@ -31562,7 +31950,7 @@ static struct win_syscall {
#endif
#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
- SIZE_T))aSyscall[65].pCurrent)
+ SIZE_T))aSyscall[67].pCurrent)
#if SQLITE_OS_WINRT
{ "CreateFile2", (SYSCALL)CreateFile2, 0 },
@@ -31571,7 +31959,7 @@ static struct win_syscall {
#endif
#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
- LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
+ LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
@@ -31580,7 +31968,7 @@ static struct win_syscall {
#endif
#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
- DWORD))aSyscall[67].pCurrent)
+ DWORD))aSyscall[69].pCurrent)
#if SQLITE_OS_WINRT
{ "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
@@ -31588,7 +31976,7 @@ static struct win_syscall {
{ "GetTickCount64", (SYSCALL)0, 0 },
#endif
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent)
#if SQLITE_OS_WINRT
{ "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
@@ -31597,7 +31985,7 @@ static struct win_syscall {
#endif
#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
- LPSYSTEM_INFO))aSyscall[69].pCurrent)
+ LPSYSTEM_INFO))aSyscall[71].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
@@ -31605,7 +31993,7 @@ static struct win_syscall {
{ "OutputDebugStringA", (SYSCALL)0, 0 },
#endif
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent)
#if defined(SQLITE_WIN32_HAS_WIDE)
{ "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
@@ -31613,11 +32001,11 @@ static struct win_syscall {
{ "OutputDebugStringW", (SYSCALL)0, 0 },
#endif
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent)
{ "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
{ "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
@@ -31626,7 +32014,7 @@ static struct win_syscall {
#endif
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
- LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
+ LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
}; /* End of the overrideable system calls */
@@ -31713,6 +32101,94 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
return 0;
}
+#ifdef SQLITE_WIN32_MALLOC
+/*
+** If a Win32 native heap has been configured, this function will attempt to
+** compact it. Upon success, SQLITE_OK will be returned. Upon failure, one
+** of SQLITE_NOMEM, SQLITE_ERROR, or SQLITE_NOTFOUND will be returned. The
+** "pnLargest" argument, if non-zero, will be used to return the size of the
+** largest committed free block in the heap, in bytes.
+*/
+SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
+ int rc = SQLITE_OK;
+ UINT nLargest = 0;
+ HANDLE hHeap;
+
+ winMemAssertMagic();
+ hHeap = winMemGetHeap();
+ assert( hHeap!=0 );
+ assert( hHeap!=INVALID_HANDLE_VALUE );
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
+ assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+#endif
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+ if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){
+ DWORD lastErrno = osGetLastError();
+ if( lastErrno==NO_ERROR ){
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapCompact (no space), heap=%p",
+ (void*)hHeap);
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlite3_log(SQLITE_ERROR, "failed to HeapCompact (%lu), heap=%p",
+ osGetLastError(), (void*)hHeap);
+ rc = SQLITE_ERROR;
+ }
+ }
+#else
+ sqlite3_log(SQLITE_NOTFOUND, "failed to HeapCompact, heap=%p",
+ (void*)hHeap);
+ rc = SQLITE_NOTFOUND;
+#endif
+ if( pnLargest ) *pnLargest = nLargest;
+ return rc;
+}
+
+/*
+** If a Win32 native heap has been configured, this function will attempt to
+** destroy and recreate it. If the Win32 native heap is not isolated and/or
+** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will
+** be returned and no changes will be made to the Win32 native heap.
+*/
+SQLITE_API int sqlite3_win32_reset_heap(){
+ int rc;
+ MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
+ MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
+ MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
+ MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
+ sqlite3_mutex_enter(pMaster);
+ sqlite3_mutex_enter(pMem);
+ winMemAssertMagic();
+ if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
+ /*
+ ** At this point, there should be no outstanding memory allocations on
+ ** the heap. Also, since both the master and memsys locks are currently
+ ** being held by us, no other function (i.e. from another thread) should
+ ** be able to even access the heap. Attempt to destroy and recreate our
+ ** isolated Win32 native heap now.
+ */
+ assert( winMemGetHeap()!=NULL );
+ assert( winMemGetOwned() );
+ assert( sqlite3_memory_used()==0 );
+ winMemShutdown(winMemGetDataPtr());
+ assert( winMemGetHeap()==NULL );
+ assert( !winMemGetOwned() );
+ assert( sqlite3_memory_used()==0 );
+ rc = winMemInit(winMemGetDataPtr());
+ assert( rc!=SQLITE_OK || winMemGetHeap()!=NULL );
+ assert( rc!=SQLITE_OK || winMemGetOwned() );
+ assert( rc!=SQLITE_OK || sqlite3_memory_used()==0 );
+ }else{
+ /*
+ ** The Win32 native heap cannot be modified because it may be in use.
+ */
+ rc = SQLITE_BUSY;
+ }
+ sqlite3_mutex_leave(pMem);
+ sqlite3_mutex_leave(pMaster);
+ return rc;
+}
+#endif /* SQLITE_WIN32_MALLOC */
+
/*
** This function outputs the specified (ANSI) string to the Win32 debugger
** (if available).
@@ -31782,16 +32258,25 @@ SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
*/
-#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
-# define isNT() (1)
+
+#if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX
+# define osIsNT() (1)
+#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
+# define osIsNT() (1)
#elif !defined(SQLITE_WIN32_HAS_WIDE)
-# define isNT() (0)
+# define osIsNT() (0)
#else
- static int isNT(void){
+ static int osIsNT(void){
if( sqlite3_os_type==0 ){
+#if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WIN8
+ OSVERSIONINFOW sInfo;
+ sInfo.dwOSVersionInfoSize = sizeof(sInfo);
+ osGetVersionExW(&sInfo);
+#else
OSVERSIONINFOA sInfo;
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
osGetVersionExA(&sInfo);
+#endif
sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
}
return sqlite3_os_type==2;
@@ -31811,12 +32296,12 @@ static void *winMemMalloc(int nBytes){
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+ assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
#endif
assert( nBytes>=0 );
p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
if( !p ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p",
nBytes, osGetLastError(), (void*)hHeap);
}
return p;
@@ -31833,11 +32318,11 @@ static void winMemFree(void *pPrior){
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+ assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p",
pPrior, osGetLastError(), (void*)hHeap);
}
}
@@ -31854,7 +32339,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
+ assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
#endif
assert( nBytes>=0 );
if( !pPrior ){
@@ -31863,7 +32348,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){
p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
}
if( !p ){
- sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
+ sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p",
pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
(void*)hHeap);
}
@@ -31882,12 +32367,12 @@ static int winMemSize(void *p){
assert( hHeap!=0 );
assert( hHeap!=INVALID_HANDLE_VALUE );
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
- assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
+ assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) );
#endif
if( !p ) return 0;
n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
if( n==(SIZE_T)-1 ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p",
p, osGetLastError(), (void*)hHeap);
return 0;
}
@@ -31908,18 +32393,25 @@ static int winMemInit(void *pAppData){
winMemData *pWinMemData = (winMemData *)pAppData;
if( !pWinMemData ) return SQLITE_ERROR;
- assert( pWinMemData->magic==WINMEM_MAGIC );
+ assert( pWinMemData->magic1==WINMEM_MAGIC1 );
+ assert( pWinMemData->magic2==WINMEM_MAGIC2 );
#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
if( !pWinMemData->hHeap ){
+ DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE;
+ DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap;
+ if( dwMaximumSize==0 ){
+ dwMaximumSize = SQLITE_WIN32_HEAP_MAX_SIZE;
+ }else if( dwInitialSize>dwMaximumSize ){
+ dwInitialSize = dwMaximumSize;
+ }
pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
- SQLITE_WIN32_HEAP_INIT_SIZE,
- SQLITE_WIN32_HEAP_MAX_SIZE);
+ dwInitialSize, dwMaximumSize);
if( !pWinMemData->hHeap ){
sqlite3_log(SQLITE_NOMEM,
- "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
- osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
- SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
+ "failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu",
+ osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize,
+ dwMaximumSize);
return SQLITE_NOMEM;
}
pWinMemData->bOwned = TRUE;
@@ -31929,7 +32421,7 @@ static int winMemInit(void *pAppData){
pWinMemData->hHeap = osGetProcessHeap();
if( !pWinMemData->hHeap ){
sqlite3_log(SQLITE_NOMEM,
- "failed to GetProcessHeap (%d)", osGetLastError());
+ "failed to GetProcessHeap (%lu)", osGetLastError());
return SQLITE_NOMEM;
}
pWinMemData->bOwned = FALSE;
@@ -31950,6 +32442,9 @@ static void winMemShutdown(void *pAppData){
winMemData *pWinMemData = (winMemData *)pAppData;
if( !pWinMemData ) return;
+ assert( pWinMemData->magic1==WINMEM_MAGIC1 );
+ assert( pWinMemData->magic2==WINMEM_MAGIC2 );
+
if( pWinMemData->hHeap ){
assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
@@ -31957,7 +32452,7 @@ static void winMemShutdown(void *pAppData){
#endif
if( pWinMemData->bOwned ){
if( !osHeapDestroy(pWinMemData->hHeap) ){
- sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
+ sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p",
osGetLastError(), (void*)pWinMemData->hHeap);
}
pWinMemData->bOwned = FALSE;
@@ -31998,7 +32493,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
**
** Space to hold the returned string is obtained from malloc.
*/
-static LPWSTR utf8ToUnicode(const char *zFilename){
+static LPWSTR winUtf8ToUnicode(const char *zFilename){
int nChar;
LPWSTR zWideFilename;
@@ -32023,7 +32518,7 @@ static LPWSTR utf8ToUnicode(const char *zFilename){
** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is
** obtained from sqlite3_malloc().
*/
-static char *unicodeToUtf8(LPCWSTR zWideFilename){
+static char *winUnicodeToUtf8(LPCWSTR zWideFilename){
int nByte;
char *zFilename;
@@ -32051,7 +32546,7 @@ static char *unicodeToUtf8(LPCWSTR zWideFilename){
** Space to hold the returned string is obtained
** from sqlite3_malloc.
*/
-static LPWSTR mbcsToUnicode(const char *zFilename){
+static LPWSTR winMbcsToUnicode(const char *zFilename){
int nByte;
LPWSTR zMbcsFilename;
int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
@@ -32081,7 +32576,7 @@ static LPWSTR mbcsToUnicode(const char *zFilename){
** Space to hold the returned string is obtained from
** sqlite3_malloc().
*/
-static char *unicodeToMbcs(LPCWSTR zWideFilename){
+static char *winUnicodeToMbcs(LPCWSTR zWideFilename){
int nByte;
char *zFilename;
int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
@@ -32111,11 +32606,11 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
char *zFilenameUtf8;
LPWSTR zTmpWide;
- zTmpWide = mbcsToUnicode(zFilename);
+ zTmpWide = winMbcsToUnicode(zFilename);
if( zTmpWide==0 ){
return 0;
}
- zFilenameUtf8 = unicodeToUtf8(zTmpWide);
+ zFilenameUtf8 = winUnicodeToUtf8(zTmpWide);
sqlite3_free(zTmpWide);
return zFilenameUtf8;
}
@@ -32128,11 +32623,11 @@ SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
char *zFilenameMbcs;
LPWSTR zTmpWide;
- zTmpWide = utf8ToUnicode(zFilename);
+ zTmpWide = winUtf8ToUnicode(zFilename);
if( zTmpWide==0 ){
return 0;
}
- zFilenameMbcs = unicodeToMbcs(zTmpWide);
+ zFilenameMbcs = winUnicodeToMbcs(zTmpWide);
sqlite3_free(zTmpWide);
return zFilenameMbcs;
}
@@ -32162,7 +32657,7 @@ SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
if( ppDirectory ){
char *zValueUtf8 = 0;
if( zValue && zValue[0] ){
- zValueUtf8 = unicodeToUtf8(zValue);
+ zValueUtf8 = winUnicodeToUtf8(zValue);
if ( zValueUtf8==0 ){
return SQLITE_NOMEM;
}
@@ -32175,11 +32670,11 @@ SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
}
/*
-** The return value of getLastErrorMsg
+** The return value of winGetLastErrorMsg
** is zero if the error message fits in the buffer, or non-zero
** otherwise (if the message was truncated).
*/
-static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
+static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
/* FormatMessage returns 0 on failure. Otherwise it
** returns the number of TCHARs written to the output
** buffer, excluding the terminating null char.
@@ -32187,16 +32682,16 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
DWORD dwLen = 0;
char *zOut = 0;
- if( isNT() ){
+ if( osIsNT() ){
#if SQLITE_OS_WINRT
- WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */
+ WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1];
dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
lastErrno,
0,
zTempWide,
- MAX_PATH,
+ SQLITE_WIN32_MAX_ERRMSG_CHARS,
0);
#else
LPWSTR zTempWide = NULL;
@@ -32213,7 +32708,7 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
if( dwLen > 0 ){
/* allocate a buffer and convert to UTF8 */
sqlite3BeginBenignMalloc();
- zOut = unicodeToUtf8(zTempWide);
+ zOut = winUnicodeToUtf8(zTempWide);
sqlite3EndBenignMalloc();
#if !SQLITE_OS_WINRT
/* free the system buffer allocated by FormatMessage */
@@ -32281,7 +32776,7 @@ static int winLogErrorAtLine(
int i; /* Loop counter */
zMsg[0] = 0;
- getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
+ winGetLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
assert( errcode!=SQLITE_OK );
if( zPath==0 ) zPath = "";
for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
@@ -32306,17 +32801,17 @@ static int winLogErrorAtLine(
#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
#endif
-static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
-static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
+static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
+static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
/*
** If a ReadFile() or WriteFile() error occurs, invoke this routine
** to see if it should be retried. Return TRUE to retry. Return FALSE
** to give up with an error.
*/
-static int retryIoerr(int *pnRetry, DWORD *pError){
+static int winRetryIoerr(int *pnRetry, DWORD *pError){
DWORD e = osGetLastError();
- if( *pnRetry>=win32IoerrRetry ){
+ if( *pnRetry>=winIoerrRetry ){
if( pError ){
*pError = e;
}
@@ -32325,7 +32820,7 @@ static int retryIoerr(int *pnRetry, DWORD *pError){
if( e==ERROR_ACCESS_DENIED ||
e==ERROR_LOCK_VIOLATION ||
e==ERROR_SHARING_VIOLATION ){
- sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry));
+ sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
++*pnRetry;
return 1;
}
@@ -32338,11 +32833,11 @@ static int retryIoerr(int *pnRetry, DWORD *pError){
/*
** Log a I/O error retry episode.
*/
-static void logIoerr(int nRetry){
+static void winLogIoerr(int nRetry){
if( nRetry ){
sqlite3_log(SQLITE_IOERR,
"delayed %dms for lock/sharing conflict",
- win32IoerrRetryDelay*nRetry*(nRetry+1)/2
+ winIoerrRetryDelay*nRetry*(nRetry+1)/2
);
}
}
@@ -32407,7 +32902,7 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
BOOL bLogged = FALSE;
BOOL bInit = TRUE;
- zName = utf8ToUnicode(zFilename);
+ zName = winUtf8ToUnicode(zFilename);
if( zName==0 ){
/* out of memory */
return SQLITE_IOERR_NOMEM;
@@ -32427,10 +32922,9 @@ static int winceCreateLock(const char *zFilename, winFile *pFile){
pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
if (!pFile->hMutex){
pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR, pFile->lastErrno,
- "winceCreateLock1", zFilename);
sqlite3_free(zName);
- return SQLITE_IOERR;
+ return winLogError(SQLITE_IOERR, pFile->lastErrno,
+ "winceCreateLock1", zFilename);
}
/* Acquire the mutex before continuing */
@@ -32680,7 +33174,7 @@ static BOOL winLockFile(
return winceLockFile(phFile, offsetLow, offsetHigh,
numBytesLow, numBytesHigh);
#else
- if( isNT() ){
+ if( osIsNT() ){
OVERLAPPED ovlp;
memset(&ovlp, 0, sizeof(OVERLAPPED));
ovlp.Offset = offsetLow;
@@ -32711,7 +33205,7 @@ static BOOL winUnlockFile(
return winceUnlockFile(phFile, offsetLow, offsetHigh,
numBytesLow, numBytesHigh);
#else
- if( isNT() ){
+ if( osIsNT() ){
OVERLAPPED ovlp;
memset(&ovlp, 0, sizeof(OVERLAPPED));
ovlp.Offset = offsetLow;
@@ -32741,7 +33235,7 @@ static BOOL winUnlockFile(
** argument to offset iOffset within the file. If successful, return 0.
** Otherwise, set pFile->lastErrno and return non-zero.
*/
-static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
+static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
#if !SQLITE_OS_WINRT
LONG upperBits; /* Most sig. 32 bits of new offset */
LONG lowerBits; /* Least sig. 32 bits of new offset */
@@ -32766,7 +33260,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
&& ((lastErrno = osGetLastError())!=NO_ERROR)) ){
pFile->lastErrno = lastErrno;
winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "seekWinFile", pFile->zPath);
+ "winSeekFile", pFile->zPath);
OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
return 1;
}
@@ -32787,7 +33281,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
if(!bRet){
pFile->lastErrno = osGetLastError();
winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "seekWinFile", pFile->zPath);
+ "winSeekFile", pFile->zPath);
OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
return 1;
}
@@ -32798,7 +33292,8 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
}
#if SQLITE_MAX_MMAP_SIZE>0
-/* Forward references to VFS methods */
+/* Forward references to VFS helper methods used for memory mapped files */
+static int winMapfile(winFile*, sqlite3_int64);
static int winUnmapfile(winFile*);
#endif
@@ -32825,8 +33320,7 @@ static int winClose(sqlite3_file *id){
OSTRACE(("CLOSE file=%p\n", pFile->h));
#if SQLITE_MAX_MMAP_SIZE>0
- rc = winUnmapfile(pFile);
- if( rc!=SQLITE_OK ) return rc;
+ winUnmapfile(pFile);
#endif
do{
@@ -32902,7 +33396,7 @@ static int winRead(
#endif
#if SQLITE_OS_WINCE
- if( seekWinFile(pFile, offset) ){
+ if( winSeekFile(pFile, offset) ){
OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
return SQLITE_FULL;
}
@@ -32915,13 +33409,13 @@ static int winRead(
osGetLastError()!=ERROR_HANDLE_EOF ){
#endif
DWORD lastErrno;
- if( retryIoerr(&nRetry, &lastErrno) ) continue;
+ if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
pFile->lastErrno = lastErrno;
OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
- "winRead", pFile->zPath);
+ "winRead", pFile->zPath);
}
- logIoerr(nRetry);
+ winLogIoerr(nRetry);
if( nRead<(DWORD)amt ){
/* Unread parts of the buffer must be zero-filled */
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
@@ -32974,7 +33468,7 @@ static int winWrite(
#endif
#if SQLITE_OS_WINCE
- rc = seekWinFile(pFile, offset);
+ rc = winSeekFile(pFile, offset);
if( rc==0 ){
#else
{
@@ -32999,7 +33493,7 @@ static int winWrite(
#else
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
#endif
- if( retryIoerr(&nRetry, &lastErrno) ) continue;
+ if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
break;
}
assert( nWrite==0 || nWrite<=(DWORD)nRem );
@@ -33025,13 +33519,14 @@ static int winWrite(
if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
|| ( pFile->lastErrno==ERROR_DISK_FULL )){
OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
- return SQLITE_FULL;
+ return winLogError(SQLITE_FULL, pFile->lastErrno,
+ "winWrite1", pFile->zPath);
}
OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
- "winWrite", pFile->zPath);
+ "winWrite2", pFile->zPath);
}else{
- logIoerr(nRetry);
+ winLogIoerr(nRetry);
}
OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
@@ -33060,7 +33555,7 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
}
/* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
- if( seekWinFile(pFile, nByte) ){
+ if( winSeekFile(pFile, nByte) ){
rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
"winTruncate1", pFile->zPath);
}else if( 0==osSetEndOfFile(pFile->h) &&
@@ -33141,6 +33636,7 @@ static int winSync(sqlite3_file *id, int flags){
** no-op
*/
#ifdef SQLITE_NO_SYNC
+ OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
#else
rc = osFlushFileBuffers(pFile->h);
@@ -33152,7 +33648,7 @@ static int winSync(sqlite3_file *id, int flags){
pFile->lastErrno = osGetLastError();
OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
- "winSync", pFile->zPath);
+ "winSync", pFile->zPath);
}
#endif
}
@@ -33193,7 +33689,7 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
&& ((lastErrno = osGetLastError())!=NO_ERROR) ){
pFile->lastErrno = lastErrno;
rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
- "winFileSize", pFile->zPath);
+ "winFileSize", pFile->zPath);
}
}
#endif
@@ -33238,10 +33734,10 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
** Different API routines are called depending on whether or not this
** is Win9x or WinNT.
*/
-static int getReadLock(winFile *pFile){
+static int winGetReadLock(winFile *pFile){
int res;
OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
- if( isNT() ){
+ if( osIsNT() ){
#if SQLITE_OS_WINCE
/*
** NOTE: Windows CE is handled differently here due its lack of the Win32
@@ -33273,11 +33769,11 @@ static int getReadLock(winFile *pFile){
/*
** Undo a readlock
*/
-static int unlockReadLock(winFile *pFile){
+static int winUnlockReadLock(winFile *pFile){
int res;
DWORD lastErrno;
OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
- if( isNT() ){
+ if( osIsNT() ){
res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
}
#ifdef SQLITE_WIN32_HAS_ANSI
@@ -33288,7 +33784,7 @@ static int unlockReadLock(winFile *pFile){
if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
pFile->lastErrno = lastErrno;
winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
- "unlockReadLock", pFile->zPath);
+ "winUnlockReadLock", pFile->zPath);
}
OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
return res;
@@ -33379,7 +33875,7 @@ static int winLock(sqlite3_file *id, int locktype){
*/
if( locktype==SHARED_LOCK && res ){
assert( pFile->locktype==NO_LOCK );
- res = getReadLock(pFile);
+ res = winGetReadLock(pFile);
if( res ){
newLocktype = SHARED_LOCK;
}else{
@@ -33410,14 +33906,14 @@ static int winLock(sqlite3_file *id, int locktype){
*/
if( locktype==EXCLUSIVE_LOCK && res ){
assert( pFile->locktype>=SHARED_LOCK );
- res = unlockReadLock(pFile);
+ res = winUnlockReadLock(pFile);
res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
SHARED_SIZE, 0);
if( res ){
newLocktype = EXCLUSIVE_LOCK;
}else{
lastErrno = osGetLastError();
- getReadLock(pFile);
+ winGetReadLock(pFile);
}
}
@@ -33434,10 +33930,10 @@ static int winLock(sqlite3_file *id, int locktype){
if( res ){
rc = SQLITE_OK;
}else{
- OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
- pFile->h, locktype, newLocktype));
pFile->lastErrno = lastErrno;
rc = SQLITE_BUSY;
+ OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
+ pFile->h, locktype, newLocktype));
}
pFile->locktype = (u8)newLocktype;
OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
@@ -33497,18 +33993,18 @@ static int winUnlock(sqlite3_file *id, int locktype){
type = pFile->locktype;
if( type>=EXCLUSIVE_LOCK ){
winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
+ if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
/* This should never happen. We should always be able to
** reacquire the read lock */
rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
- "winUnlock", pFile->zPath);
+ "winUnlock", pFile->zPath);
}
}
if( type>=RESERVED_LOCK ){
winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
}
if( locktype==NO_LOCK && type>=SHARED_LOCK ){
- unlockReadLock(pFile);
+ winUnlockReadLock(pFile);
}
if( type>=PENDING_LOCK ){
winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
@@ -33535,8 +34031,10 @@ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
}
}
-/* Forward declaration */
-static int getTempname(int nBuf, char *zBuf);
+/* Forward references to VFS helper methods used for temporary files */
+static int winGetTempname(sqlite3_vfs *, char **);
+static int winIsDir(const void *);
+static BOOL winIsDriveLetterAndColon(const char *);
/*
** Control and query of the open file handle.
@@ -33596,37 +34094,44 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
case SQLITE_FCNTL_WIN32_AV_RETRY: {
int *a = (int*)pArg;
if( a[0]>0 ){
- win32IoerrRetry = a[0];
+ winIoerrRetry = a[0];
}else{
- a[0] = win32IoerrRetry;
+ a[0] = winIoerrRetry;
}
if( a[1]>0 ){
- win32IoerrRetryDelay = a[1];
+ winIoerrRetryDelay = a[1];
}else{
- a[1] = win32IoerrRetryDelay;
+ a[1] = winIoerrRetryDelay;
}
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
}
case SQLITE_FCNTL_TEMPFILENAME: {
- char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
- if( zTFile ){
- getTempname(pFile->pVfs->mxPathname, zTFile);
+ char *zTFile = 0;
+ int rc = winGetTempname(pFile->pVfs, &zTFile);
+ if( rc==SQLITE_OK ){
*(char**)pArg = zTFile;
}
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
+ OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
+ return rc;
}
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
+ int rc = SQLITE_OK;
if( newLimit>sqlite3GlobalConfig.mxMmap ){
newLimit = sqlite3GlobalConfig.mxMmap;
}
*(i64*)pArg = pFile->mmapSizeMax;
- if( newLimit>=0 ) pFile->mmapSizeMax = newLimit;
- OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
- return SQLITE_OK;
+ if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
+ pFile->mmapSizeMax = newLimit;
+ if( pFile->mmapSize>0 ){
+ winUnmapfile(pFile);
+ rc = winMapfile(pFile, -1);
+ }
+ }
+ OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
+ return rc;
}
#endif
}
@@ -33831,7 +34336,6 @@ static int winDelete(sqlite3_vfs *,const char*,int);
static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
winShmNode **pp;
winShmNode *p;
- BOOL bRc;
assert( winShmMutexHeld() );
OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
osGetCurrentProcessId(), deleteFlag));
@@ -33839,14 +34343,16 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
while( (p = *pp)!=0 ){
if( p->nRef==0 ){
int i;
- if( p->mutex ) sqlite3_mutex_free(p->mutex);
+ if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
for(i=0; i<p->nRegion; i++){
- bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
+ BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
+ UNUSED_VARIABLE_VALUE(bRc);
bRc = osCloseHandle(p->aRegion[i].hMap);
OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
+ UNUSED_VARIABLE_VALUE(bRc);
}
if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
SimulateIOErrorBenign(1);
@@ -33941,7 +34447,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
if( rc!=SQLITE_OK ){
rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
- "winOpenShm", pDbFd->zPath);
+ "winOpenShm", pDbFd->zPath);
}
}
if( rc==SQLITE_OK ){
@@ -34201,7 +34707,7 @@ static int winShmMap(
rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
if( rc!=SQLITE_OK ){
rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap1", pDbFd->zPath);
+ "winShmMap1", pDbFd->zPath);
goto shmpage_out;
}
@@ -34216,7 +34722,7 @@ static int winShmMap(
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
if( rc!=SQLITE_OK ){
rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap2", pDbFd->zPath);
+ "winShmMap2", pDbFd->zPath);
goto shmpage_out;
}
}
@@ -34270,7 +34776,7 @@ static int winShmMap(
if( !pMap ){
pShmNode->lastErrno = osGetLastError();
rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
- "winShmMap3", pDbFd->zPath);
+ "winShmMap3", pDbFd->zPath);
if( hMap ) osCloseHandle(hMap);
goto shmpage_out;
}
@@ -34318,7 +34824,7 @@ static int winUnmapfile(winFile *pFile){
"rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
pFile->pMapRegion));
return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
- "winUnmap1", pFile->zPath);
+ "winUnmapfile1", pFile->zPath);
}
pFile->pMapRegion = 0;
pFile->mmapSize = 0;
@@ -34330,7 +34836,7 @@ static int winUnmapfile(winFile *pFile){
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
osGetCurrentProcessId(), pFile, pFile->hMap));
return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
- "winUnmap2", pFile->zPath);
+ "winUnmapfile2", pFile->zPath);
}
pFile->hMap = NULL;
}
@@ -34405,27 +34911,28 @@ static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
if( pFd->hMap==NULL ){
pFd->lastErrno = osGetLastError();
rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
- "winMapfile", pFd->zPath);
+ "winMapfile1", pFd->zPath);
/* Log the error, but continue normal operation using xRead/xWrite */
- OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
- osGetCurrentProcessId(), pFd));
+ OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=%s\n",
+ osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
return SQLITE_OK;
}
assert( (nMap % winSysInfo.dwPageSize)==0 );
+ assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
#if SQLITE_OS_WINRT
- pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, nMap);
+ pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap);
#else
- assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
#endif
if( pNew==NULL ){
osCloseHandle(pFd->hMap);
pFd->hMap = NULL;
pFd->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
- "winMapfile", pFd->zPath);
- OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=SQLITE_IOERR_MMAP\n",
- osGetCurrentProcessId(), pFd));
+ rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
+ "winMapfile2", pFd->zPath);
+ /* Log the error, but continue normal operation using xRead/xWrite */
+ OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=%s\n",
+ osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
return SQLITE_OK;
}
pFd->pMapRegion = pNew;
@@ -34564,16 +35071,37 @@ static const sqlite3_io_methods winIoMethod = {
** sqlite3_vfs object.
*/
+#if defined(__CYGWIN__)
+/*
+** Convert a filename from whatever the underlying operating system
+** supports for filenames into UTF-8. Space to hold the result is
+** obtained from malloc and must be freed by the calling function.
+*/
+static char *winConvertToUtf8Filename(const void *zFilename){
+ char *zConverted = 0;
+ if( osIsNT() ){
+ zConverted = winUnicodeToUtf8(zFilename);
+ }
+#ifdef SQLITE_WIN32_HAS_ANSI
+ else{
+ zConverted = sqlite3_win32_mbcs_to_utf8(zFilename);
+ }
+#endif
+ /* caller will handle out of memory */
+ return zConverted;
+}
+#endif
+
/*
** Convert a UTF-8 filename into whatever form the underlying
** operating system wants filenames in. Space to hold the result
** is obtained from malloc and must be freed by the calling
** function.
*/
-static void *convertUtf8Filename(const char *zFilename){
+static void *winConvertFromUtf8Filename(const char *zFilename){
void *zConverted = 0;
- if( isNT() ){
- zConverted = utf8ToUnicode(zFilename);
+ if( osIsNT() ){
+ zConverted = winUtf8ToUnicode(zFilename);
}
#ifdef SQLITE_WIN32_HAS_ANSI
else{
@@ -34585,17 +35113,39 @@ static void *convertUtf8Filename(const char *zFilename){
}
/*
-** Create a temporary file name in zBuf. zBuf must be big enough to
-** hold at pVfs->mxPathname characters.
+** This function returns non-zero if the specified UTF-8 string buffer
+** ends with a directory separator character or one was successfully
+** added to it.
+*/
+static int winMakeEndInDirSep(int nBuf, char *zBuf){
+ if( zBuf ){
+ int nLen = sqlite3Strlen30(zBuf);
+ if( nLen>0 ){
+ if( winIsDirSep(zBuf[nLen-1]) ){
+ return 1;
+ }else if( nLen+1<nBuf ){
+ zBuf[nLen] = winGetDirSep();
+ zBuf[nLen+1] = '\0';
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Create a temporary file name and store the resulting pointer into pzBuf.
+** The pointer returned in pzBuf must be freed via sqlite3_free().
*/
-static int getTempname(int nBuf, char *zBuf){
+static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
static char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
size_t i, j;
- int nTempPath;
- char zTempPath[MAX_PATH+2];
+ int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX);
+ int nMax, nBuf, nDir, nLen;
+ char *zBuf;
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
@@ -34603,21 +35153,140 @@ static int getTempname(int nBuf, char *zBuf){
*/
SimulateIOError( return SQLITE_IOERR );
- memset(zTempPath, 0, MAX_PATH+2);
+ /* Allocate a temporary buffer to store the fully qualified file
+ ** name for the temporary file. If this fails, we cannot continue.
+ */
+ nMax = pVfs->mxPathname; nBuf = nMax + 2;
+ zBuf = sqlite3MallocZero( nBuf );
+ if( !zBuf ){
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+ return SQLITE_IOERR_NOMEM;
+ }
+ /* Figure out the effective temporary directory. First, check if one
+ ** has been explicitly set by the application; otherwise, use the one
+ ** configured by the operating system.
+ */
+ nDir = nMax - (nPre + 15);
+ assert( nDir>0 );
if( sqlite3_temp_directory ){
- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
+ int nDirLen = sqlite3Strlen30(sqlite3_temp_directory);
+ if( nDirLen>0 ){
+ if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){
+ nDirLen++;
+ }
+ if( nDirLen>nDir ){
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
+ return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0);
+ }
+ sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory);
+ }
}
-#if !SQLITE_OS_WINRT
- else if( isNT() ){
+#if defined(__CYGWIN__)
+ else{
+ static const char *azDirs[] = {
+ 0, /* getenv("SQLITE_TMPDIR") */
+ 0, /* getenv("TMPDIR") */
+ 0, /* getenv("TMP") */
+ 0, /* getenv("TEMP") */
+ 0, /* getenv("USERPROFILE") */
+ "/var/tmp",
+ "/usr/tmp",
+ "/tmp",
+ ".",
+ 0 /* List terminator */
+ };
+ unsigned int i;
+ const char *zDir = 0;
+
+ if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
+ if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
+ if( !azDirs[2] ) azDirs[2] = getenv("TMP");
+ if( !azDirs[3] ) azDirs[3] = getenv("TEMP");
+ if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE");
+ for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
+ void *zConverted;
+ if( zDir==0 ) continue;
+ /* If the path starts with a drive letter followed by the colon
+ ** character, assume it is already a native Win32 path; otherwise,
+ ** it must be converted to a native Win32 path via the Cygwin API
+ ** prior to using it.
+ */
+ if( winIsDriveLetterAndColon(zDir) ){
+ zConverted = winConvertFromUtf8Filename(zDir);
+ if( !zConverted ){
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( winIsDir(zConverted) ){
+ sqlite3_snprintf(nMax, zBuf, "%s", zDir);
+ sqlite3_free(zConverted);
+ break;
+ }
+ sqlite3_free(zConverted);
+ }else{
+ zConverted = sqlite3MallocZero( nMax+1 );
+ if( !zConverted ){
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( cygwin_conv_path(
+ osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
+ zConverted, nMax+1)<0 ){
+ sqlite3_free(zConverted);
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
+ return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
+ "winGetTempname2", zDir);
+ }
+ if( winIsDir(zConverted) ){
+ /* At this point, we know the candidate directory exists and should
+ ** be used. However, we may need to convert the string containing
+ ** its name into UTF-8 (i.e. if it is UTF-16 right now).
+ */
+ char *zUtf8 = winConvertToUtf8Filename(zConverted);
+ if( !zUtf8 ){
+ sqlite3_free(zConverted);
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+ return SQLITE_IOERR_NOMEM;
+ }
+ sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
+ sqlite3_free(zUtf8);
+ sqlite3_free(zConverted);
+ break;
+ }
+ sqlite3_free(zConverted);
+ }
+ }
+ }
+#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
+ else if( osIsNT() ){
char *zMulti;
- WCHAR zWidePath[MAX_PATH];
- osGetTempPathW(MAX_PATH-30, zWidePath);
- zMulti = unicodeToUtf8(zWidePath);
+ LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) );
+ if( !zWidePath ){
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( osGetTempPathW(nMax, zWidePath)==0 ){
+ sqlite3_free(zWidePath);
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
+ return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
+ "winGetTempname2", 0);
+ }
+ zMulti = winUnicodeToUtf8(zWidePath);
if( zMulti ){
- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
+ sqlite3_snprintf(nMax, zBuf, "%s", zMulti);
sqlite3_free(zMulti);
+ sqlite3_free(zWidePath);
}else{
+ sqlite3_free(zWidePath);
+ sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
}
@@ -34625,36 +35294,62 @@ static int getTempname(int nBuf, char *zBuf){
#ifdef SQLITE_WIN32_HAS_ANSI
else{
char *zUtf8;
- char zMbcsPath[MAX_PATH];
- osGetTempPathA(MAX_PATH-30, zMbcsPath);
+ char *zMbcsPath = sqlite3MallocZero( nMax );
+ if( !zMbcsPath ){
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( osGetTempPathA(nMax, zMbcsPath)==0 ){
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
+ return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
+ "winGetTempname3", 0);
+ }
zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
if( zUtf8 ){
- sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
+ sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
sqlite3_free(zUtf8);
}else{
+ sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
}
}
-#endif
-#endif
+#endif /* SQLITE_WIN32_HAS_ANSI */
+#endif /* !SQLITE_OS_WINRT */
- /* Check that the output buffer is large enough for the temporary file
- ** name. If it is not, return SQLITE_ERROR.
+ /*
+ ** Check to make sure the temporary directory ends with an appropriate
+ ** separator. If it does not and there is not enough space left to add
+ ** one, fail.
*/
- nTempPath = sqlite3Strlen30(zTempPath);
+ if( !winMakeEndInDirSep(nDir+1, zBuf) ){
+ sqlite3_free(zBuf);
+ OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
+ return winLogError(SQLITE_ERROR, 0, "winGetTempname4", 0);
+ }
- if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
+ /*
+ ** Check that the output buffer is large enough for the temporary file
+ ** name in the following format:
+ **
+ ** "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0"
+ **
+ ** If not, return SQLITE_ERROR. The number 17 is used here in order to
+ ** account for the space used by the 15 character random suffix and the
+ ** two trailing NUL characters. The final directory separator character
+ ** has already added if it was not already present.
+ */
+ nLen = sqlite3Strlen30(zBuf);
+ if( (nLen + nPre + 17) > nBuf ){
+ sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
- return SQLITE_ERROR;
+ return winLogError(SQLITE_ERROR, 0, "winGetTempname5", 0);
}
- for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){}
- zTempPath[i] = 0;
+ sqlite3_snprintf(nBuf-16-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX);
- sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ?
- "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX,
- zTempPath);
j = sqlite3Strlen30(zBuf);
sqlite3_randomness(15, &zBuf[j]);
for(i=0; i<15; i++, j++){
@@ -34662,6 +35357,7 @@ static int getTempname(int nBuf, char *zBuf){
}
zBuf[j] = 0;
zBuf[j+1] = 0;
+ *pzBuf = zBuf;
OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
return SQLITE_OK;
@@ -34677,13 +35373,13 @@ static int winIsDir(const void *zConverted){
int rc = 0;
DWORD lastErrno;
- if( isNT() ){
+ if( osIsNT() ){
int cnt = 0;
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
memset(&sAttrData, 0, sizeof(sAttrData));
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
GetFileExInfoStandard,
- &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
+ &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
if( !rc ){
return 0; /* Invalid name? */
}
@@ -34700,14 +35396,14 @@ static int winIsDir(const void *zConverted){
** Open a file.
*/
static int winOpen(
- sqlite3_vfs *pVfs, /* Not used */
+ sqlite3_vfs *pVfs, /* Used to get maximum path name length */
const char *zName, /* Name of the file (UTF-8) */
sqlite3_file *id, /* Write the SQLite file handle here */
int flags, /* Open mode flags */
int *pOutFlags /* Status return flags */
){
HANDLE h;
- DWORD lastErrno;
+ DWORD lastErrno = 0;
DWORD dwDesiredAccess;
DWORD dwShareMode;
DWORD dwCreationDisposition;
@@ -34723,7 +35419,7 @@ static int winOpen(
/* If argument zPath is a NULL pointer, this function is required to open
** a temporary file. Use this buffer to store the file name in.
*/
- char zTmpname[MAX_PATH+2]; /* Buffer used to create temp filename */
+ char *zTmpname = 0; /* For temporary filename, if necessary. */
int rc = SQLITE_OK; /* Function Return Code */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
@@ -34778,7 +35474,7 @@ static int winOpen(
pFile->h = INVALID_HANDLE_VALUE;
#if SQLITE_OS_WINRT
- if( !sqlite3_temp_directory ){
+ if( !zUtf8Name && !sqlite3_temp_directory ){
sqlite3_log(SQLITE_ERROR,
"sqlite3_temp_directory variable should be set for WinRT");
}
@@ -34788,9 +35484,8 @@ static int winOpen(
** temporary file name to use
*/
if( !zUtf8Name ){
- assert(isDelete && !isOpenJournal);
- memset(zTmpname, 0, MAX_PATH+2);
- rc = getTempname(MAX_PATH+2, zTmpname);
+ assert( isDelete && !isOpenJournal );
+ rc = winGetTempname(pVfs, &zTmpname);
if( rc!=SQLITE_OK ){
OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
return rc;
@@ -34803,17 +35498,19 @@ static int winOpen(
** sqlite3_uri_parameter().
*/
assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
- zUtf8Name[strlen(zUtf8Name)+1]==0 );
+ zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 );
/* Convert the filename to the system encoding. */
- zConverted = convertUtf8Filename(zUtf8Name);
+ zConverted = winConvertFromUtf8Filename(zUtf8Name);
if( zConverted==0 ){
+ sqlite3_free(zTmpname);
OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
return SQLITE_IOERR_NOMEM;
}
if( winIsDir(zConverted) ){
sqlite3_free(zConverted);
+ sqlite3_free(zTmpname);
OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
return SQLITE_CANTOPEN_ISDIR;
}
@@ -34860,7 +35557,7 @@ static int winOpen(
dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
#endif
- if( isNT() ){
+ if( osIsNT() ){
#if SQLITE_OS_WINRT
CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
@@ -34875,7 +35572,7 @@ static int winOpen(
dwShareMode,
dwCreationDisposition,
&extendedParameters))==INVALID_HANDLE_VALUE &&
- retryIoerr(&cnt, &lastErrno) ){
+ winRetryIoerr(&cnt, &lastErrno) ){
/* Noop */
}
#else
@@ -34885,7 +35582,7 @@ static int winOpen(
dwCreationDisposition,
dwFlagsAndAttributes,
NULL))==INVALID_HANDLE_VALUE &&
- retryIoerr(&cnt, &lastErrno) ){
+ winRetryIoerr(&cnt, &lastErrno) ){
/* Noop */
}
#endif
@@ -34898,12 +35595,12 @@ static int winOpen(
dwCreationDisposition,
dwFlagsAndAttributes,
NULL))==INVALID_HANDLE_VALUE &&
- retryIoerr(&cnt, &lastErrno) ){
+ winRetryIoerr(&cnt, &lastErrno) ){
/* Noop */
}
}
#endif
- logIoerr(cnt);
+ winLogIoerr(cnt);
OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
@@ -34912,6 +35609,7 @@ static int winOpen(
pFile->lastErrno = lastErrno;
winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
sqlite3_free(zConverted);
+ sqlite3_free(zTmpname);
if( isReadWrite && !isExclusive ){
return winOpen(pVfs, zName, id,
((flags|SQLITE_OPEN_READONLY) &
@@ -34940,6 +35638,7 @@ static int winOpen(
){
osCloseHandle(h);
sqlite3_free(zConverted);
+ sqlite3_free(zTmpname);
OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
return rc;
}
@@ -34951,6 +35650,7 @@ static int winOpen(
sqlite3_free(zConverted);
}
+ sqlite3_free(zTmpname);
pFile->pMethod = &winIoMethod;
pFile->pVfs = pVfs;
pFile->h = h;
@@ -34994,7 +35694,7 @@ static int winDelete(
int cnt = 0;
int rc;
DWORD attr;
- DWORD lastErrno;
+ DWORD lastErrno = 0;
void *zConverted;
UNUSED_PARAMETER(pVfs);
UNUSED_PARAMETER(syncDir);
@@ -35002,11 +35702,12 @@ static int winDelete(
SimulateIOError(return SQLITE_IOERR_DELETE);
OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
- zConverted = convertUtf8Filename(zFilename);
+ zConverted = winConvertFromUtf8Filename(zFilename);
if( zConverted==0 ){
+ OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
return SQLITE_IOERR_NOMEM;
}
- if( isNT() ){
+ if( osIsNT() ){
do {
#if SQLITE_OS_WINRT
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
@@ -35045,7 +35746,7 @@ static int winDelete(
rc = SQLITE_OK; /* Deleted OK. */
break;
}
- if ( !retryIoerr(&cnt, &lastErrno) ){
+ if ( !winRetryIoerr(&cnt, &lastErrno) ){
rc = SQLITE_ERROR; /* No more retries. */
break;
}
@@ -35073,7 +35774,7 @@ static int winDelete(
rc = SQLITE_OK; /* Deleted OK. */
break;
}
- if ( !retryIoerr(&cnt, &lastErrno) ){
+ if ( !winRetryIoerr(&cnt, &lastErrno) ){
rc = SQLITE_ERROR; /* No more retries. */
break;
}
@@ -35081,10 +35782,9 @@ static int winDelete(
}
#endif
if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
- rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
- "winDelete", zFilename);
+ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
}else{
- logIoerr(cnt);
+ winLogIoerr(cnt);
}
sqlite3_free(zConverted);
OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
@@ -35102,7 +35802,7 @@ static int winAccess(
){
DWORD attr;
int rc = 0;
- DWORD lastErrno;
+ DWORD lastErrno = 0;
void *zConverted;
UNUSED_PARAMETER(pVfs);
@@ -35110,18 +35810,18 @@ static int winAccess(
OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
zFilename, flags, pResOut));
- zConverted = convertUtf8Filename(zFilename);
+ zConverted = winConvertFromUtf8Filename(zFilename);
if( zConverted==0 ){
OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
return SQLITE_IOERR_NOMEM;
}
- if( isNT() ){
+ if( osIsNT() ){
int cnt = 0;
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
memset(&sAttrData, 0, sizeof(sAttrData));
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
GetFileExInfoStandard,
- &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
+ &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
if( rc ){
/* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
** as if it does not exist.
@@ -35134,11 +35834,11 @@ static int winAccess(
attr = sAttrData.dwFileAttributes;
}
}else{
- logIoerr(cnt);
+ winLogIoerr(cnt);
if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
- winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
sqlite3_free(zConverted);
- return SQLITE_IOERR_ACCESS;
+ return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
+ zFilename);
}else{
attr = INVALID_FILE_ATTRIBUTES;
}
@@ -35168,6 +35868,15 @@ static int winAccess(
return SQLITE_OK;
}
+/*
+** Returns non-zero if the specified path name starts with a drive letter
+** followed by a colon character.
+*/
+static BOOL winIsDriveLetterAndColon(
+ const char *zPathname
+){
+ return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' );
+}
/*
** Returns non-zero if the specified path name should be used verbatim. If
@@ -35185,7 +35894,7 @@ static BOOL winIsVerbatimPathname(
** the final two cases; therefore, we return the safer return value of TRUE
** so that callers of this function will simply use it verbatim.
*/
- if ( zPathname[0]=='/' || zPathname[0]=='\\' ){
+ if ( winIsDirSep(zPathname[0]) ){
return TRUE;
}
@@ -35195,7 +35904,7 @@ static BOOL winIsVerbatimPathname(
** attempt to treat it as a relative path name (i.e. they should simply use
** it verbatim).
*/
- if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){
+ if ( winIsDriveLetterAndColon(zPathname) ){
return TRUE;
}
@@ -35221,7 +35930,6 @@ static int winFullPathname(
#if defined(__CYGWIN__)
SimulateIOError( return SQLITE_ERROR );
UNUSED_PARAMETER(nFull);
- assert( pVfs->mxPathname>=MAX_PATH );
assert( nFull>=pVfs->mxPathname );
if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
/*
@@ -35230,14 +35938,48 @@ static int winFullPathname(
** for converting the relative path name to an absolute
** one by prepending the data directory and a slash.
*/
- char zOut[MAX_PATH+1];
- memset(zOut, 0, MAX_PATH+1);
- cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
- MAX_PATH+1);
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
- sqlite3_data_directory, zOut);
+ char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
+ if( !zOut ){
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( cygwin_conv_path(
+ (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) |
+ CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){
+ sqlite3_free(zOut);
+ return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
+ "winFullPathname1", zRelative);
+ }else{
+ char *zUtf8 = winConvertToUtf8Filename(zOut);
+ if( !zUtf8 ){
+ sqlite3_free(zOut);
+ return SQLITE_IOERR_NOMEM;
+ }
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
+ sqlite3_data_directory, winGetDirSep(), zUtf8);
+ sqlite3_free(zUtf8);
+ sqlite3_free(zOut);
+ }
}else{
- cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
+ char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
+ if( !zOut ){
+ return SQLITE_IOERR_NOMEM;
+ }
+ if( cygwin_conv_path(
+ (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A),
+ zRelative, zOut, pVfs->mxPathname+1)<0 ){
+ sqlite3_free(zOut);
+ return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
+ "winFullPathname2", zRelative);
+ }else{
+ char *zUtf8 = winConvertToUtf8Filename(zOut);
+ if( !zUtf8 ){
+ sqlite3_free(zOut);
+ return SQLITE_IOERR_NOMEM;
+ }
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
+ sqlite3_free(zUtf8);
+ sqlite3_free(zOut);
+ }
}
return SQLITE_OK;
#endif
@@ -35253,8 +35995,8 @@ static int winFullPathname(
** for converting the relative path name to an absolute
** one by prepending the data directory and a backslash.
*/
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
- sqlite3_data_directory, zRelative);
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
+ sqlite3_data_directory, winGetDirSep(), zRelative);
}else{
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
}
@@ -35269,7 +36011,7 @@ static int winFullPathname(
/* If this path name begins with "/X:", where "X" is any alphabetic
** character, discard the initial "/" from the pathname.
*/
- if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
+ if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
zRelative++;
}
@@ -35286,22 +36028,21 @@ static int winFullPathname(
** for converting the relative path name to an absolute
** one by prepending the data directory and a backslash.
*/
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
- sqlite3_data_directory, zRelative);
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
+ sqlite3_data_directory, winGetDirSep(), zRelative);
return SQLITE_OK;
}
- zConverted = convertUtf8Filename(zRelative);
+ zConverted = winConvertFromUtf8Filename(zRelative);
if( zConverted==0 ){
return SQLITE_IOERR_NOMEM;
}
- if( isNT() ){
+ if( osIsNT() ){
LPWSTR zTemp;
nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
if( nByte==0 ){
- winLogError(SQLITE_ERROR, osGetLastError(),
- "GetFullPathNameW1", zConverted);
sqlite3_free(zConverted);
- return SQLITE_CANTOPEN_FULLPATH;
+ return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
+ "winFullPathname1", zRelative);
}
nByte += 3;
zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
@@ -35311,14 +36052,13 @@ static int winFullPathname(
}
nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
if( nByte==0 ){
- winLogError(SQLITE_ERROR, osGetLastError(),
- "GetFullPathNameW2", zConverted);
sqlite3_free(zConverted);
sqlite3_free(zTemp);
- return SQLITE_CANTOPEN_FULLPATH;
+ return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
+ "winFullPathname2", zRelative);
}
sqlite3_free(zConverted);
- zOut = unicodeToUtf8(zTemp);
+ zOut = winUnicodeToUtf8(zTemp);
sqlite3_free(zTemp);
}
#ifdef SQLITE_WIN32_HAS_ANSI
@@ -35326,10 +36066,9 @@ static int winFullPathname(
char *zTemp;
nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
if( nByte==0 ){
- winLogError(SQLITE_ERROR, osGetLastError(),
- "GetFullPathNameA1", zConverted);
sqlite3_free(zConverted);
- return SQLITE_CANTOPEN_FULLPATH;
+ return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
+ "winFullPathname3", zRelative);
}
nByte += 3;
zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
@@ -35339,11 +36078,10 @@ static int winFullPathname(
}
nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
if( nByte==0 ){
- winLogError(SQLITE_ERROR, osGetLastError(),
- "GetFullPathNameA2", zConverted);
sqlite3_free(zConverted);
sqlite3_free(zTemp);
- return SQLITE_CANTOPEN_FULLPATH;
+ return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
+ "winFullPathname4", zRelative);
}
sqlite3_free(zConverted);
zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
@@ -35371,12 +36109,12 @@ static int winFullPathname(
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
- void *zConverted = convertUtf8Filename(zFilename);
+ void *zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
if( zConverted==0 ){
return 0;
}
- if( isNT() ){
+ if( osIsNT() ){
#if SQLITE_OS_WINRT
h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
#else
@@ -35393,7 +36131,7 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
}
static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
UNUSED_PARAMETER(pVfs);
- getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
+ winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
}
static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
UNUSED_PARAMETER(pVfs);
@@ -35569,7 +36307,7 @@ static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
*/
static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
UNUSED_PARAMETER(pVfs);
- return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
+ return winGetLastErrorMsg(osGetLastError(), nBuf, zBuf);
}
/*
@@ -35579,7 +36317,7 @@ SQLITE_API int sqlite3_os_init(void){
static sqlite3_vfs winVfs = {
3, /* iVersion */
sizeof(winFile), /* szOsFile */
- MAX_PATH, /* mxPathname */
+ SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
0, /* pNext */
"win32", /* zName */
0, /* pAppData */
@@ -35600,10 +36338,36 @@ SQLITE_API int sqlite3_os_init(void){
winGetSystemCall, /* xGetSystemCall */
winNextSystemCall, /* xNextSystemCall */
};
+#if defined(SQLITE_WIN32_HAS_WIDE)
+ static sqlite3_vfs winLongPathVfs = {
+ 3, /* iVersion */
+ sizeof(winFile), /* szOsFile */
+ SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
+ 0, /* pNext */
+ "win32-longpath", /* zName */
+ 0, /* pAppData */
+ winOpen, /* xOpen */
+ winDelete, /* xDelete */
+ winAccess, /* xAccess */
+ winFullPathname, /* xFullPathname */
+ winDlOpen, /* xDlOpen */
+ winDlError, /* xDlError */
+ winDlSym, /* xDlSym */
+ winDlClose, /* xDlClose */
+ winRandomness, /* xRandomness */
+ winSleep, /* xSleep */
+ winCurrentTime, /* xCurrentTime */
+ winGetLastError, /* xGetLastError */
+ winCurrentTimeInt64, /* xCurrentTimeInt64 */
+ winSetSystemCall, /* xSetSystemCall */
+ winGetSystemCall, /* xGetSystemCall */
+ winNextSystemCall, /* xNextSystemCall */
+ };
+#endif
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==74 );
+ assert( ArraySize(aSyscall)==76 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
@@ -35616,6 +36380,11 @@ SQLITE_API int sqlite3_os_init(void){
assert( winSysInfo.dwPageSize>0 );
sqlite3_vfs_register(&winVfs, 1);
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+ sqlite3_vfs_register(&winLongPathVfs, 0);
+#endif
+
return SQLITE_OK;
}
@@ -37226,7 +37995,7 @@ static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
int sz; /* Bytes of memory required to allocate the new cache */
/*
- ** The seperateCache variable is true if each PCache has its own private
+ ** The separateCache variable is true if each PCache has its own private
** PGroup. In other words, separateCache is true for mode (1) where no
** mutexing is required.
**
@@ -37429,6 +38198,7 @@ static sqlite3_pcache_page *pcache1Fetch(
if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
goto fetch_out;
}
+ assert( pCache->nHash>0 && pCache->apHash );
/* Step 4. Try to recycle a page. */
if( pCache->bPurgeable && pGroup->pLruTail && (
@@ -38790,6 +39560,13 @@ struct PagerSavepoint {
};
/*
+** Bits of the Pager.doNotSpill flag. See further description below.
+*/
+#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */
+#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */
+#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */
+
+/*
** A open page cache is an instance of struct Pager. A description of
** some of the more important member variables follows:
**
@@ -38855,19 +39632,21 @@ struct PagerSavepoint {
** journal file from being successfully finalized, the setMaster flag
** is cleared anyway (and the pager will move to ERROR state).
**
-** doNotSpill, doNotSyncSpill
+** doNotSpill
**
-** These two boolean variables control the behavior of cache-spills
-** (calls made by the pcache module to the pagerStress() routine to
-** write cached data to the file-system in order to free up memory).
+** This variables control the behavior of cache-spills (calls made by
+** the pcache module to the pagerStress() routine to write cached data
+** to the file-system in order to free up memory).
**
-** When doNotSpill is non-zero, writing to the database from pagerStress()
-** is disabled altogether. This is done in a very obscure case that
+** When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set,
+** writing to the database from pagerStress() is disabled altogether.
+** The SPILLFLAG_ROLLBACK case is done in a very obscure case that
** comes up during savepoint rollback that requires the pcache module
** to allocate a new page to prevent the journal file from being written
-** while it is being traversed by code in pager_playback().
+** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF
+** case is a user preference.
**
-** If doNotSyncSpill is non-zero, writing to the database from pagerStress()
+** If the SPILLFLAG_NOSYNC bit is set, writing to the database from pagerStress()
** is permitted, but syncing the journal file is not. This flag is set
** by sqlite3PagerWrite() when the file-system sector-size is larger than
** the database page-size in order to prevent a journal sync from happening
@@ -38971,7 +39750,6 @@ struct Pager {
u8 changeCountDone; /* Set after incrementing the change-counter */
u8 setMaster; /* True if a m-j name has been written to jrnl */
u8 doNotSpill; /* Do not spill the cache when non-zero */
- u8 doNotSyncSpill; /* Do not do a spill that requires jrnl sync */
u8 subjInMemory; /* True to use in-memory sub-journals */
Pgno dbSize; /* Number of pages in the database */
Pgno dbOrigSize; /* dbSize before the current transaction */
@@ -39350,13 +40128,17 @@ static char *print_pager_state(Pager *p){
** PagerSavepoint.pInSavepoint.
*/
static int subjRequiresPage(PgHdr *pPg){
- Pgno pgno = pPg->pgno;
Pager *pPager = pPg->pPager;
+ PagerSavepoint *p;
+ Pgno pgno;
int i;
- for(i=0; i<pPager->nSavepoint; i++){
- PagerSavepoint *p = &pPager->aSavepoint[i];
- if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
- return 1;
+ if( pPager->nSavepoint ){
+ pgno = pPg->pgno;
+ for(i=0; i<pPager->nSavepoint; i++){
+ p = &pPager->aSavepoint[i];
+ if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
+ return 1;
+ }
}
}
return 0;
@@ -40148,6 +40930,7 @@ static void pager_unlock(Pager *pPager){
pPager->changeCountDone = pPager->tempFile;
pPager->eState = PAGER_OPEN;
pPager->errCode = SQLITE_OK;
+ if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
}
pPager->journalOff = 0;
@@ -40630,11 +41413,11 @@ static int pager_playback_one_page(
** requiring a journal-sync before it is written.
*/
assert( isSavepnt );
- assert( pPager->doNotSpill==0 );
- pPager->doNotSpill++;
+ assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
+ pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
rc = sqlite3PagerAcquire(pPager, pgno, &pPg, 1);
- assert( pPager->doNotSpill==1 );
- pPager->doNotSpill--;
+ assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
+ pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
if( rc!=SQLITE_OK ) return rc;
pPg->flags &= ~PGHDR_NEED_READ;
sqlite3PcacheMakeDirty(pPg);
@@ -41201,12 +41984,6 @@ static int readDbPage(PgHdr *pPg, u32 iFrame){
assert( pPager->eState>=PAGER_READER && !MEMDB );
assert( isOpen(pPager->fd) );
- if( NEVER(!isOpen(pPager->fd)) ){
- assert( pPager->tempFile );
- memset(pPg->pData, 0, pPager->pageSize);
- return SQLITE_OK;
- }
-
#ifndef SQLITE_OMIT_WAL
if( iFrame ){
/* Try to pull the page from the write-ahead log. */
@@ -41714,10 +42491,10 @@ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
static void pagerFixMaplimit(Pager *pPager){
#if SQLITE_MAX_MMAP_SIZE>0
sqlite3_file *fd = pPager->fd;
- if( isOpen(fd) ){
+ if( isOpen(fd) && fd->pMethods->iVersion>=3 ){
sqlite3_int64 sz;
- pPager->bUseFetch = (fd->pMethods->iVersion>=3) && pPager->szMmap>0;
sz = pPager->szMmap;
+ pPager->bUseFetch = (sz>0);
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
}
#endif
@@ -41739,9 +42516,12 @@ SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
}
/*
-** Adjust the robustness of the database to damage due to OS crashes
-** or power failures by changing the number of syncs()s when writing
-** the rollback journal. There are three levels:
+** Adjust settings of the pager to those specified in the pgFlags parameter.
+**
+** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
+** of the database to damage due to OS crashes or power failures by
+** changing the number of syncs()s when writing the journals.
+** There are three levels:
**
** OFF sqlite3OsSync() is never called. This is the default
** for temporary and transient files.
@@ -41782,22 +42562,21 @@ SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
+SQLITE_PRIVATE void sqlite3PagerSetFlags(
Pager *pPager, /* The pager to set safety level for */
- int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
- int bFullFsync, /* PRAGMA fullfsync */
- int bCkptFullFsync /* PRAGMA checkpoint_fullfsync */
+ unsigned pgFlags /* Various flags */
){
+ unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
assert( level>=1 && level<=3 );
pPager->noSync = (level==1 || pPager->tempFile) ?1:0;
pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
if( pPager->noSync ){
pPager->syncFlags = 0;
pPager->ckptSyncFlags = 0;
- }else if( bFullFsync ){
+ }else if( pgFlags & PAGER_FULLFSYNC ){
pPager->syncFlags = SQLITE_SYNC_FULL;
pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
- }else if( bCkptFullFsync ){
+ }else if( pgFlags & PAGER_CKPT_FULLFSYNC ){
pPager->syncFlags = SQLITE_SYNC_NORMAL;
pPager->ckptSyncFlags = SQLITE_SYNC_FULL;
}else{
@@ -41808,6 +42587,11 @@ SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(
if( pPager->fullSync ){
pPager->walSyncFlags |= WAL_SYNC_TRANSACTIONS;
}
+ if( pgFlags & PAGER_CACHESPILL ){
+ pPager->doNotSpill &= ~SPILLFLAG_OFF;
+ }else{
+ pPager->doNotSpill |= SPILLFLAG_OFF;
+ }
}
#endif
@@ -42550,7 +43334,8 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
*/
assert( rc!=SQLITE_OK || isOpen(pPager->fd) );
if( rc==SQLITE_OK
- && (pList->pDirty ? pPager->dbSize : pList->pgno+1)>pPager->dbHintSize
+ && pPager->dbHintSize<pPager->dbSize
+ && (pList->pDirty || pList->pgno>pPager->dbHintSize)
){
sqlite3_int64 szFile = pPager->pageSize * (sqlite3_int64)pPager->dbSize;
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &szFile);
@@ -42707,13 +43492,14 @@ static int pagerStress(void *p, PgHdr *pPg){
assert( pPg->pPager==pPager );
assert( pPg->flags&PGHDR_DIRTY );
- /* The doNotSyncSpill flag is set during times when doing a sync of
+ /* The doNotSpill NOSYNC bit is set during times when doing a sync of
** journal (and adding a new header) is not allowed. This occurs
** during calls to sqlite3PagerWrite() while trying to journal multiple
** pages belonging to the same sector.
**
- ** The doNotSpill flag inhibits all cache spilling regardless of whether
- ** or not a sync is required. This is set during a rollback.
+ ** The doNotSpill ROLLBACK and OFF bits inhibits all cache spilling
+ ** regardless of whether or not a sync is required. This is set during
+ ** a rollback or by user request, respectively.
**
** Spilling is also prohibited when in an error state since that could
** lead to database corruption. In the current implementaton it
@@ -42723,8 +43509,13 @@ static int pagerStress(void *p, PgHdr *pPg){
** test for the error state as a safeguard against future changes.
*/
if( NEVER(pPager->errCode) ) return SQLITE_OK;
- if( pPager->doNotSpill ) return SQLITE_OK;
- if( pPager->doNotSyncSpill && (pPg->flags & PGHDR_NEED_SYNC)!=0 ){
+ testcase( pPager->doNotSpill & SPILLFLAG_ROLLBACK );
+ testcase( pPager->doNotSpill & SPILLFLAG_OFF );
+ testcase( pPager->doNotSpill & SPILLFLAG_NOSYNC );
+ if( pPager->doNotSpill
+ && ((pPager->doNotSpill & (SPILLFLAG_ROLLBACK|SPILLFLAG_OFF))!=0
+ || (pPg->flags & PGHDR_NEED_SYNC)!=0)
+ ){
return SQLITE_OK;
}
@@ -43515,7 +44306,7 @@ static void pagerUnlockIfUnused(Pager *pPager){
** page is initialized to all zeros.
**
** If noContent is true, it means that we do not care about the contents
-** of the page. This occurs in two seperate scenarios:
+** of the page. This occurs in two scenarios:
**
** a) When reading a free-list leaf page from the database, and
**
@@ -43546,19 +44337,19 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
DbPage **ppPage, /* Write a pointer to the page here */
- int flags /* PAGER_ACQUIRE_XXX flags */
+ int flags /* PAGER_GET_XXX flags */
){
int rc = SQLITE_OK;
PgHdr *pPg = 0;
u32 iFrame = 0; /* Frame to read from WAL file */
- const int noContent = (flags & PAGER_ACQUIRE_NOCONTENT);
+ const int noContent = (flags & PAGER_GET_NOCONTENT);
/* It is acceptable to use a read-only (mmap) page for any page except
** page 1 if there is no write-transaction open or the ACQUIRE_READONLY
** flag was specified by the caller. And so long as the db is not a
** temporary or in-memory database. */
const int bMmapOk = (pgno!=1 && USEFETCH(pPager)
- && (pPager->eState==PAGER_READER || (flags & PAGER_ACQUIRE_READONLY))
+ && (pPager->eState==PAGER_READER || (flags & PAGER_GET_READONLY))
#ifdef SQLITE_HAS_CODEC
&& pPager->xCodec==0
#endif
@@ -44078,13 +44869,13 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
int ii; /* Loop counter */
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
- /* Set the doNotSyncSpill flag to 1. This is because we cannot allow
+ /* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
** a journal header to be written between the pages journaled by
** this function.
*/
assert( !MEMDB );
- assert( pPager->doNotSyncSpill==0 );
- pPager->doNotSyncSpill++;
+ assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)==0 );
+ pPager->doNotSpill |= SPILLFLAG_NOSYNC;
/* This trick assumes that both the page-size and sector-size are
** an integer power of 2. It sets variable pg1 to the identifier
@@ -44143,8 +44934,8 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
}
}
- assert( pPager->doNotSyncSpill==1 );
- pPager->doNotSyncSpill--;
+ assert( (pPager->doNotSpill & SPILLFLAG_NOSYNC)!=0 );
+ pPager->doNotSpill &= ~SPILLFLAG_NOSYNC;
}else{
rc = pager_write(pDbPage);
}
@@ -44925,7 +45716,27 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
return pPager->pCodec;
}
-#endif
+
+/*
+** This function is called by the wal module when writing page content
+** into the log file.
+**
+** This function returns a pointer to a buffer containing the encrypted
+** page content. If a malloc fails, this function may return NULL.
+*/
+SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
+ void *aData = 0;
+ CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
+ return aData;
+}
+
+/*
+** Return the current pager state
+*/
+SQLITE_PRIVATE int sqlite3PagerState(Pager *pPager){
+ return pPager->eState;
+}
+#endif /* SQLITE_HAS_CODEC */
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
@@ -45480,21 +46291,6 @@ SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){
}
#endif
-#ifdef SQLITE_HAS_CODEC
-/*
-** This function is called by the wal module when writing page content
-** into the log file.
-**
-** This function returns a pointer to a buffer containing the encrypted
-** page content. If a malloc fails, this function may return NULL.
-*/
-SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
- void *aData = 0;
- CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
- return aData;
-}
-#endif /* SQLITE_HAS_CODEC */
-
#endif /* SQLITE_OMIT_DISKIO */
/************** End of pager.c ***********************************************/
@@ -47963,7 +48759,7 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
pWal->writeLock = 0;
- rc = SQLITE_BUSY;
+ rc = SQLITE_BUSY_SNAPSHOT;
}
return rc;
@@ -48672,13 +49468,13 @@ SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
**
** OFFSET SIZE DESCRIPTION
** 0 16 Header string: "SQLite format 3\000"
-** 16 2 Page size in bytes.
+** 16 2 Page size in bytes. (1 means 65536)
** 18 1 File format write version
** 19 1 File format read version
** 20 1 Bytes of unused space at the end of each page
-** 21 1 Max embedded payload fraction
-** 22 1 Min embedded payload fraction
-** 23 1 Min leaf payload fraction
+** 21 1 Max embedded payload fraction (must be 64)
+** 22 1 Min embedded payload fraction (must be 32)
+** 23 1 Min leaf payload fraction (must be 32)
** 24 4 File change counter
** 28 4 Reserved for future use
** 32 4 First freelist page
@@ -48692,9 +49488,10 @@ SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
** 60 4 User version
** 64 4 Incremental vacuum mode
-** 68 4 unused
-** 72 4 unused
-** 76 4 unused
+** 68 4 Application-ID
+** 72 20 unused
+** 92 4 The version-valid-for number
+** 96 4 SQLITE_VERSION_NUMBER
**
** All of the integer values are big-endian (most significant byte first).
**
@@ -49135,14 +49932,19 @@ struct BtCursor {
/*
** Potential values for BtCursor.eState.
**
-** CURSOR_VALID:
-** Cursor points to a valid entry. getPayload() etc. may be called.
-**
** CURSOR_INVALID:
** Cursor does not point to a valid entry. This can happen (for example)
** because the table is empty or because BtreeCursorFirst() has not been
** called.
**
+** CURSOR_VALID:
+** Cursor points to a valid entry. getPayload() etc. may be called.
+**
+** CURSOR_SKIPNEXT:
+** Cursor is valid except that the Cursor.skipNext field is non-zero
+** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
+** operation should be a no-op.
+**
** CURSOR_REQUIRESEEK:
** The table that this cursor was opened on still exists, but has been
** modified since the cursor was last used. The cursor position is saved
@@ -49159,8 +49961,9 @@ struct BtCursor {
*/
#define CURSOR_INVALID 0
#define CURSOR_VALID 1
-#define CURSOR_REQUIRESEEK 2
-#define CURSOR_FAULT 3
+#define CURSOR_SKIPNEXT 2
+#define CURSOR_REQUIRESEEK 3
+#define CURSOR_FAULT 4
/*
** The database page the PENDING_BYTE occupies. This page is never used.
@@ -50234,7 +51037,7 @@ static int btreeMoveto(
){
int rc; /* Status code */
UnpackedRecord *pIdxKey; /* Unpacked index key */
- char aSpace[150]; /* Temp space for pIdxKey - to avoid a malloc */
+ char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */
char *pFree = 0;
if( pKey ){
@@ -50244,6 +51047,10 @@ static int btreeMoveto(
);
if( pIdxKey==0 ) return SQLITE_NOMEM;
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
+ if( pIdxKey->nField==0 ){
+ sqlite3DbFree(pCur->pKeyInfo->db, pFree);
+ return SQLITE_CORRUPT_BKPT;
+ }
}else{
pIdxKey = 0;
}
@@ -50274,6 +51081,9 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
+ if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
+ pCur->eState = CURSOR_SKIPNEXT;
+ }
}
return rc;
}
@@ -50299,7 +51109,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
*pHasMoved = 1;
return rc;
}
- if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){
+ if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
*pHasMoved = 1;
}else{
*pHasMoved = 0;
@@ -50487,7 +51297,8 @@ static void btreeParseCellPtr(
assert( n==4-4*pPage->leaf );
if( pPage->intKey ){
if( pPage->hasData ){
- n += getVarint32(&pCell[n], nPayload);
+ assert( n==0 );
+ n = getVarint32(pCell, nPayload);
}else{
nPayload = 0;
}
@@ -50765,7 +51576,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
}else if( gap+2<=top ){
/* Search the freelist looking for a free slot big enough to satisfy
** the request. The allocation is made from the first free slot in
- ** the list that is large enough to accomadate it.
+ ** the list that is large enough to accommodate it.
*/
int pc, addr;
for(addr=hdr+1; (pc = get2byte(&data[addr]))>0; addr=pc){
@@ -51131,15 +51942,12 @@ static int btreeGetPage(
BtShared *pBt, /* The btree */
Pgno pgno, /* Number of the page to fetch */
MemPage **ppPage, /* Return the page in this parameter */
- int noContent, /* Do not load page content if true */
- int bReadonly /* True if a read-only (mmap) page is ok */
+ int flags /* PAGER_GET_NOCONTENT or PAGER_GET_READONLY */
){
int rc;
DbPage *pDbPage;
- int flags = (noContent ? PAGER_ACQUIRE_NOCONTENT : 0)
- | (bReadonly ? PAGER_ACQUIRE_READONLY : 0);
- assert( noContent==0 || bReadonly==0 );
+ assert( flags==0 || flags==PAGER_GET_NOCONTENT || flags==PAGER_GET_READONLY );
assert( sqlite3_mutex_held(pBt->mutex) );
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
if( rc ) return rc;
@@ -51187,15 +51995,16 @@ static int getAndInitPage(
BtShared *pBt, /* The database file */
Pgno pgno, /* Number of the page to get */
MemPage **ppPage, /* Write the page pointer here */
- int bReadonly /* True if a read-only (mmap) page is ok */
+ int bReadonly /* PAGER_GET_READONLY or 0 */
){
int rc;
assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( bReadonly==PAGER_GET_READONLY || bReadonly==0 );
if( pgno>btreePagecount(pBt) ){
rc = SQLITE_CORRUPT_BKPT;
}else{
- rc = btreeGetPage(pBt, pgno, ppPage, 0, bReadonly);
+ rc = btreeGetPage(pBt, pgno, ppPage, bReadonly);
if( rc==SQLITE_OK ){
rc = btreeInitPage(*ppPage);
if( rc!=SQLITE_OK ){
@@ -51600,6 +52409,18 @@ static int removeFromSharingList(BtShared *pBt){
static void allocateTempSpace(BtShared *pBt){
if( !pBt->pTmpSpace ){
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
+
+ /* One of the uses of pBt->pTmpSpace is to format cells before
+ ** inserting them into a leaf page (function fillInCell()). If
+ ** a cell is less than 4 bytes in size, it is rounded up to 4 bytes
+ ** by the various routines that manipulate binary cells. Which
+ ** can mean that fillInCell() only initializes the first 2 or 3
+ ** bytes of pTmpSpace, but that the first 4 bytes are copied from
+ ** it into a database page. This is not actually a problem, but it
+ ** does cause a valgrind error when the 1 or 2 bytes of unitialized
+ ** data is passed to system call write(). So to avoid this error,
+ ** zero the first 4 bytes of temp space here. */
+ if( pBt->pTmpSpace ) memset(pBt->pTmpSpace, 0, 4);
}
}
@@ -51715,17 +52536,14 @@ SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
** probability of damage to near zero but with a write performance reduction.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(
+SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(
Btree *p, /* The btree to set the safety level on */
- int level, /* PRAGMA synchronous. 1=OFF, 2=NORMAL, 3=FULL */
- int fullSync, /* PRAGMA fullfsync. */
- int ckptFullSync /* PRAGMA checkpoint_fullfync */
+ unsigned pgFlags /* Various PAGER_* flags */
){
BtShared *pBt = p->pBt;
assert( sqlite3_mutex_held(p->db->mutex) );
- assert( level>=1 && level<=3 );
sqlite3BtreeEnter(p);
- sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync, ckptFullSync);
+ sqlite3PagerSetFlags(pBt->pPager, pgFlags);
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
@@ -51931,7 +52749,7 @@ static int lockBtree(BtShared *pBt){
assert( pBt->pPage1==0 );
rc = sqlite3PagerSharedLock(pBt->pPager);
if( rc!=SQLITE_OK ) return rc;
- rc = btreeGetPage(pBt, 1, &pPage1, 0, 0);
+ rc = btreeGetPage(pBt, 1, &pPage1, 0);
if( rc!=SQLITE_OK ) return rc;
/* Do some checking to help insure the file we opened really is
@@ -52218,7 +53036,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
goto trans_begun;
}
- assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
+ assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
/* Write transactions are not possible on a read-only database */
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
@@ -52513,7 +53331,7 @@ static int relocatePage(
** iPtrPage.
*/
if( eType!=PTRMAP_ROOTPAGE ){
- rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0, 0);
+ rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -52597,7 +53415,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */
Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */
- rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0, 0);
+ rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -52708,7 +53526,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
/*
** This routine is called prior to sqlite3PagerCommit when a transaction
-** is commited for an auto-vacuum database.
+** is committed for an auto-vacuum database.
**
** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages
** the database file should be truncated to during the commit process.
@@ -52823,12 +53641,13 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
*/
static void btreeEndTransaction(Btree *p){
BtShared *pBt = p->pBt;
+ sqlite3 *db = p->db;
assert( sqlite3BtreeHoldsMutex(p) );
#ifndef SQLITE_OMIT_AUTOVACUUM
pBt->bDoTruncate = 0;
#endif
- if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
+ if( p->inTrans>TRANS_NONE && db->nVdbeRead>1 ){
/* If there are other active statements that belong to this database
** handle, downgrade to a read-only transaction. The other statements
** may still be reading from the database. */
@@ -52995,7 +53814,7 @@ SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){
/* The rollback may have destroyed the pPage1->aData value. So
** call btreeGetPage() on page 1 again to make
** sure pPage1->aData is set correctly. */
- if( btreeGetPage(pBt, 1, &pPage1, 0, 0)==SQLITE_OK ){
+ if( btreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){
int nPage = get4byte(28+(u8*)pPage1->aData);
testcase( nPage==0 );
if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
@@ -53430,7 +54249,7 @@ static int getOverflowPage(
assert( next==0 || rc==SQLITE_DONE );
if( rc==SQLITE_OK ){
- rc = btreeGetPage(pBt, ovfl, &pPage, 0, (ppPage==0));
+ rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? PAGER_GET_READONLY : 0);
assert( rc==SQLITE_OK || pPage==0 );
if( rc==SQLITE_OK ){
next = get4byte(pPage->aData);
@@ -53652,7 +54471,7 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
- (eOp==0 ? PAGER_ACQUIRE_READONLY : 0)
+ (eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
@@ -53744,7 +54563,7 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p
*/
static const unsigned char *fetchPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
- int *pAmt, /* Write the number of available bytes here */
+ u32 *pAmt, /* Write the number of available bytes here */
int skipKey /* read beginning at data if this is true */
){
unsigned char *aPayload;
@@ -53757,7 +54576,7 @@ static const unsigned char *fetchPayload(
assert( cursorHoldsMutex(pCur) );
pPage = pCur->apPage[pCur->iPage];
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
- if( NEVER(pCur->info.nSize==0) ){
+ if( pCur->info.nSize==0 ){
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
&pCur->info);
}
@@ -53794,7 +54613,7 @@ static const unsigned char *fetchPayload(
** These routines is used to get quick access to key and data
** in the common case where no overflow pages are used.
*/
-SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){
+SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){
const void *p = 0;
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) );
@@ -53803,7 +54622,7 @@ SQLITE_PRIVATE const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){
}
return p;
}
-SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){
+SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){
const void *p = 0;
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) );
@@ -53836,7 +54655,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
return SQLITE_CORRUPT_BKPT;
}
- rc = getAndInitPage(pBt, newPgno, &pNewPage, (pCur->wrFlag==0));
+ rc = getAndInitPage(pBt, newPgno, &pNewPage,
+ pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
if( rc ) return rc;
pCur->apPage[i+1] = pNewPage;
pCur->aiIdx[i+1] = 0;
@@ -53953,7 +54773,8 @@ static int moveToRoot(BtCursor *pCur){
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}else{
- rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0);
+ rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0],
+ pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
@@ -54183,10 +55004,10 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
}
assert( pCur->apPage[0]->intKey || pIdxKey );
for(;;){
- int lwr, upr, idx;
+ int lwr, upr, idx, c;
Pgno chldPg;
MemPage *pPage = pCur->apPage[pCur->iPage];
- int c;
+ u8 *pCell; /* Pointer to current cell in pPage */
/* pPage->nCell must be greater than zero. If this is the root-page
** the cursor would have been INVALID above and this for(;;) loop
@@ -54198,35 +55019,47 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
assert( pPage->intKey==(pIdxKey==0) );
lwr = 0;
upr = pPage->nCell-1;
- if( biasRight ){
- pCur->aiIdx[pCur->iPage] = (u16)(idx = upr);
- }else{
- pCur->aiIdx[pCur->iPage] = (u16)(idx = (upr+lwr)/2);
- }
- for(;;){
- u8 *pCell; /* Pointer to current cell in pPage */
-
- assert( idx==pCur->aiIdx[pCur->iPage] );
- pCur->info.nSize = 0;
- pCell = findCell(pPage, idx) + pPage->childPtrSize;
- if( pPage->intKey ){
+ assert( biasRight==0 || biasRight==1 );
+ idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
+ pCur->aiIdx[pCur->iPage] = (u16)idx;
+ if( pPage->intKey ){
+ for(;;){
i64 nCellKey;
+ pCell = findCell(pPage, idx) + pPage->childPtrSize;
if( pPage->hasData ){
- u32 dummy;
- pCell += getVarint32(pCell, dummy);
+ while( 0x80 <= *(pCell++) ){
+ if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
+ }
}
getVarint(pCell, (u64*)&nCellKey);
- if( nCellKey==intKey ){
- c = 0;
- }else if( nCellKey<intKey ){
- c = -1;
+ if( nCellKey<intKey ){
+ lwr = idx+1;
+ if( lwr>upr ){ c = -1; break; }
+ }else if( nCellKey>intKey ){
+ upr = idx-1;
+ if( lwr>upr ){ c = +1; break; }
}else{
- assert( nCellKey>intKey );
- c = +1;
+ assert( nCellKey==intKey );
+ pCur->validNKey = 1;
+ pCur->info.nKey = nCellKey;
+ pCur->aiIdx[pCur->iPage] = (u16)idx;
+ if( !pPage->leaf ){
+ lwr = idx;
+ goto moveto_next_layer;
+ }else{
+ *pRes = 0;
+ rc = SQLITE_OK;
+ goto moveto_finish;
+ }
}
- pCur->validNKey = 1;
- pCur->info.nKey = nCellKey;
- }else{
+ assert( lwr+upr>=0 );
+ idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
+ }
+ }else{
+ for(;;){
+ int nCell;
+ pCell = findCell(pPage, idx) + pPage->childPtrSize;
+
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is less than 16384 bytes and may be stored as a 2-byte
@@ -54235,7 +55068,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
** stored entirely within the b-tree page by inspecting the first
** 2 bytes of the cell.
*/
- int nCell = pCell[0];
+ nCell = pCell[0];
if( nCell<=pPage->max1bytePayload
/* && (pCell+nCell)<pPage->aDataEnd */
){
@@ -54266,6 +55099,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
rc = SQLITE_NOMEM;
goto moveto_finish;
}
+ pCur->aiIdx[pCur->iPage] = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
if( rc ){
sqlite3_free(pCellKey);
@@ -54274,49 +55108,44 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
}
- }
- if( c==0 ){
- if( pPage->intKey && !pPage->leaf ){
- lwr = idx;
- break;
+ if( c<0 ){
+ lwr = idx+1;
+ }else if( c>0 ){
+ upr = idx-1;
}else{
+ assert( c==0 );
*pRes = 0;
rc = SQLITE_OK;
+ pCur->aiIdx[pCur->iPage] = (u16)idx;
goto moveto_finish;
}
+ if( lwr>upr ) break;
+ assert( lwr+upr>=0 );
+ idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
}
- if( c<0 ){
- lwr = idx+1;
- }else{
- upr = idx-1;
- }
- if( lwr>upr ){
- break;
- }
- pCur->aiIdx[pCur->iPage] = (u16)(idx = (lwr+upr)/2);
}
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
- chldPg = 0;
- }else if( lwr>=pPage->nCell ){
- chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- }else{
- chldPg = get4byte(findCell(pPage, lwr));
- }
- if( chldPg==0 ){
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+ pCur->aiIdx[pCur->iPage] = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto moveto_finish;
}
+moveto_next_layer:
+ if( lwr>=pPage->nCell ){
+ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+ }else{
+ chldPg = get4byte(findCell(pPage, lwr));
+ }
pCur->aiIdx[pCur->iPage] = (u16)lwr;
- pCur->info.nSize = 0;
- pCur->validNKey = 0;
rc = moveToChild(pCur, chldPg);
- if( rc ) goto moveto_finish;
+ if( rc ) break;
}
moveto_finish:
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
return rc;
}
@@ -54348,21 +55177,29 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
- rc = restoreCursorPosition(pCur);
- if( rc!=SQLITE_OK ){
- return rc;
- }
assert( pRes!=0 );
- if( CURSOR_INVALID==pCur->eState ){
- *pRes = 1;
- return SQLITE_OK;
- }
- if( pCur->skipNext>0 ){
- pCur->skipNext = 0;
- *pRes = 0;
- return SQLITE_OK;
+ assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
+ if( pCur->eState!=CURSOR_VALID ){
+ rc = restoreCursorPosition(pCur);
+ if( rc!=SQLITE_OK ){
+ *pRes = 0;
+ return rc;
+ }
+ if( CURSOR_INVALID==pCur->eState ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ if( pCur->skipNext ){
+ assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ pCur->eState = CURSOR_VALID;
+ if( pCur->skipNext>0 ){
+ pCur->skipNext = 0;
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ pCur->skipNext = 0;
+ }
}
- pCur->skipNext = 0;
pPage = pCur->apPage[pCur->iPage];
idx = ++pCur->aiIdx[pCur->iPage];
@@ -54380,7 +55217,10 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
- if( rc ) return rc;
+ if( rc ){
+ *pRes = 0;
+ return rc;
+ }
rc = moveToLeftmost(pCur);
*pRes = 0;
return rc;
@@ -54422,21 +55262,32 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
- rc = restoreCursorPosition(pCur);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ assert( pRes!=0 );
+ assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->atLast = 0;
- if( CURSOR_INVALID==pCur->eState ){
- *pRes = 1;
- return SQLITE_OK;
- }
- if( pCur->skipNext<0 ){
- pCur->skipNext = 0;
- *pRes = 0;
- return SQLITE_OK;
+ if( pCur->eState!=CURSOR_VALID ){
+ if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
+ rc = btreeRestoreCursorPosition(pCur);
+ if( rc!=SQLITE_OK ){
+ *pRes = 0;
+ return rc;
+ }
+ }
+ if( CURSOR_INVALID==pCur->eState ){
+ *pRes = 1;
+ return SQLITE_OK;
+ }
+ if( pCur->skipNext ){
+ assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
+ pCur->eState = CURSOR_VALID;
+ if( pCur->skipNext<0 ){
+ pCur->skipNext = 0;
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ pCur->skipNext = 0;
+ }
}
- pCur->skipNext = 0;
pPage = pCur->apPage[pCur->iPage];
assert( pPage->isInit );
@@ -54444,6 +55295,7 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int idx = pCur->aiIdx[pCur->iPage];
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
if( rc ){
+ *pRes = 0;
return rc;
}
rc = moveToRightmost(pCur);
@@ -54567,7 +55419,7 @@ static int allocateBtreePage(
if( iTrunk>mxPage ){
rc = SQLITE_CORRUPT_BKPT;
}else{
- rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
+ rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
}
if( rc ){
pTrunk = 0;
@@ -54631,7 +55483,7 @@ static int allocateBtreePage(
goto end_allocate_page;
}
testcase( iNewTrunk==mxPage );
- rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0, 0);
+ rc = btreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0);
if( rc!=SQLITE_OK ){
goto end_allocate_page;
}
@@ -54710,8 +55562,8 @@ static int allocateBtreePage(
memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
}
put4byte(&aData[4], k-1);
- noContent = !btreeGetHasContent(pBt, *pPgno);
- rc = btreeGetPage(pBt, *pPgno, ppPage, noContent, 0);
+ noContent = !btreeGetHasContent(pBt, *pPgno) ? PAGER_GET_NOCONTENT : 0;
+ rc = btreeGetPage(pBt, *pPgno, ppPage, noContent);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
@@ -54743,7 +55595,7 @@ static int allocateBtreePage(
** here are confined to those pages that lie between the end of the
** database image and the end of the database file.
*/
- int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate));
+ int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate)) ? PAGER_GET_NOCONTENT : 0;
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc ) return rc;
@@ -54759,7 +55611,7 @@ static int allocateBtreePage(
MemPage *pPg = 0;
TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent, 0);
+ rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pPg->pDbPage);
releasePage(pPg);
@@ -54773,7 +55625,7 @@ static int allocateBtreePage(
*pPgno = pBt->nPage;
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent, 0);
+ rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
if( rc ) return rc;
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
@@ -54841,7 +55693,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
/* If the secure_delete option is enabled, then
** always fully overwrite deleted information with zeros.
*/
- if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0, 0))!=0) )
+ if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
|| ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
){
goto freepage_out;
@@ -54868,7 +55720,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
u32 nLeaf; /* Initial number of leaf cells on trunk page */
iTrunk = get4byte(&pPage1->aData[32]);
- rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0, 0);
+ rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
if( rc!=SQLITE_OK ){
goto freepage_out;
}
@@ -54914,7 +55766,7 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
** first trunk in the free-list is full. Either way, the page being freed
** will become the new first trunk page in the free-list.
*/
- if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0, 0)) ){
+ if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
goto freepage_out;
}
rc = sqlite3PagerWrite(pPage->pDbPage);
@@ -56813,7 +57665,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
}
/* Move the page currently at pgnoRoot to pgnoMove. */
- rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
+ rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -56834,7 +57686,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
if( rc!=SQLITE_OK ){
return rc;
}
- rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0, 0);
+ rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -57012,7 +57864,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
return SQLITE_LOCKED_SHAREDCACHE;
}
- rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0, 0);
+ rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc;
rc = sqlite3BtreeClearTable(p, iTable, 0);
if( rc ){
@@ -57047,7 +57899,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
*/
MemPage *pMove;
releasePage(pPage);
- rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
+ rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -57057,7 +57909,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
return rc;
}
pMove = 0;
- rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0, 0);
+ rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
freePage(pMove, &rc);
releasePage(pMove);
if( rc!=SQLITE_OK ){
@@ -57272,7 +58124,7 @@ static void checkAppendMsg(
}
sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
va_end(ap);
- if( pCheck->errMsg.mallocFailed ){
+ if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
pCheck->mallocFailed = 1;
}
}
@@ -57469,7 +58321,7 @@ static int checkTreePage(
usableSize = pBt->usableSize;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
- if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0, 0))!=0 ){
+ if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
checkAppendMsg(pCheck, zContext,
"unable to get the page. error code=%d", rc);
return 0;
@@ -58051,12 +58903,6 @@ SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
** API functions and the related features.
*/
-/* Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
/*
** Structure allocated for each backup operation.
*/
@@ -58138,6 +58984,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
rc = SQLITE_ERROR;
}
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
+ sqlite3ParserReset(pParse);
sqlite3StackFree(pErrorDb, pParse);
}
if( rc ){
@@ -58434,7 +59281,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
DbPage *pSrcPg; /* Source page object */
rc = sqlite3PagerAcquire(pSrcPager, iSrcPg, &pSrcPg,
- PAGER_ACQUIRE_READONLY);
+ PAGER_GET_READONLY);
if( rc==SQLITE_OK ){
rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
sqlite3PagerUnref(pSrcPg);
@@ -59093,15 +59940,8 @@ SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
/*
** Convert a 64-bit IEEE double into a 64-bit signed integer.
-** If the double is too large, return 0x8000000000000000.
-**
-** Most systems appear to do this simply by assigning
-** variables and without the extra range tests. But
-** there are reports that windows throws an expection
-** if the floating point value is out of range. (See ticket #2880.)
-** Because we do not completely understand the problem, we will
-** take the conservative approach and always do range tests
-** before attempting the conversion.
+** If the double is out of range of a 64-bit signed integer then
+** return the closest available 64-bit signed integer.
*/
static i64 doubleToInt64(double r){
#ifdef SQLITE_OMIT_FLOATING_POINT
@@ -59118,14 +59958,10 @@ static i64 doubleToInt64(double r){
static const i64 maxInt = LARGEST_INT64;
static const i64 minInt = SMALLEST_INT64;
- if( r<(double)minInt ){
- return minInt;
- }else if( r>(double)maxInt ){
- /* minInt is correct here - not maxInt. It turns out that assigning
- ** a very large positive number to an integer results in a very large
- ** negative integer. This makes no sense, but it is what x86 hardware
- ** does so for compatibility we will do the same in software. */
+ if( r<=(double)minInt ){
return minInt;
+ }else if( r>=(double)maxInt ){
+ return maxInt;
}else{
return (i64)r;
}
@@ -59207,17 +60043,11 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
**
** The second and third terms in the following conditional enforces
** the second condition under the assumption that addition overflow causes
- ** values to wrap around. On x86 hardware, the third term is always
- ** true and could be omitted. But we leave it in because other
- ** architectures might behave differently.
+ ** values to wrap around.
*/
if( pMem->r==(double)pMem->u.i
&& pMem->u.i>SMALLEST_INT64
-#if defined(__i486__) || defined(__x86_64__)
- && ALWAYS(pMem->u.i<LARGEST_INT64)
-#else
&& pMem->u.i<LARGEST_INT64
-#endif
){
pMem->flags |= MEM_Int;
}
@@ -59589,34 +60419,29 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
** if both values are integers.
*/
if( combined_flags&(MEM_Int|MEM_Real) ){
- if( !(f1&(MEM_Int|MEM_Real)) ){
- return 1;
- }
- if( !(f2&(MEM_Int|MEM_Real)) ){
- return -1;
- }
- if( (f1 & f2 & MEM_Int)==0 ){
- double r1, r2;
- if( (f1&MEM_Real)==0 ){
- r1 = (double)pMem1->u.i;
- }else{
- r1 = pMem1->r;
- }
- if( (f2&MEM_Real)==0 ){
- r2 = (double)pMem2->u.i;
- }else{
- r2 = pMem2->r;
- }
- if( r1<r2 ) return -1;
- if( r1>r2 ) return 1;
- return 0;
- }else{
- assert( f1&MEM_Int );
- assert( f2&MEM_Int );
+ double r1, r2;
+ if( (f1 & f2 & MEM_Int)!=0 ){
if( pMem1->u.i < pMem2->u.i ) return -1;
if( pMem1->u.i > pMem2->u.i ) return 1;
return 0;
}
+ if( (f1&MEM_Real)!=0 ){
+ r1 = pMem1->r;
+ }else if( (f1&MEM_Int)!=0 ){
+ r1 = (double)pMem1->u.i;
+ }else{
+ return 1;
+ }
+ if( (f2&MEM_Real)!=0 ){
+ r2 = pMem2->r;
+ }else if( (f2&MEM_Int)!=0 ){
+ r2 = (double)pMem2->u.i;
+ }else{
+ return -1;
+ }
+ if( r1<r2 ) return -1;
+ if( r1>r2 ) return 1;
+ return 0;
}
/* If one value is a string and the other is a blob, the string is less.
@@ -59691,13 +60516,13 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
*/
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
- int offset, /* Offset from the start of data to return bytes from. */
- int amt, /* Number of bytes to return. */
+ u32 offset, /* Offset from the start of data to return bytes from. */
+ u32 amt, /* Number of bytes to return. */
int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
char *zData; /* Data from the btree layer */
- int available = 0; /* Number of bytes available on the local btree page */
+ u32 available = 0; /* Number of bytes available on the local btree page */
int rc = SQLITE_OK; /* Return code */
assert( sqlite3BtreeCursorIsValid(pCur) );
@@ -59712,7 +60537,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
}
assert( zData!=0 );
- if( offset+amt<=available && (pMem->flags&MEM_Dyn)==0 ){
+ if( offset+amt<=available ){
sqlite3VdbeMemRelease(pMem);
pMem->z = &zData[offset];
pMem->flags = MEM_Blob|MEM_Ephem;
@@ -59731,7 +60556,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
sqlite3VdbeMemRelease(pMem);
}
}
- pMem->n = amt;
+ pMem->n = (int)amt;
return rc;
}
@@ -59796,43 +60621,101 @@ SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *db){
}
/*
-** Create a new sqlite3_value object, containing the value of pExpr.
+** Context object passed by sqlite3Stat4ProbeSetValue() through to
+** valueNew(). See comments above valueNew() for details.
+*/
+struct ValueNewStat4Ctx {
+ Parse *pParse;
+ Index *pIdx;
+ UnpackedRecord **ppRec;
+ int iVal;
+};
+
+/*
+** Allocate and return a pointer to a new sqlite3_value object. If
+** the second argument to this function is NULL, the object is allocated
+** by calling sqlite3ValueNew().
**
-** This only works for very simple expressions that consist of one constant
-** token (i.e. "5", "5.1", "'a string'"). If the expression can
-** be converted directly into a value, then the value is allocated and
-** a pointer written to *ppVal. The caller is responsible for deallocating
-** the value by passing it to sqlite3ValueFree() later on. If the expression
-** cannot be converted to a value, then *ppVal is set to NULL.
+** Otherwise, if the second argument is non-zero, then this function is
+** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
+** already been allocated, allocate the UnpackedRecord structure that
+** that function will return to its caller here. Then return a pointer
+** an sqlite3_value within the UnpackedRecord.a[] array.
*/
-SQLITE_PRIVATE int sqlite3ValueFromExpr(
- sqlite3 *db, /* The database connection */
- Expr *pExpr, /* The expression to evaluate */
- u8 enc, /* Encoding to use */
- u8 affinity, /* Affinity to use */
- sqlite3_value **ppVal /* Write the new value here */
+static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( p ){
+ UnpackedRecord *pRec = p->ppRec[0];
+
+ if( pRec==0 ){
+ Index *pIdx = p->pIdx; /* Index being probed */
+ int nByte; /* Bytes of space to allocate */
+ int i; /* Counter variable */
+ int nCol = pIdx->nColumn; /* Number of index columns including rowid */
+
+ nByte = sizeof(Mem) * nCol + ROUND8(sizeof(UnpackedRecord));
+ pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
+ if( pRec ){
+ pRec->pKeyInfo = sqlite3KeyInfoOfIndex(p->pParse, pIdx);
+ if( pRec->pKeyInfo ){
+ assert( pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField==nCol );
+ assert( pRec->pKeyInfo->enc==ENC(db) );
+ pRec->flags = UNPACKED_PREFIX_MATCH;
+ pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
+ for(i=0; i<nCol; i++){
+ pRec->aMem[i].flags = MEM_Null;
+ pRec->aMem[i].type = SQLITE_NULL;
+ pRec->aMem[i].db = db;
+ }
+ }else{
+ sqlite3DbFree(db, pRec);
+ pRec = 0;
+ }
+ }
+ if( pRec==0 ) return 0;
+ p->ppRec[0] = pRec;
+ }
+
+ pRec->nField = p->iVal+1;
+ return &pRec->aMem[p->iVal];
+ }
+#else
+ UNUSED_PARAMETER(p);
+#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
+ return sqlite3ValueNew(db);
+}
+
+/*
+** Extract a value from the supplied expression in the manner described
+** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
+** using valueNew().
+**
+** If pCtx is NULL and an error occurs after the sqlite3_value object
+** has been allocated, it is freed before returning. Or, if pCtx is not
+** NULL, it is assumed that the caller will free any allocated object
+** in all cases.
+*/
+static int valueFromExpr(
+ sqlite3 *db, /* The database connection */
+ Expr *pExpr, /* The expression to evaluate */
+ u8 enc, /* Encoding to use */
+ u8 affinity, /* Affinity to use */
+ sqlite3_value **ppVal, /* Write the new value here */
+ struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */
){
int op;
char *zVal = 0;
sqlite3_value *pVal = 0;
int negInt = 1;
const char *zNeg = "";
+ int rc = SQLITE_OK;
if( !pExpr ){
*ppVal = 0;
return SQLITE_OK;
}
op = pExpr->op;
-
- /* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT3.
- ** The ifdef here is to enable us to achieve 100% branch test coverage even
- ** when SQLITE_ENABLE_STAT3 is omitted.
- */
-#ifdef SQLITE_ENABLE_STAT3
- if( op==TK_REGISTER ) op = pExpr->op2;
-#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
-#endif
/* Handle negative integers in a single step. This is needed in the
** case when the value is -9223372036854775808.
@@ -59846,7 +60729,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
}
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
- pVal = sqlite3ValueNew(db);
+ pVal = valueNew(db, pCtx);
if( pVal==0 ) goto no_mem;
if( ExprHasProperty(pExpr, EP_IntValue) ){
sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
@@ -59863,11 +60746,13 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
}
if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
if( enc!=SQLITE_UTF8 ){
- sqlite3VdbeChangeEncoding(pVal, enc);
+ rc = sqlite3VdbeChangeEncoding(pVal, enc);
}
}else if( op==TK_UMINUS ) {
/* This branch happens for multiple negative signs. Ex: -(-5) */
- if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
+ if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal)
+ && pVal!=0
+ ){
sqlite3VdbeMemNumerify(pVal);
if( pVal->u.i==SMALLEST_INT64 ){
pVal->flags &= MEM_Int;
@@ -59880,7 +60765,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
sqlite3ValueApplyAffinity(pVal, affinity, enc);
}
}else if( op==TK_NULL ){
- pVal = sqlite3ValueNew(db);
+ pVal = valueNew(db, pCtx);
if( pVal==0 ) goto no_mem;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
@@ -59888,7 +60773,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
int nVal;
assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
assert( pExpr->u.zToken[1]=='\'' );
- pVal = sqlite3ValueNew(db);
+ pVal = valueNew(db, pCtx);
if( !pVal ) goto no_mem;
zVal = &pExpr->u.zToken[2];
nVal = sqlite3Strlen30(zVal)-1;
@@ -59902,17 +60787,201 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
sqlite3VdbeMemStoreType(pVal);
}
*ppVal = pVal;
- return SQLITE_OK;
+ return rc;
no_mem:
db->mallocFailed = 1;
sqlite3DbFree(db, zVal);
- sqlite3ValueFree(pVal);
- *ppVal = 0;
+ assert( *ppVal==0 );
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( pCtx==0 ) sqlite3ValueFree(pVal);
+#else
+ assert( pCtx==0 ); sqlite3ValueFree(pVal);
+#endif
return SQLITE_NOMEM;
}
/*
+** Create a new sqlite3_value object, containing the value of pExpr.
+**
+** This only works for very simple expressions that consist of one constant
+** token (i.e. "5", "5.1", "'a string'"). If the expression can
+** be converted directly into a value, then the value is allocated and
+** a pointer written to *ppVal. The caller is responsible for deallocating
+** the value by passing it to sqlite3ValueFree() later on. If the expression
+** cannot be converted to a value, then *ppVal is set to NULL.
+*/
+SQLITE_PRIVATE int sqlite3ValueFromExpr(
+ sqlite3 *db, /* The database connection */
+ Expr *pExpr, /* The expression to evaluate */
+ u8 enc, /* Encoding to use */
+ u8 affinity, /* Affinity to use */
+ sqlite3_value **ppVal /* Write the new value here */
+){
+ return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0);
+}
+
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+/*
+** The implementation of the sqlite_record() function. This function accepts
+** a single argument of any type. The return value is a formatted database
+** record (a blob) containing the argument value.
+**
+** This is used to convert the value stored in the 'sample' column of the
+** sqlite_stat3 table to the record format SQLite uses internally.
+*/
+static void recordFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const int file_format = 1;
+ int iSerial; /* Serial type */
+ int nSerial; /* Bytes of space for iSerial as varint */
+ int nVal; /* Bytes of space required for argv[0] */
+ int nRet;
+ sqlite3 *db;
+ u8 *aRet;
+
+ UNUSED_PARAMETER( argc );
+ iSerial = sqlite3VdbeSerialType(argv[0], file_format);
+ nSerial = sqlite3VarintLen(iSerial);
+ nVal = sqlite3VdbeSerialTypeLen(iSerial);
+ db = sqlite3_context_db_handle(context);
+
+ nRet = 1 + nSerial + nVal;
+ aRet = sqlite3DbMallocRaw(db, nRet);
+ if( aRet==0 ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ aRet[0] = nSerial+1;
+ sqlite3PutVarint(&aRet[1], iSerial);
+ sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format);
+ sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
+ sqlite3DbFree(db, aRet);
+ }
+}
+
+/*
+** Register built-in functions used to help read ANALYZE data.
+*/
+SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){
+ static SQLITE_WSD FuncDef aAnalyzeTableFuncs[] = {
+ FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
+ };
+ int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs);
+ for(i=0; i<ArraySize(aAnalyzeTableFuncs); i++){
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
+ }
+}
+
+/*
+** This function is used to allocate and populate UnpackedRecord
+** structures intended to be compared against sample index keys stored
+** in the sqlite_stat4 table.
+**
+** A single call to this function attempts to populates field iVal (leftmost
+** is 0 etc.) of the unpacked record with a value extracted from expression
+** pExpr. Extraction of values is possible if:
+**
+** * (pExpr==0). In this case the value is assumed to be an SQL NULL,
+**
+** * The expression is a bound variable, and this is a reprepare, or
+**
+** * The sqlite3ValueFromExpr() function is able to extract a value
+** from the expression (i.e. the expression is a literal value).
+**
+** If a value can be extracted, the affinity passed as the 5th argument
+** is applied to it before it is copied into the UnpackedRecord. Output
+** parameter *pbOk is set to true if a value is extracted, or false
+** otherwise.
+**
+** When this function is called, *ppRec must either point to an object
+** allocated by an earlier call to this function, or must be NULL. If it
+** is NULL and a value can be successfully extracted, a new UnpackedRecord
+** is allocated (and *ppRec set to point to it) before returning.
+**
+** Unless an error is encountered, SQLITE_OK is returned. It is not an
+** error if a value cannot be extracted from pExpr. If an error does
+** occur, an SQLite error code is returned.
+*/
+SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
+ Parse *pParse, /* Parse context */
+ Index *pIdx, /* Index being probed */
+ UnpackedRecord **ppRec, /* IN/OUT: Probe record */
+ Expr *pExpr, /* The expression to extract a value from */
+ u8 affinity, /* Affinity to use */
+ int iVal, /* Array element to populate */
+ int *pbOk /* OUT: True if value was extracted */
+){
+ int rc = SQLITE_OK;
+ sqlite3_value *pVal = 0;
+ sqlite3 *db = pParse->db;
+
+
+ struct ValueNewStat4Ctx alloc;
+ alloc.pParse = pParse;
+ alloc.pIdx = pIdx;
+ alloc.ppRec = ppRec;
+ alloc.iVal = iVal;
+
+ /* Skip over any TK_COLLATE nodes */
+ pExpr = sqlite3ExprSkipCollate(pExpr);
+
+ if( !pExpr ){
+ pVal = valueNew(db, &alloc);
+ if( pVal ){
+ sqlite3VdbeMemSetNull((Mem*)pVal);
+ }
+ }else if( pExpr->op==TK_VARIABLE
+ || NEVER(pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
+ ){
+ Vdbe *v;
+ int iBindVar = pExpr->iColumn;
+ sqlite3VdbeSetVarmask(pParse->pVdbe, iBindVar);
+ if( (v = pParse->pReprepare)!=0 ){
+ pVal = valueNew(db, &alloc);
+ if( pVal ){
+ rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iBindVar-1]);
+ if( rc==SQLITE_OK ){
+ sqlite3ValueApplyAffinity(pVal, affinity, ENC(db));
+ }
+ pVal->db = pParse->db;
+ sqlite3VdbeMemStoreType((Mem*)pVal);
+ }
+ }
+ }else{
+ rc = valueFromExpr(db, pExpr, ENC(db), affinity, &pVal, &alloc);
+ }
+ *pbOk = (pVal!=0);
+
+ assert( pVal==0 || pVal->db==db );
+ return rc;
+}
+
+/*
+** Unless it is NULL, the argument must be an UnpackedRecord object returned
+** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes
+** the object.
+*/
+SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
+ if( pRec ){
+ int i;
+ int nCol = pRec->pKeyInfo->nField+pRec->pKeyInfo->nXField;
+ Mem *aMem = pRec->aMem;
+ sqlite3 *db = aMem[0].db;
+ for(i=0; i<nCol; i++){
+ sqlite3DbFree(db, aMem[i].zMalloc);
+ }
+ sqlite3KeyInfoUnref(pRec->pKeyInfo);
+ sqlite3DbFree(db, pRec);
+ }
+}
+#endif /* ifdef SQLITE_ENABLE_STAT4 */
+
+/*
** Change the string value of an sqlite3_value object
*/
SQLITE_PRIVATE void sqlite3ValueSetStr(
@@ -60030,15 +61099,6 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
pB->isPrepareV2 = pA->isPrepareV2;
}
-#ifdef SQLITE_DEBUG
-/*
-** Turn tracing on or off
-*/
-SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
- p->trace = trace;
-}
-#endif
-
/*
** Resize the Vdbe.aOp array so that it is at least one op larger than
** it was.
@@ -60059,6 +61119,17 @@ static int growOpArray(Vdbe *p){
return (pNew ? SQLITE_OK : SQLITE_NOMEM);
}
+#ifdef SQLITE_DEBUG
+/* This routine is just a convenient place to set a breakpoint that will
+** fire after each opcode is inserted and displayed using
+** "PRAGMA vdbe_addoptrace=on".
+*/
+static void test_addop_breakpoint(void){
+ static int n = 0;
+ n++;
+}
+#endif
+
/*
** Add a new instruction to the list of instructions current in the
** VDBE. Return the address of the new instruction.
@@ -60096,10 +61167,13 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
pOp->p3 = p3;
pOp->p4.p = 0;
pOp->p4type = P4_NOTUSED;
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
pOp->zComment = 0;
+#endif
+#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+ test_addop_breakpoint();
}
#endif
#ifdef VDBE_PROFILE
@@ -60202,8 +61276,8 @@ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe *p, int x){
int j = -1-x;
assert( p->magic==VDBE_MAGIC_INIT );
- assert( j>=0 && j<p->nLabel );
- if( p->aLabel ){
+ assert( j<p->nLabel );
+ if( j>=0 && p->aLabel ){
p->aLabel[j] = p->nOp;
}
}
@@ -60355,32 +61429,66 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
Op *pOp;
int *aLabel = p->aLabel;
p->readOnly = 1;
+ p->bIsReader = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode;
- pOp->opflags = sqlite3OpcodeProperty[opcode];
- if( opcode==OP_Function || opcode==OP_AggStep ){
- if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
- }else if( (opcode==OP_Transaction && pOp->p2!=0) || opcode==OP_Vacuum ){
- p->readOnly = 0;
+ /* NOTE: Be sure to update mkopcodeh.awk when adding or removing
+ ** cases from this switch! */
+ switch( opcode ){
+ case OP_Function:
+ case OP_AggStep: {
+ if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
+ break;
+ }
+ case OP_Transaction: {
+ if( pOp->p2!=0 ) p->readOnly = 0;
+ /* fall thru */
+ }
+ case OP_AutoCommit:
+ case OP_Savepoint: {
+ p->bIsReader = 1;
+ break;
+ }
+#ifndef SQLITE_OMIT_WAL
+ case OP_Checkpoint:
+#endif
+ case OP_Vacuum:
+ case OP_JournalMode: {
+ p->readOnly = 0;
+ p->bIsReader = 1;
+ break;
+ }
#ifndef SQLITE_OMIT_VIRTUALTABLE
- }else if( opcode==OP_VUpdate ){
- if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
- }else if( opcode==OP_VFilter ){
- int n;
- assert( p->nOp - i >= 3 );
- assert( pOp[-1].opcode==OP_Integer );
- n = pOp[-1].p1;
- if( n>nMaxArgs ) nMaxArgs = n;
+ case OP_VUpdate: {
+ if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
+ break;
+ }
+ case OP_VFilter: {
+ int n;
+ assert( p->nOp - i >= 3 );
+ assert( pOp[-1].opcode==OP_Integer );
+ n = pOp[-1].p1;
+ if( n>nMaxArgs ) nMaxArgs = n;
+ break;
+ }
#endif
- }else if( opcode==OP_Next || opcode==OP_SorterNext ){
- pOp->p4.xAdvance = sqlite3BtreeNext;
- pOp->p4type = P4_ADVANCE;
- }else if( opcode==OP_Prev ){
- pOp->p4.xAdvance = sqlite3BtreePrevious;
- pOp->p4type = P4_ADVANCE;
+ case OP_Next:
+ case OP_NextIfOpen:
+ case OP_SorterNext: {
+ pOp->p4.xAdvance = sqlite3BtreeNext;
+ pOp->p4type = P4_ADVANCE;
+ break;
+ }
+ case OP_Prev:
+ case OP_PrevIfOpen: {
+ pOp->p4.xAdvance = sqlite3BtreePrevious;
+ pOp->p4type = P4_ADVANCE;
+ break;
+ }
}
+ pOp->opflags = sqlite3OpcodeProperty[opcode];
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
assert( -1-pOp->p2<p->nLabel );
pOp->p2 = aLabel[-1-pOp->p2];
@@ -60388,8 +61496,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
}
sqlite3DbFree(p->db, p->aLabel);
p->aLabel = 0;
-
*pMaxFuncArgs = nMaxArgs;
+ assert( p->bIsReader!=0 || p->btreeMask==0 );
}
/*
@@ -60443,7 +61551,8 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
VdbeOp *pOut = &p->aOp[i+addr];
pOut->opcode = pIn->opcode;
pOut->p1 = pIn->p1;
- if( p2<0 && (sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP)!=0 ){
+ if( p2<0 ){
+ assert( sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP );
pOut->p2 = addr + ADDR(p2);
}else{
pOut->p2 = p2;
@@ -60452,8 +61561,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
pOut->p4type = P4_NOTUSED;
pOut->p4.p = 0;
pOut->p5 = 0;
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
pOut->zComment = 0;
+#endif
+#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
}
@@ -60515,8 +61626,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u8 val){
** the address of the next instruction to be coded.
*/
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
- assert( addr>=0 || p->db->mallocFailed );
- if( addr>=0 ) sqlite3VdbeChangeP2(p, addr, p->nOp);
+ if( ALWAYS(addr>=0) ) sqlite3VdbeChangeP2(p, addr, p->nOp);
}
@@ -60525,7 +61635,7 @@ SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe *p, int addr){
** the FuncDef is not ephermal, then do nothing.
*/
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
- if( ALWAYS(pDef) && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
+ if( ALWAYS(pDef) && (pDef->funcFlags & SQLITE_FUNC_EPHEM)!=0 ){
sqlite3DbFree(db, pDef);
}
}
@@ -60542,21 +61652,16 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
case P4_REAL:
case P4_INT64:
case P4_DYNAMIC:
- case P4_KEYINFO:
- case P4_INTARRAY:
- case P4_KEYINFO_HANDOFF: {
+ case P4_INTARRAY: {
sqlite3DbFree(db, p4);
break;
}
- case P4_MPRINTF: {
- if( db->pnBytesFreed==0 ) sqlite3_free(p4);
+ case P4_KEYINFO: {
+ if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
break;
}
- case P4_VDBEFUNC: {
- VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
- freeEphemeralFunction(db, pVdbeFunc->pFunc);
- if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
- sqlite3DbFree(db, pVdbeFunc);
+ case P4_MPRINTF: {
+ if( db->pnBytesFreed==0 ) sqlite3_free(p4);
break;
}
case P4_FUNCDEF: {
@@ -60591,7 +61696,7 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
Op *pOp;
for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
freeP4(db, pOp->p4type, pOp->p4.p);
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
sqlite3DbFree(db, pOp->zComment);
#endif
}
@@ -60619,6 +61724,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
freeP4(db, pOp->p4type, pOp->p4.p);
memset(pOp, 0, sizeof(pOp[0]));
pOp->opcode = OP_Noop;
+ if( addr==p->nOp-1 ) p->nOp--;
}
}
@@ -60632,14 +61738,6 @@ SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
** the string is made into memory obtained from sqlite3_malloc().
** A value of n==0 means copy bytes of zP4 up to and including the
** first null byte. If n>0 then copy n+1 bytes of zP4.
-**
-** If n==P4_KEYINFO it means that zP4 is a pointer to a KeyInfo structure.
-** A copy is made of the KeyInfo structure into memory obtained from
-** sqlite3_malloc, to be freed when the Vdbe is finalized.
-** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure
-** stored in memory that the caller has obtained from sqlite3_malloc. The
-** caller should not free the allocation, it will be freed when the Vdbe is
-** finalized.
**
** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
** to a string or structure that is guaranteed to exist for the lifetime of
@@ -60654,7 +61752,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
db = p->db;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->aOp==0 || db->mallocFailed ){
- if ( n!=P4_KEYINFO && n!=P4_VTAB ) {
+ if( n!=P4_VTAB ){
freeP4(db, n, (void*)*(char**)&zP4);
}
return;
@@ -60677,26 +61775,6 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
pOp->p4.p = 0;
pOp->p4type = P4_NOTUSED;
}else if( n==P4_KEYINFO ){
- KeyInfo *pKeyInfo;
- int nField, nByte;
-
- nField = ((KeyInfo*)zP4)->nField;
- nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
- pKeyInfo = sqlite3DbMallocRaw(0, nByte);
- pOp->p4.pKeyInfo = pKeyInfo;
- if( pKeyInfo ){
- u8 *aSortOrder;
- memcpy((char*)pKeyInfo, zP4, nByte - nField);
- aSortOrder = pKeyInfo->aSortOrder;
- assert( aSortOrder!=0 );
- pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
- memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
- pOp->p4type = P4_KEYINFO;
- }else{
- p->db->mallocFailed = 1;
- pOp->p4type = P4_NOTUSED;
- }
- }else if( n==P4_KEYINFO_HANDOFF ){
pOp->p4.p = (void*)zP4;
pOp->p4type = P4_KEYINFO;
}else if( n==P4_VTAB ){
@@ -60714,7 +61792,19 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
}
}
-#ifndef NDEBUG
+/*
+** Set the P4 on the most recently added opcode to the KeyInfo for the
+** index given.
+*/
+SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
+ Vdbe *v = pParse->pVdbe;
+ assert( v!=0 );
+ assert( pIdx!=0 );
+ sqlite3VdbeChangeP4(v, -1, (char*)sqlite3KeyInfoOfIndex(pParse, pIdx),
+ P4_KEYINFO);
+}
+
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
/*
** Change the comment on the most recently coded instruction. Or
** insert a No-op and add the comment to that new instruction. This
@@ -60789,6 +61879,81 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
}
}
+#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
+/*
+** Return an integer value for one of the parameters to the opcode pOp
+** determined by character c.
+*/
+static int translateP(char c, const Op *pOp){
+ if( c=='1' ) return pOp->p1;
+ if( c=='2' ) return pOp->p2;
+ if( c=='3' ) return pOp->p3;
+ if( c=='4' ) return pOp->p4.i;
+ return pOp->p5;
+}
+
+/*
+** Compute a string for the "comment" field of a VDBE opcode listing
+*/
+static int displayComment(
+ const Op *pOp, /* The opcode to be commented */
+ const char *zP4, /* Previously obtained value for P4 */
+ char *zTemp, /* Write result here */
+ int nTemp /* Space available in zTemp[] */
+){
+ const char *zOpName;
+ const char *zSynopsis;
+ int nOpName;
+ int ii, jj;
+ zOpName = sqlite3OpcodeName(pOp->opcode);
+ nOpName = sqlite3Strlen30(zOpName);
+ if( zOpName[nOpName+1] ){
+ int seenCom = 0;
+ char c;
+ zSynopsis = zOpName += nOpName + 1;
+ for(ii=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
+ if( c=='P' ){
+ c = zSynopsis[++ii];
+ if( c=='4' ){
+ sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
+ }else if( c=='X' ){
+ sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
+ seenCom = 1;
+ }else{
+ int v1 = translateP(c, pOp);
+ int v2;
+ sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
+ if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
+ ii += 3;
+ jj += sqlite3Strlen30(zTemp+jj);
+ v2 = translateP(zSynopsis[ii], pOp);
+ if( v2>1 ) sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
+ }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
+ ii += 4;
+ }
+ }
+ jj += sqlite3Strlen30(zTemp+jj);
+ }else{
+ zTemp[jj++] = c;
+ }
+ }
+ if( !seenCom && jj<nTemp-5 && pOp->zComment ){
+ sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
+ jj += sqlite3Strlen30(zTemp+jj);
+ }
+ if( jj<nTemp ) zTemp[jj] = 0;
+ }else if( pOp->zComment ){
+ sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment);
+ jj = sqlite3Strlen30(zTemp);
+ }else{
+ zTemp[0] = 0;
+ jj = 0;
+ }
+ return jj;
+}
+#endif /* SQLITE_DEBUG */
+
+
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
/*
@@ -60799,17 +61964,20 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
char *zP4 = zTemp;
assert( nTemp>=20 );
switch( pOp->p4type ){
- case P4_KEYINFO_STATIC:
case P4_KEYINFO: {
int i, j;
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
assert( pKeyInfo->aSortOrder!=0 );
- sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
+ sqlite3_snprintf(nTemp, zTemp, "k(%d", pKeyInfo->nField);
i = sqlite3Strlen30(zTemp);
for(j=0; j<pKeyInfo->nField; j++){
CollSeq *pColl = pKeyInfo->aColl[j];
const char *zColl = pColl ? pColl->zName : "nil";
int n = sqlite3Strlen30(zColl);
+ if( n==6 && memcmp(zColl,"BINARY",6)==0 ){
+ zColl = "B";
+ n = 1;
+ }
if( i+n>nTemp-6 ){
memcpy(&zTemp[i],",...",4);
break;
@@ -60828,7 +61996,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
}
case P4_COLLSEQ: {
CollSeq *pColl = pOp->p4.pColl;
- sqlite3_snprintf(nTemp, zTemp, "collseq(%.20s)", pColl->zName);
+ sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName);
break;
}
case P4_FUNCDEF: {
@@ -60982,16 +62150,18 @@ SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe *p){
SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
char *zP4;
char zPtr[50];
- static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
+ char zCom[100];
+ static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
if( pOut==0 ) pOut = stdout;
zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
- fprintf(pOut, zFormat1, pc,
- sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
-#ifdef SQLITE_DEBUG
- pOp->zComment ? pOp->zComment : ""
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+ displayComment(pOp, zP4, zCom, sizeof(zCom));
#else
- ""
+ zCom[0] = 0
#endif
+ fprintf(pOut, zFormat1, pc,
+ sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
+ zCom
);
fflush(pOut);
}
@@ -61137,7 +62307,7 @@ SQLITE_PRIVATE int sqlite3VdbeList(
rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3ErrStr(p->rc));
}else{
- char *z;
+ char *zP4;
Op *pOp;
if( i<p->nOp ){
/* The output line number is small enough that we are still in the
@@ -61160,7 +62330,7 @@ SQLITE_PRIVATE int sqlite3VdbeList(
pMem++;
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
- pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
+ pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
pMem->n = sqlite3Strlen30(pMem->z);
pMem->type = SQLITE_TEXT;
@@ -61207,9 +62377,9 @@ SQLITE_PRIVATE int sqlite3VdbeList(
return SQLITE_ERROR;
}
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
- z = displayP4(pOp, pMem->z, 32);
- if( z!=pMem->z ){
- sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0);
+ zP4 = displayP4(pOp, pMem->z, 32);
+ if( zP4!=pMem->z ){
+ sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
}else{
assert( pMem->z!=0 );
pMem->n = sqlite3Strlen30(pMem->z);
@@ -61230,19 +62400,19 @@ SQLITE_PRIVATE int sqlite3VdbeList(
pMem->enc = SQLITE_UTF8;
pMem++;
-#ifdef SQLITE_DEBUG
- if( pOp->zComment ){
- pMem->flags = MEM_Str|MEM_Term;
- pMem->z = pOp->zComment;
- pMem->n = sqlite3Strlen30(pMem->z);
- pMem->enc = SQLITE_UTF8;
- pMem->type = SQLITE_TEXT;
- }else
-#endif
- {
- pMem->flags = MEM_Null; /* Comment */
- pMem->type = SQLITE_NULL;
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+ if( sqlite3VdbeMemGrow(pMem, 500, 0) ){
+ assert( p->db->mallocFailed );
+ return SQLITE_ERROR;
}
+ pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
+ pMem->n = displayComment(pOp, zP4, pMem->z, 500);
+ pMem->type = SQLITE_TEXT;
+ pMem->enc = SQLITE_UTF8;
+#else
+ pMem->flags = MEM_Null; /* Comment */
+ pMem->type = SQLITE_NULL;
+#endif
}
p->nResColumn = 8 - 4*(p->explain-1);
@@ -61259,15 +62429,17 @@ SQLITE_PRIVATE int sqlite3VdbeList(
** Print the SQL that was used to generate a VDBE program.
*/
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe *p){
- int nOp = p->nOp;
- VdbeOp *pOp;
- if( nOp<1 ) return;
- pOp = &p->aOp[0];
- if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
- const char *z = pOp->p4.z;
- while( sqlite3Isspace(*z) ) z++;
- printf("SQL: [%s]\n", z);
+ const char *z = 0;
+ if( p->zSql ){
+ z = p->zSql;
+ }else if( p->nOp>=1 ){
+ const VdbeOp *pOp = &p->aOp[0];
+ if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
+ z = pOp->p4.z;
+ while( sqlite3Isspace(*z) ) z++;
+ }
}
+ if( z ) printf("SQL: [%s]\n", z);
}
#endif
@@ -61525,7 +62697,7 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
- const sqlite3_module *pModule = pCx->pModule;
+ const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
p->inVtabMethod = 1;
pModule->xClose(pVtabCursor);
p->inVtabMethod = 0;
@@ -61588,6 +62760,10 @@ static void closeAllCursors(Vdbe *p){
p->pDelFrame = pDel->pParent;
sqlite3VdbeFrameDelete(pDel);
}
+
+ /* Delete any auxdata allocations made by the VM */
+ sqlite3VdbeDeleteAuxData(p, -1, 0);
+ assert( p->pAuxData==0 );
}
/*
@@ -61696,7 +62872,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** required, as an xSync() callback may add an attached database
** to the transaction.
*/
- rc = sqlite3VtabSync(db, &p->zErrMsg);
+ rc = sqlite3VtabSync(db, p);
/* This loop determines (a) if the commit hook should be invoked and
** (b) how many database files have open write transactions, not
@@ -61915,7 +63091,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
}
/*
-** This routine checks that the sqlite3.activeVdbeCnt count variable
+** This routine checks that the sqlite3.nVdbeActive count variable
** matches the number of vdbe's in the list sqlite3.pVdbe that are
** currently active. An assertion fails if the two counts do not match.
** This is an internal self-check only - it is not an essential processing
@@ -61928,16 +63104,19 @@ static void checkActiveVdbeCnt(sqlite3 *db){
Vdbe *p;
int cnt = 0;
int nWrite = 0;
+ int nRead = 0;
p = db->pVdbe;
while( p ){
if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
cnt++;
if( p->readOnly==0 ) nWrite++;
+ if( p->bIsReader ) nRead++;
}
p = p->pNext;
}
- assert( cnt==db->activeVdbeCnt );
- assert( nWrite==db->writeVdbeCnt );
+ assert( cnt==db->nVdbeActive );
+ assert( nWrite==db->nVdbeWrite );
+ assert( nRead==db->nVdbeRead );
}
#else
#define checkActiveVdbeCnt(x)
@@ -61948,7 +63127,7 @@ static void checkActiveVdbeCnt(sqlite3 *db){
** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the
-** statement transaction is commtted.
+** statement transaction is committed.
**
** If an IO error occurs, an SQLITE_IOERR_XXX error code is returned.
** Otherwise SQLITE_OK.
@@ -62002,6 +63181,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
** the statement transaction was opened. */
if( eOp==SAVEPOINT_ROLLBACK ){
db->nDeferredCons = p->nStmtDefCons;
+ db->nDeferredImmCons = p->nStmtDefImmCons;
}
}
return rc;
@@ -62020,10 +63200,12 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
sqlite3 *db = p->db;
- if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
+ if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
+ || (!deferred && p->nFkConstraint>0)
+ ){
p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
- sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
+ sqlite3SetString(&p->zErrMsg, db, "FOREIGN KEY constraint failed");
return SQLITE_ERROR;
}
return SQLITE_OK;
@@ -62073,8 +63255,9 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
}
checkActiveVdbeCnt(db);
- /* No commit or rollback needed if the program never started */
- if( p->pc>=0 ){
+ /* No commit or rollback needed if the program never started or if the
+ ** SQL statement does not read or write a database file. */
+ if( p->pc>=0 && p->bIsReader ){
int mrc; /* Primary error code from p->rc */
int eStatementOp = 0;
int isSpecialError; /* Set to true if a 'special' error */
@@ -62127,7 +63310,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
*/
if( !sqlite3VtabInSync(db)
&& db->autoCommit
- && db->writeVdbeCnt==(p->readOnly==0)
+ && db->nVdbeWrite==(p->readOnly==0)
){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
rc = sqlite3VdbeCheckFk(p, 1);
@@ -62152,6 +63335,8 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
sqlite3RollbackAll(db, SQLITE_OK);
}else{
db->nDeferredCons = 0;
+ db->nDeferredImmCons = 0;
+ db->flags &= ~SQLITE_DeferFKs;
sqlite3CommitInternalChanges(db);
}
}else{
@@ -62208,11 +63393,12 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
/* We have successfully halted and closed the VM. Record this fact. */
if( p->pc>=0 ){
- db->activeVdbeCnt--;
- if( !p->readOnly ){
- db->writeVdbeCnt--;
- }
- assert( db->activeVdbeCnt>=db->writeVdbeCnt );
+ db->nVdbeActive--;
+ if( !p->readOnly ) db->nVdbeWrite--;
+ if( p->bIsReader ) db->nVdbeRead--;
+ assert( db->nVdbeActive>=db->nVdbeRead );
+ assert( db->nVdbeRead>=db->nVdbeWrite );
+ assert( db->nVdbeWrite>=0 );
}
p->magic = VDBE_MAGIC_HALT;
checkActiveVdbeCnt(db);
@@ -62228,7 +63414,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
sqlite3ConnectionUnlocked(db);
}
- assert( db->activeVdbeCnt>0 || db->autoCommit==0 || db->nStatement==0 );
+ assert( db->nVdbeActive>0 || db->autoCommit==0 || db->nStatement==0 );
return (p->rc==SQLITE_BUSY ? SQLITE_BUSY : SQLITE_OK);
}
@@ -62357,6 +63543,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
}
}
#endif
+ p->iCurrentTime = 0;
p->magic = VDBE_MAGIC_INIT;
return p->rc & db->errMask;
}
@@ -62376,20 +63563,35 @@ SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
}
/*
-** Call the destructor for each auxdata entry in pVdbeFunc for which
-** the corresponding bit in mask is clear. Auxdata entries beyond 31
-** are always destroyed. To destroy all auxdata entries, call this
-** routine with mask==0.
+** If parameter iOp is less than zero, then invoke the destructor for
+** all auxiliary data pointers currently cached by the VM passed as
+** the first argument.
+**
+** Or, if iOp is greater than or equal to zero, then the destructor is
+** only invoked for those auxiliary data pointers created by the user
+** function invoked by the OP_Function opcode at instruction iOp of
+** VM pVdbe, and only then if:
+**
+** * the associated function parameter is the 32nd or later (counting
+** from left to right), or
+**
+** * the corresponding bit in argument mask is clear (where the first
+** function parameter corrsponds to bit 0 etc.).
*/
-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&(((u32)1)<<i))) && pAux->pAux ){
+SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
+ AuxData **pp = &pVdbe->pAuxData;
+ while( *pp ){
+ AuxData *pAux = *pp;
+ if( (iOp<0)
+ || (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
+ ){
if( pAux->xDelete ){
pAux->xDelete(pAux->pAux);
}
- pAux->pAux = 0;
+ *pp = pAux->pNext;
+ sqlite3DbFree(pVdbe->db, pAux);
+ }else{
+ pp= &pAux->pNext;
}
}
}
@@ -62479,7 +63681,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
#endif
p->deferredMoveto = 0;
p->cacheStatus = CACHE_STALE;
- }else if( ALWAYS(p->pCursor) ){
+ }else if( p->pCursor ){
int hasMoved;
int rc = sqlite3BtreeCursorHasMoved(p->pCursor, &hasMoved);
if( rc ) return rc;
@@ -62787,15 +63989,12 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(
return 0;
}
default: {
+ static const u16 aFlag[] = { MEM_Blob|MEM_Ephem, MEM_Str|MEM_Ephem };
u32 len = (serial_type-12)/2;
pMem->z = (char *)buf;
pMem->n = len;
pMem->xDel = 0;
- if( serial_type&0x01 ){
- pMem->flags = MEM_Str | MEM_Ephem;
- }else{
- pMem->flags = MEM_Blob | MEM_Ephem;
- }
+ pMem->flags = aFlag[serial_type&1];
return len;
}
}
@@ -62908,11 +64107,10 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2 /* Right key */
){
- int d1; /* Offset into aKey[] of next data element */
+ u32 d1; /* Offset into aKey[] of next data element */
u32 idx1; /* Offset into aKey[] of next header element */
u32 szHdr1; /* Number of bytes in header */
int i = 0;
- int nField;
int rc = 0;
const unsigned char *aKey1 = (const unsigned char *)pKey1;
KeyInfo *pKeyInfo;
@@ -62935,14 +64133,27 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
- nField = pKeyInfo->nField;
+ assert( pKeyInfo->nField+pKeyInfo->nXField>=pPKey2->nField || CORRUPT_DB );
assert( pKeyInfo->aSortOrder!=0 );
- while( idx1<szHdr1 && i<pPKey2->nField ){
+ assert( pKeyInfo->nField>0 );
+ assert( idx1<=szHdr1 || CORRUPT_DB );
+ do{
u32 serial_type1;
/* Read the serial types for the next element in each key. */
idx1 += getVarint32( aKey1+idx1, serial_type1 );
- if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
+
+ /* Verify that there is enough key space remaining to avoid
+ ** a buffer overread. The "d1+serial_type1+2" subexpression will
+ ** always be greater than or equal to the amount of required key space.
+ ** Use that approximation to avoid the more expensive call to
+ ** sqlite3VdbeSerialTypeLen() in the common case.
+ */
+ if( d1+serial_type1+2>(u32)nKey1
+ && d1+sqlite3VdbeSerialTypeLen(serial_type1)>(u32)nKey1
+ ){
+ break;
+ }
/* Extract the values to be compared.
*/
@@ -62950,32 +64161,16 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
/* Do the comparison
*/
- rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
- i<nField ? pKeyInfo->aColl[i] : 0);
+ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], pKeyInfo->aColl[i]);
if( rc!=0 ){
assert( mem1.zMalloc==0 ); /* See comment below */
-
- /* Invert the result if we are using DESC sort order. */
- if( i<nField && pKeyInfo->aSortOrder[i] ){
- rc = -rc;
+ if( pKeyInfo->aSortOrder[i] ){
+ rc = -rc; /* Invert the result for DESC sort order. */
}
-
- /* 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;
- }
-
return rc;
}
i++;
- }
+ }while( idx1<szHdr1 && i<pPKey2->nField );
/* No memory allocation is ever used on mem1. Prove this using
** the following assert(). If the assert() fails, it indicates a
@@ -63033,7 +64228,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
/* Read in the complete content of the index entry */
memset(&m, 0, sizeof(m));
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m);
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
if( rc ){
return rc;
}
@@ -63111,7 +64306,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
return SQLITE_CORRUPT_BKPT;
}
memset(&m, 0, sizeof(m));
- rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
+ rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (u32)nCellKey, 1, &m);
if( rc ){
return rc;
}
@@ -63171,7 +64366,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
**
** The returned value must be freed by the caller using sqlite3ValueFree().
*/
-SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetValue(Vdbe *v, int iVar, u8 aff){
+SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff){
assert( iVar>0 );
if( v ){
Mem *pMem = &v->aVar[iVar-1];
@@ -63202,6 +64397,21 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
}
}
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
+** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
+** in memory obtained from sqlite3DbMalloc).
+*/
+SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
+ sqlite3 *db = p->db;
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
+ sqlite3_free(pVtab->zErrMsg);
+ pVtab->zErrMsg = 0;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
/************** End of vdbeaux.c *********************************************/
/************** Begin file vdbeapi.c *****************************************/
/*
@@ -63415,12 +64625,14 @@ SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = SQLITE_ERROR;
+ pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = SQLITE_ERROR;
+ pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
@@ -63484,6 +64696,7 @@ 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;
+ pCtx->fErrorOrAux = 1;
if( pCtx->s.flags & MEM_Null ){
sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
SQLITE_UTF8, SQLITE_STATIC);
@@ -63494,6 +64707,7 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
pCtx->isError = SQLITE_TOOBIG;
+ pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
SQLITE_UTF8, SQLITE_STATIC);
}
@@ -63503,6 +64717,7 @@ SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
sqlite3VdbeMemSetNull(&pCtx->s);
pCtx->isError = SQLITE_NOMEM;
+ pCtx->fErrorOrAux = 1;
pCtx->s.db->mallocFailed = 1;
}
@@ -63586,11 +64801,13 @@ static int sqlite3Step(Vdbe *p){
** reset the interrupt flag. This prevents a call to sqlite3_interrupt
** from interrupting a statement that has not yet started.
*/
- if( db->activeVdbeCnt==0 ){
+ if( db->nVdbeActive==0 ){
db->u1.isInterrupted = 0;
}
- assert( db->writeVdbeCnt>0 || db->autoCommit==0 || db->nDeferredCons==0 );
+ assert( db->nVdbeWrite>0 || db->autoCommit==0
+ || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
+ );
#ifndef SQLITE_OMIT_TRACE
if( db->xProfile && !db->init.busy ){
@@ -63598,8 +64815,9 @@ static int sqlite3Step(Vdbe *p){
}
#endif
- db->activeVdbeCnt++;
- if( p->readOnly==0 ) db->writeVdbeCnt++;
+ db->nVdbeActive++;
+ if( p->readOnly==0 ) db->nVdbeWrite++;
+ if( p->bIsReader ) db->nVdbeRead++;
p->pc = 0;
}
#ifndef SQLITE_OMIT_EXPLAIN
@@ -63608,9 +64826,9 @@ static int sqlite3Step(Vdbe *p){
}else
#endif /* SQLITE_OMIT_EXPLAIN */
{
- db->vdbeExecCnt++;
+ db->nVdbeExec++;
rc = sqlite3VdbeExec(p);
- db->vdbeExecCnt--;
+ db->nVdbeExec--;
}
#ifndef SQLITE_OMIT_TRACE
@@ -63706,6 +64924,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
return rc;
}
+
/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
@@ -63731,6 +64950,19 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
}
/*
+** Return the current time for a statement
+*/
+SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
+ Vdbe *v = p->pVdbe;
+ int rc;
+ if( v->iCurrentTime==0 ){
+ rc = sqlite3OsCurrentTimeInt64(p->s.db->pVfs, &v->iCurrentTime);
+ if( rc ) v->iCurrentTime = 0;
+ }
+ return v->iCurrentTime;
+}
+
+/*
** The following is the implementation of an SQL function that always
** fails with an error message stating that the function is used in the
** wrong context. The sqlite3_overload_function() API might construct
@@ -63785,14 +65017,14 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
** the user-function defined by pCtx.
*/
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
- VdbeFunc *pVdbeFunc;
+ AuxData *pAuxData;
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
- pVdbeFunc = pCtx->pVdbeFunc;
- if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
- return 0;
+ for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
+ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
}
- return pVdbeFunc->apAux[iArg].pAux;
+
+ return (pAuxData ? pAuxData->pAux : 0);
}
/*
@@ -63806,29 +65038,30 @@ SQLITE_API void sqlite3_set_auxdata(
void *pAux,
void (*xDelete)(void*)
){
- struct AuxData *pAuxData;
- VdbeFunc *pVdbeFunc;
- if( iArg<0 ) goto failed;
+ AuxData *pAuxData;
+ Vdbe *pVdbe = pCtx->pVdbe;
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
- pVdbeFunc = pCtx->pVdbeFunc;
- if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
- int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0);
- int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
- pVdbeFunc = sqlite3DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc);
- if( !pVdbeFunc ){
- goto failed;
- }
- pCtx->pVdbeFunc = pVdbeFunc;
- memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux));
- pVdbeFunc->nAux = iArg+1;
- pVdbeFunc->pFunc = pCtx->pFunc;
- }
+ if( iArg<0 ) goto failed;
- pAuxData = &pVdbeFunc->apAux[iArg];
- if( pAuxData->pAux && pAuxData->xDelete ){
+ for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
+ if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
+ }
+ if( pAuxData==0 ){
+ pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
+ if( !pAuxData ) goto failed;
+ pAuxData->iOp = pCtx->iOp;
+ pAuxData->iArg = iArg;
+ pAuxData->pNext = pVdbe->pAuxData;
+ pVdbe->pAuxData = pAuxData;
+ if( pCtx->fErrorOrAux==0 ){
+ pCtx->isError = 0;
+ pCtx->fErrorOrAux = 1;
+ }
+ }else if( pAuxData->xDelete ){
pAuxData->xDelete(pAuxData->pAux);
}
+
pAuxData->pAux = pAux;
pAuxData->xDelete = xDelete;
return;
@@ -64017,13 +65250,6 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
return iType;
}
-/* The following function is experimental and subject to change or
-** removal */
-/*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){
-** return sqlite3_value_numeric_type( columnMem(pStmt,i) );
-**}
-*/
-
/*
** Convert the N-th element of pStmt->pColName[] into a string using
** xFunc() then return that string. If N is out of range, return 0.
@@ -64500,9 +65726,9 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
*/
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
Vdbe *pVdbe = (Vdbe*)pStmt;
- int v = pVdbe->aCounter[op-1];
- if( resetFlag ) pVdbe->aCounter[op-1] = 0;
- return v;
+ u32 v = pVdbe->aCounter[op];
+ if( resetFlag ) pVdbe->aCounter[op] = 0;
+ return (int)v;
}
/************** End of vdbeapi.c *********************************************/
@@ -64554,9 +65780,9 @@ static int findNextHostParameter(const char *zSql, int *pnToken){
/*
** This function returns a pointer to a nul-terminated string in memory
-** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the
+** obtained from sqlite3DbMalloc(). If sqlite3.nVdbeExec is 1, then the
** string contains a copy of zRawSql but with host parameters expanded to
-** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1,
+** their current bindings. Or, if sqlite3.nVdbeExec is greater than 1,
** then the returned string holds a copy of zRawSql with "-- " prepended
** to each line of text.
**
@@ -64594,7 +65820,7 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
out.db = db;
- if( db->vdbeExecCnt>1 ){
+ if( db->nVdbeExec>1 ){
while( *zRawSql ){
const char *zStart = zRawSql;
while( *(zRawSql++)!='\n' && *zRawSql );
@@ -65015,9 +66241,8 @@ static VdbeCursor *allocateCursor(
int nByte;
VdbeCursor *pCx = 0;
nByte =
- ROUND8(sizeof(VdbeCursor)) +
- (isBtreeCursor?sqlite3BtreeCursorSize():0) +
- 2*nField*sizeof(u32);
+ ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
+ (isBtreeCursor?sqlite3BtreeCursorSize():0);
assert( iCur<p->nCursor );
if( p->apCsr[iCur] ){
@@ -65029,12 +66254,9 @@ static VdbeCursor *allocateCursor(
memset(pCx, 0, sizeof(VdbeCursor));
pCx->iDb = iDb;
pCx->nField = nField;
- if( nField ){
- pCx->aType = (u32 *)&pMem->z[ROUND8(sizeof(VdbeCursor))];
- }
if( isBtreeCursor ){
pCx->pCursor = (BtCursor*)
- &pMem->z[ROUND8(sizeof(VdbeCursor))+2*nField*sizeof(u32)];
+ &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
sqlite3BtreeCursorZero(pCx->pCursor);
}
}
@@ -65220,37 +66442,36 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
/*
** Print the value of a register for tracing purposes:
*/
-static void memTracePrint(FILE *out, Mem *p){
+static void memTracePrint(Mem *p){
if( p->flags & MEM_Invalid ){
- fprintf(out, " undefined");
+ printf(" undefined");
}else if( p->flags & MEM_Null ){
- fprintf(out, " NULL");
+ printf(" NULL");
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
- fprintf(out, " si:%lld", p->u.i);
+ printf(" si:%lld", p->u.i);
}else if( p->flags & MEM_Int ){
- fprintf(out, " i:%lld", p->u.i);
+ printf(" i:%lld", p->u.i);
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( p->flags & MEM_Real ){
- fprintf(out, " r:%g", p->r);
+ printf(" r:%g", p->r);
#endif
}else if( p->flags & MEM_RowSet ){
- fprintf(out, " (rowset)");
+ printf(" (rowset)");
}else{
char zBuf[200];
sqlite3VdbeMemPrettyPrint(p, zBuf);
- fprintf(out, " ");
- fprintf(out, "%s", zBuf);
+ printf(" %s", zBuf);
}
}
-static void registerTrace(FILE *out, int iReg, Mem *p){
- fprintf(out, "REG[%d] = ", iReg);
- memTracePrint(out, p);
- fprintf(out, "\n");
+static void registerTrace(int iReg, Mem *p){
+ printf("REG[%d] = ", iReg);
+ memTracePrint(p);
+ printf("\n");
}
#endif
#ifdef SQLITE_DEBUG
-# define REGISTER_TRACE(R,M) if(p->trace)registerTrace(p->trace,R,M)
+# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
#else
# define REGISTER_TRACE(R,M)
#endif
@@ -65389,19 +66610,6 @@ static int checkSavepointCount(sqlite3 *db){
}
#endif
-/*
-** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
-** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
-** in memory obtained from sqlite3DbMalloc).
-*/
-static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){
- sqlite3 *db = p->db;
- sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
- sqlite3_free(pVtab->zErrMsg);
- pVtab->zErrMsg = 0;
-}
-
/*
** Execute as much of a VDBE program as we can then return.
@@ -65444,16 +66652,16 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
sqlite3 *db = p->db; /* The database */
u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
u8 encoding = ENC(db); /* The database encoding */
+ int iCompare = 0; /* Result of last OP_Compare operation */
+ unsigned nVmStep = 0; /* Number of virtual machine steps */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- int checkProgress; /* True if progress callbacks are enabled */
- int nProgressOps = 0; /* Opcodes executed since progress callback. */
+ unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
#endif
Mem *aMem = p->aMem; /* Copy of p->aMem */
Mem *pIn1 = 0; /* 1st input operand */
Mem *pIn2 = 0; /* 2nd input operand */
Mem *pIn3 = 0; /* 3rd input operand */
Mem *pOut = 0; /* Output operand */
- int iCompare = 0; /* Result of last OP_Compare operation */
int *aPermute = 0; /* Permutation of columns for OP_Compare */
i64 lastRowid = db->lastRowid; /* Saved value of the last insert ROWID */
#ifdef VDBE_PROFILE
@@ -65472,29 +66680,33 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
struct OP_Yield_stack_vars {
int pcDest;
} aa;
+ struct OP_Halt_stack_vars {
+ const char *zType;
+ const char *zLogFmt;
+ } ab;
struct OP_Null_stack_vars {
int cnt;
u16 nullFlag;
- } ab;
+ } ac;
struct OP_Variable_stack_vars {
Mem *pVar; /* Value being transferred */
- } ac;
+ } ad;
struct OP_Move_stack_vars {
char *zMalloc; /* Holding variable for allocated memory */
int n; /* Number of registers left to copy */
int p1; /* Register to copy from */
int p2; /* Register to copy to */
- } ad;
+ } ae;
struct OP_Copy_stack_vars {
int n;
- } ae;
+ } af;
struct OP_ResultRow_stack_vars {
Mem *pMem;
int i;
- } af;
+ } ag;
struct OP_Concat_stack_vars {
i64 nByte;
- } ag;
+ } ah;
struct OP_Remainder_stack_vars {
char bIntint; /* Started out as two integer operands */
int flags; /* Combined MEM_* flags from both inputs */
@@ -65502,26 +66714,26 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
i64 iB; /* Integer value of right operand */
double rA; /* Real value of left operand */
double rB; /* Real value of right operand */
- } ah;
+ } ai;
struct OP_Function_stack_vars {
int i;
Mem *pArg;
sqlite3_context ctx;
sqlite3_value **apVal;
int n;
- } ai;
+ } aj;
struct OP_ShiftRight_stack_vars {
i64 iA;
u64 uA;
i64 iB;
u8 op;
- } aj;
+ } ak;
struct OP_Ge_stack_vars {
int res; /* Result of the comparison of pIn1 against pIn3 */
char affinity; /* Affinity to use for comparison */
u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */
- } ak;
+ } al;
struct OP_Compare_stack_vars {
int n;
int i;
@@ -65531,43 +66743,38 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
- } al;
+ } am;
struct OP_Or_stack_vars {
int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
- } am;
+ } an;
struct OP_IfNot_stack_vars {
int c;
- } an;
+ } ao;
struct OP_Column_stack_vars {
- u32 payloadSize; /* Number of bytes in the record */
i64 payloadSize64; /* Number of bytes in the record */
- int p1; /* P1 value of the opcode */
int p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
- char *zRec; /* Pointer to complete record-data */
BtCursor *pCrsr; /* The BTree cursor */
u32 *aType; /* aType[i] holds the numeric type of the i-th column */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
- int nField; /* number of fields in the record */
int len; /* The length of the serialized data for the column */
int i; /* Loop counter */
- char *zData; /* Part of the record being decoded */
Mem *pDest; /* Where to write the extracted value */
Mem sMem; /* For storing the record being decoded */
- u8 *zIdx; /* Index into header */
- u8 *zEndHdr; /* Pointer to first byte after the header */
+ const u8 *zData; /* Part of the record being decoded */
+ const u8 *zHdr; /* Next unparsed byte of the header */
+ const u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
u32 szField; /* Number of bytes in the content of a field */
- int szHdr; /* Size of the header size field at start of record */
- int avail; /* Number of bytes of available data */
+ u32 avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
- } ao;
+ } ap;
struct OP_Affinity_stack_vars {
const char *zAffinity; /* The affinity to be applied */
char cAff; /* A single character of affinity */
- } ap;
+ } aq;
struct OP_MakeRecord_stack_vars {
u8 *zNewRecord; /* A buffer to hold the data for the new record */
Mem *pRec; /* The new record */
@@ -65584,11 +66791,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int file_format; /* File format to use for encoding */
int i; /* Space used in zNewRecord[] */
int len; /* Length of a field */
- } aq;
+ } ar;
struct OP_Count_stack_vars {
i64 nEntry;
BtCursor *pCrsr;
- } ar;
+ } as;
struct OP_Savepoint_stack_vars {
int p1; /* Value of P1 operand */
char *zName; /* Name of savepoint */
@@ -65598,28 +66805,28 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
Savepoint *pTmp;
int iSavepoint;
int ii;
- } as;
+ } at;
struct OP_AutoCommit_stack_vars {
int desiredAutoCommit;
int iRollback;
int turnOnAC;
- } at;
+ } au;
struct OP_Transaction_stack_vars {
Btree *pBt;
- } au;
+ } av;
struct OP_ReadCookie_stack_vars {
int iMeta;
int iDb;
int iCookie;
- } av;
+ } aw;
struct OP_SetCookie_stack_vars {
Db *pDb;
- } aw;
+ } ax;
struct OP_VerifyCookie_stack_vars {
int iMeta;
int iGen;
Btree *pBt;
- } ax;
+ } ay;
struct OP_OpenWrite_stack_vars {
int nField;
KeyInfo *pKeyInfo;
@@ -65629,16 +66836,17 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
Btree *pX;
VdbeCursor *pCur;
Db *pDb;
- } ay;
+ } az;
struct OP_OpenEphemeral_stack_vars {
VdbeCursor *pCx;
- } az;
+ KeyInfo *pKeyInfo;
+ } ba;
struct OP_SorterOpen_stack_vars {
VdbeCursor *pCx;
- } ba;
+ } bb;
struct OP_OpenPseudo_stack_vars {
VdbeCursor *pCx;
- } bb;
+ } bc;
struct OP_SeekGt_stack_vars {
int res;
int oc;
@@ -65646,27 +66854,19 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
UnpackedRecord r;
int nField;
i64 iKey; /* The rowid we are to seek to */
- } bc;
+ } bd;
struct OP_Seek_stack_vars {
VdbeCursor *pC;
- } bd;
+ } be;
struct OP_Found_stack_vars {
int alreadyExists;
+ int ii;
VdbeCursor *pC;
int res;
char *pFree;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
- char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
- } be;
- struct OP_IsUnique_stack_vars {
- u16 ii;
- VdbeCursor *pCx;
- BtCursor *pCrsr;
- u16 nField;
- Mem *aMx;
- UnpackedRecord r; /* B-Tree index search key */
- i64 R; /* Rowid stored in register P3 */
+ char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
} bf;
struct OP_NotExists_stack_vars {
VdbeCursor *pC;
@@ -65700,6 +66900,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
struct OP_SorterCompare_stack_vars {
VdbeCursor *pC;
int res;
+ int nIgnore;
} bk;
struct OP_SorterData_stack_vars {
VdbeCursor *pC;
@@ -65729,7 +66930,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
BtCursor *pCrsr;
int res;
} bq;
- struct OP_Next_stack_vars {
+ struct OP_SorterNext_stack_vars {
VdbeCursor *pC;
int res;
} br;
@@ -65899,24 +67100,49 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
goto no_mem;
}
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
+ assert( p->bIsReader || p->readOnly!=0 );
p->rc = SQLITE_OK;
+ p->iCurrentTime = 0;
assert( p->explain==0 );
p->pResultSet = 0;
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- checkProgress = db->xProgress!=0;
+ if( db->xProgress ){
+ assert( 0 < db->nProgressOps );
+ nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
+ if( nProgressLimit==0 ){
+ nProgressLimit = db->nProgressOps;
+ }else{
+ nProgressLimit %= (unsigned)db->nProgressOps;
+ }
+ }
#endif
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
- if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){
+ if( p->pc==0
+ && (p->db->flags & (SQLITE_VdbeListing|SQLITE_VdbeEQP|SQLITE_VdbeTrace))!=0
+ ){
int i;
- printf("VDBE Program Listing:\n");
+ int once = 1;
sqlite3VdbePrintSql(p);
- for(i=0; i<p->nOp; i++){
- sqlite3VdbePrintOp(stdout, i, &aOp[i]);
+ if( p->db->flags & SQLITE_VdbeListing ){
+ printf("VDBE Program Listing:\n");
+ for(i=0; i<p->nOp; i++){
+ sqlite3VdbePrintOp(stdout, i, &aOp[i]);
+ }
+ }
+ if( p->db->flags & SQLITE_VdbeEQP ){
+ for(i=0; i<p->nOp; i++){
+ if( aOp[i].opcode==OP_Explain ){
+ if( once ) printf("VDBE Query Plan:\n");
+ printf("%s\n", aOp[i].p4.z);
+ once = 0;
+ }
+ }
}
+ if( p->db->flags & SQLITE_VdbeTrace ) printf("VDBE Trace:\n");
}
sqlite3EndBenignMalloc();
#endif
@@ -65927,17 +67153,14 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
origPc = pc;
start = sqlite3Hwtime();
#endif
+ nVmStep++;
pOp = &aOp[pc];
/* Only allow tracing if SQLITE_DEBUG is defined.
*/
#ifdef SQLITE_DEBUG
- if( p->trace ){
- if( pc==0 ){
- printf("VDBE Execution Trace:\n");
- sqlite3VdbePrintSql(p);
- }
- sqlite3VdbePrintOp(p->trace, pc, pOp);
+ if( db->flags & SQLITE_VdbeTrace ){
+ sqlite3VdbePrintOp(stdout, pc, pOp);
}
#endif
@@ -65954,27 +67177,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
}
#endif
-#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
- /* Call the progress callback if it is configured and the required number
- ** of VDBE ops have been executed (either since this invocation of
- ** sqlite3VdbeExec() or since last time the progress callback was called).
- ** If the progress callback returns non-zero, exit the virtual machine with
- ** a return code SQLITE_ABORT.
- */
- if( checkProgress ){
- if( db->nProgressOps==nProgressOps ){
- int prc;
- prc = db->xProgress(db->pProgressArg);
- if( prc!=0 ){
- rc = SQLITE_INTERRUPT;
- goto vdbe_error_halt;
- }
- nProgressOps = 0;
- }
- nProgressOps++;
- }
-#endif
-
/* On any opcode with the "out2-prerelease" tag, free any
** external allocations out of mem[p2] and set mem[p2] to be
** an undefined integer. Opcodes will either fill in the integer
@@ -65983,7 +67185,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
assert( pOp->p2>0 );
- assert( pOp->p2<=p->nMem );
+ assert( pOp->p2<=(p->nMem-p->nCursor) );
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
VdbeMemRelease(pOut);
@@ -65994,30 +67196,30 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#ifdef SQLITE_DEBUG
if( (pOp->opflags & OPFLG_IN1)!=0 ){
assert( pOp->p1>0 );
- assert( pOp->p1<=p->nMem );
+ assert( pOp->p1<=(p->nMem-p->nCursor) );
assert( memIsValid(&aMem[pOp->p1]) );
REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
}
if( (pOp->opflags & OPFLG_IN2)!=0 ){
assert( pOp->p2>0 );
- assert( pOp->p2<=p->nMem );
+ assert( pOp->p2<=(p->nMem-p->nCursor) );
assert( memIsValid(&aMem[pOp->p2]) );
REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
}
if( (pOp->opflags & OPFLG_IN3)!=0 ){
assert( pOp->p3>0 );
- assert( pOp->p3<=p->nMem );
+ assert( pOp->p3<=(p->nMem-p->nCursor) );
assert( memIsValid(&aMem[pOp->p3]) );
REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
}
if( (pOp->opflags & OPFLG_OUT2)!=0 ){
assert( pOp->p2>0 );
- assert( pOp->p2<=p->nMem );
+ assert( pOp->p2<=(p->nMem-p->nCursor) );
memAboutToChange(p, &aMem[pOp->p2]);
}
if( (pOp->opflags & OPFLG_OUT3)!=0 ){
assert( pOp->p3>0 );
- assert( pOp->p3<=p->nMem );
+ assert( pOp->p3<=(p->nMem-p->nCursor) );
memAboutToChange(p, &aMem[pOp->p3]);
}
#endif
@@ -66067,8 +67269,37 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
** the program.
*/
case OP_Goto: { /* jump */
- CHECK_FOR_INTERRUPT;
pc = pOp->p2 - 1;
+
+ /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
+ ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
+ ** completion. Check to see if sqlite3_interrupt() has been called
+ ** or if the progress callback needs to be invoked.
+ **
+ ** This code uses unstructured "goto" statements and does not look clean.
+ ** But that is not due to sloppy coding habits. The code is written this
+ ** way for performance, to avoid having to run the interrupt and progress
+ ** checks on every opcode. This helps sqlite3_step() to run about 1.5%
+ ** faster according to "valgrind --tool=cachegrind" */
+check_for_interrupt:
+ CHECK_FOR_INTERRUPT;
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ /* Call the progress callback if it is configured and the required number
+ ** of VDBE ops have been executed (either since this invocation of
+ ** sqlite3VdbeExec() or since last time the progress callback was called).
+ ** If the progress callback returns non-zero, exit the virtual machine with
+ ** a return code SQLITE_ABORT.
+ */
+ if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
+ assert( db->nProgressOps!=0 );
+ nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
+ if( db->xProgress(db->pProgressArg) ){
+ rc = SQLITE_INTERRUPT;
+ goto vdbe_error_halt;
+ }
+ }
+#endif
+
break;
}
@@ -66078,7 +67309,7 @@ case OP_Goto: { /* jump */
** and then jump to address P2.
*/
case OP_Gosub: { /* jump */
- assert( pOp->p1>0 && pOp->p1<=p->nMem );
+ assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
pIn1 = &aMem[pOp->p1];
assert( (pIn1->flags & MEM_Dyn)==0 );
memAboutToChange(p, pIn1);
@@ -66118,11 +67349,13 @@ case OP_Yield: { /* in1 */
break;
}
-/* Opcode: HaltIfNull P1 P2 P3 P4 *
+/* Opcode: HaltIfNull P1 P2 P3 P4 P5
+** Synopsis: if r[P3] null then halt
**
** Check the value in register P3. If it is NULL then Halt using
** parameter P1, P2, and P4 as if this were a Halt instruction. If the
** value in register P3 is not NULL, then this routine is a no-op.
+** The P5 parameter should be 1.
*/
case OP_HaltIfNull: { /* in3 */
pIn3 = &aMem[pOp->p3];
@@ -66130,7 +67363,7 @@ case OP_HaltIfNull: { /* in3 */
/* Fall through into OP_Halt */
}
-/* Opcode: Halt P1 P2 * P4 *
+/* Opcode: Halt P1 P2 * P4 P5
**
** Exit immediately. All open cursors, etc are closed
** automatically.
@@ -66145,11 +67378,27 @@ case OP_HaltIfNull: { /* in3 */
**
** If P4 is not null then it is an error message string.
**
+** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
+**
+** 0: (no change)
+** 1: NOT NULL contraint failed: P4
+** 2: UNIQUE constraint failed: P4
+** 3: CHECK constraint failed: P4
+** 4: FOREIGN KEY constraint failed: P4
+**
+** If P5 is not zero and P4 is NULL, then everything after the ":" is
+** omitted.
+**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program. So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
+#if 0 /* local variables moved into u.ab */
+ const char *zType;
+ const char *zLogFmt;
+#endif /* local variables moved into u.ab */
+
if( pOp->p1==SQLITE_OK && p->pFrame ){
/* Halt the sub-program. Return control to the parent frame. */
VdbeFrame *pFrame = p->pFrame;
@@ -66159,7 +67408,7 @@ case OP_Halt: {
pc = sqlite3VdbeFrameRestore(pFrame);
lastRowid = db->lastRowid;
if( pOp->p2==OE_Ignore ){
- /* Instruction pc is the OP_Program that invoked the sub-program
+ /* Instruction pc is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
** instruction is set to OE_Ignore, then the sub-program is throwing
** an IGNORE exception. In this case jump to the address specified
@@ -66170,18 +67419,33 @@ case OP_Halt: {
aMem = p->aMem;
break;
}
-
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
p->pc = pc;
- if( pOp->p4.z ){
- assert( p->rc!=SQLITE_OK );
- sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z);
- }else if( p->rc ){
- testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(pOp->p1, "constraint failed at %d in [%s]", pc, p->zSql);
+ if( p->rc ){
+ if( pOp->p5 ){
+ static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
+ "FOREIGN KEY" };
+ assert( pOp->p5>=1 && pOp->p5<=4 );
+ testcase( pOp->p5==1 );
+ testcase( pOp->p5==2 );
+ testcase( pOp->p5==3 );
+ testcase( pOp->p5==4 );
+ u.ab.zType = azType[pOp->p5-1];
+ }else{
+ u.ab.zType = 0;
+ }
+ assert( u.ab.zType!=0 || pOp->p4.z!=0 );
+ u.ab.zLogFmt = "abort at %d in [%s]: %s";
+ if( u.ab.zType && pOp->p4.z ){
+ sqlite3SetString(&p->zErrMsg, db, "%s constraint failed: %s",
+ u.ab.zType, pOp->p4.z);
+ }else if( pOp->p4.z ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
+ }else{
+ sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", u.ab.zType);
+ }
+ sqlite3_log(pOp->p1, u.ab.zLogFmt, pc, p->zSql, p->zErrMsg);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -66189,13 +67453,14 @@ case OP_Halt: {
p->rc = rc = SQLITE_BUSY;
}else{
assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
- assert( rc==SQLITE_OK || db->nDeferredCons>0 );
+ assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 );
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
goto vdbe_return;
}
/* Opcode: Integer P1 P2 * * *
+** Synopsis: r[P2]=P1
**
** The 32-bit integer value P1 is written into register P2.
*/
@@ -66205,6 +67470,7 @@ case OP_Integer: { /* out2-prerelease */
}
/* Opcode: Int64 * P2 * P4 *
+** Synopsis: r[P2]=P4
**
** P4 is a pointer to a 64-bit integer value.
** Write that value into register P2.
@@ -66217,6 +67483,7 @@ case OP_Int64: { /* out2-prerelease */
#ifndef SQLITE_OMIT_FLOATING_POINT
/* Opcode: Real * P2 * P4 *
+** Synopsis: r[P2]=P4
**
** P4 is a pointer to a 64-bit floating point value.
** Write that value into register P2.
@@ -66230,6 +67497,7 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
#endif
/* Opcode: String8 * P2 * P4 *
+** Synopsis: r[P2]='P4'
**
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
** into an OP_String before it is executed for the first time.
@@ -66264,6 +67532,7 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
}
/* Opcode: String P1 P2 * P4 *
+** Synopsis: r[P2]='P4' (len=P1)
**
** The string value P4 of length P1 (bytes) is stored in register P2.
*/
@@ -66278,6 +67547,7 @@ case OP_String: { /* out2-prerelease */
}
/* Opcode: Null P1 P2 P3 * *
+** Synopsis: r[P2..P3]=NULL
**
** Write a NULL into registers P2. If P3 greater than P2, then also write
** NULL into register P3 and every register in between P2 and P3. If P3
@@ -66289,25 +67559,26 @@ case OP_String: { /* out2-prerelease */
** OP_Ne or OP_Eq.
*/
case OP_Null: { /* out2-prerelease */
-#if 0 /* local variables moved into u.ab */
+#if 0 /* local variables moved into u.ac */
int cnt;
u16 nullFlag;
-#endif /* local variables moved into u.ab */
- u.ab.cnt = pOp->p3-pOp->p2;
- assert( pOp->p3<=p->nMem );
- pOut->flags = u.ab.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
- while( u.ab.cnt>0 ){
+#endif /* local variables moved into u.ac */
+ u.ac.cnt = pOp->p3-pOp->p2;
+ assert( pOp->p3<=(p->nMem-p->nCursor) );
+ pOut->flags = u.ac.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
+ while( u.ac.cnt>0 ){
pOut++;
memAboutToChange(p, pOut);
VdbeMemRelease(pOut);
- pOut->flags = u.ab.nullFlag;
- u.ab.cnt--;
+ pOut->flags = u.ac.nullFlag;
+ u.ac.cnt--;
}
break;
}
/* Opcode: Blob P1 P2 * P4
+** Synopsis: r[P2]=P4 (len=P1)
**
** P4 points to a blob of data P1 bytes long. Store this
** blob in register P2.
@@ -66321,6 +67592,7 @@ case OP_Blob: { /* out2-prerelease */
}
/* Opcode: Variable P1 P2 * P4 *
+** Synopsis: r[P2]=parameter(P1,P4)
**
** Transfer the values of bound parameter P1 into register P2
**
@@ -66328,22 +67600,23 @@ case OP_Blob: { /* out2-prerelease */
** The P4 value is used by sqlite3_bind_parameter_name().
*/
case OP_Variable: { /* out2-prerelease */
-#if 0 /* local variables moved into u.ac */
+#if 0 /* local variables moved into u.ad */
Mem *pVar; /* Value being transferred */
-#endif /* local variables moved into u.ac */
+#endif /* local variables moved into u.ad */
assert( pOp->p1>0 && pOp->p1<=p->nVar );
assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
- u.ac.pVar = &p->aVar[pOp->p1 - 1];
- if( sqlite3VdbeMemTooBig(u.ac.pVar) ){
+ u.ad.pVar = &p->aVar[pOp->p1 - 1];
+ if( sqlite3VdbeMemTooBig(u.ad.pVar) ){
goto too_big;
}
- sqlite3VdbeMemShallowCopy(pOut, u.ac.pVar, MEM_Static);
+ sqlite3VdbeMemShallowCopy(pOut, u.ad.pVar, MEM_Static);
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
/* Opcode: Move P1 P2 P3 * *
+** Synopsis: r[P2@P3]=r[P1@P3]
**
** Move the values in register P1..P1+P3 over into
** registers P2..P2+P3. Registers P1..P1+P3 are
@@ -66351,43 +67624,44 @@ case OP_Variable: { /* out2-prerelease */
** P1..P1+P3 and P2..P2+P3 to overlap.
*/
case OP_Move: {
-#if 0 /* local variables moved into u.ad */
+#if 0 /* local variables moved into u.ae */
char *zMalloc; /* Holding variable for allocated memory */
int n; /* Number of registers left to copy */
int p1; /* Register to copy from */
int p2; /* Register to copy to */
-#endif /* local variables moved into u.ad */
+#endif /* local variables moved into u.ae */
+
+ u.ae.n = pOp->p3;
+ u.ae.p1 = pOp->p1;
+ u.ae.p2 = pOp->p2;
+ assert( u.ae.n>=0 && u.ae.p1>0 && u.ae.p2>0 );
+ assert( u.ae.p1+u.ae.n<=u.ae.p2 || u.ae.p2+u.ae.n<=u.ae.p1 );
- u.ad.n = pOp->p3 + 1;
- u.ad.p1 = pOp->p1;
- u.ad.p2 = pOp->p2;
- assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 );
- assert( u.ad.p1+u.ad.n<=u.ad.p2 || u.ad.p2+u.ad.n<=u.ad.p1 );
-
- pIn1 = &aMem[u.ad.p1];
- pOut = &aMem[u.ad.p2];
- while( u.ad.n-- ){
- assert( pOut<=&aMem[p->nMem] );
- assert( pIn1<=&aMem[p->nMem] );
+ pIn1 = &aMem[u.ae.p1];
+ pOut = &aMem[u.ae.p2];
+ do{
+ assert( pOut<=&aMem[(p->nMem-p->nCursor)] );
+ assert( pIn1<=&aMem[(p->nMem-p->nCursor)] );
assert( memIsValid(pIn1) );
memAboutToChange(p, pOut);
- u.ad.zMalloc = pOut->zMalloc;
+ u.ae.zMalloc = pOut->zMalloc;
pOut->zMalloc = 0;
sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
- if( pOut->pScopyFrom>=&aMem[u.ad.p1] && pOut->pScopyFrom<&aMem[u.ad.p1+pOp->p3] ){
- pOut->pScopyFrom += u.ad.p1 - pOp->p2;
+ if( pOut->pScopyFrom>=&aMem[u.ae.p1] && pOut->pScopyFrom<&aMem[u.ae.p1+pOp->p3] ){
+ pOut->pScopyFrom += u.ae.p1 - pOp->p2;
}
#endif
- pIn1->zMalloc = u.ad.zMalloc;
- REGISTER_TRACE(u.ad.p2++, pOut);
+ pIn1->zMalloc = u.ae.zMalloc;
+ REGISTER_TRACE(u.ae.p2++, pOut);
pIn1++;
pOut++;
- }
+ }while( u.ae.n-- );
break;
}
/* Opcode: Copy P1 P2 P3 * *
+** Synopsis: r[P2@P3]=r[P1@P3]
**
** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
**
@@ -66395,11 +67669,11 @@ case OP_Move: {
** is made of any string or blob constant. See also OP_SCopy.
*/
case OP_Copy: {
-#if 0 /* local variables moved into u.ae */
+#if 0 /* local variables moved into u.af */
int n;
-#endif /* local variables moved into u.ae */
+#endif /* local variables moved into u.af */
- u.ae.n = pOp->p3;
+ u.af.n = pOp->p3;
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
@@ -66409,8 +67683,8 @@ case OP_Copy: {
#ifdef SQLITE_DEBUG
pOut->pScopyFrom = 0;
#endif
- REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
- if( (u.ae.n--)==0 ) break;
+ REGISTER_TRACE(pOp->p2+pOp->p3-u.af.n, pOut);
+ if( (u.af.n--)==0 ) break;
pOut++;
pIn1++;
}
@@ -66418,6 +67692,7 @@ case OP_Copy: {
}
/* Opcode: SCopy P1 P2 * * *
+** Synopsis: r[P2]=r[P1]
**
** Make a shallow copy of register P1 into register P2.
**
@@ -66429,7 +67704,7 @@ case OP_Copy: {
** during the lifetime of the copy. Use OP_Copy to make a complete
** copy.
*/
-case OP_SCopy: { /* in1, out2 */
+case OP_SCopy: { /* out2 */
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
@@ -66437,11 +67712,11 @@ case OP_SCopy: { /* in1, out2 */
#ifdef SQLITE_DEBUG
if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
#endif
- REGISTER_TRACE(pOp->p2, pOut);
break;
}
/* Opcode: ResultRow P1 P2 * * *
+** Synopsis: output=r[P1@P2]
**
** The registers P1 through P1+P2-1 contain a single row of
** results. This opcode causes the sqlite3_step() call to terminate
@@ -66450,13 +67725,25 @@ case OP_SCopy: { /* in1, out2 */
** row.
*/
case OP_ResultRow: {
-#if 0 /* local variables moved into u.af */
+#if 0 /* local variables moved into u.ag */
Mem *pMem;
int i;
-#endif /* local variables moved into u.af */
+#endif /* local variables moved into u.ag */
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 );
- assert( pOp->p1+pOp->p2<=p->nMem+1 );
+ assert( pOp->p1+pOp->p2<=(p->nMem-p->nCursor)+1 );
+
+#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
+ /* Run the progress counter just before returning.
+ */
+ if( db->xProgress!=0
+ && nVmStep>=nProgressLimit
+ && db->xProgress(db->pProgressArg)!=0
+ ){
+ rc = SQLITE_INTERRUPT;
+ goto vdbe_error_halt;
+ }
+#endif
/* If this statement has violated immediate foreign key constraints, do
** not return the number of rows modified. And do not RELEASE the statement
@@ -66495,15 +67782,15 @@ case OP_ResultRow: {
** and have an assigned type. The results are de-ephemeralized as
** a side effect.
*/
- u.af.pMem = p->pResultSet = &aMem[pOp->p1];
- for(u.af.i=0; u.af.i<pOp->p2; u.af.i++){
- assert( memIsValid(&u.af.pMem[u.af.i]) );
- Deephemeralize(&u.af.pMem[u.af.i]);
- assert( (u.af.pMem[u.af.i].flags & MEM_Ephem)==0
- || (u.af.pMem[u.af.i].flags & (MEM_Str|MEM_Blob))==0 );
- sqlite3VdbeMemNulTerminate(&u.af.pMem[u.af.i]);
- sqlite3VdbeMemStoreType(&u.af.pMem[u.af.i]);
- REGISTER_TRACE(pOp->p1+u.af.i, &u.af.pMem[u.af.i]);
+ u.ag.pMem = p->pResultSet = &aMem[pOp->p1];
+ for(u.ag.i=0; u.ag.i<pOp->p2; u.ag.i++){
+ assert( memIsValid(&u.ag.pMem[u.ag.i]) );
+ Deephemeralize(&u.ag.pMem[u.ag.i]);
+ assert( (u.ag.pMem[u.ag.i].flags & MEM_Ephem)==0
+ || (u.ag.pMem[u.ag.i].flags & (MEM_Str|MEM_Blob))==0 );
+ sqlite3VdbeMemNulTerminate(&u.ag.pMem[u.ag.i]);
+ sqlite3VdbeMemStoreType(&u.ag.pMem[u.ag.i]);
+ REGISTER_TRACE(pOp->p1+u.ag.i, &u.ag.pMem[u.ag.i]);
}
if( db->mallocFailed ) goto no_mem;
@@ -66515,6 +67802,7 @@ case OP_ResultRow: {
}
/* Opcode: Concat P1 P2 P3 * *
+** Synopsis: r[P3]=r[P2]+r[P1]
**
** Add the text in register P1 onto the end of the text in
** register P2 and store the result in register P3.
@@ -66527,9 +67815,9 @@ case OP_ResultRow: {
** to avoid a memcpy().
*/
case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
-#if 0 /* local variables moved into u.ag */
+#if 0 /* local variables moved into u.ah */
i64 nByte;
-#endif /* local variables moved into u.ag */
+#endif /* local variables moved into u.ah */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
@@ -66542,34 +67830,36 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
Stringify(pIn1, encoding);
Stringify(pIn2, encoding);
- u.ag.nByte = pIn1->n + pIn2->n;
- if( u.ag.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ u.ah.nByte = pIn1->n + pIn2->n;
+ if( u.ah.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
MemSetTypeFlag(pOut, MEM_Str);
- if( sqlite3VdbeMemGrow(pOut, (int)u.ag.nByte+2, pOut==pIn2) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)u.ah.nByte+2, pOut==pIn2) ){
goto no_mem;
}
if( pOut!=pIn2 ){
memcpy(pOut->z, pIn2->z, pIn2->n);
}
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
- pOut->z[u.ag.nByte] = 0;
- pOut->z[u.ag.nByte+1] = 0;
+ pOut->z[u.ah.nByte]=0;
+ pOut->z[u.ah.nByte+1] = 0;
pOut->flags |= MEM_Term;
- pOut->n = (int)u.ag.nByte;
+ pOut->n = (int)u.ah.nByte;
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
/* Opcode: Add P1 P2 P3 * *
+** Synopsis: r[P3]=r[P1]+r[P2]
**
** Add the value in register P1 to the value in register P2
** and store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: Multiply P1 P2 P3 * *
+** Synopsis: r[P3]=r[P1]*r[P2]
**
**
** Multiply the value in register P1 by the value in register P2
@@ -66577,12 +67867,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
** If either input is NULL, the result is NULL.
*/
/* Opcode: Subtract P1 P2 P3 * *
+** Synopsis: r[P3]=r[P2]-r[P1]
**
** Subtract the value in register P1 from the value in register P2
** and store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: Divide P1 P2 P3 * *
+** Synopsis: r[P3]=r[P2]/r[P1]
**
** Divide the value in register P1 by the value in register P2
** and store the result in register P3 (P3=P2/P1). If the value in
@@ -66590,10 +67882,11 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
** NULL, the result is NULL.
*/
/* Opcode: Remainder P1 P2 P3 * *
+** Synopsis: r[P3]=r[P2]%r[P1]
**
-** Compute the remainder after integer division of the value in
-** register P1 by the value in register P2 and store the result in P3.
-** If the value in register P2 is zero the result is NULL.
+** Compute the remainder after integer register P2 is divided by
+** register P1 and store the result in register P3.
+** If the value in register P1 is zero the result is NULL.
** If either operand is NULL, the result is NULL.
*/
case OP_Add: /* same as TK_PLUS, in1, in2, out3 */
@@ -66601,79 +67894,79 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
-#if 0 /* local variables moved into u.ah */
+#if 0 /* local variables moved into u.ai */
char bIntint; /* Started out as two integer operands */
int flags; /* Combined MEM_* flags from both inputs */
i64 iA; /* Integer value of left operand */
i64 iB; /* Integer value of right operand */
double rA; /* Real value of left operand */
double rB; /* Real value of right operand */
-#endif /* local variables moved into u.ah */
+#endif /* local variables moved into u.ai */
pIn1 = &aMem[pOp->p1];
applyNumericAffinity(pIn1);
pIn2 = &aMem[pOp->p2];
applyNumericAffinity(pIn2);
pOut = &aMem[pOp->p3];
- u.ah.flags = pIn1->flags | pIn2->flags;
- if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
+ u.ai.flags = pIn1->flags | pIn2->flags;
+ if( (u.ai.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
- u.ah.iA = pIn1->u.i;
- u.ah.iB = pIn2->u.i;
- u.ah.bIntint = 1;
+ u.ai.iA = pIn1->u.i;
+ u.ai.iB = pIn2->u.i;
+ u.ai.bIntint = 1;
switch( pOp->opcode ){
- case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
- case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
- case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
+ case OP_Add: if( sqlite3AddInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break;
+ case OP_Subtract: if( sqlite3SubInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break;
+ case OP_Multiply: if( sqlite3MulInt64(&u.ai.iB,u.ai.iA) ) goto fp_math; break;
case OP_Divide: {
- if( u.ah.iA==0 ) goto arithmetic_result_is_null;
- if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math;
- u.ah.iB /= u.ah.iA;
+ if( u.ai.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ai.iA==-1 && u.ai.iB==SMALLEST_INT64 ) goto fp_math;
+ u.ai.iB /= u.ai.iA;
break;
}
default: {
- if( u.ah.iA==0 ) goto arithmetic_result_is_null;
- if( u.ah.iA==-1 ) u.ah.iA = 1;
- u.ah.iB %= u.ah.iA;
+ if( u.ai.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ai.iA==-1 ) u.ai.iA = 1;
+ u.ai.iB %= u.ai.iA;
break;
}
}
- pOut->u.i = u.ah.iB;
+ pOut->u.i = u.ai.iB;
MemSetTypeFlag(pOut, MEM_Int);
}else{
- u.ah.bIntint = 0;
+ u.ai.bIntint = 0;
fp_math:
- u.ah.rA = sqlite3VdbeRealValue(pIn1);
- u.ah.rB = sqlite3VdbeRealValue(pIn2);
+ u.ai.rA = sqlite3VdbeRealValue(pIn1);
+ u.ai.rB = sqlite3VdbeRealValue(pIn2);
switch( pOp->opcode ){
- case OP_Add: u.ah.rB += u.ah.rA; break;
- case OP_Subtract: u.ah.rB -= u.ah.rA; break;
- case OP_Multiply: u.ah.rB *= u.ah.rA; break;
+ case OP_Add: u.ai.rB += u.ai.rA; break;
+ case OP_Subtract: u.ai.rB -= u.ai.rA; break;
+ case OP_Multiply: u.ai.rB *= u.ai.rA; break;
case OP_Divide: {
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- if( u.ah.rA==(double)0 ) goto arithmetic_result_is_null;
- u.ah.rB /= u.ah.rA;
+ if( u.ai.rA==(double)0 ) goto arithmetic_result_is_null;
+ u.ai.rB /= u.ai.rA;
break;
}
default: {
- u.ah.iA = (i64)u.ah.rA;
- u.ah.iB = (i64)u.ah.rB;
- if( u.ah.iA==0 ) goto arithmetic_result_is_null;
- if( u.ah.iA==-1 ) u.ah.iA = 1;
- u.ah.rB = (double)(u.ah.iB % u.ah.iA);
+ u.ai.iA = (i64)u.ai.rA;
+ u.ai.iB = (i64)u.ai.rB;
+ if( u.ai.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ai.iA==-1 ) u.ai.iA = 1;
+ u.ai.rB = (double)(u.ai.iB % u.ai.iA);
break;
}
}
#ifdef SQLITE_OMIT_FLOATING_POINT
- pOut->u.i = u.ah.rB;
+ pOut->u.i = u.ai.rB;
MemSetTypeFlag(pOut, MEM_Int);
#else
- if( sqlite3IsNaN(u.ah.rB) ){
+ if( sqlite3IsNaN(u.ai.rB) ){
goto arithmetic_result_is_null;
}
- pOut->r = u.ah.rB;
+ pOut->r = u.ai.rB;
MemSetTypeFlag(pOut, MEM_Real);
- if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
+ if( (u.ai.flags & MEM_Real)==0 && !u.ai.bIntint ){
sqlite3VdbeIntegerAffinity(pOut);
}
#endif
@@ -66709,6 +68002,7 @@ case OP_CollSeq: {
}
/* Opcode: Function P1 P2 P3 P4 P5
+** Synopsis: r[P3]=func(r[P2@P5])
**
** Invoke a user function (P4 is a pointer to a Function structure that
** defines the function) with P5 arguments taken from register P2 and
@@ -66725,92 +68019,81 @@ case OP_CollSeq: {
** See also: AggStep and AggFinal
*/
case OP_Function: {
-#if 0 /* local variables moved into u.ai */
+#if 0 /* local variables moved into u.aj */
int i;
Mem *pArg;
sqlite3_context ctx;
sqlite3_value **apVal;
int n;
-#endif /* local variables moved into u.ai */
+#endif /* local variables moved into u.aj */
- u.ai.n = pOp->p5;
- u.ai.apVal = p->apArg;
- assert( u.ai.apVal || u.ai.n==0 );
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ u.aj.n = pOp->p5;
+ u.aj.apVal = p->apArg;
+ assert( u.aj.apVal || u.aj.n==0 );
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
pOut = &aMem[pOp->p3];
memAboutToChange(p, pOut);
- assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=p->nMem+1) );
- assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ai.n );
- u.ai.pArg = &aMem[pOp->p2];
- for(u.ai.i=0; u.ai.i<u.ai.n; u.ai.i++, u.ai.pArg++){
- assert( memIsValid(u.ai.pArg) );
- u.ai.apVal[u.ai.i] = u.ai.pArg;
- Deephemeralize(u.ai.pArg);
- sqlite3VdbeMemStoreType(u.ai.pArg);
- REGISTER_TRACE(pOp->p2+u.ai.i, u.ai.pArg);
- }
-
- assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
- if( pOp->p4type==P4_FUNCDEF ){
- u.ai.ctx.pFunc = pOp->p4.pFunc;
- u.ai.ctx.pVdbeFunc = 0;
- }else{
- u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
- u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc;
+ assert( u.aj.n==0 || (pOp->p2>0 && pOp->p2+u.aj.n<=(p->nMem-p->nCursor)+1) );
+ assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.aj.n );
+ u.aj.pArg = &aMem[pOp->p2];
+ for(u.aj.i=0; u.aj.i<u.aj.n; u.aj.i++, u.aj.pArg++){
+ assert( memIsValid(u.aj.pArg) );
+ u.aj.apVal[u.aj.i] = u.aj.pArg;
+ Deephemeralize(u.aj.pArg);
+ sqlite3VdbeMemStoreType(u.aj.pArg);
+ REGISTER_TRACE(pOp->p2+u.aj.i, u.aj.pArg);
}
- u.ai.ctx.s.flags = MEM_Null;
- u.ai.ctx.s.db = db;
- u.ai.ctx.s.xDel = 0;
- u.ai.ctx.s.zMalloc = 0;
+ assert( pOp->p4type==P4_FUNCDEF );
+ u.aj.ctx.pFunc = pOp->p4.pFunc;
+ u.aj.ctx.iOp = pc;
+ u.aj.ctx.pVdbe = p;
/* The output cell may already have a buffer allocated. Move
- ** the pointer to u.ai.ctx.s so in case the user-function can use
+ ** the pointer to u.aj.ctx.s so in case the user-function can use
** the already allocated buffer instead of allocating a new one.
*/
- sqlite3VdbeMemMove(&u.ai.ctx.s, pOut);
- MemSetTypeFlag(&u.ai.ctx.s, MEM_Null);
+ memcpy(&u.aj.ctx.s, pOut, sizeof(Mem));
+ pOut->flags = MEM_Null;
+ pOut->xDel = 0;
+ pOut->zMalloc = 0;
+ MemSetTypeFlag(&u.aj.ctx.s, MEM_Null);
- u.ai.ctx.isError = 0;
- if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ u.aj.ctx.fErrorOrAux = 0;
+ if( u.aj.ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
- u.ai.ctx.pColl = pOp[-1].p4.pColl;
+ u.aj.ctx.pColl = pOp[-1].p4.pColl;
}
db->lastRowid = lastRowid;
- (*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */
+ (*u.aj.ctx.pFunc->xFunc)(&u.aj.ctx, u.aj.n, u.aj.apVal); /* IMP: R-24505-23230 */
lastRowid = db->lastRowid;
- /* If any auxiliary data functions have been called by this user function,
- ** immediately call the destructor for any non-static values.
- */
- if( u.ai.ctx.pVdbeFunc ){
- sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1);
- pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc;
- pOp->p4type = P4_VDBEFUNC;
- }
-
if( db->mallocFailed ){
/* Even though a malloc() has failed, the implementation of the
** user function may have called an sqlite3_result_XXX() function
** to return a value. The following call releases any resources
** associated with such a value.
*/
- sqlite3VdbeMemRelease(&u.ai.ctx.s);
+ sqlite3VdbeMemRelease(&u.aj.ctx.s);
goto no_mem;
}
/* If the function returned an error, throw an exception */
- if( u.ai.ctx.isError ){
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
- rc = u.ai.ctx.isError;
+ if( u.aj.ctx.fErrorOrAux ){
+ if( u.aj.ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.aj.ctx.s));
+ rc = u.aj.ctx.isError;
+ }
+ sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
}
/* Copy the result of the function into register P3 */
- sqlite3VdbeChangeEncoding(&u.ai.ctx.s, encoding);
- sqlite3VdbeMemMove(pOut, &u.ai.ctx.s);
+ sqlite3VdbeChangeEncoding(&u.aj.ctx.s, encoding);
+ assert( pOut->flags==MEM_Null );
+ memcpy(pOut, &u.aj.ctx.s, sizeof(Mem));
if( sqlite3VdbeMemTooBig(pOut) ){
goto too_big;
}
@@ -66829,18 +68112,21 @@ case OP_Function: {
}
/* Opcode: BitAnd P1 P2 P3 * *
+** Synopsis: r[P3]=r[P1]&r[P2]
**
** Take the bit-wise AND of the values in register P1 and P2 and
** store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: BitOr P1 P2 P3 * *
+** Synopsis: r[P3]=r[P1]|r[P2]
**
** Take the bit-wise OR of the values in register P1 and P2 and
** store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: ShiftLeft P1 P2 P3 * *
+** Synopsis: r[P3]=r[P2]<<r[P1]
**
** Shift the integer value in register P2 to the left by the
** number of bits specified by the integer in register P1.
@@ -66848,6 +68134,7 @@ case OP_Function: {
** If either input is NULL, the result is NULL.
*/
/* Opcode: ShiftRight P1 P2 P3 * *
+** Synopsis: r[P3]=r[P2]>>r[P1]
**
** Shift the integer value in register P2 to the right by the
** number of bits specified by the integer in register P1.
@@ -66858,12 +68145,12 @@ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */
case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */
case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */
case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
-#if 0 /* local variables moved into u.aj */
+#if 0 /* local variables moved into u.ak */
i64 iA;
u64 uA;
i64 iB;
u8 op;
-#endif /* local variables moved into u.aj */
+#endif /* local variables moved into u.ak */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
@@ -66872,43 +68159,44 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
sqlite3VdbeMemSetNull(pOut);
break;
}
- u.aj.iA = sqlite3VdbeIntValue(pIn2);
- u.aj.iB = sqlite3VdbeIntValue(pIn1);
- u.aj.op = pOp->opcode;
- if( u.aj.op==OP_BitAnd ){
- u.aj.iA &= u.aj.iB;
- }else if( u.aj.op==OP_BitOr ){
- u.aj.iA |= u.aj.iB;
- }else if( u.aj.iB!=0 ){
- assert( u.aj.op==OP_ShiftRight || u.aj.op==OP_ShiftLeft );
+ u.ak.iA = sqlite3VdbeIntValue(pIn2);
+ u.ak.iB = sqlite3VdbeIntValue(pIn1);
+ u.ak.op = pOp->opcode;
+ if( u.ak.op==OP_BitAnd ){
+ u.ak.iA &= u.ak.iB;
+ }else if( u.ak.op==OP_BitOr ){
+ u.ak.iA |= u.ak.iB;
+ }else if( u.ak.iB!=0 ){
+ assert( u.ak.op==OP_ShiftRight || u.ak.op==OP_ShiftLeft );
/* If shifting by a negative amount, shift in the other direction */
- if( u.aj.iB<0 ){
+ if( u.ak.iB<0 ){
assert( OP_ShiftRight==OP_ShiftLeft+1 );
- u.aj.op = 2*OP_ShiftLeft + 1 - u.aj.op;
- u.aj.iB = u.aj.iB>(-64) ? -u.aj.iB : 64;
+ u.ak.op = 2*OP_ShiftLeft + 1 - u.ak.op;
+ u.ak.iB = u.ak.iB>(-64) ? -u.ak.iB : 64;
}
- if( u.aj.iB>=64 ){
- u.aj.iA = (u.aj.iA>=0 || u.aj.op==OP_ShiftLeft) ? 0 : -1;
+ if( u.ak.iB>=64 ){
+ u.ak.iA = (u.ak.iA>=0 || u.ak.op==OP_ShiftLeft) ? 0 : -1;
}else{
- memcpy(&u.aj.uA, &u.aj.iA, sizeof(u.aj.uA));
- if( u.aj.op==OP_ShiftLeft ){
- u.aj.uA <<= u.aj.iB;
+ memcpy(&u.ak.uA, &u.ak.iA, sizeof(u.ak.uA));
+ if( u.ak.op==OP_ShiftLeft ){
+ u.ak.uA <<= u.ak.iB;
}else{
- u.aj.uA >>= u.aj.iB;
+ u.ak.uA >>= u.ak.iB;
/* Sign-extend on a right shift of a negative number */
- if( u.aj.iA<0 ) u.aj.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.aj.iB);
+ if( u.ak.iA<0 ) u.ak.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.ak.iB);
}
- memcpy(&u.aj.iA, &u.aj.uA, sizeof(u.aj.iA));
+ memcpy(&u.ak.iA, &u.ak.uA, sizeof(u.ak.iA));
}
}
- pOut->u.i = u.aj.iA;
+ pOut->u.i = u.ak.iA;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
/* Opcode: AddImm P1 P2 * * *
+** Synopsis: r[P1]=r[P1]+P2
**
** Add the constant P2 to the value in register P1.
** The result is always an integer.
@@ -66932,17 +68220,19 @@ case OP_AddImm: { /* in1 */
*/
case OP_MustBeInt: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
- applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
if( (pIn1->flags & MEM_Int)==0 ){
- if( pOp->p2==0 ){
- rc = SQLITE_MISMATCH;
- goto abort_due_to_error;
- }else{
- pc = pOp->p2 - 1;
+ applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
+ if( (pIn1->flags & MEM_Int)==0 ){
+ if( pOp->p2==0 ){
+ rc = SQLITE_MISMATCH;
+ goto abort_due_to_error;
+ }else{
+ pc = pOp->p2 - 1;
+ break;
+ }
}
- }else{
- MemSetTypeFlag(pIn1, MEM_Int);
}
+ MemSetTypeFlag(pIn1, MEM_Int);
break;
}
@@ -67067,6 +68357,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
#endif /* !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_FLOATING_POINT) */
/* Opcode: Lt P1 P2 P3 P4 P5
+** Synopsis: if r[P1]<r[P3] goto P2
**
** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then
** jump to address P2.
@@ -67101,6 +68392,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
** bit set.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
+** Synopsis: if r[P1]!=r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal. See the Lt opcode for
@@ -67113,6 +68405,7 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
** the SQLITE_NULLEQ flag were omitted from P5.
*/
/* Opcode: Eq P1 P2 P3 P4 P5
+** Synopsis: if r[P1]==r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the operands in registers P1 and P3 are equal.
@@ -67125,18 +68418,21 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
** the SQLITE_NULLEQ flag were omitted from P5.
*/
/* Opcode: Le P1 P2 P3 P4 P5
+** Synopsis: if r[P1]<=r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is less than or equal to the content of
** register P1. See the Lt opcode for additional information.
*/
/* Opcode: Gt P1 P2 P3 P4 P5
+** Synopsis: if r[P1]>r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is greater than the content of
** register P1. See the Lt opcode for additional information.
*/
/* Opcode: Ge P1 P2 P3 P4 P5
+** Synopsis: if r[P1]>=r[P3] goto P2
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is greater than or equal to the content of
@@ -67148,18 +68444,18 @@ case OP_Lt: /* same as TK_LT, jump, in1, in3 */
case OP_Le: /* same as TK_LE, jump, in1, in3 */
case OP_Gt: /* same as TK_GT, jump, in1, in3 */
case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
-#if 0 /* local variables moved into u.ak */
+#if 0 /* local variables moved into u.al */
int res; /* Result of the comparison of pIn1 against pIn3 */
char affinity; /* Affinity to use for comparison */
u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */
-#endif /* local variables moved into u.ak */
+#endif /* local variables moved into u.al */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
- u.ak.flags1 = pIn1->flags;
- u.ak.flags3 = pIn3->flags;
- if( (u.ak.flags1 | u.ak.flags3)&MEM_Null ){
+ u.al.flags1 = pIn1->flags;
+ u.al.flags3 = pIn3->flags;
+ if( (u.al.flags1 | u.al.flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
/* If SQLITE_NULLEQ is set (which will only happen if the operator is
@@ -67167,65 +68463,65 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** or not both operands are null.
*/
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
- assert( (u.ak.flags1 & MEM_Cleared)==0 );
- if( (u.ak.flags1&MEM_Null)!=0
- && (u.ak.flags3&MEM_Null)!=0
- && (u.ak.flags3&MEM_Cleared)==0
+ assert( (u.al.flags1 & MEM_Cleared)==0 );
+ if( (u.al.flags1&MEM_Null)!=0
+ && (u.al.flags3&MEM_Null)!=0
+ && (u.al.flags3&MEM_Cleared)==0
){
- u.ak.res = 0; /* Results are equal */
+ u.al.res = 0; /* Results are equal */
}else{
- u.ak.res = 1; /* Results are not equal */
+ u.al.res = 1; /* Results are not equal */
}
}else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
- if( pOp->p5 & SQLITE_STOREP2 ){
+ if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ pc = pOp->p2-1;
+ }else if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
MemSetTypeFlag(pOut, MEM_Null);
REGISTER_TRACE(pOp->p2, pOut);
- }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
- pc = pOp->p2-1;
}
break;
}
}else{
/* Neither operand is NULL. Do a comparison. */
- u.ak.affinity = pOp->p5 & SQLITE_AFF_MASK;
- if( u.ak.affinity ){
- applyAffinity(pIn1, u.ak.affinity, encoding);
- applyAffinity(pIn3, u.ak.affinity, encoding);
+ u.al.affinity = pOp->p5 & SQLITE_AFF_MASK;
+ if( u.al.affinity ){
+ applyAffinity(pIn1, u.al.affinity, encoding);
+ applyAffinity(pIn3, u.al.affinity, encoding);
if( db->mallocFailed ) goto no_mem;
}
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
ExpandBlob(pIn1);
ExpandBlob(pIn3);
- u.ak.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
+ u.al.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
switch( pOp->opcode ){
- case OP_Eq: u.ak.res = u.ak.res==0; break;
- case OP_Ne: u.ak.res = u.ak.res!=0; break;
- case OP_Lt: u.ak.res = u.ak.res<0; break;
- case OP_Le: u.ak.res = u.ak.res<=0; break;
- case OP_Gt: u.ak.res = u.ak.res>0; break;
- default: u.ak.res = u.ak.res>=0; break;
+ case OP_Eq: u.al.res = u.al.res==0; break;
+ case OP_Ne: u.al.res = u.al.res!=0; break;
+ case OP_Lt: u.al.res = u.al.res<0; break;
+ case OP_Le: u.al.res = u.al.res<=0; break;
+ case OP_Gt: u.al.res = u.al.res>0; break;
+ default: u.al.res = u.al.res>=0; break;
}
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = u.ak.res;
+ pOut->u.i = u.al.res;
REGISTER_TRACE(pOp->p2, pOut);
- }else if( u.ak.res ){
+ }else if( u.al.res ){
pc = pOp->p2-1;
}
/* Undo any changes made by applyAffinity() to the input registers. */
- pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.ak.flags1&MEM_TypeMask);
- pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.ak.flags3&MEM_TypeMask);
+ pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.al.flags1&MEM_TypeMask);
+ pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.al.flags3&MEM_TypeMask);
break;
}
@@ -67265,7 +68561,7 @@ case OP_Permutation: {
** and strings are less than blobs.
*/
case OP_Compare: {
-#if 0 /* local variables moved into u.al */
+#if 0 /* local variables moved into u.am */
int n;
int i;
int p1;
@@ -67274,38 +68570,38 @@ case OP_Compare: {
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
-#endif /* local variables moved into u.al */
+#endif /* local variables moved into u.am */
if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
- u.al.n = pOp->p3;
- u.al.pKeyInfo = pOp->p4.pKeyInfo;
- assert( u.al.n>0 );
- assert( u.al.pKeyInfo!=0 );
- u.al.p1 = pOp->p1;
- u.al.p2 = pOp->p2;
+ u.am.n = pOp->p3;
+ u.am.pKeyInfo = pOp->p4.pKeyInfo;
+ assert( u.am.n>0 );
+ assert( u.am.pKeyInfo!=0 );
+ u.am.p1 = pOp->p1;
+ u.am.p2 = pOp->p2;
#if SQLITE_DEBUG
if( aPermute ){
int k, mx = 0;
- for(k=0; k<u.al.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
- assert( u.al.p1>0 && u.al.p1+mx<=p->nMem+1 );
- assert( u.al.p2>0 && u.al.p2+mx<=p->nMem+1 );
+ for(k=0; k<u.am.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
+ assert( u.am.p1>0 && u.am.p1+mx<=(p->nMem-p->nCursor)+1 );
+ assert( u.am.p2>0 && u.am.p2+mx<=(p->nMem-p->nCursor)+1 );
}else{
- assert( u.al.p1>0 && u.al.p1+u.al.n<=p->nMem+1 );
- assert( u.al.p2>0 && u.al.p2+u.al.n<=p->nMem+1 );
+ assert( u.am.p1>0 && u.am.p1+u.am.n<=(p->nMem-p->nCursor)+1 );
+ assert( u.am.p2>0 && u.am.p2+u.am.n<=(p->nMem-p->nCursor)+1 );
}
#endif /* SQLITE_DEBUG */
- for(u.al.i=0; u.al.i<u.al.n; u.al.i++){
- u.al.idx = aPermute ? aPermute[u.al.i] : u.al.i;
- assert( memIsValid(&aMem[u.al.p1+u.al.idx]) );
- assert( memIsValid(&aMem[u.al.p2+u.al.idx]) );
- REGISTER_TRACE(u.al.p1+u.al.idx, &aMem[u.al.p1+u.al.idx]);
- REGISTER_TRACE(u.al.p2+u.al.idx, &aMem[u.al.p2+u.al.idx]);
- assert( u.al.i<u.al.pKeyInfo->nField );
- u.al.pColl = u.al.pKeyInfo->aColl[u.al.i];
- u.al.bRev = u.al.pKeyInfo->aSortOrder[u.al.i];
- iCompare = sqlite3MemCompare(&aMem[u.al.p1+u.al.idx], &aMem[u.al.p2+u.al.idx], u.al.pColl);
+ for(u.am.i=0; u.am.i<u.am.n; u.am.i++){
+ u.am.idx = aPermute ? aPermute[u.am.i] : u.am.i;
+ assert( memIsValid(&aMem[u.am.p1+u.am.idx]) );
+ assert( memIsValid(&aMem[u.am.p2+u.am.idx]) );
+ REGISTER_TRACE(u.am.p1+u.am.idx, &aMem[u.am.p1+u.am.idx]);
+ REGISTER_TRACE(u.am.p2+u.am.idx, &aMem[u.am.p2+u.am.idx]);
+ assert( u.am.i<u.am.pKeyInfo->nField );
+ u.am.pColl = u.am.pKeyInfo->aColl[u.am.i];
+ u.am.bRev = u.am.pKeyInfo->aSortOrder[u.am.i];
+ iCompare = sqlite3MemCompare(&aMem[u.am.p1+u.am.idx], &aMem[u.am.p2+u.am.idx], u.am.pColl);
if( iCompare ){
- if( u.al.bRev ) iCompare = -iCompare;
+ if( u.am.bRev ) iCompare = -iCompare;
break;
}
}
@@ -67331,6 +68627,7 @@ case OP_Jump: { /* jump */
}
/* Opcode: And P1 P2 P3 * *
+** Synopsis: r[P3]=(r[P1] && r[P2])
**
** Take the logical AND of the values in registers P1 and P2 and
** write the result into register P3.
@@ -67340,6 +68637,7 @@ case OP_Jump: { /* jump */
** a NULL output.
*/
/* Opcode: Or P1 P2 P3 * *
+** Synopsis: r[P3]=(r[P1] || r[P2])
**
** Take the logical OR of the values in register P1 and P2 and
** store the answer in register P3.
@@ -67350,41 +68648,42 @@ case OP_Jump: { /* jump */
*/
case OP_And: /* same as TK_AND, in1, in2, out3 */
case OP_Or: { /* same as TK_OR, in1, in2, out3 */
-#if 0 /* local variables moved into u.am */
+#if 0 /* local variables moved into u.an */
int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-#endif /* local variables moved into u.am */
+#endif /* local variables moved into u.an */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ){
- u.am.v1 = 2;
+ u.an.v1 = 2;
}else{
- u.am.v1 = sqlite3VdbeIntValue(pIn1)!=0;
+ u.an.v1 = sqlite3VdbeIntValue(pIn1)!=0;
}
pIn2 = &aMem[pOp->p2];
if( pIn2->flags & MEM_Null ){
- u.am.v2 = 2;
+ u.an.v2 = 2;
}else{
- u.am.v2 = sqlite3VdbeIntValue(pIn2)!=0;
+ u.an.v2 = sqlite3VdbeIntValue(pIn2)!=0;
}
if( pOp->opcode==OP_And ){
static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
- u.am.v1 = and_logic[u.am.v1*3+u.am.v2];
+ u.an.v1 = and_logic[u.an.v1*3+u.an.v2];
}else{
static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
- u.am.v1 = or_logic[u.am.v1*3+u.am.v2];
+ u.an.v1 = or_logic[u.an.v1*3+u.an.v2];
}
pOut = &aMem[pOp->p3];
- if( u.am.v1==2 ){
+ if( u.an.v1==2 ){
MemSetTypeFlag(pOut, MEM_Null);
}else{
- pOut->u.i = u.am.v1;
+ pOut->u.i = u.an.v1;
MemSetTypeFlag(pOut, MEM_Int);
}
break;
}
/* Opcode: Not P1 P2 * * *
+** Synopsis: r[P2]= !r[P1]
**
** Interpret the value in register P1 as a boolean value. Store the
** boolean complement in register P2. If the value in register P1 is
@@ -67402,6 +68701,7 @@ case OP_Not: { /* same as TK_NOT, in1, out2 */
}
/* Opcode: BitNot P1 P2 * * *
+** Synopsis: r[P1]= ~r[P1]
**
** Interpret the content of register P1 as an integer. Store the
** ones-complement of the P1 value into register P2. If P1 holds
@@ -67447,27 +68747,28 @@ case OP_Once: { /* jump */
*/
case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
-#if 0 /* local variables moved into u.an */
+#if 0 /* local variables moved into u.ao */
int c;
-#endif /* local variables moved into u.an */
+#endif /* local variables moved into u.ao */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ){
- u.an.c = pOp->p3;
+ u.ao.c = pOp->p3;
}else{
#ifdef SQLITE_OMIT_FLOATING_POINT
- u.an.c = sqlite3VdbeIntValue(pIn1)!=0;
+ u.ao.c = sqlite3VdbeIntValue(pIn1)!=0;
#else
- u.an.c = sqlite3VdbeRealValue(pIn1)!=0.0;
+ u.ao.c = sqlite3VdbeRealValue(pIn1)!=0.0;
#endif
- if( pOp->opcode==OP_IfNot ) u.an.c = !u.an.c;
+ if( pOp->opcode==OP_IfNot ) u.ao.c = !u.ao.c;
}
- if( u.an.c ){
+ if( u.ao.c ){
pc = pOp->p2-1;
}
break;
}
/* Opcode: IsNull P1 P2 * * *
+** Synopsis: if r[P1]==NULL goto P2
**
** Jump to P2 if the value in register P1 is NULL.
*/
@@ -67480,6 +68781,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
}
/* Opcode: NotNull P1 P2 * * *
+** Synopsis: if r[P1]!=NULL goto P2
**
** Jump to P2 if the value in register P1 is not NULL.
*/
@@ -67492,6 +68794,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
}
/* Opcode: Column P1 P2 P3 P4 P5
+** Synopsis: r[P3]=PX
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction. (See the MakeRecord opcode for additional
@@ -67516,155 +68819,105 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** skipped for length() and all content loading can be skipped for typeof().
*/
case OP_Column: {
-#if 0 /* local variables moved into u.ao */
- u32 payloadSize; /* Number of bytes in the record */
+#if 0 /* local variables moved into u.ap */
i64 payloadSize64; /* Number of bytes in the record */
- int p1; /* P1 value of the opcode */
int p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
- char *zRec; /* Pointer to complete record-data */
BtCursor *pCrsr; /* The BTree cursor */
u32 *aType; /* aType[i] holds the numeric type of the i-th column */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
- int nField; /* number of fields in the record */
int len; /* The length of the serialized data for the column */
int i; /* Loop counter */
- char *zData; /* Part of the record being decoded */
Mem *pDest; /* Where to write the extracted value */
Mem sMem; /* For storing the record being decoded */
- u8 *zIdx; /* Index into header */
- u8 *zEndHdr; /* Pointer to first byte after the header */
+ const u8 *zData; /* Part of the record being decoded */
+ const u8 *zHdr; /* Next unparsed byte of the header */
+ const u8 *zEndHdr; /* Pointer to first byte after the header */
u32 offset; /* Offset into the data */
u32 szField; /* Number of bytes in the content of a field */
- int szHdr; /* Size of the header size field at start of record */
- int avail; /* Number of bytes of available data */
+ u32 avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
-#endif /* local variables moved into u.ao */
-
-
- u.ao.p1 = pOp->p1;
- u.ao.p2 = pOp->p2;
- u.ao.pC = 0;
- memset(&u.ao.sMem, 0, sizeof(u.ao.sMem));
- assert( u.ao.p1<p->nCursor );
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.ao.pDest = &aMem[pOp->p3];
- memAboutToChange(p, u.ao.pDest);
- u.ao.zRec = 0;
+#endif /* local variables moved into u.ap */
- /* This block sets the variable u.ao.payloadSize to be the total number of
- ** bytes in the record.
- **
- ** u.ao.zRec is set to be the complete text of the record if it is available.
- ** The complete record text is always available for pseudo-tables
- ** If the record is stored in a cursor, the complete record text
- ** might be available in the u.ao.pC->aRow cache. Or it might not be.
- ** If the data is unavailable, u.ao.zRec is set to NULL.
- **
- ** We also compute the number of columns in the record. For cursors,
- ** the number of columns is stored in the VdbeCursor.nField element.
- */
- u.ao.pC = p->apCsr[u.ao.p1];
- assert( u.ao.pC!=0 );
+ u.ap.p2 = pOp->p2;
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
+ u.ap.pDest = &aMem[pOp->p3];
+ memAboutToChange(p, u.ap.pDest);
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.ap.pC = p->apCsr[pOp->p1];
+ assert( u.ap.pC!=0 );
+ assert( u.ap.p2<u.ap.pC->nField );
+ u.ap.aType = u.ap.pC->aType;
+ u.ap.aOffset = u.ap.aType + u.ap.pC->nField;
#ifndef SQLITE_OMIT_VIRTUALTABLE
- assert( u.ao.pC->pVtabCursor==0 );
-#endif
- u.ao.pCrsr = u.ao.pC->pCursor;
- if( u.ao.pCrsr!=0 ){
- /* The record is stored in a B-Tree */
- rc = sqlite3VdbeCursorMoveto(u.ao.pC);
- if( rc ) goto abort_due_to_error;
- if( u.ao.pC->nullRow ){
- u.ao.payloadSize = 0;
- }else if( u.ao.pC->cacheStatus==p->cacheCtr ){
- u.ao.payloadSize = u.ao.pC->payloadSize;
- u.ao.zRec = (char*)u.ao.pC->aRow;
- }else if( u.ao.pC->isIndex ){
- assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
- VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ao.pCrsr, &u.ao.payloadSize64);
- assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
- /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
- ** payload size, so it is impossible for u.ao.payloadSize64 to be
- ** larger than 32 bits. */
- assert( (u.ao.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ao.payloadSize64 );
- u.ao.payloadSize = (u32)u.ao.payloadSize64;
- }else{
- assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
- VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize);
- assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
- }
- }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){
- u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg];
- if( u.ao.pC->multiPseudo ){
- sqlite3VdbeMemShallowCopy(u.ao.pDest, u.ao.pReg+u.ao.p2, MEM_Ephem);
- Deephemeralize(u.ao.pDest);
- goto op_column_out;
- }
- assert( u.ao.pReg->flags & MEM_Blob );
- assert( memIsValid(u.ao.pReg) );
- u.ao.payloadSize = u.ao.pReg->n;
- u.ao.zRec = u.ao.pReg->z;
- u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
- assert( u.ao.payloadSize==0 || u.ao.zRec!=0 );
- }else{
- /* Consider the row to be NULL */
- u.ao.payloadSize = 0;
- }
-
- /* If u.ao.payloadSize is 0, then just store a NULL. This can happen because of
- ** nullRow or because of a corrupt database. */
- if( u.ao.payloadSize==0 ){
- MemSetTypeFlag(u.ao.pDest, MEM_Null);
- goto op_column_out;
- }
- assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
- if( u.ao.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
-
- u.ao.nField = u.ao.pC->nField;
- assert( u.ao.p2<u.ao.nField );
-
- /* Read and parse the table header. Store the results of the parse
- ** into the record header cache fields of the cursor.
- */
- u.ao.aType = u.ao.pC->aType;
- if( u.ao.pC->cacheStatus==p->cacheCtr ){
- u.ao.aOffset = u.ao.pC->aOffset;
- }else{
- assert(u.ao.aType);
- u.ao.avail = 0;
- u.ao.pC->aOffset = u.ao.aOffset = &u.ao.aType[u.ao.nField];
- u.ao.pC->payloadSize = u.ao.payloadSize;
- u.ao.pC->cacheStatus = p->cacheCtr;
-
- /* Figure out how many bytes are in the header */
- if( u.ao.zRec ){
- u.ao.zData = u.ao.zRec;
- }else{
- if( u.ao.pC->isIndex ){
- u.ao.zData = (char*)sqlite3BtreeKeyFetch(u.ao.pCrsr, &u.ao.avail);
+ assert( u.ap.pC->pVtabCursor==0 ); /* OP_Column never called on virtual table */
+#endif
+ u.ap.pCrsr = u.ap.pC->pCursor;
+ assert( u.ap.pCrsr!=0 || u.ap.pC->pseudoTableReg>0 ); /* u.ap.pCrsr NULL on PseudoTables */
+ assert( u.ap.pCrsr!=0 || u.ap.pC->nullRow ); /* u.ap.pC->nullRow on PseudoTables */
+
+ /* If the cursor cache is stale, bring it up-to-date */
+ rc = sqlite3VdbeCursorMoveto(u.ap.pC);
+ if( rc ) goto abort_due_to_error;
+ if( u.ap.pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){
+ if( u.ap.pC->nullRow ){
+ if( u.ap.pCrsr==0 ){
+ assert( u.ap.pC->pseudoTableReg>0 );
+ u.ap.pReg = &aMem[u.ap.pC->pseudoTableReg];
+ if( u.ap.pC->multiPseudo ){
+ sqlite3VdbeMemShallowCopy(u.ap.pDest, u.ap.pReg+u.ap.p2, MEM_Ephem);
+ Deephemeralize(u.ap.pDest);
+ goto op_column_out;
+ }
+ assert( u.ap.pReg->flags & MEM_Blob );
+ assert( memIsValid(u.ap.pReg) );
+ u.ap.pC->payloadSize = u.ap.pC->szRow = u.ap.avail = u.ap.pReg->n;
+ u.ap.pC->aRow = (u8*)u.ap.pReg->z;
}else{
- u.ao.zData = (char*)sqlite3BtreeDataFetch(u.ao.pCrsr, &u.ao.avail);
+ MemSetTypeFlag(u.ap.pDest, MEM_Null);
+ goto op_column_out;
}
- /* If KeyFetch()/DataFetch() managed to get the entire payload,
- ** save the payload in the u.ao.pC->aRow cache. That will save us from
- ** having to make additional calls to fetch the content portion of
- ** the record.
- */
- assert( u.ao.avail>=0 );
- if( u.ao.payloadSize <= (u32)u.ao.avail ){
- u.ao.zRec = u.ao.zData;
- u.ao.pC->aRow = (u8*)u.ao.zData;
+ }else{
+ assert( u.ap.pCrsr );
+ if( u.ap.pC->isTable==0 ){
+ assert( sqlite3BtreeCursorIsValid(u.ap.pCrsr) );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ap.pCrsr, &u.ap.payloadSize64);
+ assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
+ /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
+ ** payload size, so it is impossible for u.ap.payloadSize64 to be
+ ** larger than 32 bits. */
+ assert( (u.ap.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ap.payloadSize64 );
+ u.ap.pC->aRow = sqlite3BtreeKeyFetch(u.ap.pCrsr, &u.ap.avail);
+ u.ap.pC->payloadSize = (u32)u.ap.payloadSize64;
+ }else{
+ assert( sqlite3BtreeCursorIsValid(u.ap.pCrsr) );
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ap.pCrsr, &u.ap.pC->payloadSize);
+ assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
+ u.ap.pC->aRow = sqlite3BtreeDataFetch(u.ap.pCrsr, &u.ap.avail);
+ }
+ assert( u.ap.avail<=65536 ); /* Maximum page size is 64KiB */
+ if( u.ap.pC->payloadSize <= (u32)u.ap.avail ){
+ u.ap.pC->szRow = u.ap.pC->payloadSize;
}else{
- u.ao.pC->aRow = 0;
+ u.ap.pC->szRow = u.ap.avail;
}
+ if( u.ap.pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ goto too_big;
+ }
+ }
+ u.ap.pC->cacheStatus = p->cacheCtr;
+ u.ap.pC->iHdrOffset = getVarint32(u.ap.pC->aRow, u.ap.offset);
+ u.ap.pC->nHdrParsed = 0;
+ u.ap.aOffset[0] = u.ap.offset;
+ if( u.ap.avail<u.ap.offset ){
+ /* u.ap.pC->aRow does not have to hold the entire row, but it does at least
+ ** need to cover the header of the record. If u.ap.pC->aRow does not contain
+ ** the complete header, then set it to zero, forcing the header to be
+ ** dynamically allocated. */
+ u.ap.pC->aRow = 0;
+ u.ap.pC->szRow = 0;
}
- /* The following assert is true in all cases except when
- ** the database file has been corrupted externally.
- ** assert( u.ao.zRec!=0 || u.ao.avail>=u.ao.payloadSize || u.ao.avail>=9 ); */
- u.ao.szHdr = getVarint32((u8*)u.ao.zData, u.ao.offset);
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
@@ -67675,161 +68928,155 @@ case OP_Column: {
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
- if( u.ao.offset > 98307 ){
+ if( u.ap.offset > 98307 || u.ap.offset > u.ap.pC->payloadSize ){
rc = SQLITE_CORRUPT_BKPT;
- goto op_column_out;
+ goto op_column_error;
}
+ }
- /* Compute in u.ao.len the number of bytes of data we need to read in order
- ** to get u.ao.nField type values. u.ao.offset is an upper bound on this. But
- ** u.ao.nField might be significantly less than the true number of columns
- ** in the table, and in that case, 5*u.ao.nField+3 might be smaller than u.ao.offset.
- ** We want to minimize u.ao.len in order to limit the size of the memory
- ** allocation, especially if a corrupt database file has caused u.ao.offset
- ** to be oversized. Offset is limited to 98307 above. But 98307 might
- ** still exceed Robson memory allocation limits on some configurations.
- ** On systems that cannot tolerate large memory allocations, u.ao.nField*5+3
- ** will likely be much smaller since u.ao.nField will likely be less than
- ** 20 or so. This insures that Robson memory allocation limits are
- ** not exceeded even for corrupt database files.
- */
- u.ao.len = u.ao.nField*5 + 3;
- if( u.ao.len > (int)u.ao.offset ) u.ao.len = (int)u.ao.offset;
-
- /* The KeyFetch() or DataFetch() above are fast and will get the entire
- ** record header in most cases. But they will fail to get the complete
- ** record header if the record header does not fit on a single page
- ** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to
- ** acquire the complete header text.
+ /* Make sure at least the first u.ap.p2+1 entries of the header have been
+ ** parsed and valid information is in u.ap.aOffset[] and u.ap.aType[].
+ */
+ if( u.ap.pC->nHdrParsed<=u.ap.p2 ){
+ /* If there is more header available for parsing in the record, try
+ ** to extract additional fields up through the u.ap.p2+1-th field
*/
- if( !u.ao.zRec && u.ao.avail<u.ao.len ){
- u.ao.sMem.flags = 0;
- u.ao.sMem.db = 0;
- rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, 0, u.ao.len, u.ao.pC->isIndex, &u.ao.sMem);
- if( rc!=SQLITE_OK ){
- goto op_column_out;
+ if( u.ap.pC->iHdrOffset<u.ap.aOffset[0] ){
+ /* Make sure u.ap.zData points to enough of the record to cover the header. */
+ if( u.ap.pC->aRow==0 ){
+ memset(&u.ap.sMem, 0, sizeof(u.ap.sMem));
+ rc = sqlite3VdbeMemFromBtree(u.ap.pCrsr, 0, u.ap.aOffset[0],
+ !u.ap.pC->isTable, &u.ap.sMem);
+ if( rc!=SQLITE_OK ){
+ goto op_column_error;
+ }
+ u.ap.zData = (u8*)u.ap.sMem.z;
+ }else{
+ u.ap.zData = u.ap.pC->aRow;
}
- u.ao.zData = u.ao.sMem.z;
- }
- u.ao.zEndHdr = (u8 *)&u.ao.zData[u.ao.len];
- u.ao.zIdx = (u8 *)&u.ao.zData[u.ao.szHdr];
- /* Scan the header and use it to fill in the u.ao.aType[] and u.ao.aOffset[]
- ** arrays. u.ao.aType[u.ao.i] will contain the type integer for the u.ao.i-th
- ** column and u.ao.aOffset[u.ao.i] will contain the u.ao.offset from the beginning
- ** of the record to the start of the data for the u.ao.i-th column
- */
- for(u.ao.i=0; u.ao.i<u.ao.nField; u.ao.i++){
- if( u.ao.zIdx<u.ao.zEndHdr ){
- u.ao.aOffset[u.ao.i] = u.ao.offset;
- if( u.ao.zIdx[0]<0x80 ){
- u.ao.t = u.ao.zIdx[0];
- u.ao.zIdx++;
+ /* Fill in u.ap.aType[u.ap.i] and u.ap.aOffset[u.ap.i] values through the u.ap.p2-th field. */
+ u.ap.i = u.ap.pC->nHdrParsed;
+ u.ap.offset = u.ap.aOffset[u.ap.i];
+ u.ap.zHdr = u.ap.zData + u.ap.pC->iHdrOffset;
+ u.ap.zEndHdr = u.ap.zData + u.ap.aOffset[0];
+ assert( u.ap.i<=u.ap.p2 && u.ap.zHdr<u.ap.zEndHdr );
+ do{
+ if( u.ap.zHdr[0]<0x80 ){
+ u.ap.t = u.ap.zHdr[0];
+ u.ap.zHdr++;
}else{
- u.ao.zIdx += sqlite3GetVarint32(u.ao.zIdx, &u.ao.t);
+ u.ap.zHdr += sqlite3GetVarint32(u.ap.zHdr, &u.ap.t);
}
- u.ao.aType[u.ao.i] = u.ao.t;
- u.ao.szField = sqlite3VdbeSerialTypeLen(u.ao.t);
- u.ao.offset += u.ao.szField;
- if( u.ao.offset<u.ao.szField ){ /* True if u.ao.offset overflows */
- u.ao.zIdx = &u.ao.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
+ u.ap.aType[u.ap.i] = u.ap.t;
+ u.ap.szField = sqlite3VdbeSerialTypeLen(u.ap.t);
+ u.ap.offset += u.ap.szField;
+ if( u.ap.offset<u.ap.szField ){ /* True if u.ap.offset overflows */
+ u.ap.zHdr = &u.ap.zEndHdr[1]; /* Forces SQLITE_CORRUPT return below */
break;
}
- }else{
- /* If u.ao.i is less that u.ao.nField, then there are fewer fields in this
- ** record than SetNumColumns indicated there are columns in the
- ** table. Set the u.ao.offset for any extra columns not present in
- ** the record to 0. This tells code below to store the default value
- ** for the column instead of deserializing a value from the record.
- */
- u.ao.aOffset[u.ao.i] = 0;
+ u.ap.i++;
+ u.ap.aOffset[u.ap.i] = u.ap.offset;
+ }while( u.ap.i<=u.ap.p2 && u.ap.zHdr<u.ap.zEndHdr );
+ u.ap.pC->nHdrParsed = u.ap.i;
+ u.ap.pC->iHdrOffset = (u32)(u.ap.zHdr - u.ap.zData);
+ if( u.ap.pC->aRow==0 ){
+ sqlite3VdbeMemRelease(&u.ap.sMem);
+ u.ap.sMem.flags = MEM_Null;
+ }
+
+ /* If we have read more header data than was contained in the header,
+ ** or if the end of the last field appears to be past the end of the
+ ** record, or if the end of the last field appears to be before the end
+ ** of the record (when all fields present), then we must be dealing
+ ** with a corrupt database.
+ */
+ if( (u.ap.zHdr > u.ap.zEndHdr)
+ || (u.ap.offset > u.ap.pC->payloadSize)
+ || (u.ap.zHdr==u.ap.zEndHdr && u.ap.offset!=u.ap.pC->payloadSize)
+ ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto op_column_error;
}
}
- sqlite3VdbeMemRelease(&u.ao.sMem);
- u.ao.sMem.flags = MEM_Null;
- /* If we have read more header data than was contained in the header,
- ** or if the end of the last field appears to be past the end of the
- ** record, or if the end of the last field appears to be before the end
- ** of the record (when all fields present), then we must be dealing
- ** with a corrupt database.
+ /* If after trying to extra new entries from the header, nHdrParsed is
+ ** still not up to u.ap.p2, that means that the record has fewer than u.ap.p2
+ ** columns. So the result will be either the default value or a NULL.
*/
- if( (u.ao.zIdx > u.ao.zEndHdr) || (u.ao.offset > u.ao.payloadSize)
- || (u.ao.zIdx==u.ao.zEndHdr && u.ao.offset!=u.ao.payloadSize) ){
- rc = SQLITE_CORRUPT_BKPT;
+ if( u.ap.pC->nHdrParsed<=u.ap.p2 ){
+ if( pOp->p4type==P4_MEM ){
+ sqlite3VdbeMemShallowCopy(u.ap.pDest, pOp->p4.pMem, MEM_Static);
+ }else{
+ MemSetTypeFlag(u.ap.pDest, MEM_Null);
+ }
goto op_column_out;
}
}
- /* Get the column information. If u.ao.aOffset[u.ao.p2] is non-zero, then
- ** deserialize the value from the record. If u.ao.aOffset[u.ao.p2] is zero,
- ** then there are not enough fields in the record to satisfy the
- ** request. In this case, set the value NULL or to P4 if P4 is
- ** a pointer to a Mem object.
+ /* Extract the content for the u.ap.p2+1-th column. Control can only
+ ** reach this point if u.ap.aOffset[u.ap.p2], u.ap.aOffset[u.ap.p2+1], and u.ap.aType[u.ap.p2] are
+ ** all valid.
*/
- if( u.ao.aOffset[u.ao.p2] ){
- assert( rc==SQLITE_OK );
- if( u.ao.zRec ){
- /* This is the common case where the whole row fits on a single page */
- VdbeMemRelease(u.ao.pDest);
- sqlite3VdbeSerialGet((u8 *)&u.ao.zRec[u.ao.aOffset[u.ao.p2]], u.ao.aType[u.ao.p2], u.ao.pDest);
+ assert( u.ap.p2<u.ap.pC->nHdrParsed );
+ assert( rc==SQLITE_OK );
+ if( u.ap.pC->szRow>=u.ap.aOffset[u.ap.p2+1] ){
+ /* This is the common case where the desired content fits on the original
+ ** page - where the content is not on an overflow page */
+ VdbeMemRelease(u.ap.pDest);
+ sqlite3VdbeSerialGet(u.ap.pC->aRow+u.ap.aOffset[u.ap.p2], u.ap.aType[u.ap.p2], u.ap.pDest);
+ }else{
+ /* This branch happens only when content is on overflow pages */
+ u.ap.t = u.ap.aType[u.ap.p2];
+ if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
+ && ((u.ap.t>=12 && (u.ap.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
+ || (u.ap.len = sqlite3VdbeSerialTypeLen(u.ap.t))==0
+ ){
+ /* Content is irrelevant for the typeof() function and for
+ ** the length(X) function if X is a blob. So we might as well use
+ ** bogus content rather than reading content from disk. NULL works
+ ** for text and blob and whatever is in the u.ap.payloadSize64 variable
+ ** will work for everything else. Content is also irrelevant if
+ ** the content length is 0. */
+ u.ap.zData = u.ap.t<=13 ? (u8*)&u.ap.payloadSize64 : 0;
+ u.ap.sMem.zMalloc = 0;
}else{
- /* This branch happens only when the row overflows onto multiple pages */
- u.ao.t = u.ao.aType[u.ao.p2];
- if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
- && ((u.ao.t>=12 && (u.ao.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
- ){
- /* Content is irrelevant for the typeof() function and for
- ** the length(X) function if X is a blob. So we might as well use
- ** bogus content rather than reading content from disk. NULL works
- ** for text and blob and whatever is in the u.ao.payloadSize64 variable
- ** will work for everything else. */
- u.ao.zData = u.ao.t<12 ? (char*)&u.ao.payloadSize64 : 0;
- }else{
- u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.t);
- sqlite3VdbeMemMove(&u.ao.sMem, u.ao.pDest);
- rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, u.ao.aOffset[u.ao.p2], u.ao.len, u.ao.pC->isIndex,
- &u.ao.sMem);
- if( rc!=SQLITE_OK ){
- goto op_column_out;
- }
- u.ao.zData = u.ao.sMem.z;
+ memset(&u.ap.sMem, 0, sizeof(u.ap.sMem));
+ sqlite3VdbeMemMove(&u.ap.sMem, u.ap.pDest);
+ rc = sqlite3VdbeMemFromBtree(u.ap.pCrsr, u.ap.aOffset[u.ap.p2], u.ap.len, !u.ap.pC->isTable,
+ &u.ap.sMem);
+ if( rc!=SQLITE_OK ){
+ goto op_column_error;
}
- sqlite3VdbeSerialGet((u8*)u.ao.zData, u.ao.t, u.ao.pDest);
+ u.ap.zData = (u8*)u.ap.sMem.z;
}
- u.ao.pDest->enc = encoding;
- }else{
- if( pOp->p4type==P4_MEM ){
- sqlite3VdbeMemShallowCopy(u.ao.pDest, pOp->p4.pMem, MEM_Static);
- }else{
- MemSetTypeFlag(u.ao.pDest, MEM_Null);
+ sqlite3VdbeSerialGet(u.ap.zData, u.ap.t, u.ap.pDest);
+ /* If we dynamically allocated space to hold the data (in the
+ ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
+ ** dynamically allocated space over to the u.ap.pDest structure.
+ ** This prevents a memory copy. */
+ if( u.ap.sMem.zMalloc ){
+ assert( u.ap.sMem.z==u.ap.sMem.zMalloc );
+ assert( !(u.ap.pDest->flags & MEM_Dyn) );
+ assert( !(u.ap.pDest->flags & (MEM_Blob|MEM_Str)) || u.ap.pDest->z==u.ap.sMem.z );
+ u.ap.pDest->flags &= ~(MEM_Ephem|MEM_Static);
+ u.ap.pDest->flags |= MEM_Term;
+ u.ap.pDest->z = u.ap.sMem.z;
+ u.ap.pDest->zMalloc = u.ap.sMem.zMalloc;
}
}
-
- /* If we dynamically allocated space to hold the data (in the
- ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
- ** dynamically allocated space over to the u.ao.pDest structure.
- ** This prevents a memory copy.
- */
- if( u.ao.sMem.zMalloc ){
- assert( u.ao.sMem.z==u.ao.sMem.zMalloc );
- assert( !(u.ao.pDest->flags & MEM_Dyn) );
- assert( !(u.ao.pDest->flags & (MEM_Blob|MEM_Str)) || u.ao.pDest->z==u.ao.sMem.z );
- u.ao.pDest->flags &= ~(MEM_Ephem|MEM_Static);
- u.ao.pDest->flags |= MEM_Term;
- u.ao.pDest->z = u.ao.sMem.z;
- u.ao.pDest->zMalloc = u.ao.sMem.zMalloc;
- }
-
- rc = sqlite3VdbeMemMakeWriteable(u.ao.pDest);
+ u.ap.pDest->enc = encoding;
op_column_out:
- UPDATE_MAX_BLOBSIZE(u.ao.pDest);
- REGISTER_TRACE(pOp->p3, u.ao.pDest);
+ rc = sqlite3VdbeMemMakeWriteable(u.ap.pDest);
+op_column_error:
+ UPDATE_MAX_BLOBSIZE(u.ap.pDest);
+ REGISTER_TRACE(pOp->p3, u.ap.pDest);
break;
}
/* Opcode: Affinity P1 P2 * P4 *
+** Synopsis: affinity(r[P1@P2])
**
** Apply affinities to a range of P2 registers starting with P1.
**
@@ -67838,26 +69085,27 @@ op_column_out:
** memory cell in the range.
*/
case OP_Affinity: {
-#if 0 /* local variables moved into u.ap */
+#if 0 /* local variables moved into u.aq */
const char *zAffinity; /* The affinity to be applied */
char cAff; /* A single character of affinity */
-#endif /* local variables moved into u.ap */
+#endif /* local variables moved into u.aq */
- u.ap.zAffinity = pOp->p4.z;
- assert( u.ap.zAffinity!=0 );
- assert( u.ap.zAffinity[pOp->p2]==0 );
+ u.aq.zAffinity = pOp->p4.z;
+ assert( u.aq.zAffinity!=0 );
+ assert( u.aq.zAffinity[pOp->p2]==0 );
pIn1 = &aMem[pOp->p1];
- while( (u.ap.cAff = *(u.ap.zAffinity++))!=0 ){
- assert( pIn1 <= &p->aMem[p->nMem] );
+ while( (u.aq.cAff = *(u.aq.zAffinity++))!=0 ){
+ assert( pIn1 <= &p->aMem[(p->nMem-p->nCursor)] );
assert( memIsValid(pIn1) );
ExpandBlob(pIn1);
- applyAffinity(pIn1, u.ap.cAff, encoding);
+ applyAffinity(pIn1, u.aq.cAff, encoding);
pIn1++;
}
break;
}
/* Opcode: MakeRecord P1 P2 P3 P4 *
+** Synopsis: r[P3]=mkrec(r[P1@P2])
**
** Convert P2 registers beginning with P1 into the [record format]
** use as a data record in a database table or as a key
@@ -67873,7 +69121,7 @@ case OP_Affinity: {
** If P4 is NULL then all index fields have the affinity NONE.
*/
case OP_MakeRecord: {
-#if 0 /* local variables moved into u.aq */
+#if 0 /* local variables moved into u.ar */
u8 *zNewRecord; /* A buffer to hold the data for the new record */
Mem *pRec; /* The new record */
u64 nData; /* Number of bytes of data space */
@@ -67889,7 +69137,7 @@ case OP_MakeRecord: {
int file_format; /* File format to use for encoding */
int i; /* Space used in zNewRecord[] */
int len; /* Length of a field */
-#endif /* local variables moved into u.aq */
+#endif /* local variables moved into u.ar */
/* Assuming the record contains N fields, the record format looks
** like this:
@@ -67906,16 +69154,16 @@ case OP_MakeRecord: {
** hdr-size field is also a varint which is the offset from the beginning
** of the record to data0.
*/
- u.aq.nData = 0; /* Number of bytes of data space */
- u.aq.nHdr = 0; /* Number of bytes of header space */
- u.aq.nZero = 0; /* Number of zero bytes at the end of the record */
- u.aq.nField = pOp->p1;
- u.aq.zAffinity = pOp->p4.z;
- assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=p->nMem+1 );
- u.aq.pData0 = &aMem[u.aq.nField];
- u.aq.nField = pOp->p2;
- u.aq.pLast = &u.aq.pData0[u.aq.nField-1];
- u.aq.file_format = p->minWriteFileFormat;
+ u.ar.nData = 0; /* Number of bytes of data space */
+ u.ar.nHdr = 0; /* Number of bytes of header space */
+ u.ar.nZero = 0; /* Number of zero bytes at the end of the record */
+ u.ar.nField = pOp->p1;
+ u.ar.zAffinity = pOp->p4.z;
+ assert( u.ar.nField>0 && pOp->p2>0 && pOp->p2+u.ar.nField<=(p->nMem-p->nCursor)+1 );
+ u.ar.pData0 = &aMem[u.ar.nField];
+ u.ar.nField = pOp->p2;
+ u.ar.pLast = &u.ar.pData0[u.ar.nField-1];
+ u.ar.file_format = p->minWriteFileFormat;
/* Identify the output register */
assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
@@ -67925,34 +69173,34 @@ case OP_MakeRecord: {
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
- for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
- assert( memIsValid(u.aq.pRec) );
- if( u.aq.zAffinity ){
- applyAffinity(u.aq.pRec, u.aq.zAffinity[u.aq.pRec-u.aq.pData0], encoding);
+ for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){
+ assert( memIsValid(u.ar.pRec) );
+ if( u.ar.zAffinity ){
+ applyAffinity(u.ar.pRec, u.ar.zAffinity[u.ar.pRec-u.ar.pData0], encoding);
}
- if( u.aq.pRec->flags&MEM_Zero && u.aq.pRec->n>0 ){
- sqlite3VdbeMemExpandBlob(u.aq.pRec);
+ if( u.ar.pRec->flags&MEM_Zero && u.ar.pRec->n>0 ){
+ sqlite3VdbeMemExpandBlob(u.ar.pRec);
}
- u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
- u.aq.len = sqlite3VdbeSerialTypeLen(u.aq.serial_type);
- u.aq.nData += u.aq.len;
- u.aq.nHdr += sqlite3VarintLen(u.aq.serial_type);
- if( u.aq.pRec->flags & MEM_Zero ){
+ u.ar.serial_type = sqlite3VdbeSerialType(u.ar.pRec, u.ar.file_format);
+ u.ar.len = sqlite3VdbeSerialTypeLen(u.ar.serial_type);
+ u.ar.nData += u.ar.len;
+ u.ar.nHdr += sqlite3VarintLen(u.ar.serial_type);
+ if( u.ar.pRec->flags & MEM_Zero ){
/* Only pure zero-filled BLOBs can be input to this Opcode.
** We do not allow blobs with a prefix and a zero-filled tail. */
- u.aq.nZero += u.aq.pRec->u.nZero;
- }else if( u.aq.len ){
- u.aq.nZero = 0;
+ u.ar.nZero += u.ar.pRec->u.nZero;
+ }else if( u.ar.len ){
+ u.ar.nZero = 0;
}
}
/* Add the initial header varint and total the size */
- u.aq.nHdr += u.aq.nVarint = sqlite3VarintLen(u.aq.nHdr);
- if( u.aq.nVarint<sqlite3VarintLen(u.aq.nHdr) ){
- u.aq.nHdr++;
+ u.ar.nHdr += u.ar.nVarint = sqlite3VarintLen(u.ar.nHdr);
+ if( u.ar.nVarint<sqlite3VarintLen(u.ar.nHdr) ){
+ u.ar.nHdr++;
}
- u.aq.nByte = u.aq.nHdr+u.aq.nData-u.aq.nZero;
- if( u.aq.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ u.ar.nByte = u.ar.nHdr+u.ar.nData-u.ar.nZero;
+ if( u.ar.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
@@ -67961,28 +69209,28 @@ case OP_MakeRecord: {
** be one of the input registers (because the following call to
** sqlite3VdbeMemGrow() could clobber the value before it is used).
*/
- if( sqlite3VdbeMemGrow(pOut, (int)u.aq.nByte, 0) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)u.ar.nByte, 0) ){
goto no_mem;
}
- u.aq.zNewRecord = (u8 *)pOut->z;
+ u.ar.zNewRecord = (u8 *)pOut->z;
/* Write the record */
- u.aq.i = putVarint32(u.aq.zNewRecord, u.aq.nHdr);
- for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
- u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
- u.aq.i += putVarint32(&u.aq.zNewRecord[u.aq.i], u.aq.serial_type); /* serial type */
+ u.ar.i = putVarint32(u.ar.zNewRecord, u.ar.nHdr);
+ for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){
+ u.ar.serial_type = sqlite3VdbeSerialType(u.ar.pRec, u.ar.file_format);
+ u.ar.i += putVarint32(&u.ar.zNewRecord[u.ar.i], u.ar.serial_type); /* serial type */
}
- for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){ /* serial data */
- u.aq.i += sqlite3VdbeSerialPut(&u.aq.zNewRecord[u.aq.i], (int)(u.aq.nByte-u.aq.i), u.aq.pRec,u.aq.file_format);
+ for(u.ar.pRec=u.ar.pData0; u.ar.pRec<=u.ar.pLast; u.ar.pRec++){ /* serial data */
+ u.ar.i += sqlite3VdbeSerialPut(&u.ar.zNewRecord[u.ar.i], (int)(u.ar.nByte-u.ar.i), u.ar.pRec,u.ar.file_format);
}
- assert( u.aq.i==u.aq.nByte );
+ assert( u.ar.i==u.ar.nByte );
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pOut->n = (int)u.aq.nByte;
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
+ pOut->n = (int)u.ar.nByte;
pOut->flags = MEM_Blob | MEM_Dyn;
pOut->xDel = 0;
- if( u.aq.nZero ){
- pOut->u.nZero = u.aq.nZero;
+ if( u.ar.nZero ){
+ pOut->u.nZero = u.ar.nZero;
pOut->flags |= MEM_Zero;
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
@@ -67992,24 +69240,22 @@ case OP_MakeRecord: {
}
/* Opcode: Count P1 P2 * * *
+** Synopsis: r[P2]=count()
**
** Store the number of entries (an integer value) in the table or index
** opened by cursor P1 in register P2
*/
#ifndef SQLITE_OMIT_BTREECOUNT
case OP_Count: { /* out2-prerelease */
-#if 0 /* local variables moved into u.ar */
+#if 0 /* local variables moved into u.as */
i64 nEntry;
BtCursor *pCrsr;
-#endif /* local variables moved into u.ar */
+#endif /* local variables moved into u.as */
- u.ar.pCrsr = p->apCsr[pOp->p1]->pCursor;
- if( ALWAYS(u.ar.pCrsr) ){
- rc = sqlite3BtreeCount(u.ar.pCrsr, &u.ar.nEntry);
- }else{
- u.ar.nEntry = 0;
- }
- pOut->u.i = u.ar.nEntry;
+ u.as.pCrsr = p->apCsr[pOp->p1]->pCursor;
+ assert( u.as.pCrsr );
+ rc = sqlite3BtreeCount(u.as.pCrsr, &u.as.nEntry);
+ pOut->u.i = u.as.nEntry;
break;
}
#endif
@@ -68021,7 +69267,7 @@ case OP_Count: { /* out2-prerelease */
** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
*/
case OP_Savepoint: {
-#if 0 /* local variables moved into u.as */
+#if 0 /* local variables moved into u.at */
int p1; /* Value of P1 operand */
char *zName; /* Name of savepoint */
int nName;
@@ -68030,21 +69276,22 @@ case OP_Savepoint: {
Savepoint *pTmp;
int iSavepoint;
int ii;
-#endif /* local variables moved into u.as */
+#endif /* local variables moved into u.at */
- u.as.p1 = pOp->p1;
- u.as.zName = pOp->p4.z;
+ u.at.p1 = pOp->p1;
+ u.at.zName = pOp->p4.z;
- /* Assert that the u.as.p1 parameter is valid. Also that if there is no open
+ /* Assert that the u.at.p1 parameter is valid. Also that if there is no open
** transaction, then there cannot be any savepoints.
*/
assert( db->pSavepoint==0 || db->autoCommit==0 );
- assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK );
+ assert( u.at.p1==SAVEPOINT_BEGIN||u.at.p1==SAVEPOINT_RELEASE||u.at.p1==SAVEPOINT_ROLLBACK );
assert( db->pSavepoint || db->isTransactionSavepoint==0 );
assert( checkSavepointCount(db) );
+ assert( p->bIsReader );
- if( u.as.p1==SAVEPOINT_BEGIN ){
- if( db->writeVdbeCnt>0 ){
+ if( u.at.p1==SAVEPOINT_BEGIN ){
+ if( db->nVdbeWrite>0 ){
/* A new savepoint cannot be created if there are active write
** statements (i.e. open read/write incremental blob handles).
*/
@@ -68052,7 +69299,7 @@ case OP_Savepoint: {
"SQL statements in progress");
rc = SQLITE_BUSY;
}else{
- u.as.nName = sqlite3Strlen30(u.as.zName);
+ u.at.nName = sqlite3Strlen30(u.at.zName);
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* This call is Ok even if this savepoint is actually a transaction
@@ -68066,10 +69313,10 @@ case OP_Savepoint: {
#endif
/* Create a new savepoint structure. */
- u.as.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.as.nName+1);
- if( u.as.pNew ){
- u.as.pNew->zName = (char *)&u.as.pNew[1];
- memcpy(u.as.pNew->zName, u.as.zName, u.as.nName+1);
+ u.at.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.at.nName+1);
+ if( u.at.pNew ){
+ u.at.pNew->zName = (char *)&u.at.pNew[1];
+ memcpy(u.at.pNew->zName, u.at.zName, u.at.nName+1);
/* If there is no open transaction, then mark this as a special
** "transaction savepoint". */
@@ -68081,27 +69328,28 @@ case OP_Savepoint: {
}
/* Link the new savepoint into the database handle's list. */
- u.as.pNew->pNext = db->pSavepoint;
- db->pSavepoint = u.as.pNew;
- u.as.pNew->nDeferredCons = db->nDeferredCons;
+ u.at.pNew->pNext = db->pSavepoint;
+ db->pSavepoint = u.at.pNew;
+ u.at.pNew->nDeferredCons = db->nDeferredCons;
+ u.at.pNew->nDeferredImmCons = db->nDeferredImmCons;
}
}
}else{
- u.as.iSavepoint = 0;
+ u.at.iSavepoint = 0;
/* Find the named savepoint. If there is no such savepoint, then an
** an error is returned to the user. */
for(
- u.as.pSavepoint = db->pSavepoint;
- u.as.pSavepoint && sqlite3StrICmp(u.as.pSavepoint->zName, u.as.zName);
- u.as.pSavepoint = u.as.pSavepoint->pNext
+ u.at.pSavepoint = db->pSavepoint;
+ u.at.pSavepoint && sqlite3StrICmp(u.at.pSavepoint->zName, u.at.zName);
+ u.at.pSavepoint = u.at.pSavepoint->pNext
){
- u.as.iSavepoint++;
+ u.at.iSavepoint++;
}
- if( !u.as.pSavepoint ){
- sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName);
+ if( !u.at.pSavepoint ){
+ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.at.zName);
rc = SQLITE_ERROR;
- }else if( db->writeVdbeCnt>0 && u.as.p1==SAVEPOINT_RELEASE ){
+ }else if( db->nVdbeWrite>0 && u.at.p1==SAVEPOINT_RELEASE ){
/* It is not possible to release (commit) a savepoint if there are
** active write statements.
*/
@@ -68115,8 +69363,8 @@ case OP_Savepoint: {
** and this is a RELEASE command, then the current transaction
** is committed.
*/
- int isTransaction = u.as.pSavepoint->pNext==0 && db->isTransactionSavepoint;
- if( isTransaction && u.as.p1==SAVEPOINT_RELEASE ){
+ int isTransaction = u.at.pSavepoint->pNext==0 && db->isTransactionSavepoint;
+ if( isTransaction && u.at.p1==SAVEPOINT_RELEASE ){
if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
goto vdbe_return;
}
@@ -68130,19 +69378,19 @@ case OP_Savepoint: {
db->isTransactionSavepoint = 0;
rc = p->rc;
}else{
- u.as.iSavepoint = db->nSavepoint - u.as.iSavepoint - 1;
- if( u.as.p1==SAVEPOINT_ROLLBACK ){
- for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
- sqlite3BtreeTripAllCursors(db->aDb[u.as.ii].pBt, SQLITE_ABORT);
+ u.at.iSavepoint = db->nSavepoint - u.at.iSavepoint - 1;
+ if( u.at.p1==SAVEPOINT_ROLLBACK ){
+ for(u.at.ii=0; u.at.ii<db->nDb; u.at.ii++){
+ sqlite3BtreeTripAllCursors(db->aDb[u.at.ii].pBt, SQLITE_ABORT);
}
}
- for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
- rc = sqlite3BtreeSavepoint(db->aDb[u.as.ii].pBt, u.as.p1, u.as.iSavepoint);
+ for(u.at.ii=0; u.at.ii<db->nDb; u.at.ii++){
+ rc = sqlite3BtreeSavepoint(db->aDb[u.at.ii].pBt, u.at.p1, u.at.iSavepoint);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
}
- if( u.as.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
+ if( u.at.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
db->flags = (db->flags | SQLITE_InternChanges);
@@ -68151,10 +69399,10 @@ case OP_Savepoint: {
/* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
** savepoints nested inside of the savepoint being operated on. */
- while( db->pSavepoint!=u.as.pSavepoint ){
- u.as.pTmp = db->pSavepoint;
- db->pSavepoint = u.as.pTmp->pNext;
- sqlite3DbFree(db, u.as.pTmp);
+ while( db->pSavepoint!=u.at.pSavepoint ){
+ u.at.pTmp = db->pSavepoint;
+ db->pSavepoint = u.at.pTmp->pNext;
+ sqlite3DbFree(db, u.at.pTmp);
db->nSavepoint--;
}
@@ -68162,19 +69410,20 @@ case OP_Savepoint: {
** too. If it is a ROLLBACK TO, then set the number of deferred
** constraint violations present in the database to the value stored
** when the savepoint was created. */
- if( u.as.p1==SAVEPOINT_RELEASE ){
- assert( u.as.pSavepoint==db->pSavepoint );
- db->pSavepoint = u.as.pSavepoint->pNext;
- sqlite3DbFree(db, u.as.pSavepoint);
+ if( u.at.p1==SAVEPOINT_RELEASE ){
+ assert( u.at.pSavepoint==db->pSavepoint );
+ db->pSavepoint = u.at.pSavepoint->pNext;
+ sqlite3DbFree(db, u.at.pSavepoint);
if( !isTransaction ){
db->nSavepoint--;
}
}else{
- db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
+ db->nDeferredCons = u.at.pSavepoint->nDeferredCons;
+ db->nDeferredImmCons = u.at.pSavepoint->nDeferredImmCons;
}
if( !isTransaction ){
- rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint);
+ rc = sqlite3VtabSavepoint(db, u.at.p1, u.at.iSavepoint);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
@@ -68193,21 +69442,22 @@ case OP_Savepoint: {
** This instruction causes the VM to halt.
*/
case OP_AutoCommit: {
-#if 0 /* local variables moved into u.at */
+#if 0 /* local variables moved into u.au */
int desiredAutoCommit;
int iRollback;
int turnOnAC;
-#endif /* local variables moved into u.at */
+#endif /* local variables moved into u.au */
- u.at.desiredAutoCommit = pOp->p1;
- u.at.iRollback = pOp->p2;
- u.at.turnOnAC = u.at.desiredAutoCommit && !db->autoCommit;
- assert( u.at.desiredAutoCommit==1 || u.at.desiredAutoCommit==0 );
- assert( u.at.desiredAutoCommit==1 || u.at.iRollback==0 );
- assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
+ u.au.desiredAutoCommit = pOp->p1;
+ u.au.iRollback = pOp->p2;
+ u.au.turnOnAC = u.au.desiredAutoCommit && !db->autoCommit;
+ assert( u.au.desiredAutoCommit==1 || u.au.desiredAutoCommit==0 );
+ assert( u.au.desiredAutoCommit==1 || u.au.iRollback==0 );
+ assert( db->nVdbeActive>0 ); /* At least this one VM is active */
+ assert( p->bIsReader );
#if 0
- if( u.at.turnOnAC && u.at.iRollback && db->activeVdbeCnt>1 ){
+ if( u.au.turnOnAC && u.au.iRollback && db->nVdbeActive>1 ){
/* If this instruction implements a ROLLBACK and other VMs are
** still running, and a transaction is active, return an error indicating
** that the other VMs must complete first.
@@ -68217,25 +69467,25 @@ case OP_AutoCommit: {
rc = SQLITE_BUSY;
}else
#endif
- if( u.at.turnOnAC && !u.at.iRollback && db->writeVdbeCnt>0 ){
+ if( u.au.turnOnAC && !u.au.iRollback && db->nVdbeWrite>0 ){
/* If this instruction implements a COMMIT and other VMs are writing
** return an error indicating that the other VMs must complete first.
*/
sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
"SQL statements in progress");
rc = SQLITE_BUSY;
- }else if( u.at.desiredAutoCommit!=db->autoCommit ){
- if( u.at.iRollback ){
- assert( u.at.desiredAutoCommit==1 );
+ }else if( u.au.desiredAutoCommit!=db->autoCommit ){
+ if( u.au.iRollback ){
+ assert( u.au.desiredAutoCommit==1 );
sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
db->autoCommit = 1;
}else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
goto vdbe_return;
}else{
- db->autoCommit = (u8)u.at.desiredAutoCommit;
+ db->autoCommit = (u8)u.au.desiredAutoCommit;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pc = pc;
- db->autoCommit = (u8)(1-u.at.desiredAutoCommit);
+ db->autoCommit = (u8)(1-u.au.desiredAutoCommit);
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
@@ -68250,8 +69500,8 @@ case OP_AutoCommit: {
goto vdbe_return;
}else{
sqlite3SetString(&p->zErrMsg, db,
- (!u.at.desiredAutoCommit)?"cannot start a transaction within a transaction":(
- (u.at.iRollback)?"cannot rollback - no transaction is active":
+ (!u.au.desiredAutoCommit)?"cannot start a transaction within a transaction":(
+ (u.au.iRollback)?"cannot rollback - no transaction is active":
"cannot commit - no transaction is active"));
rc = SQLITE_ERROR;
@@ -68275,8 +69525,8 @@ case OP_AutoCommit: {
** other process can start another write transaction while this transaction is
** underway. Starting a write transaction also creates a rollback journal. A
** write transaction must be started before any changes can be made to the
-** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained
-** on the file.
+** database. If P2 is greater than or equal to 2 then an EXCLUSIVE lock is
+** also obtained on the file.
**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
** true (this flag is set if the Vdbe may modify more than one row and may
@@ -68291,16 +69541,22 @@ case OP_AutoCommit: {
** If P2 is zero, then a read-lock is obtained on the database file.
*/
case OP_Transaction: {
-#if 0 /* local variables moved into u.au */
+#if 0 /* local variables moved into u.av */
Btree *pBt;
-#endif /* local variables moved into u.au */
+#endif /* local variables moved into u.av */
+ assert( p->bIsReader );
+ assert( p->readOnly==0 || pOp->p2==0 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
- u.au.pBt = db->aDb[pOp->p1].pBt;
+ if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
+ rc = SQLITE_READONLY;
+ goto abort_due_to_error;
+ }
+ u.av.pBt = db->aDb[pOp->p1].pBt;
- if( u.au.pBt ){
- rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
+ if( u.av.pBt ){
+ rc = sqlite3BtreeBeginTrans(u.av.pBt, pOp->p2);
if( rc==SQLITE_BUSY ){
p->pc = pc;
p->rc = rc = SQLITE_BUSY;
@@ -68311,9 +69567,9 @@ case OP_Transaction: {
}
if( pOp->p2 && p->usesStmtJournal
- && (db->autoCommit==0 || db->activeVdbeCnt>1)
+ && (db->autoCommit==0 || db->nVdbeRead>1)
){
- assert( sqlite3BtreeIsInTrans(u.au.pBt) );
+ assert( sqlite3BtreeIsInTrans(u.av.pBt) );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
db->nStatement++;
@@ -68322,13 +69578,14 @@ case OP_Transaction: {
rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement);
+ rc = sqlite3BtreeBeginStmt(u.av.pBt, p->iStatement);
}
/* Store the current value of the database handles deferred constraint
** counter. If the statement transaction needs to be rolled back,
** the value of this counter needs to be restored too. */
p->nStmtDefCons = db->nDeferredCons;
+ p->nStmtDefImmCons = db->nDeferredImmCons;
}
}
break;
@@ -68347,21 +69604,22 @@ case OP_Transaction: {
** executing this instruction.
*/
case OP_ReadCookie: { /* out2-prerelease */
-#if 0 /* local variables moved into u.av */
+#if 0 /* local variables moved into u.aw */
int iMeta;
int iDb;
int iCookie;
-#endif /* local variables moved into u.av */
+#endif /* local variables moved into u.aw */
- u.av.iDb = pOp->p1;
- u.av.iCookie = pOp->p3;
+ assert( p->bIsReader );
+ u.aw.iDb = pOp->p1;
+ u.aw.iCookie = pOp->p3;
assert( pOp->p3<SQLITE_N_BTREE_META );
- assert( u.av.iDb>=0 && u.av.iDb<db->nDb );
- assert( db->aDb[u.av.iDb].pBt!=0 );
- assert( (p->btreeMask & (((yDbMask)1)<<u.av.iDb))!=0 );
+ assert( u.aw.iDb>=0 && u.aw.iDb<db->nDb );
+ assert( db->aDb[u.aw.iDb].pBt!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<<u.aw.iDb))!=0 );
- sqlite3BtreeGetMeta(db->aDb[u.av.iDb].pBt, u.av.iCookie, (u32 *)&u.av.iMeta);
- pOut->u.i = u.av.iMeta;
+ sqlite3BtreeGetMeta(db->aDb[u.aw.iDb].pBt, u.aw.iCookie, (u32 *)&u.aw.iMeta);
+ pOut->u.i = u.aw.iMeta;
break;
}
@@ -68376,26 +69634,27 @@ case OP_ReadCookie: { /* out2-prerelease */
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: { /* in3 */
-#if 0 /* local variables moved into u.aw */
+#if 0 /* local variables moved into u.ax */
Db *pDb;
-#endif /* local variables moved into u.aw */
+#endif /* local variables moved into u.ax */
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
- u.aw.pDb = &db->aDb[pOp->p1];
- assert( u.aw.pDb->pBt!=0 );
+ assert( p->readOnly==0 );
+ u.ax.pDb = &db->aDb[pOp->p1];
+ assert( u.ax.pDb->pBt!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
pIn3 = &aMem[pOp->p3];
sqlite3VdbeMemIntegerify(pIn3);
/* See note about index shifting on OP_ReadCookie */
- rc = sqlite3BtreeUpdateMeta(u.aw.pDb->pBt, pOp->p2, (int)pIn3->u.i);
+ rc = sqlite3BtreeUpdateMeta(u.ax.pDb->pBt, pOp->p2, (int)pIn3->u.i);
if( pOp->p2==BTREE_SCHEMA_VERSION ){
/* When the schema cookie changes, record the new cookie internally */
- u.aw.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
+ u.ax.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
db->flags |= SQLITE_InternChanges;
}else if( pOp->p2==BTREE_FILE_FORMAT ){
/* Record changes in the file format */
- u.aw.pDb->pSchema->file_format = (u8)pIn3->u.i;
+ u.ax.pDb->pSchema->file_format = (u8)pIn3->u.i;
}
if( pOp->p1==1 ){
/* Invalidate all prepared statements whenever the TEMP database
@@ -68425,23 +69684,24 @@ case OP_SetCookie: { /* in3 */
** invoked.
*/
case OP_VerifyCookie: {
-#if 0 /* local variables moved into u.ax */
+#if 0 /* local variables moved into u.ay */
int iMeta;
int iGen;
Btree *pBt;
-#endif /* local variables moved into u.ax */
+#endif /* local variables moved into u.ay */
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
- u.ax.pBt = db->aDb[pOp->p1].pBt;
- if( u.ax.pBt ){
- sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta);
- u.ax.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
+ assert( p->bIsReader );
+ u.ay.pBt = db->aDb[pOp->p1].pBt;
+ if( u.ay.pBt ){
+ sqlite3BtreeGetMeta(u.ay.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ay.iMeta);
+ u.ay.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
}else{
- u.ax.iGen = u.ax.iMeta = 0;
+ u.ay.iGen = u.ay.iMeta = 0;
}
- if( u.ax.iMeta!=pOp->p2 || u.ax.iGen!=pOp->p3 ){
+ if( u.ay.iMeta!=pOp->p2 || u.ay.iGen!=pOp->p3 ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
@@ -68457,7 +69717,7 @@ case OP_VerifyCookie: {
** to be invalidated whenever sqlite3_step() is called from within
** a v-table method.
*/
- if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ax.iMeta ){
+ if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ay.iMeta ){
sqlite3ResetOneSchema(db, pOp->p1);
}
@@ -68468,6 +69728,7 @@ case OP_VerifyCookie: {
}
/* Opcode: OpenRead P1 P2 P3 P4 P5
+** Synopsis: root=P2 iDb=P3
**
** Open a read-only cursor for the database table whose root page is
** P2 in a database file. The database file is determined by P3.
@@ -68498,6 +69759,7 @@ case OP_VerifyCookie: {
** See also OpenWrite.
*/
/* Opcode: OpenWrite P1 P2 P3 P4 P5
+** Synopsis: root=P2 iDb=P3
**
** Open a read/write cursor named P1 on the table or index whose root
** page is P2. Or if P5!=0 use the content of register P2 to find the
@@ -68518,7 +69780,7 @@ case OP_VerifyCookie: {
*/
case OP_OpenRead:
case OP_OpenWrite: {
-#if 0 /* local variables moved into u.ay */
+#if 0 /* local variables moved into u.az */
int nField;
KeyInfo *pKeyInfo;
int p2;
@@ -68527,82 +69789,87 @@ case OP_OpenWrite: {
Btree *pX;
VdbeCursor *pCur;
Db *pDb;
-#endif /* local variables moved into u.ay */
+#endif /* local variables moved into u.az */
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
+ assert( p->bIsReader );
+ assert( pOp->opcode==OP_OpenRead || p->readOnly==0 );
if( p->expired ){
rc = SQLITE_ABORT;
break;
}
- u.ay.nField = 0;
- u.ay.pKeyInfo = 0;
- u.ay.p2 = pOp->p2;
- u.ay.iDb = pOp->p3;
- assert( u.ay.iDb>=0 && u.ay.iDb<db->nDb );
- assert( (p->btreeMask & (((yDbMask)1)<<u.ay.iDb))!=0 );
- u.ay.pDb = &db->aDb[u.ay.iDb];
- u.ay.pX = u.ay.pDb->pBt;
- assert( u.ay.pX!=0 );
+ u.az.nField = 0;
+ u.az.pKeyInfo = 0;
+ u.az.p2 = pOp->p2;
+ u.az.iDb = pOp->p3;
+ assert( u.az.iDb>=0 && u.az.iDb<db->nDb );
+ assert( (p->btreeMask & (((yDbMask)1)<<u.az.iDb))!=0 );
+ u.az.pDb = &db->aDb[u.az.iDb];
+ u.az.pX = u.az.pDb->pBt;
+ assert( u.az.pX!=0 );
if( pOp->opcode==OP_OpenWrite ){
- u.ay.wrFlag = 1;
- assert( sqlite3SchemaMutexHeld(db, u.ay.iDb, 0) );
- if( u.ay.pDb->pSchema->file_format < p->minWriteFileFormat ){
- p->minWriteFileFormat = u.ay.pDb->pSchema->file_format;
+ u.az.wrFlag = 1;
+ assert( sqlite3SchemaMutexHeld(db, u.az.iDb, 0) );
+ if( u.az.pDb->pSchema->file_format < p->minWriteFileFormat ){
+ p->minWriteFileFormat = u.az.pDb->pSchema->file_format;
}
}else{
- u.ay.wrFlag = 0;
+ u.az.wrFlag = 0;
}
if( pOp->p5 & OPFLAG_P2ISREG ){
- assert( u.ay.p2>0 );
- assert( u.ay.p2<=p->nMem );
- pIn2 = &aMem[u.ay.p2];
+ assert( u.az.p2>0 );
+ assert( u.az.p2<=(p->nMem-p->nCursor) );
+ pIn2 = &aMem[u.az.p2];
assert( memIsValid(pIn2) );
assert( (pIn2->flags & MEM_Int)!=0 );
sqlite3VdbeMemIntegerify(pIn2);
- u.ay.p2 = (int)pIn2->u.i;
- /* The u.ay.p2 value always comes from a prior OP_CreateTable opcode and
- ** that opcode will always set the u.ay.p2 value to 2 or more or else fail.
+ u.az.p2 = (int)pIn2->u.i;
+ /* The u.az.p2 value always comes from a prior OP_CreateTable opcode and
+ ** that opcode will always set the u.az.p2 value to 2 or more or else fail.
** If there were a failure, the prepared statement would have halted
** before reaching this instruction. */
- if( NEVER(u.ay.p2<2) ) {
+ if( NEVER(u.az.p2<2) ) {
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
}
if( pOp->p4type==P4_KEYINFO ){
- u.ay.pKeyInfo = pOp->p4.pKeyInfo;
- u.ay.pKeyInfo->enc = ENC(p->db);
- u.ay.nField = u.ay.pKeyInfo->nField+1;
+ u.az.pKeyInfo = pOp->p4.pKeyInfo;
+ assert( u.az.pKeyInfo->enc==ENC(db) );
+ assert( u.az.pKeyInfo->db==db );
+ u.az.nField = u.az.pKeyInfo->nField+u.az.pKeyInfo->nXField;
}else if( pOp->p4type==P4_INT32 ){
- u.ay.nField = pOp->p4.i;
+ u.az.nField = pOp->p4.i;
}
assert( pOp->p1>=0 );
- u.ay.pCur = allocateCursor(p, pOp->p1, u.ay.nField, u.ay.iDb, 1);
- if( u.ay.pCur==0 ) goto no_mem;
- u.ay.pCur->nullRow = 1;
- u.ay.pCur->isOrdered = 1;
- rc = sqlite3BtreeCursor(u.ay.pX, u.ay.p2, u.ay.wrFlag, u.ay.pKeyInfo, u.ay.pCur->pCursor);
- u.ay.pCur->pKeyInfo = u.ay.pKeyInfo;
+ assert( u.az.nField>=0 );
+ testcase( u.az.nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
+ u.az.pCur = allocateCursor(p, pOp->p1, u.az.nField, u.az.iDb, 1);
+ if( u.az.pCur==0 ) goto no_mem;
+ u.az.pCur->nullRow = 1;
+ u.az.pCur->isOrdered = 1;
+ rc = sqlite3BtreeCursor(u.az.pX, u.az.p2, u.az.wrFlag, u.az.pKeyInfo, u.az.pCur->pCursor);
+ u.az.pCur->pKeyInfo = u.az.pKeyInfo;
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
- sqlite3BtreeCursorHints(u.ay.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
+ sqlite3BtreeCursorHints(u.az.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
/* Since it performs no memory allocation or IO, the only value that
** sqlite3BtreeCursor() may return is SQLITE_OK. */
assert( rc==SQLITE_OK );
- /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
+ /* Set the VdbeCursor.isTable variable. Previous versions of
** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has
** since moved into the btree layer. */
- u.ay.pCur->isTable = pOp->p4type!=P4_KEYINFO;
- u.ay.pCur->isIndex = !u.ay.pCur->isTable;
+ u.az.pCur->isTable = pOp->p4type!=P4_KEYINFO;
break;
}
/* Opcode: OpenEphemeral P1 P2 * P4 P5
+** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if
@@ -68614,18 +69881,13 @@ case OP_OpenWrite: {
** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
**
-** This opcode was once called OpenTemp. But that created
-** confusion because the term "temp table", might refer either
-** to a TEMP table at the SQL level, or to a table opened by
-** this opcode. Then this opcode was call OpenVirtual. But
-** that created confusion with the whole virtual-table idea.
-**
** The P5 parameter can be a mask of the BTREE_* flags defined
** in btree.h. These flags control aspects of the operation of
** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
** added automatically.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
+** Synopsis: nColumn=P2
**
** This opcode works the same as OP_OpenEphemeral. It has a
** different name to distinguish its use. Tables created using
@@ -68634,24 +69896,26 @@ case OP_OpenWrite: {
*/
case OP_OpenAutoindex:
case OP_OpenEphemeral: {
-#if 0 /* local variables moved into u.az */
+#if 0 /* local variables moved into u.ba */
VdbeCursor *pCx;
-#endif /* local variables moved into u.az */
+ KeyInfo *pKeyInfo;
+#endif /* local variables moved into u.ba */
+
static const int vfsFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TRANSIENT_DB;
-
assert( pOp->p1>=0 );
- u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
- if( u.az.pCx==0 ) goto no_mem;
- u.az.pCx->nullRow = 1;
- rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.az.pCx->pBt,
+ assert( pOp->p2>=0 );
+ u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( u.ba.pCx==0 ) goto no_mem;
+ u.ba.pCx->nullRow = 1;
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ba.pCx->pBt,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(u.az.pCx->pBt, 1);
+ rc = sqlite3BtreeBeginTrans(u.ba.pCx->pBt, 1);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
@@ -68659,49 +69923,51 @@ case OP_OpenEphemeral: {
** opening it. If a transient table is required, just use the
** automatically created table with root-page 1 (an BLOB_INTKEY table).
*/
- if( pOp->p4.pKeyInfo ){
+ if( (u.ba.pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(u.az.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+ rc = sqlite3BtreeCreateTable(u.ba.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
- rc = sqlite3BtreeCursor(u.az.pCx->pBt, pgno, 1,
- (KeyInfo*)pOp->p4.z, u.az.pCx->pCursor);
- u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
- u.az.pCx->pKeyInfo->enc = ENC(p->db);
+ assert( u.ba.pKeyInfo->db==db );
+ assert( u.ba.pKeyInfo->enc==ENC(db) );
+ u.ba.pCx->pKeyInfo = u.ba.pKeyInfo;
+ rc = sqlite3BtreeCursor(u.ba.pCx->pBt, pgno, 1, u.ba.pKeyInfo, u.ba.pCx->pCursor);
}
- u.az.pCx->isTable = 0;
+ u.ba.pCx->isTable = 0;
}else{
- rc = sqlite3BtreeCursor(u.az.pCx->pBt, MASTER_ROOT, 1, 0, u.az.pCx->pCursor);
- u.az.pCx->isTable = 1;
+ rc = sqlite3BtreeCursor(u.ba.pCx->pBt, MASTER_ROOT, 1, 0, u.ba.pCx->pCursor);
+ u.ba.pCx->isTable = 1;
}
}
- u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
- u.az.pCx->isIndex = !u.az.pCx->isTable;
+ u.ba.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
break;
}
-/* Opcode: SorterOpen P1 P2 * P4 *
+/* Opcode: SorterOpen P1 * * P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
** tables using an external merge-sort algorithm.
*/
case OP_SorterOpen: {
-#if 0 /* local variables moved into u.ba */
+#if 0 /* local variables moved into u.bb */
VdbeCursor *pCx;
-#endif /* local variables moved into u.ba */
+#endif /* local variables moved into u.bb */
- u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
- if( u.ba.pCx==0 ) goto no_mem;
- u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
- u.ba.pCx->pKeyInfo->enc = ENC(p->db);
- u.ba.pCx->isSorter = 1;
- rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
+ assert( pOp->p1>=0 );
+ assert( pOp->p2>=0 );
+ u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( u.bb.pCx==0 ) goto no_mem;
+ u.bb.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+ assert( u.bb.pCx->pKeyInfo->db==db );
+ assert( u.bb.pCx->pKeyInfo->enc==ENC(db) );
+ rc = sqlite3VdbeSorterInit(db, u.bb.pCx);
break;
}
/* Opcode: OpenPseudo P1 P2 P3 * P5
+** Synopsis: content in r[P2@P3]
**
** Open a new cursor that points to a fake table that contains a single
** row of data. The content of that one row in the content of memory
@@ -68718,18 +69984,18 @@ case OP_SorterOpen: {
** the pseudo-table.
*/
case OP_OpenPseudo: {
-#if 0 /* local variables moved into u.bb */
+#if 0 /* local variables moved into u.bc */
VdbeCursor *pCx;
-#endif /* local variables moved into u.bb */
+#endif /* local variables moved into u.bc */
assert( pOp->p1>=0 );
- u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
- if( u.bb.pCx==0 ) goto no_mem;
- u.bb.pCx->nullRow = 1;
- u.bb.pCx->pseudoTableReg = pOp->p2;
- u.bb.pCx->isTable = 1;
- u.bb.pCx->isIndex = 0;
- u.bb.pCx->multiPseudo = pOp->p5;
+ assert( pOp->p3>=0 );
+ u.bc.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+ if( u.bc.pCx==0 ) goto no_mem;
+ u.bc.pCx->nullRow = 1;
+ u.bc.pCx->pseudoTableReg = pOp->p2;
+ u.bc.pCx->isTable = 1;
+ u.bc.pCx->multiPseudo = pOp->p5;
break;
}
@@ -68746,6 +70012,7 @@ case OP_Close: {
}
/* Opcode: SeekGe P1 P2 P3 P4 *
+** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
** use the value in register P3 as the key. If cursor P1 refers
@@ -68759,6 +70026,7 @@ case OP_Close: {
** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
*/
/* Opcode: SeekGt P1 P2 P3 P4 *
+** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
** use the value in register P3 as a key. If cursor P1 refers
@@ -68772,6 +70040,7 @@ case OP_Close: {
** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
*/
/* Opcode: SeekLt P1 P2 P3 P4 *
+** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
** use the value in register P3 as a key. If cursor P1 refers
@@ -68785,6 +70054,7 @@ case OP_Close: {
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
*/
/* Opcode: SeekLe P1 P2 P3 P4 *
+** Synopsis: key=r[P3@P4]
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
** use the value in register P3 as a key. If cursor P1 refers
@@ -68801,157 +70071,143 @@ case OP_SeekLt: /* jump, in3 */
case OP_SeekLe: /* jump, in3 */
case OP_SeekGe: /* jump, in3 */
case OP_SeekGt: { /* jump, in3 */
-#if 0 /* local variables moved into u.bc */
+#if 0 /* local variables moved into u.bd */
int res;
int oc;
VdbeCursor *pC;
UnpackedRecord r;
int nField;
i64 iKey; /* The rowid we are to seek to */
-#endif /* local variables moved into u.bc */
+#endif /* local variables moved into u.bd */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p2!=0 );
- u.bc.pC = p->apCsr[pOp->p1];
- assert( u.bc.pC!=0 );
- assert( u.bc.pC->pseudoTableReg==0 );
+ u.bd.pC = p->apCsr[pOp->p1];
+ assert( u.bd.pC!=0 );
+ assert( u.bd.pC->pseudoTableReg==0 );
assert( OP_SeekLe == OP_SeekLt+1 );
assert( OP_SeekGe == OP_SeekLt+2 );
assert( OP_SeekGt == OP_SeekLt+3 );
- assert( u.bc.pC->isOrdered );
- if( ALWAYS(u.bc.pC->pCursor!=0) ){
- u.bc.oc = pOp->opcode;
- u.bc.pC->nullRow = 0;
- if( u.bc.pC->isTable ){
- /* The input value in P3 might be of any type: integer, real, string,
- ** blob, or NULL. But it needs to be an integer before we can do
- ** the seek, so covert it. */
- pIn3 = &aMem[pOp->p3];
- applyNumericAffinity(pIn3);
- u.bc.iKey = sqlite3VdbeIntValue(pIn3);
- u.bc.pC->rowidIsValid = 0;
-
- /* If the P3 value could not be converted into an integer without
- ** loss of information, then special processing is required... */
- if( (pIn3->flags & MEM_Int)==0 ){
- if( (pIn3->flags & MEM_Real)==0 ){
- /* If the P3 value cannot be converted into any kind of a number,
- ** then the seek is not possible, so jump to P2 */
- pc = pOp->p2 - 1;
- break;
- }
- /* If we reach this point, then the P3 value must be a floating
- ** point number. */
- assert( (pIn3->flags & MEM_Real)!=0 );
-
- if( u.bc.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bc.iKey || pIn3->r>0) ){
- /* The P3 value is too large in magnitude to be expressed as an
- ** integer. */
- u.bc.res = 1;
- if( pIn3->r<0 ){
- if( u.bc.oc>=OP_SeekGe ){ assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
- rc = sqlite3BtreeFirst(u.bc.pC->pCursor, &u.bc.res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- }
- }else{
- if( u.bc.oc<=OP_SeekLe ){ assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
- rc = sqlite3BtreeLast(u.bc.pC->pCursor, &u.bc.res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- }
- }
- if( u.bc.res ){
- pc = pOp->p2 - 1;
- }
- break;
- }else if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekGe ){
- /* Use the ceiling() function to convert real->int */
- if( pIn3->r > (double)u.bc.iKey ) u.bc.iKey++;
- }else{
- /* Use the floor() function to convert real->int */
- assert( u.bc.oc==OP_SeekLe || u.bc.oc==OP_SeekGt );
- if( pIn3->r < (double)u.bc.iKey ) u.bc.iKey--;
- }
+ assert( u.bd.pC->isOrdered );
+ assert( u.bd.pC->pCursor!=0 );
+ u.bd.oc = pOp->opcode;
+ u.bd.pC->nullRow = 0;
+ if( u.bd.pC->isTable ){
+ /* The input value in P3 might be of any type: integer, real, string,
+ ** blob, or NULL. But it needs to be an integer before we can do
+ ** the seek, so covert it. */
+ pIn3 = &aMem[pOp->p3];
+ applyNumericAffinity(pIn3);
+ u.bd.iKey = sqlite3VdbeIntValue(pIn3);
+ u.bd.pC->rowidIsValid = 0;
+
+ /* If the P3 value could not be converted into an integer without
+ ** loss of information, then special processing is required... */
+ if( (pIn3->flags & MEM_Int)==0 ){
+ if( (pIn3->flags & MEM_Real)==0 ){
+ /* If the P3 value cannot be converted into any kind of a number,
+ ** then the seek is not possible, so jump to P2 */
+ pc = pOp->p2 - 1;
+ break;
}
- rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, 0, (u64)u.bc.iKey, 0, &u.bc.res);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
+
+ /* If the approximation u.bd.iKey is larger than the actual real search
+ ** term, substitute >= for > and < for <=. e.g. if the search term
+ ** is 4.9 and the integer approximation 5:
+ **
+ ** (x > 4.9) -> (x >= 5)
+ ** (x <= 4.9) -> (x < 5)
+ */
+ if( pIn3->r<(double)u.bd.iKey ){
+ assert( OP_SeekGe==(OP_SeekGt-1) );
+ assert( OP_SeekLt==(OP_SeekLe-1) );
+ assert( (OP_SeekLe & 0x0001)==(OP_SeekGt & 0x0001) );
+ if( (u.bd.oc & 0x0001)==(OP_SeekGt & 0x0001) ) u.bd.oc--;
}
- if( u.bc.res==0 ){
- u.bc.pC->rowidIsValid = 1;
- u.bc.pC->lastRowid = u.bc.iKey;
+
+ /* If the approximation u.bd.iKey is smaller than the actual real search
+ ** term, substitute <= for < and > for >=. */
+ else if( pIn3->r>(double)u.bd.iKey ){
+ assert( OP_SeekLe==(OP_SeekLt+1) );
+ assert( OP_SeekGt==(OP_SeekGe+1) );
+ assert( (OP_SeekLt & 0x0001)==(OP_SeekGe & 0x0001) );
+ if( (u.bd.oc & 0x0001)==(OP_SeekLt & 0x0001) ) u.bd.oc++;
}
- }else{
- u.bc.nField = pOp->p4.i;
- assert( pOp->p4type==P4_INT32 );
- assert( u.bc.nField>0 );
- u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
- u.bc.r.nField = (u16)u.bc.nField;
-
- /* The next line of code computes as follows, only faster:
- ** if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){
- ** u.bc.r.flags = UNPACKED_INCRKEY;
- ** }else{
- ** u.bc.r.flags = 0;
- ** }
- */
- u.bc.r.flags = (u8)(UNPACKED_INCRKEY * (1 & (u.bc.oc - OP_SeekLt)));
- assert( u.bc.oc!=OP_SeekGt || u.bc.r.flags==UNPACKED_INCRKEY );
- assert( u.bc.oc!=OP_SeekLe || u.bc.r.flags==UNPACKED_INCRKEY );
- assert( u.bc.oc!=OP_SeekGe || u.bc.r.flags==0 );
- assert( u.bc.oc!=OP_SeekLt || u.bc.r.flags==0 );
+ }
+ rc = sqlite3BtreeMovetoUnpacked(u.bd.pC->pCursor, 0, (u64)u.bd.iKey, 0, &u.bd.res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ if( u.bd.res==0 ){
+ u.bd.pC->rowidIsValid = 1;
+ u.bd.pC->lastRowid = u.bd.iKey;
+ }
+ }else{
+ u.bd.nField = pOp->p4.i;
+ assert( pOp->p4type==P4_INT32 );
+ assert( u.bd.nField>0 );
+ u.bd.r.pKeyInfo = u.bd.pC->pKeyInfo;
+ u.bd.r.nField = (u16)u.bd.nField;
+
+ /* The next line of code computes as follows, only faster:
+ ** if( u.bd.oc==OP_SeekGt || u.bd.oc==OP_SeekLe ){
+ ** u.bd.r.flags = UNPACKED_INCRKEY;
+ ** }else{
+ ** u.bd.r.flags = 0;
+ ** }
+ */
+ u.bd.r.flags = (u8)(UNPACKED_INCRKEY * (1 & (u.bd.oc - OP_SeekLt)));
+ assert( u.bd.oc!=OP_SeekGt || u.bd.r.flags==UNPACKED_INCRKEY );
+ assert( u.bd.oc!=OP_SeekLe || u.bd.r.flags==UNPACKED_INCRKEY );
+ assert( u.bd.oc!=OP_SeekGe || u.bd.r.flags==0 );
+ assert( u.bd.oc!=OP_SeekLt || u.bd.r.flags==0 );
- u.bc.r.aMem = &aMem[pOp->p3];
+ u.bd.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<u.bc.r.nField; i++) assert( memIsValid(&u.bc.r.aMem[i]) ); }
+ { int i; for(i=0; i<u.bd.r.nField; i++) assert( memIsValid(&u.bd.r.aMem[i]) ); }
#endif
- ExpandBlob(u.bc.r.aMem);
- rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, &u.bc.r, 0, 0, &u.bc.res);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- u.bc.pC->rowidIsValid = 0;
+ ExpandBlob(u.bd.r.aMem);
+ rc = sqlite3BtreeMovetoUnpacked(u.bd.pC->pCursor, &u.bd.r, 0, 0, &u.bd.res);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
}
- u.bc.pC->deferredMoveto = 0;
- u.bc.pC->cacheStatus = CACHE_STALE;
+ u.bd.pC->rowidIsValid = 0;
+ }
+ u.bd.pC->deferredMoveto = 0;
+ u.bd.pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
- sqlite3_search_count++;
+ sqlite3_search_count++;
#endif
- if( u.bc.oc>=OP_SeekGe ){ assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
- if( u.bc.res<0 || (u.bc.res==0 && u.bc.oc==OP_SeekGt) ){
- rc = sqlite3BtreeNext(u.bc.pC->pCursor, &u.bc.res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- u.bc.pC->rowidIsValid = 0;
- }else{
- u.bc.res = 0;
- }
+ if( u.bd.oc>=OP_SeekGe ){ assert( u.bd.oc==OP_SeekGe || u.bd.oc==OP_SeekGt );
+ if( u.bd.res<0 || (u.bd.res==0 && u.bd.oc==OP_SeekGt) ){
+ rc = sqlite3BtreeNext(u.bd.pC->pCursor, &u.bd.res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ u.bd.pC->rowidIsValid = 0;
}else{
- assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
- if( u.bc.res>0 || (u.bc.res==0 && u.bc.oc==OP_SeekLt) ){
- rc = sqlite3BtreePrevious(u.bc.pC->pCursor, &u.bc.res);
- if( rc!=SQLITE_OK ) goto abort_due_to_error;
- u.bc.pC->rowidIsValid = 0;
- }else{
- /* u.bc.res might be negative because the table is empty. Check to
- ** see if this is the case.
- */
- u.bc.res = sqlite3BtreeEof(u.bc.pC->pCursor);
- }
- }
- assert( pOp->p2>0 );
- if( u.bc.res ){
- pc = pOp->p2 - 1;
+ u.bd.res = 0;
}
}else{
- /* This happens when attempting to open the sqlite3_master table
- ** for read access returns SQLITE_EMPTY. In this case always
- ** take the jump (since there are no records in the table).
- */
+ assert( u.bd.oc==OP_SeekLt || u.bd.oc==OP_SeekLe );
+ if( u.bd.res>0 || (u.bd.res==0 && u.bd.oc==OP_SeekLt) ){
+ rc = sqlite3BtreePrevious(u.bd.pC->pCursor, &u.bd.res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ u.bd.pC->rowidIsValid = 0;
+ }else{
+ /* u.bd.res might be negative because the table is empty. Check to
+ ** see if this is the case.
+ */
+ u.bd.res = sqlite3BtreeEof(u.bd.pC->pCursor);
+ }
+ }
+ assert( pOp->p2>0 );
+ if( u.bd.res ){
pc = pOp->p2 - 1;
}
break;
}
/* Opcode: Seek P1 P2 * * *
+** Synopsis: intkey=r[P2]
**
** P1 is an open table cursor and P2 is a rowid integer. Arrange
** for P1 to move so that it points to the rowid given by P2.
@@ -68961,26 +70217,26 @@ case OP_SeekGt: { /* jump, in3 */
** occur, no unnecessary I/O happens.
*/
case OP_Seek: { /* in2 */
-#if 0 /* local variables moved into u.bd */
+#if 0 /* local variables moved into u.be */
VdbeCursor *pC;
-#endif /* local variables moved into u.bd */
+#endif /* local variables moved into u.be */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bd.pC = p->apCsr[pOp->p1];
- assert( u.bd.pC!=0 );
- if( ALWAYS(u.bd.pC->pCursor!=0) ){
- assert( u.bd.pC->isTable );
- u.bd.pC->nullRow = 0;
- pIn2 = &aMem[pOp->p2];
- u.bd.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
- u.bd.pC->rowidIsValid = 0;
- u.bd.pC->deferredMoveto = 1;
- }
+ u.be.pC = p->apCsr[pOp->p1];
+ assert( u.be.pC!=0 );
+ assert( u.be.pC->pCursor!=0 );
+ assert( u.be.pC->isTable );
+ u.be.pC->nullRow = 0;
+ pIn2 = &aMem[pOp->p2];
+ u.be.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+ u.be.pC->rowidIsValid = 0;
+ u.be.pC->deferredMoveto = 1;
break;
}
/* Opcode: Found P1 P2 P3 P4 *
+** Synopsis: key=r[P3@P4]
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
@@ -68989,8 +70245,11 @@ case OP_Seek: { /* in2 */
** Cursor P1 is on an index btree. If the record identified by P3 and P4
** is a prefix of any entry in P1 then a jump is made to P2 and
** P1 is left pointing at the matching entry.
+**
+** See also: NotFound, NoConflict, NotExists. SeekGe
*/
/* Opcode: NotFound P1 P2 P3 P4 *
+** Synopsis: key=r[P3@P4]
**
** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
** P4>0 then register P3 is the first of P4 registers that form an unpacked
@@ -69002,173 +70261,122 @@ case OP_Seek: { /* in2 */
** falls through to the next instruction and P1 is left pointing at the
** matching entry.
**
-** See also: Found, NotExists, IsUnique
+** See also: Found, NotExists, NoConflict
*/
+/* Opcode: NoConflict P1 P2 P3 P4 *
+** Synopsis: key=r[P3@P4]
+**
+** If P4==0 then register P3 holds a blob constructed by MakeRecord. If
+** P4>0 then register P3 is the first of P4 registers that form an unpacked
+** record.
+**
+** Cursor P1 is on an index btree. If the record identified by P3 and P4
+** contains any NULL value, jump immediately to P2. If all terms of the
+** record are not-NULL then a check is done to determine if any row in the
+** P1 index btree has a matching key prefix. If there are no matches, jump
+** immediately to P2. If there is a match, fall through and leave the P1
+** cursor pointing to the matching row.
+**
+** This opcode is similar to OP_NotFound with the exceptions that the
+** branch is always taken if any part of the search key input is NULL.
+**
+** See also: NotFound, Found, NotExists
+*/
+case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
-#if 0 /* local variables moved into u.be */
+#if 0 /* local variables moved into u.bf */
int alreadyExists;
+ int ii;
VdbeCursor *pC;
int res;
char *pFree;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
- char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-#endif /* local variables moved into u.be */
+ char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*4 + 7];
+#endif /* local variables moved into u.bf */
#ifdef SQLITE_TEST
- sqlite3_found_count++;
+ if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
#endif
- u.be.alreadyExists = 0;
+ u.bf.alreadyExists = 0;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p4type==P4_INT32 );
- u.be.pC = p->apCsr[pOp->p1];
- assert( u.be.pC!=0 );
+ u.bf.pC = p->apCsr[pOp->p1];
+ assert( u.bf.pC!=0 );
pIn3 = &aMem[pOp->p3];
- if( ALWAYS(u.be.pC->pCursor!=0) ){
-
- assert( u.be.pC->isTable==0 );
- if( pOp->p4.i>0 ){
- u.be.r.pKeyInfo = u.be.pC->pKeyInfo;
- u.be.r.nField = (u16)pOp->p4.i;
- u.be.r.aMem = pIn3;
+ assert( u.bf.pC->pCursor!=0 );
+ assert( u.bf.pC->isTable==0 );
+ if( pOp->p4.i>0 ){
+ u.bf.r.pKeyInfo = u.bf.pC->pKeyInfo;
+ u.bf.r.nField = (u16)pOp->p4.i;
+ u.bf.r.aMem = pIn3;
#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<u.be.r.nField; i++) assert( memIsValid(&u.be.r.aMem[i]) ); }
-#endif
- u.be.r.flags = UNPACKED_PREFIX_MATCH;
- u.be.pIdxKey = &u.be.r;
- }else{
- u.be.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
- u.be.pC->pKeyInfo, u.be.aTempRec, sizeof(u.be.aTempRec), &u.be.pFree
- );
- if( u.be.pIdxKey==0 ) goto no_mem;
- assert( pIn3->flags & MEM_Blob );
- assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
- sqlite3VdbeRecordUnpack(u.be.pC->pKeyInfo, pIn3->n, pIn3->z, u.be.pIdxKey);
- u.be.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
- }
- rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, u.be.pIdxKey, 0, 0, &u.be.res);
- if( pOp->p4.i==0 ){
- sqlite3DbFree(db, u.be.pFree);
+ {
+ int i;
+ for(i=0; i<u.bf.r.nField; i++){
+ assert( memIsValid(&u.bf.r.aMem[i]) );
+ if( i ) REGISTER_TRACE(pOp->p3+i, &u.bf.r.aMem[i]);
+ }
}
- if( rc!=SQLITE_OK ){
- break;
+#endif
+ u.bf.r.flags = UNPACKED_PREFIX_MATCH;
+ u.bf.pIdxKey = &u.bf.r;
+ }else{
+ u.bf.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+ u.bf.pC->pKeyInfo, u.bf.aTempRec, sizeof(u.bf.aTempRec), &u.bf.pFree
+ );
+ if( u.bf.pIdxKey==0 ) goto no_mem;
+ assert( pIn3->flags & MEM_Blob );
+ assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
+ sqlite3VdbeRecordUnpack(u.bf.pC->pKeyInfo, pIn3->n, pIn3->z, u.bf.pIdxKey);
+ u.bf.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+ }
+ if( pOp->opcode==OP_NoConflict ){
+ /* For the OP_NoConflict opcode, take the jump if any of the
+ ** input fields are NULL, since any key with a NULL will not
+ ** conflict */
+ for(u.bf.ii=0; u.bf.ii<u.bf.r.nField; u.bf.ii++){
+ if( u.bf.r.aMem[u.bf.ii].flags & MEM_Null ){
+ pc = pOp->p2 - 1;
+ break;
+ }
}
- u.be.alreadyExists = (u.be.res==0);
- u.be.pC->deferredMoveto = 0;
- u.be.pC->cacheStatus = CACHE_STALE;
}
- if( pOp->opcode==OP_Found ){
- if( u.be.alreadyExists ) pc = pOp->p2 - 1;
- }else{
- if( !u.be.alreadyExists ) pc = pOp->p2 - 1;
+ rc = sqlite3BtreeMovetoUnpacked(u.bf.pC->pCursor, u.bf.pIdxKey, 0, 0, &u.bf.res);
+ if( pOp->p4.i==0 ){
+ sqlite3DbFree(db, u.bf.pFree);
}
- break;
-}
-
-/* Opcode: IsUnique P1 P2 P3 P4 *
-**
-** Cursor P1 is open on an index b-tree - that is to say, a btree which
-** no data and where the key are records generated by OP_MakeRecord with
-** the list field being the integer ROWID of the entry that the index
-** entry refers to.
-**
-** 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 */
-#if 0 /* local variables moved into u.bf */
- u16 ii;
- VdbeCursor *pCx;
- BtCursor *pCrsr;
- u16 nField;
- Mem *aMx;
- UnpackedRecord r; /* B-Tree index search key */
- i64 R; /* Rowid stored in register P3 */
-#endif /* local variables moved into u.bf */
-
- pIn3 = &aMem[pOp->p3];
- u.bf.aMx = &aMem[pOp->p4.i];
- /* 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 );
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
-
- /* Find the index cursor. */
- u.bf.pCx = p->apCsr[pOp->p1];
- assert( u.bf.pCx->deferredMoveto==0 );
- u.bf.pCx->seekResult = 0;
- u.bf.pCx->cacheStatus = CACHE_STALE;
- u.bf.pCrsr = u.bf.pCx->pCursor;
-
- /* If any of the values are NULL, take the jump. */
- u.bf.nField = u.bf.pCx->pKeyInfo->nField;
- for(u.bf.ii=0; u.bf.ii<u.bf.nField; u.bf.ii++){
- if( u.bf.aMx[u.bf.ii].flags & MEM_Null ){
- pc = pOp->p2 - 1;
- u.bf.pCrsr = 0;
- break;
- }
+ if( rc!=SQLITE_OK ){
+ break;
}
- assert( (u.bf.aMx[u.bf.nField].flags & MEM_Null)==0 );
-
- if( u.bf.pCrsr!=0 ){
- /* Populate the index search key. */
- u.bf.r.pKeyInfo = u.bf.pCx->pKeyInfo;
- u.bf.r.nField = u.bf.nField + 1;
- u.bf.r.flags = UNPACKED_PREFIX_SEARCH;
- u.bf.r.aMem = u.bf.aMx;
-#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<u.bf.r.nField; i++) assert( memIsValid(&u.bf.r.aMem[i]) ); }
-#endif
-
- /* Extract the value of u.bf.R from register P3. */
- sqlite3VdbeMemIntegerify(pIn3);
- u.bf.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(u.bf.pCrsr, &u.bf.r, 0, 0, &u.bf.pCx->seekResult);
- if( (u.bf.r.flags & UNPACKED_PREFIX_SEARCH) || u.bf.r.rowid==u.bf.R ){
- pc = pOp->p2 - 1;
- }else{
- pIn3->u.i = u.bf.r.rowid;
- }
+ u.bf.pC->seekResult = u.bf.res;
+ u.bf.alreadyExists = (u.bf.res==0);
+ u.bf.pC->nullRow = 1-u.bf.alreadyExists;
+ u.bf.pC->deferredMoveto = 0;
+ u.bf.pC->cacheStatus = CACHE_STALE;
+ if( pOp->opcode==OP_Found ){
+ if( u.bf.alreadyExists ) pc = pOp->p2 - 1;
+ }else{
+ if( !u.bf.alreadyExists ) pc = pOp->p2 - 1;
}
break;
}
/* Opcode: NotExists P1 P2 P3 * *
+** Synopsis: intkey=r[P3]
**
-** Use the content of register P3 as an integer key. If a record
-** with that key does not exist in table of P1, then jump to P2.
-** If the record does exist, then fall through. The cursor is left
-** pointing to the record if it exists.
+** P1 is the index of a cursor open on an SQL table btree (with integer
+** keys). P3 is an integer rowid. If P1 does not contain a record with
+** rowid P3 then jump immediately to P2. If P1 does contain a record
+** with rowid P3 then leave the cursor pointing at that record and fall
+** through to the next instruction.
**
-** The difference between this operation and NotFound is that this
-** operation assumes the key is an integer and that P1 is a table whereas
-** NotFound assumes key is a blob constructed from MakeRecord and
-** P1 is an index.
+** The OP_NotFound opcode performs the same operation on index btrees
+** (with arbitrary multi-value keys).
**
-** See also: Found, NotFound, IsUnique
+** See also: Found, NotFound, NoConflict
*/
case OP_NotExists: { /* jump, in3 */
#if 0 /* local variables moved into u.bg */
@@ -69186,32 +70394,25 @@ case OP_NotExists: { /* jump, in3 */
assert( u.bg.pC->isTable );
assert( u.bg.pC->pseudoTableReg==0 );
u.bg.pCrsr = u.bg.pC->pCursor;
- if( ALWAYS(u.bg.pCrsr!=0) ){
- u.bg.res = 0;
- u.bg.iKey = pIn3->u.i;
- rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res);
- u.bg.pC->lastRowid = pIn3->u.i;
- u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0;
- u.bg.pC->nullRow = 0;
- u.bg.pC->cacheStatus = CACHE_STALE;
- u.bg.pC->deferredMoveto = 0;
- if( u.bg.res!=0 ){
- pc = pOp->p2 - 1;
- assert( u.bg.pC->rowidIsValid==0 );
- }
- u.bg.pC->seekResult = u.bg.res;
- }else{
- /* This happens when an attempt to open a read cursor on the
- ** sqlite_master table returns SQLITE_EMPTY.
- */
+ assert( u.bg.pCrsr!=0 );
+ u.bg.res = 0;
+ u.bg.iKey = pIn3->u.i;
+ rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res);
+ u.bg.pC->lastRowid = pIn3->u.i;
+ u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0;
+ u.bg.pC->nullRow = 0;
+ u.bg.pC->cacheStatus = CACHE_STALE;
+ u.bg.pC->deferredMoveto = 0;
+ if( u.bg.res!=0 ){
pc = pOp->p2 - 1;
assert( u.bg.pC->rowidIsValid==0 );
- u.bg.pC->seekResult = 0;
}
+ u.bg.pC->seekResult = u.bg.res;
break;
}
/* Opcode: Sequence P1 P2 * * *
+** Synopsis: r[P2]=rowid
**
** Find the next available sequence number for cursor P1.
** Write the sequence number into register P2.
@@ -69227,6 +70428,7 @@ case OP_Sequence: { /* out2-prerelease */
/* Opcode: NewRowid P1 P2 P3 * *
+** Synopsis: r[P2]=rowid
**
** Get a new integer record number (a.k.a "rowid") used as the key to a table.
** The record number is not previously used as a key in the database
@@ -69315,7 +70517,7 @@ case OP_NewRowid: { /* out2-prerelease */
u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3];
}else{
/* Assert that P3 is a valid memory cell. */
- assert( pOp->p3<=p->nMem );
+ assert( pOp->p3<=(p->nMem-p->nCursor) );
u.bh.pMem = &aMem[pOp->p3];
memAboutToChange(p, u.bh.pMem);
}
@@ -69378,6 +70580,7 @@ case OP_NewRowid: { /* out2-prerelease */
}
/* Opcode: Insert P1 P2 P3 P4 P5
+** Synopsis: intkey=r[P3] data=r[P2]
**
** Write an entry into the table of cursor P1. A new entry is
** created if it doesn't already exist or the data for an existing
@@ -69417,6 +70620,7 @@ case OP_NewRowid: { /* out2-prerelease */
** for indices is OP_IdxInsert.
*/
/* Opcode: InsertInt P1 P2 P3 P4 P5
+** Synopsis: intkey=P3 data=r[P2]
**
** This works exactly like OP_Insert except that the key is the
** integer value P3, not the value of the integer stored in register P3.
@@ -69473,7 +70677,7 @@ case OP_InsertInt: {
sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey,
u.bi.pData->z, u.bi.pData->n, u.bi.nZero,
- pOp->p5 & OPFLAG_APPEND, u.bi.seekResult
+ (pOp->p5 & OPFLAG_APPEND)!=0, u.bi.seekResult
);
u.bi.pC->rowidIsValid = 0;
u.bi.pC->deferredMoveto = 0;
@@ -69517,20 +70721,11 @@ case OP_Delete: {
VdbeCursor *pC;
#endif /* local variables moved into u.bj */
- u.bj.iKey = 0;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
u.bj.pC = p->apCsr[pOp->p1];
assert( u.bj.pC!=0 );
assert( u.bj.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
-
- /* If the update-hook will be invoked, set u.bj.iKey to the rowid of the
- ** row being deleted.
- */
- if( db->xUpdateCallback && pOp->p4.z ){
- assert( u.bj.pC->isTable );
- assert( u.bj.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
- u.bj.iKey = u.bj.pC->lastRowid;
- }
+ u.bj.iKey = u.bj.pC->lastRowid; /* Only used for the update hook */
/* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
** OP_Column on the same table without any intervening operations that
@@ -69548,10 +70743,9 @@ case OP_Delete: {
u.bj.pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
- if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
- const char *zDb = db->aDb[u.bj.pC->iDb].zName;
- const char *zTbl = pOp->p4.z;
- db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bj.iKey);
+ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z && u.bj.pC->isTable ){
+ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE,
+ db->aDb[u.bj.pC->iDb].zName, pOp->p4.z, u.bj.iKey);
assert( u.bj.pC->iDb>=0 );
}
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
@@ -69570,23 +70764,34 @@ case OP_ResetCount: {
break;
}
-/* Opcode: SorterCompare P1 P2 P3
+/* Opcode: SorterCompare P1 P2 P3 P4
+** Synopsis: if key(P1)!=rtrim(r[P3],P4) goto P2
+**
+** P1 is a sorter cursor. This instruction compares a prefix of the
+** the record blob in register P3 against a prefix of the entry that
+** the sorter cursor currently points to. The final P4 fields of both
+** the P3 and sorter record are ignored.
+**
+** If either P3 or the sorter contains a NULL in one of their significant
+** fields (not counting the P4 fields at the end which are ignored) then
+** the comparison is assumed to be equal.
**
-** P1 is a sorter cursor. This instruction compares the record blob in
-** register P3 with the entry that the sorter cursor currently points to.
-** If, excluding the rowid fields at the end, the two records are a match,
-** fall through to the next instruction. Otherwise, jump to instruction P2.
+** Fall through to next instruction if the two records compare equal to
+** each other. Jump to P2 if they are different.
*/
case OP_SorterCompare: {
#if 0 /* local variables moved into u.bk */
VdbeCursor *pC;
int res;
+ int nIgnore;
#endif /* local variables moved into u.bk */
u.bk.pC = p->apCsr[pOp->p1];
assert( isSorter(u.bk.pC) );
+ assert( pOp->p4type==P4_INT32 );
pIn3 = &aMem[pOp->p3];
- rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, &u.bk.res);
+ u.bk.nIgnore = pOp->p4.i;
+ rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, u.bk.nIgnore, &u.bk.res);
if( u.bk.res ){
pc = pOp->p2-1;
}
@@ -69594,6 +70799,7 @@ case OP_SorterCompare: {
};
/* Opcode: SorterData P1 P2 * * *
+** Synopsis: r[P2]=data
**
** Write into register P2 the current sorter data for sorter cursor P1.
*/
@@ -69604,12 +70810,13 @@ case OP_SorterData: {
pOut = &aMem[pOp->p2];
u.bl.pC = p->apCsr[pOp->p1];
- assert( u.bl.pC->isSorter );
+ assert( isSorter(u.bl.pC) );
rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
break;
}
/* Opcode: RowData P1 P2 * * *
+** Synopsis: r[P2]=data
**
** Write into register P2 the complete row data for cursor P1.
** There is no interpretation of the data.
@@ -69620,6 +70827,7 @@ case OP_SorterData: {
** of a real table, not a pseudo-table.
*/
/* Opcode: RowKey P1 P2 * * *
+** Synopsis: r[P2]=key
**
** Write into register P2 the complete row key for cursor P1.
** There is no interpretation of the data.
@@ -69644,9 +70852,9 @@ case OP_RowData: {
/* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
u.bm.pC = p->apCsr[pOp->p1];
- assert( u.bm.pC->isSorter==0 );
+ assert( isSorter(u.bm.pC)==0 );
assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData );
- assert( u.bm.pC->isIndex || pOp->opcode==OP_RowData );
+ assert( u.bm.pC->isTable==0 || pOp->opcode==OP_RowData );
assert( u.bm.pC!=0 );
assert( u.bm.pC->nullRow==0 );
assert( u.bm.pC->pseudoTableReg==0 );
@@ -69663,7 +70871,7 @@ case OP_RowData: {
rc = sqlite3VdbeCursorMoveto(u.bm.pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
- if( u.bm.pC->isIndex ){
+ if( u.bm.pC->isTable==0 ){
assert( !u.bm.pC->isTable );
VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
@@ -69683,17 +70891,19 @@ case OP_RowData: {
}
pOut->n = u.bm.n;
MemSetTypeFlag(pOut, MEM_Blob);
- if( u.bm.pC->isIndex ){
+ if( u.bm.pC->isTable==0 ){
rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z);
}else{
rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z);
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
UPDATE_MAX_BLOBSIZE(pOut);
+ REGISTER_TRACE(pOp->p2, pOut);
break;
}
/* Opcode: Rowid P1 P2 * * *
+** Synopsis: r[P2]=rowid
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
@@ -69725,7 +70935,7 @@ case OP_Rowid: { /* out2-prerelease */
u.bn.pModule = u.bn.pVtab->pModule;
assert( u.bn.pModule->xRowid );
rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
- importVtabErrMsg(p, u.bn.pVtab);
+ sqlite3VtabImportErrmsg(p, u.bn.pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( u.bn.pC->pCursor!=0 );
@@ -69758,6 +70968,7 @@ case OP_NullRow: {
assert( u.bo.pC!=0 );
u.bo.pC->nullRow = 1;
u.bo.pC->rowidIsValid = 0;
+ u.bo.pC->cacheStatus = CACHE_STALE;
assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor );
if( u.bo.pC->pCursor ){
sqlite3BtreeClearCursor(u.bo.pC->pCursor);
@@ -69785,9 +70996,8 @@ case OP_Last: { /* jump */
assert( u.bp.pC!=0 );
u.bp.pCrsr = u.bp.pC->pCursor;
u.bp.res = 0;
- if( ALWAYS(u.bp.pCrsr!=0) ){
- rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res);
- }
+ assert( u.bp.pCrsr!=0 );
+ rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res);
u.bp.pC->nullRow = (u8)u.bp.res;
u.bp.pC->deferredMoveto = 0;
u.bp.pC->rowidIsValid = 0;
@@ -69817,7 +71027,7 @@ case OP_Sort: { /* jump */
sqlite3_sort_count++;
sqlite3_search_count--;
#endif
- p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
+ p->aCounter[SQLITE_STMTSTATUS_SORT]++;
/* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
@@ -69838,7 +71048,7 @@ case OP_Rewind: { /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
u.bq.pC = p->apCsr[pOp->p1];
assert( u.bq.pC!=0 );
- assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterSort) );
+ assert( isSorter(u.bq.pC)==(pOp->opcode==OP_SorterSort) );
u.bq.res = 1;
if( isSorter(u.bq.pC) ){
rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res);
@@ -69846,7 +71056,6 @@ case OP_Rewind: { /* jump */
u.bq.pCrsr = u.bq.pC->pCursor;
assert( u.bq.pCrsr );
rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res);
- u.bq.pC->atFirst = u.bq.res==0 ?1:0;
u.bq.pC->deferredMoveto = 0;
u.bq.pC->cacheStatus = CACHE_STALE;
u.bq.pC->rowidIsValid = 0;
@@ -69859,14 +71068,15 @@ case OP_Rewind: { /* jump */
break;
}
-/* Opcode: Next P1 P2 * P4 P5
+/* Opcode: Next P1 P2 * * P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
** to the following instruction. But if the cursor advance was successful,
** jump immediately to P2.
**
-** The P1 cursor must be for a real table, not a pseudo-table.
+** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
+** been opened prior to this opcode or the program will segfault.
**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreeNext().
@@ -69874,7 +71084,12 @@ case OP_Rewind: { /* jump */
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
-** See also: Prev
+** See also: Prev, NextIfOpen
+*/
+/* Opcode: NextIfOpen P1 P2 * * P5
+**
+** This opcode works just like OP_Next except that if cursor P1 is not
+** open it behaves a no-op.
*/
/* Opcode: Prev P1 P2 * * P5
**
@@ -69883,7 +71098,8 @@ case OP_Rewind: { /* jump */
** to the following instruction. But if the cursor backup was successful,
** jump immediately to P2.
**
-** The P1 cursor must be for a real table, not a pseudo-table.
+** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
+** not open then the behavior is undefined.
**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreePrevious().
@@ -69891,47 +71107,56 @@ case OP_Rewind: { /* jump */
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
-case OP_SorterNext: /* jump */
-case OP_Prev: /* jump */
-case OP_Next: { /* jump */
+/* Opcode: PrevIfOpen P1 P2 * * P5
+**
+** This opcode works just like OP_Prev except that if cursor P1 is not
+** open it behaves a no-op.
+*/
+case OP_SorterNext: { /* jump */
#if 0 /* local variables moved into u.br */
VdbeCursor *pC;
int res;
#endif /* local variables moved into u.br */
- CHECK_FOR_INTERRUPT;
+ u.br.pC = p->apCsr[pOp->p1];
+ assert( isSorter(u.br.pC) );
+ rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
+ goto next_tail;
+case OP_PrevIfOpen: /* jump */
+case OP_NextIfOpen: /* jump */
+ if( p->apCsr[pOp->p1]==0 ) break;
+ /* Fall through */
+case OP_Prev: /* jump */
+case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- assert( pOp->p5<=ArraySize(p->aCounter) );
+ assert( pOp->p5<ArraySize(p->aCounter) );
u.br.pC = p->apCsr[pOp->p1];
- if( u.br.pC==0 ){
- break; /* See ticket #2273 */
- }
- assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) );
- if( isSorter(u.br.pC) ){
- assert( pOp->opcode==OP_SorterNext );
- rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
- }else{
- u.br.res = 1;
- assert( u.br.pC->deferredMoveto==0 );
- assert( u.br.pC->pCursor );
- assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
- assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
- rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
- }
- u.br.pC->nullRow = (u8)u.br.res;
+ assert( u.br.pC!=0 );
+ assert( u.br.pC->deferredMoveto==0 );
+ assert( u.br.pC->pCursor );
+ assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
+ assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
+ assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
+ assert( pOp->opcode!=OP_PrevIfOpen || pOp->p4.xAdvance==sqlite3BtreePrevious);
+ rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
+next_tail:
u.br.pC->cacheStatus = CACHE_STALE;
if( u.br.res==0 ){
+ u.br.pC->nullRow = 0;
pc = pOp->p2 - 1;
- if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
+ p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
+ }else{
+ u.br.pC->nullRow = 1;
}
u.br.pC->rowidIsValid = 0;
- break;
+ goto check_for_interrupt;
}
/* Opcode: IdxInsert P1 P2 P3 * P5
+** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions. This opcode writes that key
@@ -69955,31 +71180,32 @@ case OP_IdxInsert: { /* in2 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
u.bs.pC = p->apCsr[pOp->p1];
assert( u.bs.pC!=0 );
- assert( u.bs.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
+ assert( isSorter(u.bs.pC)==(pOp->opcode==OP_SorterInsert) );
pIn2 = &aMem[pOp->p2];
assert( pIn2->flags & MEM_Blob );
u.bs.pCrsr = u.bs.pC->pCursor;
- if( ALWAYS(u.bs.pCrsr!=0) ){
- assert( u.bs.pC->isTable==0 );
- rc = ExpandBlob(pIn2);
- if( rc==SQLITE_OK ){
- if( isSorter(u.bs.pC) ){
- rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2);
- }else{
- u.bs.nKey = pIn2->n;
- u.bs.zKey = pIn2->z;
- rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3,
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0)
- );
- assert( u.bs.pC->deferredMoveto==0 );
- u.bs.pC->cacheStatus = CACHE_STALE;
- }
+ if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
+ assert( u.bs.pCrsr!=0 );
+ assert( u.bs.pC->isTable==0 );
+ rc = ExpandBlob(pIn2);
+ if( rc==SQLITE_OK ){
+ if( isSorter(u.bs.pC) ){
+ rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2);
+ }else{
+ u.bs.nKey = pIn2->n;
+ u.bs.zKey = pIn2->z;
+ rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3,
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0)
+ );
+ assert( u.bs.pC->deferredMoveto==0 );
+ u.bs.pC->cacheStatus = CACHE_STALE;
}
}
break;
}
/* Opcode: IdxDelete P1 P2 P3 * *
+** Synopsis: key=r[P2@P3]
**
** The content of P3 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the
@@ -69994,30 +71220,31 @@ case OP_IdxDelete: {
#endif /* local variables moved into u.bt */
assert( pOp->p3>0 );
- assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
+ assert( pOp->p2>0 && pOp->p2+pOp->p3<=(p->nMem-p->nCursor)+1 );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
u.bt.pC = p->apCsr[pOp->p1];
assert( u.bt.pC!=0 );
u.bt.pCrsr = u.bt.pC->pCursor;
- if( ALWAYS(u.bt.pCrsr!=0) ){
- u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
- u.bt.r.nField = (u16)pOp->p3;
- u.bt.r.flags = 0;
- u.bt.r.aMem = &aMem[pOp->p2];
+ assert( u.bt.pCrsr!=0 );
+ assert( pOp->p5==0 );
+ u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
+ u.bt.r.nField = (u16)pOp->p3;
+ u.bt.r.flags = UNPACKED_PREFIX_MATCH;
+ u.bt.r.aMem = &aMem[pOp->p2];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
+ { int i; for(i=0; i<u.bt.r.nField; i++) assert( memIsValid(&u.bt.r.aMem[i]) ); }
#endif
- rc = sqlite3BtreeMovetoUnpacked(u.bt.pCrsr, &u.bt.r, 0, 0, &u.bt.res);
- if( rc==SQLITE_OK && u.bt.res==0 ){
- rc = sqlite3BtreeDelete(u.bt.pCrsr);
- }
- assert( u.bt.pC->deferredMoveto==0 );
- u.bt.pC->cacheStatus = CACHE_STALE;
+ rc = sqlite3BtreeMovetoUnpacked(u.bt.pCrsr, &u.bt.r, 0, 0, &u.bt.res);
+ if( rc==SQLITE_OK && u.bt.res==0 ){
+ rc = sqlite3BtreeDelete(u.bt.pCrsr);
}
+ assert( u.bt.pC->deferredMoveto==0 );
+ u.bt.pC->cacheStatus = CACHE_STALE;
break;
}
/* Opcode: IdxRowid P1 P2 * * *
+** Synopsis: r[P2]=rowid
**
** Write into register P2 an integer which is the last entry in the record at
** the end of the index key pointed to by cursor P1. This integer should be
@@ -70036,25 +71263,25 @@ case OP_IdxRowid: { /* out2-prerelease */
u.bu.pC = p->apCsr[pOp->p1];
assert( u.bu.pC!=0 );
u.bu.pCrsr = u.bu.pC->pCursor;
+ assert( u.bu.pCrsr!=0 );
pOut->flags = MEM_Null;
- if( ALWAYS(u.bu.pCrsr!=0) ){
- rc = sqlite3VdbeCursorMoveto(u.bu.pC);
- if( NEVER(rc) ) goto abort_due_to_error;
- assert( u.bu.pC->deferredMoveto==0 );
- assert( u.bu.pC->isTable==0 );
- if( !u.bu.pC->nullRow ){
- rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid);
- if( rc!=SQLITE_OK ){
- goto abort_due_to_error;
- }
- pOut->u.i = u.bu.rowid;
- pOut->flags = MEM_Int;
+ rc = sqlite3VdbeCursorMoveto(u.bu.pC);
+ if( NEVER(rc) ) goto abort_due_to_error;
+ assert( u.bu.pC->deferredMoveto==0 );
+ assert( u.bu.pC->isTable==0 );
+ if( !u.bu.pC->nullRow ){
+ rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid);
+ if( rc!=SQLITE_OK ){
+ goto abort_due_to_error;
}
+ pOut->u.i = u.bu.rowid;
+ pOut->flags = MEM_Int;
}
break;
}
/* Opcode: IdxGE P1 P2 P3 P4 P5
+** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
** key that omits the ROWID. Compare this key value against the index
@@ -70069,6 +71296,7 @@ case OP_IdxRowid: { /* out2-prerelease */
** the result is false whereas it would be true with IdxGT.
*/
/* Opcode: IdxLT P1 P2 P3 P4 P5
+** Synopsis: key=r[P3@P4]
**
** The P4 register values beginning with P3 form an unpacked index
** key that omits the ROWID. Compare this key value against the index
@@ -70092,31 +71320,30 @@ case OP_IdxGE: { /* jump */
u.bv.pC = p->apCsr[pOp->p1];
assert( u.bv.pC!=0 );
assert( u.bv.pC->isOrdered );
- if( ALWAYS(u.bv.pC->pCursor!=0) ){
- assert( u.bv.pC->deferredMoveto==0 );
- assert( pOp->p5==0 || pOp->p5==1 );
- assert( pOp->p4type==P4_INT32 );
- u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo;
- u.bv.r.nField = (u16)pOp->p4.i;
- if( pOp->p5 ){
- u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
- }else{
- u.bv.r.flags = UNPACKED_PREFIX_MATCH;
- }
- u.bv.r.aMem = &aMem[pOp->p3];
+ assert( u.bv.pC->pCursor!=0);
+ assert( u.bv.pC->deferredMoveto==0 );
+ assert( pOp->p5==0 || pOp->p5==1 );
+ assert( pOp->p4type==P4_INT32 );
+ u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo;
+ u.bv.r.nField = (u16)pOp->p4.i;
+ if( pOp->p5 ){
+ u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
+ }else{
+ u.bv.r.flags = UNPACKED_PREFIX_MATCH;
+ }
+ u.bv.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; i<u.bv.r.nField; i++) assert( memIsValid(&u.bv.r.aMem[i]) ); }
+ { int i; for(i=0; i<u.bv.r.nField; i++) assert( memIsValid(&u.bv.r.aMem[i]) ); }
#endif
- rc = sqlite3VdbeIdxKeyCompare(u.bv.pC, &u.bv.r, &u.bv.res);
- if( pOp->opcode==OP_IdxLT ){
- u.bv.res = -u.bv.res;
- }else{
- assert( pOp->opcode==OP_IdxGE );
- u.bv.res++;
- }
- if( u.bv.res>0 ){
- pc = pOp->p2 - 1 ;
- }
+ rc = sqlite3VdbeIdxKeyCompare(u.bv.pC, &u.bv.r, &u.bv.res);
+ if( pOp->opcode==OP_IdxLT ){
+ u.bv.res = -u.bv.res;
+ }else{
+ assert( pOp->opcode==OP_IdxGE );
+ u.bv.res++;
+ }
+ if( u.bv.res>0 ){
+ pc = pOp->p2 - 1 ;
}
break;
}
@@ -70149,15 +71376,18 @@ case OP_Destroy: { /* out2-prerelease */
int iDb;
#endif /* local variables moved into u.bw */
+ assert( p->readOnly==0 );
#ifndef SQLITE_OMIT_VIRTUALTABLE
u.bw.iCnt = 0;
for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){
- if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 ){
+ if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->bIsReader
+ && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0
+ ){
u.bw.iCnt++;
}
}
#else
- u.bw.iCnt = db->activeVdbeCnt;
+ u.bw.iCnt = db->nVdbeRead;
#endif
pOut->flags = MEM_Null;
if( u.bw.iCnt>1 ){
@@ -70206,6 +71436,8 @@ case OP_Clear: {
#endif /* local variables moved into u.bx */
u.bx.nChange = 0;
+ assert( p->readOnly==0 );
+ assert( pOp->p1!=1 );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p2))!=0 );
rc = sqlite3BtreeClearTable(
db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
@@ -70222,6 +71454,7 @@ case OP_Clear: {
}
/* Opcode: CreateTable P1 P2 * * *
+** Synopsis: r[P2]=root iDb=P1
**
** Allocate a new table in the main database file if P1==0 or in the
** auxiliary database file if P1==1 or in an attached database if
@@ -70235,6 +71468,7 @@ case OP_Clear: {
** See also: CreateIndex
*/
/* Opcode: CreateIndex P1 P2 * * *
+** Synopsis: r[P2]=root iDb=P1
**
** Allocate a new index in the main database file if P1==0 or in the
** auxiliary database file if P1==1 or in an attached database if
@@ -70254,6 +71488,7 @@ case OP_CreateTable: { /* out2-prerelease */
u.by.pgno = 0;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ assert( p->readOnly==0 );
u.by.pDb = &db->aDb[pOp->p1];
assert( u.by.pDb->pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
@@ -70406,11 +71641,12 @@ case OP_IntegrityCk: {
Mem *pnErr; /* Register keeping track of errors remaining */
#endif /* local variables moved into u.ca */
+ assert( p->bIsReader );
u.ca.nRoot = pOp->p2;
assert( u.ca.nRoot>0 );
u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
if( u.ca.aRoot==0 ) goto no_mem;
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
u.ca.pnErr = &aMem[pOp->p3];
assert( (u.ca.pnErr->flags & MEM_Int)!=0 );
assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
@@ -70440,6 +71676,7 @@ case OP_IntegrityCk: {
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
/* Opcode: RowSetAdd P1 P2 * * *
+** Synopsis: rowset(P1)=r[P2]
**
** Insert the integer value held by register P2 into a boolean index
** held in register P1.
@@ -70459,6 +71696,7 @@ case OP_RowSetAdd: { /* in1, in2 */
}
/* Opcode: RowSetRead P1 P2 P3 * *
+** Synopsis: r[P3]=rowset(P1)
**
** Extract the smallest value from boolean index P1 and put that value into
** register P3. Or, if boolean index P1 is initially empty, leave P3
@@ -70468,7 +71706,7 @@ case OP_RowSetRead: { /* jump, in1, out3 */
#if 0 /* local variables moved into u.cb */
i64 val;
#endif /* local variables moved into u.cb */
- CHECK_FOR_INTERRUPT;
+
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_RowSet)==0
|| sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
@@ -70480,10 +71718,11 @@ case OP_RowSetRead: { /* jump, in1, out3 */
/* A value was pulled from the index */
sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
}
- break;
+ goto check_for_interrupt;
}
/* Opcode: RowSetTest P1 P2 P3 P4
+** Synopsis: if r[P3] in rowset(P1) goto P2
**
** Register P3 is assumed to hold a 64-bit integer value. If register P1
** contains a RowSet object and that RowSet object contains
@@ -70693,6 +71932,7 @@ case OP_Param: { /* out2-prerelease */
#ifndef SQLITE_OMIT_FOREIGN_KEY
/* Opcode: FkCounter P1 P2 * * *
+** Synopsis: fkctr[P1]+=P2
**
** Increment a "constraint counter" by P2 (P2 may be negative or positive).
** If P1 is non-zero, the database constraint counter is incremented
@@ -70700,7 +71940,9 @@ case OP_Param: { /* out2-prerelease */
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
- if( pOp->p1 ){
+ if( db->flags & SQLITE_DeferFKs ){
+ db->nDeferredImmCons += pOp->p2;
+ }else if( pOp->p1 ){
db->nDeferredCons += pOp->p2;
}else{
p->nFkConstraint += pOp->p2;
@@ -70709,6 +71951,7 @@ case OP_FkCounter: {
}
/* Opcode: FkIfZero P1 P2 * * *
+** Synopsis: if fkctr[P1]==0 goto P2
**
** This opcode tests if a foreign key constraint-counter is currently zero.
** If so, jump to instruction P2. Otherwise, fall through to the next
@@ -70721,9 +71964,9 @@ case OP_FkCounter: {
*/
case OP_FkIfZero: { /* jump */
if( pOp->p1 ){
- if( db->nDeferredCons==0 ) pc = pOp->p2-1;
+ if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
}else{
- if( p->nFkConstraint==0 ) pc = pOp->p2-1;
+ if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
}
break;
}
@@ -70731,6 +71974,7 @@ case OP_FkIfZero: { /* jump */
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Opcode: MemMax P1 P2 * * *
+** Synopsis: r[P1]=max(r[P1],r[P2])
**
** P1 is a register in the root frame of this VM (the root frame is
** different from the current frame if this instruction is being executed
@@ -70763,6 +72007,7 @@ case OP_MemMax: { /* in2 */
#endif /* SQLITE_OMIT_AUTOINCREMENT */
/* Opcode: IfPos P1 P2 * * *
+** Synopsis: if r[P1]>0 goto P2
**
** If the value of register P1 is 1 or greater, jump to P2.
**
@@ -70779,6 +72024,7 @@ case OP_IfPos: { /* jump, in1 */
}
/* Opcode: IfNeg P1 P2 * * *
+** Synopsis: if r[P1]<0 goto P2
**
** If the value of register P1 is less than zero, jump to P2.
**
@@ -70795,6 +72041,7 @@ case OP_IfNeg: { /* jump, in1 */
}
/* Opcode: IfZero P1 P2 P3 * *
+** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
**
** The register P1 must contain an integer. Add literal P3 to the
** value in register P1. If the result is exactly 0, jump to P2.
@@ -70813,6 +72060,7 @@ case OP_IfZero: { /* jump, in1 */
}
/* Opcode: AggStep * P2 P3 P4 P5
+** Synopsis: accum=r[P3] step(r[P2@P5])
**
** Execute the step function for an aggregate. The
** function has P5 arguments. P4 is a pointer to the FuncDef
@@ -70844,7 +72092,7 @@ case OP_AggStep: {
sqlite3VdbeMemStoreType(u.cg.pRec);
}
u.cg.ctx.pFunc = pOp->p4.pFunc;
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3];
u.cg.pMem->n++;
u.cg.ctx.s.flags = MEM_Null;
@@ -70855,7 +72103,7 @@ case OP_AggStep: {
u.cg.ctx.isError = 0;
u.cg.ctx.pColl = 0;
u.cg.ctx.skipFlag = 0;
- if( u.cg.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ if( u.cg.ctx.pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>p->aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
@@ -70878,6 +72126,7 @@ case OP_AggStep: {
}
/* Opcode: AggFinal P1 P2 * P4 *
+** Synopsis: accum=r[P1] N=P2
**
** Execute the finalizer function for an aggregate. P1 is
** the memory location that is the accumulator for the aggregate.
@@ -70893,7 +72142,7 @@ case OP_AggFinal: {
#if 0 /* local variables moved into u.ch */
Mem *pMem;
#endif /* local variables moved into u.ch */
- assert( pOp->p1>0 && pOp->p1<=p->nMem );
+ assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
u.ch.pMem = &aMem[pOp->p1];
assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc);
@@ -70927,6 +72176,7 @@ case OP_Checkpoint: {
Mem *pMem; /* Write results here */
#endif /* local variables moved into u.ci */
+ assert( p->readOnly==0 );
u.ci.aRes[0] = 0;
u.ci.aRes[1] = u.ci.aRes[2] = -1;
assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
@@ -70978,6 +72228,7 @@ case OP_JournalMode: { /* out2-prerelease */
|| u.cj.eNew==PAGER_JOURNALMODE_QUERY
);
assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( p->readOnly==0 );
u.cj.pBt = db->aDb[pOp->p1].pBt;
u.cj.pPager = sqlite3BtreePager(u.cj.pBt);
@@ -71001,7 +72252,7 @@ case OP_JournalMode: { /* out2-prerelease */
if( (u.cj.eNew!=u.cj.eOld)
&& (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL)
){
- if( !db->autoCommit || db->activeVdbeCnt>1 ){
+ if( !db->autoCommit || db->nVdbeRead>1 ){
rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, db,
"cannot change %s wal mode from within a transaction",
@@ -71060,6 +72311,7 @@ case OP_JournalMode: { /* out2-prerelease */
** a transaction.
*/
case OP_Vacuum: {
+ assert( p->readOnly==0 );
rc = sqlite3RunVacuum(&p->zErrMsg, db);
break;
}
@@ -71079,6 +72331,7 @@ case OP_IncrVacuum: { /* jump */
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
+ assert( p->readOnly==0 );
u.ck.pBt = db->aDb[pOp->p1].pBt;
rc = sqlite3BtreeIncrVacuum(u.ck.pBt);
if( rc==SQLITE_DONE ){
@@ -71109,6 +72362,7 @@ case OP_Expire: {
#ifndef SQLITE_OMIT_SHARED_CACHE
/* Opcode: TableLock P1 P2 P3 P4 *
+** Synopsis: iDb=P1 root=P2 write=P3
**
** Obtain a lock on a particular table. This instruction is only used when
** the shared-cache feature is enabled.
@@ -71155,7 +72409,7 @@ case OP_VBegin: {
#endif /* local variables moved into u.cl */
u.cl.pVTab = pOp->p4.pVtab;
rc = sqlite3VtabBegin(db, u.cl.pVTab);
- if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab);
+ if( u.cl.pVTab ) sqlite3VtabImportErrmsg(p, u.cl.pVTab->pVtab);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -71201,13 +72455,14 @@ case OP_VOpen: {
sqlite3_module *pModule;
#endif /* local variables moved into u.cm */
+ assert( p->bIsReader );
u.cm.pCur = 0;
u.cm.pVtabCursor = 0;
u.cm.pVtab = pOp->p4.pVtab->pVtab;
u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
assert(u.cm.pVtab && u.cm.pModule);
rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor);
- importVtabErrMsg(p, u.cm.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cm.pVtab);
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
u.cm.pVtabCursor->pVtab = u.cm.pVtab;
@@ -71216,7 +72471,6 @@ case OP_VOpen: {
u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
if( u.cm.pCur ){
u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
- u.cm.pCur->pModule = u.cm.pVtabCursor->pVtab->pModule;
}else{
db->mallocFailed = 1;
u.cm.pModule->xClose(u.cm.pVtabCursor);
@@ -71228,6 +72482,7 @@ case OP_VOpen: {
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
+** Synopsis: iPlan=r[P3] zPlan='P4'
**
** P1 is a cursor opened using VOpen. P2 is an address to jump to if
** the filtered result set is empty.
@@ -71287,7 +72542,7 @@ case OP_VFilter: { /* jump */
p->inVtabMethod = 1;
rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg);
p->inVtabMethod = 0;
- importVtabErrMsg(p, u.cn.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cn.pVtab);
if( rc==SQLITE_OK ){
u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor);
}
@@ -71304,6 +72559,7 @@ case OP_VFilter: { /* jump */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VColumn P1 P2 P3 * *
+** Synopsis: r[P3]=vcolumn(P2)
**
** Store the value of the P2-th column of
** the row of the virtual-table that the
@@ -71319,7 +72575,7 @@ case OP_VColumn: {
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
- assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
u.co.pDest = &aMem[pOp->p3];
memAboutToChange(p, u.co.pDest);
if( pCur->nullRow ){
@@ -71340,7 +72596,7 @@ case OP_VColumn: {
MemSetTypeFlag(&u.co.sContext.s, MEM_Null);
rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2);
- importVtabErrMsg(p, u.co.pVtab);
+ sqlite3VtabImportErrmsg(p, u.co.pVtab);
if( u.co.sContext.isError ){
rc = u.co.sContext.isError;
}
@@ -71395,7 +72651,7 @@ case OP_VNext: { /* jump */
p->inVtabMethod = 1;
rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor);
p->inVtabMethod = 0;
- importVtabErrMsg(p, u.cp.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cp.pVtab);
if( rc==SQLITE_OK ){
u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
}
@@ -71404,7 +72660,7 @@ case OP_VNext: { /* jump */
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
- break;
+ goto check_for_interrupt;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -71425,6 +72681,7 @@ case OP_VRename: {
u.cq.pName = &aMem[pOp->p1];
assert( u.cq.pVtab->pModule->xRename );
assert( memIsValid(u.cq.pName) );
+ assert( p->readOnly==0 );
REGISTER_TRACE(pOp->p1, u.cq.pName);
assert( u.cq.pName->flags & MEM_Str );
testcase( u.cq.pName->enc==SQLITE_UTF8 );
@@ -71433,7 +72690,7 @@ case OP_VRename: {
rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8);
if( rc==SQLITE_OK ){
rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z);
- importVtabErrMsg(p, u.cq.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cq.pVtab);
p->expired = 0;
}
break;
@@ -71442,6 +72699,7 @@ case OP_VRename: {
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VUpdate P1 P2 P3 P4 *
+** Synopsis: data=r[P3@P2]
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** This opcode invokes the corresponding xUpdate method. P2 values
@@ -71478,6 +72736,7 @@ case OP_VUpdate: {
assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
);
+ assert( p->readOnly==0 );
u.cr.pVtab = pOp->p4.pVtab->pVtab;
u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule;
u.cr.nArg = pOp->p2;
@@ -71496,7 +72755,7 @@ case OP_VUpdate: {
db->vtabOnConflict = pOp->p5;
rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
db->vtabOnConflict = vtabOnConflict;
- importVtabErrMsg(p, u.cr.pVtab);
+ sqlite3VtabImportErrmsg(p, u.cr.pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
db->lastRowid = lastRowid = u.cr.rowid;
@@ -71572,6 +72831,16 @@ case OP_Trace: {
db->xTrace(db->pTraceArg, u.cs.z);
sqlite3DbFree(db, u.cs.z);
}
+#ifdef SQLITE_USE_FCNTL_TRACE
+ u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
+ if( u.cs.zTrace ){
+ int i;
+ for(i=0; i<db->nDb; i++){
+ if( ((1<<i) & p->btreeMask)==0 ) continue;
+ sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, u.cs.zTrace);
+ }
+ }
+#endif /* SQLITE_USE_FCNTL_TRACE */
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0
&& (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
@@ -71629,13 +72898,13 @@ default: { /* This is really OP_Noop and OP_Explain */
assert( pc>=-1 && pc<p->nOp );
#ifdef SQLITE_DEBUG
- if( p->trace ){
- if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
+ if( db->flags & SQLITE_VdbeTrace ){
+ if( rc!=0 ) printf("rc=%d\n",rc);
if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){
- registerTrace(p->trace, pOp->p2, &aMem[pOp->p2]);
+ registerTrace(pOp->p2, &aMem[pOp->p2]);
}
if( pOp->opflags & OPFLG_OUT3 ){
- registerTrace(p->trace, pOp->p3, &aMem[pOp->p3]);
+ registerTrace(pOp->p3, &aMem[pOp->p3]);
}
}
#endif /* SQLITE_DEBUG */
@@ -71663,6 +72932,8 @@ vdbe_error_halt:
** top. */
vdbe_return:
db->lastRowid = lastRowid;
+ testcase( nVmStep>0 );
+ p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
sqlite3VdbeLeave(p);
return rc;
@@ -71770,7 +73041,8 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
rc = sqlite3_step(p->pStmt);
if( rc==SQLITE_ROW ){
- u32 type = v->apCsr[0]->aType[p->iCol];
+ VdbeCursor *pC = v->apCsr[0];
+ u32 type = pC->aType[p->iCol];
if( type<12 ){
zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
type==0?"null": type==7?"real": "integer"
@@ -71779,9 +73051,9 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
sqlite3_finalize(p->pStmt);
p->pStmt = 0;
}else{
- p->iOffset = v->apCsr[0]->aOffset[p->iCol];
+ p->iOffset = pC->aType[p->iCol + pC->nField];
p->nByte = sqlite3VdbeSerialTypeLen(type);
- p->pCsr = v->apCsr[0]->pCursor;
+ p->pCsr = pC->pCursor;
sqlite3BtreeEnterCursor(p->pCsr);
sqlite3BtreeCacheOverflow(p->pCsr);
sqlite3BtreeLeaveCursor(p->pCsr);
@@ -71884,6 +73156,10 @@ SQLITE_API int sqlite3_blob_open(
pTab = 0;
sqlite3ErrorMsg(pParse, "cannot open virtual table: %s", zTable);
}
+ if( pTab && !HasRowid(pTab) ){
+ pTab = 0;
+ sqlite3ErrorMsg(pParse, "cannot open table without rowid: %s", zTable);
+ }
#ifndef SQLITE_OMIT_VIEW
if( pTab && pTab->pSelect ){
pTab = 0;
@@ -71941,7 +73217,7 @@ SQLITE_API int sqlite3_blob_open(
#endif
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int j;
- for(j=0; j<pIdx->nColumn; j++){
+ for(j=0; j<pIdx->nKeyCol; j++){
if( pIdx->aiColumn[j]==iCol ){
zFault = "indexed";
}
@@ -72030,6 +73306,7 @@ blob_open_out:
}
sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
+ sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
@@ -72230,7 +73507,7 @@ typedef struct FileWriter FileWriter;
** other key value. If the keys are equal (only possible with two EOF
** values), it doesn't matter which index is stored.
**
-** The (N/4) elements of aTree[] that preceed the final (N/2) described
+** The (N/4) elements of aTree[] that precede the final (N/2) described
** above contains the index of the smallest of each block of 4 iterators.
** And so on. So that aTree[1] contains the index of the iterator that
** currently points to the smallest key value. aTree[0] is unused.
@@ -72562,7 +73839,7 @@ static int vdbeSorterIterInit(
*/
static void vdbeSorterCompare(
const VdbeCursor *pCsr, /* Cursor object (for pKeyInfo) */
- int bOmitRowid, /* Ignore rowid field at end of keys */
+ int nIgnore, /* Ignore the last nIgnore fields */
const void *pKey1, int nKey1, /* Left side of comparison */
const void *pKey2, int nKey2, /* Right side of comparison */
int *pRes /* OUT: Result of comparison */
@@ -72576,8 +73853,8 @@ static void vdbeSorterCompare(
sqlite3VdbeRecordUnpack(pKeyInfo, nKey2, pKey2, r2);
}
- if( bOmitRowid ){
- r2->nField = pKeyInfo->nField;
+ if( nIgnore ){
+ r2->nField = pKeyInfo->nField - nIgnore;
assert( r2->nField>0 );
for(i=0; i<r2->nField; i++){
if( r2->aMem[i].flags & MEM_Null ){
@@ -73203,13 +74480,14 @@ SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *pCsr, Mem *pOut){
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
const VdbeCursor *pCsr, /* Sorter cursor */
Mem *pVal, /* Value to compare to current sorter key */
+ int nIgnore, /* Ignore this many fields at the end */
int *pRes /* OUT: Result of comparison */
){
VdbeSorter *pSorter = pCsr->pSorter;
void *pKey; int nKey; /* Sorter key to compare pVal with */
pKey = vdbeSorterRowkey(pSorter, &nKey);
- vdbeSorterCompare(pCsr, 1, pVal->z, pVal->n, pKey, nKey, pRes);
+ vdbeSorterCompare(pCsr, nIgnore, pVal->z, pVal->n, pKey, nKey, pRes);
return SQLITE_OK;
}
@@ -73505,12 +74783,6 @@ typedef struct FileChunk FileChunk;
*/
#define JOURNAL_CHUNKSIZE ((int)(1024-sizeof(FileChunk*)))
-/* Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
/*
** The rollback journal is composed of a linked list of these structures.
*/
@@ -73780,7 +75052,7 @@ SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
testcase( ExprHasProperty(pExpr, EP_Reduced) );
rc = pWalker->xExprCallback(pWalker, pExpr);
if( rc==WRC_Continue
- && !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){
+ && !ExprHasProperty(pExpr,EP_TokenOnly) ){
if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
@@ -73947,7 +75219,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** column reference is so that the column reference will be recognized as
** usable by indices within the WHERE clause processing logic.
**
-** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
+** The TK_AS operator is inhibited if zType[0]=='G'. This means
** that in a GROUP BY clause, the expression is evaluated twice. Hence:
**
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
@@ -73957,8 +75229,9 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
**
** The result of random()%5 in the GROUP BY clause is probably different
-** from the result in the result-set. We might fix this someday. Or
-** then again, we might not...
+** from the result in the result-set. On the other hand Standard SQL does
+** not allow the GROUP BY clause to contain references to result-set columns.
+** So this should never come up in well-formed queries.
**
** If the reference is followed by a COLLATE operator, then make sure
** the COLLATE operator is preserved. For example:
@@ -73998,10 +75271,11 @@ static void resolveAlias(
incrAggFunctionDepth(pDup, nSubquery);
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
if( pDup==0 ) return;
- if( pEList->a[iCol].iAlias==0 ){
- pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
+ ExprSetProperty(pDup, EP_Skip);
+ if( pEList->a[iCol].u.x.iAlias==0 ){
+ pEList->a[iCol].u.x.iAlias = (u16)(++pParse->nAlias);
}
- pDup->iTable = pEList->a[iCol].iAlias;
+ pDup->iTable = pEList->a[iCol].u.x.iAlias;
}
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
@@ -74020,7 +75294,7 @@ static void resolveAlias(
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
- pExpr->flags2 |= EP2_MallocedToken;
+ pExpr->flags |= EP_MemToken;
}
sqlite3DbFree(db, pDup);
}
@@ -74116,27 +75390,38 @@ static int lookupName(
struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
NameContext *pTopNC = pNC; /* First namecontext in the list */
Schema *pSchema = 0; /* Schema of the expression */
- int isTrigger = 0;
+ int isTrigger = 0; /* True if resolved to a trigger column */
+ Table *pTab = 0; /* Table hold the row */
+ Column *pCol; /* A column of pTab */
assert( pNC ); /* the name context cannot be NULL. */
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
- assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
/* Initialize the node to no-match */
pExpr->iTable = -1;
pExpr->pTab = 0;
- ExprSetIrreducible(pExpr);
+ ExprSetVVAProperty(pExpr, EP_NoReduce);
/* Translate the schema name in zDb into a pointer to the corresponding
** schema. If not found, pSchema will remain NULL and nothing will match
** resulting in an appropriate error message toward the end of this routine
*/
if( zDb ){
- for(i=0; i<db->nDb; i++){
- assert( db->aDb[i].zName );
- if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
- pSchema = db->aDb[i].pSchema;
- break;
+ testcase( pNC->ncFlags & NC_PartIdx );
+ testcase( pNC->ncFlags & NC_IsCheck );
+ if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){
+ /* Silently ignore database qualifiers inside CHECK constraints and partial
+ ** indices. Do not raise errors because that might break legacy and
+ ** because it does not hurt anything to just ignore the database name. */
+ zDb = 0;
+ }else{
+ for(i=0; i<db->nDb; i++){
+ assert( db->aDb[i].zName );
+ if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
+ pSchema = db->aDb[i].pSchema;
+ break;
+ }
}
}
}
@@ -74148,9 +75433,6 @@ static int lookupName(
if( pSrcList ){
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
- Table *pTab;
- Column *pCol;
-
pTab = pItem->pTab;
assert( pTab!=0 && pTab->zName!=0 );
assert( pTab->nCol>0 );
@@ -74210,9 +75492,8 @@ static int lookupName(
/* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference
*/
- if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){
+ if( zDb==0 && zTab!=0 && cntTab==0 && pParse->pTriggerTab!=0 ){
int op = pParse->eTriggerOp;
- Table *pTab = 0;
assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
if( op!=TK_DELETE && sqlite3StrICmp("new",zTab) == 0 ){
pExpr->iTable = 1;
@@ -74226,8 +75507,7 @@ static int lookupName(
int iCol;
pSchema = pTab->pSchema;
cntTab++;
- for(iCol=0; iCol<pTab->nCol; iCol++){
- Column *pCol = &pTab->aCol[iCol];
+ for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
if( iCol==pTab->iPKey ){
iCol = -1;
@@ -74235,8 +75515,10 @@ static int lookupName(
break;
}
}
- if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) ){
- iCol = -1; /* IMP: R-44911-55124 */
+ if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
+ /* IMP: R-24309-18625 */
+ /* IMP: R-44911-55124 */
+ iCol = -1;
}
if( iCol<pTab->nCol ){
cnt++;
@@ -74262,7 +75544,8 @@ static int lookupName(
/*
** Perhaps the name is a reference to the ROWID
*/
- if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+ assert( pTab!=0 || cntTab==0 );
+ if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) && HasRowid(pTab) ){
cnt = 1;
pExpr->iColumn = -1; /* IMP: R-44911-55124 */
pExpr->affinity = SQLITE_AFF_INTEGER;
@@ -74279,10 +75562,16 @@ static int lookupName(
** forms the result set entry ("a+b" in the example) and return immediately.
** Note that the expression in the result set should have already been
** resolved by the time the WHERE clause is resolved.
+ **
+ ** The ability to use an output result-set column in the WHERE, GROUP BY,
+ ** or HAVING clauses, or as part of a larger expression in the ORDRE BY
+ ** clause is not standard SQL. This is a (goofy) SQLite extension, that
+ ** is supported for backwards compatibility only. TO DO: Issue a warning
+ ** on sqlite3_log() whenever the capability is used.
*/
if( (pEList = pNC->pEList)!=0
&& zTab==0
- && ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0)
+ && cnt==0
){
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zName;
@@ -74415,6 +75704,52 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
}
/*
+** Report an error that an expression is not valid for a partial index WHERE
+** clause.
+*/
+static void notValidPartIdxWhere(
+ Parse *pParse, /* Leave error message here */
+ NameContext *pNC, /* The name context */
+ const char *zMsg /* Type of error */
+){
+ if( (pNC->ncFlags & NC_PartIdx)!=0 ){
+ sqlite3ErrorMsg(pParse, "%s prohibited in partial index WHERE clauses",
+ zMsg);
+ }
+}
+
+#ifndef SQLITE_OMIT_CHECK
+/*
+** Report an error that an expression is not valid for a CHECK constraint.
+*/
+static void notValidCheckConstraint(
+ Parse *pParse, /* Leave error message here */
+ NameContext *pNC, /* The name context */
+ const char *zMsg /* Type of error */
+){
+ if( (pNC->ncFlags & NC_IsCheck)!=0 ){
+ sqlite3ErrorMsg(pParse,"%s prohibited in CHECK constraints", zMsg);
+ }
+}
+#else
+# define notValidCheckConstraint(P,N,M)
+#endif
+
+/*
+** Expression p should encode a floating point value between 1.0 and 0.0.
+** Return 1024 times this value. Or return -1 if p is not a floating point
+** value between 1.0 and 0.0.
+*/
+static int exprProbability(Expr *p){
+ double r = -1.0;
+ if( p->op!=TK_FLOAT ) return -1;
+ sqlite3AtoF(p->u.zToken, &r, sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
+ assert( r>=0.0 );
+ if( r>1.0 ) return -1;
+ return (int)(r*1000.0);
+}
+
+/*
** This routine is callback for sqlite3WalkExpr().
**
** Resolve symbolic names into TK_COLUMN operators for the current
@@ -74434,7 +75769,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pParse = pNC->pParse;
assert( pParse==pWalker->pParse );
- if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
+ if( ExprHasProperty(pExpr, EP_Resolved) ) return WRC_Prune;
ExprSetProperty(pExpr, EP_Resolved);
#ifndef NDEBUG
if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
@@ -74498,7 +75833,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
/* Resolve function names
*/
- case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pList = pExpr->x.pList; /* The argument list */
int n = pList ? pList->nExpr : 0; /* Number of arguments */
@@ -74511,8 +75845,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
- testcase( pExpr->op==TK_CONST_FUNC );
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ notValidPartIdxWhere(pParse, pNC, "functions");
zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId);
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
@@ -74525,6 +75859,23 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
}else{
is_agg = pDef->xFunc==0;
+ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
+ ExprSetProperty(pExpr, EP_Unlikely|EP_Skip);
+ if( n==2 ){
+ pExpr->iTable = exprProbability(pList->a[1].pExpr);
+ if( pExpr->iTable<0 ){
+ sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
+ "constant between 0.0 and 1.0");
+ pNC->nErr++;
+ }
+ }else{
+ /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
+ ** likelihood(X, 0.0625).
+ ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
+ ** likelihood(X,0.0625). */
+ pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */
+ }
+ }
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pDef ){
@@ -74538,6 +75889,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pExpr->op = TK_NULL;
return WRC_Prune;
}
+ if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant);
}
#endif
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
@@ -74578,11 +75930,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_IN );
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
- if( (pNC->ncFlags & NC_IsCheck)!=0 ){
- sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
- }
-#endif
+ notValidCheckConstraint(pParse, pNC, "subqueries");
+ notValidPartIdxWhere(pParse, pNC, "subqueries");
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
@@ -74591,14 +75940,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
break;
}
-#ifndef SQLITE_OMIT_CHECK
case TK_VARIABLE: {
- if( (pNC->ncFlags & NC_IsCheck)!=0 ){
- sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
- }
+ notValidCheckConstraint(pParse, pNC, "parameters");
+ notValidPartIdxWhere(pParse, pNC, "parameters");
break;
}
-#endif
}
return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
}
@@ -74689,7 +76035,7 @@ static int resolveOrderByTermToExprList(
** result-set entry.
*/
for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprCompare(pEList->a[i].pExpr, pE)<2 ){
+ if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){
return i+1;
}
}
@@ -74795,7 +76141,7 @@ static int resolveCompoundOrderBy(
pItem->pExpr->pLeft = pNew;
}
sqlite3ExprDelete(db, pE);
- pItem->iOrderByCol = (u16)iCol;
+ pItem->u.x.iOrderByCol = (u16)iCol;
pItem->done = 1;
}else{
moreToDo = 1;
@@ -74816,8 +76162,8 @@ static int resolveCompoundOrderBy(
/*
** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
** the SELECT statement pSelect. If any term is reference to a
-** result set expression (as determined by the ExprList.a.iCol field)
-** then convert that term into a copy of the corresponding result set
+** result set expression (as determined by the ExprList.a.u.x.iOrderByCol
+** field) then convert that term into a copy of the corresponding result set
** column.
**
** If any errors are detected, add an error message to pParse and
@@ -74844,12 +76190,12 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
pEList = pSelect->pEList;
assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
- if( pItem->iOrderByCol ){
- if( pItem->iOrderByCol>pEList->nExpr ){
+ if( pItem->u.x.iOrderByCol ){
+ if( pItem->u.x.iOrderByCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
return 1;
}
- resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0);
+ resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0);
}
}
return 0;
@@ -74864,7 +76210,7 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
** If the order-by term is an integer I between 1 and N (where N is the
** number of columns in the result set of the SELECT) then the expression
** in the resolution is a copy of the I-th result-set expression. If
-** the order-by term is an identify that corresponds to the AS-name of
+** the order-by term is an identifier that corresponds to the AS-name of
** a result-set expression, then the term resolves to a copy of the
** result-set expression. Otherwise, the expression is resolved in
** the usual way - using sqlite3ResolveExprNames().
@@ -74890,16 +76236,19 @@ static int resolveOrderGroupBy(
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
- iCol = resolveAsName(pParse, pSelect->pEList, pE);
- if( iCol>0 ){
- /* If an AS-name match is found, mark this ORDER BY column as being
- ** a copy of the iCol-th result-set column. The subsequent call to
- ** sqlite3ResolveOrderGroupBy() will convert the expression to a
- ** copy of the iCol-th result-set expression. */
- pItem->iOrderByCol = (u16)iCol;
- continue;
+ Expr *pE2 = sqlite3ExprSkipCollate(pE);
+ if( zType[0]!='G' ){
+ iCol = resolveAsName(pParse, pSelect->pEList, pE2);
+ if( iCol>0 ){
+ /* If an AS-name match is found, mark this ORDER BY column as being
+ ** a copy of the iCol-th result-set column. The subsequent call to
+ ** sqlite3ResolveOrderGroupBy() will convert the expression to a
+ ** copy of the iCol-th result-set expression. */
+ pItem->u.x.iOrderByCol = (u16)iCol;
+ continue;
+ }
}
- if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
+ if( sqlite3ExprIsInteger(pE2, &iCol) ){
/* The ORDER BY term is an integer constant. Again, set the column
** number so that sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
@@ -74907,18 +76256,18 @@ static int resolveOrderGroupBy(
resolveOutOfRangeError(pParse, zType, i+1, nResult);
return 1;
}
- pItem->iOrderByCol = (u16)iCol;
+ pItem->u.x.iOrderByCol = (u16)iCol;
continue;
}
/* Otherwise, treat the ORDER BY term as an ordinary expression */
- pItem->iOrderByCol = 0;
+ pItem->u.x.iOrderByCol = 0;
if( sqlite3ResolveExprNames(pNC, pE) ){
return 1;
}
for(j=0; j<pSelect->pEList->nExpr; j++){
- if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr)==0 ){
- pItem->iOrderByCol = j+1;
+ if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
+ pItem->u.x.iOrderByCol = j+1;
}
}
}
@@ -75042,7 +76391,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
- /* Add the expression list to the name-context before parsing the
+ /* Add the output column list to the name-context before parsing the
** other expressions in the SELECT statement. This is so that
** expressions in the WHERE clause (etc.) can refer to expressions by
** aliases in the result set.
@@ -75051,10 +76400,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** re-evaluated for each reference to it.
*/
sNC.pEList = p->pEList;
- sNC.ncFlags |= NC_AsMaybe;
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
- sNC.ncFlags &= ~NC_AsMaybe;
/* The ORDER BY and GROUP BY clauses may not refer to terms in
** outer queries
@@ -75224,6 +76571,48 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
sqlite3WalkSelect(&w, p);
}
+/*
+** Resolve names in expressions that can only reference a single table:
+**
+** * CHECK constraints
+** * WHERE clauses on partial indices
+**
+** The Expr.iTable value for Expr.op==TK_COLUMN nodes of the expression
+** is set to -1 and the Expr.iColumn value is set to the column number.
+**
+** Any errors cause an error message to be set in pParse.
+*/
+SQLITE_PRIVATE void sqlite3ResolveSelfReference(
+ Parse *pParse, /* Parsing context */
+ Table *pTab, /* The table being referenced */
+ int type, /* NC_IsCheck or NC_PartIdx */
+ Expr *pExpr, /* Expression to resolve. May be NULL. */
+ ExprList *pList /* Expression list to resolve. May be NUL. */
+){
+ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
+ NameContext sNC; /* Name context for pParse->pNewTable */
+ int i; /* Loop counter */
+
+ assert( type==NC_IsCheck || type==NC_PartIdx );
+ memset(&sNC, 0, sizeof(sNC));
+ memset(&sSrc, 0, sizeof(sSrc));
+ sSrc.nSrc = 1;
+ sSrc.a[0].zName = pTab->zName;
+ sSrc.a[0].pTab = pTab;
+ sSrc.a[0].iCursor = -1;
+ sNC.pParse = pParse;
+ sNC.pSrcList = &sSrc;
+ sNC.ncFlags = type;
+ if( sqlite3ResolveExprNames(&sNC, pExpr) ) return;
+ if( pList ){
+ for(i=0; i<pList->nExpr; i++){
+ if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
+ return;
+ }
+ }
+ }
+}
+
/************** End of resolve.c *********************************************/
/************** Begin file expr.c ********************************************/
/*
@@ -75268,7 +76657,7 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
- return sqlite3AffinityType(pExpr->u.zToken);
+ return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
@@ -75297,7 +76686,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Toke
Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
if( pNew ){
pNew->pLeft = pExpr;
- pNew->flags |= EP_Collate;
+ pNew->flags |= EP_Collate|EP_Skip;
pExpr = pNew;
}
}
@@ -75312,13 +76701,21 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, con
}
/*
-** Skip over any TK_COLLATE and/or TK_AS operators at the root of
-** an expression.
+** Skip over any TK_COLLATE or TK_AS operators and any unlikely()
+** or likelihood() function at the root of an expression.
*/
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
- while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
- pExpr = pExpr->pLeft;
- }
+ while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
+ if( ExprHasProperty(pExpr, EP_Unlikely) ){
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ assert( pExpr->x.pList->nExpr>0 );
+ assert( pExpr->op==TK_FUNCTION );
+ pExpr = pExpr->x.pList->a[0].pExpr;
+ }else{
+ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS );
+ pExpr = pExpr->pLeft;
+ }
+ }
return pExpr;
}
@@ -75341,8 +76738,7 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
p = p->pLeft;
continue;
}
- assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
- if( op==TK_COLLATE ){
+ if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
@@ -75824,7 +77220,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
const char *z;
if( pExpr==0 ) return;
- assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
+ assert( !ExprHasProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
z = pExpr->u.zToken;
assert( z!=0 );
assert( z[0]!=0 );
@@ -75894,12 +77290,12 @@ SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p==0 ) return;
/* Sanity check: Assert that the IntValue is non-negative if it exists */
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
- if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
+ if( !ExprHasProperty(p, EP_TokenOnly) ){
+ /* The Expr.x union is never used at the same time as Expr.pRight */
+ assert( p->x.pList==0 || p->pRight==0 );
sqlite3ExprDelete(db, p->pLeft);
sqlite3ExprDelete(db, p->pRight);
- if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){
- sqlite3DbFree(db, p->u.zToken);
- }
+ if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
if( ExprHasProperty(p, EP_xIsSelect) ){
sqlite3SelectDelete(db, p->x.pSelect);
}else{
@@ -75959,16 +77355,19 @@ static int exprStructSize(Expr *p){
static int dupedExprStructSize(Expr *p, int flags){
int nSize;
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
+ assert( EXPR_FULLSIZE<=0xfff );
+ assert( (0xfff & (EP_Reduced|EP_TokenOnly))==0 );
if( 0==(flags&EXPRDUP_REDUCE) ){
nSize = EXPR_FULLSIZE;
}else{
- assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
+ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(p, EP_FromJoin) );
- assert( (p->flags2 & EP2_MallocedToken)==0 );
- assert( (p->flags2 & EP2_Irreducible)==0 );
- if( p->pLeft || p->pRight || p->x.pList ){
+ assert( !ExprHasProperty(p, EP_MemToken) );
+ assert( !ExprHasProperty(p, EP_NoReduce) );
+ if( p->pLeft || p->x.pList ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
}else{
+ assert( p->pRight==0 );
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
}
}
@@ -76062,7 +77461,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
}
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
- pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
+ pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
pNew->flags |= staticFlag;
@@ -76082,7 +77481,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
}
/* Fill in pNew->pLeft and pNew->pRight. */
- if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){
+ if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
zAlloc += dupedExprNodeSize(p, flags);
if( ExprHasProperty(pNew, EP_Reduced) ){
pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
@@ -76092,8 +77491,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
*pzBuffer = zAlloc;
}
}else{
- pNew->flags2 = 0;
- if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
+ if( !ExprHasProperty(p, EP_TokenOnly) ){
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
@@ -76147,8 +77545,8 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags)
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortOrder = pOldItem->sortOrder;
pItem->done = 0;
- pItem->iOrderByCol = pOldItem->iOrderByCol;
- pItem->iAlias = pOldItem->iAlias;
+ pItem->bSpanIsTab = pOldItem->bSpanIsTab;
+ pItem->u = pOldItem->u;
}
return pNew;
}
@@ -76402,16 +77800,19 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* If pWalker->u.i is 3 then any term of the expression that comes from
** the ON or USING clauses of a join disqualifies the expression
** from being considered constant. */
- if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
+ if( pWalker->u.i==3 && ExprHasProperty(pExpr, EP_FromJoin) ){
pWalker->u.i = 0;
return WRC_Abort;
}
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
- ** and pWalker->u.i==2 */
+ ** and either pWalker->u.i==2 or the function as the SQLITE_FUNC_CONST
+ ** flag. */
case TK_FUNCTION:
- if( pWalker->u.i==2 ) return 0;
+ if( pWalker->u.i==2 || ExprHasProperty(pExpr,EP_Constant) ){
+ return WRC_Continue;
+ }
/* Fall through */
case TK_ID:
case TK_COLUMN:
@@ -76505,6 +77906,7 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr *p, int *pValue){
case TK_UMINUS: {
int v;
if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+ assert( v!=(-2147483647-1) );
*pValue = -v;
rc = 1;
}
@@ -76748,8 +78150,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
Expr *pExpr; /* Expression <column> */
- int iCol; /* Index of column <column> */
- int iDb; /* Database idx for pTab */
+ i16 iCol; /* Index of column <column> */
+ i16 iDb; /* Database idx for pTab */
assert( p ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
@@ -76757,7 +78159,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
pTab = p->pSrc->a[0].pTab;
pExpr = p->pEList->a[0].pExpr;
- iCol = pExpr->iColumn;
+ iCol = (i16)pExpr->iColumn;
/* Code an OP_VerifyCookie and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -76795,16 +78197,11 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
if( (pIdx->aiColumn[0]==iCol)
&& sqlite3FindCollSeq(db, ENC(db), pIdx->azColl[0], 0)==pReq
- && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
+ && (!mustBeUnique || (pIdx->nKeyCol==1 && pIdx->onError!=OE_None))
){
- int iAddr;
- char *pKey;
-
- pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
- iAddr = sqlite3CodeOnce(pParse);
-
- sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
- pKey,P4_KEYINFO_HANDOFF);
+ int iAddr = sqlite3CodeOnce(pParse);
+ sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "%s", pIdx->zName));
assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
@@ -76823,16 +78220,16 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
/* Could not found an existing table or index to use as the RHS b-tree.
** We will have to generate an ephemeral table to do the job.
*/
- double savedNQueryLoop = pParse->nQueryLoop;
+ u32 savedNQueryLoop = pParse->nQueryLoop;
int rMayHaveNull = 0;
eType = IN_INDEX_EPH;
if( prNotFound ){
*prNotFound = rMayHaveNull = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
}else{
- testcase( pParse->nQueryLoop>(double)1 );
- pParse->nQueryLoop = (double)1;
- if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
+ testcase( pParse->nQueryLoop>0 );
+ pParse->nQueryLoop = 0;
+ if( pX->pLeft->iColumn<0 && !ExprHasProperty(pX, EP_xIsSelect) ){
eType = IN_INDEX_ROWID;
}
}
@@ -76873,7 +78270,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
**
** If rMayHaveNull is zero, that means that the subquery is being used
** for membership testing only. There is no need to initialize any
-** registers to indicate the presense or absence of NULLs on the RHS.
+** registers to indicate the presence or absence of NULLs on the RHS.
**
** For a SELECT or EXISTS operator, return the register that holds the
** result. For IN operators or if an error occurs, the return value is 0.
@@ -76901,7 +78298,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
** If all of the above are false, then we can run this code just once
** save the results, and reuse the same result on subsequent invocations.
*/
- if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){
+ if( !ExprHasProperty(pExpr, EP_VarSelect) ){
testAddr = sqlite3CodeOnce(pParse);
}
@@ -76918,10 +78315,9 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
switch( pExpr->op ){
case TK_IN: {
char affinity; /* Affinity of the LHS of the IN */
- KeyInfo keyInfo; /* Keyinfo for the generated table */
- static u8 sortOrder = 0; /* Fake aSortOrder for keyInfo */
int addr; /* Address of OP_OpenEphemeral instruction */
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
+ KeyInfo *pKeyInfo = 0; /* Key information */
if( rMayHaveNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
@@ -76945,9 +78341,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
pExpr->iTable = pParse->nTab++;
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
- memset(&keyInfo, 0, sizeof(keyInfo));
- keyInfo.nField = 1;
- keyInfo.aSortOrder = &sortOrder;
+ pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* Case 1: expr IN (SELECT ...)
@@ -76963,14 +78357,18 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
dest.affSdst = (u8)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pExpr->x.pSelect->iLimit = 0;
+ testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
+ sqlite3KeyInfoUnref(pKeyInfo);
return 0;
}
pEList = pExpr->x.pSelect->pEList;
- if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){
- keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
- pEList->a[0].pExpr);
- }
+ assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
+ assert( pEList!=0 );
+ assert( pEList->nExpr>0 );
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
+ pEList->a[0].pExpr);
}else if( ALWAYS(pExpr->x.pList!=0) ){
/* Case 2: expr IN (exprlist)
**
@@ -76987,8 +78385,10 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
if( !affinity ){
affinity = SQLITE_AFF_NONE;
}
- keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- keyInfo.aSortOrder = &sortOrder;
+ if( pKeyInfo ){
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+ }
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
@@ -77027,8 +78427,8 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
- if( !isRowid ){
- sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
+ if( pKeyInfo ){
+ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
}
break;
}
@@ -77069,7 +78469,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
return 0;
}
rReg = dest.iSDParm;
- ExprSetIrreducible(pExpr);
+ ExprSetVVAProperty(pExpr, EP_NoReduce);
break;
}
}
@@ -77429,15 +78829,19 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
Vdbe *v, /* The VDBE under construction */
Table *pTab, /* The table containing the value */
- int iTabCur, /* The cursor for this table */
+ int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */
int iCol, /* Index of the column to extract */
- int regOut /* Extract the valud into this register */
+ int regOut /* Extract the value into this register */
){
if( iCol<0 || iCol==pTab->iPKey ){
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
}else{
int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
- sqlite3VdbeAddOp3(v, op, iTabCur, iCol, regOut);
+ int x = iCol;
+ if( !HasRowid(pTab) ){
+ x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
+ }
+ sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
}
if( iCol>=0 ){
sqlite3ColumnDefault(v, pTab, iCol, regOut);
@@ -77542,6 +78946,16 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
#endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */
/*
+** Convert an expression node to a TK_REGISTER
+*/
+static void exprToRegister(Expr *p, int iReg){
+ p->op2 = p->op;
+ p->op = TK_REGISTER;
+ p->iTable = iReg;
+ ExprClearProperty(p, EP_Skip);
+}
+
+/*
** Generate code into the current Vdbe to evaluate the given
** expression. Attempt to store the results in register "target".
** Return the register where results are stored.
@@ -77560,6 +78974,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
int regFree2 = 0; /* If non-zero free this temporary register */
int r1, r2, r3, r4; /* Various register numbers */
sqlite3 *db = pParse->db; /* The database connection */
+ Expr tempX; /* Temporary expression node */
assert( target>0 && target<=pParse->nMem );
if( v==0 ){
@@ -77588,15 +79003,20 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
/* Otherwise, fall thru into the TK_COLUMN case */
}
case TK_COLUMN: {
- if( pExpr->iTable<0 ){
- /* This only happens when coding check constraints */
- assert( pParse->ckBase>0 );
- inReg = pExpr->iColumn + pParse->ckBase;
- }else{
- inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
- pExpr->iColumn, pExpr->iTable, target,
- pExpr->op2);
+ int iTab = pExpr->iTable;
+ if( iTab<0 ){
+ if( pParse->ckBase>0 ){
+ /* Generating CHECK constraints or inserting into partial index */
+ inReg = pExpr->iColumn + pParse->ckBase;
+ break;
+ }else{
+ /* Deleting from a partial index */
+ iTab = pParse->iPartIdxTab;
+ }
}
+ inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+ pExpr->iColumn, iTab, target,
+ pExpr->op2);
break;
}
case TK_INTEGER: {
@@ -77661,7 +79081,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
int aff, to_op;
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
assert( !ExprHasProperty(pExpr, EP_IntValue) );
- aff = sqlite3AffinityType(pExpr->u.zToken);
+ aff = sqlite3AffinityType(pExpr->u.zToken, 0);
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
@@ -77774,8 +79194,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
codeReal(v, pLeft->u.zToken, 1, target);
#endif
}else{
- regFree1 = r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
+ tempX.op = TK_INTEGER;
+ tempX.flags = EP_IntValue|EP_TokenOnly;
+ tempX.u.iValue = 0;
+ r1 = sqlite3ExprCodeTemp(pParse, &tempX, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
testcase( regFree2==0 );
@@ -77820,7 +79242,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
break;
}
- case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
int nFarg; /* Number of function arguments */
@@ -77833,9 +79254,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
CollSeq *pColl = 0; /* A collating sequence */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- testcase( op==TK_CONST_FUNC );
- testcase( op==TK_FUNCTION );
- if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
+ if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
@@ -77854,7 +79273,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
** IFNULL() functions. This avoids unnecessary evalation of
** arguments past the first non-NULL argument.
*/
- if( pDef->flags & SQLITE_FUNC_COALESCE ){
+ if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
int endCoalesce = sqlite3VdbeMakeLabel(v);
assert( nFarg>=2 );
sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
@@ -77869,16 +79288,37 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
+ /* The UNLIKELY() function is a no-op. The result is the value
+ ** of the first argument.
+ */
+ if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
+ assert( nFarg>=1 );
+ sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
+ break;
+ }
+ for(i=0; i<nFarg; i++){
+ if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
+ constMask |= (1<<i);
+ }
+ if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
+ pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
+ }
+ }
if( pFarg ){
- r1 = sqlite3GetTempRange(pParse, nFarg);
+ if( constMask ){
+ r1 = pParse->nMem+1;
+ pParse->nMem += nFarg;
+ }else{
+ r1 = sqlite3GetTempRange(pParse, nFarg);
+ }
/* For length() and typeof() functions with a column argument,
** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG
** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data
** loading.
*/
- if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
+ if( (pDef->funcFlags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){
u8 exprOp;
assert( nFarg==1 );
assert( pFarg->a[0].pExpr!=0 );
@@ -77886,13 +79326,15 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){
assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG );
assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG );
- testcase( pDef->flags==SQLITE_FUNC_LENGTH );
- pFarg->a[0].pExpr->op2 = pDef->flags;
+ testcase( pDef->funcFlags & OPFLAG_LENGTHARG );
+ pFarg->a[0].pExpr->op2 =
+ pDef->funcFlags & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG);
}
}
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
- sqlite3ExprCodeExprList(pParse, pFarg, r1, 1);
+ sqlite3ExprCodeExprList(pParse, pFarg, r1,
+ SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
}else{
r1 = 0;
@@ -77916,22 +79358,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
pDef = sqlite3VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
}
#endif
- for(i=0; i<nFarg; i++){
- if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
- constMask |= (1<<i);
- }
- if( (pDef->flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
- pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
- }
- }
- if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){
+ if( pDef->funcFlags & SQLITE_FUNC_NEEDCOLL ){
if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
(char*)pDef, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nFarg);
- if( nFarg ){
+ if( nFarg && constMask==0 ){
sqlite3ReleaseTempRange(pParse, r1, nFarg);
}
break;
@@ -78065,9 +79499,9 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
** WHEN x=eN THEN rN ELSE y END
**
** X (if it exists) is in pExpr->pLeft.
- ** Y is in pExpr->pRight. The Y is also optional. If there is no
- ** ELSE clause and no other term matches, then the result of the
- ** exprssion is NULL.
+ ** Y is in the last element of pExpr->x.pList if pExpr->x.pList->nExpr is
+ ** odd. The Y is also optional. If the number of elements in x.pList
+ ** is even, then Y is omitted and the "otherwise" result is NULL.
** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
**
** The result of the expression is the Ri for the first matching Ei,
@@ -78082,27 +79516,23 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
ExprList *pEList; /* List of WHEN terms */
struct ExprList_item *aListelem; /* Array of WHEN terms */
Expr opCompare; /* The X==Ei expression */
- 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);
assert(pExpr->x.pList->nExpr > 0);
pEList = pExpr->x.pList;
aListelem = pEList->a;
nExpr = pEList->nExpr;
endLabel = sqlite3VdbeMakeLabel(v);
if( (pX = pExpr->pLeft)!=0 ){
- cacheX = *pX;
+ tempX = *pX;
testcase( pX->op==TK_COLUMN );
- testcase( pX->op==TK_REGISTER );
- cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
+ exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, &regFree1));
testcase( regFree1==0 );
- cacheX.op = TK_REGISTER;
opCompare.op = TK_EQ;
- opCompare.pLeft = &cacheX;
+ opCompare.pLeft = &tempX;
pTest = &opCompare;
/* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
** The value in regFree1 might get SCopy-ed into the file result.
@@ -78110,7 +79540,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
** purposes and possibly overwritten. */
regFree1 = 0;
}
- for(i=0; i<nExpr; i=i+2){
+ for(i=0; i<nExpr-1; i=i+2){
sqlite3ExprCachePush(pParse);
if( pX ){
assert( pTest!=0 );
@@ -78122,15 +79552,14 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
testcase( pTest->op==TK_COLUMN );
sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
- 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 ){
+ if( (nExpr&1)!=0 ){
sqlite3ExprCachePush(pParse);
- sqlite3ExprCode(pParse, pExpr->pRight, target);
+ sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
sqlite3ExprCachePop(pParse, 1);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
@@ -78161,7 +79590,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
}else{
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
- pExpr->affinity, pExpr->u.zToken, 0);
+ pExpr->affinity, pExpr->u.zToken, 0, 0);
}
break;
@@ -78174,6 +79603,28 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
/*
+** Factor out the code of the given expression to initialization time.
+*/
+SQLITE_PRIVATE void sqlite3ExprCodeAtInit(
+ Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* The expression to code when the VDBE initializes */
+ int regDest, /* Store the value in this register */
+ u8 reusable /* True if this expression is reusable */
+){
+ ExprList *p;
+ assert( ConstFactorOk(pParse) );
+ p = pParse->pConstExpr;
+ pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
+ p = sqlite3ExprListAppend(pParse, p, pExpr);
+ if( p ){
+ struct ExprList_item *pItem = &p->a[p->nExpr-1];
+ pItem->u.iConstExprReg = regDest;
+ pItem->reusable = reusable;
+ }
+ pParse->pConstExpr = p;
+}
+
+/*
** Generate code to evaluate an expression and store the results
** into a register. Return the register number where the results
** are stored.
@@ -78181,15 +79632,40 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
** If the register is a temporary register that can be deallocated,
** then write its number into *pReg. If the result register is not
** a temporary, then set *pReg to zero.
+**
+** If pExpr is a constant, then this routine might generate this
+** code to fill the register in the initialization section of the
+** VDBE program, in order to factor it out of the evaluation loop.
*/
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
- int r1 = sqlite3GetTempReg(pParse);
- int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
- if( r2==r1 ){
- *pReg = r1;
+ int r2;
+ pExpr = sqlite3ExprSkipCollate(pExpr);
+ if( ConstFactorOk(pParse)
+ && pExpr->op!=TK_REGISTER
+ && sqlite3ExprIsConstantNotJoin(pExpr)
+ ){
+ ExprList *p = pParse->pConstExpr;
+ int i;
+ *pReg = 0;
+ if( p ){
+ struct ExprList_item *pItem;
+ for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
+ if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
+ return pItem->u.iConstExprReg;
+ }
+ }
+ }
+ r2 = ++pParse->nMem;
+ sqlite3ExprCodeAtInit(pParse, pExpr, r2, 1);
}else{
- sqlite3ReleaseTempReg(pParse, r1);
- *pReg = 0;
+ int r1 = sqlite3GetTempReg(pParse);
+ r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
+ if( r2==r1 ){
+ *pReg = r1;
+ }else{
+ sqlite3ReleaseTempReg(pParse, r1);
+ *pReg = 0;
+ }
}
return r2;
}
@@ -78232,19 +79708,18 @@ SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targe
int inReg;
inReg = sqlite3ExprCode(pParse, pExpr, target);
assert( target>0 );
- /* This routine is called for terms to INSERT or UPDATE. And the only
- ** other place where expressions can be converted into TK_REGISTER is
- ** in WHERE clause processing. So as currently implemented, there is
- ** no way for a TK_REGISTER to exist here. But it seems prudent to
- ** keep the ALWAYS() in case the conditions above change with future
- ** modifications or enhancements. */
+ /* The only place, other than this routine, where expressions can be
+ ** converted to TK_REGISTER is internal subexpressions in BETWEEN and
+ ** CASE operators. Neither ever calls this routine. And this routine
+ ** is never called twice on the same expression. Hence it is impossible
+ ** for the input to this routine to already be a register. Nevertheless,
+ ** it seems prudent to keep the ALWAYS() in case the conditions above
+ ** change with future modifications or enhancements. */
if( ALWAYS(pExpr->op!=TK_REGISTER) ){
int iMem;
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
- pExpr->iTable = iMem;
- pExpr->op2 = pExpr->op;
- pExpr->op = TK_REGISTER;
+ exprToRegister(pExpr, iMem);
}
return inReg;
}
@@ -78323,7 +79798,7 @@ SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
const char *zAff = "unk";
- switch( sqlite3AffinityType(pExpr->u.zToken) ){
+ switch( sqlite3AffinityType(pExpr->u.zToken, 0) ){
case SQLITE_AFF_TEXT: zAff = "TEXT"; break;
case SQLITE_AFF_NONE: zAff = "NONE"; break;
case SQLITE_AFF_NUMERIC: zAff = "NUMERIC"; break;
@@ -78371,10 +79846,9 @@ SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
}
case TK_AGG_FUNCTION:
- case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
- if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
+ if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
@@ -78523,165 +79997,40 @@ SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
#endif /* SQLITE_DEBUG */
/*
-** Return TRUE if pExpr is an constant expression that is appropriate
-** for factoring out of a loop. Appropriate expressions are:
-**
-** * Any expression that evaluates to two or more opcodes.
-**
-** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
-** or OP_Variable that does not need to be placed in a
-** specific register.
-**
-** There is no point in factoring out single-instruction constant
-** expressions that need to be placed in a particular register.
-** We could factor them out, but then we would end up adding an
-** OP_SCopy instruction to move the value into the correct register
-** later. We might as well just use the original instruction and
-** avoid the OP_SCopy.
-*/
-static int isAppropriateForFactoring(Expr *p){
- if( !sqlite3ExprIsConstantNotJoin(p) ){
- return 0; /* Only constant expressions are appropriate for factoring */
- }
- if( (p->flags & EP_FixedDest)==0 ){
- return 1; /* Any constant without a fixed destination is appropriate */
- }
- while( p->op==TK_UPLUS ) p = p->pLeft;
- switch( p->op ){
-#ifndef SQLITE_OMIT_BLOB_LITERAL
- case TK_BLOB:
-#endif
- case TK_VARIABLE:
- case TK_INTEGER:
- case TK_FLOAT:
- case TK_NULL:
- case TK_STRING: {
- testcase( p->op==TK_BLOB );
- testcase( p->op==TK_VARIABLE );
- testcase( p->op==TK_INTEGER );
- testcase( p->op==TK_FLOAT );
- testcase( p->op==TK_NULL );
- testcase( p->op==TK_STRING );
- /* Single-instruction constants with a fixed destination are
- ** better done in-line. If we factor them, they will just end
- ** up generating an OP_SCopy to move the value to the destination
- ** register. */
- return 0;
- }
- case TK_UMINUS: {
- if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){
- return 0;
- }
- break;
- }
- default: {
- break;
- }
- }
- return 1;
-}
-
-/*
-** If pExpr is a constant expression that is appropriate for
-** factoring out of a loop, then evaluate the expression
-** into a register and convert the expression into a TK_REGISTER
-** expression.
-*/
-static int evalConstExpr(Walker *pWalker, Expr *pExpr){
- Parse *pParse = pWalker->pParse;
- switch( pExpr->op ){
- case TK_IN:
- case TK_REGISTER: {
- return WRC_Prune;
- }
- case TK_COLLATE: {
- return WRC_Continue;
- }
- case TK_FUNCTION:
- case TK_AGG_FUNCTION:
- case TK_CONST_FUNC: {
- /* The arguments to a function have a fixed destination.
- ** Mark them this way to avoid generated unneeded OP_SCopy
- ** instructions.
- */
- ExprList *pList = pExpr->x.pList;
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
- if( pList ){
- int i = pList->nExpr;
- struct ExprList_item *pItem = pList->a;
- for(; i>0; i--, pItem++){
- if( ALWAYS(pItem->pExpr) ) pItem->pExpr->flags |= EP_FixedDest;
- }
- }
- break;
- }
- }
- if( isAppropriateForFactoring(pExpr) ){
- int r1 = ++pParse->nMem;
- int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
- /* If r2!=r1, it means that register r1 is never used. That is harmless
- ** but suboptimal, so we want to know about the situation to fix it.
- ** Hence the following assert: */
- assert( r2==r1 );
- pExpr->op2 = pExpr->op;
- pExpr->op = TK_REGISTER;
- pExpr->iTable = r2;
- return WRC_Prune;
- }
- return WRC_Continue;
-}
-
-/*
-** Preevaluate constant subexpressions within pExpr and store the
-** results in registers. Modify pExpr so that the constant subexpresions
-** are TK_REGISTER opcodes that refer to the precomputed values.
-**
-** This routine is a no-op if the jump to the cookie-check code has
-** already occur. Since the cookie-check jump is generated prior to
-** any other serious processing, this check ensures that there is no
-** way to accidently bypass the constant initializations.
-**
-** This routine is also a no-op if the SQLITE_FactorOutConst optimization
-** is disabled via the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS)
-** interface. This allows test logic to verify that the same answer is
-** obtained for queries regardless of whether or not constants are
-** precomputed into registers or if they are inserted in-line.
-*/
-SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
- Walker w;
- if( pParse->cookieGoto ) return;
- if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
- memset(&w, 0, sizeof(w));
- w.xExprCallback = evalConstExpr;
- w.pParse = pParse;
- sqlite3WalkExpr(&w, pExpr);
-}
-
-
-/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
** Return the number of elements evaluated.
+**
+** The SQLITE_ECEL_DUP flag prevents the arguments from being
+** filled using OP_SCopy. OP_Copy must be used instead.
+**
+** The SQLITE_ECEL_FACTOR argument allows constant arguments to be
+** factored out into initialization code.
*/
SQLITE_PRIVATE int sqlite3ExprCodeExprList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* The expression list to be coded */
int target, /* Where to write results */
- int doHardCopy /* Make a hard copy of every element */
+ u8 flags /* SQLITE_ECEL_* flags */
){
struct ExprList_item *pItem;
int i, n;
+ u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy;
assert( pList!=0 );
assert( target>0 );
assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */
n = pList->nExpr;
+ if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
Expr *pExpr = pItem->pExpr;
- int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
- if( inReg!=target+i ){
- sqlite3VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy,
- inReg, target+i);
+ if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){
+ sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0);
+ }else{
+ int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
+ if( inReg!=target+i ){
+ sqlite3VdbeAddOp2(pParse->pVdbe, copyOp, inReg, target+i);
+ }
}
}
return n;
@@ -78723,8 +80072,7 @@ static void exprCodeBetween(
compRight.op = TK_LE;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
- exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
- exprX.op = TK_REGISTER;
+ exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, &regFree1));
if( jumpIfTrue ){
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
}else{
@@ -79019,6 +80367,12 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
** by a COLLATE operator at the top level. Return 2 if there are differences
** other than the top-level COLLATE operator.
**
+** If any subelement of pB has Expr.iTable==(-1) then it is allowed
+** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
+**
+** The pA side might be using TK_REGISTER. If that is the case and pB is
+** not using TK_REGISTER but is otherwise equivalent, then still return 0.
+**
** Sometimes this routine will return 2 even if the two expressions
** really are equivalent. If we cannot prove that the expressions are
** identical, we return 2 just to be safe. So if this routine
@@ -79029,39 +80383,44 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
*/
-SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
- if( pA==0||pB==0 ){
+SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
+ u32 combinedFlags;
+ if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
}
- assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
- assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
- if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
+ combinedFlags = pA->flags | pB->flags;
+ if( combinedFlags & EP_IntValue ){
+ if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
+ return 0;
+ }
return 2;
}
- if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( pA->op!=pB->op ){
- if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
return 1;
}
- if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
+ if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){
return 1;
}
return 2;
}
- if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
- if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
- if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
- if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
- if( ExprHasProperty(pA, EP_IntValue) ){
- if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
- return 2;
- }
- }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
- if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
+ if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken ){
if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
return pA->op==TK_COLLATE ? 1 : 2;
}
}
+ if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
+ if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
+ if( combinedFlags & EP_xIsSelect ) return 2;
+ if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
+ if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
+ if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
+ if( ALWAYS((combinedFlags & EP_Reduced)==0) ){
+ if( pA->iColumn!=pB->iColumn ) return 2;
+ if( pA->iTable!=pB->iTable
+ && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
+ }
+ }
return 0;
}
@@ -79069,6 +80428,9 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
** Compare two ExprList objects. Return 0 if they are identical and
** non-zero if they differ in any way.
**
+** If any subelement of pB has Expr.iTable==(-1) then it is allowed
+** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
+**
** This routine might return non-zero for equivalent ExprLists. The
** only consequence will be disabled optimizations. But this routine
** must never return 0 if the two ExprList objects are different, or
@@ -79077,7 +80439,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
** Two NULL pointers are considered to be the same. But a NULL pointer
** always differs from a non-NULL pointer.
*/
-SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
+SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
int i;
if( pA==0 && pB==0 ) return 0;
if( pA==0 || pB==0 ) return 1;
@@ -79086,7 +80448,46 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
- if( sqlite3ExprCompare(pExprA, pExprB) ) return 1;
+ if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Return true if we can prove the pE2 will always be true if pE1 is
+** true. Return false if we cannot complete the proof or if pE2 might
+** be false. Examples:
+**
+** pE1: x==5 pE2: x==5 Result: true
+** pE1: x>0 pE2: x==5 Result: false
+** pE1: x=21 pE2: x=21 OR y=43 Result: true
+** pE1: x!=123 pE2: x IS NOT NULL Result: true
+** pE1: x!=?1 pE2: x IS NOT NULL Result: true
+** pE1: x IS NULL pE2: x IS NOT NULL Result: false
+** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false
+**
+** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
+** Expr.iTable<0 then assume a table number given by iTab.
+**
+** When in doubt, return false. Returning true might give a performance
+** improvement. Returning false might cause a performance reduction, but
+** it will always give the correct answer and is hence always safe.
+*/
+SQLITE_PRIVATE int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
+ if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){
+ return 1;
+ }
+ if( pE2->op==TK_OR
+ && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
+ || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
+ ){
+ return 1;
+ }
+ if( pE2->op==TK_NOTNULL
+ && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
+ && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
+ ){
+ return 1;
}
return 0;
}
@@ -79203,7 +80604,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
struct SrcList_item *pItem = pSrcList->a;
for(i=0; i<pSrcList->nSrc; i++, pItem++){
struct AggInfo_col *pCol;
- assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
if( pExpr->iTable==pItem->iCursor ){
/* If we reach this point, it means that pExpr refers to a table
** that is in the FROM clause of the aggregate query.
@@ -79252,7 +80653,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
** Convert the pExpr to be a TK_AGG_COLUMN referring to that
** pAggInfo->aCol[] entry.
*/
- ExprSetIrreducible(pExpr);
+ ExprSetVVAProperty(pExpr, EP_NoReduce);
pExpr->pAggInfo = pAggInfo;
pExpr->op = TK_AGG_COLUMN;
pExpr->iAgg = (i16)k;
@@ -79271,7 +80672,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
- if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
+ if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){
break;
}
}
@@ -79298,8 +80699,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
}
/* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
*/
- assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
- ExprSetIrreducible(pExpr);
+ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+ ExprSetVVAProperty(pExpr, EP_NoReduce);
pExpr->iAgg = (i16)i;
pExpr->pAggInfo = pAggInfo;
return WRC_Prune;
@@ -80106,7 +81507,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
** can handle (i.e. not CURRENT_TIME etc.)
*/
if( pDflt ){
- sqlite3_value *pVal;
+ sqlite3_value *pVal = 0;
if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
db->mallocFailed = 1;
return;
@@ -80247,7 +81648,7 @@ exit_begin_add_column:
/************** End of alter.c ***********************************************/
/************** Begin file analyze.c *****************************************/
/*
-** 2005 July 8
+** 2005-07-08
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -80268,15 +81669,23 @@ exit_begin_add_column:
** CREATE TABLE sqlite_stat1(tbl, idx, stat);
** CREATE TABLE sqlite_stat2(tbl, idx, sampleno, sample);
** CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
+** CREATE TABLE sqlite_stat4(tbl, idx, nEq, nLt, nDLt, sample);
**
** Additional tables might be added in future releases of SQLite.
** The sqlite_stat2 table is not created or used unless the SQLite version
** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated.
-** The sqlite_stat2 table is superceded by sqlite_stat3, which is only
+** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
** created and used by SQLite versions 3.7.9 and later and with
-** SQLITE_ENABLE_STAT3 defined. The fucntionality of sqlite_stat3
-** is a superset of sqlite_stat2.
+** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
+** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
+** version of sqlite_stat3 and is only available when compiled with
+** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is
+** not possible to enable both STAT3 and STAT4 at the same time. If they
+** are both enabled, then STAT4 takes precedence.
+**
+** For most applications, sqlite_stat1 provides all the statisics required
+** for the query planner to make good choices.
**
** Format of sqlite_stat1:
**
@@ -80284,7 +81693,8 @@ exit_begin_add_column:
** name in the idx column. The tbl column is the name of the table to
** which the index belongs. In each such row, the stat column will be
** a string consisting of a list of integers. The first integer in this
-** list is the number of rows in the index and in the table. The second
+** list is the number of rows in the index. (This is the same as the
+** number of rows in the table, except for partial indices.) The second
** integer is the average number of rows in the index that have the same
** value in the first column of the index. The third integer is the average
** number of rows in the index that have the same value for the first two
@@ -80331,53 +81741,81 @@ exit_begin_add_column:
**
** Format for sqlite_stat3:
**
-** The sqlite_stat3 is an enhancement to sqlite_stat2. A new name is
-** used to avoid compatibility problems.
+** The sqlite_stat3 format is a subset of sqlite_stat4. Hence, the
+** sqlite_stat4 format will be described first. Further information
+** about sqlite_stat3 follows the sqlite_stat4 description.
+**
+** Format for sqlite_stat4:
+**
+** As with sqlite_stat2, the sqlite_stat4 table contains histogram data
+** to aid the query planner in choosing good indices based on the values
+** that indexed columns are compared against in the WHERE clauses of
+** queries.
**
-** The format of the sqlite_stat3 table is similar to the format of
-** the sqlite_stat2 table. There are multiple entries for each index.
+** The sqlite_stat4 table contains multiple entries for each index.
** The idx column names the index and the tbl column is the table of the
** index. If the idx and tbl columns are the same, then the sample is
-** of the INTEGER PRIMARY KEY. The sample column is a value taken from
-** the left-most column of the index. The nEq column is the approximate
-** number of entires in the index whose left-most column exactly matches
-** the sample. nLt is the approximate number of entires whose left-most
-** column is less than the sample. The nDLt column is the approximate
-** number of distinct left-most entries in the index that are less than
-** the sample.
-**
-** Future versions of SQLite might change to store a string containing
-** multiple integers values in the nDLt column of sqlite_stat3. The first
-** integer will be the number of prior index entires that are distinct in
-** the left-most column. The second integer will be the number of prior index
-** entries that are distinct in the first two columns. The third integer
-** will be the number of prior index entries that are distinct in the first
-** three columns. And so forth. With that extension, the nDLt field is
-** similar in function to the sqlite_stat1.stat field.
-**
-** There can be an arbitrary number of sqlite_stat3 entries per index.
-** The ANALYZE command will typically generate sqlite_stat3 tables
+** of the INTEGER PRIMARY KEY. The sample column is a blob which is the
+** binary encoding of a key from the index. The nEq column is a
+** list of integers. The first integer is the approximate number
+** of entries in the index whose left-most column exactly matches
+** the left-most column of the sample. The second integer in nEq
+** is the approximate number of entries in the index where the
+** first two columns match the first two columns of the sample.
+** And so forth. nLt is another list of integers that show the approximate
+** number of entries that are strictly less than the sample. The first
+** integer in nLt contains the number of entries in the index where the
+** left-most column is less than the left-most column of the sample.
+** The K-th integer in the nLt entry is the number of index entries
+** where the first K columns are less than the first K columns of the
+** sample. The nDLt column is like nLt except that it contains the
+** number of distinct entries in the index that are less than the
+** sample.
+**
+** There can be an arbitrary number of sqlite_stat4 entries per index.
+** The ANALYZE command will typically generate sqlite_stat4 tables
** that contain between 10 and 40 samples which are distributed across
** the key space, though not uniformly, and which include samples with
-** largest possible nEq values.
+** large nEq values.
+**
+** Format for sqlite_stat3 redux:
+**
+** The sqlite_stat3 table is like sqlite_stat4 except that it only
+** looks at the left-most column of the index. The sqlite_stat3.sample
+** column contains the actual value of the left-most column instead
+** of a blob encoding of the complete index key as is found in
+** sqlite_stat4.sample. The nEq, nLt, and nDLt entries of sqlite_stat3
+** all contain just a single integer which is the same as the first
+** integer in the equivalent columns in sqlite_stat4.
*/
#ifndef SQLITE_OMIT_ANALYZE
+#if defined(SQLITE_ENABLE_STAT4)
+# define IsStat4 1
+# define IsStat3 0
+#elif defined(SQLITE_ENABLE_STAT3)
+# define IsStat4 0
+# define IsStat3 1
+#else
+# define IsStat4 0
+# define IsStat3 0
+# undef SQLITE_STAT4_SAMPLES
+# define SQLITE_STAT4_SAMPLES 1
+#endif
+#define IsStat34 (IsStat3+IsStat4) /* 1 for STAT3 or STAT4. 0 otherwise */
+
/*
-** This routine generates code that opens the sqlite_stat1 table for
-** writing with cursor iStatCur. If the library was built with the
-** SQLITE_ENABLE_STAT3 macro defined, then the sqlite_stat3 table is
-** opened for writing using cursor (iStatCur+1)
+** This routine generates code that opens the sqlite_statN tables.
+** The sqlite_stat1 table is always relevant. sqlite_stat2 is now
+** obsolete. sqlite_stat3 and sqlite_stat4 are only opened when
+** appropriate compile-time options are provided.
**
-** If the sqlite_stat1 tables does not previously exist, it is created.
-** Similarly, if the sqlite_stat3 table does not exist and the library
-** is compiled with SQLITE_ENABLE_STAT3 defined, it is created.
+** If the sqlite_statN tables do not previously exist, it is created.
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
-** the sqlite_stat1 and (if applicable) sqlite_stat3 tables associated
-** with the named table are deleted. If zWhere==0, then code is generated
-** to delete all stat table entries.
+** the sqlite_statN tables associated with the named table are deleted.
+** If zWhere==0, then code is generated to delete all stat table entries.
*/
static void openStatTable(
Parse *pParse, /* Parsing context */
@@ -80391,18 +81829,24 @@ static void openStatTable(
const char *zCols;
} aTable[] = {
{ "sqlite_stat1", "tbl,idx,stat" },
-#ifdef SQLITE_ENABLE_STAT3
+#if defined(SQLITE_ENABLE_STAT4)
+ { "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
+ { "sqlite_stat3", 0 },
+#elif defined(SQLITE_ENABLE_STAT3)
{ "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
+ { "sqlite_stat4", 0 },
+#else
+ { "sqlite_stat3", 0 },
+ { "sqlite_stat4", 0 },
#endif
};
-
- int aRoot[] = {0, 0};
- u8 aCreateTbl[] = {0, 0};
-
int i;
sqlite3 *db = pParse->db;
Db *pDb;
Vdbe *v = sqlite3GetVdbe(pParse);
+ int aRoot[ArraySize(aTable)];
+ u8 aCreateTbl[ArraySize(aTable)];
+
if( v==0 ) return;
assert( sqlite3BtreeHoldsAllMutexes(db) );
assert( sqlite3VdbeDb(v)==db );
@@ -80415,258 +81859,712 @@ static void openStatTable(
const char *zTab = aTable[i].zName;
Table *pStat;
if( (pStat = sqlite3FindTable(db, zTab, pDb->zName))==0 ){
- /* The sqlite_stat[12] table does not exist. Create it. Note that a
- ** side-effect of the CREATE TABLE statement is to leave the rootpage
- ** of the new table in register pParse->regRoot. This is important
- ** because the OpenWrite opcode below will be needing it. */
- sqlite3NestedParse(pParse,
- "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
- );
- aRoot[i] = pParse->regRoot;
- aCreateTbl[i] = OPFLAG_P2ISREG;
+ if( aTable[i].zCols ){
+ /* The sqlite_statN table does not exist. Create it. Note that a
+ ** side-effect of the CREATE TABLE statement is to leave the rootpage
+ ** of the new table in register pParse->regRoot. This is important
+ ** because the OpenWrite opcode below will be needing it. */
+ sqlite3NestedParse(pParse,
+ "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
+ );
+ aRoot[i] = pParse->regRoot;
+ aCreateTbl[i] = OPFLAG_P2ISREG;
+ }
}else{
/* The table already exists. If zWhere is not NULL, delete all entries
** associated with the table zWhere. If zWhere is NULL, delete the
** entire contents of the table. */
aRoot[i] = pStat->tnum;
+ aCreateTbl[i] = 0;
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
if( zWhere ){
sqlite3NestedParse(pParse,
- "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
+ "DELETE FROM %Q.%s WHERE %s=%Q",
+ pDb->zName, zTab, zWhereType, zWhere
);
}else{
- /* The sqlite_stat[12] table already exists. Delete all rows. */
+ /* The sqlite_stat[134] table already exists. Delete all rows. */
sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
}
}
}
- /* Open the sqlite_stat[13] tables for writing. */
- for(i=0; i<ArraySize(aTable); i++){
- sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
- sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32);
+ /* Open the sqlite_stat[134] tables for writing. */
+ for(i=0; aTable[i].zCols; i++){
+ assert( i<ArraySize(aTable) );
+ sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
}
}
/*
-** Recommended number of samples for sqlite_stat3
+** Recommended number of samples for sqlite_stat4
*/
-#ifndef SQLITE_STAT3_SAMPLES
-# define SQLITE_STAT3_SAMPLES 24
+#ifndef SQLITE_STAT4_SAMPLES
+# define SQLITE_STAT4_SAMPLES 24
#endif
/*
-** Three SQL functions - stat3_init(), stat3_push(), and stat3_pop() -
+** Three SQL functions - stat_init(), stat_push(), and stat_get() -
** share an instance of the following structure to hold their state
** information.
*/
-typedef struct Stat3Accum Stat3Accum;
-struct Stat3Accum {
+typedef struct Stat4Accum Stat4Accum;
+typedef struct Stat4Sample Stat4Sample;
+struct Stat4Sample {
+ tRowcnt *anEq; /* sqlite_stat4.nEq */
+ tRowcnt *anDLt; /* sqlite_stat4.nDLt */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ tRowcnt *anLt; /* sqlite_stat4.nLt */
+ union {
+ i64 iRowid; /* Rowid in main table of the key */
+ u8 *aRowid; /* Key for WITHOUT ROWID tables */
+ } u;
+ u32 nRowid; /* Sizeof aRowid[] */
+ u8 isPSample; /* True if a periodic sample */
+ int iCol; /* If !isPSample, the reason for inclusion */
+ u32 iHash; /* Tiebreaker hash */
+#endif
+};
+struct Stat4Accum {
tRowcnt nRow; /* Number of rows in the entire table */
tRowcnt nPSample; /* How often to do a periodic sample */
- int iMin; /* Index of entry with minimum nEq and hash */
+ int nCol; /* Number of columns in index + rowid */
int mxSample; /* Maximum number of samples to accumulate */
- int nSample; /* Current number of samples */
+ Stat4Sample current; /* Current row as a Stat4Sample */
u32 iPrn; /* Pseudo-random number used for sampling */
- struct Stat3Sample {
- i64 iRowid; /* Rowid in main table of the key */
- tRowcnt nEq; /* sqlite_stat3.nEq */
- tRowcnt nLt; /* sqlite_stat3.nLt */
- tRowcnt nDLt; /* sqlite_stat3.nDLt */
- u8 isPSample; /* True if a periodic sample */
- u32 iHash; /* Tiebreaker hash */
- } *a; /* An array of samples */
+ Stat4Sample *aBest; /* Array of nCol best samples */
+ int iMin; /* Index in a[] of entry with minimum score */
+ int nSample; /* Current number of samples */
+ int iGet; /* Index of current sample accessed by stat_get() */
+ Stat4Sample *a; /* Array of mxSample Stat4Sample objects */
+ sqlite3 *db; /* Database connection, for malloc() */
};
-#ifdef SQLITE_ENABLE_STAT3
+/* Reclaim memory used by a Stat4Sample
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static void sampleClear(sqlite3 *db, Stat4Sample *p){
+ assert( db!=0 );
+ if( p->nRowid ){
+ sqlite3DbFree(db, p->u.aRowid);
+ p->nRowid = 0;
+ }
+}
+#endif
+
+/* Initialize the BLOB value of a ROWID
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
+ assert( db!=0 );
+ if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
+ p->u.aRowid = sqlite3DbMallocRaw(db, n);
+ if( p->u.aRowid ){
+ p->nRowid = n;
+ memcpy(p->u.aRowid, pData, n);
+ }else{
+ p->nRowid = 0;
+ }
+}
+#endif
+
+/* Initialize the INTEGER value of a ROWID.
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
+ assert( db!=0 );
+ if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
+ p->nRowid = 0;
+ p->u.iRowid = iRowid;
+}
+#endif
+
+
/*
-** Implementation of the stat3_init(C,S) SQL function. The two parameters
-** are the number of rows in the table or index (C) and the number of samples
-** to accumulate (S).
-**
-** This routine allocates the Stat3Accum object.
+** Copy the contents of object (*pFrom) into (*pTo).
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
+ pTo->isPSample = pFrom->isPSample;
+ pTo->iCol = pFrom->iCol;
+ pTo->iHash = pFrom->iHash;
+ memcpy(pTo->anEq, pFrom->anEq, sizeof(tRowcnt)*p->nCol);
+ memcpy(pTo->anLt, pFrom->anLt, sizeof(tRowcnt)*p->nCol);
+ memcpy(pTo->anDLt, pFrom->anDLt, sizeof(tRowcnt)*p->nCol);
+ if( pFrom->nRowid ){
+ sampleSetRowid(p->db, pTo, pFrom->nRowid, pFrom->u.aRowid);
+ }else{
+ sampleSetRowidInt64(p->db, pTo, pFrom->u.iRowid);
+ }
+}
+#endif
+
+/*
+** Reclaim all memory of a Stat4Accum structure.
+*/
+static void stat4Destructor(void *pOld){
+ Stat4Accum *p = (Stat4Accum*)pOld;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ int i;
+ for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
+ for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
+ sampleClear(p->db, &p->current);
+#endif
+ sqlite3DbFree(p->db, p);
+}
+
+/*
+** Implementation of the stat_init(N,C) SQL function. The two parameters
+** are the number of rows in the table or index (C) and the number of columns
+** in the index (N). The second argument (C) is only used for STAT3 and STAT4.
**
-** The return value is the Stat3Accum object (P).
+** This routine allocates the Stat4Accum object in heap memory. The return
+** value is a pointer to the the Stat4Accum object encoded as a blob (i.e.
+** the size of the blob is sizeof(void*) bytes).
*/
-static void stat3Init(
+static void statInit(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
- Stat3Accum *p;
- tRowcnt nRow;
- int mxSample;
- int n;
+ Stat4Accum *p;
+ int nCol; /* Number of columns in index being sampled */
+ int nColUp; /* nCol rounded up for alignment */
+ int n; /* Bytes of space to allocate */
+ sqlite3 *db; /* Database connection */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ int mxSample = SQLITE_STAT4_SAMPLES;
+#endif
+ /* Decode the three function arguments */
UNUSED_PARAMETER(argc);
- nRow = (tRowcnt)sqlite3_value_int64(argv[0]);
- mxSample = sqlite3_value_int(argv[1]);
- n = sizeof(*p) + sizeof(p->a[0])*mxSample;
- p = sqlite3MallocZero( n );
+ nCol = sqlite3_value_int(argv[0]);
+ assert( nCol>1 ); /* >1 because it includes the rowid column */
+ nColUp = sizeof(tRowcnt)<8 ? (nCol+1)&~1 : nCol;
+
+ /* Allocate the space required for the Stat4Accum object */
+ n = sizeof(*p)
+ + sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */
+ + sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ + sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */
+ + sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */
+ + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
+#endif
+ ;
+ db = sqlite3_context_db_handle(context);
+ p = sqlite3DbMallocZero(db, n);
if( p==0 ){
sqlite3_result_error_nomem(context);
return;
}
- p->a = (struct Stat3Sample*)&p[1];
- p->nRow = nRow;
- p->mxSample = mxSample;
- p->nPSample = p->nRow/(mxSample/3+1) + 1;
- sqlite3_randomness(sizeof(p->iPrn), &p->iPrn);
- sqlite3_result_blob(context, p, sizeof(p), sqlite3_free);
-}
-static const FuncDef stat3InitFuncdef = {
- 2, /* nArg */
- SQLITE_UTF8, /* iPrefEnc */
- 0, /* flags */
- 0, /* pUserData */
- 0, /* pNext */
- stat3Init, /* xFunc */
- 0, /* xStep */
- 0, /* xFinalize */
- "stat3_init", /* zName */
- 0, /* pHash */
- 0 /* pDestructor */
+
+ p->db = db;
+ p->nRow = 0;
+ p->nCol = nCol;
+ p->current.anDLt = (tRowcnt*)&p[1];
+ p->current.anEq = &p->current.anDLt[nColUp];
+
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ {
+ u8 *pSpace; /* Allocated space not yet assigned */
+ int i; /* Used to iterate through p->aSample[] */
+
+ p->iGet = -1;
+ p->mxSample = mxSample;
+ p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[1])/(mxSample/3+1) + 1);
+ p->current.anLt = &p->current.anEq[nColUp];
+ p->iPrn = nCol*0x689e962d ^ sqlite3_value_int(argv[1])*0xd0944565;
+
+ /* Set up the Stat4Accum.a[] and aBest[] arrays */
+ p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
+ p->aBest = &p->a[mxSample];
+ pSpace = (u8*)(&p->a[mxSample+nCol]);
+ for(i=0; i<(mxSample+nCol); i++){
+ p->a[i].anEq = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
+ p->a[i].anLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
+ p->a[i].anDLt = (tRowcnt *)pSpace; pSpace += (sizeof(tRowcnt) * nColUp);
+ }
+ assert( (pSpace - (u8*)p)==n );
+
+ for(i=0; i<nCol; i++){
+ p->aBest[i].iCol = i;
+ }
+ }
+#endif
+
+ /* Return a pointer to the allocated object to the caller */
+ sqlite3_result_blob(context, p, sizeof(p), stat4Destructor);
+}
+static const FuncDef statInitFuncdef = {
+ 1+IsStat34, /* nArg */
+ SQLITE_UTF8, /* funcFlags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ statInit, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat_init", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
};
+#ifdef SQLITE_ENABLE_STAT4
+/*
+** pNew and pOld are both candidate non-periodic samples selected for
+** the same column (pNew->iCol==pOld->iCol). Ignoring this column and
+** considering only any trailing columns and the sample hash value, this
+** function returns true if sample pNew is to be preferred over pOld.
+** In other words, if we assume that the cardinalities of the selected
+** column for pNew and pOld are equal, is pNew to be preferred over pOld.
+**
+** This function assumes that for each argument sample, the contents of
+** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid.
+*/
+static int sampleIsBetterPost(
+ Stat4Accum *pAccum,
+ Stat4Sample *pNew,
+ Stat4Sample *pOld
+){
+ int nCol = pAccum->nCol;
+ int i;
+ assert( pNew->iCol==pOld->iCol );
+ for(i=pNew->iCol+1; i<nCol; i++){
+ if( pNew->anEq[i]>pOld->anEq[i] ) return 1;
+ if( pNew->anEq[i]<pOld->anEq[i] ) return 0;
+ }
+ if( pNew->iHash>pOld->iHash ) return 1;
+ return 0;
+}
+#endif
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
-** Implementation of the stat3_push(nEq,nLt,nDLt,rowid,P) SQL function. The
-** arguments describe a single key instance. This routine makes the
-** decision about whether or not to retain this key for the sqlite_stat3
-** table.
+** Return true if pNew is to be preferred over pOld.
**
-** The return value is NULL.
+** This function assumes that for each argument sample, the contents of
+** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid.
*/
-static void stat3Push(
+static int sampleIsBetter(
+ Stat4Accum *pAccum,
+ Stat4Sample *pNew,
+ Stat4Sample *pOld
+){
+ tRowcnt nEqNew = pNew->anEq[pNew->iCol];
+ tRowcnt nEqOld = pOld->anEq[pOld->iCol];
+
+ assert( pOld->isPSample==0 && pNew->isPSample==0 );
+ assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) );
+
+ if( (nEqNew>nEqOld) ) return 1;
+#ifdef SQLITE_ENABLE_STAT4
+ if( nEqNew==nEqOld ){
+ if( pNew->iCol<pOld->iCol ) return 1;
+ return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld));
+ }
+ return 0;
+#else
+ return (nEqNew==nEqOld && pNew->iHash>pOld->iHash);
+#endif
+}
+
+/*
+** Copy the contents of sample *pNew into the p->a[] array. If necessary,
+** remove the least desirable sample from p->a[] to make room.
+*/
+static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
+ Stat4Sample *pSample = 0;
+ int i;
+
+ assert( IsStat4 || nEqZero==0 );
+
+#ifdef SQLITE_ENABLE_STAT4
+ if( pNew->isPSample==0 ){
+ Stat4Sample *pUpgrade = 0;
+ assert( pNew->anEq[pNew->iCol]>0 );
+
+ /* This sample is being added because the prefix that ends in column
+ ** iCol occurs many times in the table. However, if we have already
+ ** added a sample that shares this prefix, there is no need to add
+ ** this one. Instead, upgrade the priority of the highest priority
+ ** existing sample that shares this prefix. */
+ for(i=p->nSample-1; i>=0; i--){
+ Stat4Sample *pOld = &p->a[i];
+ if( pOld->anEq[pNew->iCol]==0 ){
+ if( pOld->isPSample ) return;
+ assert( pOld->iCol>pNew->iCol );
+ assert( sampleIsBetter(p, pNew, pOld) );
+ if( pUpgrade==0 || sampleIsBetter(p, pOld, pUpgrade) ){
+ pUpgrade = pOld;
+ }
+ }
+ }
+ if( pUpgrade ){
+ pUpgrade->iCol = pNew->iCol;
+ pUpgrade->anEq[pUpgrade->iCol] = pNew->anEq[pUpgrade->iCol];
+ goto find_new_min;
+ }
+ }
+#endif
+
+ /* If necessary, remove sample iMin to make room for the new sample. */
+ if( p->nSample>=p->mxSample ){
+ Stat4Sample *pMin = &p->a[p->iMin];
+ tRowcnt *anEq = pMin->anEq;
+ tRowcnt *anLt = pMin->anLt;
+ tRowcnt *anDLt = pMin->anDLt;
+ sampleClear(p->db, pMin);
+ memmove(pMin, &pMin[1], sizeof(p->a[0])*(p->nSample-p->iMin-1));
+ pSample = &p->a[p->nSample-1];
+ pSample->nRowid = 0;
+ pSample->anEq = anEq;
+ pSample->anDLt = anDLt;
+ pSample->anLt = anLt;
+ p->nSample = p->mxSample-1;
+ }
+
+ /* The "rows less-than" for the rowid column must be greater than that
+ ** for the last sample in the p->a[] array. Otherwise, the samples would
+ ** be out of order. */
+#ifdef SQLITE_ENABLE_STAT4
+ assert( p->nSample==0
+ || pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] );
+#endif
+
+ /* Insert the new sample */
+ pSample = &p->a[p->nSample];
+ sampleCopy(p, pSample, pNew);
+ p->nSample++;
+
+ /* Zero the first nEqZero entries in the anEq[] array. */
+ memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero);
+
+#ifdef SQLITE_ENABLE_STAT4
+ find_new_min:
+#endif
+ if( p->nSample>=p->mxSample ){
+ int iMin = -1;
+ for(i=0; i<p->mxSample; i++){
+ if( p->a[i].isPSample ) continue;
+ if( iMin<0 || sampleIsBetter(p, &p->a[iMin], &p->a[i]) ){
+ iMin = i;
+ }
+ }
+ assert( iMin>=0 );
+ p->iMin = iMin;
+ }
+}
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
+
+/*
+** Field iChng of the index being scanned has changed. So at this point
+** p->current contains a sample that reflects the previous row of the
+** index. The value of anEq[iChng] and subsequent anEq[] elements are
+** correct at this point.
+*/
+static void samplePushPrevious(Stat4Accum *p, int iChng){
+#ifdef SQLITE_ENABLE_STAT4
+ int i;
+
+ /* Check if any samples from the aBest[] array should be pushed
+ ** into IndexSample.a[] at this point. */
+ for(i=(p->nCol-2); i>=iChng; i--){
+ Stat4Sample *pBest = &p->aBest[i];
+ pBest->anEq[i] = p->current.anEq[i];
+ if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){
+ sampleInsert(p, pBest, i);
+ }
+ }
+
+ /* Update the anEq[] fields of any samples already collected. */
+ for(i=p->nSample-1; i>=0; i--){
+ int j;
+ for(j=iChng; j<p->nCol; j++){
+ if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
+ }
+ }
+#endif
+
+#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
+ if( iChng==0 ){
+ tRowcnt nLt = p->current.anLt[0];
+ tRowcnt nEq = p->current.anEq[0];
+
+ /* Check if this is to be a periodic sample. If so, add it. */
+ if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){
+ p->current.isPSample = 1;
+ sampleInsert(p, &p->current, 0);
+ p->current.isPSample = 0;
+ }else
+
+ /* Or if it is a non-periodic sample. Add it in this case too. */
+ if( p->nSample<p->mxSample
+ || sampleIsBetter(p, &p->current, &p->a[p->iMin])
+ ){
+ sampleInsert(p, &p->current, 0);
+ }
+ }
+#endif
+
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
+ UNUSED_PARAMETER( p );
+ UNUSED_PARAMETER( iChng );
+#endif
+}
+
+/*
+** Implementation of the stat_push SQL function: stat_push(P,C,R)
+** Arguments:
+**
+** P Pointer to the Stat4Accum object created by stat_init()
+** C Index of left-most column to differ from previous row
+** R Rowid for the current row. Might be a key record for
+** WITHOUT ROWID tables.
+**
+** The SQL function always returns NULL.
+**
+** The R parameter is only used for STAT3 and STAT4
+*/
+static void statPush(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
- Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[4]);
- tRowcnt nEq = sqlite3_value_int64(argv[0]);
- tRowcnt nLt = sqlite3_value_int64(argv[1]);
- tRowcnt nDLt = sqlite3_value_int64(argv[2]);
- i64 rowid = sqlite3_value_int64(argv[3]);
- u8 isPSample = 0;
- u8 doInsert = 0;
- int iMin = p->iMin;
- struct Stat3Sample *pSample;
int i;
- u32 h;
- UNUSED_PARAMETER(context);
- UNUSED_PARAMETER(argc);
- if( nEq==0 ) return;
- h = p->iPrn = p->iPrn*1103515245 + 12345;
- if( (nLt/p->nPSample)!=((nEq+nLt)/p->nPSample) ){
- doInsert = isPSample = 1;
- }else if( p->nSample<p->mxSample ){
- doInsert = 1;
+ /* The three function arguments */
+ Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
+ int iChng = sqlite3_value_int(argv[1]);
+
+ UNUSED_PARAMETER( argc );
+ UNUSED_PARAMETER( context );
+ assert( p->nCol>1 ); /* Includes rowid field */
+ assert( iChng<p->nCol );
+
+ if( p->nRow==0 ){
+ /* This is the first call to this function. Do initialization. */
+ for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
}else{
- if( nEq>p->a[iMin].nEq || (nEq==p->a[iMin].nEq && h>p->a[iMin].iHash) ){
- doInsert = 1;
+ /* Second and subsequent calls get processed here */
+ samplePushPrevious(p, iChng);
+
+ /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
+ ** to the current row of the index. */
+ for(i=0; i<iChng; i++){
+ p->current.anEq[i]++;
+ }
+ for(i=iChng; i<p->nCol; i++){
+ p->current.anDLt[i]++;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ p->current.anLt[i] += p->current.anEq[i];
+#endif
+ p->current.anEq[i] = 1;
}
}
- if( !doInsert ) return;
- if( p->nSample==p->mxSample ){
- assert( p->nSample - iMin - 1 >= 0 );
- memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1));
- pSample = &p->a[p->nSample-1];
+ p->nRow++;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
+ sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
}else{
- pSample = &p->a[p->nSample++];
+ sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
+ sqlite3_value_blob(argv[2]));
}
- pSample->iRowid = rowid;
- pSample->nEq = nEq;
- pSample->nLt = nLt;
- pSample->nDLt = nDLt;
- pSample->iHash = h;
- pSample->isPSample = isPSample;
+ p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
+#endif
- /* Find the new minimum */
- if( p->nSample==p->mxSample ){
- pSample = p->a;
- i = 0;
- while( pSample->isPSample ){
- i++;
- pSample++;
- assert( i<p->nSample );
- }
- nEq = pSample->nEq;
- h = pSample->iHash;
- iMin = i;
- for(i++, pSample++; i<p->nSample; i++, pSample++){
- if( pSample->isPSample ) continue;
- if( pSample->nEq<nEq
- || (pSample->nEq==nEq && pSample->iHash<h)
- ){
- iMin = i;
- nEq = pSample->nEq;
- h = pSample->iHash;
+#ifdef SQLITE_ENABLE_STAT4
+ {
+ tRowcnt nLt = p->current.anLt[p->nCol-1];
+
+ /* Check if this is to be a periodic sample. If so, add it. */
+ if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
+ p->current.isPSample = 1;
+ p->current.iCol = 0;
+ sampleInsert(p, &p->current, p->nCol-1);
+ p->current.isPSample = 0;
+ }
+
+ /* Update the aBest[] array. */
+ for(i=0; i<(p->nCol-1); i++){
+ p->current.iCol = i;
+ if( i>=iChng || sampleIsBetterPost(p, &p->current, &p->aBest[i]) ){
+ sampleCopy(p, &p->aBest[i], &p->current);
}
}
- p->iMin = iMin;
}
+#endif
}
-static const FuncDef stat3PushFuncdef = {
- 5, /* nArg */
- SQLITE_UTF8, /* iPrefEnc */
- 0, /* flags */
- 0, /* pUserData */
- 0, /* pNext */
- stat3Push, /* xFunc */
- 0, /* xStep */
- 0, /* xFinalize */
- "stat3_push", /* zName */
- 0, /* pHash */
- 0 /* pDestructor */
+static const FuncDef statPushFuncdef = {
+ 2+IsStat34, /* nArg */
+ SQLITE_UTF8, /* funcFlags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ statPush, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat_push", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
};
+#define STAT_GET_STAT1 0 /* "stat" column of stat1 table */
+#define STAT_GET_ROWID 1 /* "rowid" column of stat[34] entry */
+#define STAT_GET_NEQ 2 /* "neq" column of stat[34] entry */
+#define STAT_GET_NLT 3 /* "nlt" column of stat[34] entry */
+#define STAT_GET_NDLT 4 /* "ndlt" column of stat[34] entry */
+
/*
-** Implementation of the stat3_get(P,N,...) SQL function. This routine is
-** used to query the results. Content is returned for the Nth sqlite_stat3
-** row where N is between 0 and S-1 and S is the number of samples. The
-** value returned depends on the number of arguments.
+** Implementation of the stat_get(P,J) SQL function. This routine is
+** used to query the results. Content is returned for parameter J
+** which is one of the STAT_GET_xxxx values defined above.
**
-** argc==2 result: rowid
-** argc==3 result: nEq
-** argc==4 result: nLt
-** argc==5 result: nDLt
+** If neither STAT3 nor STAT4 are enabled, then J is always
+** STAT_GET_STAT1 and is hence omitted and this routine becomes
+** a one-parameter function, stat_get(P), that always returns the
+** stat1 table entry information.
*/
-static void stat3Get(
+static void statGet(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
- int n = sqlite3_value_int(argv[1]);
- Stat3Accum *p = (Stat3Accum*)sqlite3_value_blob(argv[0]);
+ Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ /* STAT3 and STAT4 have a parameter on this routine. */
+ int eCall = sqlite3_value_int(argv[1]);
+ assert( argc==2 );
+ assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ
+ || eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
+ || eCall==STAT_GET_NDLT
+ );
+ if( eCall==STAT_GET_STAT1 )
+#else
+ assert( argc==1 );
+#endif
+ {
+ /* Return the value to store in the "stat" column of the sqlite_stat1
+ ** table for this index.
+ **
+ ** The value is a string composed of a list of integers describing
+ ** the index. The first integer in the list is the total number of
+ ** entries in the index. There is one additional integer in the list
+ ** for each indexed column. This additional integer is an estimate of
+ ** the number of rows matched by a stabbing query on the index using
+ ** a key with the corresponding number of fields. In other words,
+ ** if the index is on columns (a,b) and the sqlite_stat1 value is
+ ** "100 10 2", then SQLite estimates that:
+ **
+ ** * the index contains 100 rows,
+ ** * "WHERE a=?" matches 10 rows, and
+ ** * "WHERE a=? AND b=?" matches 2 rows.
+ **
+ ** If D is the count of distinct values and K is the total number of
+ ** rows, then each estimate is computed as:
+ **
+ ** I = (K+D-1)/D
+ */
+ char *z;
+ int i;
- assert( p!=0 );
- if( p->nSample<=n ) return;
- switch( argc ){
- case 2: sqlite3_result_int64(context, p->a[n].iRowid); break;
- case 3: sqlite3_result_int64(context, p->a[n].nEq); break;
- case 4: sqlite3_result_int64(context, p->a[n].nLt); break;
- default: sqlite3_result_int64(context, p->a[n].nDLt); break;
- }
-}
-static const FuncDef stat3GetFuncdef = {
- -1, /* nArg */
- SQLITE_UTF8, /* iPrefEnc */
- 0, /* flags */
- 0, /* pUserData */
- 0, /* pNext */
- stat3Get, /* xFunc */
- 0, /* xStep */
- 0, /* xFinalize */
- "stat3_get", /* zName */
- 0, /* pHash */
- 0 /* pDestructor */
-};
-#endif /* SQLITE_ENABLE_STAT3 */
+ char *zRet = sqlite3MallocZero(p->nCol * 25);
+ if( zRet==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+
+ sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
+ z = zRet + sqlite3Strlen30(zRet);
+ for(i=0; i<(p->nCol-1); i++){
+ u64 nDistinct = p->current.anDLt[i] + 1;
+ u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
+ sqlite3_snprintf(24, z, " %llu", iVal);
+ z += sqlite3Strlen30(z);
+ assert( p->current.anEq[i] );
+ }
+ assert( z[0]=='\0' && z>zRet );
+
+ sqlite3_result_text(context, zRet, -1, sqlite3_free);
+ }
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ else if( eCall==STAT_GET_ROWID ){
+ if( p->iGet<0 ){
+ samplePushPrevious(p, 0);
+ p->iGet = 0;
+ }
+ if( p->iGet<p->nSample ){
+ Stat4Sample *pS = p->a + p->iGet;
+ if( pS->nRowid==0 ){
+ sqlite3_result_int64(context, pS->u.iRowid);
+ }else{
+ sqlite3_result_blob(context, pS->u.aRowid, pS->nRowid,
+ SQLITE_TRANSIENT);
+ }
+ }
+ }else{
+ tRowcnt *aCnt = 0;
+ assert( p->iGet<p->nSample );
+ switch( eCall ){
+ case STAT_GET_NEQ: aCnt = p->a[p->iGet].anEq; break;
+ case STAT_GET_NLT: aCnt = p->a[p->iGet].anLt; break;
+ default: {
+ aCnt = p->a[p->iGet].anDLt;
+ p->iGet++;
+ break;
+ }
+ }
+ if( IsStat3 ){
+ sqlite3_result_int64(context, (i64)aCnt[0]);
+ }else{
+ char *zRet = sqlite3MallocZero(p->nCol * 25);
+ if( zRet==0 ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ int i;
+ char *z = zRet;
+ for(i=0; i<p->nCol; i++){
+ sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
+ z += sqlite3Strlen30(z);
+ }
+ assert( z[0]=='\0' && z>zRet );
+ z[-1] = '\0';
+ sqlite3_result_text(context, zRet, -1, sqlite3_free);
+ }
+ }
+ }
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
+#ifndef SQLITE_DEBUG
+ UNUSED_PARAMETER( argc );
+#endif
+}
+static const FuncDef statGetFuncdef = {
+ 1+IsStat34, /* nArg */
+ SQLITE_UTF8, /* funcFlags */
+ 0, /* pUserData */
+ 0, /* pNext */
+ statGet, /* xFunc */
+ 0, /* xStep */
+ 0, /* xFinalize */
+ "stat_get", /* zName */
+ 0, /* pHash */
+ 0 /* pDestructor */
+};
+static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
+ assert( regOut!=regStat4 && regOut!=regStat4+1 );
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
+#elif SQLITE_DEBUG
+ assert( iParam==STAT_GET_STAT1 );
+#else
+ UNUSED_PARAMETER( iParam );
+#endif
+ sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
+ sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 1 + IsStat34);
+}
/*
** Generate code to do an analysis of all indices associated with
@@ -80677,41 +82575,31 @@ static void analyzeOneTable(
Table *pTab, /* Table whose indices are to be analyzed */
Index *pOnlyIdx, /* If not NULL, only analyze this one index */
int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */
- int iMem /* Available memory locations begin here */
+ int iMem, /* Available memory locations begin here */
+ int iTab /* Next available cursor */
){
sqlite3 *db = pParse->db; /* Database handle */
Index *pIdx; /* An index to being analyzed */
int iIdxCur; /* Cursor open on index being analyzed */
+ int iTabCur; /* Table cursor */
Vdbe *v; /* The virtual machine being built up */
int i; /* Loop counter */
- int topOfLoop; /* The top of the loop */
- int endOfLoop; /* The end of the loop */
int jZeroRows = -1; /* Jump from here if number of rows is zero */
int iDb; /* Index of database containing pTab */
+ u8 needTableCnt = 1; /* True to count the table */
+ int regNewRowid = iMem++; /* Rowid for the inserted record */
+ int regStat4 = iMem++; /* Register to hold Stat4Accum object */
+ int regChng = iMem++; /* Index of changed index field */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ int regRowid = iMem++; /* Rowid argument passed to stat_push() */
+#endif
+ int regTemp = iMem++; /* Temporary use register */
int regTabname = iMem++; /* Register containing table name */
int regIdxname = iMem++; /* Register containing index name */
- int regStat1 = iMem++; /* The stat column of sqlite_stat1 */
-#ifdef SQLITE_ENABLE_STAT3
- int regNumEq = regStat1; /* Number of instances. Same as regStat1 */
- int regNumLt = iMem++; /* Number of keys less than regSample */
- int regNumDLt = iMem++; /* Number of distinct keys less than regSample */
- int regSample = iMem++; /* The next sample value */
- int regRowid = regSample; /* Rowid of a sample */
- int regAccum = iMem++; /* Register to hold Stat3Accum object */
- int regLoop = iMem++; /* Loop counter */
- int regCount = iMem++; /* Number of rows in the table or index */
- int regTemp1 = iMem++; /* Intermediate register */
- int regTemp2 = iMem++; /* Intermediate register */
- int once = 1; /* One-time initialization */
- int shortJump = 0; /* Instruction address */
- int iTabCur = pParse->nTab++; /* Table cursor */
-#endif
- int regCol = iMem++; /* Content of a column in analyzed table */
- int regRec = iMem++; /* Register holding completed record */
- int regTemp = iMem++; /* Temporary use register */
- int regNewRowid = iMem++; /* Rowid for the inserted record */
-
+ int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
+ int regPrev = iMem; /* MUST BE LAST (see below) */
+ pParse->nMem = MAX(pParse->nMem, iMem);
v = sqlite3GetVdbe(pParse);
if( v==0 || NEVER(pTab==0) ){
return;
@@ -80735,215 +82623,244 @@ static void analyzeOneTable(
}
#endif
- /* Establish a read-lock on the table at the shared-cache level. */
+ /* Establish a read-lock on the table at the shared-cache level.
+ ** Open a read-only cursor on the table. Also allocate a cursor number
+ ** to use for scanning indexes (iIdxCur). No index cursor is opened at
+ ** this time though. */
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
-
- iIdxCur = pParse->nTab++;
+ iTabCur = iTab++;
+ iIdxCur = iTab++;
+ pParse->nTab = MAX(pParse->nTab, iTab);
+ sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
sqlite3VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
+
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int nCol;
- KeyInfo *pKey;
- int addrIfNot = 0; /* address of OP_IfNot */
- int *aChngAddr; /* Array of jump instruction addresses */
+ int nCol; /* Number of columns indexed by pIdx */
+ int *aGotoChng; /* Array of jump instruction addresses */
+ int addrRewind; /* Address of "OP_Rewind iIdxCur" */
+ int addrGotoChng0; /* Address of "Goto addr_chng_0" */
+ int addrNextRow; /* Address of "next_row:" */
+ const char *zIdxName; /* Name of the index */
if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
+ if( pIdx->pPartIdxWhere==0 ) needTableCnt = 0;
VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
- nCol = pIdx->nColumn;
- aChngAddr = sqlite3DbMallocRaw(db, sizeof(int)*nCol);
- if( aChngAddr==0 ) continue;
- pKey = sqlite3IndexKeyinfo(pParse, pIdx);
- if( iMem+1+(nCol*2)>pParse->nMem ){
- pParse->nMem = iMem+1+(nCol*2);
- }
-
- /* Open a cursor to the index to be analyzed. */
- assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
- sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb,
- (char *)pKey, P4_KEYINFO_HANDOFF);
- VdbeComment((v, "%s", pIdx->zName));
+ nCol = pIdx->nKeyCol;
+ aGotoChng = sqlite3DbMallocRaw(db, sizeof(int)*(nCol+1));
+ if( aGotoChng==0 ) continue;
/* Populate the register containing the index name. */
- sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0);
+ if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
+ zIdxName = pTab->zName;
+ }else{
+ zIdxName = pIdx->zName;
+ }
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, zIdxName, 0);
-#ifdef SQLITE_ENABLE_STAT3
- if( once ){
- once = 0;
- sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
- }
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regCount);
- sqlite3VdbeAddOp2(v, OP_Integer, SQLITE_STAT3_SAMPLES, regTemp1);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumEq);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regNumLt);
- sqlite3VdbeAddOp2(v, OP_Integer, -1, regNumDLt);
- sqlite3VdbeAddOp3(v, OP_Null, 0, regSample, regAccum);
- sqlite3VdbeAddOp4(v, OP_Function, 1, regCount, regAccum,
- (char*)&stat3InitFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 2);
-#endif /* SQLITE_ENABLE_STAT3 */
-
- /* The block of memory cells initialized here is used as follows.
+ /*
+ ** Pseudo-code for loop that calls stat_push():
+ **
+ ** Rewind csr
+ ** if eof(csr) goto end_of_scan;
+ ** regChng = 0
+ ** goto chng_addr_0;
**
- ** iMem:
- ** The total number of rows in the table.
+ ** next_row:
+ ** regChng = 0
+ ** if( idx(0) != regPrev(0) ) goto chng_addr_0
+ ** regChng = 1
+ ** if( idx(1) != regPrev(1) ) goto chng_addr_1
+ ** ...
+ ** regChng = N
+ ** goto chng_addr_N
**
- ** iMem+1 .. iMem+nCol:
- ** Number of distinct entries in index considering the
- ** left-most N columns only, where N is between 1 and nCol,
- ** inclusive.
+ ** chng_addr_0:
+ ** regPrev(0) = idx(0)
+ ** chng_addr_1:
+ ** regPrev(1) = idx(1)
+ ** ...
**
- ** iMem+nCol+1 .. Mem+2*nCol:
- ** Previous value of indexed columns, from left to right.
+ ** chng_addr_N:
+ ** regRowid = idx(rowid)
+ ** stat_push(P, regChng, regRowid)
+ ** Next csr
+ ** if !eof(csr) goto next_row;
**
- ** Cells iMem through iMem+nCol are initialized to 0. The others are
- ** initialized to contain an SQL NULL.
+ ** end_of_scan:
*/
- for(i=0; i<=nCol; i++){
- sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i);
- }
- for(i=0; i<nCol; i++){
- sqlite3VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1);
- }
- /* Start the analysis loop. This loop runs through all the entries in
- ** the index b-tree. */
- endOfLoop = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
- topOfLoop = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); /* Increment row counter */
+ /* Make sure there are enough memory cells allocated to accommodate
+ ** the regPrev array and a trailing rowid (the rowid slot is required
+ ** when building a record to insert into the sample column of
+ ** the sqlite_stat4 table. */
+ pParse->nMem = MAX(pParse->nMem, regPrev+nCol);
- for(i=0; i<nCol; i++){
- CollSeq *pColl;
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol);
- if( i==0 ){
- /* Always record the very first row */
- addrIfNot = sqlite3VdbeAddOp1(v, OP_IfNot, iMem+1);
- }
- assert( pIdx->azColl!=0 );
- assert( pIdx->azColl[i]!=0 );
- pColl = sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
- aChngAddr[i] = sqlite3VdbeAddOp4(v, OP_Ne, regCol, 0, iMem+nCol+i+1,
- (char*)pColl, P4_COLLSEQ);
- sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
- VdbeComment((v, "jump if column %d changed", i));
-#ifdef SQLITE_ENABLE_STAT3
- if( i==0 ){
- sqlite3VdbeAddOp2(v, OP_AddImm, regNumEq, 1);
- VdbeComment((v, "incr repeat count"));
- }
-#endif
- }
- sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
- for(i=0; i<nCol; i++){
- sqlite3VdbeJumpHere(v, aChngAddr[i]); /* Set jump dest for the OP_Ne */
- if( i==0 ){
- sqlite3VdbeJumpHere(v, addrIfNot); /* Jump dest for OP_IfNot */
-#ifdef SQLITE_ENABLE_STAT3
- sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
- (char*)&stat3PushFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 5);
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, pIdx->nColumn, regRowid);
- sqlite3VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt);
- sqlite3VdbeAddOp2(v, OP_AddImm, regNumDLt, 1);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regNumEq);
-#endif
- }
- sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1);
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);
- }
- sqlite3DbFree(db, aChngAddr);
-
- /* Always jump here after updating the iMem+1...iMem+1+nCol counters */
- sqlite3VdbeResolveLabel(v, endOfLoop);
+ /* Open a read-only cursor on the index being analyzed. */
+ assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) );
+ sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb);
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
+ VdbeComment((v, "%s", pIdx->zName));
- sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
- sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
-#ifdef SQLITE_ENABLE_STAT3
- sqlite3VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
- (char*)&stat3PushFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 5);
- sqlite3VdbeAddOp2(v, OP_Integer, -1, regLoop);
- shortJump =
- sqlite3VdbeAddOp2(v, OP_AddImm, regLoop, 1);
- sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regTemp1,
- (char*)&stat3GetFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 2);
- sqlite3VdbeAddOp1(v, OP_IsNull, regTemp1);
- sqlite3VdbeAddOp3(v, OP_NotExists, iTabCur, shortJump, regTemp1);
- sqlite3VdbeAddOp3(v, OP_Column, iTabCur, pIdx->aiColumn[0], regSample);
- sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[0], regSample);
- sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumEq,
- (char*)&stat3GetFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 3);
- sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumLt,
- (char*)&stat3GetFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 4);
- sqlite3VdbeAddOp4(v, OP_Function, 1, regAccum, regNumDLt,
- (char*)&stat3GetFuncdef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, 5);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regRec, "bbbbbb", 0);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid);
- sqlite3VdbeAddOp2(v, OP_Goto, 0, shortJump);
- sqlite3VdbeJumpHere(v, shortJump+2);
-#endif
-
- /* Store the results in sqlite_stat1.
+ /* Invoke the stat_init() function. The arguments are:
+ **
+ ** (1) the number of columns in the index including the rowid,
+ ** (2) the number of rows in the index,
**
- ** The result is a single row of the sqlite_stat1 table. The first
- ** two columns are the names of the table and index. The third column
- ** is a string composed of a list of integer statistics about the
- ** index. The first integer in the list is the total number of entries
- ** in the index. There is one additional integer in the list for each
- ** column of the table. This additional integer is a guess of how many
- ** rows of the table the index will select. If D is the count of distinct
- ** values and K is the total number of rows, then the integer is computed
- ** as:
+ ** The second argument is only used for STAT3 and STAT4
+ */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+2);
+#endif
+ sqlite3VdbeAddOp2(v, OP_Integer, nCol+1, regStat4+1);
+ sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4+1, regStat4);
+ sqlite3VdbeChangeP4(v, -1, (char*)&statInitFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 1+IsStat34);
+
+ /* Implementation of the following:
**
- ** I = (K+D-1)/D
+ ** Rewind csr
+ ** if eof(csr) goto end_of_scan;
+ ** regChng = 0
+ ** goto next_push_0;
**
- ** If K==0 then no entry is made into the sqlite_stat1 table.
- ** If K>0 then it is always the case the D>0 so division by zero
- ** is never possible.
*/
- sqlite3VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
- if( jZeroRows<0 ){
- jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, iMem);
+ addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
+ addrGotoChng0 = sqlite3VdbeAddOp0(v, OP_Goto);
+
+ /*
+ ** next_row:
+ ** regChng = 0
+ ** if( idx(0) != regPrev(0) ) goto chng_addr_0
+ ** regChng = 1
+ ** if( idx(1) != regPrev(1) ) goto chng_addr_1
+ ** ...
+ ** regChng = N
+ ** goto chng_addr_N
+ */
+ addrNextRow = sqlite3VdbeCurrentAddr(v);
+ for(i=0; i<nCol; i++){
+ char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
+ sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
+ aGotoChng[i] =
+ sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
}
+ sqlite3VdbeAddOp2(v, OP_Integer, nCol, regChng);
+ aGotoChng[nCol] = sqlite3VdbeAddOp0(v, OP_Goto);
+
+ /*
+ ** chng_addr_0:
+ ** regPrev(0) = idx(0)
+ ** chng_addr_1:
+ ** regPrev(1) = idx(1)
+ ** ...
+ */
+ sqlite3VdbeJumpHere(v, addrGotoChng0);
for(i=0; i<nCol; i++){
- sqlite3VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0);
- sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
- sqlite3VdbeAddOp3(v, OP_Add, iMem, iMem+i+1, regTemp);
- sqlite3VdbeAddOp2(v, OP_AddImm, regTemp, -1);
- sqlite3VdbeAddOp3(v, OP_Divide, iMem+i+1, regTemp, regTemp);
- sqlite3VdbeAddOp1(v, OP_ToInt, regTemp);
- sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
- }
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
+ sqlite3VdbeJumpHere(v, aGotoChng[i]);
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
+ }
+
+ /*
+ ** chng_addr_N:
+ ** regRowid = idx(rowid) // STAT34 only
+ ** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only
+ ** Next csr
+ ** if !eof(csr) goto next_row;
+ */
+ sqlite3VdbeJumpHere(v, aGotoChng[nCol]);
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ assert( regRowid==(regStat4+2) );
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
+ }else{
+ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
+ int j, k, regKey;
+ regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
+ for(j=0; j<pPk->nKeyCol; j++){
+ k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
+ VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
+ sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
+ }
+#endif
+ assert( regChng==(regStat4+1) );
+ sqlite3VdbeAddOp3(v, OP_Function, 1, regStat4, regTemp);
+ sqlite3VdbeChangeP4(v, -1, (char*)&statPushFuncdef, P4_FUNCDEF);
+ sqlite3VdbeChangeP5(v, 2+IsStat34);
+ sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow);
+
+ /* Add the entry to the stat1 table. */
+ callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+
+ /* Add the entries to the stat3 or stat4 table. */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ {
+ int regEq = regStat1;
+ int regLt = regStat1+1;
+ int regDLt = regStat1+2;
+ int regSample = regStat1+3;
+ int regCol = regStat1+4;
+ int regSampleRowid = regCol + nCol;
+ int addrNext;
+ int addrIsNull;
+ u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
+
+ pParse->nMem = MAX(pParse->nMem, regCol+nCol+1);
+
+ addrNext = sqlite3VdbeCurrentAddr(v);
+ callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
+ addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
+ callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
+ callStatGet(v, regStat4, STAT_GET_NLT, regLt);
+ callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
+ sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
+#ifdef SQLITE_ENABLE_STAT3
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
+ pIdx->aiColumn[0], regSample);
+#else
+ for(i=0; i<nCol; i++){
+ i16 iCol = pIdx->aiColumn[i];
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, iCol, regCol+i);
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol+1, regSample);
+#endif
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regTemp, "bbbbbb", 0);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext);
+ sqlite3VdbeJumpHere(v, addrIsNull);
+ }
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
+
+ /* End of analysis */
+ sqlite3VdbeJumpHere(v, addrRewind);
+ sqlite3DbFree(db, aGotoChng);
}
- /* If the table has no indices, create a single sqlite_stat1 entry
- ** containing NULL as the index name and the row count as the content.
+
+ /* Create a single sqlite_stat1 entry containing NULL as the index
+ ** name and the row count as the content.
*/
- if( pTab->pIndex==0 ){
- sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pTab->tnum, iDb);
+ if( pOnlyIdx==0 && needTableCnt ){
VdbeComment((v, "%s", pTab->zName));
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat1);
- sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);
+ sqlite3VdbeAddOp2(v, OP_Count, iTabCur, regStat1);
jZeroRows = sqlite3VdbeAddOp1(v, OP_IfNot, regStat1);
- }else{
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "aaa", 0);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regTemp, regNewRowid);
+ sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3VdbeJumpHere(v, jZeroRows);
- jZeroRows = sqlite3VdbeAddOp0(v, OP_Goto);
}
- sqlite3VdbeAddOp2(v, OP_Null, 0, regIdxname);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
- sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
- sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
- if( pParse->nMem<regRec ) pParse->nMem = regRec;
- sqlite3VdbeJumpHere(v, jZeroRows);
}
@@ -80967,16 +82884,18 @@ static void analyzeDatabase(Parse *pParse, int iDb){
HashElem *k;
int iStatCur;
int iMem;
+ int iTab;
sqlite3BeginWriteOperation(pParse, 0, iDb);
iStatCur = pParse->nTab;
pParse->nTab += 3;
openStatTable(pParse, iDb, iStatCur, 0, 0);
iMem = pParse->nMem+1;
+ iTab = pParse->nTab;
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
Table *pTab = (Table*)sqliteHashData(k);
- analyzeOneTable(pParse, pTab, 0, iStatCur, iMem);
+ analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab);
}
loadAnalysis(pParse, iDb);
}
@@ -81001,7 +82920,7 @@ static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){
}else{
openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl");
}
- analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem+1);
+ analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur,pParse->nMem+1,pParse->nTab);
loadAnalysis(pParse, iDb);
}
@@ -81085,6 +83004,52 @@ struct analysisInfo {
};
/*
+** The first argument points to a nul-terminated string containing a
+** list of space separated integers. Read the first nOut of these into
+** the array aOut[].
+*/
+static void decodeIntArray(
+ char *zIntArray, /* String containing int array to decode */
+ int nOut, /* Number of slots in aOut[] */
+ tRowcnt *aOut, /* Store integers here */
+ Index *pIndex /* Handle extra flags for this index, if not NULL */
+){
+ char *z = zIntArray;
+ int c;
+ int i;
+ tRowcnt v;
+
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( z==0 ) z = "";
+#else
+ if( NEVER(z==0) ) z = "";
+#endif
+ for(i=0; *z && i<nOut; i++){
+ v = 0;
+ while( (c=z[0])>='0' && c<='9' ){
+ v = v*10 + c - '0';
+ z++;
+ }
+ aOut[i] = v;
+ if( *z==' ' ) z++;
+ }
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
+ assert( pIndex!=0 );
+#else
+ if( pIndex )
+#endif
+ {
+ if( strcmp(z, "unordered")==0 ){
+ pIndex->bUnordered = 1;
+ }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
+ int v32 = 0;
+ sqlite3GetInt32(z+3, &v32);
+ pIndex->szIdxRow = sqlite3LogEst(v32);
+ }
+ }
+}
+
+/*
** This callback is invoked once for each index when reading the
** sqlite_stat1 table.
**
@@ -81099,8 +83064,6 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
analysisInfo *pInfo = (analysisInfo*)pData;
Index *pIndex;
Table *pTable;
- int i, c, n;
- tRowcnt v;
const char *z;
assert( argc==3 );
@@ -81113,28 +83076,25 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
if( pTable==0 ){
return 0;
}
- if( argv[1] ){
- pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
- }else{
+ if( argv[1]==0 ){
pIndex = 0;
+ }else if( sqlite3_stricmp(argv[0],argv[1])==0 ){
+ pIndex = sqlite3PrimaryKeyIndex(pTable);
+ }else{
+ pIndex = sqlite3FindIndex(pInfo->db, argv[1], pInfo->zDatabase);
}
- n = pIndex ? pIndex->nColumn : 0;
z = argv[2];
- for(i=0; *z && i<=n; i++){
- v = 0;
- while( (c=z[0])>='0' && c<='9' ){
- v = v*10 + c - '0';
- z++;
- }
- if( i==0 ) pTable->nRowEst = v;
- if( pIndex==0 ) break;
- pIndex->aiRowEst[i] = v;
- if( *z==' ' ) z++;
- if( strcmp(z, "unordered")==0 ){
- pIndex->bUnordered = 1;
- break;
- }
+
+ if( pIndex ){
+ decodeIntArray((char*)z, pIndex->nKeyCol+1, pIndex->aiRowEst, pIndex);
+ if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
+ }else{
+ Index fakeIdx;
+ fakeIdx.szIdxRow = pTable->szTabRow;
+ decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx);
+ pTable->szTabRow = fakeIdx.szIdxRow;
}
+
return 0;
}
@@ -81143,14 +83103,12 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
** and its contents.
*/
SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( pIdx->aSample ){
int j;
for(j=0; j<pIdx->nSample; j++){
IndexSample *p = &pIdx->aSample[j];
- if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
- sqlite3DbFree(db, p->u.z);
- }
+ sqlite3DbFree(db, p->p);
}
sqlite3DbFree(db, pIdx->aSample);
}
@@ -81161,31 +83119,92 @@ SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
#else
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(pIdx);
-#endif
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
}
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
-** Load content from the sqlite_stat3 table into the Index.aSample[]
-** arrays of all indices.
+** Populate the pIdx->aAvgEq[] array based on the samples currently
+** stored in pIdx->aSample[].
*/
-static int loadStat3(sqlite3 *db, const char *zDb){
+static void initAvgEq(Index *pIdx){
+ if( pIdx ){
+ IndexSample *aSample = pIdx->aSample;
+ IndexSample *pFinal = &aSample[pIdx->nSample-1];
+ int iCol;
+ for(iCol=0; iCol<pIdx->nKeyCol; iCol++){
+ int i; /* Used to iterate through samples */
+ tRowcnt sumEq = 0; /* Sum of the nEq values */
+ tRowcnt nSum = 0; /* Number of terms contributing to sumEq */
+ tRowcnt avgEq = 0;
+ tRowcnt nDLt = pFinal->anDLt[iCol];
+
+ /* Set nSum to the number of distinct (iCol+1) field prefixes that
+ ** occur in the stat4 table for this index before pFinal. Set
+ ** sumEq to the sum of the nEq values for column iCol for the same
+ ** set (adding the value only once where there exist dupicate
+ ** prefixes). */
+ for(i=0; i<(pIdx->nSample-1); i++){
+ if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){
+ sumEq += aSample[i].anEq[iCol];
+ nSum++;
+ }
+ }
+ if( nDLt>nSum ){
+ avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum);
+ }
+ if( avgEq==0 ) avgEq = 1;
+ pIdx->aAvgEq[iCol] = avgEq;
+ if( pIdx->nSampleCol==1 ) break;
+ }
+ }
+}
+
+/*
+** Look up an index by name. Or, if the name of a WITHOUT ROWID table
+** is supplied instead, find the PRIMARY KEY index for that table.
+*/
+static Index *findIndexOrPrimaryKey(
+ sqlite3 *db,
+ const char *zName,
+ const char *zDb
+){
+ Index *pIdx = sqlite3FindIndex(db, zName, zDb);
+ if( pIdx==0 ){
+ Table *pTab = sqlite3FindTable(db, zName, zDb);
+ if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab);
+ }
+ return pIdx;
+}
+
+/*
+** Load the content from either the sqlite_stat4 or sqlite_stat3 table
+** into the relevant Index.aSample[] arrays.
+**
+** Arguments zSql1 and zSql2 must point to SQL statements that return
+** data equivalent to the following (statements are different for stat3,
+** see the caller of this function for details):
+**
+** zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx
+** zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4
+**
+** where %Q is replaced with the database name before the SQL is executed.
+*/
+static int loadStatTbl(
+ sqlite3 *db, /* Database handle */
+ int bStat3, /* Assume single column records only */
+ const char *zSql1, /* SQL statement 1 (see above) */
+ const char *zSql2, /* SQL statement 2 (see above) */
+ const char *zDb /* Database name (e.g. "main") */
+){
int rc; /* Result codes from subroutines */
sqlite3_stmt *pStmt = 0; /* An SQL statement being run */
char *zSql; /* Text of the SQL statement */
Index *pPrevIdx = 0; /* Previous index in the loop */
- int idx = 0; /* slot in pIdx->aSample[] for next sample */
- int eType; /* Datatype of a sample */
IndexSample *pSample; /* A slot in pIdx->aSample[] */
assert( db->lookaside.bEnabled==0 );
- if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){
- return SQLITE_OK;
- }
-
- zSql = sqlite3MPrintf(db,
- "SELECT idx,count(*) FROM %Q.sqlite_stat3"
- " GROUP BY idx", zDb);
+ zSql = sqlite3MPrintf(db, zSql1, zDb);
if( !zSql ){
return SQLITE_NOMEM;
}
@@ -81194,30 +83213,51 @@ static int loadStat3(sqlite3 *db, const char *zDb){
if( rc ) return rc;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
+ int nIdxCol = 1; /* Number of columns in stat4 records */
+ int nAvgCol = 1; /* Number of entries in Index.aAvgEq */
+
char *zIndex; /* Index name */
Index *pIdx; /* Pointer to the index object */
int nSample; /* Number of samples */
+ int nByte; /* Bytes of space required */
+ int i; /* Bytes of space required */
+ tRowcnt *pSpace;
zIndex = (char *)sqlite3_column_text(pStmt, 0);
if( zIndex==0 ) continue;
nSample = sqlite3_column_int(pStmt, 1);
- pIdx = sqlite3FindIndex(db, zIndex, zDb);
- if( pIdx==0 ) continue;
- assert( pIdx->nSample==0 );
- pIdx->nSample = nSample;
- pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample));
- pIdx->avgEq = pIdx->aiRowEst[1];
+ pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
+ assert( pIdx==0 || bStat3 || pIdx->nSample==0 );
+ /* Index.nSample is non-zero at this point if data has already been
+ ** loaded from the stat4 table. In this case ignore stat3 data. */
+ if( pIdx==0 || pIdx->nSample ) continue;
+ if( bStat3==0 ){
+ nIdxCol = pIdx->nKeyCol+1;
+ nAvgCol = pIdx->nKeyCol;
+ }
+ pIdx->nSampleCol = nIdxCol;
+ nByte = sizeof(IndexSample) * nSample;
+ nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
+ nByte += nAvgCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
+
+ pIdx->aSample = sqlite3DbMallocZero(db, nByte);
if( pIdx->aSample==0 ){
- db->mallocFailed = 1;
sqlite3_finalize(pStmt);
return SQLITE_NOMEM;
}
+ pSpace = (tRowcnt*)&pIdx->aSample[nSample];
+ pIdx->aAvgEq = pSpace; pSpace += nAvgCol;
+ for(i=0; i<nSample; i++){
+ pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
+ pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol;
+ pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol;
+ }
+ assert( ((u8*)pSpace)-nByte==(u8*)(pIdx->aSample) );
}
rc = sqlite3_finalize(pStmt);
if( rc ) return rc;
- zSql = sqlite3MPrintf(db,
- "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
+ zSql = sqlite3MPrintf(db, zSql2, zDb);
if( !zSql ){
return SQLITE_NOMEM;
}
@@ -81226,86 +83266,88 @@ static int loadStat3(sqlite3 *db, const char *zDb){
if( rc ) return rc;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
- char *zIndex; /* Index name */
- Index *pIdx; /* Pointer to the index object */
- int i; /* Loop counter */
- tRowcnt sumEq; /* Sum of the nEq values */
+ char *zIndex; /* Index name */
+ Index *pIdx; /* Pointer to the index object */
+ int nCol = 1; /* Number of columns in index */
zIndex = (char *)sqlite3_column_text(pStmt, 0);
if( zIndex==0 ) continue;
- pIdx = sqlite3FindIndex(db, zIndex, zDb);
+ pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
if( pIdx==0 ) continue;
- if( pIdx==pPrevIdx ){
- idx++;
- }else{
+ /* This next condition is true if data has already been loaded from
+ ** the sqlite_stat4 table. In this case ignore stat3 data. */
+ nCol = pIdx->nSampleCol;
+ if( bStat3 && nCol>1 ) continue;
+ if( pIdx!=pPrevIdx ){
+ initAvgEq(pPrevIdx);
pPrevIdx = pIdx;
- idx = 0;
- }
- assert( idx<pIdx->nSample );
- pSample = &pIdx->aSample[idx];
- pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 1);
- pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 2);
- pSample->nDLt = (tRowcnt)sqlite3_column_int64(pStmt, 3);
- if( idx==pIdx->nSample-1 ){
- if( pSample->nDLt>0 ){
- for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq;
- pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt;
- }
- if( pIdx->avgEq<=0 ) pIdx->avgEq = 1;
- }
- eType = sqlite3_column_type(pStmt, 4);
- pSample->eType = (u8)eType;
- switch( eType ){
- case SQLITE_INTEGER: {
- pSample->u.i = sqlite3_column_int64(pStmt, 4);
- break;
- }
- case SQLITE_FLOAT: {
- pSample->u.r = sqlite3_column_double(pStmt, 4);
- break;
- }
- case SQLITE_NULL: {
- break;
- }
- default: assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); {
- const char *z = (const char *)(
- (eType==SQLITE_BLOB) ?
- sqlite3_column_blob(pStmt, 4):
- sqlite3_column_text(pStmt, 4)
- );
- int n = z ? sqlite3_column_bytes(pStmt, 4) : 0;
- pSample->nByte = n;
- if( n < 1){
- pSample->u.z = 0;
- }else{
- pSample->u.z = sqlite3DbMallocRaw(db, n);
- if( pSample->u.z==0 ){
- db->mallocFailed = 1;
- sqlite3_finalize(pStmt);
- return SQLITE_NOMEM;
- }
- memcpy(pSample->u.z, z, n);
- }
- }
}
+ pSample = &pIdx->aSample[pIdx->nSample];
+ decodeIntArray((char*)sqlite3_column_text(pStmt,1), nCol, pSample->anEq, 0);
+ decodeIntArray((char*)sqlite3_column_text(pStmt,2), nCol, pSample->anLt, 0);
+ decodeIntArray((char*)sqlite3_column_text(pStmt,3), nCol, pSample->anDLt,0);
+
+ /* Take a copy of the sample. Add two 0x00 bytes the end of the buffer.
+ ** This is in case the sample record is corrupted. In that case, the
+ ** sqlite3VdbeRecordCompare() may read up to two varints past the
+ ** end of the allocated buffer before it realizes it is dealing with
+ ** a corrupt record. Adding the two 0x00 bytes prevents this from causing
+ ** a buffer overread. */
+ pSample->n = sqlite3_column_bytes(pStmt, 4);
+ pSample->p = sqlite3DbMallocZero(db, pSample->n + 2);
+ if( pSample->p==0 ){
+ sqlite3_finalize(pStmt);
+ return SQLITE_NOMEM;
+ }
+ memcpy(pSample->p, sqlite3_column_blob(pStmt, 4), pSample->n);
+ pIdx->nSample++;
}
- return sqlite3_finalize(pStmt);
+ rc = sqlite3_finalize(pStmt);
+ if( rc==SQLITE_OK ) initAvgEq(pPrevIdx);
+ return rc;
+}
+
+/*
+** Load content from the sqlite_stat4 and sqlite_stat3 tables into
+** the Index.aSample[] arrays of all indices.
+*/
+static int loadStat4(sqlite3 *db, const char *zDb){
+ int rc = SQLITE_OK; /* Result codes from subroutines */
+
+ assert( db->lookaside.bEnabled==0 );
+ if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
+ rc = loadStatTbl(db, 0,
+ "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx",
+ "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
+ zDb
+ );
+ }
+
+ if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){
+ rc = loadStatTbl(db, 1,
+ "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx",
+ "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3",
+ zDb
+ );
+ }
+
+ return rc;
}
-#endif /* SQLITE_ENABLE_STAT3 */
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
/*
-** Load the content of the sqlite_stat1 and sqlite_stat3 tables. The
+** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The
** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
-** arrays. The contents of sqlite_stat3 are used to populate the
+** arrays. The contents of sqlite_stat3/4 are used to populate the
** Index.aSample[] arrays.
**
** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
-** is returned. In this case, even if SQLITE_ENABLE_STAT3 was defined
-** during compilation and the sqlite_stat3 table is present, no data is
+** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined
+** during compilation and the sqlite_stat3/4 table is present, no data is
** read from it.
**
-** If SQLITE_ENABLE_STAT3 was defined during compilation and the
-** sqlite_stat3 table is not present in the database, SQLITE_ERROR is
+** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the
+** sqlite_stat4 table is not present in the database, SQLITE_ERROR is
** returned. However, in this case, data is read from the sqlite_stat1
** table (if it is present) before returning.
**
@@ -81327,7 +83369,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3DefaultRowEst(pIdx);
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3DeleteIndexSamples(db, pIdx);
pIdx->aSample = 0;
#endif
@@ -81351,12 +83393,12 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
}
- /* Load the statistics from the sqlite_stat3 table. */
-#ifdef SQLITE_ENABLE_STAT3
+ /* Load the statistics from the sqlite_stat4 table. */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( rc==SQLITE_OK ){
int lookasideEnabled = db->lookaside.bEnabled;
db->lookaside.bEnabled = 0;
- rc = loadStat3(db, sInfo.zDatabase);
+ rc = loadStat4(db, sInfo.zDatabase);
db->lookaside.bEnabled = lookasideEnabled;
}
#endif
@@ -81531,6 +83573,9 @@ static void attachFunc(
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
sqlite3BtreeSecureDelete(aNew->pBt,
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+ sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
+#endif
}
aNew->safety_level = 3;
aNew->zName = sqlite3DbStrDup(db, zName);
@@ -81749,8 +83794,7 @@ attach_end:
SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){
static const FuncDef detach_func = {
1, /* nArg */
- SQLITE_UTF8, /* iPrefEnc */
- 0, /* flags */
+ SQLITE_UTF8, /* funcFlags */
0, /* pUserData */
0, /* pNext */
detachFunc, /* xFunc */
@@ -81771,8 +83815,7 @@ SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){
SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
static const FuncDef attach_func = {
3, /* nArg */
- SQLITE_UTF8, /* iPrefEnc */
- 0, /* flags */
+ SQLITE_UTF8, /* funcFlags */
0, /* pUserData */
0, /* pNext */
attachFunc, /* xFunc */
@@ -81789,11 +83832,8 @@ SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *p
/*
** Initialize a DbFixer structure. This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
-**
-** The return value indicates whether or not fixation is required. TRUE
-** means we do need to fix the database references, FALSE means we do not.
*/
-SQLITE_PRIVATE int sqlite3FixInit(
+SQLITE_PRIVATE void sqlite3FixInit(
DbFixer *pFix, /* The fixer to be initialized */
Parse *pParse, /* Error messages will be written here */
int iDb, /* This is the database that must be used */
@@ -81802,7 +83842,6 @@ SQLITE_PRIVATE int sqlite3FixInit(
){
sqlite3 *db;
- if( NEVER(iDb<0) || iDb==1 ) return 0;
db = pParse->db;
assert( db->nDb>iDb );
pFix->pParse = pParse;
@@ -81810,7 +83849,7 @@ SQLITE_PRIVATE int sqlite3FixInit(
pFix->pSchema = db->aDb[iDb].pSchema;
pFix->zType = zType;
pFix->pName = pName;
- return 1;
+ pFix->bVarOnly = (iDb==1);
}
/*
@@ -81838,15 +83877,17 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
if( NEVER(pList==0) ) return 0;
zDb = pFix->zDb;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
- sqlite3ErrorMsg(pFix->pParse,
- "%s %T cannot reference objects in database %s",
- pFix->zType, pFix->pName, pItem->zDatabase);
- return 1;
+ if( pFix->bVarOnly==0 ){
+ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
+ sqlite3ErrorMsg(pFix->pParse,
+ "%s %T cannot reference objects in database %s",
+ pFix->zType, pFix->pName, pItem->zDatabase);
+ return 1;
+ }
+ sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
+ pItem->zDatabase = 0;
+ pItem->pSchema = pFix->pSchema;
}
- sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
- pItem->zDatabase = 0;
- pItem->pSchema = pFix->pSchema;
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
@@ -81869,9 +83910,21 @@ SQLITE_PRIVATE int sqlite3FixSelect(
if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
return 1;
}
+ if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
+ return 1;
+ }
if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
return 1;
}
+ if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
+ return 1;
+ }
+ if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
+ return 1;
+ }
+ if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
+ return 1;
+ }
pSelect = pSelect->pPrior;
}
return 0;
@@ -81881,7 +83934,15 @@ SQLITE_PRIVATE int sqlite3FixExpr(
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
- if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break;
+ if( pExpr->op==TK_VARIABLE ){
+ if( pFix->pParse->db->init.busy ){
+ pExpr->op = TK_NULL;
+ }else{
+ sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
+ return 1;
+ }
+ }
+ if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
}else{
@@ -82335,7 +84396,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
*/
if( pParse->cookieGoto>0 ){
yDbMask mask;
- int iDb;
+ int iDb, i, addr;
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
if( (mask & pParse->cookieMask)==0 ) continue;
@@ -82349,14 +84410,11 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- {
- int i;
- for(i=0; i<pParse->nVtabLock; i++){
- char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
- sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
- }
- pParse->nVtabLock = 0;
+ for(i=0; i<pParse->nVtabLock; i++){
+ char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
+ sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
}
+ pParse->nVtabLock = 0;
#endif
/* Once all the cookies have been verified and transactions opened,
@@ -82369,8 +84427,18 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
*/
sqlite3AutoincrementBegin(pParse);
+ /* Code constant expressions that where factored out of inner loops */
+ addr = pParse->cookieGoto;
+ if( pParse->pConstExpr ){
+ ExprList *pEL = pParse->pConstExpr;
+ pParse->cookieGoto = 0;
+ for(i=0; i<pEL->nExpr; i++){
+ sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
+ }
+ }
+
/* Finally, jump back to the beginning of the executable code. */
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
}
}
@@ -82378,10 +84446,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
/* Get the VDBE program ready for execution
*/
if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
-#ifdef SQLITE_DEBUG
- FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
- sqlite3VdbeTrace(v, trace);
-#endif
assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
@@ -82567,7 +84631,10 @@ static void freeIndex(sqlite3 *db, Index *p){
#ifndef SQLITE_OMIT_ANALYZE
sqlite3DeleteIndexSamples(db, p);
#endif
+ if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo);
+ sqlite3ExprDelete(db, p->pPartIdxWhere);
sqlite3DbFree(db, p->zColAff);
+ if( p->isResized ) sqlite3DbFree(db, p->azColl);
sqlite3DbFree(db, p);
}
@@ -82825,8 +84892,7 @@ SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
- sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
- sqlite3VdbeChangeP4(v, -1, (char *)5, P4_INT32); /* 5 column table */
+ sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
}
@@ -82932,6 +84998,27 @@ SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){
}
/*
+** Return the PRIMARY KEY index of a table
+*/
+SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table *pTab){
+ Index *p;
+ for(p=pTab->pIndex; p && p->autoIndex!=2; p=p->pNext){}
+ return p;
+}
+
+/*
+** Return the column of index pIdx that corresponds to table
+** column iCol. Return -1 if not found.
+*/
+SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
+ int i;
+ for(i=0; i<pIdx->nColumn; i++){
+ if( iCol==pIdx->aiColumn[i] ) return i;
+ }
+ return -1;
+}
+
+/*
** Begin constructing a new table representation in memory. This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement. In particular, this routine is called
@@ -83063,7 +85150,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
- pTable->nRowEst = 1000000;
+ pTable->nRowEst = 1048576;
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
@@ -83130,7 +85217,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
}else
#endif
{
- sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
+ pParse->addrCrTab = sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
}
sqlite3OpenMasterTable(pParse, iDb);
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
@@ -83210,6 +85297,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token *pName){
** be called next to set pCol->affinity correctly.
*/
pCol->affinity = SQLITE_AFF_NONE;
+ pCol->szEst = 1;
p->nCol++;
}
@@ -83251,15 +85339,18 @@ SQLITE_PRIVATE void sqlite3AddNotNull(Parse *pParse, int onError){
** If none of the substrings in the above table are found,
** SQLITE_AFF_NUMERIC is returned.
*/
-SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
+SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn, u8 *pszEst){
u32 h = 0;
char aff = SQLITE_AFF_NUMERIC;
+ const char *zChar = 0;
- if( zIn ) while( zIn[0] ){
+ if( zIn==0 ) return aff;
+ while( zIn[0] ){
h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff];
zIn++;
if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */
- aff = SQLITE_AFF_TEXT;
+ aff = SQLITE_AFF_TEXT;
+ zChar = zIn;
}else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */
aff = SQLITE_AFF_TEXT;
}else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */
@@ -83267,6 +85358,7 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
}else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */
&& (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){
aff = SQLITE_AFF_NONE;
+ if( zIn[0]=='(' ) zChar = zIn;
#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */
&& aff==SQLITE_AFF_NUMERIC ){
@@ -83284,6 +85376,28 @@ SQLITE_PRIVATE char sqlite3AffinityType(const char *zIn){
}
}
+ /* If pszEst is not NULL, store an estimate of the field size. The
+ ** estimate is scaled so that the size of an integer is 1. */
+ if( pszEst ){
+ *pszEst = 1; /* default size is approx 4 bytes */
+ if( aff<=SQLITE_AFF_NONE ){
+ if( zChar ){
+ while( zChar[0] ){
+ if( sqlite3Isdigit(zChar[0]) ){
+ int v = 0;
+ sqlite3GetInt32(zChar, &v);
+ v = v/4 + 1;
+ if( v>255 ) v = 255;
+ *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */
+ break;
+ }
+ zChar++;
+ }
+ }else{
+ *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/
+ }
+ }
+ }
return aff;
}
@@ -83305,7 +85419,7 @@ SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){
pCol = &p->aCol[p->nCol-1];
assert( pCol->zType==0 );
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
- pCol->affinity = sqlite3AffinityType(pCol->zType);
+ pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
}
/*
@@ -83371,6 +85485,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
Table *pTab = pParse->pNewTable;
char *zType = 0;
int iCol = -1, i;
+ int nTerm;
if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
if( pTab->tabFlags & TF_HasPrimaryKey ){
sqlite3ErrorMsg(pParse,
@@ -83381,38 +85496,43 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
if( pList==0 ){
iCol = pTab->nCol - 1;
pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
+ zType = pTab->aCol[iCol].zType;
+ nTerm = 1;
}else{
- for(i=0; i<pList->nExpr; i++){
+ nTerm = pList->nExpr;
+ for(i=0; i<nTerm; i++){
for(iCol=0; iCol<pTab->nCol; iCol++){
if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){
+ pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
+ zType = pTab->aCol[iCol].zType;
break;
}
}
- if( iCol<pTab->nCol ){
- pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
- }
}
- if( pList->nExpr>1 ) iCol = -1;
- }
- if( iCol>=0 && iCol<pTab->nCol ){
- zType = pTab->aCol[iCol].zType;
}
- if( zType && sqlite3StrICmp(zType, "INTEGER")==0
- && sortOrder==SQLITE_SO_ASC ){
+ if( nTerm==1
+ && zType && sqlite3StrICmp(zType, "INTEGER")==0
+ && sortOrder==SQLITE_SO_ASC
+ ){
pTab->iPKey = iCol;
pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
+ if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
"INTEGER PRIMARY KEY");
#endif
}else{
+ Vdbe *v = pParse->pVdbe;
Index *p;
- p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0);
+ if( v ) pParse->addrSkipPK = sqlite3VdbeAddOp0(v, OP_Noop);
+ p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
+ 0, sortOrder, 0);
if( p ){
p->autoIndex = 2;
+ if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
}
pList = 0;
}
@@ -83461,6 +85581,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
if( sqlite3LocateCollSeq(pParse, zColl) ){
Index *pIdx;
+ sqlite3DbFree(db, p->aCol[i].zColl);
p->aCol[i].zColl = zColl;
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
@@ -83468,7 +85589,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
** collation type was added. Correct this if it is the case.
*/
for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
- assert( pIdx->nColumn==1 );
+ assert( pIdx->nKeyCol==1 );
if( pIdx->aiColumn[0]==i ){
pIdx->azColl[0] = p->aCol[i].zColl;
}
@@ -83651,7 +85772,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
zType = azType[pCol->affinity - SQLITE_AFF_TEXT];
len = sqlite3Strlen30(zType);
assert( pCol->affinity==SQLITE_AFF_NONE
- || pCol->affinity==sqlite3AffinityType(zType) );
+ || pCol->affinity==sqlite3AffinityType(zType, 0) );
memcpy(&zStmt[k], zType, len);
k += len;
assert( k<=n );
@@ -83661,6 +85782,191 @@ static char *createTableStmt(sqlite3 *db, Table *p){
}
/*
+** Resize an Index object to hold N columns total. Return SQLITE_OK
+** on success and SQLITE_NOMEM on an OOM error.
+*/
+static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
+ char *zExtra;
+ int nByte;
+ if( pIdx->nColumn>=N ) return SQLITE_OK;
+ assert( pIdx->isResized==0 );
+ nByte = (sizeof(char*) + sizeof(i16) + 1)*N;
+ zExtra = sqlite3DbMallocZero(db, nByte);
+ if( zExtra==0 ) return SQLITE_NOMEM;
+ memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
+ pIdx->azColl = (char**)zExtra;
+ zExtra += sizeof(char*)*N;
+ memcpy(zExtra, pIdx->aiColumn, sizeof(i16)*pIdx->nColumn);
+ pIdx->aiColumn = (i16*)zExtra;
+ zExtra += sizeof(i16)*N;
+ memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
+ pIdx->aSortOrder = (u8*)zExtra;
+ pIdx->nColumn = N;
+ pIdx->isResized = 1;
+ return SQLITE_OK;
+}
+
+/*
+** Estimate the total row width for a table.
+*/
+static void estimateTableWidth(Table *pTab){
+ unsigned wTable = 0;
+ const Column *pTabCol;
+ int i;
+ for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){
+ wTable += pTabCol->szEst;
+ }
+ if( pTab->iPKey<0 ) wTable++;
+ pTab->szTabRow = sqlite3LogEst(wTable*4);
+}
+
+/*
+** Estimate the average size of a row for an index.
+*/
+static void estimateIndexWidth(Index *pIdx){
+ unsigned wIndex = 0;
+ int i;
+ const Column *aCol = pIdx->pTable->aCol;
+ for(i=0; i<pIdx->nColumn; i++){
+ i16 x = pIdx->aiColumn[i];
+ assert( x<pIdx->pTable->nCol );
+ wIndex += x<0 ? 1 : aCol[pIdx->aiColumn[i]].szEst;
+ }
+ pIdx->szIdxRow = sqlite3LogEst(wIndex*4);
+}
+
+/* Return true if value x is found any of the first nCol entries of aiCol[]
+*/
+static int hasColumn(const i16 *aiCol, int nCol, int x){
+ while( nCol-- > 0 ) if( x==*(aiCol++) ) return 1;
+ return 0;
+}
+
+/*
+** This routine runs at the end of parsing a CREATE TABLE statement that
+** has a WITHOUT ROWID clause. The job of this routine is to convert both
+** internal schema data structures and the generated VDBE code so that they
+** are appropriate for a WITHOUT ROWID table instead of a rowid table.
+** Changes include:
+**
+** (1) Convert the OP_CreateTable into an OP_CreateIndex. There is
+** no rowid btree for a WITHOUT ROWID. Instead, the canonical
+** data storage is a covering index btree.
+** (2) Bypass the creation of the sqlite_master table entry
+** for the PRIMARY KEY as the the primary key index is now
+** identified by the sqlite_master table entry of the table itself.
+** (3) Set the Index.tnum of the PRIMARY KEY Index object in the
+** schema to the rootpage from the main table.
+** (4) Set all columns of the PRIMARY KEY schema object to be NOT NULL.
+** (5) Add all table columns to the PRIMARY KEY Index object
+** so that the PRIMARY KEY is a covering index. The surplus
+** columns are part of KeyInfo.nXField and are not used for
+** sorting or lookup or uniqueness checks.
+** (6) Replace the rowid tail on all automatically generated UNIQUE
+** indices with the PRIMARY KEY columns.
+*/
+static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
+ Index *pIdx;
+ Index *pPk;
+ int nPk;
+ int i, j;
+ sqlite3 *db = pParse->db;
+ Vdbe *v = pParse->pVdbe;
+
+ /* Convert the OP_CreateTable opcode that would normally create the
+ ** root-page for the table into a OP_CreateIndex opcode. The index
+ ** created will become the PRIMARY KEY index.
+ */
+ if( pParse->addrCrTab ){
+ assert( v );
+ sqlite3VdbeGetOp(v, pParse->addrCrTab)->opcode = OP_CreateIndex;
+ }
+
+ /* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
+ ** table entry.
+ */
+ if( pParse->addrSkipPK ){
+ assert( v );
+ sqlite3VdbeGetOp(v, pParse->addrSkipPK)->opcode = OP_Goto;
+ }
+
+ /* Locate the PRIMARY KEY index. Or, if this table was originally
+ ** an INTEGER PRIMARY KEY table, create a new PRIMARY KEY index.
+ */
+ if( pTab->iPKey>=0 ){
+ ExprList *pList;
+ pList = sqlite3ExprListAppend(pParse, 0, 0);
+ if( pList==0 ) return;
+ pList->a[0].zName = sqlite3DbStrDup(pParse->db,
+ pTab->aCol[pTab->iPKey].zName);
+ pList->a[0].sortOrder = pParse->iPkSortOrder;
+ assert( pParse->pNewTable==pTab );
+ pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
+ if( pPk==0 ) return;
+ pPk->autoIndex = 2;
+ pTab->iPKey = -1;
+ }else{
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ }
+ pPk->isCovering = 1;
+ assert( pPk!=0 );
+ nPk = pPk->nKeyCol;
+
+ /* Make sure every column of the PRIMARY KEY is NOT NULL */
+ for(i=0; i<nPk; i++){
+ pTab->aCol[pPk->aiColumn[i]].notNull = 1;
+ }
+ pPk->uniqNotNull = 1;
+
+ /* The root page of the PRIMARY KEY is the table root page */
+ pPk->tnum = pTab->tnum;
+
+ /* Update the in-memory representation of all UNIQUE indices by converting
+ ** the final rowid column into one or more columns of the PRIMARY KEY.
+ */
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int n;
+ if( pIdx->autoIndex==2 ) continue;
+ for(i=n=0; i<nPk; i++){
+ if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
+ }
+ if( n==0 ){
+ /* This index is a superset of the primary key */
+ pIdx->nColumn = pIdx->nKeyCol;
+ continue;
+ }
+ if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
+ for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
+ if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ){
+ pIdx->aiColumn[j] = pPk->aiColumn[i];
+ pIdx->azColl[j] = pPk->azColl[i];
+ j++;
+ }
+ }
+ assert( pIdx->nColumn>=pIdx->nKeyCol+n );
+ assert( pIdx->nColumn>=j );
+ }
+
+ /* Add all table columns to the PRIMARY KEY index
+ */
+ if( nPk<pTab->nCol ){
+ if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
+ for(i=0, j=nPk; i<pTab->nCol; i++){
+ if( !hasColumn(pPk->aiColumn, j, i) ){
+ assert( j<pPk->nColumn );
+ pPk->aiColumn[j] = i;
+ pPk->azColl[j] = "BINARY";
+ j++;
+ }
+ }
+ assert( pPk->nColumn==j );
+ assert( pTab->nCol==j );
+ }else{
+ pPk->nColumn = pTab->nCol;
+ }
+}
+
+/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
**
@@ -83683,12 +85989,14 @@ static char *createTableStmt(sqlite3 *db, Table *p){
SQLITE_PRIVATE void sqlite3EndTable(
Parse *pParse, /* Parse context */
Token *pCons, /* The ',' token after the last column defn. */
- Token *pEnd, /* The final ')' token in the CREATE TABLE */
+ Token *pEnd, /* The ')' before options in the CREATE TABLE */
+ u8 tabOpts, /* Extra table options. Usually 0. */
Select *pSelect /* Select from a "CREATE ... AS SELECT" */
){
- Table *p;
- sqlite3 *db = pParse->db;
- int iDb;
+ Table *p; /* The new table */
+ sqlite3 *db = pParse->db; /* The database connection */
+ int iDb; /* Database in which the table lives */
+ Index *pIdx; /* An implied index of the table */
if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
return;
@@ -83698,43 +86006,45 @@ SQLITE_PRIVATE void sqlite3EndTable(
assert( !db->init.busy || !pSelect );
+ /* If the db->init.busy is 1 it means we are reading the SQL off the
+ ** "sqlite_master" or "sqlite_temp_master" table on the disk.
+ ** So do not write to the disk again. Extract the root page number
+ ** for the table from the db->init.newTnum field. (The page number
+ ** should have been put there by the sqliteOpenCb routine.)
+ */
+ if( db->init.busy ){
+ p->tnum = db->init.newTnum;
+ }
+
+ /* Special processing for WITHOUT ROWID Tables */
+ if( tabOpts & TF_WithoutRowid ){
+ if( (p->tabFlags & TF_Autoincrement) ){
+ sqlite3ErrorMsg(pParse,
+ "AUTOINCREMENT not allowed on WITHOUT ROWID tables");
+ return;
+ }
+ if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
+ sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
+ }else{
+ p->tabFlags |= TF_WithoutRowid;
+ convertToWithoutRowidTable(pParse, p);
+ }
+ }
+
iDb = sqlite3SchemaToIndex(db, p->pSchema);
#ifndef SQLITE_OMIT_CHECK
/* Resolve names in all CHECK constraint expressions.
*/
if( p->pCheck ){
- SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
- NameContext sNC; /* Name context for pParse->pNewTable */
- ExprList *pList; /* List of all CHECK constraints */
- int i; /* Loop counter */
-
- memset(&sNC, 0, sizeof(sNC));
- memset(&sSrc, 0, sizeof(sSrc));
- sSrc.nSrc = 1;
- sSrc.a[0].zName = p->zName;
- sSrc.a[0].pTab = p;
- sSrc.a[0].iCursor = -1;
- sNC.pParse = pParse;
- sNC.pSrcList = &sSrc;
- sNC.ncFlags = NC_IsCheck;
- pList = p->pCheck;
- for(i=0; i<pList->nExpr; i++){
- if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
- return;
- }
- }
+ sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
- /* If the db->init.busy is 1 it means we are reading the SQL off the
- ** "sqlite_master" or "sqlite_temp_master" table on the disk.
- ** So do not write to the disk again. Extract the root page number
- ** for the table from the db->init.newTnum field. (The page number
- ** should have been put there by the sqliteOpenCb routine.)
- */
- if( db->init.busy ){
- p->tnum = db->init.newTnum;
+ /* Estimate the average row size for the table and for all implied indices */
+ estimateTableWidth(p);
+ for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
+ estimateIndexWidth(pIdx);
}
/* If not initializing, then create a record for the new table
@@ -83810,7 +86120,9 @@ SQLITE_PRIVATE void sqlite3EndTable(
if( pSelect ){
zStmt = createTableStmt(db, p);
}else{
- n = (int)(pEnd->z - pParse->sNameToken.z) + 1;
+ Token *pEnd2 = tabOpts ? &pParse->sLastToken : pEnd;
+ n = (int)(pEnd2->z - pParse->sNameToken.z);
+ if( pEnd2->z[0]!=';' ) n += pEnd2->n;
zStmt = sqlite3MPrintf(db,
"CREATE %s %.*s", zType2, n, pParse->sNameToken.z
);
@@ -83853,7 +86165,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
/* Reparse everything to update our internal data structures */
sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlite3MPrintf(db, "tbl_name='%q'", p->zName));
+ sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
}
@@ -83923,9 +86235,8 @@ SQLITE_PRIVATE void sqlite3CreateView(
}
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
- if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
- && sqlite3FixSelect(&sFix, pSelect)
- ){
+ sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
+ if( sqlite3FixSelect(&sFix, pSelect) ){
sqlite3SelectDelete(db, pSelect);
return;
}
@@ -83959,7 +86270,7 @@ SQLITE_PRIVATE void sqlite3CreateView(
sEnd.n = 1;
/* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
- sqlite3EndTable(pParse, 0, &sEnd, 0);
+ sqlite3EndTable(pParse, 0, &sEnd, 0, 0);
return;
}
#endif /* SQLITE_OMIT_VIEW */
@@ -84225,7 +86536,7 @@ static void sqlite3ClearStatTables(
){
int i;
const char *zDbName = pParse->db->aDb[iDb].zName;
- for(i=1; i<=3; i++){
+ for(i=1; i<=4; i++){
char zTab[24];
sqlite3_snprintf(sizeof(zTab),zTab,"sqlite_stat%d",i);
if( sqlite3FindTable(pParse->db, zTab, zDbName) ){
@@ -84414,8 +86725,8 @@ exit_drop_table:
** currently under construction. pFromCol determines which columns
** in the current table point to the foreign key. If pFromCol==0 then
** connect the key to the last column inserted. pTo is the name of
-** the table referred to. pToCol is a list of tables in the other
-** pTo table that the foreign key points to. flags contains all
+** the table referred to (a.k.a the "parent" table). pToCol is a list
+** of tables in the parent pTo table. flags contains all
** information about the conflict resolution algorithms specified
** in the ON DELETE, ON UPDATE and ON INSERT clauses.
**
@@ -84575,6 +86886,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
int addr1; /* Address of top of loop */
int addr2; /* Address to jump to for next iteration */
int tnum; /* Root page of index */
+ int iPartIdxLabel; /* Jump to this label to skip a row */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
int regRecord; /* Register holding assemblied index record */
@@ -84597,16 +86909,13 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
tnum = memRootPage;
}else{
tnum = pIndex->tnum;
- sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
}
- pKey = sqlite3IndexKeyinfo(pParse, pIndex);
- sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
- (char *)pKey, P4_KEYINFO_HANDOFF);
- sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
+ pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
/* Open the sorter cursor if we are to use one. */
iSorter = pParse->nTab++;
- sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
+ sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)
+ sqlite3KeyInfoRef(pKey), P4_KEYINFO);
/* Open the table. Loop through all rows of the table, inserting index
** records into the sorter. */
@@ -84614,19 +86923,25 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
regRecord = sqlite3GetTempReg(pParse);
- sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
+ sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 0, &iPartIdxLabel);
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
+ sqlite3VdbeResolveLabel(v, iPartIdxLabel);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
sqlite3VdbeJumpHere(v, addr1);
+ if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
+ sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
+ (char *)pKey, P4_KEYINFO);
+ sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
+
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
- if( pIndex->onError!=OE_None ){
+ assert( pKey!=0 || db->mallocFailed || pParse->nErr );
+ if( pIndex->onError!=OE_None && pKey!=0 ){
int j2 = sqlite3VdbeCurrentAddr(v) + 3;
sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
addr2 = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
- OE_Abort, "indexed columns are not unique", P4_STATIC
- );
+ sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
+ pKey->nField - pIndex->nKeyCol);
+ sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
}else{
addr2 = sqlite3VdbeCurrentAddr(v);
}
@@ -84643,6 +86958,41 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
}
/*
+** Allocate heap space to hold an Index object with nCol columns.
+**
+** Increase the allocation size to provide an extra nExtra bytes
+** of 8-byte aligned space after the Index object and return a
+** pointer to this extra space in *ppExtra.
+*/
+SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(
+ sqlite3 *db, /* Database connection */
+ i16 nCol, /* Total number of columns in the index */
+ int nExtra, /* Number of bytes of extra space to alloc */
+ char **ppExtra /* Pointer to the "extra" space */
+){
+ Index *p; /* Allocated index object */
+ int nByte; /* Bytes of space for Index object + arrays */
+
+ nByte = ROUND8(sizeof(Index)) + /* Index structure */
+ ROUND8(sizeof(char*)*nCol) + /* Index.azColl */
+ ROUND8(sizeof(tRowcnt)*(nCol+1) + /* Index.aiRowEst */
+ sizeof(i16)*nCol + /* Index.aiColumn */
+ sizeof(u8)*nCol); /* Index.aSortOrder */
+ p = sqlite3DbMallocZero(db, nByte + nExtra);
+ if( p ){
+ char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
+ p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
+ p->aiRowEst = (tRowcnt*)pExtra; pExtra += sizeof(tRowcnt)*(nCol+1);
+ p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
+ p->aSortOrder = (u8*)pExtra;
+ p->nColumn = nCol;
+ p->nKeyCol = nCol - 1;
+ *ppExtra = ((char*)p) + nByte;
+ }
+ return p;
+}
+
+/*
** Create a new index for an SQL table. pName1.pName2 is the name of the index
** and pTblList is the name of the table that is to be indexed. Both will
** be NULL for a primary key or an index that is created to satisfy a
@@ -84666,7 +87016,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
ExprList *pList, /* A list of columns to be indexed */
int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
Token *pStart, /* The CREATE token that begins this statement */
- Token *pEnd, /* The ")" that closes the CREATE INDEX statement */
+ Expr *pPIWhere, /* WHERE clause for partial indices */
int sortOrder, /* Sort order of primary key when pList==NULL */
int ifNotExist /* Omit error if index already exists */
){
@@ -84676,7 +87026,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
char *zName = 0; /* Name of the index */
int nName; /* Number of characters in zName */
int i, j;
- Token nullId; /* Fake token for an empty ID list */
DbFixer sFix; /* For assigning database names to pTable */
int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */
sqlite3 *db = pParse->db;
@@ -84684,11 +87033,12 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
int iDb; /* Index of the database that is being written */
Token *pName = 0; /* Unqualified name of the index to create */
struct ExprList_item *pListItem; /* For looping over pList */
- int nCol;
- int nExtra = 0;
- char *zExtra;
+ const Column *pTabCol; /* A column in the table */
+ int nExtra = 0; /* Space allocated for zExtra[] */
+ int nExtraCol; /* Number of extra columns needed */
+ char *zExtra = 0; /* Extra space after the Index object */
+ Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
- assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */
assert( pParse->nErr==0 ); /* Never called with prior errors */
if( db->mallocFailed || IN_DECLARE_VTAB ){
goto exit_create_index;
@@ -84724,9 +87074,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
}
#endif
- if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) &&
- sqlite3FixSrcList(&sFix, pTblName)
- ){
+ sqlite3FixInit(&sFix, pParse, iDb, "index", pName);
+ if( sqlite3FixSrcList(&sFix, pTblName) ){
/* Because the parser constructs pTblName from a single identifier,
** sqlite3FixSrcList can never fail. */
assert(0);
@@ -84734,7 +87083,13 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
assert( db->mallocFailed==0 || pTab==0 );
if( pTab==0 ) goto exit_create_index;
- assert( db->aDb[iDb].pSchema==pTab->pSchema );
+ if( iDb==1 && db->aDb[iDb].pSchema!=pTab->pSchema ){
+ sqlite3ErrorMsg(pParse,
+ "cannot create a TEMP index on non-TEMP table \"%s\"",
+ pTab->zName);
+ goto exit_create_index;
+ }
+ if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab);
}else{
assert( pName==0 );
assert( pStart==0 );
@@ -84830,11 +87185,10 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** So create a fake list to simulate this.
*/
if( pList==0 ){
- nullId.z = pTab->aCol[pTab->nCol-1].zName;
- nullId.n = sqlite3Strlen30((char*)nullId.z);
pList = sqlite3ExprListAppend(pParse, 0, 0);
if( pList==0 ) goto exit_create_index;
- sqlite3ExprListSetName(pParse, pList, &nullId, 0);
+ pList->a[0].zName = sqlite3DbStrDup(pParse->db,
+ pTab->aCol[pTab->nCol-1].zName);
pList->a[0].sortOrder = (u8)sortOrder;
}
@@ -84853,35 +87207,28 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** Allocate the index structure.
*/
nName = sqlite3Strlen30(zName);
- nCol = pList->nExpr;
- pIndex = sqlite3DbMallocZero(db,
- ROUND8(sizeof(Index)) + /* Index structure */
- ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */
- sizeof(char *)*nCol + /* Index.azColl */
- sizeof(int)*nCol + /* Index.aiColumn */
- sizeof(u8)*nCol + /* Index.aSortOrder */
- nName + 1 + /* Index.zName */
- nExtra /* Collation sequence names */
- );
+ nExtraCol = pPk ? pPk->nKeyCol : 1;
+ pIndex = sqlite3AllocateIndexObject(db, pList->nExpr + nExtraCol,
+ nName + nExtra + 1, &zExtra);
if( db->mallocFailed ){
goto exit_create_index;
}
- zExtra = (char*)pIndex;
- pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))];
- pIndex->azColl = (char**)
- ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1));
assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
- pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
- pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]);
- pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
- zExtra = (char *)(&pIndex->zName[nName+1]);
+ pIndex->zName = zExtra;
+ zExtra += nName + 1;
memcpy(pIndex->zName, zName, nName+1);
pIndex->pTable = pTab;
- pIndex->nColumn = pList->nExpr;
pIndex->onError = (u8)onError;
+ pIndex->uniqNotNull = onError!=OE_None;
pIndex->autoIndex = (u8)(pName==0);
pIndex->pSchema = db->aDb[iDb].pSchema;
+ pIndex->nKeyCol = pList->nExpr;
+ if( pPIWhere ){
+ sqlite3ResolveSelfReference(pParse, pTab, NC_PartIdx, pPIWhere, 0);
+ pIndex->pPartIdxWhere = pPIWhere;
+ pPIWhere = 0;
+ }
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
/* Check to see if we should honor DESC requests on index columns
@@ -84904,7 +87251,6 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
*/
for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
const char *zColName = pListItem->zName;
- Column *pTabCol;
int requestedSortOrder;
char *zColl; /* Collation sequence name */
@@ -84917,7 +87263,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
pParse->checkSchema = 1;
goto exit_create_index;
}
- pIndex->aiColumn[i] = j;
+ assert( pTab->nCol<=0x7fff && j<=0x7fff );
+ pIndex->aiColumn[i] = (i16)j;
if( pListItem->pExpr ){
int nColl;
assert( pListItem->pExpr->op==TK_COLLATE );
@@ -84938,8 +87285,27 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
pIndex->azColl[i] = zColl;
requestedSortOrder = pListItem->sortOrder & sortOrderMask;
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
+ if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0;
+ }
+ if( pPk ){
+ for(j=0; j<pPk->nKeyCol; j++){
+ int x = pPk->aiColumn[j];
+ if( hasColumn(pIndex->aiColumn, pIndex->nKeyCol, x) ){
+ pIndex->nColumn--;
+ }else{
+ pIndex->aiColumn[i] = x;
+ pIndex->azColl[i] = pPk->azColl[j];
+ pIndex->aSortOrder[i] = pPk->aSortOrder[j];
+ i++;
+ }
+ }
+ assert( i==pIndex->nColumn );
+ }else{
+ pIndex->aiColumn[i] = -1;
+ pIndex->azColl[i] = "BINARY";
}
sqlite3DefaultRowEst(pIndex);
+ if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex);
if( pTab==pParse->pNewTable ){
/* This routine has been called to create an automatic index as a
@@ -84970,8 +87336,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
assert( pIdx->autoIndex );
assert( pIndex->onError!=OE_None );
- if( pIdx->nColumn!=pIndex->nColumn ) continue;
- for(k=0; k<pIdx->nColumn; k++){
+ if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
+ for(k=0; k<pIdx->nKeyCol; k++){
const char *z1;
const char *z2;
if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
@@ -84979,7 +87345,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
z2 = pIndex->azColl[k];
if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break;
}
- if( k==pIdx->nColumn ){
+ if( k==pIdx->nKeyCol ){
if( pIdx->onError!=pIndex->onError ){
/* This constraint creates the same index as a previous
** constraint specified somewhere in the CREATE TABLE statement.
@@ -85021,22 +87387,20 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
}
}
- /* If the db->init.busy is 0 then create the index on disk. This
- ** involves writing the index into the master table and filling in the
- ** index with the current table contents.
- **
- ** The db->init.busy is 0 when the user first enters a CREATE INDEX
- ** command. db->init.busy is 1 when a database is opened and
- ** CREATE INDEX statements are read out of the master table. In
- ** the latter case the index already exists on disk, which is why
- ** we don't want to recreate it.
+ /* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
+ ** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
+ ** emit code to allocate the index rootpage on disk and make an entry for
+ ** the index in the sqlite_master table and populate the index with
+ ** content. But, do not do this if we are simply reading the sqlite_master
+ ** table to parse the schema, or if this index is the PRIMARY KEY index
+ ** of a WITHOUT ROWID table.
**
- ** If pTblName==0 it means this index is generated as a primary key
- ** or UNIQUE constraint of a CREATE TABLE statement. Since the table
+ ** If pTblName==0 it means this index is generated as an implied PRIMARY KEY
+ ** or UNIQUE index in a CREATE TABLE statement. Since the table
** has just been created, it contains no data and the index initialization
** step can be skipped.
*/
- else{ /* if( db->init.busy==0 ) */
+ else if( pParse->nErr==0 && (HasRowid(pTab) || pTblName!=0) ){
Vdbe *v;
char *zStmt;
int iMem = ++pParse->nMem;
@@ -85054,12 +87418,11 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** the zStmt variable
*/
if( pStart ){
- assert( pEnd!=0 );
+ int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
+ if( pName->z[n-1]==';' ) n--;
/* A named index with an explicit CREATE INDEX statement */
zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",
- onError==OE_None ? "" : " UNIQUE",
- (int)(pEnd->z - pName->z) + 1,
- pName->z);
+ onError==OE_None ? "" : " UNIQUE", n, pName->z);
}else{
/* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
/* zStmt = sqlite3MPrintf(""); */
@@ -85115,10 +87478,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
/* Clean up before exiting */
exit_create_index:
- if( pIndex ){
- sqlite3DbFree(db, pIndex->zColAff);
- sqlite3DbFree(db, pIndex);
- }
+ if( pIndex ) freeIndex(db, pIndex);
+ sqlite3ExprDelete(db, pPIWhere);
sqlite3ExprListDelete(db, pList);
sqlite3SrcListDelete(db, pTblName);
sqlite3DbFree(db, zName);
@@ -85151,12 +87512,12 @@ SQLITE_PRIVATE void sqlite3DefaultRowEst(Index *pIdx){
a[0] = pIdx->pTable->nRowEst;
if( a[0]<10 ) a[0] = 10;
n = 10;
- for(i=1; i<=pIdx->nColumn; i++){
+ for(i=1; i<=pIdx->nKeyCol; i++){
a[i] = n;
if( n>5 ) n--;
}
if( pIdx->onError!=OE_None ){
- a[pIdx->nColumn] = 1;
+ a[pIdx->nKeyCol] = 1;
}
}
@@ -85369,7 +87730,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
}
pSrc = pNew;
nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
- pSrc->nAlloc = (u16)nGot;
+ pSrc->nAlloc = (u8)nGot;
}
/* Move existing slots that come after the newly inserted slots
@@ -85377,7 +87738,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
for(i=pSrc->nSrc-1; i>=iStart; i--){
pSrc->a[i+nExtra] = pSrc->a[i];
}
- pSrc->nSrc += (i16)nExtra;
+ pSrc->nSrc += (i8)nExtra;
/* Zero the newly allocated slots */
memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
@@ -85844,7 +88205,8 @@ SQLITE_PRIVATE void sqlite3HaltConstraint(
int errCode, /* extended error code */
int onError, /* Constraint type */
char *p4, /* Error message */
- int p4type /* P4_STATIC or P4_TRANSIENT */
+ i8 p4type, /* P4_STATIC or P4_TRANSIENT */
+ u8 p5Errmsg /* P5_ErrMsg type */
){
Vdbe *v = sqlite3GetVdbe(pParse);
assert( (errCode&0xff)==SQLITE_CONSTRAINT );
@@ -85852,6 +88214,58 @@ SQLITE_PRIVATE void sqlite3HaltConstraint(
sqlite3MayAbort(pParse);
}
sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
+ if( p5Errmsg ) sqlite3VdbeChangeP5(v, p5Errmsg);
+}
+
+/*
+** Code an OP_Halt due to UNIQUE or PRIMARY KEY constraint violation.
+*/
+SQLITE_PRIVATE void sqlite3UniqueConstraint(
+ Parse *pParse, /* Parsing context */
+ int onError, /* Constraint type */
+ Index *pIdx /* The index that triggers the constraint */
+){
+ char *zErr;
+ int j;
+ StrAccum errMsg;
+ Table *pTab = pIdx->pTable;
+
+ sqlite3StrAccumInit(&errMsg, 0, 0, 200);
+ errMsg.db = pParse->db;
+ for(j=0; j<pIdx->nKeyCol; j++){
+ char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
+ if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
+ sqlite3StrAccumAppend(&errMsg, pTab->zName, -1);
+ sqlite3StrAccumAppend(&errMsg, ".", 1);
+ sqlite3StrAccumAppend(&errMsg, zCol, -1);
+ }
+ zErr = sqlite3StrAccumFinish(&errMsg);
+ sqlite3HaltConstraint(pParse,
+ (pIdx->autoIndex==2)?SQLITE_CONSTRAINT_PRIMARYKEY:SQLITE_CONSTRAINT_UNIQUE,
+ onError, zErr, P4_DYNAMIC, P5_ConstraintUnique);
+}
+
+
+/*
+** Code an OP_Halt due to non-unique rowid.
+*/
+SQLITE_PRIVATE void sqlite3RowidConstraint(
+ Parse *pParse, /* Parsing context */
+ int onError, /* Conflict resolution algorithm */
+ Table *pTab /* The table with the non-unique rowid */
+){
+ char *zMsg;
+ int rc;
+ if( pTab->iPKey>=0 ){
+ zMsg = sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName,
+ pTab->aCol[pTab->iPKey].zName);
+ rc = SQLITE_CONSTRAINT_PRIMARYKEY;
+ }else{
+ zMsg = sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName);
+ rc = SQLITE_CONSTRAINT_ROWID;
+ }
+ sqlite3HaltConstraint(pParse, rc, onError, zMsg, P4_DYNAMIC,
+ P5_ConstraintUnique);
}
/*
@@ -85864,8 +88278,8 @@ static int collationMatch(const char *zColl, Index *pIndex){
assert( zColl!=0 );
for(i=0; i<pIndex->nColumn; i++){
const char *z = pIndex->azColl[i];
- assert( z!=0 );
- if( 0==sqlite3StrICmp(z, zColl) ){
+ assert( z!=0 || pIndex->aiColumn[i]<0 );
+ if( pIndex->aiColumn[i]>=0 && 0==sqlite3StrICmp(z, zColl) ){
return 1;
}
}
@@ -85984,40 +88398,49 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
#endif
/*
-** Return a dynamicly allocated KeyInfo structure that can be used
-** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
+** Return a KeyInfo structure that is appropriate for the given Index.
**
-** If successful, a pointer to the new structure is returned. In this case
-** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
-** pointer. If an error occurs (out of memory or missing collation
-** sequence), NULL is returned and the state of pParse updated to reflect
-** the error.
+** The KeyInfo structure for an index is cached in the Index object.
+** So there might be multiple references to the returned pointer. The
+** caller should not try to modify the KeyInfo object.
+**
+** The caller should invoke sqlite3KeyInfoUnref() on the returned object
+** when it has finished using it.
*/
-SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
- int i;
- int nCol = pIdx->nColumn;
- int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
- sqlite3 *db = pParse->db;
- KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes);
-
- if( pKey ){
- pKey->db = pParse->db;
- pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
- assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) );
- for(i=0; i<nCol; i++){
- char *zColl = pIdx->azColl[i];
- assert( zColl );
- pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl);
- pKey->aSortOrder[i] = pIdx->aSortOrder[i];
- }
- pKey->nField = (u16)nCol;
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
+ if( pParse->nErr ) return 0;
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){
+ sqlite3KeyInfoUnref(pIdx->pKeyInfo);
+ pIdx->pKeyInfo = 0;
}
-
- if( pParse->nErr ){
- sqlite3DbFree(db, pKey);
- pKey = 0;
+#endif
+ if( pIdx->pKeyInfo==0 ){
+ int i;
+ int nCol = pIdx->nColumn;
+ int nKey = pIdx->nKeyCol;
+ KeyInfo *pKey;
+ if( pIdx->uniqNotNull ){
+ pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
+ }else{
+ pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
+ }
+ if( pKey ){
+ assert( sqlite3KeyInfoIsWriteable(pKey) );
+ for(i=0; i<nCol; i++){
+ char *zColl = pIdx->azColl[i];
+ if( NEVER(zColl==0) ) zColl = "BINARY";
+ pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl);
+ pKey->aSortOrder[i] = pIdx->aSortOrder[i];
+ }
+ if( pParse->nErr ){
+ sqlite3KeyInfoUnref(pKey);
+ }else{
+ pIdx->pKeyInfo = pKey;
+ }
+ }
}
- return pKey;
+ return sqlite3KeyInfoRef(pIdx->pKeyInfo);
}
/************** End of build.c ***********************************************/
@@ -86293,9 +88716,9 @@ static int matchQuality(
}
/* Bonus points if the text encoding matches */
- if( enc==p->iPrefEnc ){
+ if( enc==(p->funcFlags & SQLITE_FUNC_ENCMASK) ){
match += 2; /* Exact encoding match */
- }else if( (enc & p->iPrefEnc & 2)!=0 ){
+ }else if( (enc & p->funcFlags & 2)!=0 ){
match += 1; /* Both are UTF16, but with different byte orders */
}
@@ -86429,7 +88852,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
pBest->zName = (char *)&pBest[1];
pBest->nArg = (u16)nArg;
- pBest->iPrefEnc = enc;
+ pBest->funcFlags = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
sqlite3FuncDefInsert(&db->aFunc, pBest);
@@ -86637,7 +89060,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
ExprList *pOrderBy, /* The ORDER BY clause. May be null */
Expr *pLimit, /* The LIMIT clause. May be null */
Expr *pOffset, /* The OFFSET clause. May be null */
- char *zStmtType /* Either DELETE or UPDATE. For error messages. */
+ char *zStmtType /* Either DELETE or UPDATE. For err msgs. */
){
Expr *pWhereRowid = NULL; /* WHERE rowid .. */
Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
@@ -86712,7 +89135,8 @@ limit_where_cleanup_2:
sqlite3ExprDelete(pParse->db, pOffset);
return 0;
}
-#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */
+ /* && !defined(SQLITE_OMIT_SUBQUERY) */
/*
** Generate code for a DELETE FROM statement.
@@ -86729,18 +89153,34 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
const char *zDb; /* Name of database holding pTab */
- int end, addr = 0; /* A couple addresses of generated code */
int i; /* Loop counter */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Index *pIdx; /* For looping over indices of the table */
- int iCur; /* VDBE Cursor number for pTab */
+ int iTabCur; /* Cursor number for the table */
+ int iDataCur; /* VDBE cursor for the canonical data source */
+ int iIdxCur; /* Cursor number of the first index */
+ int nIdx; /* Number of indices */
sqlite3 *db; /* Main database structure */
AuthContext sContext; /* Authorization context */
NameContext sNC; /* Name context to resolve expressions in */
int iDb; /* Database number */
int memCnt = -1; /* Memory cell used for change counting */
int rcauth; /* Value returned by authorization callback */
-
+ int okOnePass; /* True for one-pass algorithm without the FIFO */
+ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
+ u8 *aToOpen = 0; /* Open cursor iTabCur+j if aToOpen[j] is true */
+ Index *pPk; /* The PRIMARY KEY index on the table */
+ int iPk = 0; /* First of nPk registers holding PRIMARY KEY value */
+ i16 nPk = 1; /* Number of columns in the PRIMARY KEY */
+ int iKey; /* Memory cell holding key of row to be deleted */
+ i16 nKey; /* Number of memory cells in the row key */
+ int iEphCur = 0; /* Ephemeral table holding all primary key values */
+ int iRowSet = 0; /* Register for rowset of rows to delete */
+ int addrBypass = 0; /* Address of jump over the delete logic */
+ int addrLoop = 0; /* Top of the delete loop */
+ int addrDelete = 0; /* Jump directly to the delete logic */
+ int addrEphOpen = 0; /* Instruction to open the Ephermeral table */
+
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
Trigger *pTrigger; /* List of table triggers, if required */
@@ -86795,11 +89235,11 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
}
assert(!isView || pTrigger);
- /* Assign cursor number to the table and all its indices.
+ /* Assign cursor numbers to the table and all its indices.
*/
assert( pTabList->nSrc==1 );
- iCur = pTabList->a[0].iCursor = pParse->nTab++;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ iTabCur = pTabList->a[0].iCursor = pParse->nTab++;
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
pParse->nTab++;
}
@@ -86823,7 +89263,8 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
- sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+ sqlite3MaterializeView(pParse, pTab, pWhere, iTabCur);
+ iDataCur = iIdxCur = iTabCur;
}
#endif
@@ -86853,78 +89294,169 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
&& 0==sqlite3FkRequired(pParse, pTab, 0, 0)
){
assert( !isView );
- sqlite3VdbeAddOp4(v, OP_Clear, pTab->tnum, iDb, memCnt,
- pTab->zName, P4_STATIC);
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
+ if( HasRowid(pTab) ){
+ 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);
}
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
- /* The usual case: There is a WHERE clause so we have to scan through
- ** the table and pick which records to delete.
- */
{
- int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
- int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
- int regRowid; /* Actual register containing rowids */
-
- /* Collect rowids of every row to be deleted.
+ if( HasRowid(pTab) ){
+ /* For a rowid table, initialize the RowSet to an empty set */
+ pPk = 0;
+ nPk = 1;
+ iRowSet = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
+ }else{
+ /* For a WITHOUT ROWID table, create an ephermeral table used to
+ ** hold all primary keys for rows to be deleted. */
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ nPk = pPk->nKeyCol;
+ iPk = pParse->nMem+1;
+ pParse->nMem += nPk;
+ iEphCur = pParse->nTab++;
+ addrEphOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEphCur, nPk);
+ sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+ }
+
+ /* Construct a query to find the rowid or primary key for every row
+ ** to be deleted, based on the WHERE clause.
*/
- sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
- pWInfo = sqlite3WhereBegin(
- pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
- );
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
+ WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK,
+ iTabCur+1);
if( pWInfo==0 ) goto delete_from_cleanup;
- regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
+ okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+
+ /* Keep track of the number of rows to be deleted */
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
}
+
+ /* Extract the rowid or primary key for the current row */
+ if( pPk ){
+ for(i=0; i<nPk; i++){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur,
+ pPk->aiColumn[i], iPk+i);
+ }
+ iKey = iPk;
+ }else{
+ iKey = pParse->nMem + 1;
+ iKey = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iTabCur, iKey, 0);
+ if( iKey>pParse->nMem ) pParse->nMem = iKey;
+ }
+
+ if( okOnePass ){
+ /* For ONEPASS, no need to store the rowid/primary-key. There is only
+ ** one, so just keep it in its register(s) and fall through to the
+ ** delete code.
+ */
+ nKey = nPk; /* OP_Found will use an unpacked key */
+ aToOpen = sqlite3DbMallocRaw(db, nIdx+2);
+ if( aToOpen==0 ){
+ sqlite3WhereEnd(pWInfo);
+ goto delete_from_cleanup;
+ }
+ memset(aToOpen, 1, nIdx+1);
+ aToOpen[nIdx+1] = 0;
+ if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iTabCur] = 0;
+ if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iTabCur] = 0;
+ if( addrEphOpen ) sqlite3VdbeChangeToNoop(v, addrEphOpen);
+ addrDelete = sqlite3VdbeAddOp0(v, OP_Goto); /* Jump to DELETE logic */
+ }else if( pPk ){
+ /* Construct a composite key for the row to be deleted and remember it */
+ iKey = ++pParse->nMem;
+ nKey = 0; /* Zero tells OP_Found to use a composite key */
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
+ sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
+ }else{
+ /* Get the rowid of the row to be deleted and remember it in the RowSet */
+ nKey = 1; /* OP_Seek always uses a single rowid */
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
+ }
+
+ /* End of the WHERE loop */
sqlite3WhereEnd(pWInfo);
-
- /* Delete every item whose key was written to the list during the
- ** database scan. We have to delete items after the scan is complete
- ** because deleting an item can change the scan order. */
- end = sqlite3VdbeMakeLabel(v);
-
+ if( okOnePass ){
+ /* Bypass the delete logic below if the WHERE loop found zero rows */
+ addrBypass = sqlite3VdbeMakeLabel(v);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBypass);
+ sqlite3VdbeJumpHere(v, addrDelete);
+ }
+
/* Unless this is a view, open cursors for the table we are
** deleting from and all its indices. If this is a view, then the
** only effect this statement has is to fire the INSTEAD OF
- ** triggers. */
+ ** triggers.
+ */
if( !isView ){
- sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
+ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iTabCur, aToOpen,
+ &iDataCur, &iIdxCur);
+ assert( pPk || iDataCur==iTabCur );
+ assert( pPk || iIdxCur==iDataCur+1 );
}
-
- addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
-
+
+ /* Set up a loop over the rowids/primary-keys that were found in the
+ ** where-clause loop above.
+ */
+ if( okOnePass ){
+ /* Just one row. Hence the top-of-loop is a no-op */
+ assert( nKey==nPk ); /* OP_Found will use an unpacked key */
+ if( aToOpen[iDataCur-iTabCur] ){
+ assert( pPk!=0 );
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
+ }
+ }else if( pPk ){
+ addrLoop = sqlite3VdbeAddOp1(v, OP_Rewind, iEphCur);
+ sqlite3VdbeAddOp2(v, OP_RowKey, iEphCur, iKey);
+ assert( nKey==0 ); /* OP_Found will use a composite key */
+ }else{
+ addrLoop = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, 0, iKey);
+ assert( nKey==1 );
+ }
+
/* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
sqlite3VtabMakeWritable(pParse, pTab);
- sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
+ sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
sqlite3VdbeChangeP5(v, OE_Abort);
sqlite3MayAbort(pParse);
}else
#endif
{
int count = (pParse->nested==0); /* True to count changes */
- sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default);
+ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+ iKey, nKey, count, OE_Default, okOnePass);
}
-
- /* End of the delete loop */
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
- sqlite3VdbeResolveLabel(v, end);
-
+
+ /* End of the loop over all rowids/primary-keys. */
+ if( okOnePass ){
+ sqlite3VdbeResolveLabel(v, addrBypass);
+ }else if( pPk ){
+ sqlite3VdbeAddOp2(v, OP_Next, iEphCur, addrLoop+1);
+ sqlite3VdbeJumpHere(v, addrLoop);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrLoop);
+ sqlite3VdbeJumpHere(v, addrLoop);
+ }
+
/* Close the cursors open on the table and its indexes. */
if( !isView && !IsVirtual(pTab) ){
- for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum);
+ if( !pPk ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
+ for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+ sqlite3VdbeAddOp1(v, OP_Close, iIdxCur + i);
}
- sqlite3VdbeAddOp1(v, OP_Close, iCur);
}
- }
+ } /* End non-truncate path */
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
@@ -86948,6 +89480,7 @@ delete_from_cleanup:
sqlite3AuthContextPop(&sContext);
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprDelete(db, pWhere);
+ sqlite3DbFree(db, aToOpen);
return;
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
@@ -86962,50 +89495,59 @@ delete_from_cleanup:
/*
** This routine generates VDBE code that causes a single row of a
-** single table to be deleted.
+** single table to be deleted. Both the original table entry and
+** all indices are removed.
**
-** The VDBE must be in a particular state when this routine is called.
-** These are the requirements:
+** Preconditions:
**
-** 1. A read/write cursor pointing to pTab, the table containing the row
-** to be deleted, must be opened as cursor number $iCur.
+** 1. iDataCur is an open cursor on the btree that is the canonical data
+** store for the table. (This will be either the table itself,
+** in the case of a rowid table, or the PRIMARY KEY index in the case
+** of a WITHOUT ROWID table.)
**
** 2. Read/write cursors for all indices of pTab must be open as
-** cursor number base+i for the i-th index.
+** cursor number iIdxCur+i for the i-th index.
**
-** 3. The record number of the row to be deleted must be stored in
-** memory cell iRowid.
-**
-** This routine generates code to remove both the table record and all
-** index entries that point to that record.
+** 3. The primary key for the row to be deleted must be stored in a
+** sequence of nPk memory cells starting at iPk. If nPk==0 that means
+** that a search record formed from OP_MakeRecord is contained in the
+** single memory location iPk.
*/
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
Parse *pParse, /* Parsing context */
Table *pTab, /* Table containing the row to be deleted */
- int iCur, /* Cursor number for the table */
- int iRowid, /* Memory cell that contains the rowid to delete */
- int count, /* If non-zero, increment the row change counter */
Trigger *pTrigger, /* List of triggers to (potentially) fire */
- int onconf /* Default ON CONFLICT policy for triggers */
+ int iDataCur, /* Cursor from which column data is extracted */
+ int iIdxCur, /* First index cursor */
+ int iPk, /* First memory cell containing the PRIMARY KEY */
+ i16 nPk, /* Number of PRIMARY KEY memory cells */
+ u8 count, /* If non-zero, increment the row change counter */
+ u8 onconf, /* Default ON CONFLICT policy for triggers */
+ u8 bNoSeek /* iDataCur is already pointing to the row to delete */
){
Vdbe *v = pParse->pVdbe; /* Vdbe */
int iOld = 0; /* First register in OLD.* array */
int iLabel; /* Label resolved to end of generated code */
+ u8 opSeek; /* Seek opcode */
/* Vdbe is guaranteed to have been allocated by this stage. */
assert( v );
+ VdbeModuleComment((v, "BEGIN: GenRowDel(%d,%d,%d,%d)",
+ iDataCur, iIdxCur, iPk, (int)nPk));
/* Seek cursor iCur to the row to delete. If this row no longer exists
** (this can happen if a trigger program has already deleted it), do
** not attempt to delete it or fire any DELETE triggers. */
iLabel = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
+ opSeek = HasRowid(pTab) ? OP_NotExists : OP_NotFound;
+ if( !bNoSeek ) sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
/* If there are any triggers to fire, allocate a range of registers to
** use for the old.* references in the triggers. */
if( sqlite3FkRequired(pParse, pTab, 0, 0) || pTrigger ){
u32 mask; /* Mask of OLD.* columns in use */
int iCol; /* Iterator used while populating OLD.* */
+ int addrStart; /* Start of BEFORE trigger programs */
/* TODO: Could use temporary registers here. Also could attempt to
** avoid copying the contents of the rowid register. */
@@ -87018,36 +89560,40 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
/* Populate the OLD.* pseudo-table register array. These values will be
** used by any BEFORE and AFTER triggers that exist. */
- sqlite3VdbeAddOp2(v, OP_Copy, iRowid, iOld);
+ sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
for(iCol=0; iCol<pTab->nCol; iCol++){
if( mask==0xffffffff || mask&(1<<iCol) ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, iOld+iCol+1);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
}
}
/* Invoke BEFORE DELETE trigger programs. */
+ addrStart = sqlite3VdbeCurrentAddr(v);
sqlite3CodeRowTrigger(pParse, pTrigger,
TK_DELETE, 0, TRIGGER_BEFORE, pTab, iOld, onconf, iLabel
);
- /* Seek the cursor to the row to be deleted again. It may be that
- ** the BEFORE triggers coded above have already removed the row
- ** being deleted. Do not attempt to delete the row a second time, and
- ** do not fire AFTER triggers. */
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, iLabel, iRowid);
+ /* If any BEFORE triggers were coded, then seek the cursor to the
+ ** row to be deleted again. It may be that the BEFORE triggers moved
+ ** the cursor or of already deleted the row that the cursor was
+ ** pointing to.
+ */
+ if( addrStart<sqlite3VdbeCurrentAddr(v) ){
+ sqlite3VdbeAddOp4Int(v, opSeek, iDataCur, iLabel, iPk, nPk);
+ }
/* Do FK processing. This call checks that any FK constraints that
** refer to this table (i.e. constraints attached to other tables)
** are not violated by deleting this row. */
- sqlite3FkCheck(pParse, pTab, iOld, 0);
+ sqlite3FkCheck(pParse, pTab, iOld, 0, 0, 0);
}
/* Delete the index and table entries. Skip this step if pTab is really
** a view (in which case the only effect of the DELETE statement is to
** fire the INSTEAD OF triggers). */
if( pTab->pSelect==0 ){
- sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);
- sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0);
+ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
if( count ){
sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
}
@@ -87056,7 +89602,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
** to the row just deleted. */
- sqlite3FkActions(pParse, pTab, 0, iOld);
+ sqlite3FkActions(pParse, pTab, 0, iOld, 0, 0);
/* Invoke AFTER DELETE trigger programs. */
sqlite3CodeRowTrigger(pParse, pTrigger,
@@ -87067,78 +89613,113 @@ SQLITE_PRIVATE void sqlite3GenerateRowDelete(
** trigger programs were invoked. Or if a trigger program throws a
** RAISE(IGNORE) exception. */
sqlite3VdbeResolveLabel(v, iLabel);
+ VdbeModuleComment((v, "END: GenRowDel()"));
}
/*
** This routine generates VDBE code that causes the deletion of all
-** index entries associated with a single row of a single table.
+** index entries associated with a single row of a single table, pTab
**
-** The VDBE must be in a particular state when this routine is called.
-** These are the requirements:
+** Preconditions:
**
-** 1. A read/write cursor pointing to pTab, the table containing the row
-** to be deleted, must be opened as cursor number "iCur".
+** 1. A read/write cursor "iDataCur" must be open on the canonical storage
+** btree for the table pTab. (This will be either the table itself
+** for rowid tables or to the primary key index for WITHOUT ROWID
+** tables.)
**
** 2. Read/write cursors for all indices of pTab must be open as
-** cursor number iCur+i for the i-th index.
+** cursor number iIdxCur+i for the i-th index. (The pTab->pIndex
+** index is the 0-th index.)
**
-** 3. The "iCur" cursor must be pointing to the row that is to be
-** deleted.
+** 3. The "iDataCur" cursor must be already be positioned on the row
+** that is to be deleted.
*/
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(
Parse *pParse, /* Parsing and code generating context */
Table *pTab, /* Table containing the row to be deleted */
- int iCur, /* Cursor number for the table */
+ int iDataCur, /* Cursor of table holding data. */
+ int iIdxCur, /* First index cursor */
int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
){
- int i;
- Index *pIdx;
- int r1;
+ int i; /* Index loop counter */
+ int r1; /* Register holding an index key */
+ int iPartIdxLabel; /* Jump destination for skipping partial index entries */
+ Index *pIdx; /* Current index */
+ Vdbe *v; /* The prepared statement under construction */
+ Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
- for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);
- sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
+ v = pParse->pVdbe;
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
+ for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
+ assert( iIdxCur+i!=iDataCur || pPk==pIdx );
+ if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
+ if( pIdx==pPk ) continue;
+ VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, &iPartIdxLabel);
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
+ pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
+ sqlite3VdbeResolveLabel(v, iPartIdxLabel);
}
}
/*
-** Generate code that will assemble an index key and put it in register
+** Generate code that will assemble an index key and stores it in register
** regOut. The key with be for index pIdx which is an index on pTab.
** iCur is the index of a cursor open on the pTab table and pointing to
-** the entry that needs indexing.
+** the entry that needs indexing. If pTab is a WITHOUT ROWID table, then
+** iCur must be the cursor of the PRIMARY KEY index.
**
** Return a register number which is the first in a block of
** registers that holds the elements of the index key. The
** block of registers has already been deallocated by the time
** this routine returns.
+**
+** If *piPartIdxLabel is not NULL, fill it in with a label and jump
+** to that label if pIdx is a partial index that should be skipped.
+** A partial index should be skipped if its WHERE clause evaluates
+** to false or null. If pIdx is not a partial index, *piPartIdxLabel
+** will be set to zero which is an empty label that is ignored by
+** sqlite3VdbeResolveLabel().
*/
SQLITE_PRIVATE int sqlite3GenerateIndexKey(
- Parse *pParse, /* Parsing context */
- Index *pIdx, /* The index for which to generate a key */
- int iCur, /* Cursor number for the pIdx->pTable table */
- int regOut, /* Write the new index key to this register */
- int doMakeRec /* Run the OP_MakeRecord instruction if true */
+ Parse *pParse, /* Parsing context */
+ Index *pIdx, /* The index for which to generate a key */
+ int iDataCur, /* Cursor number from which to take column data */
+ int regOut, /* Put the new key into this register if not 0 */
+ int prefixOnly, /* Compute only a unique prefix of the key */
+ int *piPartIdxLabel /* OUT: Jump to this label to skip partial index */
){
Vdbe *v = pParse->pVdbe;
int j;
Table *pTab = pIdx->pTable;
int regBase;
int nCol;
-
- nCol = pIdx->nColumn;
- regBase = sqlite3GetTempRange(pParse, nCol+1);
- sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);
+ Index *pPk;
+
+ if( piPartIdxLabel ){
+ if( pIdx->pPartIdxWhere ){
+ *piPartIdxLabel = sqlite3VdbeMakeLabel(v);
+ pParse->iPartIdxTab = iDataCur;
+ sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
+ SQLITE_JUMPIFNULL);
+ }else{
+ *piPartIdxLabel = 0;
+ }
+ }
+ nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
+ regBase = sqlite3GetTempRange(pParse, nCol);
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(j=0; j<nCol; j++){
- int idx = pIdx->aiColumn[j];
- if( idx==pTab->iPKey ){
- sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);
+ i16 idx = pIdx->aiColumn[j];
+ if( pPk ) idx = sqlite3ColumnOfIndex(pPk, idx);
+ if( idx<0 || idx==pTab->iPKey ){
+ sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regBase+j);
}else{
- sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
- sqlite3ColumnDefault(v, pTab, idx, -1);
+ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, idx, regBase+j);
+ sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[j], -1);
}
}
- if( doMakeRec ){
+ if( regOut ){
const char *zAff;
if( pTab->pSelect
|| OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
@@ -87147,10 +89728,10 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
}else{
zAff = sqlite3IndexAffinityStr(v, pIdx);
}
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
}
- sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
+ sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
}
@@ -87294,8 +89875,8 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
i64 iVal = sqlite3_value_int64(argv[0]);
if( iVal<0 ){
if( (iVal<<1)==0 ){
- /* IMP: R-35460-15084 If X is the integer -9223372036854775807 then
- ** abs(X) throws an integer overflow error since there is no
+ /* IMP: R-31676-45509 If X is the integer -9223372036854775808
+ ** then abs(X) throws an integer overflow error since there is no
** equivalent positive 64-bit two complement value. */
sqlite3_result_error(context, "integer overflow", -1);
return;
@@ -87384,7 +89965,7 @@ static void instrFunc(
**
** If p1 is negative, then we begin abs(p1) from the end of x[].
**
-** If p2 is negative, return the p2 characters preceeding p1.
+** If p2 is negative, return the p2 characters preceding p1.
*/
static void substrFunc(
sqlite3_context *context,
@@ -87574,14 +90155,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
/*
-** The COALESCE() and IFNULL() functions are implemented as VDBE code so
-** that unused argument values do not have to be computed. However, we
-** still need some kind of function implementation for this routines in
-** the function table. That function implementation will never be called
-** so it doesn't matter what the implementation is. We might as well use
-** the "version()" function as a substitute.
+** Some functions like COALESCE() and IFNULL() and UNLIKELY() are implemented
+** as VDBE code so that unused argument values do not have to be computed.
+** However, we still need some kind of function implementation for this
+** routines in the function table. The noopFunc macro provides this.
+** noopFunc will never be called so it doesn't matter what the implementation
+** is. We might as well use the "version()" function as a substitute.
*/
-#define ifnullFunc versionFunc /* Substitute function - never called */
+#define noopFunc versionFunc /* Substitute function - never called */
/*
** Implementation of random(). Return a random integer.
@@ -87700,9 +90281,9 @@ struct compareInfo {
*/
#if defined(SQLITE_EBCDIC)
# define sqlite3Utf8Read(A) (*((*A)++))
-# define GlogUpperToLower(A) A = sqlite3UpperToLower[A]
+# define GlobUpperToLower(A) A = sqlite3UpperToLower[A]
#else
-# define GlogUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
+# define GlobUpperToLower(A) if( !((A)&~0x7f) ){ A = sqlite3UpperToLower[A]; }
#endif
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
@@ -87781,11 +90362,11 @@ static int patternCompare(
}
while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
if( noCase ){
- GlogUpperToLower(c2);
- GlogUpperToLower(c);
+ GlobUpperToLower(c2);
+ GlobUpperToLower(c);
while( c2 != 0 && c2 != c ){
c2 = sqlite3Utf8Read(&zString);
- GlogUpperToLower(c2);
+ GlobUpperToLower(c2);
}
}else{
while( c2 != 0 && c2 != c ){
@@ -87837,8 +90418,8 @@ static int patternCompare(
}else{
c2 = sqlite3Utf8Read(&zString);
if( noCase ){
- GlogUpperToLower(c);
- GlogUpperToLower(c2);
+ GlobUpperToLower(c);
+ GlobUpperToLower(c2);
}
if( c!=c2 ){
return 0;
@@ -88043,10 +90624,6 @@ static const char hexdigits[] = {
};
/*
-** EXPERIMENTAL - This is not an official function. The interface may
-** change. This function may disappear. Do not write code that depends
-** on this function.
-**
** Implementation of the QUOTE() function. This function takes a single
** argument. If the argument is numeric, the return value is the same as
** the argument. If the argument is NULL, the return value is the string
@@ -88235,7 +90812,7 @@ static void zeroblobFunc(
/*
** The replace() function. Three arguments are all strings: call
** them A, B, and C. The result is also a string which is derived
-** from A by replacing every occurance of B with C. The match
+** from A by replacing every occurrence of B with C. The match
** must be exact. Collating sequences are not used.
*/
static void replaceFunc(
@@ -88682,9 +91259,9 @@ static void groupConcatFinalize(sqlite3_context *context){
StrAccum *pAccum;
pAccum = sqlite3_aggregate_context(context, 0);
if( pAccum ){
- if( pAccum->tooBig ){
+ if( pAccum->accError==STRACCUM_TOOBIG ){
sqlite3_result_error_toobig(context);
- }else if( pAccum->mallocFailed ){
+ }else if( pAccum->accError==STRACCUM_NOMEM ){
sqlite3_result_error_nomem(context);
}else{
sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
@@ -88714,7 +91291,7 @@ static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName),
2, SQLITE_UTF8, 0);
if( ALWAYS(pDef) ){
- pDef->flags = flagVal;
+ pDef->funcFlags |= flagVal;
}
}
@@ -88758,7 +91335,7 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas
pDef = sqlite3FindFunction(db, pExpr->u.zToken,
sqlite3Strlen30(pExpr->u.zToken),
2, SQLITE_UTF8, 0);
- if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
+ if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
return 0;
}
@@ -88770,7 +91347,7 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas
assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
- *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
+ *pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0;
return 1;
}
@@ -88819,11 +91396,13 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
FUNCTION(lower, 1, 0, 0, lowerFunc ),
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
- FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
+ FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
FUNCTION(hex, 1, 0, 0, hexFunc ),
- FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE),
- FUNCTION(random, 0, 0, 0, randomFunc ),
- FUNCTION(randomblob, 1, 0, 0, randomBlob ),
+ FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
+ FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
+ FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
+ VFUNCTION(random, 0, 0, 0, randomFunc ),
+ VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
@@ -88833,9 +91412,9 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
FUNCTION(quote, 1, 0, 0, quoteFunc ),
- FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
- FUNCTION(changes, 0, 0, 0, changes ),
- FUNCTION(total_changes, 0, 0, 0, total_changes ),
+ VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
+ VFUNCTION(changes, 0, 0, 0, changes ),
+ VFUNCTION(total_changes, 0, 0, 0, total_changes ),
FUNCTION(replace, 3, 0, 0, replaceFunc ),
FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
#ifdef SQLITE_SOUNDEX
@@ -88849,7 +91428,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
/* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */
- {0,SQLITE_UTF8,SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
+ {0,SQLITE_UTF8|SQLITE_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize),
AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
@@ -88875,6 +91454,9 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions();
#endif
+#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
+ sqlite3AnalyzeFunctions();
+#endif
}
/************** End of func.c ************************************************/
@@ -89105,7 +91687,7 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(
}
for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->nColumn==nCol && pIdx->onError!=OE_None ){
+ if( pIdx->nKeyCol==nCol && pIdx->onError!=OE_None ){
/* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
** of columns. If each indexed column corresponds to a foreign key
** column of pFKey, then this index is a winner. */
@@ -89128,7 +91710,7 @@ SQLITE_PRIVATE int sqlite3FkLocateIndex(
** the default collation sequences for each column. */
int i, j;
for(i=0; i<nCol; i++){
- int iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
+ i16 iCol = pIdx->aiColumn[i]; /* Index of column in parent tbl */
char *zDfltColl; /* Def. collation for column */
char *zIdxCol; /* Name of indexed column */
@@ -89259,10 +91841,9 @@ static void fkLookupParent(
int nCol = pFKey->nCol;
int regTemp = sqlite3GetTempRange(pParse, nCol);
int regRec = sqlite3GetTempReg(pParse);
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
- sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
}
@@ -89302,15 +91883,17 @@ static void fkLookupParent(
}
}
- if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
+ if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs)
+ && !pParse->pToplevel
+ && !pParse->isMultiWrite
+ ){
/* Special case: If this is an INSERT statement that will insert exactly
** one row into the table, raise a constraint immediately instead of
** incrementing a counter. This is necessary as the VM code is being
** generated for will not open a statement transaction. */
assert( nIncr==1 );
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
- OE_Abort, "foreign key constraint failed", P4_STATIC
- );
+ OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
}else{
if( nIncr>0 && pFKey->isDeferred==0 ){
sqlite3ParseToplevel(pParse)->mayAbort = 1;
@@ -89322,6 +91905,62 @@ static void fkLookupParent(
sqlite3VdbeAddOp1(v, OP_Close, iCur);
}
+
+/*
+** Return an Expr object that refers to a memory register corresponding
+** to column iCol of table pTab.
+**
+** regBase is the first of an array of register that contains the data
+** for pTab. regBase itself holds the rowid. regBase+1 holds the first
+** column. regBase+2 holds the second column, and so forth.
+*/
+static Expr *exprTableRegister(
+ Parse *pParse, /* Parsing and code generating context */
+ Table *pTab, /* The table whose content is at r[regBase]... */
+ int regBase, /* Contents of table pTab */
+ i16 iCol /* Which column of pTab is desired */
+){
+ Expr *pExpr;
+ Column *pCol;
+ const char *zColl;
+ sqlite3 *db = pParse->db;
+
+ pExpr = sqlite3Expr(db, TK_REGISTER, 0);
+ if( pExpr ){
+ if( iCol>=0 && iCol!=pTab->iPKey ){
+ pCol = &pTab->aCol[iCol];
+ pExpr->iTable = regBase + iCol + 1;
+ pExpr->affinity = pCol->affinity;
+ zColl = pCol->zColl;
+ if( zColl==0 ) zColl = db->pDfltColl->zName;
+ pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
+ }else{
+ pExpr->iTable = regBase;
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ }
+ }
+ return pExpr;
+}
+
+/*
+** Return an Expr object that refers to column iCol of table pTab which
+** has cursor iCur.
+*/
+static Expr *exprTableColumn(
+ sqlite3 *db, /* The database connection */
+ Table *pTab, /* The table whose column is desired */
+ int iCursor, /* The open cursor on the table */
+ i16 iCol /* The column that is wanted */
+){
+ Expr *pExpr = sqlite3Expr(db, TK_COLUMN, 0);
+ if( pExpr ){
+ pExpr->pTab = pTab;
+ pExpr->iTable = iCursor;
+ pExpr->iColumn = iCol;
+ }
+ return pExpr;
+}
+
/*
** This function is called to generate code executed when a row is deleted
** from the parent table of foreign key constraint pFKey and, if pFKey is
@@ -89337,13 +91976,13 @@ static void fkLookupParent(
** --------------------------------------------------------------------------
** DELETE immediate Increment the "immediate constraint counter".
** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
-** throw a "foreign key constraint failed" exception.
+** throw a "FOREIGN KEY constraint failed" exception.
**
** INSERT immediate Decrement the "immediate constraint counter".
**
** DELETE deferred Increment the "deferred constraint counter".
** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
-** throw a "foreign key constraint failed" exception.
+** throw a "FOREIGN KEY constraint failed" exception.
**
** INSERT deferred Decrement the "deferred constraint counter".
**
@@ -89352,12 +91991,12 @@ static void fkLookupParent(
*/
static void fkScanChildren(
Parse *pParse, /* Parse context */
- SrcList *pSrc, /* SrcList containing the table to scan */
- Table *pTab,
- Index *pIdx, /* Foreign key index */
- FKey *pFKey, /* Foreign key relationship */
+ SrcList *pSrc, /* The child table to be scanned */
+ Table *pTab, /* The parent table */
+ Index *pIdx, /* Index on parent covering the foreign key */
+ FKey *pFKey, /* The foreign key linking pSrc to pTab */
int *aiCol, /* Map from pIdx cols to child table cols */
- int regData, /* Referenced table data starts here */
+ int regData, /* Parent row data starts here */
int nIncr /* Amount to increment deferred counter by */
){
sqlite3 *db = pParse->db; /* Database handle */
@@ -89368,7 +92007,10 @@ static void fkScanChildren(
int iFkIfZero = 0; /* Address of OP_FkIfZero */
Vdbe *v = sqlite3GetVdbe(pParse);
- assert( !pIdx || pIdx->pTable==pTab );
+ assert( pIdx==0 || pIdx->pTable==pTab );
+ assert( pIdx==0 || pIdx->nKeyCol==pFKey->nCol );
+ assert( pIdx!=0 || pFKey->nCol==1 );
+ assert( pIdx!=0 || HasRowid(pTab) );
if( nIncr<0 ){
iFkIfZero = sqlite3VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
@@ -89386,29 +92028,11 @@ static void fkScanChildren(
Expr *pLeft; /* Value from parent table row */
Expr *pRight; /* Column ref to child table */
Expr *pEq; /* Expression (pLeft = pRight) */
- int iCol; /* Index of column in child table */
+ i16 iCol; /* Index of column in child table */
const char *zCol; /* Name of column in child table */
- pLeft = sqlite3Expr(db, TK_REGISTER, 0);
- if( pLeft ){
- /* Set the collation sequence and affinity of the LHS of each TK_EQ
- ** expression to the parent key column defaults. */
- if( pIdx ){
- Column *pCol;
- const char *zColl;
- iCol = pIdx->aiColumn[i];
- pCol = &pTab->aCol[iCol];
- if( pTab->iPKey==iCol ) iCol = -1;
- pLeft->iTable = regData+iCol+1;
- pLeft->affinity = pCol->affinity;
- zColl = pCol->zColl;
- if( zColl==0 ) zColl = db->pDfltColl->zName;
- pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
- }else{
- pLeft->iTable = regData;
- pLeft->affinity = SQLITE_AFF_INTEGER;
- }
- }
+ iCol = pIdx ? pIdx->aiColumn[i] : -1;
+ pLeft = exprTableRegister(pParse, pTab, regData, iCol);
iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
assert( iCol>=0 );
zCol = pFKey->pFrom->aCol[iCol].zName;
@@ -89417,24 +92041,39 @@ static void fkScanChildren(
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
}
- /* If the child table is the same as the parent table, and this scan
- ** is taking place as part of a DELETE operation (operation D.2), omit the
- ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE
- ** clause, where $rowid is the rowid of the row being deleted. */
+ /* If the child table is the same as the parent table, then add terms
+ ** to the WHERE clause that prevent this entry from being scanned.
+ ** The added WHERE clause terms are like this:
+ **
+ ** $current_rowid!=rowid
+ ** NOT( $current_a==a AND $current_b==b AND ... )
+ **
+ ** The first form is used for rowid tables. The second form is used
+ ** for WITHOUT ROWID tables. In the second form, the primary key is
+ ** (a,b,...)
+ */
if( pTab==pFKey->pFrom && nIncr>0 ){
- Expr *pEq; /* Expression (pLeft = pRight) */
+ Expr *pNe; /* Expression (pLeft != pRight) */
Expr *pLeft; /* Value from parent table row */
Expr *pRight; /* Column ref to child table */
- pLeft = sqlite3Expr(db, TK_REGISTER, 0);
- pRight = sqlite3Expr(db, TK_COLUMN, 0);
- if( pLeft && pRight ){
- pLeft->iTable = regData;
- pLeft->affinity = SQLITE_AFF_INTEGER;
- pRight->iTable = pSrc->a[0].iCursor;
- pRight->iColumn = -1;
- }
- pEq = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0);
- pWhere = sqlite3ExprAnd(db, pWhere, pEq);
+ if( HasRowid(pTab) ){
+ pLeft = exprTableRegister(pParse, pTab, regData, -1);
+ pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, -1);
+ pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight, 0);
+ }else{
+ Expr *pEq, *pAll = 0;
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pIdx!=0 );
+ for(i=0; i<pPk->nKeyCol; i++){
+ i16 iCol = pIdx->aiColumn[i];
+ pLeft = exprTableRegister(pParse, pTab, regData, iCol);
+ pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight, 0);
+ pAll = sqlite3ExprAnd(db, pAll, pEq);
+ }
+ pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0, 0);
+ }
+ pWhere = sqlite3ExprAnd(db, pWhere, pNe);
}
/* Resolve the references in the WHERE clause. */
@@ -89464,8 +92103,8 @@ static void fkScanChildren(
}
/*
-** This function returns a pointer to the head of a linked list of FK
-** constraints for which table pTab is the parent table. For example,
+** This function returns a linked list of FKey objects (connected by
+** FKey.pNextTo) holding all children of table pTab. For example,
** given the following schema:
**
** CREATE TABLE t1(a PRIMARY KEY);
@@ -89533,7 +92172,7 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
** when this statement is run. */
FKey *p;
for(p=pTab->pFKey; p; p=p->pNextFrom){
- if( p->isDeferred ) break;
+ if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
}
if( !p ) return;
iSkip = sqlite3VdbeMakeLabel(v);
@@ -89547,11 +92186,17 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
/* If the DELETE has generated immediate foreign key constraint
** violations, halt the VDBE and return an error at this point, before
** any modifications to the schema are made. This is because statement
- ** transactions are not able to rollback schema changes. */
- sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
- OE_Abort, "foreign key constraint failed", P4_STATIC
- );
+ ** transactions are not able to rollback schema changes.
+ **
+ ** If the SQLITE_DeferFKs flag is set, then this is not required, as
+ ** the statement transaction will not be rolled back even if FK
+ ** constraints are violated.
+ */
+ if( (db->flags & SQLITE_DeferFKs)==0 ){
+ sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+ OE_Abort, 0, P4_STATIC, P5_ConstraintFK);
+ }
if( iSkip ){
sqlite3VdbeResolveLabel(v, iSkip);
@@ -89559,6 +92204,70 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
}
}
+
+/*
+** The second argument points to an FKey object representing a foreign key
+** for which pTab is the child table. An UPDATE statement against pTab
+** is currently being processed. For each column of the table that is
+** actually updated, the corresponding element in the aChange[] array
+** is zero or greater (if a column is unmodified the corresponding element
+** is set to -1). If the rowid column is modified by the UPDATE statement
+** the bChngRowid argument is non-zero.
+**
+** This function returns true if any of the columns that are part of the
+** child key for FK constraint *p are modified.
+*/
+static int fkChildIsModified(
+ Table *pTab, /* Table being updated */
+ FKey *p, /* Foreign key for which pTab is the child */
+ int *aChange, /* Array indicating modified columns */
+ int bChngRowid /* True if rowid is modified by this update */
+){
+ int i;
+ for(i=0; i<p->nCol; i++){
+ int iChildKey = p->aCol[i].iFrom;
+ if( aChange[iChildKey]>=0 ) return 1;
+ if( iChildKey==pTab->iPKey && bChngRowid ) return 1;
+ }
+ return 0;
+}
+
+/*
+** The second argument points to an FKey object representing a foreign key
+** for which pTab is the parent table. An UPDATE statement against pTab
+** is currently being processed. For each column of the table that is
+** actually updated, the corresponding element in the aChange[] array
+** is zero or greater (if a column is unmodified the corresponding element
+** is set to -1). If the rowid column is modified by the UPDATE statement
+** the bChngRowid argument is non-zero.
+**
+** This function returns true if any of the columns that are part of the
+** parent key for FK constraint *p are modified.
+*/
+static int fkParentIsModified(
+ Table *pTab,
+ FKey *p,
+ int *aChange,
+ int bChngRowid
+){
+ int i;
+ for(i=0; i<p->nCol; i++){
+ char *zKey = p->aCol[i].zCol;
+ int iKey;
+ for(iKey=0; iKey<pTab->nCol; iKey++){
+ if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
+ Column *pCol = &pTab->aCol[iKey];
+ if( zKey ){
+ if( 0==sqlite3StrICmp(pCol->zName, zKey) ) return 1;
+ }else if( pCol->colFlags & COLFLAG_PRIMKEY ){
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
/*
** This function is called when inserting, deleting or updating a row of
** table pTab to generate VDBE code to perform foreign key constraint
@@ -89583,7 +92292,9 @@ SQLITE_PRIVATE void sqlite3FkCheck(
Parse *pParse, /* Parse context */
Table *pTab, /* Row is being deleted from this table */
int regOld, /* Previous row data is stored here */
- int regNew /* New row data is stored here */
+ int regNew, /* New row data is stored here */
+ int *aChange, /* Array indicating UPDATEd columns (or 0) */
+ int bChngRowid /* True if rowid is UPDATEd */
){
sqlite3 *db = pParse->db; /* Database handle */
FKey *pFKey; /* Used to iterate through FKs */
@@ -89611,6 +92322,13 @@ SQLITE_PRIVATE void sqlite3FkCheck(
int i;
int isIgnore = 0;
+ if( aChange
+ && sqlite3_stricmp(pTab->zName, pFKey->zTo)!=0
+ && fkChildIsModified(pTab, pFKey, aChange, bChngRowid)==0
+ ){
+ continue;
+ }
+
/* Find the parent table of this foreign key. Also find a unique index
** on the parent key columns in the parent table. If either of these
** schema items cannot be located, set an error in pParse and return
@@ -89687,13 +92405,20 @@ SQLITE_PRIVATE void sqlite3FkCheck(
sqlite3DbFree(db, aiFree);
}
- /* Loop through all the foreign key constraints that refer to this table */
+ /* Loop through all the foreign key constraints that refer to this table.
+ ** (the "child" constraints) */
for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
Index *pIdx = 0; /* Foreign key index for pFKey */
SrcList *pSrc;
int *aiCol = 0;
- if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
+ if( aChange && fkParentIsModified(pTab, pFKey, aChange, bChngRowid)==0 ){
+ continue;
+ }
+
+ if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs)
+ && !pParse->pToplevel && !pParse->isMultiWrite
+ ){
assert( regOld==0 && regNew!=0 );
/* Inserting a single row into a parent table cannot cause an immediate
** foreign key violation. So do nothing in this case. */
@@ -89706,9 +92431,8 @@ SQLITE_PRIVATE void sqlite3FkCheck(
}
assert( aiCol || pFKey->nCol==1 );
- /* Create a SrcList structure containing a single table (the table
- ** the foreign key that refers to this table is attached to). This
- ** is required for the sqlite3WhereXXX() interface. */
+ /* Create a SrcList structure containing the child table. We need the
+ ** child table as a SrcList for sqlite3WhereBegin() */
pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
if( pSrc ){
struct SrcList_item *pItem = pSrc->a;
@@ -89757,13 +92481,14 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
Index *pIdx = 0;
sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
if( pIdx ){
- for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
+ for(i=0; i<pIdx->nKeyCol; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
}
}
}
return mask;
}
+
/*
** This function is called before generating code to update or delete a
** row contained in table pTab. If the operation is a DELETE, then
@@ -89793,32 +92518,16 @@ SQLITE_PRIVATE int sqlite3FkRequired(
}else{
/* This is an UPDATE. Foreign key processing is only required if the
** operation modifies one or more child or parent key columns. */
- int i;
FKey *p;
/* Check if any child key columns are being modified. */
for(p=pTab->pFKey; p; p=p->pNextFrom){
- for(i=0; i<p->nCol; i++){
- int iChildKey = p->aCol[i].iFrom;
- if( aChange[iChildKey]>=0 ) return 1;
- if( iChildKey==pTab->iPKey && chngRowid ) return 1;
- }
+ if( fkChildIsModified(pTab, p, aChange, chngRowid) ) return 1;
}
/* Check if any parent key columns are being modified. */
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
- for(i=0; i<p->nCol; i++){
- char *zKey = p->aCol[i].zCol;
- int iKey;
- for(iKey=0; iKey<pTab->nCol; iKey++){
- Column *pCol = &pTab->aCol[iKey];
- if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey)
- : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){
- if( aChange[iKey]>=0 ) return 1;
- if( iKey==pTab->iPKey && chngRowid ) return 1;
- }
- }
- }
+ if( fkParentIsModified(pTab, p, aChange, chngRowid) ) return 1;
}
}
}
@@ -89964,7 +92673,7 @@ static Trigger *fkActionTrigger(
tFrom.z = zFrom;
tFrom.n = nFrom;
- pRaise = sqlite3Expr(db, TK_RAISE, "foreign key constraint failed");
+ pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
if( pRaise ){
pRaise->affinity = OE_Abort;
}
@@ -90044,7 +92753,9 @@ SQLITE_PRIVATE void sqlite3FkActions(
Parse *pParse, /* Parse context */
Table *pTab, /* Table being updated or deleted from */
ExprList *pChanges, /* Change-list for UPDATE, NULL for DELETE */
- int regOld /* Address of array containing old row */
+ int regOld, /* Address of array containing old row */
+ int *aChange, /* Array indicating UPDATEd columns (or 0) */
+ int bChngRowid /* True if rowid is UPDATEd */
){
/* If foreign-key support is enabled, iterate through all FKs that
** refer to table pTab. If there is an action associated with the FK
@@ -90053,9 +92764,11 @@ SQLITE_PRIVATE void sqlite3FkActions(
if( pParse->db->flags&SQLITE_ForeignKeys ){
FKey *pFKey; /* Iterator variable */
for(pFKey = sqlite3FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
- Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges);
- if( pAction ){
- sqlite3CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0);
+ if( aChange==0 || fkParentIsModified(pTab, pFKey, aChange, bChngRowid) ){
+ Trigger *pAct = fkActionTrigger(pParse, pTab, pFKey, pChanges);
+ if( pAct ){
+ sqlite3CodeRowTriggerDirect(pParse, pAct, pTab, regOld, OE_Abort, 0);
+ }
}
}
}
@@ -90124,10 +92837,16 @@ SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *db, Table *pTab){
*/
/*
-** Generate code that will open a table for reading.
+** Generate code that will
+**
+** (1) acquire a lock for table pTab then
+** (2) open pTab as cursor iCur.
+**
+** If pTab is a WITHOUT ROWID table, then it is the PRIMARY KEY index
+** for that table that is actually opened.
*/
SQLITE_PRIVATE void sqlite3OpenTable(
- Parse *p, /* Generate code into this VDBE */
+ Parse *pParse, /* 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 */
@@ -90135,12 +92854,21 @@ SQLITE_PRIVATE void sqlite3OpenTable(
){
Vdbe *v;
assert( !IsVirtual(pTab) );
- v = sqlite3GetVdbe(p);
+ v = sqlite3GetVdbe(pParse);
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));
+ sqlite3TableLock(pParse, iDb, pTab->tnum,
+ (opcode==OP_OpenWrite)?1:0, pTab->zName);
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
+ VdbeComment((v, "%s", pTab->zName));
+ }else{
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+ assert( pPk!=0 );
+ assert( pPk->tnum=pTab->tnum );
+ sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
+ sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+ VdbeComment((v, "%s", pTab->zName));
+ }
}
/*
@@ -90176,15 +92904,15 @@ SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
int n;
Table *pTab = pIdx->pTable;
sqlite3 *db = sqlite3VdbeDb(v);
- pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+2);
+ pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1);
if( !pIdx->zColAff ){
db->mallocFailed = 1;
return 0;
}
for(n=0; n<pIdx->nColumn; n++){
- pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
+ i16 x = pIdx->aiColumn[n];
+ pIdx->zColAff[n] = x<0 ? SQLITE_AFF_INTEGER : pTab->aCol[x].affinity;
}
- pIdx->zColAff[n++] = SQLITE_AFF_INTEGER;
pIdx->zColAff[n] = 0;
}
@@ -90530,7 +93258,7 @@ static int xferOptimization(
);
/*
-** This routine is call to handle SQL of the following forms:
+** This routine is called to handle SQL of the following forms:
**
** insert into TABLE (IDLIST) values(EXPRLIST)
** insert into TABLE (IDLIST) select
@@ -90545,12 +93273,12 @@ static int xferOptimization(
** data for the insert.
**
** The code generated follows one of four templates. For a simple
-** select with data coming from a VALUES clause, the code executes
+** insert with data coming from a VALUES clause, the code executes
** once straight down through. Pseudo-code follows (we call this
** the "1st template"):
**
** open write cursor to <table> and its indices
-** puts VALUES clause expressions onto the stack
+** put VALUES clause expressions into registers
** write the resulting record into <table>
** cleanup
**
@@ -90648,8 +93376,9 @@ SQLITE_PRIVATE void sqlite3Insert(
Index *pIdx; /* For looping over indices of the table */
int nColumn; /* Number of columns in the data */
int nHidden = 0; /* Number of hidden columns if TABLE is virtual */
- int baseCur = 0; /* VDBE Cursor number for pTab */
- int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
+ int iDataCur = 0; /* VDBE cursor that is the main data repository */
+ int iIdxCur = 0; /* First index cursor */
+ int ipkColumn = -1; /* Column that is the INTEGER PRIMARY KEY */
int endOfLoop; /* Label for the end of the insertion loop */
int useTempTable = 0; /* Store SELECT results in intermediate table */
int srcTab = 0; /* Data comes from this temporary cursor if >=0 */
@@ -90660,6 +93389,7 @@ SQLITE_PRIVATE void sqlite3Insert(
int iDb; /* Index of database holding TABLE */
Db *pDb; /* The database containing table being inserted into */
int appendFlag = 0; /* True if the insert is likely to be an append */
+ int withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
/* Register allocations */
int regFromSelect = 0;/* Base register for data coming from SELECT */
@@ -90699,6 +93429,7 @@ SQLITE_PRIVATE void sqlite3Insert(
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
goto insert_cleanup;
}
+ withoutRowid = !HasRowid(pTab);
/* Figure out if we have any triggers and if the table being
** inserted into is a view
@@ -90718,16 +93449,13 @@ SQLITE_PRIVATE void sqlite3Insert(
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
/* If pTab is really a view, make sure it has been initialized.
- ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual
- ** module table).
+ ** ViewGetColumnNames() is a no-op if pTab is not a view.
*/
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto insert_cleanup;
}
- /* Ensure that:
- * (a) the table is not read-only,
- * (b) that if it is a view then ON INSERT triggers exist
+ /* Cannot insert into a read-only table.
*/
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
goto insert_cleanup;
@@ -90768,8 +93496,7 @@ SQLITE_PRIVATE void sqlite3Insert(
** co-routine is the common header to the 3rd and 4th templates.
*/
if( pSelect ){
- /* Data is coming from a SELECT. Generate a co-routine to run that
- ** SELECT. */
+ /* Data is coming from a SELECT. Generate a co-routine to run the SELECT */
int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
if( rc ) goto insert_cleanup;
@@ -90781,7 +93508,7 @@ SQLITE_PRIVATE void sqlite3Insert(
/* Set useTempTable to TRUE if the result of the SELECT statement
** should be written into a temporary table (template 4). Set to
- ** FALSE if each* row of the SELECT can be written directly into
+ ** FALSE if each output row of the SELECT can be written directly into
** the destination table (template 3).
**
** A temp table must be used if the table being updated is also one
@@ -90864,11 +93591,11 @@ SQLITE_PRIVATE void sqlite3Insert(
** remember the column indices.
**
** If the table has an INTEGER PRIMARY KEY column and that column
- ** is named in the IDLIST, then record in the keyColumn variable
- ** the index into IDLIST of the primary key column. keyColumn is
+ ** is named in the IDLIST, then record in the ipkColumn variable
+ ** the index into IDLIST of the primary key column. ipkColumn is
** the index of the primary key as it appears in IDLIST, not as
- ** is appears in the original table. (The index of the primary
- ** key in the original table is pTab->iPKey.)
+ ** is appears in the original table. (The index of the INTEGER
+ ** PRIMARY KEY in the original table is pTab->iPKey.)
*/
if( pColumn ){
for(i=0; i<pColumn->nId; i++){
@@ -90879,14 +93606,14 @@ SQLITE_PRIVATE void sqlite3Insert(
if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
pColumn->a[i].idx = j;
if( j==pTab->iPKey ){
- keyColumn = i;
+ ipkColumn = i; assert( !withoutRowid );
}
break;
}
}
if( j>=pTab->nCol ){
- if( sqlite3IsRowid(pColumn->a[i].zName) ){
- keyColumn = i;
+ if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
+ ipkColumn = i;
}else{
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
pTabList, 0, pColumn->a[i].zName);
@@ -90898,11 +93625,11 @@ SQLITE_PRIVATE void sqlite3Insert(
}
/* If there is no IDLIST term but the table has an integer primary
- ** key, the set the keyColumn variable to the primary key column index
- ** in the original table definition.
+ ** key, the set the ipkColumn variable to the integer primary key
+ ** column index in the original table definition.
*/
if( pColumn==0 && nColumn>0 ){
- keyColumn = pTab->iPKey;
+ ipkColumn = pTab->iPKey;
}
/* Initialize the count of rows to be inserted
@@ -90915,9 +93642,8 @@ SQLITE_PRIVATE void sqlite3Insert(
/* If this is not a view, open the table and and all indices */
if( !isView ){
int nIdx;
-
- baseCur = pParse->nTab;
- nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite);
+ nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, -1, 0,
+ &iDataCur, &iIdxCur);
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
if( aRegIdx==0 ){
goto insert_cleanup;
@@ -90977,15 +93703,16 @@ SQLITE_PRIVATE void sqlite3Insert(
** we do not know what the unique ID will be (because the insert has
** not happened yet) so we substitute a rowid of -1
*/
- if( keyColumn<0 ){
+ if( ipkColumn<0 ){
sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
}else{
int j1;
+ assert( !withoutRowid );
if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regCols);
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regCols);
}else{
assert( pSelect==0 ); /* Otherwise useTempTable is true */
- sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regCols);
+ sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regCols);
}
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols);
sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols);
@@ -91035,29 +93762,27 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
}
- /* Push the record number for the new entry onto the stack. The
- ** record number is a randomly generate integer created by NewRowid
- ** except when the table has an INTEGER PRIMARY KEY column, in which
- ** case the record number is the same as that column.
+ /* Compute the content of the next row to insert into a range of
+ ** registers beginning at regIns.
*/
if( !isView ){
if( IsVirtual(pTab) ){
/* The row that the VUpdate opcode will delete: none */
sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
}
- if( keyColumn>=0 ){
+ if( ipkColumn>=0 ){
if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid);
}else if( pSelect ){
- sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid);
+ sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+ipkColumn, regRowid);
}else{
VdbeOp *pOp;
- sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);
+ sqlite3ExprCode(pParse, pList->a[ipkColumn].pExpr, regRowid);
pOp = sqlite3VdbeGetOp(v, -1);
if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){
appendFlag = 1;
pOp->opcode = OP_NewRowid;
- pOp->p1 = baseCur;
+ pOp->p1 = iDataCur;
pOp->p2 = regRowid;
pOp->p3 = regAutoinc;
}
@@ -91069,7 +93794,7 @@ SQLITE_PRIVATE void sqlite3Insert(
int j1;
if( !IsVirtual(pTab) ){
j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid);
- sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
+ sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
sqlite3VdbeJumpHere(v, j1);
}else{
j1 = sqlite3VdbeCurrentAddr(v);
@@ -91077,15 +93802,15 @@ SQLITE_PRIVATE void sqlite3Insert(
}
sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
}
- }else if( IsVirtual(pTab) ){
+ }else if( IsVirtual(pTab) || withoutRowid ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);
}else{
- sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);
+ sqlite3VdbeAddOp3(v, OP_NewRowid, iDataCur, regRowid, regAutoinc);
appendFlag = 1;
}
autoIncStep(pParse, regAutoinc, regRowid);
- /* Push onto the stack, data for all columns of the new entry, beginning
+ /* Compute data for all columns of the new entry, beginning
** with the first column.
*/
nHidden = 0;
@@ -91093,8 +93818,8 @@ SQLITE_PRIVATE void sqlite3Insert(
int iRegStore = regRowid+1+i;
if( i==pTab->iPKey ){
/* The value of the INTEGER PRIMARY KEY column is always a NULL.
- ** Whenever this column is read, the record number will be substituted
- ** in its place. So will fill this column with a NULL to avoid
+ ** Whenever this column is read, the rowid will be substituted
+ ** in its place. Hence, fill this column with a NULL to avoid
** taking up data space with information that will never be used. */
sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore);
continue;
@@ -91137,13 +93862,12 @@ SQLITE_PRIVATE void sqlite3Insert(
#endif
{
int isReplace; /* Set to true if constraints may cause a replace */
- sqlite3GenerateConstraintChecks(pParse, pTab, baseCur, regIns, aRegIdx,
- keyColumn>=0, 0, onError, endOfLoop, &isReplace
- );
- sqlite3FkCheck(pParse, pTab, 0, regIns);
- sqlite3CompleteInsertion(
- pParse, pTab, baseCur, regIns, aRegIdx, 0, appendFlag, isReplace==0
+ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
+ regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace
);
+ sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
+ sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
+ regIns, aRegIdx, 0, appendFlag, isReplace==0);
}
}
@@ -91174,9 +93898,9 @@ SQLITE_PRIVATE void sqlite3Insert(
if( !IsVirtual(pTab) && !isView ){
/* Close all tables opened */
- sqlite3VdbeAddOp1(v, OP_Close, baseCur);
- for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
- sqlite3VdbeAddOp1(v, OP_Close, idx+baseCur);
+ if( iDataCur<iIdxCur ) sqlite3VdbeAddOp1(v, OP_Close, iDataCur);
+ for(idx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
+ sqlite3VdbeAddOp1(v, OP_Close, idx+iIdxCur);
}
}
@@ -91221,36 +93945,48 @@ insert_cleanup:
#undef tmask
#endif
-
/*
-** Generate code to do constraint checks prior to an INSERT or an UPDATE.
-**
-** The input is a range of consecutive registers as follows:
+** Generate code to do constraint checks prior to an INSERT or an UPDATE
+** on table pTab.
**
-** 1. The rowid of the row after the update.
+** The regNewData parameter is the first register in a range that contains
+** the data to be inserted or the data after the update. There will be
+** pTab->nCol+1 registers in this range. The first register (the one
+** that regNewData points to) will contain the new rowid, or NULL in the
+** case of a WITHOUT ROWID table. The second register in the range will
+** contain the content of the first table column. The third register will
+** contain the content of the second table column. And so forth.
**
-** 2. The data in the first column of the entry after the update.
+** The regOldData parameter is similar to regNewData except that it contains
+** the data prior to an UPDATE rather than afterwards. regOldData is zero
+** for an INSERT. This routine can distinguish between UPDATE and INSERT by
+** checking regOldData for zero.
**
-** i. Data from middle columns...
+** For an UPDATE, the pkChng boolean is true if the true primary key (the
+** rowid for a normal table or the PRIMARY KEY for a WITHOUT ROWID table)
+** might be modified by the UPDATE. If pkChng is false, then the key of
+** the iDataCur content table is guaranteed to be unchanged by the UPDATE.
**
-** N. The data in the last column of the entry after the update.
+** For an INSERT, the pkChng boolean indicates whether or not the rowid
+** was explicitly specified as part of the INSERT statement. If pkChng
+** is zero, it means that the either rowid is computed automatically or
+** that the table is a WITHOUT ROWID table and has no rowid. On an INSERT,
+** pkChng will only be true if the INSERT statement provides an integer
+** value for either the rowid column or its INTEGER PRIMARY KEY alias.
**
-** The regRowid parameter is the index of the register containing (1).
-**
-** If isUpdate is true and rowidChng is non-zero, then rowidChng contains
-** the address of a register containing the rowid before the update takes
-** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
-** is false, indicating an INSERT statement, then a non-zero rowidChng
-** indicates that the rowid was explicitly specified as part of the
-** INSERT statement. If rowidChng is false, it means that the rowid is
-** computed automatically in an insert or that the rowid value is not
-** modified by an update.
-**
-** The code generated by this routine store new index entries into
+** The code generated by this routine will store new index entries into
** registers identified by aRegIdx[]. No index entry is created for
** indices where aRegIdx[i]==0. The order of indices in aRegIdx[] is
** the same as the order of indices on the linked list of indices
-** attached to the table.
+** at pTab->pIndex.
+**
+** The caller must have already opened writeable cursors on the main
+** table and all applicable indices (that is to say, all indices for which
+** aRegIdx[] is not zero). iDataCur is the cursor for the main table when
+** inserting or updating a rowid table, or the cursor for the PRIMARY KEY
+** index when operating on a WITHOUT ROWID table. iIdxCur is the cursor
+** for the first index in the pTab->pIndex list. Cursors for other indices
+** are at iIdxCur+N for the N-th element of the pTab->pIndex list.
**
** This routine also generates code to check constraints. NOT NULL,
** CHECK, and UNIQUE constraints are all checked. If a constraint fails,
@@ -91260,22 +93996,23 @@ insert_cleanup:
** Constraint type Action What Happens
** --------------- ---------- ----------------------------------------
** any ROLLBACK The current transaction is rolled back and
-** sqlite3_exec() returns immediately with a
+** sqlite3_step() returns immediately with a
** return code of SQLITE_CONSTRAINT.
**
** any ABORT Back out changes from the current command
** only (do not do a complete rollback) then
-** cause sqlite3_exec() to return immediately
+** cause sqlite3_step() to return immediately
** with SQLITE_CONSTRAINT.
**
-** any FAIL Sqlite3_exec() returns immediately with a
+** any FAIL Sqlite3_step() returns immediately with a
** return code of SQLITE_CONSTRAINT. The
** transaction is not rolled back and any
-** prior changes are retained.
+** changes to prior rows are retained.
**
-** any IGNORE The record number and data is popped from
-** the stack and there is an immediate jump
-** to label ignoreDest.
+** any IGNORE The attempt in insert or update the current
+** row is skipped, without throwing an error.
+** Processing continues with the next row.
+** (There is an immediate jump to ignoreDest.)
**
** NOT NULL REPLACE The NULL value is replace by the default
** value for that column. If the default value
@@ -91290,44 +94027,57 @@ insert_cleanup:
** Or if overrideError==OE_Default, then the pParse->onError parameter
** is used. Or if pParse->onError==OE_Default then the onError value
** for the constraint is used.
-**
-** The calling routine must open a read/write cursor for pTab with
-** cursor number "baseCur". All indices of pTab must also have open
-** read/write cursors with cursor number baseCur+i for the i-th cursor.
-** Except, if there is no possibility of a REPLACE action then
-** cursors do not need to be open for indices where aRegIdx[i]==0.
*/
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
- Parse *pParse, /* The parser context */
- Table *pTab, /* the table into which we are inserting */
- int baseCur, /* Index of a read/write cursor pointing at pTab */
- int regRowid, /* Index of the range of input registers */
- int *aRegIdx, /* Register used by each index. 0 for unused indices */
- 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 *pbMayReplace /* OUT: Set to true if constraint may cause a replace */
-){
- 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; /* Table cursor number */
+ Parse *pParse, /* The parser context */
+ Table *pTab, /* The table being inserted or updated */
+ int *aRegIdx, /* Use register aRegIdx[i] for index i. 0 for unused */
+ int iDataCur, /* Canonical data cursor (main table or PK index) */
+ int iIdxCur, /* First index cursor */
+ int regNewData, /* First register in a range holding values to insert */
+ int regOldData, /* Previous content. 0 for INSERTs */
+ u8 pkChng, /* Non-zero if the rowid or PRIMARY KEY changed */
+ u8 overrideError, /* Override onError to this if not OE_Default */
+ int ignoreDest, /* Jump to this label on an OE_Ignore resolution */
+ int *pbMayReplace /* OUT: Set to true if constraint may cause a replace */
+){
+ Vdbe *v; /* VDBE under constrution */
Index *pIdx; /* Pointer to one of the indices */
+ Index *pPk = 0; /* The PRIMARY KEY index */
sqlite3 *db; /* Database connection */
+ int i; /* loop counter */
+ int ix; /* Index loop counter */
+ int nCol; /* Number of columns */
+ int onError; /* Conflict resolution strategy */
+ int j1; /* Addresss of jump instruction */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
- int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid;
+ int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
+ int ipkTop = 0; /* Top of the rowid change constraint check */
+ int ipkBottom = 0; /* Bottom of the rowid change constraint check */
+ u8 isUpdate; /* True if this is an UPDATE operation */
+ isUpdate = regOldData!=0;
db = pParse->db;
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
nCol = pTab->nCol;
- regData = regRowid + 1;
+
+ /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
+ ** normal rowid tables. nPkField is the number of key fields in the
+ ** pPk index or 1 for a rowid table. In other words, nPkField is the
+ ** number of fields in the true primary key of the table. */
+ if( HasRowid(pTab) ){
+ pPk = 0;
+ nPkField = 1;
+ }else{
+ pPk = sqlite3PrimaryKeyIndex(pTab);
+ nPkField = pPk->nKeyCol;
+ }
+
+ /* Record that this module has started */
+ VdbeModuleComment((v, "BEGIN: GenCnstCks(%d,%d,%d,%d,%d)",
+ iDataCur, iIdxCur, regNewData, regOldData, pkChng));
/* Test all NOT NULL constraints.
*/
@@ -91350,24 +94100,24 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
switch( onError ){
case OE_Abort:
sqlite3MayAbort(pParse);
+ /* Fall through */
case OE_Rollback:
case OE_Fail: {
- char *zMsg;
- sqlite3VdbeAddOp3(v, OP_HaltIfNull,
- SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
- zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
- pTab->zName, pTab->aCol[i].zName);
- sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
+ char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
+ pTab->aCol[i].zName);
+ sqlite3VdbeAddOp4(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
+ regNewData+1+i, zMsg, P4_DYNAMIC);
+ sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
break;
}
case OE_Ignore: {
- sqlite3VdbeAddOp2(v, OP_IsNull, regData+i, ignoreDest);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
break;
}
default: {
assert( onError==OE_Replace );
- j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i);
+ j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regNewData+1+i);
+ sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
sqlite3VdbeJumpHere(v, j1);
break;
}
@@ -91379,7 +94129,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
#ifndef SQLITE_OMIT_CHECK
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
ExprList *pCheck = pTab->pCheck;
- pParse->ckBase = regData;
+ pParse->ckBase = regNewData+1;
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
for(i=0; i<pCheck->nExpr; i++){
int allOk = sqlite3VdbeMakeLabel(v);
@@ -91387,37 +94137,58 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
if( onError==OE_Ignore ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
}else{
- char *zConsName = pCheck->a[i].zName;
+ char *zName = pCheck->a[i].zName;
+ if( zName==0 ) zName = pTab->zName;
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
- if( zConsName ){
- zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName);
- }else{
- zConsName = 0;
- }
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
- onError, zConsName, P4_DYNAMIC);
+ onError, zName, P4_TRANSIENT,
+ P5_ConstraintCheck);
}
sqlite3VdbeResolveLabel(v, allOk);
}
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
- /* If we have an INTEGER PRIMARY KEY, make sure the primary key
- ** of the new record does not previously exist. Except, if this
- ** is an UPDATE and the primary key is not changing, that is OK.
+ /* If rowid is changing, make sure the new rowid does not previously
+ ** exist in the table.
*/
- if( rowidChng ){
+ if( pkChng && pPk==0 ){
+ int addrRowidOk = sqlite3VdbeMakeLabel(v);
+
+ /* Figure out what action to take in case of a rowid collision */
onError = pTab->keyConf;
if( overrideError!=OE_Default ){
onError = overrideError;
}else if( onError==OE_Default ){
onError = OE_Abort;
}
-
+
if( isUpdate ){
- j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, rowidChng);
+ /* pkChng!=0 does not mean that the rowid has change, only that
+ ** it might have changed. Skip the conflict logic below if the rowid
+ ** is unchanged. */
+ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
}
- j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
+
+ /* If the response to a rowid conflict is REPLACE but the response
+ ** to some other UNIQUE constraint is FAIL or IGNORE, then we need
+ ** to defer the running of the rowid conflict checking until after
+ ** the UNIQUE constraints have run.
+ */
+ if( onError==OE_Replace && overrideError!=OE_Replace ){
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->onError==OE_Ignore || pIdx->onError==OE_Fail ){
+ ipkTop = sqlite3VdbeAddOp0(v, OP_Goto);
+ break;
+ }
+ }
+ }
+
+ /* Check to see if the new rowid already exists in the table. Skip
+ ** the following conflict logic if it does not. */
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
+
+ /* Generate code that deals with a rowid collision */
switch( onError ){
default: {
onError = OE_Abort;
@@ -91426,8 +94197,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
- onError, "PRIMARY KEY must be unique", P4_STATIC);
+ sqlite3RowidConstraint(pParse, onError, pTab);
break;
}
case OE_Replace: {
@@ -91459,57 +94229,88 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
sqlite3MultiWrite(pParse);
- sqlite3GenerateRowDelete(
- pParse, pTab, baseCur, regRowid, 0, pTrigger, OE_Replace
- );
+ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+ regNewData, 1, 0, OE_Replace, 1);
}else if( pTab->pIndex ){
sqlite3MultiWrite(pParse);
- sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, 0);
}
seenReplace = 1;
break;
}
case OE_Ignore: {
- assert( seenReplace==0 );
+ /*assert( seenReplace==0 );*/
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
break;
}
}
- sqlite3VdbeJumpHere(v, j3);
- if( isUpdate ){
- sqlite3VdbeJumpHere(v, j2);
+ sqlite3VdbeResolveLabel(v, addrRowidOk);
+ if( ipkTop ){
+ ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
+ sqlite3VdbeJumpHere(v, ipkTop);
}
}
/* Test all UNIQUE constraints by creating entries for each UNIQUE
** index and making sure that duplicate entries do not already exist.
- ** Add the new records to the indices as we go.
- */
- for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
- int regIdx;
- int regR;
-
- if( aRegIdx[iCur]==0 ) continue; /* Skip unused indices */
-
- /* Create a key for accessing the index entry */
- regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);
+ ** Compute the revised record entries for indices as we go.
+ **
+ ** This loop also handles the case of the PRIMARY KEY index for a
+ ** WITHOUT ROWID table.
+ */
+ for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
+ int regIdx; /* Range of registers hold conent for pIdx */
+ int regR; /* Range of registers holding conflicting PK */
+ int iThisCur; /* Cursor for this UNIQUE index */
+ int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */
+
+ if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
+ iThisCur = iIdxCur+ix;
+ addrUniqueOk = sqlite3VdbeMakeLabel(v);
+
+ /* Skip partial indices for which the WHERE clause is not true */
+ if( pIdx->pPartIdxWhere ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
+ pParse->ckBase = regNewData+1;
+ sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
+ SQLITE_JUMPIFNULL);
+ pParse->ckBase = 0;
+ }
+
+ /* Create a record for this index entry as it should appear after
+ ** the insert or update. Store that record in the aRegIdx[ix] register
+ */
+ regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
for(i=0; i<pIdx->nColumn; i++){
- int idx = pIdx->aiColumn[i];
- if( idx==pTab->iPKey ){
- sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
+ int iField = pIdx->aiColumn[i];
+ int x;
+ if( iField<0 || iField==pTab->iPKey ){
+ x = regNewData;
}else{
- sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);
+ x = iField + regNewData + 1;
}
+ sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
+ VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
}
- sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), P4_TRANSIENT);
- sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
+ VdbeComment((v, "for %s", pIdx->zName));
+ sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn);
+
+ /* In an UPDATE operation, if this index is the PRIMARY KEY index
+ ** of a WITHOUT ROWID table and there has been no change the
+ ** primary key, then no collision is possible. The collision detection
+ ** logic below can all be skipped. */
+ if( isUpdate && pPk==pIdx && pkChng==0 ){
+ sqlite3VdbeResolveLabel(v, addrUniqueOk);
+ continue;
+ }
- /* Find out what action to take in case there is an indexing conflict */
+ /* Find out what action to take in case there is a uniqueness conflict */
onError = pIdx->onError;
if( onError==OE_None ){
- sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
+ sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
+ sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue; /* pIdx is not a UNIQUE index */
}
if( overrideError!=OE_Default ){
@@ -91517,18 +94318,57 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}else if( onError==OE_Default ){
onError = OE_Abort;
}
- if( seenReplace ){
- if( onError==OE_Ignore ) onError = OE_Replace;
- else if( onError==OE_Fail ) onError = OE_Abort;
- }
/* Check to see if the new index entry will be unique */
- regR = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_SCopy, regOldRowid, regR);
- j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,
- regR, SQLITE_INT_TO_PTR(regIdx),
- P4_INT32);
- sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
+ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
+ regIdx, pIdx->nKeyCol);
+
+ /* Generate code to handle collisions */
+ regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
+ /* Conflict only if the rowid of the existing index entry
+ ** is different from old-rowid */
+ if( isUpdate ){
+ sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
+ }
+ }else{
+ int x;
+ /* Extract the PRIMARY KEY from the end of the index entry and
+ ** store it in registers regR..regR+nPk-1 */
+ if( (isUpdate || onError==OE_Replace) && pIdx!=pPk ){
+ for(i=0; i<pPk->nKeyCol; i++){
+ x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
+ sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
+ VdbeComment((v, "%s.%s", pTab->zName,
+ pTab->aCol[pPk->aiColumn[i]].zName));
+ }
+ }
+ if( isUpdate ){
+ /* If currently processing the PRIMARY KEY of a WITHOUT ROWID
+ ** table, only conflict if the new PRIMARY KEY values are actually
+ ** different from the old.
+ **
+ ** For a UNIQUE index, only conflict if the PRIMARY KEY values
+ ** of the matched index row are different from the original PRIMARY
+ ** KEY values of this row before the update. */
+ int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
+ int op = OP_Ne;
+ int regCmp = (pIdx->autoIndex==2 ? regIdx : regR);
+
+ for(i=0; i<pPk->nKeyCol; i++){
+ char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
+ x = pPk->aiColumn[i];
+ if( i==(pPk->nKeyCol-1) ){
+ addrJump = addrUniqueOk;
+ op = OP_Eq;
+ }
+ sqlite3VdbeAddOp4(v, op,
+ regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
+ );
+ }
+ }
+ }
/* Generate code that executes if the new index entry is not unique */
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
@@ -91537,30 +94377,10 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
- int j;
- StrAccum errMsg;
- const char *zSep;
- char *zErr;
-
- sqlite3StrAccumInit(&errMsg, 0, 0, 200);
- errMsg.db = db;
- zSep = pIdx->nColumn>1 ? "columns " : "column ";
- for(j=0; j<pIdx->nColumn; j++){
- char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
- sqlite3StrAccumAppend(&errMsg, zSep, -1);
- zSep = ", ";
- sqlite3StrAccumAppend(&errMsg, zCol, -1);
- }
- sqlite3StrAccumAppend(&errMsg,
- pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
- zErr = sqlite3StrAccumFinish(&errMsg);
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
- onError, zErr, 0);
- sqlite3DbFree(errMsg.db, zErr);
+ sqlite3UniqueConstraint(pParse, onError, pIdx);
break;
}
case OE_Ignore: {
- assert( seenReplace==0 );
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
break;
}
@@ -91571,26 +94391,29 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
if( db->flags&SQLITE_RecTriggers ){
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
}
- sqlite3GenerateRowDelete(
- pParse, pTab, baseCur, regR, 0, pTrigger, OE_Replace
- );
+ sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
+ regR, nPkField, 0, OE_Replace, pIdx==pPk);
seenReplace = 1;
break;
}
}
- sqlite3VdbeJumpHere(v, j3);
- sqlite3ReleaseTempReg(pParse, regR);
+ sqlite3VdbeResolveLabel(v, addrUniqueOk);
+ sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
+ if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
}
-
- if( pbMayReplace ){
- *pbMayReplace = seenReplace;
+ if( ipkTop ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, ipkTop+1);
+ sqlite3VdbeJumpHere(v, ipkBottom);
}
+
+ *pbMayReplace = seenReplace;
+ VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}
/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite3GenerateConstraintChecks.
-** A consecutive range of registers starting at regRowid contains the
+** A consecutive range of registers starting at regNewData contains the
** rowid and the content to be inserted.
**
** The arguments to this routine should be the same as the first six
@@ -91599,33 +94422,40 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
SQLITE_PRIVATE void sqlite3CompleteInsertion(
Parse *pParse, /* The parser context */
Table *pTab, /* the table into which we are inserting */
- int baseCur, /* Index of a read/write cursor pointing at pTab */
- int regRowid, /* Range of content */
+ int iDataCur, /* Cursor of the canonical data source */
+ int iIdxCur, /* First index cursor */
+ int regNewData, /* Range of content */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
int isUpdate, /* True for UPDATE, False for INSERT */
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;
- int nIdx;
- Index *pIdx;
- u8 pik_flags;
- int regData;
- int regRec;
+ Vdbe *v; /* Prepared statements under construction */
+ Index *pIdx; /* An index being inserted or updated */
+ u8 pik_flags; /* flag values passed to the btree insert */
+ int regData; /* Content registers (after the rowid) */
+ int regRec; /* Register holding assemblied record for the table */
+ int i; /* Loop counter */
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
- for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
- for(i=nIdx-1; i>=0; i--){
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( aRegIdx[i]==0 ) continue;
- sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
- if( useSeekResult ){
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ if( pIdx->pPartIdxWhere ){
+ sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
}
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
+ pik_flags = 0;
+ if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
+ if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
+ assert( pParse->nested==0 );
+ pik_flags |= OPFLAG_NCHANGE;
+ }
+ if( pik_flags ) sqlite3VdbeChangeP5(v, pik_flags);
}
- regData = regRowid + 1;
+ if( !HasRowid(pTab) ) return;
+ regData = regNewData + 1;
regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
sqlite3TableAffinityStr(v, pTab);
@@ -91642,7 +94472,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
if( useSeekResult ){
pik_flags |= OPFLAG_USESEEKRESULT;
}
- sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, iDataCur, regRec, regNewData);
if( !pParse->nested ){
sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_TRANSIENT);
}
@@ -91650,39 +94480,71 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
}
/*
-** Generate code that will open cursors for a table and for all
-** indices of that table. The "baseCur" parameter is the cursor number used
-** for the table. Indices are opened on subsequent cursors.
+** Allocate cursors for the pTab table and all its indices and generate
+** code to open and initialized those cursors.
+**
+** The cursor for the object that contains the complete data (normally
+** the table itself, but the PRIMARY KEY index in the case of a WITHOUT
+** ROWID table) is returned in *piDataCur. The first index cursor is
+** returned in *piIdxCur. The number of indices is returned.
+**
+** Use iBase as the first cursor (either the *piDataCur for rowid tables
+** or the first index for WITHOUT ROWID tables) if it is non-negative.
+** If iBase is negative, then allocate the next available cursor.
**
-** Return the number of indices on the table.
+** For a rowid table, *piDataCur will be exactly one less than *piIdxCur.
+** For a WITHOUT ROWID table, *piDataCur will be somewhere in the range
+** of *piIdxCurs, depending on where the PRIMARY KEY index appears on the
+** pTab->pIndex list.
*/
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(
Parse *pParse, /* Parsing context */
Table *pTab, /* Table to be opened */
- int baseCur, /* Cursor number assigned to the table */
- int op /* OP_OpenRead or OP_OpenWrite */
+ int op, /* OP_OpenRead or OP_OpenWrite */
+ int iBase, /* Use this for the table cursor, if there is one */
+ u8 *aToOpen, /* If not NULL: boolean for each table and index */
+ int *piDataCur, /* Write the database source cursor number here */
+ int *piIdxCur /* Write the first index cursor number here */
){
int i;
int iDb;
+ int iDataCur;
Index *pIdx;
Vdbe *v;
- if( IsVirtual(pTab) ) return 0;
+ assert( op==OP_OpenRead || op==OP_OpenWrite );
+ if( IsVirtual(pTab) ){
+ assert( aToOpen==0 );
+ *piDataCur = 0;
+ *piIdxCur = 1;
+ return 0;
+ }
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
- sqlite3OpenTable(pParse, baseCur, iDb, pTab, op);
- for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
- assert( pIdx->pSchema==pTab->pSchema );
- sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb,
- (char*)pKey, P4_KEYINFO_HANDOFF);
- VdbeComment((v, "%s", pIdx->zName));
+ if( iBase<0 ) iBase = pParse->nTab;
+ iDataCur = iBase++;
+ if( piDataCur ) *piDataCur = iDataCur;
+ if( HasRowid(pTab) && (aToOpen==0 || aToOpen[0]) ){
+ sqlite3OpenTable(pParse, iDataCur, iDb, pTab, op);
+ }else{
+ sqlite3TableLock(pParse, iDb, pTab->tnum, op==OP_OpenWrite, pTab->zName);
}
- if( pParse->nTab<baseCur+i ){
- pParse->nTab = baseCur+i;
+ if( piIdxCur ) *piIdxCur = iBase;
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ int iIdxCur = iBase++;
+ assert( pIdx->pSchema==pTab->pSchema );
+ if( pIdx->autoIndex==2 && !HasRowid(pTab) && piDataCur ){
+ *piDataCur = iIdxCur;
+ }
+ if( aToOpen==0 || aToOpen[i+1] ){
+ sqlite3VdbeAddOp3(v, op, iIdxCur, pIdx->tnum, iDb);
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
+ VdbeComment((v, "%s", pIdx->zName));
+ }
}
- return i-1;
+ if( iBase>pParse->nTab ) pParse->nTab = iBase;
+ return i;
}
@@ -91721,18 +94583,19 @@ static int xferCompatibleCollation(const char *z1, const char *z2){
** * The same DESC and ASC markings occurs on all columns
** * The same onError processing (OE_Abort, OE_Ignore, etc)
** * The same collating sequence on each column
+** * The index has the exact same WHERE clause
*/
static int xferCompatibleIndex(Index *pDest, Index *pSrc){
int i;
assert( pDest && pSrc );
assert( pDest->pTable!=pSrc->pTable );
- if( pDest->nColumn!=pSrc->nColumn ){
+ if( pDest->nKeyCol!=pSrc->nKeyCol ){
return 0; /* Different number of columns */
}
if( pDest->onError!=pSrc->onError ){
return 0; /* Different conflict resolution strategies */
}
- for(i=0; i<pSrc->nColumn; i++){
+ for(i=0; i<pSrc->nKeyCol; i++){
if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
return 0; /* Different columns indexed */
}
@@ -91743,6 +94606,9 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){
return 0; /* Different collating sequences */
}
}
+ if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){
+ return 0; /* Different WHERE clauses */
+ }
/* If no test above fails then the indices must be compatible */
return 1;
@@ -91788,10 +94654,9 @@ static int xferOptimization(
int iDbSrc; /* The database of pSrc */
int iSrc, iDest; /* Cursors from source and destination */
int addr1, addr2; /* Loop addresses */
- int emptyDestTest; /* Address of test for empty pDest */
- int emptySrcTest; /* Address of test for empty pSrc */
+ int emptyDestTest = 0; /* Address of test for empty pDest */
+ int emptySrcTest = 0; /* Address of test for empty pSrc */
Vdbe *v; /* The VDBE we are building */
- KeyInfo *pKey; /* Key information for an index */
int regAutoinc; /* Memory register used by AUTOINC */
int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
int regData, regRowid; /* Registers holding data and rowid */
@@ -91861,6 +94726,9 @@ static int xferOptimization(
if( pSrc==pDest ){
return 0; /* tab1 and tab2 may not be the same table */
}
+ if( HasRowid(pDest)!=HasRowid(pSrc) ){
+ return 0; /* source and destination must both be WITHOUT ROWID or not */
+ }
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pSrc->tabFlags & TF_Virtual ){
return 0; /* tab2 must not be a virtual table */
@@ -91898,7 +94766,7 @@ static int xferOptimization(
}
}
#ifndef SQLITE_OMIT_CHECK
- if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){
+ if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck,pDest->pCheck,-1) ){
return 0; /* Tables have different CHECK constraints. Ticket #2252 */
}
#endif
@@ -91931,7 +94799,10 @@ static int xferOptimization(
iSrc = pParse->nTab++;
iDest = pParse->nTab++;
regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
+ regData = sqlite3GetTempReg(pParse);
+ regRowid = sqlite3GetTempReg(pParse);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
+ assert( HasRowid(pDest) || destHasUniqueIdx );
if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
|| destHasUniqueIdx /* (2) */
|| (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */
@@ -91953,57 +94824,56 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0);
emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
sqlite3VdbeJumpHere(v, addr1);
- }else{
- emptyDestTest = 0;
}
- sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
- emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
- regData = sqlite3GetTempReg(pParse);
- regRowid = sqlite3GetTempReg(pParse);
- if( pDest->iPKey>=0 ){
- addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
- onError, "PRIMARY KEY must be unique", P4_STATIC);
- sqlite3VdbeJumpHere(v, addr2);
- autoIncStep(pParse, regAutoinc, regRowid);
- }else if( pDest->pIndex==0 ){
- addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
+ if( HasRowid(pSrc) ){
+ sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
+ emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
+ if( pDest->iPKey>=0 ){
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
+ addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
+ sqlite3RowidConstraint(pParse, onError, pDest);
+ sqlite3VdbeJumpHere(v, addr2);
+ autoIncStep(pParse, regAutoinc, regRowid);
+ }else if( pDest->pIndex==0 ){
+ addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
+ }else{
+ addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
+ assert( (pDest->tabFlags & TF_Autoincrement)==0 );
+ }
+ sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
+ sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
+ sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
+ sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
+ sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
+ sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
}else{
- addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- assert( (pDest->tabFlags & TF_Autoincrement)==0 );
+ sqlite3TableLock(pParse, iDbDest, pDest->tnum, 1, pDest->zName);
+ sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName);
}
- sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
- sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
- sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
- sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
- sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
}
assert( pSrcIdx );
- sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
- sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
- pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx);
- sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc,
- (char*)pKey, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeAddOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc);
+ sqlite3VdbeSetP4KeyInfo(pParse, pSrcIdx);
VdbeComment((v, "%s", pSrcIdx->zName));
- pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
- sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,
- (char*)pKey, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest);
+ sqlite3VdbeSetP4KeyInfo(pParse, pDestIdx);
+ sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
sqlite3VdbeJumpHere(v, addr1);
+ sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
+ sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
}
sqlite3VdbeJumpHere(v, emptySrcTest);
sqlite3ReleaseTempReg(pParse, regRowid);
sqlite3ReleaseTempReg(pParse, regData);
- sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
- sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
if( emptyDestTest ){
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);
sqlite3VdbeJumpHere(v, emptyDestTest);
@@ -92655,11 +95525,14 @@ struct sqlite3_api_routines {
** extension */
# define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v;
+# define SQLITE_EXTENSION_INIT3 \
+ extern const sqlite3_api_routines *sqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
+# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* _SQLITE3EXT_H_ */
@@ -93317,6 +96190,35 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
}
/*
+** Cancel a prior call to sqlite3_auto_extension. Remove xInit from the
+** set of routines that is invoked for each new database connection, if it
+** is currently on the list. If xInit is not on the list, then this
+** routine is a no-op.
+**
+** Return 1 if xInit was found on the list and removed. Return 0 if xInit
+** was not on the list.
+*/
+SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){
+#if SQLITE_THREADSAFE
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+#endif
+ int i;
+ int n = 0;
+ wsdAutoextInit;
+ sqlite3_mutex_enter(mutex);
+ for(i=wsdAutoext.nExt-1; i>=0; i--){
+ if( wsdAutoext.aExt[i]==xInit ){
+ wsdAutoext.nExt--;
+ wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
+ n++;
+ break;
+ }
+ }
+ sqlite3_mutex_leave(mutex);
+ return n;
+}
+
+/*
** Reset the automatic extension loading mechanism.
*/
SQLITE_API void sqlite3_reset_auto_extension(void){
@@ -93392,6 +96294,462 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
** This file contains code used to implement the PRAGMA command.
*/
+#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
+# if defined(__APPLE__)
+# define SQLITE_ENABLE_LOCKING_STYLE 1
+# else
+# define SQLITE_ENABLE_LOCKING_STYLE 0
+# endif
+#endif
+
+/***************************************************************************
+** The next block of code, including the PragTyp_XXXX macro definitions and
+** the aPragmaName[] object is composed of generated code. DO NOT EDIT.
+**
+** To add new pragmas, edit the code in ../tool/mkpragmatab.tcl and rerun
+** that script. Then copy/paste the output in place of the following:
+*/
+#define PragTyp_HEADER_VALUE 0
+#define PragTyp_AUTO_VACUUM 1
+#define PragTyp_FLAG 2
+#define PragTyp_BUSY_TIMEOUT 3
+#define PragTyp_CACHE_SIZE 4
+#define PragTyp_CASE_SENSITIVE_LIKE 5
+#define PragTyp_COLLATION_LIST 6
+#define PragTyp_COMPILE_OPTIONS 7
+#define PragTyp_DATA_STORE_DIRECTORY 8
+#define PragTyp_DATABASE_LIST 9
+#define PragTyp_DEFAULT_CACHE_SIZE 10
+#define PragTyp_ENCODING 11
+#define PragTyp_FOREIGN_KEY_CHECK 12
+#define PragTyp_FOREIGN_KEY_LIST 13
+#define PragTyp_INCREMENTAL_VACUUM 14
+#define PragTyp_INDEX_INFO 15
+#define PragTyp_INDEX_LIST 16
+#define PragTyp_INTEGRITY_CHECK 17
+#define PragTyp_JOURNAL_MODE 18
+#define PragTyp_JOURNAL_SIZE_LIMIT 19
+#define PragTyp_LOCK_PROXY_FILE 20
+#define PragTyp_LOCKING_MODE 21
+#define PragTyp_PAGE_COUNT 22
+#define PragTyp_MMAP_SIZE 23
+#define PragTyp_PAGE_SIZE 24
+#define PragTyp_SECURE_DELETE 25
+#define PragTyp_SHRINK_MEMORY 26
+#define PragTyp_SOFT_HEAP_LIMIT 27
+#define PragTyp_STATS 28
+#define PragTyp_SYNCHRONOUS 29
+#define PragTyp_TABLE_INFO 30
+#define PragTyp_TEMP_STORE 31
+#define PragTyp_TEMP_STORE_DIRECTORY 32
+#define PragTyp_WAL_AUTOCHECKPOINT 33
+#define PragTyp_WAL_CHECKPOINT 34
+#define PragTyp_ACTIVATE_EXTENSIONS 35
+#define PragTyp_HEXKEY 36
+#define PragTyp_KEY 37
+#define PragTyp_REKEY 38
+#define PragTyp_LOCK_STATUS 39
+#define PragTyp_PARSER_TRACE 40
+#define PragFlag_NeedSchema 0x01
+static const struct sPragmaNames {
+ const char *const zName; /* Name of pragma */
+ u8 ePragTyp; /* PragTyp_XXX value */
+ u8 mPragFlag; /* Zero or more PragFlag_XXX values */
+ u32 iArg; /* Extra argument */
+} aPragmaNames[] = {
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
+ { /* zName: */ "activate_extensions",
+ /* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
+ { /* zName: */ "application_id",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_AUTOVACUUM)
+ { /* zName: */ "auto_vacuum",
+ /* ePragTyp: */ PragTyp_AUTO_VACUUM,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if !defined(SQLITE_OMIT_AUTOMATIC_INDEX)
+ { /* zName: */ "automatic_index",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_AutoIndex },
+#endif
+#endif
+ { /* zName: */ "busy_timeout",
+ /* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+ { /* zName: */ "cache_size",
+ /* ePragTyp: */ PragTyp_CACHE_SIZE,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "cache_spill",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_CacheSpill },
+#endif
+ { /* zName: */ "case_sensitive_like",
+ /* ePragTyp: */ PragTyp_CASE_SENSITIVE_LIKE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "checkpoint_fullfsync",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_CkptFullFSync },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+ { /* zName: */ "collation_list",
+ /* ePragTyp: */ PragTyp_COLLATION_LIST,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
+ { /* zName: */ "compile_options",
+ /* ePragTyp: */ PragTyp_COMPILE_OPTIONS,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "count_changes",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_CountRows },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_OS_WIN
+ { /* zName: */ "data_store_directory",
+ /* ePragTyp: */ PragTyp_DATA_STORE_DIRECTORY,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+ { /* zName: */ "database_list",
+ /* ePragTyp: */ PragTyp_DATABASE_LIST,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
+ { /* zName: */ "default_cache_size",
+ /* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+ { /* zName: */ "defer_foreign_keys",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_DeferFKs },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "empty_result_callbacks",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_NullCallback },
+#endif
+#if !defined(SQLITE_OMIT_UTF16)
+ { /* zName: */ "encoding",
+ /* ePragTyp: */ PragTyp_ENCODING,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+ { /* zName: */ "foreign_key_check",
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FOREIGN_KEY)
+ { /* zName: */ "foreign_key_list",
+ /* ePragTyp: */ PragTyp_FOREIGN_KEY_LIST,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
+ { /* zName: */ "foreign_keys",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_ForeignKeys },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
+ { /* zName: */ "freelist_count",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "full_column_names",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_FullColNames },
+ { /* zName: */ "fullfsync",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_FullFSync },
+#endif
+#if defined(SQLITE_HAS_CODEC)
+ { /* zName: */ "hexkey",
+ /* ePragTyp: */ PragTyp_HEXKEY,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+ { /* zName: */ "hexrekey",
+ /* ePragTyp: */ PragTyp_HEXKEY,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if !defined(SQLITE_OMIT_CHECK)
+ { /* zName: */ "ignore_check_constraints",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_IgnoreChecks },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_AUTOVACUUM)
+ { /* zName: */ "incremental_vacuum",
+ /* ePragTyp: */ PragTyp_INCREMENTAL_VACUUM,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+ { /* zName: */ "index_info",
+ /* ePragTyp: */ PragTyp_INDEX_INFO,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+ { /* zName: */ "index_list",
+ /* ePragTyp: */ PragTyp_INDEX_LIST,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
+ { /* zName: */ "integrity_check",
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+ { /* zName: */ "journal_mode",
+ /* ePragTyp: */ PragTyp_JOURNAL_MODE,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+ { /* zName: */ "journal_size_limit",
+ /* ePragTyp: */ PragTyp_JOURNAL_SIZE_LIMIT,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if defined(SQLITE_HAS_CODEC)
+ { /* zName: */ "key",
+ /* ePragTyp: */ PragTyp_KEY,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "legacy_file_format",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_LegacyFileFmt },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
+ { /* zName: */ "lock_proxy_file",
+ /* ePragTyp: */ PragTyp_LOCK_PROXY_FILE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+ { /* zName: */ "lock_status",
+ /* ePragTyp: */ PragTyp_LOCK_STATUS,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+ { /* zName: */ "locking_mode",
+ /* ePragTyp: */ PragTyp_LOCKING_MODE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+ { /* zName: */ "max_page_count",
+ /* ePragTyp: */ PragTyp_PAGE_COUNT,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+ { /* zName: */ "mmap_size",
+ /* ePragTyp: */ PragTyp_MMAP_SIZE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+ { /* zName: */ "page_count",
+ /* ePragTyp: */ PragTyp_PAGE_COUNT,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+ { /* zName: */ "page_size",
+ /* ePragTyp: */ PragTyp_PAGE_SIZE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if defined(SQLITE_DEBUG)
+ { /* zName: */ "parser_trace",
+ /* ePragTyp: */ PragTyp_PARSER_TRACE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "query_only",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_QueryOnly },
+#endif
+#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
+ { /* zName: */ "quick_check",
+ /* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "read_uncommitted",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_ReadUncommitted },
+ { /* zName: */ "recursive_triggers",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_RecTriggers },
+#endif
+#if defined(SQLITE_HAS_CODEC)
+ { /* zName: */ "rekey",
+ /* ePragTyp: */ PragTyp_REKEY,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "reverse_unordered_selects",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_ReverseOrder },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
+ { /* zName: */ "schema_version",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+ { /* zName: */ "secure_delete",
+ /* ePragTyp: */ PragTyp_SECURE_DELETE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "short_column_names",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_ShortColNames },
+#endif
+ { /* zName: */ "shrink_memory",
+ /* ePragTyp: */ PragTyp_SHRINK_MEMORY,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+ { /* zName: */ "soft_heap_limit",
+ /* ePragTyp: */ PragTyp_SOFT_HEAP_LIMIT,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if defined(SQLITE_DEBUG)
+ { /* zName: */ "sql_trace",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_SqlTrace },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+ { /* zName: */ "stats",
+ /* ePragTyp: */ PragTyp_STATS,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+ { /* zName: */ "synchronous",
+ /* ePragTyp: */ PragTyp_SYNCHRONOUS,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+ { /* zName: */ "table_info",
+ /* ePragTyp: */ PragTyp_TABLE_INFO,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
+ { /* zName: */ "temp_store",
+ /* ePragTyp: */ PragTyp_TEMP_STORE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+ { /* zName: */ "temp_store_directory",
+ /* ePragTyp: */ PragTyp_TEMP_STORE_DIRECTORY,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
+ { /* zName: */ "user_version",
+ /* ePragTyp: */ PragTyp_HEADER_VALUE,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+#if defined(SQLITE_DEBUG)
+ { /* zName: */ "vdbe_addoptrace",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_VdbeAddopTrace },
+ { /* zName: */ "vdbe_debug",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_SqlTrace|SQLITE_VdbeListing|SQLITE_VdbeTrace },
+ { /* zName: */ "vdbe_eqp",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_VdbeEQP },
+ { /* zName: */ "vdbe_listing",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_VdbeListing },
+ { /* zName: */ "vdbe_trace",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_VdbeTrace },
+#endif
+#endif
+#if !defined(SQLITE_OMIT_WAL)
+ { /* zName: */ "wal_autocheckpoint",
+ /* ePragTyp: */ PragTyp_WAL_AUTOCHECKPOINT,
+ /* ePragFlag: */ 0,
+ /* iArg: */ 0 },
+ { /* zName: */ "wal_checkpoint",
+ /* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 0 },
+#endif
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
+ { /* zName: */ "writable_schema",
+ /* ePragTyp: */ PragTyp_FLAG,
+ /* ePragFlag: */ 0,
+ /* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
+#endif
+};
+/* Number of pragmas: 56 on by default, 69 total. */
+/* End of the automatically generated pragma table.
+***************************************************************************/
+
/*
** Interpret the given string as a safety level. Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
@@ -93537,92 +96895,35 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
}
-#ifndef SQLITE_OMIT_FLAG_PRAGMAS
-/*
-** Check to see if zRight and zLeft refer to a pragma that queries
-** or changes one of the flags in db->flags. Return 1 if so and 0 if not.
-** Also, implement the pragma.
-*/
-static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
- static const struct sPragmaType {
- const char *zName; /* Name of the pragma */
- int mask; /* Mask for the db->flags value */
- } aPragma[] = {
- { "full_column_names", SQLITE_FullColNames },
- { "short_column_names", SQLITE_ShortColNames },
- { "count_changes", SQLITE_CountRows },
- { "empty_result_callbacks", SQLITE_NullCallback },
- { "legacy_file_format", SQLITE_LegacyFileFmt },
- { "fullfsync", SQLITE_FullFSync },
- { "checkpoint_fullfsync", SQLITE_CkptFullFSync },
- { "reverse_unordered_selects", SQLITE_ReverseOrder },
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
- { "automatic_index", SQLITE_AutoIndex },
-#endif
-#ifdef SQLITE_DEBUG
- { "sql_trace", SQLITE_SqlTrace },
- { "vdbe_listing", SQLITE_VdbeListing },
- { "vdbe_trace", SQLITE_VdbeTrace },
- { "vdbe_addoptrace", SQLITE_VdbeAddopTrace},
- { "vdbe_debug", SQLITE_SqlTrace | SQLITE_VdbeListing
- | SQLITE_VdbeTrace },
-#endif
-#ifndef SQLITE_OMIT_CHECK
- { "ignore_check_constraints", SQLITE_IgnoreChecks },
-#endif
- /* The following is VERY experimental */
- { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode },
-
- /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted
- ** flag if there are any active statements. */
- { "read_uncommitted", SQLITE_ReadUncommitted },
- { "recursive_triggers", SQLITE_RecTriggers },
-
- /* This flag may only be set if both foreign-key and trigger support
- ** are present in the build. */
-#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
- { "foreign_keys", SQLITE_ForeignKeys },
-#endif
- };
- int i;
- const struct sPragmaType *p;
- for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){
- if( sqlite3StrICmp(zLeft, p->zName)==0 ){
- sqlite3 *db = pParse->db;
- Vdbe *v;
- v = sqlite3GetVdbe(pParse);
- assert( v!=0 ); /* Already allocated by sqlite3Pragma() */
- if( ALWAYS(v) ){
- if( zRight==0 ){
- returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 );
- }else{
- int mask = p->mask; /* Mask of bits to set or clear. */
- if( db->autoCommit==0 ){
- /* Foreign key support may not be enabled or disabled while not
- ** in auto-commit mode. */
- mask &= ~(SQLITE_ForeignKeys);
- }
-
- if( sqlite3GetBoolean(zRight, 0) ){
- db->flags |= mask;
- }else{
- db->flags &= ~mask;
- }
- /* Many of the flag-pragmas modify the code generated by the SQL
- ** compiler (eg. count_changes). So add an opcode to expire all
- ** compiled SQL statements after modifying a pragma value.
- */
- sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
- }
+/*
+** Set the safety_level and pager flags for pager iDb. Or if iDb<0
+** set these values for all pagers.
+*/
+#ifndef SQLITE_OMIT_PAGER_PRAGMAS
+static void setAllPagerFlags(sqlite3 *db){
+ if( db->autoCommit ){
+ Db *pDb = db->aDb;
+ int n = db->nDb;
+ assert( SQLITE_FullFSync==PAGER_FULLFSYNC );
+ assert( SQLITE_CkptFullFSync==PAGER_CKPT_FULLFSYNC );
+ assert( SQLITE_CacheSpill==PAGER_CACHESPILL );
+ assert( (PAGER_FULLFSYNC | PAGER_CKPT_FULLFSYNC | PAGER_CACHESPILL)
+ == PAGER_FLAGS_MASK );
+ assert( (pDb->safety_level & PAGER_SYNCHRONOUS_MASK)==pDb->safety_level );
+ while( (n--) > 0 ){
+ if( pDb->pBt ){
+ sqlite3BtreeSetPagerFlags(pDb->pBt,
+ pDb->safety_level | (db->flags & PAGER_FLAGS_MASK) );
}
-
- return 1;
+ pDb++;
}
}
- return 0;
}
-#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
+#else
+# define setAllPagerFlags(X) /* no-op */
+#endif
+
/*
** Return a human-readable name for a constraint resolution action.
@@ -93693,8 +96994,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
char *zRight = 0; /* Nul-terminated UTF-8 string <value>, or NULL */
const char *zDb = 0; /* The database name */
Token *pId; /* Pointer to <id> token */
- int iDb; /* Database index for <database> */
char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */
+ int iDb; /* Database index for <database> */
+ int lwr, upr, mid; /* Binary search bounds */
int rc; /* return value form SQLITE_FCNTL_PRAGMA */
sqlite3 *db = pParse->db; /* The database connection */
Db *pDb; /* The specific database being pragmaed */
@@ -93750,16 +97052,41 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
sqlite3_free(aFcntl[0]);
}
- }else if( rc!=SQLITE_NOTFOUND ){
+ goto pragma_out;
+ }
+ if( rc!=SQLITE_NOTFOUND ){
if( aFcntl[0] ){
sqlite3ErrorMsg(pParse, "%s", aFcntl[0]);
sqlite3_free(aFcntl[0]);
}
pParse->nErr++;
pParse->rc = rc;
- }else
-
-
+ goto pragma_out;
+ }
+
+ /* Locate the pragma in the lookup table */
+ lwr = 0;
+ upr = ArraySize(aPragmaNames)-1;
+ while( lwr<=upr ){
+ mid = (lwr+upr)/2;
+ rc = sqlite3_stricmp(zLeft, aPragmaNames[mid].zName);
+ if( rc==0 ) break;
+ if( rc<0 ){
+ upr = mid - 1;
+ }else{
+ lwr = mid + 1;
+ }
+ }
+ if( lwr>upr ) goto pragma_out;
+
+ /* Make sure the database schema is loaded if the pragma requires that */
+ if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ }
+
+ /* Jump to the appropriate pragma handler */
+ switch( aPragmaNames[mid].ePragTyp ){
+
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
/*
** PRAGMA [database.]default_cache_size
@@ -93777,7 +97104,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** size. But continue to take the absolute value of the default cache
** size of historical compatibility.
*/
- if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
+ case PragTyp_DEFAULT_CACHE_SIZE: {
static const VdbeOpList getCacheSize[] = {
{ OP_Transaction, 0, 0, 0}, /* 0 */
{ OP_ReadCookie, 0, 1, BTREE_DEFAULT_CACHE_SIZE}, /* 1 */
@@ -93790,7 +97117,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
{ OP_ResultRow, 1, 1, 0},
};
int addr;
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeUsesBtree(v, iDb);
if( !zRight ){
sqlite3VdbeSetNumCols(v, 1);
@@ -93809,7 +97135,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
}
- }else
+ break;
+ }
#endif /* !SQLITE_OMIT_PAGER_PRAGMAS && !SQLITE_OMIT_DEPRECATED */
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -93822,7 +97149,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** database page size value. The value can only be set if
** the database has not yet been created.
*/
- if( sqlite3StrICmp(zLeft,"page_size")==0 ){
+ case PragTyp_PAGE_SIZE: {
Btree *pBt = pDb->pBt;
assert( pBt!=0 );
if( !zRight ){
@@ -93837,7 +97164,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
db->mallocFailed = 1;
}
}
- }else
+ break;
+ }
/*
** PRAGMA [database.]secure_delete
@@ -93847,7 +97175,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** secure_delete flag. The second form changes the secure_delete
** flag setting and reports thenew value.
*/
- if( sqlite3StrICmp(zLeft,"secure_delete")==0 ){
+ case PragTyp_SECURE_DELETE: {
Btree *pBt = pDb->pBt;
int b = -1;
assert( pBt!=0 );
@@ -93862,7 +97190,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
b = sqlite3BtreeSecureDelete(pBt, b);
returnSingleInt(pParse, "secure_delete", b);
- }else
+ break;
+ }
/*
** PRAGMA [database.]max_page_count
@@ -93881,11 +97210,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
**
** Return the number of pages in the specified database.
*/
- if( sqlite3StrICmp(zLeft,"page_count")==0
- || sqlite3StrICmp(zLeft,"max_page_count")==0
- ){
+ case PragTyp_PAGE_COUNT: {
int iReg;
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3CodeVerifySchema(pParse, iDb);
iReg = ++pParse->nMem;
if( sqlite3Tolower(zLeft[0])=='p' ){
@@ -93897,13 +97223,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
- }else
+ break;
+ }
/*
** PRAGMA [database.]locking_mode
** PRAGMA [database.]locking_mode = (normal|exclusive)
*/
- if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){
+ case PragTyp_LOCKING_MODE: {
const char *zRet = "normal";
int eMode = getLockingMode(zRight);
@@ -93936,7 +97263,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
eMode = sqlite3PagerLockingMode(pPager, eMode);
}
- assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE);
+ assert( eMode==PAGER_LOCKINGMODE_NORMAL
+ || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
zRet = "exclusive";
}
@@ -93944,25 +97272,18 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- }else
+ break;
+ }
/*
** PRAGMA [database.]journal_mode
** PRAGMA [database.]journal_mode =
** (delete|persist|off|truncate|memory|wal|off)
*/
- if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
+ case PragTyp_JOURNAL_MODE: {
int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */
int ii; /* Loop counter */
- /* Force the schema to be loaded on all databases. This causes all
- ** database files to be opened and the journal_modes set. This is
- ** necessary because subsequent processing must know if the databases
- ** are in WAL mode. */
- if( sqlite3ReadSchema(pParse) ){
- goto pragma_out;
- }
-
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
@@ -93994,7 +97315,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- }else
+ break;
+ }
/*
** PRAGMA [database.]journal_size_limit
@@ -94002,16 +97324,17 @@ SQLITE_PRIVATE void sqlite3Pragma(
**
** Get or set the size limit on rollback journal files.
*/
- if( sqlite3StrICmp(zLeft,"journal_size_limit")==0 ){
+ case PragTyp_JOURNAL_SIZE_LIMIT: {
Pager *pPager = sqlite3BtreePager(pDb->pBt);
i64 iLimit = -2;
if( zRight ){
- sqlite3Atoi64(zRight, &iLimit, 1000000, SQLITE_UTF8);
+ sqlite3Atoi64(zRight, &iLimit, sqlite3Strlen30(zRight), SQLITE_UTF8);
if( iLimit<-1 ) iLimit = -1;
}
iLimit = sqlite3PagerJournalSizeLimit(pPager, iLimit);
returnSingleInt(pParse, "journal_size_limit", iLimit);
- }else
+ break;
+ }
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
@@ -94023,57 +97346,47 @@ SQLITE_PRIVATE void sqlite3Pragma(
** The value is one of: 0 NONE 1 FULL 2 INCREMENTAL
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){
+ case PragTyp_AUTO_VACUUM: {
Btree *pBt = pDb->pBt;
assert( pBt!=0 );
- if( sqlite3ReadSchema(pParse) ){
- goto pragma_out;
- }
if( !zRight ){
- int auto_vacuum;
- if( ALWAYS(pBt) ){
- auto_vacuum = sqlite3BtreeGetAutoVacuum(pBt);
- }else{
- auto_vacuum = SQLITE_DEFAULT_AUTOVACUUM;
- }
- returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
+ returnSingleInt(pParse, "auto_vacuum", sqlite3BtreeGetAutoVacuum(pBt));
}else{
int eAuto = getAutoVacuum(zRight);
assert( eAuto>=0 && eAuto<=2 );
db->nextAutovac = (u8)eAuto;
- if( ALWAYS(eAuto>=0) ){
- /* Call SetAutoVacuum() to set initialize the internal auto and
- ** incr-vacuum flags. This is required in case this connection
- ** creates the database file. It is important that it is created
- ** as an auto-vacuum capable db.
+ /* Call SetAutoVacuum() to set initialize the internal auto and
+ ** incr-vacuum flags. This is required in case this connection
+ ** creates the database file. It is important that it is created
+ ** as an auto-vacuum capable db.
+ */
+ rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
+ if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
+ /* When setting the auto_vacuum mode to either "full" or
+ ** "incremental", write the value of meta[6] in the database
+ ** file. Before writing to meta[6], check that meta[3] indicates
+ ** that this really is an auto-vacuum capable database.
*/
- rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto);
- if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){
- /* When setting the auto_vacuum mode to either "full" or
- ** "incremental", write the value of meta[6] in the database
- ** file. Before writing to meta[6], check that meta[3] indicates
- ** that this really is an auto-vacuum capable database.
- */
- static const VdbeOpList setMeta6[] = {
- { OP_Transaction, 0, 1, 0}, /* 0 */
- { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
- { OP_If, 1, 0, 0}, /* 2 */
- { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
- { OP_Integer, 0, 1, 0}, /* 4 */
- { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
- };
- int iAddr;
- iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
- sqlite3VdbeChangeP1(v, iAddr, iDb);
- sqlite3VdbeChangeP1(v, iAddr+1, iDb);
- sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
- sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
- sqlite3VdbeChangeP1(v, iAddr+5, iDb);
- sqlite3VdbeUsesBtree(v, iDb);
- }
+ static const VdbeOpList setMeta6[] = {
+ { OP_Transaction, 0, 1, 0}, /* 0 */
+ { OP_ReadCookie, 0, 1, BTREE_LARGEST_ROOT_PAGE},
+ { OP_If, 1, 0, 0}, /* 2 */
+ { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */
+ { OP_Integer, 0, 1, 0}, /* 4 */
+ { OP_SetCookie, 0, BTREE_INCR_VACUUM, 1}, /* 5 */
+ };
+ int iAddr;
+ iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6);
+ sqlite3VdbeChangeP1(v, iAddr, iDb);
+ sqlite3VdbeChangeP1(v, iAddr+1, iDb);
+ sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
+ sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
+ sqlite3VdbeChangeP1(v, iAddr+5, iDb);
+ sqlite3VdbeUsesBtree(v, iDb);
}
}
- }else
+ break;
+ }
#endif
/*
@@ -94082,11 +97395,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
** Do N steps of incremental vacuuming on a database.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){
+ case PragTyp_INCREMENTAL_VACUUM: {
int iLimit, addr;
- if( sqlite3ReadSchema(pParse) ){
- goto pragma_out;
- }
if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
iLimit = 0x7fffffff;
}
@@ -94097,7 +97407,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr);
sqlite3VdbeJumpHere(v, addr);
- }else
+ break;
+ }
#endif
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
@@ -94112,8 +97423,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** number of pages is adjusted so that the cache uses -N kibibytes
** of memory.
*/
- if( sqlite3StrICmp(zLeft,"cache_size")==0 ){
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ case PragTyp_CACHE_SIZE: {
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( !zRight ){
returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size);
@@ -94122,7 +97432,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
}
- }else
+ break;
+ }
/*
** PRAGMA [database.]mmap_size(N)
@@ -94138,12 +97449,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
** as little or as much as it wants. Except, if N is set to 0 then the
** upper layers will never invoke the xFetch interfaces to the VFS.
*/
- if( sqlite3StrICmp(zLeft,"mmap_size")==0 ){
+ case PragTyp_MMAP_SIZE: {
sqlite3_int64 sz;
+#if SQLITE_MAX_MMAP_SIZE>0
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
if( zRight ){
int ii;
- sqlite3Atoi64(zRight, &sz, 1000, SQLITE_UTF8);
+ sqlite3Atoi64(zRight, &sz, sqlite3Strlen30(zRight), SQLITE_UTF8);
if( sz<0 ) sz = sqlite3GlobalConfig.szMmap;
if( pId2->n==0 ) db->szMmap = sz;
for(ii=db->nDb-1; ii>=0; ii--){
@@ -94153,13 +97465,19 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
sz = -1;
- if( sqlite3_file_control(db,zDb,SQLITE_FCNTL_MMAP_SIZE,&sz)==SQLITE_OK ){
-#if SQLITE_MAX_MMAP_SIZE==0
- sz = 0;
+ rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_MMAP_SIZE, &sz);
+#else
+ sz = 0;
+ rc = SQLITE_OK;
#endif
+ if( rc==SQLITE_OK ){
returnSingleInt(pParse, "mmap_size", sz);
+ }else if( rc!=SQLITE_NOTFOUND ){
+ pParse->nErr++;
+ pParse->rc = rc;
}
- }else
+ break;
+ }
/*
** PRAGMA temp_store
@@ -94172,13 +97490,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
** Note that it is possible for the library compile-time options to
** override this setting
*/
- if( sqlite3StrICmp(zLeft, "temp_store")==0 ){
+ case PragTyp_TEMP_STORE: {
if( !zRight ){
returnSingleInt(pParse, "temp_store", db->temp_store);
}else{
changeTempStorage(pParse, zRight);
}
- }else
+ break;
+ }
/*
** PRAGMA temp_store_directory
@@ -94190,7 +97509,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** If temporary directory is changed, then invalidateTempStorage.
**
*/
- if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){
+ case PragTyp_TEMP_STORE_DIRECTORY: {
if( !zRight ){
if( sqlite3_temp_directory ){
sqlite3VdbeSetNumCols(v, 1);
@@ -94223,7 +97542,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
#endif /* SQLITE_OMIT_WSD */
}
- }else
+ break;
+ }
#if SQLITE_OS_WIN
/*
@@ -94239,7 +97559,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** by this setting, regardless of its value.
**
*/
- if( sqlite3StrICmp(zLeft, "data_store_directory")==0 ){
+ case PragTyp_DATA_STORE_DIRECTORY: {
if( !zRight ){
if( sqlite3_data_directory ){
sqlite3VdbeSetNumCols(v, 1);
@@ -94266,26 +97586,20 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
#endif /* SQLITE_OMIT_WSD */
}
- }else
+ break;
+ }
#endif
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-# if defined(__APPLE__)
-# define SQLITE_ENABLE_LOCKING_STYLE 1
-# else
-# define SQLITE_ENABLE_LOCKING_STYLE 0
-# endif
-#endif
#if SQLITE_ENABLE_LOCKING_STYLE
/*
- ** PRAGMA [database.]lock_proxy_file
- ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path"
- **
- ** Return or set the value of the lock_proxy_file flag. Changing
- ** the value sets a specific file to be used for database access locks.
- **
- */
- if( sqlite3StrICmp(zLeft, "lock_proxy_file")==0 ){
+ ** PRAGMA [database.]lock_proxy_file
+ ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path"
+ **
+ ** Return or set the value of the lock_proxy_file flag. Changing
+ ** the value sets a specific file to be used for database access locks.
+ **
+ */
+ case PragTyp_LOCK_PROXY_FILE: {
if( !zRight ){
Pager *pPager = sqlite3BtreePager(pDb->pBt);
char *proxy_file_path = NULL;
@@ -94316,7 +97630,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
goto pragma_out;
}
}
- }else
+ break;
+ }
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
/*
@@ -94328,8 +97643,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** default value will be restored the next time the database is
** opened.
*/
- if( sqlite3StrICmp(zLeft,"synchronous")==0 ){
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ case PragTyp_SYNCHRONOUS: {
if( !zRight ){
returnSingleInt(pParse, "synchronous", pDb->safety_level-1);
}else{
@@ -94338,16 +97652,42 @@ SQLITE_PRIVATE void sqlite3Pragma(
"Safety level may not be changed inside a transaction");
}else{
pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
+ setAllPagerFlags(db);
}
}
- }else
+ break;
+ }
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
- if( flagPragma(pParse, zLeft, zRight) ){
- /* The flagPragma() subroutine also generates any necessary code
- ** there is nothing more to do here */
- }else
+ case PragTyp_FLAG: {
+ if( zRight==0 ){
+ returnSingleInt(pParse, aPragmaNames[mid].zName,
+ (db->flags & aPragmaNames[mid].iArg)!=0 );
+ }else{
+ int mask = aPragmaNames[mid].iArg; /* Mask of bits to set or clear. */
+ if( db->autoCommit==0 ){
+ /* Foreign key support may not be enabled or disabled while not
+ ** in auto-commit mode. */
+ mask &= ~(SQLITE_ForeignKeys);
+ }
+
+ if( sqlite3GetBoolean(zRight, 0) ){
+ db->flags |= mask;
+ }else{
+ db->flags &= ~mask;
+ if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
+ }
+
+ /* Many of the flag-pragmas modify the code generated by the SQL
+ ** compiler (eg. count_changes). So add an opcode to expire all
+ ** compiled SQL statements after modifying a pragma value.
+ */
+ sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
+ setAllPagerFlags(db);
+ }
+ break;
+ }
#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS
@@ -94363,16 +97703,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
** notnull: True if 'NOT NULL' is part of column declaration
** dflt_value: The default value for the column, if any.
*/
- if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){
+ case PragTyp_TABLE_INFO: if( zRight ){
Table *pTab;
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
int i, k;
int nHidden = 0;
Column *pCol;
- Index *pPk;
- for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab);
sqlite3VdbeSetNumCols(v, 6);
pParse->nMem = 6;
sqlite3CodeVerifySchema(pParse, iDb);
@@ -94409,12 +97747,42 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
}
}
- }else
+ }
+ break;
+
+ case PragTyp_STATS: {
+ Index *pIdx;
+ HashElem *i;
+ v = sqlite3GetVdbe(pParse);
+ sqlite3VdbeSetNumCols(v, 4);
+ pParse->nMem = 4;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC);
+ for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
+ Table *pTab = sqliteHashData(i);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
+ sqlite3VdbeAddOp2(v, OP_Integer,
+ (int)sqlite3LogEstToInt(pTab->szTabRow), 3);
+ sqlite3VdbeAddOp2(v, OP_Integer, (int)pTab->nRowEst, 4);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_Integer,
+ (int)sqlite3LogEstToInt(pIdx->szIdxRow), 3);
+ sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
+ }
+ }
+ }
+ break;
- if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){
+ case PragTyp_INDEX_INFO: if( zRight ){
Index *pIdx;
Table *pTab;
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
pIdx = sqlite3FindIndex(db, zRight, zDb);
if( pIdx ){
int i;
@@ -94425,8 +97793,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
- for(i=0; i<pIdx->nColumn; i++){
- int cnum = pIdx->aiColumn[i];
+ for(i=0; i<pIdx->nKeyCol; i++){
+ i16 cnum = pIdx->aiColumn[i];
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
assert( pTab->nCol>cnum );
@@ -94434,39 +97802,34 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
}
}
- }else
+ }
+ break;
- if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){
+ case PragTyp_INDEX_LIST: if( zRight ){
Index *pIdx;
Table *pTab;
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ int i;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
v = sqlite3GetVdbe(pParse);
- pIdx = pTab->pIndex;
- if( pIdx ){
- int i = 0;
- sqlite3VdbeSetNumCols(v, 3);
- pParse->nMem = 3;
- sqlite3CodeVerifySchema(pParse, iDb);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
- while(pIdx){
- sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
- ++i;
- pIdx = pIdx->pNext;
- }
+ sqlite3VdbeSetNumCols(v, 3);
+ pParse->nMem = 3;
+ sqlite3CodeVerifySchema(pParse, iDb);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
+ for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
+ sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
}
}
- }else
+ }
+ break;
- if( sqlite3StrICmp(zLeft, "database_list")==0 ){
+ case PragTyp_DATABASE_LIST: {
int i;
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
@@ -94481,9 +97844,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3BtreeGetFilename(db->aDb[i].pBt), 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
}
- }else
+ }
+ break;
- if( sqlite3StrICmp(zLeft, "collation_list")==0 ){
+ case PragTyp_COLLATION_LIST: {
int i = 0;
HashElem *p;
sqlite3VdbeSetNumCols(v, 2);
@@ -94496,14 +97860,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
- }else
+ }
+ break;
#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */
#ifndef SQLITE_OMIT_FOREIGN_KEY
- if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){
+ case PragTyp_FOREIGN_KEY_LIST: if( zRight ){
FKey *pFK;
Table *pTab;
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
v = sqlite3GetVdbe(pParse);
@@ -94543,12 +97907,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
}
- }else
+ }
+ break;
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef SQLITE_OMIT_FOREIGN_KEY
#ifndef SQLITE_OMIT_TRIGGER
- if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
+ case PragTyp_FOREIGN_KEY_CHECK: {
FKey *pFK; /* A foreign key constraint */
Table *pTab; /* Child table contain "REFERENCES" keyword */
Table *pParent; /* Parent table that child points to */
@@ -94564,7 +97929,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
int addrOk; /* Jump here if the key is OK */
int *aiCols; /* child to parent column mapping */
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
regResult = pParse->nMem+1;
pParse->nMem += 4;
regKey = ++pParse->nMem;
@@ -94592,8 +97956,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
P4_TRANSIENT);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
- pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
- if( pParent==0 ) break;
+ pParent = sqlite3FindTable(db, pFK->zTo, zDb);
+ if( pParent==0 ) continue;
pIdx = 0;
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
@@ -94601,27 +97965,28 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( pIdx==0 ){
sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
}else{
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
- sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
}
}else{
k = 0;
break;
}
}
+ assert( pParse->nErr>0 || pFK==0 );
if( pFK ) break;
if( pParse->nTab<i ) pParse->nTab = i;
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
- pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
- assert( pParent!=0 );
+ pParent = sqlite3FindTable(db, pFK->zTo, zDb);
pIdx = 0;
aiCols = 0;
- x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
- assert( x==0 );
+ if( pParent ){
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
+ assert( x==0 );
+ }
addrOk = sqlite3VdbeMakeLabel(v);
- if( pIdx==0 ){
+ if( pParent && pIdx==0 ){
int iKey = pFK->aCol[0].iFrom;
assert( iKey>=0 && iKey<pTab->nCol );
if( iKey!=pTab->iPKey ){
@@ -94639,13 +98004,15 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else{
for(j=0; j<pFK->nCol; j++){
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
- aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
+ aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
}
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
- sqlite3VdbeChangeP4(v, -1,
- sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
- sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+ if( pParent ){
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
+ sqlite3VdbeChangeP4(v, -1,
+ sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+ }
}
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
@@ -94658,12 +98025,13 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
sqlite3VdbeJumpHere(v, addrTop);
}
- }else
+ }
+ break;
#endif /* !defined(SQLITE_OMIT_TRIGGER) */
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
#ifndef NDEBUG
- if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
+ case PragTyp_PARSER_TRACE: {
if( zRight ){
if( sqlite3GetBoolean(zRight, 0) ){
sqlite3ParserTrace(stderr, "parser: ");
@@ -94671,30 +98039,30 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3ParserTrace(0, 0);
}
}
- }else
+ }
+ break;
#endif
/* Reinstall the LIKE and GLOB functions. The variant of LIKE
** used will be case sensitive or not depending on the RHS.
*/
- if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){
+ case PragTyp_CASE_SENSITIVE_LIKE: {
if( zRight ){
sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0));
}
- }else
+ }
+ break;
#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
#endif
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
- /* Pragma "quick_check" is an experimental reduced version of
+ /* Pragma "quick_check" is reduced version of
** integrity_check designed to detect most database corruption
** without most of the overhead of a full integrity-check.
*/
- if( sqlite3StrICmp(zLeft, "integrity_check")==0
- || sqlite3StrICmp(zLeft, "quick_check")==0
- ){
+ case PragTyp_INTEGRITY_CHECK: {
int i, j, addr, mxErr;
/* Code that appears at the end of the integrity check. If no error
@@ -94724,7 +98092,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( pId2->z==0 ) iDb = -1;
/* Initialize the VDBE program */
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
pParse->nMem = 6;
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
@@ -94763,18 +98130,20 @@ SQLITE_PRIVATE void sqlite3Pragma(
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx;
- sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt);
- cnt++;
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp2(v, OP_Integer, pTab->tnum, 2+cnt);
+ VdbeComment((v, "%s", pTab->zName));
+ cnt++;
+ }
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->tnum, 2+cnt);
+ VdbeComment((v, "%s", pIdx->zName));
cnt++;
}
}
/* Make sure sufficient number of registers have been allocated */
- if( pParse->nMem < cnt+4 ){
- pParse->nMem = cnt+4;
- }
+ pParse->nMem = MAX( pParse->nMem, cnt+8 );
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
@@ -94792,77 +98161,74 @@ SQLITE_PRIVATE void sqlite3Pragma(
*/
for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
- Index *pIdx;
+ Index *pIdx, *pPk;
int loopTop;
+ int iDataCur, iIdxCur;
if( pTab->pIndex==0 ) continue;
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);
- sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
- sqlite3VdbeAddOp2(v, OP_Integer, 0, 2); /* reg(2) will count entries */
- loopTop = sqlite3VdbeAddOp2(v, OP_Rewind, 1, 0);
- sqlite3VdbeAddOp2(v, OP_AddImm, 2, 1); /* increment entry count */
+ sqlite3ExprCacheClear(pParse);
+ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead,
+ 1, 0, &iDataCur, &iIdxCur);
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- int jmp2;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
+ }
+ pParse->nMem = MAX(pParse->nMem, 8+j);
+ sqlite3VdbeAddOp2(v, OP_Rewind, iDataCur, 0);
+ loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
+ for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+ int jmp2, jmp3, jmp4;
int r1;
- static const VdbeOpList idxErr[] = {
- { OP_AddImm, 1, -1, 0},
- { OP_String8, 0, 3, 0}, /* 1 */
- { OP_Rowid, 1, 4, 0},
- { OP_String8, 0, 5, 0}, /* 3 */
- { OP_String8, 0, 6, 0}, /* 4 */
- { OP_Concat, 4, 3, 3},
- { OP_Concat, 5, 3, 3},
- { OP_Concat, 6, 3, 3},
- { OP_ResultRow, 3, 1, 0},
- { OP_IfPos, 1, 0, 0}, /* 9 */
- { OP_Halt, 0, 0, 0},
- };
- r1 = sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 0);
- jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, j+2, 0, r1, pIdx->nColumn+1);
- addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
- sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
- sqlite3VdbeChangeP4(v, addr+3, " missing from index ", P4_STATIC);
- sqlite3VdbeChangeP4(v, addr+4, pIdx->zName, P4_TRANSIENT);
- sqlite3VdbeJumpHere(v, addr+9);
+ if( pPk==pIdx ) continue;
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3);
+ sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
+ jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1,
+ pIdx->nColumn);
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, "row ", P4_STATIC);
+ sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, " missing from index ",
+ P4_STATIC);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, pIdx->zName, P4_TRANSIENT);
+ sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
+ jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
+ sqlite3VdbeAddOp0(v, OP_Halt);
+ sqlite3VdbeJumpHere(v, jmp4);
sqlite3VdbeJumpHere(v, jmp2);
+ sqlite3VdbeResolveLabel(v, jmp3);
}
- sqlite3VdbeAddOp2(v, OP_Next, 1, loopTop+1);
- sqlite3VdbeJumpHere(v, loopTop);
+ sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop);
+ sqlite3VdbeJumpHere(v, loopTop-1);
+#ifndef SQLITE_OMIT_BTREECOUNT
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0,
+ "wrong # of entries in index ", P4_STATIC);
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
- static const VdbeOpList cntIdx[] = {
- { OP_Integer, 0, 3, 0},
- { OP_Rewind, 0, 0, 0}, /* 1 */
- { OP_AddImm, 3, 1, 0},
- { OP_Next, 0, 0, 0}, /* 3 */
- { OP_Eq, 2, 0, 3}, /* 4 */
- { OP_AddImm, 1, -1, 0},
- { OP_String8, 0, 2, 0}, /* 6 */
- { OP_String8, 0, 3, 0}, /* 7 */
- { OP_Concat, 3, 2, 2},
- { OP_ResultRow, 2, 1, 0},
- };
- addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1);
+ if( pPk==pIdx ) continue;
+ addr = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
- sqlite3VdbeJumpHere(v, addr);
- addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
- sqlite3VdbeChangeP1(v, addr+1, j+2);
- sqlite3VdbeChangeP2(v, addr+1, addr+4);
- sqlite3VdbeChangeP1(v, addr+3, j+2);
- sqlite3VdbeChangeP2(v, addr+3, addr+2);
- sqlite3VdbeJumpHere(v, addr+4);
- sqlite3VdbeChangeP4(v, addr+6,
- "wrong # of entries in index ", P4_STATIC);
- sqlite3VdbeChangeP4(v, addr+7, pIdx->zName, P4_TRANSIENT);
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
+ sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3);
+ sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pIdx->zName, P4_TRANSIENT);
+ sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
}
+#endif /* SQLITE_OMIT_BTREECOUNT */
}
}
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
sqlite3VdbeChangeP2(v, addr, -mxErr);
sqlite3VdbeJumpHere(v, addr+1);
sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
- }else
+ }
+ break;
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
#ifndef SQLITE_OMIT_UTF16
@@ -94888,7 +98254,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** new database files created using this database handle. It is only
** useful if invoked immediately after the main database i
*/
- if( sqlite3StrICmp(zLeft, "encoding")==0 ){
+ case PragTyp_ENCODING: {
static const struct EncName {
char *zName;
u8 enc;
@@ -94935,7 +98301,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
}
- }else
+ }
+ break;
#endif /* SQLITE_OMIT_UTF16 */
#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
@@ -94969,11 +98336,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** The user-version is not used internally by SQLite. It may be used by
** applications for any purpose.
*/
- if( sqlite3StrICmp(zLeft, "schema_version")==0
- || sqlite3StrICmp(zLeft, "user_version")==0
- || sqlite3StrICmp(zLeft, "freelist_count")==0
- || sqlite3StrICmp(zLeft, "application_id")==0
- ){
+ case PragTyp_HEADER_VALUE: {
int iCookie; /* Cookie index. 1 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
switch( zLeft[0] ){
@@ -95017,7 +98380,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
}
- }else
+ }
+ break;
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
@@ -95027,7 +98391,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** Return the names of all compile-time options used in this build,
** one option per row.
*/
- if( sqlite3StrICmp(zLeft, "compile_options")==0 ){
+ case PragTyp_COMPILE_OPTIONS: {
int i = 0;
const char *zOpt;
sqlite3VdbeSetNumCols(v, 1);
@@ -95037,7 +98401,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}
- }else
+ }
+ break;
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
#ifndef SQLITE_OMIT_WAL
@@ -95046,7 +98411,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
**
** Checkpoint the database.
*/
- if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){
+ case PragTyp_WAL_CHECKPOINT: {
int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
int eMode = SQLITE_CHECKPOINT_PASSIVE;
if( zRight ){
@@ -95056,7 +98421,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
eMode = SQLITE_CHECKPOINT_RESTART;
}
}
- if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
@@ -95065,7 +98429,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp3(v, OP_Checkpoint, iBt, eMode, 1);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
- }else
+ }
+ break;
/*
** PRAGMA wal_autocheckpoint
@@ -95075,14 +98440,15 @@ SQLITE_PRIVATE void sqlite3Pragma(
** after accumulating N frames in the log. Or query for the current value
** of N.
*/
- if( sqlite3StrICmp(zLeft, "wal_autocheckpoint")==0 ){
+ case PragTyp_WAL_AUTOCHECKPOINT: {
if( zRight ){
sqlite3_wal_autocheckpoint(db, sqlite3Atoi(zRight));
}
returnSingleInt(pParse, "wal_autocheckpoint",
db->xWalCallback==sqlite3WalDefaultHook ?
SQLITE_PTR_TO_INT(db->pWalArg) : 0);
- }else
+ }
+ break;
#endif
/*
@@ -95091,9 +98457,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
** This pragma attempts to free as much memory as possible from the
** current database connection.
*/
- if( sqlite3StrICmp(zLeft, "shrink_memory")==0 ){
+ case PragTyp_SHRINK_MEMORY: {
sqlite3_db_release_memory(db);
- }else
+ break;
+ }
/*
** PRAGMA busy_timeout
@@ -95104,18 +98471,36 @@ SQLITE_PRIVATE void sqlite3Pragma(
** then 0 is returned. Setting the busy_timeout to 0 or negative
** disables the timeout.
*/
- if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){
+ /*case PragTyp_BUSY_TIMEOUT*/ default: {
+ assert( aPragmaNames[mid].ePragTyp==PragTyp_BUSY_TIMEOUT );
if( zRight ){
sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
}
returnSingleInt(pParse, "timeout", db->busyTimeout);
- }else
+ break;
+ }
+
+ /*
+ ** PRAGMA soft_heap_limit
+ ** PRAGMA soft_heap_limit = N
+ **
+ ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted,
+ ** use -1.
+ */
+ case PragTyp_SOFT_HEAP_LIMIT: {
+ sqlite3_int64 N;
+ if( zRight && sqlite3Atoi64(zRight, &N, 1000000, SQLITE_UTF8)==SQLITE_OK ){
+ sqlite3_soft_heap_limit64(N);
+ }
+ returnSingleInt(pParse, "soft_heap_limit", sqlite3_soft_heap_limit64(-1));
+ break;
+ }
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
*/
- if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
+ case PragTyp_LOCK_STATUS: {
static const char *const azLockName[] = {
"unlocked", "shared", "reserved", "pending", "exclusive"
};
@@ -95140,35 +98525,39 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
-
- }else
+ break;
+ }
#endif
#ifdef SQLITE_HAS_CODEC
- if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
- sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
- }else
- if( sqlite3StrICmp(zLeft, "rekey")==0 && zRight ){
- sqlite3_rekey(db, zRight, sqlite3Strlen30(zRight));
- }else
- if( zRight && (sqlite3StrICmp(zLeft, "hexkey")==0 ||
- sqlite3StrICmp(zLeft, "hexrekey")==0) ){
- int i, h1, h2;
- char zKey[40];
- for(i=0; (h1 = zRight[i])!=0 && (h2 = zRight[i+1])!=0; i+=2){
- h1 += 9*(1&(h1>>6));
- h2 += 9*(1&(h2>>6));
- zKey[i/2] = (h2 & 0x0f) | ((h1 & 0xf)<<4);
- }
- if( (zLeft[3] & 0xf)==0xb ){
- sqlite3_key(db, zKey, i/2);
- }else{
- sqlite3_rekey(db, zKey, i/2);
+ case PragTyp_KEY: {
+ if( zRight ) sqlite3_key_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
+ break;
+ }
+ case PragTyp_REKEY: {
+ if( zRight ) sqlite3_rekey_v2(db, zDb, zRight, sqlite3Strlen30(zRight));
+ break;
+ }
+ case PragTyp_HEXKEY: {
+ if( zRight ){
+ u8 iByte;
+ int i;
+ char zKey[40];
+ for(i=0, iByte=0; i<sizeof(zKey)*2 && sqlite3Isxdigit(zRight[i]); i++){
+ iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
+ if( (i&1)!=0 ) zKey[i/2] = iByte;
+ }
+ if( (zLeft[3] & 0xf)==0xb ){
+ sqlite3_key_v2(db, zDb, zKey, i/2);
+ }else{
+ sqlite3_rekey_v2(db, zDb, zKey, i/2);
+ }
}
- }else
+ break;
+ }
#endif
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
- if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
+ case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){
#ifdef SQLITE_HAS_CODEC
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
sqlite3_activate_see(&zRight[4]);
@@ -95179,23 +98568,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3_activate_cerod(&zRight[6]);
}
#endif
- }else
+ }
+ break;
#endif
-
- {/* Empty ELSE clause */}
+ } /* End of the PRAGMA switch */
- /*
- ** Reset the safety level, in case the fullfsync flag or synchronous
- ** setting changed.
- */
-#ifndef SQLITE_OMIT_PAGER_PRAGMAS
- if( db->autoCommit ){
- sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level,
- (db->flags&SQLITE_FullFSync)!=0,
- (db->flags&SQLITE_CkptFullFSync)!=0);
- }
-#endif
pragma_out:
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
@@ -95731,6 +99109,13 @@ SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
}
/*
+** Free all memory allocations in the pParse object
+*/
+SQLITE_PRIVATE void sqlite3ParserReset(Parse *pParse){
+ if( pParse ) sqlite3ExprListDelete(pParse->db, pParse->pConstExpr);
+}
+
+/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
static int sqlite3Prepare(
@@ -95798,7 +99183,7 @@ static int sqlite3Prepare(
sqlite3VtabUnlockList(db);
pParse->db = db;
- pParse->nQueryLoop = (double)1;
+ pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -95820,7 +99205,7 @@ static int sqlite3Prepare(
}else{
sqlite3RunParser(pParse, zSql, &zErrMsg);
}
- assert( 1==(int)pParse->nQueryLoop );
+ assert( 0==pParse->nQueryLoop );
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM;
@@ -95887,6 +99272,7 @@ static int sqlite3Prepare(
end_prepare:
+ sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );
@@ -96016,6 +99402,12 @@ static int sqlite3Prepare16(
if( !sqlite3SafetyCheckOk(db) ){
return SQLITE_MISUSE_BKPT;
}
+ if( nBytes>=0 ){
+ int sz;
+ const char *z = (const char*)zSql;
+ for(sz=0; sz<nBytes && (z[sz]!=0 || z[sz+1]!=0); sz += 2){}
+ nBytes = sz;
+ }
sqlite3_mutex_enter(db->mutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
@@ -96184,7 +99576,7 @@ SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
}
/*
-** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
+** Given 1 to 3 identifiers preceding the JOIN keyword, determine the
** type of join. Return an integer constant that expresses that type
** in terms of the following bit values:
**
@@ -96339,8 +99731,8 @@ static void addWhereTerm(
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
if( pEq && isOuterJoin ){
ExprSetProperty(pEq, EP_FromJoin);
- assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) );
- ExprSetIrreducible(pEq);
+ assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
+ ExprSetVVAProperty(pEq, EP_NoReduce);
pEq->iRightJoinTable = (i16)pE2->iTable;
}
*ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
@@ -96375,8 +99767,8 @@ static void addWhereTerm(
static void setJoinExpr(Expr *p, int iTable){
while( p ){
ExprSetProperty(p, EP_FromJoin);
- assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
- ExprSetIrreducible(p);
+ assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
+ ExprSetVVAProperty(p, EP_NoReduce);
p->iRightJoinTable = (i16)iTable;
setJoinExpr(p->pLeft, iTable);
p = p->pRight;
@@ -96674,7 +100066,8 @@ static void selectInnerLoop(
** values returned by the SELECT are not required.
*/
sqlite3ExprCacheClear(pParse);
- sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
+ sqlite3ExprCodeExprList(pParse, pEList, regResult,
+ (eDest==SRT_Output)?SQLITE_ECEL_DUP:0);
}
nColumn = nResultCol;
@@ -96878,6 +100271,58 @@ static void selectInnerLoop(
}
/*
+** Allocate a KeyInfo object sufficient for an index of N key columns and
+** X extra columns.
+*/
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
+ KeyInfo *p = sqlite3DbMallocZero(0,
+ sizeof(KeyInfo) + (N+X)*(sizeof(CollSeq*)+1));
+ if( p ){
+ p->aSortOrder = (u8*)&p->aColl[N+X];
+ p->nField = (u16)N;
+ p->nXField = (u16)X;
+ p->enc = ENC(db);
+ p->db = db;
+ p->nRef = 1;
+ }else{
+ db->mallocFailed = 1;
+ }
+ return p;
+}
+
+/*
+** Deallocate a KeyInfo object
+*/
+SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo *p){
+ if( p ){
+ assert( p->nRef>0 );
+ p->nRef--;
+ if( p->nRef==0 ) sqlite3DbFree(0, p);
+ }
+}
+
+/*
+** Make a new pointer to a KeyInfo object
+*/
+SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo *p){
+ if( p ){
+ assert( p->nRef>0 );
+ p->nRef++;
+ }
+ return p;
+}
+
+#ifdef SQLITE_DEBUG
+/*
+** Return TRUE if a KeyInfo object can be change. The KeyInfo object
+** can only be changed if this is just a single reference to the object.
+**
+** This routine is used only inside of assert() statements.
+*/
+SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo *p){ return p->nRef==1; }
+#endif /* SQLITE_DEBUG */
+
+/*
** Given an expression list, generate a KeyInfo structure that records
** the collating sequence for each expression in that expression list.
**
@@ -96889,29 +100334,23 @@ static void selectInnerLoop(
**
** Space to hold the KeyInfo structure is obtain from malloc. The calling
** function is responsible for seeing that this structure is eventually
-** freed. Add the KeyInfo structure to the P4 field of an opcode using
-** P4_KEYINFO_HANDOFF is the usual way of dealing with this.
+** freed.
*/
static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
- sqlite3 *db = pParse->db;
int nExpr;
KeyInfo *pInfo;
struct ExprList_item *pItem;
+ sqlite3 *db = pParse->db;
int i;
nExpr = pList->nExpr;
- pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
+ pInfo = sqlite3KeyInfoAlloc(db, nExpr, 1);
if( pInfo ){
- pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
- pInfo->nField = (u16)nExpr;
- pInfo->enc = ENC(db);
- pInfo->db = db;
+ assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
CollSeq *pColl;
pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
- if( !pColl ){
- pColl = db->pDfltColl;
- }
+ if( !pColl ) pColl = db->pDfltColl;
pInfo->aColl[i] = pColl;
pInfo->aSortOrder[i] = pItem->sortOrder;
}
@@ -97123,6 +100562,9 @@ static void generateSortTail(
** Return a pointer to a string containing the 'declaration type' of the
** expression pExpr. The string may be treated as static by the caller.
**
+** Also try to estimate the size of the returned value and return that
+** result in *pEstWidth.
+**
** The declaration type is the exact datatype definition extracted from the
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
@@ -97136,21 +100578,36 @@ static void generateSortTail(
** SELECT abc FROM (SELECT col AS abc FROM tbl);
**
** The declaration type for any expression other than a column is NULL.
+**
+** This routine has either 3 or 6 parameters depending on whether or not
+** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
*/
-static const char *columnType(
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
+static const char *columnTypeImpl(
+ NameContext *pNC,
+ Expr *pExpr,
+ const char **pzOrigDb,
+ const char **pzOrigTab,
+ const char **pzOrigCol,
+ u8 *pEstWidth
+){
+ char const *zOrigDb = 0;
+ char const *zOrigTab = 0;
+ char const *zOrigCol = 0;
+#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
+static const char *columnTypeImpl(
NameContext *pNC,
Expr *pExpr,
- const char **pzOriginDb,
- const char **pzOriginTab,
- const char **pzOriginCol
+ u8 *pEstWidth
){
+#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
char const *zType = 0;
- char const *zOriginDb = 0;
- char const *zOriginTab = 0;
- char const *zOriginCol = 0;
int j;
- if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
+ u8 estWidth = 1;
+ if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
switch( pExpr->op ){
case TK_AGG_COLUMN:
case TK_COLUMN: {
@@ -97211,25 +100668,35 @@ static const char *columnType(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
+ zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
}
}else if( ALWAYS(pTab->pSchema) ){
/* A real table */
assert( !pS );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
if( iCol<0 ){
zType = "INTEGER";
- zOriginCol = "rowid";
+ zOrigCol = "rowid";
}else{
zType = pTab->aCol[iCol].zType;
- zOriginCol = pTab->aCol[iCol].zName;
+ zOrigCol = pTab->aCol[iCol].zName;
+ estWidth = pTab->aCol[iCol].szEst;
}
- zOriginTab = pTab->zName;
+ zOrigTab = pTab->zName;
if( pNC->pParse ){
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
- zOriginDb = pNC->pParse->db->aDb[iDb].zName;
+ zOrigDb = pNC->pParse->db->aDb[iDb].zName;
+ }
+#else
+ if( iCol<0 ){
+ zType = "INTEGER";
+ }else{
+ zType = pTab->aCol[iCol].zType;
+ estWidth = pTab->aCol[iCol].szEst;
}
+#endif
}
break;
}
@@ -97246,18 +100713,21 @@ static const char *columnType(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
- zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
break;
}
#endif
}
-
- if( pzOriginDb ){
- assert( pzOriginTab && pzOriginCol );
- *pzOriginDb = zOriginDb;
- *pzOriginTab = zOriginTab;
- *pzOriginCol = zOriginCol;
+
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ if( pzOrigDb ){
+ assert( pzOrigTab && pzOrigCol );
+ *pzOrigDb = zOrigDb;
+ *pzOrigTab = zOrigTab;
+ *pzOrigCol = zOrigCol;
}
+#endif
+ if( pEstWidth ) *pEstWidth = estWidth;
return zType;
}
@@ -97283,7 +100753,7 @@ static void generateColumnTypes(
const char *zOrigDb = 0;
const char *zOrigTab = 0;
const char *zOrigCol = 0;
- zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
+ zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
/* The vdbe must make its own copy of the column-type and other
** column specific strings, in case the schema is reset before this
@@ -97293,11 +100763,11 @@ static void generateColumnTypes(
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
#else
- zType = columnType(&sNC, p, 0, 0, 0);
+ zType = columnType(&sNC, p, 0, 0, 0, 0);
#endif
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
}
-#endif /* SQLITE_OMIT_DECLTYPE */
+#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
}
/*
@@ -97486,8 +100956,7 @@ static int selectColumnsFromExprList(
*/
static void selectAddColumnTypeAndCollation(
Parse *pParse, /* Parsing contexts */
- int nCol, /* Number of columns */
- Column *aCol, /* List of columns */
+ Table *pTab, /* Add column type information to this table */
Select *pSelect /* SELECT used to determine types and collations */
){
sqlite3 *db = pParse->db;
@@ -97497,17 +100966,19 @@ static void selectAddColumnTypeAndCollation(
int i;
Expr *p;
struct ExprList_item *a;
+ u64 szAll = 0;
assert( pSelect!=0 );
assert( (pSelect->selFlags & SF_Resolved)!=0 );
- assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
+ assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
if( db->mallocFailed ) return;
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
a = pSelect->pEList->a;
- for(i=0, pCol=aCol; i<nCol; i++, pCol++){
+ for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
p = a[i].pExpr;
- pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
+ pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
+ szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
pColl = sqlite3ExprCollSeq(pParse, p);
@@ -97515,6 +100986,7 @@ static void selectAddColumnTypeAndCollation(
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
}
}
+ pTab->szTabRow = sqlite3LogEst(szAll*4);
}
/*
@@ -97542,9 +101014,9 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
assert( db->lookaside.bEnabled==0 );
pTab->nRef = 1;
pTab->zName = 0;
- pTab->nRowEst = 1000000;
+ pTab->nRowEst = 1048576;
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
+ selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
pTab->iPKey = -1;
if( db->mallocFailed ){
sqlite3DeleteTable(db, pTab);
@@ -97598,7 +101070,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
/*
** "LIMIT -1" always shows all rows. There is some
- ** contraversy about what the correct behavior should be.
+ ** controversy about what the correct behavior should be.
** The current implementation interprets "LIMIT 0" to mean
** no rows.
*/
@@ -97613,8 +101085,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak);
- }else{
- if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
+ }else if( n>=0 && p->nSelectRow>(u64)n ){
+ p->nSelectRow = n;
}
}else{
sqlite3ExprCode(pParse, p->pLimit, iLimit);
@@ -97808,9 +101280,9 @@ static int multiSelect(
p->nSelectRow += pPrior->nSelectRow;
if( pPrior->pLimit
&& sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
- && p->nSelectRow > (double)nLimit
+ && nLimit>0 && p->nSelectRow > (u64)nLimit
){
- p->nSelectRow = (double)nLimit;
+ p->nSelectRow = nLimit;
}
if( addr ){
sqlite3VdbeJumpHere(v, addr);
@@ -98017,23 +101489,17 @@ static int multiSelect(
assert( p->pRightmost==p );
nCol = p->pEList->nExpr;
- pKeyInfo = sqlite3DbMallocZero(db,
- sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));
+ pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
if( !pKeyInfo ){
rc = SQLITE_NOMEM;
goto multi_select_end;
}
-
- pKeyInfo->enc = ENC(db);
- pKeyInfo->nField = (u16)nCol;
-
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
*apColl = multiSelectCollSeq(pParse, p, i);
if( 0==*apColl ){
*apColl = db->pDfltColl;
}
}
- pKeyInfo->aSortOrder = (u8*)apColl;
for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
for(i=0; i<2; i++){
@@ -98045,11 +101511,12 @@ static int multiSelect(
break;
}
sqlite3VdbeChangeP2(v, addr, nCol);
- sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO);
+ sqlite3VdbeChangeP4(v, addr, (char*)sqlite3KeyInfoRef(pKeyInfo),
+ P4_KEYINFO);
pLoop->addrOpenEphm[i] = -1;
}
}
- sqlite3DbFree(db, pKeyInfo);
+ sqlite3KeyInfoUnref(pKeyInfo);
}
multi_select_end:
@@ -98088,7 +101555,6 @@ static int generateOutputSubroutine(
int regReturn, /* The return address register */
int regPrev, /* Previous result register. No uniqueness if 0 */
KeyInfo *pKeyInfo, /* For comparing with previous entry */
- int p4type, /* The p4 type for pKeyInfo */
int iBreak /* Jump here if we hit the LIMIT */
){
Vdbe *v = pParse->pVdbe;
@@ -98104,7 +101570,7 @@ static int generateOutputSubroutine(
int j1, j2;
j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);
j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst,
- (char*)pKeyInfo, p4type);
+ (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
@@ -98374,8 +101840,8 @@ static int multiSelectOrderBy(
for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
struct ExprList_item *pItem;
for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
- assert( pItem->iOrderByCol>0 );
- if( pItem->iOrderByCol==i ) break;
+ assert( pItem->u.x.iOrderByCol>0 );
+ if( pItem->u.x.iOrderByCol==i ) break;
}
if( j==nOrderBy ){
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
@@ -98383,7 +101849,7 @@ static int multiSelectOrderBy(
pNew->flags |= EP_IntValue;
pNew->u.iValue = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
- if( pOrderBy ) pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i;
+ if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i;
}
}
}
@@ -98399,15 +101865,12 @@ static int multiSelectOrderBy(
if( aPermute ){
struct ExprList_item *pItem;
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
- assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr );
- aPermute[i] = pItem->iOrderByCol - 1;
+ assert( pItem->u.x.iOrderByCol>0
+ && pItem->u.x.iOrderByCol<=p->pEList->nExpr );
+ aPermute[i] = pItem->u.x.iOrderByCol - 1;
}
- pKeyMerge =
- sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
+ pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1);
if( pKeyMerge ){
- pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy];
- pKeyMerge->nField = (u16)nOrderBy;
- pKeyMerge->enc = ENC(db);
for(i=0; i<nOrderBy; i++){
CollSeq *pColl;
Expr *pTerm = pOrderBy->a[i].pExpr;
@@ -98419,6 +101882,7 @@ static int multiSelectOrderBy(
pOrderBy->a[i].pExpr =
sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
}
+ assert( sqlite3KeyInfoIsWriteable(pKeyMerge) );
pKeyMerge->aColl[i] = pColl;
pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
}
@@ -98444,12 +101908,9 @@ static int multiSelectOrderBy(
regPrev = pParse->nMem+1;
pParse->nMem += nExpr+1;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
- pKeyDup = sqlite3DbMallocZero(db,
- sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
+ pKeyDup = sqlite3KeyInfoAlloc(db, nExpr, 1);
if( pKeyDup ){
- pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr];
- pKeyDup->nField = (u16)nExpr;
- pKeyDup->enc = ENC(db);
+ assert( sqlite3KeyInfoIsWriteable(pKeyDup) );
for(i=0; i<nExpr; i++){
pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
pKeyDup->aSortOrder[i] = 0;
@@ -98531,7 +101992,7 @@ static int multiSelectOrderBy(
VdbeNoopComment((v, "Output routine for A"));
addrOutA = generateOutputSubroutine(pParse,
p, &destA, pDest, regOutA,
- regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd);
+ regPrev, pKeyDup, labelEnd);
/* Generate a subroutine that outputs the current row of the B
** select as the next output row of the compound select.
@@ -98540,8 +102001,9 @@ static int multiSelectOrderBy(
VdbeNoopComment((v, "Output routine for B"));
addrOutB = generateOutputSubroutine(pParse,
p, &destB, pDest, regOutB,
- regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd);
+ regPrev, pKeyDup, labelEnd);
}
+ sqlite3KeyInfoUnref(pKeyDup);
/* Generate a subroutine to run when the results from select A
** are exhausted and only data in select B remains.
@@ -98620,7 +102082,7 @@ static int multiSelectOrderBy(
sqlite3VdbeResolveLabel(v, labelCmpr);
sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
- (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
+ (char*)pKeyMerge, P4_KEYINFO);
sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
@@ -98985,7 +102447,7 @@ static int flattenSubquery(
if( p->pOrderBy ){
int ii;
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
- if( p->pOrderBy->a[ii].iOrderByCol==0 ) return 0;
+ if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
}
@@ -99304,7 +102766,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
if( IsVirtual(pTab) ) return 0;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
if( NEVER(pAggInfo->nFunc==0) ) return 0;
- if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
+ if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
if( pExpr->flags&EP_Distinct ) return 0;
return pTab;
@@ -99470,11 +102932,11 @@ static int selectExpander(Walker *pWalker, Select *p){
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
pTab->nRef = 1;
- pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
+ pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
while( pSel->pPrior ){ pSel = pSel->pPrior; }
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
pTab->iPKey = -1;
- pTab->nRowEst = 1000000;
+ pTab->nRowEst = 1048576;
pTab->tabFlags |= TF_Ephemeral;
#endif
}else{
@@ -99715,10 +103177,12 @@ static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
Walker w;
memset(&w, 0, sizeof(w));
- w.xSelectCallback = convertCompoundSelectToSubquery;
w.xExprCallback = exprWalkNoop;
w.pParse = pParse;
- sqlite3WalkSelect(&w, pSelect);
+ if( pParse->hasCompound ){
+ w.xSelectCallback = convertCompoundSelectToSubquery;
+ sqlite3WalkSelect(&w, pSelect);
+ }
w.xSelectCallback = selectExpander;
sqlite3WalkSelect(&w, pSelect);
}
@@ -99756,7 +103220,7 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Select *pSel = pFrom->pSelect;
assert( pSel );
while( pSel->pPrior ) pSel = pSel->pPrior;
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
+ selectAddColumnTypeAndCollation(pParse, pTab, pSel);
}
}
}
@@ -99844,7 +103308,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
}else{
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
- (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ (char*)pKeyInfo, P4_KEYINFO);
}
}
}
@@ -99889,7 +103353,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
- sqlite3ExprCodeExprList(pParse, pList, regAgg, 1);
+ sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP);
}else{
nArg = 0;
regAgg = 0;
@@ -99899,7 +103363,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
assert( nArg==1 );
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
}
- if( pF->pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl = 0;
struct ExprList_item *pItem;
int j;
@@ -99959,11 +103423,10 @@ static void explainSimpleCount(
Index *pIdx /* Index used to optimize scan, or NULL */
){
if( pParse->explain==2 ){
- char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s %s%s(~%d rows)",
+ char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
pTab->zName,
- pIdx ? "USING COVERING INDEX " : "",
- pIdx ? pIdx->zName : "",
- pTab->nRowEst
+ pIdx ? " USING COVERING INDEX " : "",
+ pIdx ? pIdx->zName : ""
);
sqlite3VdbeAddOp4(
pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
@@ -100121,7 +103584,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
/* Increment Parse.nHeight by the height of the largest expression
- ** tree refered to by this, the parent select. The child select
+ ** tree referred to by this, the parent select. The child select
** may contain expression trees of at most
** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
** more conservative than necessary, but much easier than enforcing
@@ -100253,7 +103716,7 @@ SQLITE_PRIVATE int sqlite3Select(
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
** to disable this optimization for testing purposes.
*/
- if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
+ if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy, -1)==0
&& OptimizationEnabled(db, SQLITE_GroupByOrder) ){
pOrderBy = 0;
}
@@ -100274,7 +103737,7 @@ SQLITE_PRIVATE int sqlite3Select(
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
- && sqlite3ExprListCompare(pOrderBy, p->pEList)==0
+ && sqlite3ExprListCompare(pOrderBy, p->pEList, -1)==0
){
p->selFlags &= ~SF_Distinct;
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
@@ -100300,7 +103763,7 @@ SQLITE_PRIVATE int sqlite3Select(
p->addrOpenEphm[2] = addrSortIndex =
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
pOrderBy->iECursor, pOrderBy->nExpr+2, 0,
- (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ (char*)pKeyInfo, P4_KEYINFO);
}else{
addrSortIndex = -1;
}
@@ -100314,7 +103777,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(v);
- p->nSelectRow = (double)LARGEST_INT64;
+ p->nSelectRow = LARGEST_INT64;
computeLimitRegisters(pParse, p, iEnd);
if( p->iLimit==0 && addrSortIndex>=0 ){
sqlite3VdbeGetOp(v, addrSortIndex)->opcode = OP_SorterOpen;
@@ -100328,7 +103791,7 @@ SQLITE_PRIVATE int sqlite3Select(
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
sDistinct.tabTnct, 0, 0,
(char*)keyInfoFromExprList(pParse, p->pEList),
- P4_KEYINFO_HANDOFF);
+ P4_KEYINFO);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
}else{
@@ -100337,14 +103800,19 @@ SQLITE_PRIVATE int sqlite3Select(
if( !isAgg && pGroupBy==0 ){
/* No aggregate functions and no GROUP BY clause */
- ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0);
+ u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
/* Begin the database scan. */
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, p->pEList,
+ wctrlFlags, 0);
if( pWInfo==0 ) goto select_end;
- if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
- if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct;
- if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0;
+ if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
+ p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
+ }
+ if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
+ sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
+ }
+ if( pOrderBy && sqlite3WhereIsOrdered(pWInfo) ) pOrderBy = 0;
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -100357,7 +103825,8 @@ SQLITE_PRIVATE int sqlite3Select(
/* Use the standard inner loop. */
selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest,
- pWInfo->iContinue, pWInfo->iBreak);
+ sqlite3WhereContinueLabel(pWInfo),
+ sqlite3WhereBreakLabel(pWInfo));
/* End the database scan loop.
*/
@@ -100385,14 +103854,14 @@ SQLITE_PRIVATE int sqlite3Select(
struct ExprList_item *pItem; /* For looping over expression in a list */
for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
- pItem->iAlias = 0;
+ pItem->u.x.iAlias = 0;
}
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
- pItem->iAlias = 0;
+ pItem->u.x.iAlias = 0;
}
- if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
+ if( p->nSelectRow>100 ) p->nSelectRow = 100;
}else{
- p->nSelectRow = (double)1;
+ p->nSelectRow = 1;
}
@@ -100446,7 +103915,7 @@ SQLITE_PRIVATE int sqlite3Select(
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen,
sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
- 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ 0, (char*)pKeyInfo, P4_KEYINFO);
/* Initialize memory locations used by GROUP BY aggregate processing
*/
@@ -100472,9 +103941,10 @@ 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, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
+ WHERE_GROUPBY, 0);
if( pWInfo==0 ) goto select_end;
- if( pWInfo->nOBSat==pGroupBy->nExpr ){
+ if( sqlite3WhereIsOrdered(pWInfo) ){
/* The optimizer is able to deliver rows in group by order so
** we do not have to sort. The OP_OpenEphemeral table will be
** cancelled later because we still need to use the pKeyInfo
@@ -100559,7 +104029,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
}
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
- (char*)pKeyInfo, P4_KEYINFO);
+ (char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
j1 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1);
@@ -100665,33 +104135,34 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
- /* Search for the index that has the least amount of columns. If
- ** there is such an index, and it has less columns than the table
- ** does, then we can assume that it consumes less space on disk and
- ** will therefore be cheaper to scan to determine the query result.
- ** In this case set iRoot to the root page number of the index b-tree
- ** and pKeyInfo to the KeyInfo structure required to navigate the
- ** index.
+ /* Search for the index that has the lowest scan cost.
**
** (2011-04-15) Do not do a full scan of an unordered index.
**
+ ** (2013-10-03) Do not count the entries in a partial index.
+ **
** In practice the KeyInfo structure will not be used. It is only
** passed to keep OP_OpenRead happy.
*/
+ if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->bUnordered==0 && (!pBest || pIdx->nColumn<pBest->nColumn) ){
+ if( pIdx->bUnordered==0
+ && pIdx->szIdxRow<pTab->szTabRow
+ && pIdx->pPartIdxWhere==0
+ && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
+ ){
pBest = pIdx;
}
}
- if( pBest && pBest->nColumn<pTab->nCol ){
+ if( pBest ){
iRoot = pBest->tnum;
- pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest);
+ pKeyInfo = sqlite3KeyInfoOfIndex(pParse, pBest);
}
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
- sqlite3VdbeAddOp3(v, OP_OpenRead, iCsr, iRoot, iDb);
+ sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
if( pKeyInfo ){
- sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
}
sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
@@ -100755,8 +104226,8 @@ SQLITE_PRIVATE int sqlite3Select(
}
updateAccumulator(pParse, &sAggInfo);
assert( pMinMax==0 || pMinMax->nExpr==1 );
- if( pWInfo->nOBSat>0 ){
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
+ if( sqlite3WhereIsOrdered(pWInfo) ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3WhereBreakLabel(pWInfo));
VdbeComment((v, "%s() by index",
(flag==WHERE_ORDERBY_MIN?"min":"max")));
}
@@ -101261,8 +104732,8 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
/* Ensure the table name matches database name and that the table exists */
if( db->mallocFailed ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
- sqlite3FixSrcList(&sFix, pTableName) ){
+ sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName);
+ if( sqlite3FixSrcList(&sFix, pTableName) ){
goto trigger_cleanup;
}
pTab = sqlite3SrcListLookup(pParse, pTableName);
@@ -101404,8 +104875,10 @@ SQLITE_PRIVATE void sqlite3FinishTrigger(
}
nameToken.z = pTrig->zName;
nameToken.n = sqlite3Strlen30(nameToken.z);
- if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken)
- && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
+ sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken);
+ if( sqlite3FixTriggerStep(&sFix, pTrig->step_list)
+ || sqlite3FixExpr(&sFix, pTrig->pWhen)
+ ){
goto triggerfinish_cleanup;
}
@@ -101895,7 +105368,7 @@ static int codeTriggerProgram(
return 0;
}
-#ifdef SQLITE_DEBUG
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
/*
** This function is used to add VdbeComment() annotations to a VDBE
** program. It is not used in production code, only for debugging.
@@ -102035,6 +105508,7 @@ static TriggerPrg *codeRowTrigger(
assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
+ sqlite3ParserReset(pSubParse);
sqlite3StackFree(db, pSubParse);
return pPrg;
@@ -102115,7 +105589,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
/*
** This is called to code the required FOR EACH ROW triggers for an operation
** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE)
-** is given by the op paramater. The tr_tm parameter determines whether the
+** is given by the op parameter. The tr_tm parameter determines whether the
** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then
** parameter pChanges is passed the list of columns being modified.
**
@@ -102309,7 +105783,7 @@ static void updateVirtualTable(
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
assert( pTab!=0 );
if( !pTab->pSelect ){
- sqlite3_value *pValue;
+ sqlite3_value *pValue = 0;
u8 enc = ENC(sqlite3VdbeDb(v));
Column *pCol = &pTab->aCol[i];
VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
@@ -102343,25 +105817,32 @@ SQLITE_PRIVATE void sqlite3Update(
){
int i, j; /* Loop counters */
Table *pTab; /* The table to be updated */
- int addr = 0; /* VDBE instruction address of the start of the loop */
+ int addrTop = 0; /* VDBE instruction address of the start of the loop */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Vdbe *v; /* The virtual database engine */
Index *pIdx; /* For looping over indices */
+ Index *pPk; /* The PRIMARY KEY index for WITHOUT ROWID tables */
int nIdx; /* Number of indices that need updating */
- int iCur; /* VDBE Cursor number of pTab */
+ int iBaseCur; /* Base cursor number */
+ int iDataCur; /* Cursor for the canonical data btree */
+ int iIdxCur; /* Cursor for the first index */
sqlite3 *db; /* The database structure */
int *aRegIdx = 0; /* One register assigned to each index to be updated */
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
- int chngRowid; /* True if the record number is being changed */
+ u8 *aToOpen; /* 1 for tables and indices to be opened */
+ u8 chngPk; /* PRIMARY KEY changed in a WITHOUT ROWID table */
+ u8 chngRowid; /* Rowid changed in a normal table */
+ u8 chngKey; /* Either chngPk or chngRowid */
Expr *pRowidExpr = 0; /* Expression defining the new record number */
- int openAll = 0; /* True if all indices need to be opened */
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
int okOnePass; /* True for one-pass algorithm without the FIFO */
int hasFK; /* True if foreign key processing is required */
+ int labelBreak; /* Jump here to break out of UPDATE loop */
+ int labelContinue; /* Jump here to continue next step of UPDATE loop */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True when updating a view (INSTEAD OF trigger) */
@@ -102369,6 +105850,9 @@ SQLITE_PRIVATE void sqlite3Update(
int tmask; /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
#endif
int newmask; /* Mask of NEW.* columns accessed by BEFORE triggers */
+ int iEph = 0; /* Ephemeral table holding all primary key values */
+ int nKey = 0; /* Number of elements in regKey for WITHOUT ROWID */
+ int aiCurOnePass[2]; /* The write cursors opened by WHERE_ONEPASS */
/* Register Allocations */
int regRowCount = 0; /* A count of rows changed */
@@ -102377,6 +105861,7 @@ SQLITE_PRIVATE void sqlite3Update(
int regNew; /* Content of the NEW.* table in triggers */
int regOld = 0; /* Content of OLD.* table in triggers */
int regRowSet = 0; /* Rowset of rows to be updated */
+ int regKey = 0; /* composite PRIMARY KEY value */
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
@@ -102414,20 +105899,34 @@ SQLITE_PRIVATE void sqlite3Update(
if( sqlite3IsReadOnly(pParse, pTab, tmask) ){
goto update_cleanup;
}
- aXRef = sqlite3DbMallocRaw(db, sizeof(int) * pTab->nCol );
- if( aXRef==0 ) goto update_cleanup;
- for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
/* Allocate a cursors for the main database table and for all indices.
** The index cursors might not be used, but if they are used they
** need to occur right after the database cursor. So go ahead and
** allocate enough space, just in case.
*/
- pTabList->a[0].iCursor = iCur = pParse->nTab++;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ pTabList->a[0].iCursor = iBaseCur = iDataCur = pParse->nTab++;
+ iIdxCur = iDataCur+1;
+ pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
+ if( pIdx->autoIndex==2 && pPk!=0 ){
+ iDataCur = pParse->nTab;
+ pTabList->a[0].iCursor = iDataCur;
+ }
pParse->nTab++;
}
+ /* Allocate space for aXRef[], aRegIdx[], and aToOpen[].
+ ** Initialize aXRef[] and aToOpen[] to their default values.
+ */
+ aXRef = sqlite3DbMallocRaw(db, sizeof(int) * (pTab->nCol+nIdx) + nIdx+2 );
+ if( aXRef==0 ) goto update_cleanup;
+ aRegIdx = aXRef+pTab->nCol;
+ aToOpen = (u8*)(aRegIdx+nIdx);
+ memset(aToOpen, 1, nIdx+1);
+ aToOpen[nIdx+1] = 0;
+ for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
+
/* Initialize the name-context */
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
@@ -102439,7 +105938,7 @@ SQLITE_PRIVATE void sqlite3Update(
** column to be updated, make sure we have authorization to change
** that column.
*/
- chngRowid = 0;
+ chngRowid = chngPk = 0;
for(i=0; i<pChanges->nExpr; i++){
if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
@@ -102449,13 +105948,15 @@ SQLITE_PRIVATE void sqlite3Update(
if( j==pTab->iPKey ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
+ }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
+ chngPk = 1;
}
aXRef[j] = i;
break;
}
}
if( j>=pTab->nCol ){
- if( sqlite3IsRowid(pChanges->a[i].zName) ){
+ if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
j = -1;
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
@@ -102479,32 +105980,36 @@ SQLITE_PRIVATE void sqlite3Update(
}
#endif
}
+ assert( (chngRowid & chngPk)==0 );
+ assert( chngRowid==0 || chngRowid==1 );
+ assert( chngPk==0 || chngPk==1 );
+ chngKey = chngRowid + chngPk;
- hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngRowid);
+ /* The SET expressions are not actually used inside the WHERE loop.
+ ** So reset the colUsed mask
+ */
+ pTabList->a[0].colUsed = 0;
+
+ hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngKey);
- /* Allocate memory for the array aRegIdx[]. There is one entry in the
- ** array for each index associated with table being updated. Fill in
- ** the value with a register number for indices that are to be used
- ** and with zero for unused indices.
+ /* There is one entry in the aRegIdx[] array for each index on the table
+ ** being updated. Fill in aRegIdx[] with a register number that will hold
+ ** the key for accessing each index.
*/
- for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
- if( nIdx>0 ){
- aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
- if( aRegIdx==0 ) goto update_cleanup;
- }
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
int reg;
- if( hasFK || chngRowid ){
+ if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){
reg = ++pParse->nMem;
}else{
reg = 0;
- for(i=0; i<pIdx->nColumn; i++){
+ for(i=0; i<pIdx->nKeyCol; i++){
if( aXRef[pIdx->aiColumn[i]]>=0 ){
reg = ++pParse->nMem;
break;
}
}
}
+ if( reg==0 ) aToOpen[j+1] = 0;
aRegIdx[j] = reg;
}
@@ -102528,11 +106033,11 @@ SQLITE_PRIVATE void sqlite3Update(
/* Allocate required registers. */
regRowSet = ++pParse->nMem;
regOldRowid = regNewRowid = ++pParse->nMem;
- if( pTrigger || hasFK ){
+ if( chngPk || pTrigger || hasFK ){
regOld = pParse->nMem + 1;
pParse->nMem += pTab->nCol;
}
- if( chngRowid || pTrigger || hasFK ){
+ if( chngKey || pTrigger || hasFK ){
regNewRowid = ++pParse->nMem;
}
regNew = pParse->nMem + 1;
@@ -102548,7 +106053,7 @@ SQLITE_PRIVATE void sqlite3Update(
*/
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
- sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+ sqlite3MaterializeView(pParse, pTab, pWhere, iDataCur);
}
#endif
@@ -102561,24 +106066,58 @@ SQLITE_PRIVATE void sqlite3Update(
/* Begin the database scan
*/
- sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
- pWInfo = sqlite3WhereBegin(
- pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
- );
- if( pWInfo==0 ) goto update_cleanup;
- okOnePass = pWInfo->okOnePass;
+ if( HasRowid(pTab) ){
+ sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
+ pWInfo = sqlite3WhereBegin(
+ pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, iIdxCur
+ );
+ if( pWInfo==0 ) goto update_cleanup;
+ okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+
+ /* Remember the rowid of every item to be updated.
+ */
+ sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regOldRowid);
+ if( !okOnePass ){
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+ }
+
+ /* End the database scan loop.
+ */
+ sqlite3WhereEnd(pWInfo);
+ }else{
+ int iPk; /* First of nPk memory cells holding PRIMARY KEY value */
+ i16 nPk; /* Number of components of the PRIMARY KEY */
+ int addrOpen; /* Address of the OpenEphemeral instruction */
- /* Remember the rowid of every item to be updated.
- */
- sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
- if( !okOnePass ){
- sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+ assert( pPk!=0 );
+ nPk = pPk->nKeyCol;
+ iPk = pParse->nMem+1;
+ pParse->nMem += nPk;
+ regKey = ++pParse->nMem;
+ iEph = pParse->nTab++;
+ sqlite3VdbeAddOp2(v, OP_Null, 0, iPk);
+ addrOpen = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iEph, nPk);
+ sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,
+ WHERE_ONEPASS_DESIRED, iIdxCur);
+ if( pWInfo==0 ) goto update_cleanup;
+ okOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
+ for(i=0; i<nPk; i++){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pPk->aiColumn[i],
+ iPk+i);
+ }
+ if( okOnePass ){
+ sqlite3VdbeChangeToNoop(v, addrOpen);
+ nKey = nPk;
+ regKey = iPk;
+ }else{
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
+ sqlite3IndexAffinityStr(v, pPk), P4_TRANSIENT);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey);
+ }
+ sqlite3WhereEnd(pWInfo);
}
- /* End the database scan loop.
- */
- sqlite3WhereEnd(pWInfo);
-
/* Initialize the count of updated rows
*/
if( (db->flags & SQLITE_CountRows) && !pParse->pTriggerTab ){
@@ -102586,6 +106125,7 @@ SQLITE_PRIVATE void sqlite3Update(
sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
}
+ labelBreak = sqlite3VdbeMakeLabel(v);
if( !isView ){
/*
** Open every index that needs updating. Note that if any
@@ -102593,68 +106133,71 @@ SQLITE_PRIVATE void sqlite3Update(
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
- if( !okOnePass ) sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
if( onError==OE_Replace ){
- openAll = 1;
+ memset(aToOpen, 1, nIdx+1);
}else{
- openAll = 0;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->onError==OE_Replace ){
- openAll = 1;
+ memset(aToOpen, 1, nIdx+1);
break;
}
}
}
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- assert( aRegIdx );
- if( openAll || aRegIdx[i]>0 ){
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
- sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
- (char*)pKey, P4_KEYINFO_HANDOFF);
- assert( pParse->nTab>iCur+i+1 );
- }
+ if( okOnePass ){
+ if( aiCurOnePass[0]>=0 ) aToOpen[aiCurOnePass[0]-iBaseCur] = 0;
+ if( aiCurOnePass[1]>=0 ) aToOpen[aiCurOnePass[1]-iBaseCur] = 0;
}
+ sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, iBaseCur, aToOpen,
+ 0, 0);
}
/* Top of the update loop */
if( okOnePass ){
- int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
- addr = sqlite3VdbeAddOp0(v, OP_Goto);
- sqlite3VdbeJumpHere(v, a1);
+ if( aToOpen[iDataCur-iBaseCur] ){
+ assert( pPk!=0 );
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey, nKey);
+ }
+ labelContinue = labelBreak;
+ sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
+ }else if( pPk ){
+ labelContinue = sqlite3VdbeMakeLabel(v);
+ sqlite3VdbeAddOp2(v, OP_Rewind, iEph, labelBreak);
+ addrTop = sqlite3VdbeAddOp2(v, OP_RowKey, iEph, regKey);
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue, regKey, 0);
}else{
- addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid);
+ labelContinue = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, labelBreak,
+ regOldRowid);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
}
- /* Make cursor iCur point to the record that is being updated. If
- ** this record does not exist for some reason (deleted by a trigger,
- ** for example, then jump to the next iteration of the RowSet loop. */
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
-
/* If the record number will change, set register regNewRowid to
** contain the new value. If the record number is not being modified,
** then regNewRowid is the same register as regOldRowid, which is
** already populated. */
- assert( chngRowid || pTrigger || hasFK || regOldRowid==regNewRowid );
+ assert( chngKey || pTrigger || hasFK || regOldRowid==regNewRowid );
if( chngRowid ){
sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
}
- /* If there are triggers on this table, populate an array of registers
- ** with the required old.* column data. */
- if( hasFK || pTrigger ){
+ /* Compute the old pre-UPDATE content of the row being changed, if that
+ ** information is needed */
+ if( chngPk || hasFK || pTrigger ){
u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
oldmask |= sqlite3TriggerColmask(pParse,
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
);
for(i=0; i<pTab->nCol; i++){
- if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<<i))) ){
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld+i);
+ if( oldmask==0xffffffff
+ || (i<32 && (oldmask & (1<<i)))
+ || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
+ ){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
}
}
- if( chngRowid==0 ){
+ if( chngRowid==0 && pPk==0 ){
sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
}
}
@@ -102691,8 +106234,7 @@ SQLITE_PRIVATE void sqlite3Update(
*/
testcase( i==31 );
testcase( i==32 );
- sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
- sqlite3ColumnDefault(v, pTab, i, regNew+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
}
}
}
@@ -102704,7 +106246,7 @@ SQLITE_PRIVATE void sqlite3Update(
sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
sqlite3TableAffinityStr(v, pTab);
sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
- TRIGGER_BEFORE, pTab, regOldRowid, onError, addr);
+ TRIGGER_BEFORE, pTab, regOldRowid, onError, labelContinue);
/* The row-trigger may have deleted the row being updated. In this
** case, jump to the next row. No updates or AFTER triggers are
@@ -102712,7 +106254,11 @@ SQLITE_PRIVATE void sqlite3Update(
** is deleted or renamed by a BEFORE trigger - is left undefined in the
** documentation.
*/
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);
+ if( pPk ){
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelContinue,regKey,nKey);
+ }else{
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue, regOldRowid);
+ }
/* If it did not delete it, the row-trigger may still have modified
** some of the columns of the row being updated. Load the values for
@@ -102721,46 +106267,56 @@ SQLITE_PRIVATE void sqlite3Update(
*/
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]<0 && i!=pTab->iPKey ){
- sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew+i);
- sqlite3ColumnDefault(v, pTab, i, regNew+i);
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
}
}
}
if( !isView ){
- int j1; /* Address of jump instruction */
+ int j1 = 0; /* Address of jump instruction */
+ int bReplace = 0; /* True if REPLACE conflict resolution might happen */
/* Do constraint checks. */
- sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid,
- aRegIdx, (chngRowid?regOldRowid:0), 1, onError, addr, 0);
+ assert( regOldRowid>0 );
+ sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
+ regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace);
/* Do FK constraint checks. */
if( hasFK ){
- sqlite3FkCheck(pParse, pTab, regOldRowid, 0);
+ sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
}
/* Delete the index entries associated with the current record. */
- j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid);
- sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);
+ if( bReplace || chngKey ){
+ if( pPk ){
+ j1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
+ }else{
+ j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
+ }
+ }
+ sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx);
/* If changing the record number, delete the old record. */
- if( hasFK || chngRowid ){
- sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
+ if( hasFK || chngKey || pPk!=0 ){
+ sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
+ }
+ if( bReplace || chngKey ){
+ sqlite3VdbeJumpHere(v, j1);
}
- sqlite3VdbeJumpHere(v, j1);
if( hasFK ){
- sqlite3FkCheck(pParse, pTab, 0, regNewRowid);
+ sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);
}
/* Insert the new index entries and the new record. */
- sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, 1, 0, 0);
+ sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
+ regNewRowid, aRegIdx, 1, 0, 0);
/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
** handle rows (possibly in other tables) that refer via a foreign key
** to the row just updated. */
if( hasFK ){
- sqlite3FkActions(pParse, pTab, pChanges, regOldRowid);
+ sqlite3FkActions(pParse, pTab, pChanges, regOldRowid, aXRef, chngKey);
}
}
@@ -102771,22 +106327,29 @@ SQLITE_PRIVATE void sqlite3Update(
}
sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
- TRIGGER_AFTER, pTab, regOldRowid, onError, addr);
+ TRIGGER_AFTER, pTab, regOldRowid, onError, labelContinue);
/* Repeat the above with the next record to be updated, until
** all record selected by the WHERE clause have been updated.
*/
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
- sqlite3VdbeJumpHere(v, addr);
+ if( okOnePass ){
+ /* Nothing to do at end-of-loop for a single-pass */
+ }else if( pPk ){
+ sqlite3VdbeResolveLabel(v, labelContinue);
+ sqlite3VdbeAddOp2(v, OP_Next, iEph, addrTop);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, labelContinue);
+ }
+ sqlite3VdbeResolveLabel(v, labelBreak);
/* Close all tables */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
assert( aRegIdx );
- if( openAll || aRegIdx[i]>0 ){
- sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0);
+ if( aToOpen[i+1] ){
+ sqlite3VdbeAddOp2(v, OP_Close, iIdxCur+i, 0);
}
}
- sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
+ if( iDataCur<iIdxCur ) sqlite3VdbeAddOp2(v, OP_Close, iDataCur, 0);
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
@@ -102809,8 +106372,7 @@ SQLITE_PRIVATE void sqlite3Update(
update_cleanup:
sqlite3AuthContextPop(&sContext);
- sqlite3DbFree(db, aRegIdx);
- sqlite3DbFree(db, aXRef);
+ sqlite3DbFree(db, aXRef); /* Also frees aRegIdx[] and aToOpen[] */
sqlite3SrcListDelete(db, pTabList);
sqlite3ExprListDelete(db, pChanges);
sqlite3ExprDelete(db, pWhere);
@@ -102996,14 +106558,34 @@ static int execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
}
/*
-** The non-standard VACUUM command is used to clean up the database,
+** The VACUUM command is used to clean up the database,
** collapse free space, etc. It is modelled after the VACUUM command
-** in PostgreSQL.
-**
-** In version 1.0.x of SQLite, the VACUUM command would call
-** gdbm_reorganize() on all the database tables. But beginning
-** with 2.0.0, SQLite no longer uses GDBM so this command has
-** become a no-op.
+** in PostgreSQL. The VACUUM command works as follows:
+**
+** (1) Create a new transient database file
+** (2) Copy all content from the database being vacuumed into
+** the new transient database file
+** (3) Copy content from the transient database back into the
+** original database.
+**
+** The transient database requires temporary disk space approximately
+** equal to the size of the original database. The copy operation of
+** step (3) requires additional temporary disk space approximately equal
+** to the size of the original database for the rollback journal.
+** Hence, temporary disk space that is approximately 2x the size of the
+** orginal database is required. Every page of the database is written
+** approximately 3 times: Once for step (2) and twice for step (3).
+** Two writes per page are required in step (3) because the original
+** database content must be written into the rollback journal prior to
+** overwriting the database with the vacuumed content.
+**
+** Only 1x temporary space and only 1x writes would be required if
+** the copy of step (3) were replace by deleting the original database
+** and renaming the transient database as the original. But that will
+** not work if other processes are attached to the original database.
+** And a power loss in between deleting the original and renaming the
+** transient would cause the database file to appear to be deleted
+** following reboot.
*/
SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse);
@@ -103035,7 +106617,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
return SQLITE_ERROR;
}
- if( db->activeVdbeCnt>1 ){
+ if( db->nVdbeActive>1 ){
sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
return SQLITE_ERROR;
}
@@ -103138,7 +106720,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
rc = execExecSql(db, pzErrMsg,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14) "
" FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
- " AND rootpage>0"
+ " AND coalesce(rootpage,1)>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db, pzErrMsg,
@@ -103159,7 +106741,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
"|| ' SELECT * FROM main.' || quote(name) || ';'"
"FROM main.sqlite_master "
"WHERE type = 'table' AND name!='sqlite_sequence' "
- " AND rootpage>0"
+ " AND coalesce(rootpage,1)>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
@@ -104013,6 +107595,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sqlite3VdbeFinalize(pParse->pVdbe);
}
sqlite3DeleteTable(db, pParse->pNewTable);
+ sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
}
@@ -104085,10 +107668,9 @@ static void callFinaliser(sqlite3 *db, int offset){
** array. Return the error code for the first error that occurs, or
** SQLITE_OK if all xSync operations are successful.
**
-** Set *pzErrmsg to point to a buffer that should be released using
-** sqlite3DbFree() containing an error message, if one is available.
+** If an error message is available, leave it in p->zErrMsg.
*/
-SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe *p){
int i;
int rc = SQLITE_OK;
VTable **aVTrans = db->aVTrans;
@@ -104099,9 +107681,7 @@ SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
sqlite3_vtab *pVtab = aVTrans[i]->pVtab;
if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
rc = x(pVtab);
- sqlite3DbFree(db, *pzErrmsg);
- *pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
- sqlite3_free(pVtab->zErrMsg);
+ sqlite3VtabImportErrmsg(p, pVtab);
}
}
db->aVTrans = aVTrans;
@@ -104291,7 +107871,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1);
pNew->xFunc = xFunc;
pNew->pUserData = pArg;
- pNew->flags |= SQLITE_FUNC_EPHEM;
+ pNew->funcFlags |= SQLITE_FUNC_EPHEM;
return pNew;
}
@@ -104393,7 +107973,24 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
*/
-
+/************** Include whereInt.h in the middle of where.c ******************/
+/************** Begin file whereInt.h ****************************************/
+/*
+** 2013-11-12
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains structure and macro definitions for the query
+** planner logic in "where.c". These definitions are broken out into
+** a separate source file for easier editing.
+*/
/*
** Trace output macros
@@ -104403,18 +108000,170 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
#endif
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
-# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X
+# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
+# define WHERETRACE_ENABLED 1
#else
-# define WHERETRACE(X)
+# define WHERETRACE(K,X)
#endif
-/* Forward reference
+/* Forward references
*/
typedef struct WhereClause WhereClause;
typedef struct WhereMaskSet WhereMaskSet;
typedef struct WhereOrInfo WhereOrInfo;
typedef struct WhereAndInfo WhereAndInfo;
-typedef struct WhereCost WhereCost;
+typedef struct WhereLevel WhereLevel;
+typedef struct WhereLoop WhereLoop;
+typedef struct WherePath WherePath;
+typedef struct WhereTerm WhereTerm;
+typedef struct WhereLoopBuilder WhereLoopBuilder;
+typedef struct WhereScan WhereScan;
+typedef struct WhereOrCost WhereOrCost;
+typedef struct WhereOrSet WhereOrSet;
+
+/*
+** This object contains information needed to implement a single nested
+** loop in WHERE clause.
+**
+** Contrast this object with WhereLoop. This object describes the
+** implementation of the loop. WhereLoop describes the algorithm.
+** This object contains a pointer to the WhereLoop algorithm as one of
+** its elements.
+**
+** The WhereInfo object contains a single instance of this object for
+** each term in the FROM clause (which is to say, for each of the
+** nested loops as implemented). The order of WhereLevel objects determines
+** the loop nested order, with WhereInfo.a[0] being the outer loop and
+** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop.
+*/
+struct WhereLevel {
+ int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
+ int iTabCur; /* The VDBE cursor used to access the table */
+ int iIdxCur; /* The VDBE cursor used to access pIdx */
+ int addrBrk; /* Jump here to break out of the loop */
+ int addrNxt; /* Jump here to start the next IN combination */
+ int addrSkip; /* Jump here for next iteration of skip-scan */
+ int addrCont; /* Jump here to continue with the next loop cycle */
+ int addrFirst; /* First instruction of interior of the loop */
+ int addrBody; /* Beginning of the body of this loop */
+ u8 iFrom; /* Which entry in the FROM clause */
+ u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */
+ int p1, p2; /* Operands of the opcode used to ends the loop */
+ union { /* Information that depends on pWLoop->wsFlags */
+ struct {
+ int nIn; /* Number of entries in aInLoop[] */
+ struct InLoop {
+ int iCur; /* The VDBE cursor used by this IN operator */
+ int addrInTop; /* Top of the IN loop */
+ u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
+ } *aInLoop; /* Information about each nested IN operator */
+ } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
+ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
+ } u;
+ struct WhereLoop *pWLoop; /* The selected WhereLoop object */
+ Bitmask notReady; /* FROM entries not usable at this level */
+};
+
+/*
+** Each instance of this object represents an algorithm for evaluating one
+** term of a join. Every term of the FROM clause will have at least
+** one corresponding WhereLoop object (unless INDEXED BY constraints
+** prevent a query solution - which is an error) and many terms of the
+** FROM clause will have multiple WhereLoop objects, each describing a
+** potential way of implementing that FROM-clause term, together with
+** dependencies and cost estimates for using the chosen algorithm.
+**
+** Query planning consists of building up a collection of these WhereLoop
+** objects, then computing a particular sequence of WhereLoop objects, with
+** one WhereLoop object per FROM clause term, that satisfy all dependencies
+** and that minimize the overall cost.
+*/
+struct WhereLoop {
+ Bitmask prereq; /* Bitmask of other loops that must run first */
+ Bitmask maskSelf; /* Bitmask identifying table iTab */
+#ifdef SQLITE_DEBUG
+ char cId; /* Symbolic ID of this loop for debugging use */
+#endif
+ u8 iTab; /* Position in FROM clause of table for this loop */
+ u8 iSortIdx; /* Sorting index number. 0==None */
+ LogEst rSetup; /* One-time setup cost (ex: create transient index) */
+ LogEst rRun; /* Cost of running each loop */
+ LogEst nOut; /* Estimated number of output rows */
+ union {
+ struct { /* Information for internal btree tables */
+ u16 nEq; /* Number of equality constraints */
+ u16 nSkip; /* Number of initial index columns to skip */
+ Index *pIndex; /* Index used, or NULL */
+ } btree;
+ struct { /* Information for virtual tables */
+ int idxNum; /* Index number */
+ u8 needFree; /* True if sqlite3_free(idxStr) is needed */
+ u8 isOrdered; /* True if satisfies ORDER BY */
+ u16 omitMask; /* Terms that may be omitted */
+ char *idxStr; /* Index identifier string */
+ } vtab;
+ } u;
+ u32 wsFlags; /* WHERE_* flags describing the plan */
+ u16 nLTerm; /* Number of entries in aLTerm[] */
+ /**** whereLoopXfer() copies fields above ***********************/
+# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
+ u16 nLSlot; /* Number of slots allocated for aLTerm[] */
+ WhereTerm **aLTerm; /* WhereTerms used */
+ WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
+ WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */
+};
+
+/* This object holds the prerequisites and the cost of running a
+** subquery on one operand of an OR operator in the WHERE clause.
+** See WhereOrSet for additional information
+*/
+struct WhereOrCost {
+ Bitmask prereq; /* Prerequisites */
+ LogEst rRun; /* Cost of running this subquery */
+ LogEst nOut; /* Number of outputs for this subquery */
+};
+
+/* The WhereOrSet object holds a set of possible WhereOrCosts that
+** correspond to the subquery(s) of OR-clause processing. Only the
+** best N_OR_COST elements are retained.
+*/
+#define N_OR_COST 3
+struct WhereOrSet {
+ u16 n; /* Number of valid a[] entries */
+ WhereOrCost a[N_OR_COST]; /* Set of best costs */
+};
+
+
+/* Forward declaration of methods */
+static int whereLoopResize(sqlite3*, WhereLoop*, int);
+
+/*
+** Each instance of this object holds a sequence of WhereLoop objects
+** that implement some or all of a query plan.
+**
+** Think of each WhereLoop object as a node in a graph with arcs
+** showing dependencies and costs for travelling between nodes. (That is
+** not a completely accurate description because WhereLoop costs are a
+** vector, not a scalar, and because dependencies are many-to-one, not
+** one-to-one as are graph nodes. But it is a useful visualization aid.)
+** Then a WherePath object is a path through the graph that visits some
+** or all of the WhereLoop objects once.
+**
+** The "solver" works by creating the N best WherePath objects of length
+** 1. Then using those as a basis to compute the N best WherePath objects
+** of length 2. And so forth until the length of WherePaths equals the
+** number of nodes in the FROM clause. The best (lowest cost) WherePath
+** at the end is the choosen query plan.
+*/
+struct WherePath {
+ Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */
+ Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
+ LogEst nRow; /* Estimated number of rows generated by this path */
+ LogEst rCost; /* Total cost of this path */
+ u8 isOrdered; /* True if this path satisfies ORDER BY */
+ u8 isOrderedValid; /* True if the isOrdered field is valid */
+ WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
+};
/*
** The query generator uses an array of instances of this structure to
@@ -104442,9 +108191,9 @@ typedef struct WhereCost WhereCost;
**
** (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
**
-** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR
+** In this second case, wtFlag has the TERM_ORINFO bit set and eOperator==WO_OR
** and the WhereTerm.u.pOrInfo field points to auxiliary information that
-** is collected about the
+** is collected about the OR clause.
**
** If a term in the WHERE clause does not match either of the two previous
** categories, then eOperator==0. The WhereTerm.pExpr field is still set
@@ -104467,7 +108216,6 @@ typedef struct WhereCost WhereCost;
** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
** is only able to process joins with 64 or fewer tables.
*/
-typedef struct WhereTerm WhereTerm;
struct WhereTerm {
Expr *pExpr; /* Pointer to the subexpression that is this term */
int iParent; /* Disable pWC->a[iParent] when this term disabled */
@@ -104477,6 +108225,7 @@ struct WhereTerm {
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
} u;
+ LogEst truthProb; /* Probability of truth for this expression */
u16 eOperator; /* A WO_xx value describing <op> */
u8 wtFlags; /* TERM_xxx bit flags. See below */
u8 nChild; /* Number of children that must disable us */
@@ -104495,13 +108244,29 @@ struct WhereTerm {
#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
#else
# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
#endif
/*
+** An instance of the WhereScan object is used as an iterator for locating
+** terms in the WHERE clause that are useful to the query planner.
+*/
+struct WhereScan {
+ WhereClause *pOrigWC; /* Original, innermost WhereClause */
+ WhereClause *pWC; /* WhereClause currently being scanned */
+ char *zCollName; /* Required collating sequence, if not NULL */
+ char idxaff; /* Must match this affinity, if zCollName!=NULL */
+ unsigned char nEquiv; /* Number of entries in aEquiv[] */
+ unsigned char iEquiv; /* Next unused slot in aEquiv[] */
+ u32 opMask; /* Acceptable operators */
+ int k; /* Resume scanning at this->pWC->a[this->k] */
+ int aEquiv[22]; /* Cursor,Column pairs for equivalence classes */
+};
+
+/*
** An instance of the following structure holds all information about a
** WHERE clause. Mostly this is a container for one or more WhereTerms.
**
@@ -104514,11 +108279,9 @@ struct WhereTerm {
** subclauses points to the WhereClause object for the whole clause.
*/
struct WhereClause {
- Parse *pParse; /* The parser context */
- WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */
+ WhereInfo *pWInfo; /* WHERE clause processing context */
WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
- u16 wctrlFlags; /* Might include WHERE_AND_ONLY */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
@@ -104578,19 +108341,60 @@ struct WhereMaskSet {
};
/*
-** A WhereCost object records a lookup strategy and the estimated
-** cost of pursuing that strategy.
+** This object is a convenience wrapper holding all information needed
+** to construct WhereLoop objects for a particular query.
*/
-struct WhereCost {
- WherePlan plan; /* The lookup strategy */
- double rCost; /* Overall cost of pursuing this search strategy */
- Bitmask used; /* Bitmask of cursors used by this plan */
+struct WhereLoopBuilder {
+ WhereInfo *pWInfo; /* Information about this WHERE */
+ WhereClause *pWC; /* WHERE clause terms */
+ ExprList *pOrderBy; /* ORDER BY clause */
+ WhereLoop *pNew; /* Template WhereLoop */
+ WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ UnpackedRecord *pRec; /* Probe for stat4 (if required) */
+ int nRecValid; /* Number of valid fields currently in pRec */
+#endif
+};
+
+/*
+** The WHERE clause processing routine has two halves. The
+** first part does the start of the WHERE loop and the second
+** half does the tail of the WHERE loop. An instance of
+** this structure is returned by the first half and passed
+** into the second half to give some continuity.
+**
+** An instance of this object holds the complete state of the query
+** planner.
+*/
+struct WhereInfo {
+ Parse *pParse; /* Parsing and code generating context */
+ SrcList *pTabList; /* List of tables in the join */
+ ExprList *pOrderBy; /* The ORDER BY clause or NULL */
+ ExprList *pResultSet; /* Result set. DISTINCT operates on these */
+ WhereLoop *pLoops; /* List of all WhereLoop objects */
+ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
+ LogEst nRowOut; /* Estimated number of output rows */
+ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
+ u8 bOBSat; /* ORDER BY satisfied by indices */
+ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
+ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
+ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
+ u8 nLevel; /* Number of nested loop */
+ int iTop; /* The very beginning of the WHERE loop */
+ int iContinue; /* Jump here to continue with next record */
+ int iBreak; /* Jump here to break out of the loop */
+ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
+ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
+ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
+ WhereClause sWC; /* Decomposition of the WHERE clause */
+ WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
/*
-** Bitmasks for the operators that indices are able to exploit. An
+** Bitmasks for the operators on WhereTerm objects. These are all
+** operators that are of interest to the query planner. An
** OR-ed combination of these values can be used when searching for
-** terms in the where clause.
+** particular WhereTerms within a WhereClause.
*/
#define WO_IN 0x001
#define WO_EQ 0x002
@@ -104609,74 +108413,136 @@ struct WhereCost {
#define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */
/*
-** Value for wsFlags returned by bestIndex() and stored in
-** WhereLevel.wsFlags. These flags determine which search
-** strategies are appropriate.
-**
-** The least significant 12 bits is reserved as a mask for WO_ values above.
-** The WhereLevel.wsFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
-** But if the table is the right table of a left join, WhereLevel.wsFlags
-** is set to WO_IN|WO_EQ. The WhereLevel.wsFlags field can then be used as
-** the "op" parameter to findTerm when we are resolving equality constraints.
-** ISNULL constraints will then not be used on the right table of a left
-** join. Tickets #2177 and #2189.
-*/
-#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 (...) or x IS NULL */
-#define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
-#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
-#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
-#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
-#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
-#define WHERE_IN_ABLE 0x080f1000 /* 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_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
-#define WHERE_IDX_ONLY 0x00400000 /* Use index only - omit table */
-#define WHERE_ORDERED 0x00800000 /* Output will appear in correct order */
-#define WHERE_REVERSE 0x01000000 /* Scan in reverse order */
-#define WHERE_UNIQUE 0x02000000 /* Selects no more than one row */
-#define WHERE_ALL_UNIQUE 0x04000000 /* This and all prior have one row */
-#define WHERE_OB_UNIQUE 0x00004000 /* Values in ORDER BY columns are
- ** different for every output row */
-#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
-#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
-#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
-#define WHERE_DISTINCT 0x40000000 /* Correct order for DISTINCT */
-#define WHERE_COVER_SCAN 0x80000000 /* Full scan of a covering index */
-
-/*
-** This module contains many separate subroutines that work together to
-** find the best indices to use for accessing a particular table in a query.
-** An instance of the following structure holds context information about the
-** index search so that it can be more easily passed between the various
-** routines.
+** These are definitions of bits in the WhereLoop.wsFlags field.
+** The particular combination of bits in each WhereLoop help to
+** determine the algorithm that WhereLoop represents.
*/
-typedef struct WhereBestIdx WhereBestIdx;
-struct WhereBestIdx {
- Parse *pParse; /* Parser context */
- WhereClause *pWC; /* The WHERE clause */
- struct SrcList_item *pSrc; /* The FROM clause term to search */
- Bitmask notReady; /* Mask of cursors not available */
- Bitmask notValid; /* Cursors not available for any purpose */
- ExprList *pOrderBy; /* The ORDER BY clause */
- ExprList *pDistinct; /* The select-list if query is DISTINCT */
- sqlite3_index_info **ppIdxInfo; /* Index information passed to xBestIndex */
- int i, n; /* Which loop is being coded; # of loops */
- WhereLevel *aLevel; /* Info about outer loops */
- WhereCost cost; /* Lowest cost query plan */
-};
+#define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR */
+#define WHERE_COLUMN_RANGE 0x00000002 /* x<EXPR and/or x>EXPR */
+#define WHERE_COLUMN_IN 0x00000004 /* x IN (...) */
+#define WHERE_COLUMN_NULL 0x00000008 /* x IS NULL */
+#define WHERE_CONSTRAINT 0x0000000f /* Any of the WHERE_COLUMN_xxx values */
+#define WHERE_TOP_LIMIT 0x00000010 /* x<EXPR or x<=EXPR constraint */
+#define WHERE_BTM_LIMIT 0x00000020 /* x>EXPR or x>=EXPR constraint */
+#define WHERE_BOTH_LIMIT 0x00000030 /* Both x>EXPR and x<EXPR */
+#define WHERE_IDX_ONLY 0x00000040 /* Use index only - omit table */
+#define WHERE_IPK 0x00000100 /* x is the INTEGER PRIMARY KEY */
+#define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */
+#define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */
+#define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
+#define WHERE_ONEROW 0x00001000 /* Selects no more than one row */
+#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
+#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
+#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
+
+/************** End of whereInt.h ********************************************/
+/************** Continuing where we left off in where.c **********************/
/*
-** Return TRUE if the probe cost is less than the baseline cost
+** Return the estimated number of output rows from a WHERE clause
*/
-static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
- if( pProbe->rCost<pBaseline->rCost ) return 1;
- if( pProbe->rCost>pBaseline->rCost ) return 0;
- if( pProbe->plan.nOBSat>pBaseline->plan.nOBSat ) return 1;
- if( pProbe->plan.nRow<pBaseline->plan.nRow ) return 1;
- return 0;
+SQLITE_PRIVATE u64 sqlite3WhereOutputRowCount(WhereInfo *pWInfo){
+ return sqlite3LogEstToInt(pWInfo->nRowOut);
+}
+
+/*
+** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
+** WHERE clause returns outputs for DISTINCT processing.
+*/
+SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo *pWInfo){
+ return pWInfo->eDistinct;
+}
+
+/*
+** Return TRUE if the WHERE clause returns rows in ORDER BY order.
+** Return FALSE if the output needs to be sorted.
+*/
+SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo *pWInfo){
+ return pWInfo->bOBSat!=0;
+}
+
+/*
+** Return the VDBE address or label to jump to in order to continue
+** immediately with the next row of a WHERE clause.
+*/
+SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo *pWInfo){
+ return pWInfo->iContinue;
+}
+
+/*
+** Return the VDBE address or label to jump to in order to break
+** out of a WHERE loop.
+*/
+SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo *pWInfo){
+ return pWInfo->iBreak;
+}
+
+/*
+** Return TRUE if an UPDATE or DELETE statement can operate directly on
+** the rowids returned by a WHERE clause. Return FALSE if doing an
+** UPDATE or DELETE might change subsequent WHERE clause results.
+**
+** If the ONEPASS optimization is used (if this routine returns true)
+** then also write the indices of open cursors used by ONEPASS
+** into aiCur[0] and aiCur[1]. iaCur[0] gets the cursor of the data
+** table and iaCur[1] gets the cursor used by an auxiliary index.
+** Either value may be -1, indicating that cursor is not used.
+** Any cursors returned will have been opened for writing.
+**
+** aiCur[0] and aiCur[1] both get -1 if the where-clause logic is
+** unable to use the ONEPASS optimization.
+*/
+SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo *pWInfo, int *aiCur){
+ memcpy(aiCur, pWInfo->aiCurOnePass, sizeof(int)*2);
+ return pWInfo->okOnePass;
+}
+
+/*
+** Move the content of pSrc into pDest
+*/
+static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
+ pDest->n = pSrc->n;
+ memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
+}
+
+/*
+** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet.
+**
+** The new entry might overwrite an existing entry, or it might be
+** appended, or it might be discarded. Do whatever is the right thing
+** so that pSet keeps the N_OR_COST best entries seen so far.
+*/
+static int whereOrInsert(
+ WhereOrSet *pSet, /* The WhereOrSet to be updated */
+ Bitmask prereq, /* Prerequisites of the new entry */
+ LogEst rRun, /* Run-cost of the new entry */
+ LogEst nOut /* Number of outputs for the new entry */
+){
+ u16 i;
+ WhereOrCost *p;
+ for(i=pSet->n, p=pSet->a; i>0; i--, p++){
+ if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
+ goto whereOrInsert_done;
+ }
+ if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){
+ return 0;
+ }
+ }
+ if( pSet->n<N_OR_COST ){
+ p = &pSet->a[pSet->n++];
+ p->nOut = nOut;
+ }else{
+ p = pSet->a;
+ for(i=1; i<pSet->n; i++){
+ if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i;
+ }
+ if( p->rRun<=rRun ) return 0;
+ }
+whereOrInsert_done:
+ p->prereq = prereq;
+ p->rRun = rRun;
+ if( p->nOut>nOut ) p->nOut = nOut;
+ return 1;
}
/*
@@ -104684,17 +108550,13 @@ static int compareCost(const WhereCost *pProbe, const WhereCost *pBaseline){
*/
static void whereClauseInit(
WhereClause *pWC, /* The WhereClause to be initialized */
- Parse *pParse, /* The parsing context */
- WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmasks */
- u16 wctrlFlags /* Might include WHERE_AND_ONLY */
+ WhereInfo *pWInfo /* The WHERE processing context */
){
- pWC->pParse = pParse;
- pWC->pMaskSet = pMaskSet;
+ pWC->pWInfo = pWInfo;
pWC->pOuter = 0;
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
- pWC->wctrlFlags = wctrlFlags;
}
/* Forward reference */
@@ -104723,7 +108585,7 @@ static void whereAndInfoDelete(sqlite3 *db, WhereAndInfo *p){
static void whereClauseClear(WhereClause *pWC){
int i;
WhereTerm *a;
- sqlite3 *db = pWC->pParse->db;
+ sqlite3 *db = pWC->pWInfo->pParse->db;
for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
if( a->wtFlags & TERM_DYNAMIC ){
sqlite3ExprDelete(db, a->pExpr);
@@ -104761,10 +108623,10 @@ static void whereClauseClear(WhereClause *pWC){
static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
WhereTerm *pTerm;
int idx;
- testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */
+ testcase( wtFlags & TERM_VIRTUAL );
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
- sqlite3 *db = pWC->pParse->db;
+ sqlite3 *db = pWC->pWInfo->pParse->db;
pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ){
if( wtFlags & TERM_DYNAMIC ){
@@ -104780,6 +108642,11 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
}
pTerm = &pWC->a[idx = pWC->nTerm++];
+ if( p && ExprHasProperty(p, EP_Unlikely) ){
+ pTerm->truthProb = sqlite3LogEst(p->iTable) - 99;
+ }else{
+ pTerm->truthProb = -1;
+ }
pTerm->pExpr = sqlite3ExprSkipCollate(p);
pTerm->wtFlags = wtFlags;
pTerm->pWC = pWC;
@@ -104804,8 +108671,8 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
** the WhereClause.a[] array. The slot[] array grows as needed to contain
** all terms of the WHERE clause.
*/
-static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
- pWC->op = (u8)op;
+static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
+ pWC->op = op;
if( pExpr==0 ) return;
if( pExpr->op!=op ){
whereClauseInsert(pWC, pExpr, 0);
@@ -104816,9 +108683,9 @@ static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
}
/*
-** Initialize an expression mask set (a WhereMaskSet object)
+** Initialize a WhereMaskSet object
*/
-#define initMaskSet(P) memset(P, 0, sizeof(*P))
+#define initMaskSet(P) (P)->n=0
/*
** Return the bitmask for the given cursor number. Return 0 if
@@ -104829,7 +108696,7 @@ static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){
assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
for(i=0; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){
- return ((Bitmask)1)<<i;
+ return MASKBIT(i);
}
}
return 0;
@@ -104849,18 +108716,9 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
}
/*
-** This routine walks (recursively) an expression tree and generates
+** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
-**
-** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ResolveExprNames() on the expression. See
-** the header comment on that routine for additional information.
-** The sqlite3ResolveExprNames() routines looks for column names and
-** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
-** the VDBE cursor number of the table. This routine just has to
-** translate the cursor numbers into bitmask values and OR all
-** the bitmasks together.
*/
static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*);
static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*);
@@ -104914,14 +108772,7 @@ static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
/*
** Return TRUE if the given operator is one of the operators that is
** allowed for an indexable WHERE clause term. The allowed operators are
-** "=", "<", ">", "<=", ">=", and "IN".
-**
-** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be
-** of one of the following forms: column = expression column > expression
-** column >= expression column < expression column <= expression
-** expression = column expression > column expression >= column
-** expression < column expression <= column column IN
-** (expression-list) column IN (subquery) column IS NULL
+** "=", "<", ">", "<=", ">=", "IN", and "IS NULL"
*/
static int allowedOp(int op){
assert( TK_GT>TK_EQ && TK_GT<TK_GE );
@@ -104941,10 +108792,9 @@ static int allowedOp(int op){
** are converted into "Y op X".
**
** If left/right precedence rules come into play when determining the
-** collating
-** side of the comparison, it remains associated with the same side after
-** the commutation. So "Y collate NOCASE op X" becomes
-** "X op Y". This is because any collation sequence on
+** collating sequence, then COLLATE operators are adjusted to ensure
+** that the collating sequence does not change. For example:
+** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_Collate flag
** is not commuted.
@@ -105002,6 +108852,133 @@ static u16 operatorMask(int op){
}
/*
+** Advance to the next WhereTerm that matches according to the criteria
+** established when the pScan object was initialized by whereScanInit().
+** Return NULL if there are no more matching WhereTerms.
+*/
+static WhereTerm *whereScanNext(WhereScan *pScan){
+ int iCur; /* The cursor on the LHS of the term */
+ int iColumn; /* The column on the LHS of the term. -1 for IPK */
+ Expr *pX; /* An expression being tested */
+ WhereClause *pWC; /* Shorthand for pScan->pWC */
+ WhereTerm *pTerm; /* The term being tested */
+ int k = pScan->k; /* Where to start scanning */
+
+ while( pScan->iEquiv<=pScan->nEquiv ){
+ iCur = pScan->aEquiv[pScan->iEquiv-2];
+ iColumn = pScan->aEquiv[pScan->iEquiv-1];
+ while( (pWC = pScan->pWC)!=0 ){
+ for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
+ if( pTerm->leftCursor==iCur
+ && pTerm->u.leftColumn==iColumn
+ && (pScan->iEquiv<=2 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
+ ){
+ if( (pTerm->eOperator & WO_EQUIV)!=0
+ && pScan->nEquiv<ArraySize(pScan->aEquiv)
+ ){
+ int j;
+ pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
+ assert( pX->op==TK_COLUMN );
+ for(j=0; j<pScan->nEquiv; j+=2){
+ if( pScan->aEquiv[j]==pX->iTable
+ && pScan->aEquiv[j+1]==pX->iColumn ){
+ break;
+ }
+ }
+ if( j==pScan->nEquiv ){
+ pScan->aEquiv[j] = pX->iTable;
+ pScan->aEquiv[j+1] = pX->iColumn;
+ pScan->nEquiv += 2;
+ }
+ }
+ if( (pTerm->eOperator & pScan->opMask)!=0 ){
+ /* Verify the affinity and collating sequence match */
+ if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
+ CollSeq *pColl;
+ Parse *pParse = pWC->pWInfo->pParse;
+ pX = pTerm->pExpr;
+ if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
+ continue;
+ }
+ assert(pX->pLeft);
+ pColl = sqlite3BinaryCompareCollSeq(pParse,
+ pX->pLeft, pX->pRight);
+ if( pColl==0 ) pColl = pParse->db->pDfltColl;
+ if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
+ continue;
+ }
+ }
+ if( (pTerm->eOperator & WO_EQ)!=0
+ && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
+ && pX->iTable==pScan->aEquiv[0]
+ && pX->iColumn==pScan->aEquiv[1]
+ ){
+ continue;
+ }
+ pScan->k = k+1;
+ return pTerm;
+ }
+ }
+ }
+ pScan->pWC = pScan->pWC->pOuter;
+ k = 0;
+ }
+ pScan->pWC = pScan->pOrigWC;
+ k = 0;
+ pScan->iEquiv += 2;
+ }
+ return 0;
+}
+
+/*
+** Initialize a WHERE clause scanner object. Return a pointer to the
+** first match. Return NULL if there are no matches.
+**
+** The scanner will be searching the WHERE clause pWC. It will look
+** for terms of the form "X <op> <expr>" where X is column iColumn of table
+** iCur. The <op> must be one of the operators described by opMask.
+**
+** If the search is for X and the WHERE clause contains terms of the
+** form X=Y then this routine might also return terms of the form
+** "Y <op> <expr>". The number of levels of transitivity is limited,
+** but is enough to handle most commonly occurring SQL statements.
+**
+** If X is not the INTEGER PRIMARY KEY then X must be compatible with
+** index pIdx.
+*/
+static WhereTerm *whereScanInit(
+ WhereScan *pScan, /* The WhereScan object being initialized */
+ WhereClause *pWC, /* The WHERE clause to be scanned */
+ int iCur, /* Cursor to scan for */
+ int iColumn, /* Column to scan for */
+ u32 opMask, /* Operator(s) to scan for */
+ Index *pIdx /* Must be compatible with this index */
+){
+ int j;
+
+ /* memset(pScan, 0, sizeof(*pScan)); */
+ pScan->pOrigWC = pWC;
+ pScan->pWC = pWC;
+ if( pIdx && iColumn>=0 ){
+ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
+ for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
+ if( NEVER(j>=pIdx->nKeyCol) ) return 0;
+ }
+ pScan->zCollName = pIdx->azColl[j];
+ }else{
+ pScan->idxaff = 0;
+ pScan->zCollName = 0;
+ }
+ pScan->opMask = opMask;
+ pScan->k = 0;
+ pScan->aEquiv[0] = iCur;
+ pScan->aEquiv[1] = iColumn;
+ pScan->nEquiv = 2;
+ pScan->iEquiv = 2;
+ return whereScanNext(pScan);
+}
+
+/*
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
** where X is a reference to the iColumn of table iCur and <op> is one of
** the WO_xx operator codes specified by the op parameter.
@@ -105032,84 +109009,20 @@ static WhereTerm *findTerm(
u32 op, /* Mask of WO_xx values describing operator */
Index *pIdx /* Must be compatible with this index, if not NULL */
){
- WhereTerm *pTerm; /* Term being examined as possible result */
- WhereTerm *pResult = 0; /* The answer to return */
- WhereClause *pWCOrig = pWC; /* Original pWC value */
- int j, k; /* Loop counters */
- Expr *pX; /* Pointer to an expression */
- Parse *pParse; /* Parsing context */
- int iOrigCol = iColumn; /* Original value of iColumn */
- int nEquiv = 2; /* Number of entires in aEquiv[] */
- int iEquiv = 2; /* Number of entries of aEquiv[] processed so far */
- int aEquiv[22]; /* iCur,iColumn and up to 10 other equivalents */
-
- assert( iCur>=0 );
- aEquiv[0] = iCur;
- aEquiv[1] = iColumn;
- for(;;){
- for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
- for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
- if( pTerm->leftCursor==iCur
- && pTerm->u.leftColumn==iColumn
- ){
- if( (pTerm->prereqRight & notReady)==0
- && (pTerm->eOperator & op & WO_ALL)!=0
- ){
- if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
- CollSeq *pColl;
- char idxaff;
-
- pX = pTerm->pExpr;
- pParse = pWC->pParse;
- idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
- if( !sqlite3IndexAffinityOk(pX, idxaff) ){
- continue;
- }
-
- /* Figure out the collation sequence required from an index for
- ** it to be useful for optimising expression pX. Store this
- ** value in variable pColl.
- */
- assert(pX->pLeft);
- pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
- if( pColl==0 ) pColl = pParse->db->pDfltColl;
-
- for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
- if( NEVER(j>=pIdx->nColumn) ) return 0;
- }
- if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
- continue;
- }
- }
- if( pTerm->prereqRight==0 && (pTerm->eOperator&WO_EQ)!=0 ){
- pResult = pTerm;
- goto findTerm_success;
- }else if( pResult==0 ){
- pResult = pTerm;
- }
- }
- if( (pTerm->eOperator & WO_EQUIV)!=0
- && nEquiv<ArraySize(aEquiv)
- ){
- pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
- assert( pX->op==TK_COLUMN );
- for(j=0; j<nEquiv; j+=2){
- if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
- }
- if( j==nEquiv ){
- aEquiv[j] = pX->iTable;
- aEquiv[j+1] = pX->iColumn;
- nEquiv += 2;
- }
- }
- }
+ WhereTerm *pResult = 0;
+ WhereTerm *p;
+ WhereScan scan;
+
+ p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx);
+ while( p ){
+ if( (p->prereqRight & notReady)==0 ){
+ if( p->prereqRight==0 && (p->eOperator&WO_EQ)!=0 ){
+ return p;
}
+ if( pResult==0 ) pResult = p;
}
- if( iEquiv>=nEquiv ) break;
- iCur = aEquiv[iEquiv++];
- iColumn = aEquiv[iEquiv++];
+ p = whereScanNext(&scan);
}
-findTerm_success:
return pResult;
}
@@ -105118,8 +109031,6 @@ static void exprAnalyze(SrcList*, WhereClause*, int);
/*
** Call exprAnalyze on all terms in a WHERE clause.
-**
-**
*/
static void exprAnalyzeAll(
SrcList *pTabList, /* the FROM clause */
@@ -105177,13 +109088,10 @@ static int isLikeOrGlob(
pRight = pList->a[0].pExpr;
op = pRight->op;
- if( op==TK_REGISTER ){
- op = pRight->op2;
- }
if( op==TK_VARIABLE ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
- pVal = sqlite3VdbeGetValue(pReprepare, iCol, SQLITE_AFF_NONE);
+ pVal = sqlite3VdbeGetBoundValue(pReprepare, iCol, SQLITE_AFF_NONE);
if( pVal && sqlite3_value_type(pVal)==SQLITE_TEXT ){
z = (char *)sqlite3_value_text(pVal);
}
@@ -105265,8 +109173,10 @@ static int isMatchOfColumn(
** a join, then transfer the appropriate markings over to derived.
*/
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
- pDerived->flags |= pBase->flags & EP_FromJoin;
- pDerived->iRightJoinTable = pBase->iRightJoinTable;
+ if( pDerived ){
+ pDerived->flags |= pBase->flags & EP_FromJoin;
+ pDerived->iRightJoinTable = pBase->iRightJoinTable;
+ }
}
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
@@ -105325,10 +109235,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
** From another point of view, "indexable" means that the subterm could
** potentially be used with an index if an appropriate index exists.
** This analysis does not consider whether or not the index exists; that
-** is something the bestIndex() routine will determine. This analysis
-** only looks at whether subterms appropriate for indexing exist.
+** is decided elsewhere. This analysis only looks at whether subterms
+** appropriate for indexing exist.
**
-** All examples A through E above all satisfy case 2. But if a term
+** All examples A through E above satisfy case 2. But if a term
** also statisfies case 1 (such as B) we know that the optimizer will
** always prefer case 1, so in that case we pretend that case 2 is not
** satisfied.
@@ -105351,11 +109261,11 @@ static void exprAnalyzeOrTerm(
WhereClause *pWC, /* the complete WHERE clause */
int idxTerm /* Index of the OR-term to be analyzed */
){
- Parse *pParse = pWC->pParse; /* Parser context */
+ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
+ Parse *pParse = pWInfo->pParse; /* Parser context */
sqlite3 *db = pParse->db; /* Database connection */
WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */
Expr *pExpr = pTerm->pExpr; /* The expression of the term */
- WhereMaskSet *pMaskSet = pWC->pMaskSet; /* Table use masks */
int i; /* Loop counters */
WhereClause *pOrWc; /* Breakup of pTerm into subterms */
WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */
@@ -105374,7 +109284,7 @@ static void exprAnalyzeOrTerm(
if( pOrInfo==0 ) return;
pTerm->wtFlags |= TERM_ORINFO;
pOrWc = &pOrInfo->wc;
- whereClauseInit(pOrWc, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+ whereClauseInit(pOrWc, pWInfo);
whereSplit(pOrWc, pExpr, TK_OR);
exprAnalyzeAll(pSrc, pOrWc);
if( db->mallocFailed ) return;
@@ -105400,7 +109310,7 @@ static void exprAnalyzeOrTerm(
pOrTerm->wtFlags |= TERM_ANDINFO;
pOrTerm->eOperator = WO_AND;
pAndWC = &pAndInfo->wc;
- whereClauseInit(pAndWC, pWC->pParse, pMaskSet, pWC->wctrlFlags);
+ whereClauseInit(pAndWC, pWC->pWInfo);
whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
exprAnalyzeAll(pSrc, pAndWC);
pAndWC->pOuter = pWC;
@@ -105409,7 +109319,7 @@ static void exprAnalyzeOrTerm(
for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
assert( pAndTerm->pExpr );
if( allowedOp(pAndTerm->pExpr->op) ){
- b |= getMask(pMaskSet, pAndTerm->leftCursor);
+ b |= getMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
}
}
}
@@ -105420,10 +109330,10 @@ static void exprAnalyzeOrTerm(
** corresponding TERM_VIRTUAL term */
}else{
Bitmask b;
- b = getMask(pMaskSet, pOrTerm->leftCursor);
+ b = getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor);
if( pOrTerm->wtFlags & TERM_VIRTUAL ){
WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
- b |= getMask(pMaskSet, pOther->leftCursor);
+ b |= getMask(&pWInfo->sMaskSet, pOther->leftCursor);
}
indexable &= b;
if( (pOrTerm->eOperator & WO_EQ)==0 ){
@@ -105485,7 +109395,7 @@ static void exprAnalyzeOrTerm(
assert( j==1 );
continue;
}
- if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){
+ if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){
/* This term must be of the form t1.a==t2.b where t2 is in the
** chngToIN set but t1 is not. This term will be either preceeded
** or follwed by an inverted copy (t2.b==t1.a). Skip this term
@@ -105504,7 +109414,7 @@ static void exprAnalyzeOrTerm(
** on the second iteration */
assert( j==1 );
assert( IsPowerOfTwo(chngToIN) );
- assert( chngToIN==getMask(pMaskSet, iCursor) );
+ assert( chngToIN==getMask(&pWInfo->sMaskSet, iCursor) );
break;
}
testcase( j==1 );
@@ -105538,8 +109448,6 @@ static void exprAnalyzeOrTerm(
/* At this point, okToChngToIN is true if original pTerm satisfies
** case 1. In that case, construct a new virtual term that is
** pTerm converted into an IN operator.
- **
- ** EV: R-00211-15100
*/
if( okToChngToIN ){
Expr *pDup; /* A transient duplicate expression */
@@ -105553,7 +109461,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
- pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup);
+ pList = sqlite3ExprListAppend(pWInfo->pParse, pList, pDup);
pLeft = pOrTerm->pExpr->pLeft;
}
assert( pLeft!=0 );
@@ -105602,6 +109510,7 @@ static void exprAnalyze(
WhereClause *pWC, /* the WHERE clause */
int idxTerm /* Index of the term to be analyzed */
){
+ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
WhereTerm *pTerm; /* The term to be analyzed */
WhereMaskSet *pMaskSet; /* Set of table index masks */
Expr *pExpr; /* The expression to be analyzed */
@@ -105612,14 +109521,14 @@ static void exprAnalyze(
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
int noCase = 0; /* LIKE/GLOB distinguishes case */
int op; /* Top-level operator. pExpr->op */
- Parse *pParse = pWC->pParse; /* Parsing context */
+ Parse *pParse = pWInfo->pParse; /* Parsing context */
sqlite3 *db = pParse->db; /* Database connection */
if( db->mallocFailed ){
return;
}
pTerm = &pWC->a[idxTerm];
- pMaskSet = pWC->pMaskSet;
+ pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr;
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
@@ -105724,6 +109633,7 @@ static void exprAnalyze(
pNewExpr = sqlite3PExpr(pParse, ops[i],
sqlite3ExprDup(db, pExpr->pLeft, 0),
sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
+ transferJoinMarkings(pNewExpr, pExpr);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
@@ -105780,9 +109690,7 @@ static void exprAnalyze(
** inequality. To avoid this, make sure to also run the full
** LIKE on all candidate expressions by clearing the isComplete flag
*/
- if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */
-
-
+ if( c=='A'-1 ) isComplete = 0;
c = sqlite3UpperToLower[c];
}
*pC = c + 1;
@@ -105793,6 +109701,7 @@ static void exprAnalyze(
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
pStr1, 0);
+ transferJoinMarkings(pNewExpr1, pExpr);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew1==0 );
exprAnalyze(pSrc, pWC, idxNew1);
@@ -105800,6 +109709,7 @@ static void exprAnalyze(
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
pStr2, 0);
+ transferJoinMarkings(pNewExpr2, pExpr);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew2==0 );
exprAnalyze(pSrc, pWC, idxNew2);
@@ -105849,7 +109759,7 @@ static void exprAnalyze(
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/* When sqlite_stat3 histogram data is available an operator of the
** form "x IS NOT NULL" can sometimes be evaluated more efficiently
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
@@ -105863,6 +109773,7 @@ static void exprAnalyze(
if( pExpr->op==TK_NOTNULL
&& pExpr->pLeft->op==TK_COLUMN
&& pExpr->pLeft->iColumn>=0
+ && OptimizationEnabled(db, SQLITE_Stat3)
){
Expr *pNewExpr;
Expr *pLeft = pExpr->pLeft;
@@ -105888,7 +109799,7 @@ static void exprAnalyze(
pNewTerm->prereqAll = pTerm->prereqAll;
}
}
-#endif /* SQLITE_ENABLE_STAT */
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
/* Prevent ON clause terms of a LEFT JOIN from being used to drive
** an index for tables to the left of the join.
@@ -105897,11 +109808,8 @@ static void exprAnalyze(
}
/*
-** This function searches the expression list passed as the second argument
-** for an expression of type TK_COLUMN that refers to the same column and
-** uses the same collation sequence as the iCol'th column of index pIdx.
-** Argument iBase is the cursor number used for the table that pIdx refers
-** to.
+** This function searches pList for a entry that matches the iCol-th column
+** of index pIdx.
**
** If such an expression is found, its index in pList->a[] is returned. If
** no expression is found, -1 is returned.
@@ -105933,76 +109841,17 @@ static int findIndexCol(
}
/*
-** This routine determines if pIdx can be used to assist in processing a
-** DISTINCT qualifier. In other words, it tests whether or not using this
-** index for the outer loop guarantees that rows with equal values for
-** all expressions in the pDistinct list are delivered grouped together.
-**
-** For example, the query
-**
-** SELECT DISTINCT a, b, c FROM tbl WHERE a = ?
-**
-** can benefit from any index on columns "b" and "c".
-*/
-static int isDistinctIndex(
- Parse *pParse, /* Parsing context */
- WhereClause *pWC, /* The WHERE clause */
- Index *pIdx, /* The index being considered */
- int base, /* Cursor number for the table pIdx is on */
- ExprList *pDistinct, /* The DISTINCT expressions */
- int nEqCol /* Number of index columns with == */
-){
- Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
- int i; /* Iterator variable */
-
- assert( pDistinct!=0 );
- if( pIdx->zName==0 || pDistinct->nExpr>=BMS ) return 0;
- testcase( pDistinct->nExpr==BMS-1 );
-
- /* Loop through all the expressions in the distinct list. If any of them
- ** are not simple column references, return early. Otherwise, test if the
- ** WHERE clause contains a "col=X" clause. If it does, the expression
- ** can be ignored. If it does not, and the column does not belong to the
- ** same table as index pIdx, return early. Finally, if there is no
- ** matching "col=X" expression and the column is on the same table as pIdx,
- ** set the corresponding bit in variable mask.
- */
- for(i=0; i<pDistinct->nExpr; i++){
- WhereTerm *pTerm;
- Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
- if( p->op!=TK_COLUMN ) return 0;
- pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
- if( pTerm ){
- Expr *pX = pTerm->pExpr;
- CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
- CollSeq *p2 = sqlite3ExprCollSeq(pParse, p);
- if( p1==p2 ) continue;
- }
- if( p->iTable!=base ) return 0;
- mask |= (((Bitmask)1) << i);
- }
-
- for(i=nEqCol; mask && i<pIdx->nColumn; i++){
- int iExpr = findIndexCol(pParse, pDistinct, base, pIdx, i);
- if( iExpr<0 ) break;
- mask &= ~(((Bitmask)1) << iExpr);
- }
-
- return (mask==0);
-}
-
-
-/*
** Return true if the DISTINCT expression-list passed as the third argument
-** is redundant. A DISTINCT list is redundant if the database contains a
-** UNIQUE index that guarantees that the result of the query will be distinct
-** anyway.
+** is redundant.
+**
+** A DISTINCT list is redundant if the database contains some subset of
+** columns that are unique and non-null.
*/
static int isDistinctRedundant(
- Parse *pParse,
- SrcList *pTabList,
- WhereClause *pWC,
- ExprList *pDistinct
+ Parse *pParse, /* Parsing context */
+ SrcList *pTabList, /* The FROM clause */
+ WhereClause *pWC, /* The WHERE clause */
+ ExprList *pDistinct /* The result set that needs to be DISTINCT */
){
Table *pTab;
Index *pIdx;
@@ -106040,16 +109889,16 @@ static int isDistinctRedundant(
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->onError==OE_None ) continue;
- for(i=0; i<pIdx->nColumn; i++){
- int iCol = pIdx->aiColumn[i];
+ for(i=0; i<pIdx->nKeyCol; i++){
+ i16 iCol = pIdx->aiColumn[i];
if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){
int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i);
- if( iIdxCol<0 || pTab->aCol[pIdx->aiColumn[i]].notNull==0 ){
+ if( iIdxCol<0 || pTab->aCol[iCol].notNull==0 ){
break;
}
}
}
- if( i==pIdx->nColumn ){
+ if( i==pIdx->nKeyCol ){
/* This index implies that the DISTINCT qualifier is redundant. */
return 1;
}
@@ -106058,21 +109907,13 @@ static int isDistinctRedundant(
return 0;
}
+
/*
-** Prepare a crude estimate of the logarithm of the input value.
-** The results need not be exact. This is only used for estimating
-** the total cost of performing operations with O(logN) or O(NlogN)
-** complexity. Because N is just a guess, it is no great tragedy if
-** logN is a little off.
+** Estimate the logarithm of the input value to base 2.
*/
-static double estLog(double N){
- double logN = 1;
- double x = 10;
- while( N>x ){
- logN += 1;
- x *= 10;
- }
- return logN;
+static LogEst estLog(LogEst N){
+ LogEst x = sqlite3LogEst(N);
+ return x>33 ? x - 33 : 0;
}
/*
@@ -106081,7 +109922,7 @@ static double estLog(double N){
** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
** are no-ops.
*/
-#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_DEBUG)
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
int i;
if( !sqlite3WhereTrace ) return;
@@ -106113,113 +109954,13 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
sqlite3DebugPrintf(" idxStr=%s\n", p->idxStr);
sqlite3DebugPrintf(" orderByConsumed=%d\n", p->orderByConsumed);
sqlite3DebugPrintf(" estimatedCost=%g\n", p->estimatedCost);
+ sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
}
#else
#define TRACE_IDX_INPUTS(A)
#define TRACE_IDX_OUTPUTS(A)
#endif
-/*
-** Required because bestIndex() is called by bestOrClauseIndex()
-*/
-static void bestIndex(WhereBestIdx*);
-
-/*
-** 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(WhereBestIdx *p){
-#ifndef SQLITE_OMIT_OR_OPTIMIZATION
- WhereClause *pWC = p->pWC; /* The WHERE clause */
- struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
- const int iCur = pSrc->iCursor; /* The cursor of the table */
- 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 */
-
- /* The OR-clause optimization is disallowed if the INDEXED BY or
- ** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */
- if( pSrc->notIndexed || pSrc->pIndex!=0 ){
- return;
- }
- if( pWC->wctrlFlags & WHERE_AND_ONLY ){
- return;
- }
-
- /* Search the WHERE clause terms for a usable WO_OR term. */
- for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
- if( (pTerm->eOperator & WO_OR)!=0
- && ((pTerm->prereqAll & ~maskSrc) & p->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;
- Bitmask used = 0;
- WhereBestIdx sBOI;
-
- sBOI = *p;
- sBOI.pOrderBy = 0;
- sBOI.pDistinct = 0;
- sBOI.ppIdxInfo = 0;
- for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
- WHERETRACE(("... Multi-index OR testing for term %d of %d....\n",
- (pOrTerm - pOrWC->a), (pTerm - pWC->a)
- ));
- if( (pOrTerm->eOperator& WO_AND)!=0 ){
- sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
- bestIndex(&sBOI);
- }else if( pOrTerm->leftCursor==iCur ){
- WhereClause tempWC;
- tempWC.pParse = pWC->pParse;
- tempWC.pMaskSet = pWC->pMaskSet;
- tempWC.pOuter = pWC;
- tempWC.op = TK_AND;
- tempWC.a = pOrTerm;
- tempWC.wctrlFlags = 0;
- tempWC.nTerm = 1;
- sBOI.pWC = &tempWC;
- bestIndex(&sBOI);
- }else{
- continue;
- }
- rTotal += sBOI.cost.rCost;
- nRow += sBOI.cost.plan.nRow;
- used |= sBOI.cost.used;
- if( rTotal>=p->cost.rCost ) break;
- }
-
- /* If there is an ORDER BY clause, increase the scan cost to account
- ** for the cost of the sort. */
- if( p->pOrderBy!=0 ){
- WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
- rTotal, rTotal+nRow*estLog(nRow)));
- rTotal += nRow*estLog(nRow);
- }
-
- /* 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<p->cost.rCost ){
- p->cost.rCost = rTotal;
- p->cost.used = used;
- p->cost.plan.nRow = nRow;
- p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
- p->cost.plan.wsFlags = flags;
- p->cost.plan.u.pTerm = pTerm;
- }
- }
- }
-#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
-}
-
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
** Return TRUE if the WHERE clause term pTerm is of a form where it
@@ -106235,88 +109976,13 @@ static int termCanDriveIndex(
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
+ if( pTerm->u.leftColumn<0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
return 1;
}
#endif
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
-/*
-** If the query plan for pSrc specified in pCost is a full table scan
-** and indexing is allows (if there is no NOT INDEXED clause) and it
-** possible to construct a transient index that would perform better
-** than a full table scan even when the cost of constructing the index
-** is taken into account, then alter the query plan to use the
-** transient index.
-*/
-static void bestAutomaticIndex(WhereBestIdx *p){
- Parse *pParse = p->pParse; /* The parsing context */
- WhereClause *pWC = p->pWC; /* The WHERE clause */
- struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
- double nTableRow; /* Rows in the input table */
- double logN; /* log(nTableRow) */
- double costTempIdx; /* per-query cost of the transient index */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
- WhereTerm *pWCEnd; /* End of pWC->a[] */
- Table *pTable; /* Table tht might be indexed */
-
- if( pParse->nQueryLoop<=(double)1 ){
- /* There is no point in building an automatic index for a single scan */
- return;
- }
- if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){
- /* Automatic indices are disabled at run-time */
- return;
- }
- if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0
- && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0
- ){
- /* We already have some kind of index in use for this query. */
- return;
- }
- if( pSrc->viaCoroutine ){
- /* Cannot index a co-routine */
- return;
- }
- if( pSrc->notIndexed ){
- /* The NOT INDEXED clause appears in the SQL. */
- return;
- }
- if( pSrc->isCorrelated ){
- /* The source is a correlated sub-query. No point in indexing it. */
- return;
- }
-
- assert( pParse->nQueryLoop >= (double)1 );
- pTable = pSrc->pTab;
- nTableRow = pTable->nRowEst;
- logN = estLog(nTableRow);
- costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
- if( costTempIdx>=p->cost.rCost ){
- /* The cost of creating the transient table would be greater than
- ** doing the full table scan */
- return;
- }
-
- /* Search for any equality comparison term */
- pWCEnd = &pWC->a[pWC->nTerm];
- for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
- if( termCanDriveIndex(pTerm, pSrc, p->notReady) ){
- WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
- p->cost.rCost, costTempIdx));
- p->cost.rCost = costTempIdx;
- p->cost.plan.nRow = logN + 1;
- p->cost.plan.wsFlags = WHERE_TEMP_INDEX;
- p->cost.used = pTerm->prereqRight;
- break;
- }
- }
-}
-#else
-# define bestAutomaticIndex(A) /* no-op */
-#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
-
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/*
@@ -106331,23 +109997,24 @@ static void constructAutomaticIndex(
Bitmask notReady, /* Mask of cursors that are not available */
WhereLevel *pLevel /* Write new index here */
){
- int nColumn; /* Number of columns in the constructed index */
+ int nKeyCol; /* Number of columns in the constructed index */
WhereTerm *pTerm; /* A single term of the WHERE clause */
WhereTerm *pWCEnd; /* End of pWC->a[] */
- int nByte; /* Byte of memory needed for pIdx */
Index *pIdx; /* Object describing the transient index */
Vdbe *v; /* Prepared statement under construction */
int addrInit; /* Address of the initialization bypass jump */
Table *pTable; /* The table being indexed */
- KeyInfo *pKeyinfo; /* Key information for the index */
int addrTop; /* Top of the index fill loop */
int regRecord; /* Register holding an index record */
int n; /* Column counter */
int i; /* Loop counter */
int mxBitCol; /* Maximum column in pSrc->colUsed */
CollSeq *pColl; /* Collating sequence to on a column */
+ WhereLoop *pLoop; /* The Loop object */
+ char *zNotUsed; /* Extra space on the end of pIdx */
Bitmask idxCols; /* Bitmap of columns used for indexing */
Bitmask extraCols; /* Bitmap of additional columns */
+ u8 sentWarning = 0; /* True if a warnning has been issued */
/* Generate code to skip over the creation and initialization of the
** transient index on 2nd and subsequent iterations of the loop. */
@@ -106357,24 +110024,34 @@ static void constructAutomaticIndex(
/* Count the number of columns that will be added to the index
** and used to match WHERE clause constraints */
- nColumn = 0;
+ nKeyCol = 0;
pTable = pSrc->pTab;
pWCEnd = &pWC->a[pWC->nTerm];
+ pLoop = pLevel->pWLoop;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol = pTerm->u.leftColumn;
- Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
+ Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
+ if( !sentWarning ){
+ sqlite3_log(SQLITE_WARNING_AUTOINDEX,
+ "automatic index on %s(%s)", pTable->zName,
+ pTable->aCol[iCol].zName);
+ sentWarning = 1;
+ }
if( (idxCols & cMask)==0 ){
- nColumn++;
+ if( whereLoopResize(pParse->db, pLoop, nKeyCol+1) ) return;
+ pLoop->aLTerm[nKeyCol++] = pTerm;
idxCols |= cMask;
}
}
}
- assert( nColumn>0 );
- pLevel->plan.nEq = nColumn;
+ assert( nKeyCol>0 );
+ pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
+ pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
+ | WHERE_AUTO_INDEX;
/* Count the number of additional columns needed to create a
** covering index. A "covering index" is an index that contains all
@@ -106384,38 +110061,32 @@ static void constructAutomaticIndex(
** original table changes and the index and table cannot both be used
** if they go out of sync.
*/
- extraCols = pSrc->colUsed & (~idxCols | (((Bitmask)1)<<(BMS-1)));
+ extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol;
testcase( pTable->nCol==BMS-1 );
testcase( pTable->nCol==BMS-2 );
for(i=0; i<mxBitCol; i++){
- if( extraCols & (((Bitmask)1)<<i) ) nColumn++;
+ if( extraCols & MASKBIT(i) ) nKeyCol++;
}
- if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
- nColumn += pTable->nCol - BMS + 1;
+ if( pSrc->colUsed & MASKBIT(BMS-1) ){
+ nKeyCol += pTable->nCol - BMS + 1;
}
- pLevel->plan.wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WO_EQ;
+ pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY;
/* Construct the Index object to describe this index */
- nByte = sizeof(Index);
- nByte += nColumn*sizeof(int); /* Index.aiColumn */
- nByte += nColumn*sizeof(char*); /* Index.azColl */
- nByte += nColumn; /* Index.aSortOrder */
- pIdx = sqlite3DbMallocZero(pParse->db, nByte);
+ pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed);
if( pIdx==0 ) return;
- pLevel->plan.u.pIdx = pIdx;
- pIdx->azColl = (char**)&pIdx[1];
- pIdx->aiColumn = (int*)&pIdx->azColl[nColumn];
- pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn];
+ pLoop->u.btree.pIndex = pIdx;
pIdx->zName = "auto-index";
- pIdx->nColumn = nColumn;
pIdx->pTable = pTable;
n = 0;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol = pTerm->u.leftColumn;
- Bitmask cMask = iCol>=BMS ? ((Bitmask)1)<<(BMS-1) : ((Bitmask)1)<<iCol;
+ Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
+ testcase( iCol==BMS-1 );
+ testcase( iCol==BMS );
if( (idxCols & cMask)==0 ){
Expr *pX = pTerm->pExpr;
idxCols |= cMask;
@@ -106426,37 +110097,39 @@ static void constructAutomaticIndex(
}
}
}
- assert( (u32)n==pLevel->plan.nEq );
+ assert( (u32)n==pLoop->u.btree.nEq );
/* Add additional columns needed to make the automatic index into
** a covering index */
for(i=0; i<mxBitCol; i++){
- if( extraCols & (((Bitmask)1)<<i) ){
+ if( extraCols & MASKBIT(i) ){
pIdx->aiColumn[n] = i;
pIdx->azColl[n] = "BINARY";
n++;
}
}
- if( pSrc->colUsed & (((Bitmask)1)<<(BMS-1)) ){
+ if( pSrc->colUsed & MASKBIT(BMS-1) ){
for(i=BMS-1; i<pTable->nCol; i++){
pIdx->aiColumn[n] = i;
pIdx->azColl[n] = "BINARY";
n++;
}
}
- assert( n==nColumn );
+ assert( n==nKeyCol );
+ pIdx->aiColumn[n] = -1;
+ pIdx->azColl[n] = "BINARY";
/* Create the automatic index */
- pKeyinfo = sqlite3IndexKeyinfo(pParse, pIdx);
assert( pLevel->iIdxCur>=0 );
- sqlite3VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0,
- (char*)pKeyinfo, P4_KEYINFO_HANDOFF);
+ pLevel->iIdxCur = pParse->nTab++;
+ sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
+ sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "for %s", pTable->zName));
/* Fill the automatic index with content */
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur);
regRecord = sqlite3GetTempReg(pParse);
- sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1);
+ sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
@@ -106475,11 +110148,12 @@ static void constructAutomaticIndex(
** 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(WhereBestIdx *p){
- Parse *pParse = p->pParse;
- WhereClause *pWC = p->pWC;
- struct SrcList_item *pSrc = p->pSrc;
- ExprList *pOrderBy = p->pOrderBy;
+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;
@@ -106489,8 +110163,6 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
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++){
@@ -106526,7 +110198,6 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
+ sizeof(*pIdxOrderBy)*nOrderBy );
if( pIdxInfo==0 ){
sqlite3ErrorMsg(pParse, "out of memory");
- /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
return 0;
}
@@ -106582,8 +110253,8 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
/*
** 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.
+** method of the virtual table with the sqlite3_index_info object that
+** comes in as the 3rd argument to this function.
**
** 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
@@ -106598,7 +110269,6 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
int i;
int rc;
- WHERETRACE(("xBestIndex for %s\n", pTab->zName));
TRACE_IDX_INPUTS(p);
rc = pVtab->pModule->xBestIndex(pVtab, p);
TRACE_IDX_OUTPUTS(p);
@@ -106624,209 +110294,10 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
return pParse->nErr;
}
+#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
-/*
-** Compute the best index for a virtual table.
-**
-** The best index is computed by the xBestIndex method of the virtual
-** table module. This routine is really just a wrapper that sets up
-** the sqlite3_index_info structure that is used to communicate with
-** xBestIndex.
-**
-** In a join, this routine might be called multiple times for the
-** same virtual table. The sqlite3_index_info structure is created
-** and initialized on the first invocation and reused on all subsequent
-** invocations. The sqlite3_index_info structure is also used when
-** code is generated to access the virtual table. The whereInfoDelete()
-** routine takes care of freeing the sqlite3_index_info structure after
-** everybody has finished with it.
-*/
-static void bestVirtualIndex(WhereBestIdx *p){
- Parse *pParse = p->pParse; /* The parsing context */
- WhereClause *pWC = p->pWC; /* The WHERE clause */
- struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
- Table *pTab = pSrc->pTab;
- sqlite3_index_info *pIdxInfo;
- struct sqlite3_index_constraint *pIdxCons;
- struct sqlite3_index_constraint_usage *pUsage;
- WhereTerm *pTerm;
- int i, j;
- int nOrderBy;
- int bAllowIN; /* Allow IN optimizations */
- double rCost;
-
- /* 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(&p->cost, 0, sizeof(p->cost));
- p->cost.plan.wsFlags = WHERE_VIRTUALTABLE;
-
- /* If the sqlite3_index_info structure has not been previously
- ** allocated and initialized, then allocate and initialize it now.
- */
- pIdxInfo = *p->ppIdxInfo;
- if( pIdxInfo==0 ){
- *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p);
- }
- if( pIdxInfo==0 ){
- return;
- }
-
- /* At this point, the sqlite3_index_info structure that pIdxInfo points
- ** to will have been initialized, either during the current invocation or
- ** during some prior invocation. Now we just have to customize the
- ** details of pIdxInfo for the current invocation and pass it to
- ** xBestIndex.
- */
-
- /* The module name must be defined. Also, by this point there must
- ** be a pointer to an sqlite3_vtab structure. Otherwise
- ** sqlite3ViewGetColumnNames() would have picked up the error.
- */
- assert( pTab->azModuleArg && pTab->azModuleArg[0] );
- assert( sqlite3GetVTable(pParse->db, pTab) );
-
- /* Try once or twice. On the first attempt, allow IN optimizations.
- ** If an IN optimization is accepted by the virtual table xBestIndex
- ** method, but the pInfo->aConstrainUsage.omit flag is not set, then
- ** the query will not work because it might allow duplicate rows in
- ** output. In that case, run the xBestIndex method a second time
- ** without the IN constraints. Usually this loop only runs once.
- ** The loop will exit using a "break" statement.
- */
- for(bAllowIN=1; 1; bAllowIN--){
- assert( bAllowIN==0 || bAllowIN==1 );
-
- /* Set the aConstraint[].usable fields and initialize all
- ** output variables to zero.
- **
- ** aConstraint[].usable is true for constraints where the right-hand
- ** side contains only references to tables to the left of the current
- ** table. In other words, if the constraint is of the form:
- **
- ** column = expr
- **
- ** and we are evaluating a join, then the constraint on column is
- ** only valid if all tables referenced in expr occur to the left
- ** of the table containing column.
- **
- ** The aConstraints[] array contains entries for all constraints
- ** on the current table. That way we only have to compute it once
- ** even though we might try to pick the best index multiple times.
- ** For each attempt at picking an index, the order of tables in the
- ** join might be different so we have to recompute the usable flag
- ** each time.
- */
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- pUsage = pIdxInfo->aConstraintUsage;
- for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
- j = pIdxCons->iTermOffset;
- pTerm = &pWC->a[j];
- if( (pTerm->prereqRight&p->notReady)==0
- && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
- ){
- pIdxCons->usable = 1;
- }else{
- pIdxCons->usable = 0;
- }
- }
- memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
- if( pIdxInfo->needToFreeIdxStr ){
- sqlite3_free(pIdxInfo->idxStr);
- }
- pIdxInfo->idxStr = 0;
- pIdxInfo->idxNum = 0;
- pIdxInfo->needToFreeIdxStr = 0;
- pIdxInfo->orderByConsumed = 0;
- /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
- pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
- nOrderBy = pIdxInfo->nOrderBy;
- if( !p->pOrderBy ){
- pIdxInfo->nOrderBy = 0;
- }
-
- if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
- return;
- }
-
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
- if( pUsage[i].argvIndex>0 ){
- j = pIdxCons->iTermOffset;
- pTerm = &pWC->a[j];
- p->cost.used |= pTerm->prereqRight;
- if( (pTerm->eOperator & WO_IN)!=0 ){
- if( pUsage[i].omit==0 ){
- /* Do not attempt to use an IN constraint if the virtual table
- ** says that the equivalent EQ constraint cannot be safely omitted.
- ** If we do attempt to use such a constraint, some rows might be
- ** repeated in the output. */
- break;
- }
- /* A virtual table that is constrained by an IN clause may not
- ** consume the ORDER BY clause because (1) the order of IN terms
- ** is not necessarily related to the order of output terms and
- ** (2) Multiple outputs from a single IN value will not merge
- ** together. */
- pIdxInfo->orderByConsumed = 0;
- }
- }
- }
- if( i>=pIdxInfo->nConstraint ) break;
- }
-
- /* The orderByConsumed signal is only valid if all outer loops collectively
- ** generate just a single row of output.
- */
- if( pIdxInfo->orderByConsumed ){
- for(i=0; i<p->i; i++){
- if( (p->aLevel[i].plan.wsFlags & WHERE_UNIQUE)==0 ){
- pIdxInfo->orderByConsumed = 0;
- }
- }
- }
-
- /* If there is an ORDER BY clause, and the selected virtual table index
- ** does not satisfy it, increase the cost of the scan accordingly. This
- ** matches the processing for non-virtual tables in bestBtreeIndex().
- */
- rCost = pIdxInfo->estimatedCost;
- if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
- rCost += estLog(rCost)*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.
- **
- ** Use "(double)2" instead of "2.0" in case OMIT_FLOATING_POINT
- ** is defined.
- */
- if( (SQLITE_BIG_DBL/((double)2))<rCost ){
- p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
- }else{
- p->cost.rCost = rCost;
- }
- p->cost.plan.u.pVtabIdx = pIdxInfo;
- if( pIdxInfo->orderByConsumed ){
- p->cost.plan.wsFlags |= WHERE_ORDERED;
- p->cost.plan.nOBSat = nOrderBy;
- }else{
- p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
- }
- p->cost.plan.nEq = 0;
- pIdxInfo->nOrderBy = nOrderBy;
-
- /* Try to find a more efficient access pattern by using multiple indexes
- ** to optimize an OR expression within the WHERE clause.
- */
- bestOrClauseIndex(p);
-}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Estimate the location of a particular key among all keys in an
** index. Store the results in aStat as follows:
@@ -106836,140 +110307,75 @@ static void bestVirtualIndex(WhereBestIdx *p){
**
** Return SQLITE_OK on success.
*/
-static int whereKeyStats(
+static void whereKeyStats(
Parse *pParse, /* Database connection */
Index *pIdx, /* Index to consider domain of */
- sqlite3_value *pVal, /* Value to consider */
+ UnpackedRecord *pRec, /* Vector of values to consider */
int roundUp, /* Round up if true. Round down if false */
tRowcnt *aStat /* OUT: stats written here */
){
- tRowcnt n;
- IndexSample *aSample;
- int i, eType;
- int isEq = 0;
- i64 v;
- double r, rS;
+ IndexSample *aSample = pIdx->aSample;
+ int iCol; /* Index of required stats in anEq[] etc. */
+ int iMin = 0; /* Smallest sample not yet tested */
+ int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */
+ int iTest; /* Next sample to test */
+ int res; /* Result of comparison operation */
- assert( roundUp==0 || roundUp==1 );
+#ifndef SQLITE_DEBUG
+ UNUSED_PARAMETER( pParse );
+#endif
+ assert( pRec!=0 );
+ iCol = pRec->nField - 1;
assert( pIdx->nSample>0 );
- if( pVal==0 ) return SQLITE_ERROR;
- n = pIdx->aiRowEst[0];
- aSample = pIdx->aSample;
- eType = sqlite3_value_type(pVal);
-
- if( eType==SQLITE_INTEGER ){
- v = sqlite3_value_int64(pVal);
- r = (i64)v;
- for(i=0; i<pIdx->nSample; i++){
- if( aSample[i].eType==SQLITE_NULL ) continue;
- if( aSample[i].eType>=SQLITE_TEXT ) break;
- if( aSample[i].eType==SQLITE_INTEGER ){
- if( aSample[i].u.i>=v ){
- isEq = aSample[i].u.i==v;
- break;
- }
- }else{
- assert( aSample[i].eType==SQLITE_FLOAT );
- if( aSample[i].u.r>=r ){
- isEq = aSample[i].u.r==r;
- break;
- }
- }
- }
- }else if( eType==SQLITE_FLOAT ){
- r = sqlite3_value_double(pVal);
- for(i=0; i<pIdx->nSample; i++){
- if( aSample[i].eType==SQLITE_NULL ) continue;
- if( aSample[i].eType>=SQLITE_TEXT ) break;
- if( aSample[i].eType==SQLITE_FLOAT ){
- rS = aSample[i].u.r;
- }else{
- rS = aSample[i].u.i;
- }
- if( rS>=r ){
- isEq = rS==r;
- break;
- }
+ assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
+ do{
+ iTest = (iMin+i)/2;
+ res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
+ if( res<0 ){
+ iMin = iTest+1;
+ }else{
+ i = iTest;
}
- }else if( eType==SQLITE_NULL ){
- i = 0;
- if( aSample[0].eType==SQLITE_NULL ) isEq = 1;
+ }while( res && iMin<i );
+
+#ifdef SQLITE_DEBUG
+ /* The following assert statements check that the binary search code
+ ** above found the right answer. This block serves no purpose other
+ ** than to invoke the asserts. */
+ if( res==0 ){
+ /* If (res==0) is true, then sample $i must be equal to pRec */
+ assert( i<pIdx->nSample );
+ assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
+ || pParse->db->mallocFailed );
}else{
- assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
- for(i=0; i<pIdx->nSample; i++){
- if( aSample[i].eType==SQLITE_TEXT || aSample[i].eType==SQLITE_BLOB ){
- break;
- }
- }
- if( i<pIdx->nSample ){
- sqlite3 *db = pParse->db;
- CollSeq *pColl;
- const u8 *z;
- if( eType==SQLITE_BLOB ){
- z = (const u8 *)sqlite3_value_blob(pVal);
- pColl = db->pDfltColl;
- assert( pColl->enc==SQLITE_UTF8 );
- }else{
- pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
- if( pColl==0 ){
- return SQLITE_ERROR;
- }
- z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
- if( !z ){
- return SQLITE_NOMEM;
- }
- assert( z && pColl && pColl->xCmp );
- }
- n = sqlite3ValueBytes(pVal, pColl->enc);
-
- for(; i<pIdx->nSample; i++){
- int c;
- int eSampletype = aSample[i].eType;
- if( eSampletype<eType ) continue;
- if( eSampletype!=eType ) break;
-#ifndef SQLITE_OMIT_UTF16
- if( pColl->enc!=SQLITE_UTF8 ){
- int nSample;
- char *zSample = sqlite3Utf8to16(
- db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample
- );
- if( !zSample ){
- assert( db->mallocFailed );
- return SQLITE_NOMEM;
- }
- c = pColl->xCmp(pColl->pUser, nSample, zSample, n, z);
- sqlite3DbFree(db, zSample);
- }else
-#endif
- {
- c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
- }
- if( c>=0 ){
- if( c==0 ) isEq = 1;
- break;
- }
- }
- }
+ /* Otherwise, pRec must be smaller than sample $i and larger than
+ ** sample ($i-1). */
+ assert( i==pIdx->nSample
+ || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
+ || pParse->db->mallocFailed );
+ assert( i==0
+ || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
+ || pParse->db->mallocFailed );
}
+#endif /* ifdef SQLITE_DEBUG */
/* At this point, aSample[i] is the first sample that is greater than
** or equal to pVal. Or if i==pIdx->nSample, then all samples are less
- ** than pVal. If aSample[i]==pVal, then isEq==1.
+ ** than pVal. If aSample[i]==pVal, then res==0.
*/
- if( isEq ){
- assert( i<pIdx->nSample );
- aStat[0] = aSample[i].nLt;
- aStat[1] = aSample[i].nEq;
+ if( res==0 ){
+ aStat[0] = aSample[i].anLt[iCol];
+ aStat[1] = aSample[i].anEq[iCol];
}else{
tRowcnt iLower, iUpper, iGap;
if( i==0 ){
iLower = 0;
- iUpper = aSample[0].nLt;
+ iUpper = aSample[0].anLt[iCol];
}else{
- iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
- iLower = aSample[i-1].nEq + aSample[i-1].nLt;
+ iUpper = i>=pIdx->nSample ? pIdx->aiRowEst[0] : aSample[i].anLt[iCol];
+ iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol];
}
- aStat[1] = pIdx->avgEq;
+ aStat[1] = (pIdx->nKeyCol>iCol ? pIdx->aAvgEq[iCol] : 1);
if( iLower>=iUpper ){
iGap = 0;
}else{
@@ -106982,44 +110388,8 @@ static int whereKeyStats(
}
aStat[0] = iLower + iGap;
}
- return SQLITE_OK;
-}
-#endif /* SQLITE_ENABLE_STAT3 */
-
-/*
-** If expression pExpr represents a literal value, set *pp to point to
-** an sqlite3_value structure containing the same value, with affinity
-** aff applied to it, before returning. It is the responsibility of the
-** caller to eventually release this structure by passing it to
-** sqlite3ValueFree().
-**
-** If the current parse is a recompile (sqlite3Reprepare()) and pExpr
-** is an SQL variable that currently has a non-NULL value bound to it,
-** create an sqlite3_value structure containing this value, again with
-** affinity aff applied to it, instead.
-**
-** If neither of the above apply, set *pp to NULL.
-**
-** If an error occurs, return an error code. Otherwise, SQLITE_OK.
-*/
-#ifdef SQLITE_ENABLE_STAT3
-static int valueFromExpr(
- Parse *pParse,
- Expr *pExpr,
- u8 aff,
- sqlite3_value **pp
-){
- if( pExpr->op==TK_VARIABLE
- || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
- ){
- int iVar = pExpr->iColumn;
- sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
- *pp = sqlite3VdbeGetValue(pParse->pReprepare, iVar, aff);
- return SQLITE_OK;
- }
- return sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, aff, pp);
}
-#endif
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
/*
** This function is used to estimate the number of rows that will be visited
@@ -107036,97 +110406,161 @@ static int valueFromExpr(
** If either of the upper or lower bound is not present, then NULL is passed in
** place of the corresponding WhereTerm.
**
-** The nEq parameter is passed the index of the index column subject to the
-** range constraint. Or, equivalently, the number of equality constraints
-** optimized by the proposed index scan. For example, assuming index p is
-** on t1(a, b), and the SQL query is:
+** The value in (pBuilder->pNew->u.btree.nEq) is the index of the index
+** column subject to the range constraint. Or, equivalently, the number of
+** equality constraints optimized by the proposed index scan. For example,
+** assuming index p is on t1(a, b), and the SQL query is:
**
** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ...
**
-** then nEq should be passed the value 1 (as the range restricted column,
-** b, is the second left-most column of the index). Or, if the query is:
+** then nEq is set to 1 (as the range restricted column, b, is the second
+** left-most column of the index). Or, if the query is:
**
** ... FROM t1 WHERE a > ? AND a < ? ...
**
-** then nEq should be passed 0.
+** then nEq is set to 0.
**
-** The returned value is an integer divisor to reduce the estimated
-** search space. A return value of 1 means that range constraints are
-** no help at all. A return value of 2 means range constraints are
-** expected to reduce the search space by half. And so forth...
-**
-** In the absence of sqlite_stat3 ANALYZE data, each range inequality
-** reduces the search space by a factor of 4. Hence a single constraint (x>?)
-** results in a return of 4 and a range constraint (x>? AND x<?) results
-** in a return of 16.
+** When this function is called, *pnOut is set to the sqlite3LogEst() of the
+** number of rows that the index scan is expected to visit without
+** considering the range constraints. If nEq is 0, this is the number of
+** rows in the index. Assuming no error occurs, *pnOut is adjusted (reduced)
+** to account for the range contraints pLower and pUpper.
+**
+** In the absence of sqlite_stat4 ANALYZE data, or if such data cannot be
+** used, each range inequality reduces the search space by a factor of 4.
+** Hence a pair of constraints (x>? AND x<?) reduces the expected number of
+** rows visited by a factor of 16.
*/
static int whereRangeScanEst(
Parse *pParse, /* Parsing & code generating context */
- Index *p, /* The index containing the range-compared column; "x" */
- int nEq, /* index into p->aCol[] of the range-compared column */
+ WhereLoopBuilder *pBuilder,
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
- double *pRangeDiv /* OUT: Reduce search space by this divisor */
+ WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */
){
int rc = SQLITE_OK;
+ int nOut = pLoop->nOut;
+ LogEst nNew;
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ Index *p = pLoop->u.btree.pIndex;
+ int nEq = pLoop->u.btree.nEq;
- if( nEq==0 && p->nSample ){
- sqlite3_value *pRangeVal;
- tRowcnt iLower = 0;
- tRowcnt iUpper = p->aiRowEst[0];
+ if( p->nSample>0
+ && nEq==pBuilder->nRecValid
+ && nEq<p->nSampleCol
+ && OptimizationEnabled(pParse->db, SQLITE_Stat3)
+ ){
+ UnpackedRecord *pRec = pBuilder->pRec;
tRowcnt a[2];
- u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
+ u8 aff;
+
+ /* Variable iLower will be set to the estimate of the number of rows in
+ ** the index that are less than the lower bound of the range query. The
+ ** lower bound being the concatenation of $P and $L, where $P is the
+ ** key-prefix formed by the nEq values matched against the nEq left-most
+ ** columns of the index, and $L is the value in pLower.
+ **
+ ** Or, if pLower is NULL or $L cannot be extracted from it (because it
+ ** is not a simple variable or literal value), the lower bound of the
+ ** range is $P. Due to a quirk in the way whereKeyStats() works, even
+ ** if $L is available, whereKeyStats() is called for both ($P) and
+ ** ($P:$L) and the larger of the two returned values used.
+ **
+ ** Similarly, iUpper is to be set to the estimate of the number of rows
+ ** less than the upper bound of the range query. Where the upper bound
+ ** is either ($P) or ($P:$U). Again, even if $U is available, both values
+ ** of iUpper are requested of whereKeyStats() and the smaller used.
+ */
+ tRowcnt iLower;
+ tRowcnt iUpper;
+
+ if( nEq==p->nKeyCol ){
+ aff = SQLITE_AFF_INTEGER;
+ }else{
+ aff = p->pTable->aCol[p->aiColumn[nEq]].affinity;
+ }
+ /* Determine iLower and iUpper using ($P) only. */
+ if( nEq==0 ){
+ iLower = 0;
+ iUpper = p->aiRowEst[0];
+ }else{
+ /* Note: this call could be optimized away - since the same values must
+ ** have been requested when testing key $P in whereEqualScanEst(). */
+ whereKeyStats(pParse, p, pRec, 0, a);
+ iLower = a[0];
+ iUpper = a[0] + a[1];
+ }
+ /* If possible, improve on the iLower estimate using ($P:$L). */
if( pLower ){
+ int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pLower->pExpr->pRight;
- rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
- if( rc==SQLITE_OK
- && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
- ){
- iLower = a[0];
- if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
+ rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
+ if( rc==SQLITE_OK && bOk ){
+ tRowcnt iNew;
+ whereKeyStats(pParse, p, pRec, 0, a);
+ iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0);
+ if( iNew>iLower ) iLower = iNew;
+ nOut--;
}
- sqlite3ValueFree(pRangeVal);
}
- if( rc==SQLITE_OK && pUpper ){
+
+ /* If possible, improve on the iUpper estimate using ($P:$U). */
+ if( pUpper ){
+ int bOk; /* True if value is extracted from pExpr */
Expr *pExpr = pUpper->pExpr->pRight;
- rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
- if( rc==SQLITE_OK
- && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
- ){
- iUpper = a[0];
- if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
+ rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
+ if( rc==SQLITE_OK && bOk ){
+ tRowcnt iNew;
+ whereKeyStats(pParse, p, pRec, 1, a);
+ iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0);
+ if( iNew<iUpper ) iUpper = iNew;
+ nOut--;
}
- sqlite3ValueFree(pRangeVal);
}
+
+ pBuilder->pRec = pRec;
if( rc==SQLITE_OK ){
- if( iUpper<=iLower ){
- *pRangeDiv = (double)p->aiRowEst[0];
+ if( iUpper>iLower ){
+ nNew = sqlite3LogEst(iUpper - iLower);
}else{
- *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower);
+ nNew = 10; assert( 10==sqlite3LogEst(2) );
+ }
+ if( nNew<nOut ){
+ nOut = nNew;
}
- WHERETRACE(("range scan regions: %u..%u div=%g\n",
- (u32)iLower, (u32)iUpper, *pRangeDiv));
+ pLoop->nOut = (LogEst)nOut;
+ WHERETRACE(0x10, ("range scan regions: %u..%u est=%d\n",
+ (u32)iLower, (u32)iUpper, nOut));
return SQLITE_OK;
}
}
#else
UNUSED_PARAMETER(pParse);
- UNUSED_PARAMETER(p);
- UNUSED_PARAMETER(nEq);
+ UNUSED_PARAMETER(pBuilder);
#endif
assert( pLower || pUpper );
- *pRangeDiv = (double)1;
- if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4;
- if( pUpper ) *pRangeDiv *= (double)4;
+ /* TUNING: Each inequality constraint reduces the search space 4-fold.
+ ** A BETWEEN operator, therefore, reduces the search space 16-fold */
+ nNew = nOut;
+ if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
+ nNew -= 20; assert( 20==sqlite3LogEst(4) );
+ nOut--;
+ }
+ if( pUpper ){
+ nNew -= 20; assert( 20==sqlite3LogEst(4) );
+ nOut--;
+ }
+ if( nNew<10 ) nNew = 10;
+ if( nNew<nOut ) nOut = nNew;
+ pLoop->nOut = (LogEst)nOut;
return rc;
}
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Estimate the number of rows that will be returned based on
** an equality constraint x=VALUE and where that VALUE occurs in
@@ -107146,37 +110580,53 @@ static int whereRangeScanEst(
*/
static int whereEqualScanEst(
Parse *pParse, /* Parsing & code generating context */
- Index *p, /* The index whose left-most column is pTerm */
+ WhereLoopBuilder *pBuilder,
Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */
- double *pnRow /* Write the revised row estimate here */
+ tRowcnt *pnRow /* Write the revised row estimate here */
){
- sqlite3_value *pRhs = 0; /* VALUE on right-hand side of pTerm */
+ Index *p = pBuilder->pNew->u.btree.pIndex;
+ int nEq = pBuilder->pNew->u.btree.nEq;
+ UnpackedRecord *pRec = pBuilder->pRec;
u8 aff; /* Column affinity */
int rc; /* Subfunction return code */
tRowcnt a[2]; /* Statistics */
+ int bOk;
+ assert( nEq>=1 );
+ assert( nEq<=(p->nKeyCol+1) );
assert( p->aSample!=0 );
assert( p->nSample>0 );
- aff = p->pTable->aCol[p->aiColumn[0]].affinity;
- if( pExpr ){
- rc = valueFromExpr(pParse, pExpr, aff, &pRhs);
- if( rc ) goto whereEqualScanEst_cancel;
- }else{
- pRhs = sqlite3ValueNew(pParse->db);
+ assert( pBuilder->nRecValid<nEq );
+
+ /* If values are not available for all fields of the index to the left
+ ** of this one, no estimate can be made. Return SQLITE_NOTFOUND. */
+ if( pBuilder->nRecValid<(nEq-1) ){
+ return SQLITE_NOTFOUND;
}
- if( pRhs==0 ) return SQLITE_NOTFOUND;
- rc = whereKeyStats(pParse, p, pRhs, 0, a);
- if( rc==SQLITE_OK ){
- WHERETRACE(("equality scan regions: %d\n", (int)a[1]));
- *pnRow = a[1];
+
+ /* This is an optimization only. The call to sqlite3Stat4ProbeSetValue()
+ ** below would return the same value. */
+ if( nEq>p->nKeyCol ){
+ *pnRow = 1;
+ return SQLITE_OK;
}
-whereEqualScanEst_cancel:
- sqlite3ValueFree(pRhs);
+
+ aff = p->pTable->aCol[p->aiColumn[nEq-1]].affinity;
+ rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk);
+ pBuilder->pRec = pRec;
+ if( rc!=SQLITE_OK ) return rc;
+ if( bOk==0 ) return SQLITE_NOTFOUND;
+ pBuilder->nRecValid = nEq;
+
+ whereKeyStats(pParse, p, pRec, 0, a);
+ WHERETRACE(0x10,("equality scan regions: %d\n", (int)a[1]));
+ *pnRow = a[1];
+
return rc;
}
-#endif /* defined(SQLITE_ENABLE_STAT3) */
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
-#ifdef SQLITE_ENABLE_STAT3
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Estimate the number of rows that will be returned based on
** an IN constraint where the right-hand side of the IN operator
@@ -107195,902 +110645,34 @@ whereEqualScanEst_cancel:
*/
static int whereInScanEst(
Parse *pParse, /* Parsing & code generating context */
- Index *p, /* The index whose left-most column is pTerm */
+ WhereLoopBuilder *pBuilder,
ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
- double *pnRow /* Write the revised row estimate here */
+ tRowcnt *pnRow /* Write the revised row estimate here */
){
- int rc = SQLITE_OK; /* Subfunction return code */
- double nEst; /* Number of rows for a single term */
- double nRowEst = (double)0; /* New estimate of the number of rows */
- int i; /* Loop counter */
+ Index *p = pBuilder->pNew->u.btree.pIndex;
+ int nRecValid = pBuilder->nRecValid;
+ int rc = SQLITE_OK; /* Subfunction return code */
+ tRowcnt nEst; /* Number of rows for a single term */
+ tRowcnt nRowEst = 0; /* New estimate of the number of rows */
+ int i; /* Loop counter */
assert( p->aSample!=0 );
for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){
nEst = p->aiRowEst[0];
- rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst);
+ rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst);
nRowEst += nEst;
+ pBuilder->nRecValid = nRecValid;
}
+
if( rc==SQLITE_OK ){
if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
*pnRow = nRowEst;
- WHERETRACE(("IN row estimate: est=%g\n", nRowEst));
+ WHERETRACE(0x10,("IN row estimate: est=%g\n", nRowEst));
}
+ assert( pBuilder->nRecValid==nRecValid );
return rc;
}
-#endif /* defined(SQLITE_ENABLE_STAT3) */
-
-/*
-** Check to see if column iCol of the table with cursor iTab will appear
-** in sorted order according to the current query plan.
-**
-** Return values:
-**
-** 0 iCol is not ordered
-** 1 iCol has only a single value
-** 2 iCol is in ASC order
-** 3 iCol is in DESC order
-*/
-static int isOrderedColumn(
- WhereBestIdx *p,
- int iTab,
- int iCol
-){
- int i, j;
- WhereLevel *pLevel = &p->aLevel[p->i-1];
- Index *pIdx;
- u8 sortOrder;
- for(i=p->i-1; i>=0; i--, pLevel--){
- if( pLevel->iTabCur!=iTab ) continue;
- if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
- return 1;
- }
- assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
- if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
- if( iCol<0 ){
- sortOrder = 0;
- testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
- }else{
- int n = pIdx->nColumn;
- for(j=0; j<n; j++){
- if( iCol==pIdx->aiColumn[j] ) break;
- }
- if( j>=n ) return 0;
- sortOrder = pIdx->aSortOrder[j];
- testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
- }
- }else{
- if( iCol!=(-1) ) return 0;
- sortOrder = 0;
- testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
- }
- if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
- assert( sortOrder==0 || sortOrder==1 );
- testcase( sortOrder==1 );
- sortOrder = 1 - sortOrder;
- }
- return sortOrder+2;
- }
- return 0;
-}
-
-/*
-** This routine decides if pIdx can be used to satisfy the ORDER BY
-** clause, either in whole or in part. The return value is the
-** cumulative number of terms in the ORDER BY clause that are satisfied
-** by the index pIdx and other indices in outer loops.
-**
-** The table being queried has a cursor number of "base". pIdx is the
-** index that is postulated for use to access the table.
-**
-** The *pbRev value is set to 0 order 1 depending on whether or not
-** pIdx should be run in the forward order or in reverse order.
-*/
-static int isSortingIndex(
- WhereBestIdx *p, /* Best index search context */
- Index *pIdx, /* The index we are testing */
- int base, /* Cursor number for the table to be sorted */
- int *pbRev, /* Set to 1 for reverse-order scan of pIdx */
- int *pbObUnique /* ORDER BY column values will different in every row */
-){
- int i; /* Number of pIdx terms used */
- int j; /* Number of ORDER BY terms satisfied */
- int sortOrder = 2; /* 0: forward. 1: backward. 2: unknown */
- int nTerm; /* Number of ORDER BY terms */
- struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
- Table *pTab = pIdx->pTable; /* Table that owns index pIdx */
- ExprList *pOrderBy; /* The ORDER BY clause */
- Parse *pParse = p->pParse; /* Parser context */
- sqlite3 *db = pParse->db; /* Database connection */
- int nPriorSat; /* ORDER BY terms satisfied by outer loops */
- int seenRowid = 0; /* True if an ORDER BY rowid term is seen */
- int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */
- int outerObUnique; /* Outer loops generate different values in
- ** every row for the ORDER BY columns */
-
- if( p->i==0 ){
- nPriorSat = 0;
- outerObUnique = 1;
- }else{
- u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
- nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
- if( (wsFlags & WHERE_ORDERED)==0 ){
- /* This loop cannot be ordered unless the next outer loop is
- ** also ordered */
- return nPriorSat;
- }
- if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
- /* Only look at the outer-most loop if the OrderByIdxJoin
- ** optimization is disabled */
- return nPriorSat;
- }
- testcase( wsFlags & WHERE_OB_UNIQUE );
- testcase( wsFlags & WHERE_ALL_UNIQUE );
- outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
- }
- pOrderBy = p->pOrderBy;
- assert( pOrderBy!=0 );
- if( pIdx->bUnordered ){
- /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
- ** be used for sorting */
- return nPriorSat;
- }
- nTerm = pOrderBy->nExpr;
- uniqueNotNull = pIdx->onError!=OE_None;
- assert( nTerm>0 );
-
- /* Argument pIdx must either point to a 'real' named index structure,
- ** or an index structure allocated on the stack by bestBtreeIndex() to
- ** represent the rowid index that is part of every table. */
- assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
-
- /* Match terms of the ORDER BY clause against columns of
- ** the index.
- **
- ** Note that indices have pIdx->nColumn regular columns plus
- ** one additional column containing the rowid. The rowid column
- ** of the index is also allowed to match against the ORDER BY
- ** clause.
- */
- j = nPriorSat;
- for(i=0,pOBItem=&pOrderBy->a[j]; j<nTerm && i<=pIdx->nColumn; i++){
- Expr *pOBExpr; /* The expression of the ORDER BY pOBItem */
- CollSeq *pColl; /* The collating sequence of pOBExpr */
- int termSortOrder; /* Sort order for this term */
- int iColumn; /* The i-th column of the index. -1 for rowid */
- int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */
- int isEq; /* Subject to an == or IS NULL constraint */
- int isMatch; /* ORDER BY term matches the index term */
- const char *zColl; /* Name of collating sequence for i-th index term */
- WhereTerm *pConstraint; /* A constraint in the WHERE clause */
-
- /* If the next term of the ORDER BY clause refers to anything other than
- ** a column in the "base" table, then this index will not be of any
- ** further use in handling the ORDER BY. */
- pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
- if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
- break;
- }
-
- /* Find column number and collating sequence for the next entry
- ** in the index */
- if( pIdx->zName && i<pIdx->nColumn ){
- iColumn = pIdx->aiColumn[i];
- if( iColumn==pIdx->pTable->iPKey ){
- iColumn = -1;
- }
- iSortOrder = pIdx->aSortOrder[i];
- zColl = pIdx->azColl[i];
- assert( zColl!=0 );
- }else{
- iColumn = -1;
- iSortOrder = 0;
- zColl = 0;
- }
-
- /* Check to see if the column number and collating sequence of the
- ** index match the column number and collating sequence of the ORDER BY
- ** clause entry. Set isMatch to 1 if they both match. */
- if( pOBExpr->iColumn==iColumn ){
- if( zColl ){
- pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
- }else{
- isMatch = 1;
- }
- }else{
- isMatch = 0;
- }
-
- /* termSortOrder is 0 or 1 for whether or not the access loop should
- ** run forward or backwards (respectively) in order to satisfy this
- ** term of the ORDER BY clause. */
- assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
- assert( iSortOrder==0 || iSortOrder==1 );
- termSortOrder = iSortOrder ^ pOBItem->sortOrder;
-
- /* If X is the column in the index and ORDER BY clause, check to see
- ** if there are any X= or X IS NULL constraints in the WHERE clause. */
- pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
- WO_EQ|WO_ISNULL|WO_IN, pIdx);
- if( pConstraint==0 ){
- isEq = 0;
- }else if( (pConstraint->eOperator & WO_IN)!=0 ){
- isEq = 0;
- }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
- uniqueNotNull = 0;
- isEq = 1; /* "X IS NULL" means X has only a single value */
- }else if( pConstraint->prereqRight==0 ){
- isEq = 1; /* Constraint "X=constant" means X has only a single value */
- }else{
- Expr *pRight = pConstraint->pExpr->pRight;
- if( pRight->op==TK_COLUMN ){
- WHERETRACE((" .. isOrderedColumn(tab=%d,col=%d)",
- pRight->iTable, pRight->iColumn));
- isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
- WHERETRACE((" -> isEq=%d\n", isEq));
-
- /* If the constraint is of the form X=Y where Y is an ordered value
- ** in an outer loop, then make sure the sort order of Y matches the
- ** sort order required for X. */
- if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
- testcase( isEq==2 );
- testcase( isEq==3 );
- break;
- }
- }else{
- isEq = 0; /* "X=expr" places no ordering constraints on X */
- }
- }
- if( !isMatch ){
- if( isEq==0 ){
- break;
- }else{
- continue;
- }
- }else if( isEq!=1 ){
- if( sortOrder==2 ){
- sortOrder = termSortOrder;
- }else if( termSortOrder!=sortOrder ){
- break;
- }
- }
- j++;
- pOBItem++;
- if( iColumn<0 ){
- seenRowid = 1;
- break;
- }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
- testcase( isEq==0 );
- testcase( isEq==2 );
- testcase( isEq==3 );
- uniqueNotNull = 0;
- }
- }
- if( seenRowid ){
- uniqueNotNull = 1;
- }else if( uniqueNotNull==0 || i<pIdx->nColumn ){
- uniqueNotNull = 0;
- }
-
- /* If we have not found at least one ORDER BY term that matches the
- ** index, then show no progress. */
- if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
-
- /* Either the outer queries must generate rows where there are no two
- ** rows with the same values in all ORDER BY columns, or else this
- ** loop must generate just a single row of output. Example: Suppose
- ** the outer loops generate A=1 and A=1, and this loop generates B=3
- ** and B=4. Then without the following test, ORDER BY A,B would
- ** generate the wrong order output: 1,3 1,4 1,3 1,4
- */
- if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
- *pbObUnique = uniqueNotNull;
-
- /* Return the necessary scan order back to the caller */
- *pbRev = sortOrder & 1;
-
- /* If there was an "ORDER BY rowid" term that matched, or it is only
- ** possible for a single row from this table to match, then skip over
- ** any additional ORDER BY terms dealing with this table.
- */
- if( uniqueNotNull ){
- /* Advance j over additional ORDER BY terms associated with base */
- WhereMaskSet *pMS = p->pWC->pMaskSet;
- Bitmask m = ~getMask(pMS, base);
- while( j<nTerm && (exprTableUsage(pMS, pOrderBy->a[j].pExpr)&m)==0 ){
- j++;
- }
- }
- return j;
-}
-
-/*
-** Find the best query plan for accessing a particular table. Write the
-** best query plan and its cost into the p->cost.
-**
-** The lowest cost plan wins. The cost is an estimate of the amount of
-** CPU and disk I/O needed to process the requested result.
-** Factors that influence cost include:
-**
-** * The estimated number of rows that will be retrieved. (The
-** fewer the better.)
-**
-** * Whether or not sorting must occur.
-**
-** * Whether or not there must be separate lookups in the
-** index and in the main table.
-**
-** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in
-** the SQL statement, then this function only considers plans using the
-** named index. If no such plan is found, then the returned cost is
-** SQLITE_BIG_DBL. If a plan is found that uses the named index,
-** then the cost is calculated in the usual way.
-**
-** If a NOT INDEXED clause was attached to the table
-** in the SELECT statement, then no indexes are considered. However, the
-** selected plan may still take advantage of the built-in rowid primary key
-** index.
-*/
-static void bestBtreeIndex(WhereBestIdx *p){
- Parse *pParse = p->pParse; /* The parsing context */
- WhereClause *pWC = p->pWC; /* The WHERE clause */
- struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
- int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
- Index *pProbe; /* An index we are evaluating */
- Index *pIdx; /* Copy of pProbe, or zero for IPK index */
- int eqTermMask; /* Current mask of valid equality operators */
- int idxEqTermMask; /* Index mask of valid equality operators */
- Index sPk; /* A fake index object for the primary key */
- tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
- int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
- int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */
- int nPriorSat; /* ORDER BY terms satisfied by outer loops */
- int nOrderBy; /* Number of ORDER BY terms */
- char bSortInit; /* Initializer for bSort in inner loop */
- char bDistInit; /* Initializer for bDist in inner loop */
-
-
- /* Initialize the cost to a worst-case value */
- memset(&p->cost, 0, sizeof(p->cost));
- p->cost.rCost = SQLITE_BIG_DBL;
-
- /* 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
- ** because columns might end up being NULL if the table does not match -
- ** a circumstance which the index cannot help us discover. Ticket #2177.
- */
- if( pSrc->jointype & JT_LEFT ){
- idxEqTermMask = WO_EQ|WO_IN;
- }else{
- idxEqTermMask = WO_EQ|WO_IN|WO_ISNULL;
- }
-
- if( pSrc->pIndex ){
- /* An INDEXED BY clause specifies a particular index to use */
- pIdx = pProbe = pSrc->pIndex;
- wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
- eqTermMask = idxEqTermMask;
- }else{
- /* There is no INDEXED BY clause. Create a fake Index object in local
- ** variable sPk to represent the rowid primary key index. Make this
- ** fake index the first in a chain of Index objects with all of the real
- ** indices to follow */
- Index *pFirst; /* First of real indices on the table */
- memset(&sPk, 0, sizeof(Index));
- sPk.nColumn = 1;
- sPk.aiColumn = &aiColumnPk;
- sPk.aiRowEst = aiRowEstPk;
- sPk.onError = OE_Replace;
- sPk.pTable = pSrc->pTab;
- aiRowEstPk[0] = pSrc->pTab->nRowEst;
- aiRowEstPk[1] = 1;
- pFirst = pSrc->pTab->pIndex;
- if( pSrc->notIndexed==0 ){
- /* The real indices of the table are only considered if the
- ** NOT INDEXED qualifier is omitted from the FROM clause */
- sPk.pNext = pFirst;
- }
- pProbe = &sPk;
- wsFlagMask = ~(
- WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE
- );
- eqTermMask = WO_EQ|WO_IN;
- pIdx = 0;
- }
-
- nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
- if( p->i ){
- nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
- bSortInit = nPriorSat<nOrderBy;
- bDistInit = 0;
- }else{
- nPriorSat = 0;
- bSortInit = nOrderBy>0;
- bDistInit = p->pDistinct!=0;
- }
-
- /* Loop over all indices looking for the best one to use
- */
- for(; pProbe; pIdx=pProbe=pProbe->pNext){
- const tRowcnt * const aiRowEst = pProbe->aiRowEst;
- WhereCost pc; /* Cost of using pProbe */
- double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */
-
- /* The following variables are populated based on the properties of
- ** index being evaluated. They are then used to determine the expected
- ** cost and number of rows returned.
- **
- ** pc.plan.nEq:
- ** Number of equality terms that can be implemented using the index.
- ** In other words, the number of initial fields in the index that
- ** are used in == or IN or NOT NULL constraints of the WHERE clause.
- **
- ** nInMul:
- ** The "in-multiplier". This is an estimate of how many seek operations
- ** SQLite must perform on the index in question. For example, if the
- ** WHERE clause is:
- **
- ** WHERE a IN (1, 2, 3) AND b IN (4, 5, 6)
- **
- ** SQLite must perform 9 lookups on an index on (a, b), so nInMul is
- ** set to 9. Given the same schema and either of the following WHERE
- ** clauses:
- **
- ** WHERE a = 1
- ** WHERE a >= 2
- **
- ** nInMul is set to 1.
- **
- ** If there exists a WHERE term of the form "x IN (SELECT ...)", then
- ** the sub-select is assumed to return 25 rows for the purposes of
- ** determining nInMul.
- **
- ** bInEst:
- ** Set to true if there was at least one "x IN (SELECT ...)" term used
- ** in determining the value of nInMul. Note that the RHS of the
- ** IN operator must be a SELECT, not a value list, for this variable
- ** to be true.
- **
- ** rangeDiv:
- ** An estimate of a divisor by which to reduce the search space due
- ** to inequality constraints. In the absence of sqlite_stat3 ANALYZE
- ** data, a single inequality reduces the search space to 1/4rd its
- ** original size (rangeDiv==4). Two inequalities reduce the search
- ** space to 1/16th of its original size (rangeDiv==16).
- **
- ** bSort:
- ** Boolean. True if there is an ORDER BY clause that will require an
- ** external sort (i.e. scanning the index being evaluated will not
- ** correctly order records).
- **
- ** bDist:
- ** Boolean. True if there is a DISTINCT clause that will require an
- ** external btree.
- **
- ** bLookup:
- ** Boolean. True if a table lookup is required for each index entry
- ** visited. In other words, true if this is not a covering index.
- ** This is always false for the rowid primary key index of a table.
- ** For other indexes, it is true unless all the columns of the table
- ** used by the SELECT statement are present in the index (such an
- ** index is sometimes described as a covering index).
- ** For example, given the index on (a, b), the second of the following
- ** two queries requires table b-tree lookups in order to find the value
- ** of column c, but the first does not because columns a and b are
- ** both available in the index.
- **
- ** SELECT a, b FROM tbl WHERE a = 1;
- ** SELECT a, b, c FROM tbl WHERE a = 1;
- */
- int bInEst = 0; /* True if "x IN (SELECT...)" seen */
- int nInMul = 1; /* Number of distinct equalities to lookup */
- double rangeDiv = (double)1; /* Estimated reduction in search space */
- int nBound = 0; /* Number of range constraints seen */
- char bSort = bSortInit; /* True if external sort required */
- char bDist = bDistInit; /* True if index cannot help with DISTINCT */
- char bLookup = 0; /* True if not a covering index */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
-#ifdef SQLITE_ENABLE_STAT3
- WhereTerm *pFirstTerm = 0; /* First term matching the index */
-#endif
-
- WHERETRACE((
- " %s(%s):\n",
- pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
- ));
- memset(&pc, 0, sizeof(pc));
- pc.plan.nOBSat = nPriorSat;
-
- /* Determine the values of pc.plan.nEq and nInMul */
- for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){
- int j = pProbe->aiColumn[pc.plan.nEq];
- pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
- if( pTerm==0 ) break;
- pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
- testcase( pTerm->pWC!=pWC );
- if( pTerm->eOperator & WO_IN ){
- Expr *pExpr = pTerm->pExpr;
- pc.plan.wsFlags |= WHERE_COLUMN_IN;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- /* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */
- nInMul *= 25;
- bInEst = 1;
- }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
- /* "x IN (value, value, ...)" */
- nInMul *= pExpr->x.pList->nExpr;
- }
- }else if( pTerm->eOperator & WO_ISNULL ){
- pc.plan.wsFlags |= WHERE_COLUMN_NULL;
- }
-#ifdef SQLITE_ENABLE_STAT3
- if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
-#endif
- pc.used |= pTerm->prereqRight;
- }
-
- /* If the index being considered is UNIQUE, and there is an equality
- ** constraint for all columns in the index, then this search will find
- ** at most a single row. In this case set the WHERE_UNIQUE flag to
- ** indicate this to the caller.
- **
- ** Otherwise, if the search may find more than one row, test to see if
- ** there is a range constraint on indexed column (pc.plan.nEq+1) that
- ** can be optimized using the index.
- */
- if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
- testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
- testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
- if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
- pc.plan.wsFlags |= WHERE_UNIQUE;
- if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
- pc.plan.wsFlags |= WHERE_ALL_UNIQUE;
- }
- }
- }else if( pProbe->bUnordered==0 ){
- int j;
- j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]);
- if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
- WhereTerm *pTop, *pBtm;
- pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx);
- pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx);
- whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv);
- if( pTop ){
- nBound = 1;
- pc.plan.wsFlags |= WHERE_TOP_LIMIT;
- pc.used |= pTop->prereqRight;
- testcase( pTop->pWC!=pWC );
- }
- if( pBtm ){
- nBound++;
- pc.plan.wsFlags |= WHERE_BTM_LIMIT;
- pc.used |= pBtm->prereqRight;
- testcase( pBtm->pWC!=pWC );
- }
- pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
- }
- }
-
- /* If there is an ORDER BY clause and the index being considered will
- ** naturally scan rows in the required order, set the appropriate flags
- ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
- ** the index will scan rows in a different order, set the bSort
- ** variable. */
- if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
- int bRev = 2;
- int bObUnique = 0;
- WHERETRACE((" --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
- pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
- WHERETRACE((" --> after isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
- bRev, bObUnique, pc.plan.nOBSat));
- if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
- pc.plan.wsFlags |= WHERE_ORDERED;
- if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
- }
- if( nOrderBy==pc.plan.nOBSat ){
- bSort = 0;
- pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE;
- }
- if( bRev & 1 ) pc.plan.wsFlags |= WHERE_REVERSE;
- }
-
- /* If there is a DISTINCT qualifier and this index will scan rows in
- ** order of the DISTINCT expressions, clear bDist and set the appropriate
- ** flags in pc.plan.wsFlags. */
- if( bDist
- && isDistinctIndex(pParse, pWC, pProbe, iCur, p->pDistinct, pc.plan.nEq)
- && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0
- ){
- bDist = 0;
- pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
- }
-
- /* If currently calculating the cost of using an index (not the IPK
- ** index), determine if all required column data may be obtained without
- ** using the main table (i.e. if the index is a covering
- ** index for this query). If it is, set the WHERE_IDX_ONLY flag in
- ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true. */
- if( pIdx ){
- Bitmask m = pSrc->colUsed;
- int j;
- for(j=0; j<pIdx->nColumn; j++){
- int x = pIdx->aiColumn[j];
- if( x<BMS-1 ){
- m &= ~(((Bitmask)1)<<x);
- }
- }
- if( m==0 ){
- pc.plan.wsFlags |= WHERE_IDX_ONLY;
- }else{
- bLookup = 1;
- }
- }
-
- /*
- ** Estimate the number of rows of output. For an "x IN (SELECT...)"
- ** constraint, do not let the estimate exceed half the rows in the table.
- */
- pc.plan.nRow = (double)(aiRowEst[pc.plan.nEq] * nInMul);
- if( bInEst && pc.plan.nRow*2>aiRowEst[0] ){
- pc.plan.nRow = aiRowEst[0]/2;
- nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]);
- }
-
-#ifdef SQLITE_ENABLE_STAT3
- /* If the constraint is of the form x=VALUE or x IN (E1,E2,...)
- ** and we do not think that values of x are unique and if histogram
- ** data is available for column x, then it might be possible
- ** to get a better estimate on the number of rows based on
- ** VALUE and how common that value is according to the histogram.
- */
- if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
- && pFirstTerm!=0 && aiRowEst[1]>1 ){
- assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
- if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
- testcase( pFirstTerm->eOperator & WO_EQ );
- testcase( pFirstTerm->eOperator & WO_EQUIV );
- testcase( pFirstTerm->eOperator & WO_ISNULL );
- whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
- &pc.plan.nRow);
- }else if( bInEst==0 ){
- assert( pFirstTerm->eOperator & WO_IN );
- whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
- &pc.plan.nRow);
- }
- }
-#endif /* SQLITE_ENABLE_STAT3 */
-
- /* Adjust the number of output rows and downward to reflect rows
- ** that are excluded by range constraints.
- */
- pc.plan.nRow = pc.plan.nRow/rangeDiv;
- if( pc.plan.nRow<1 ) pc.plan.nRow = 1;
-
- /* Experiments run on real SQLite databases show that the time needed
- ** to do a binary search to locate a row in a table or index is roughly
- ** log10(N) times the time to move from one row to the next row within
- ** a table or index. The actual times can vary, with the size of
- ** records being an important factor. Both moves and searches are
- ** slower with larger records, presumably because fewer records fit
- ** on one page and hence more pages have to be fetched.
- **
- ** The ANALYZE command and the sqlite_stat1 and sqlite_stat3 tables do
- ** not give us data on the relative sizes of table and index records.
- ** So this computation assumes table records are about twice as big
- ** as index records
- */
- if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
- ==WHERE_IDX_ONLY
- && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
- && sqlite3GlobalConfig.bUseCis
- && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
- ){
- /* This index is not useful for indexing, but it is a covering index.
- ** A full-scan of the index might be a little faster than a full-scan
- ** of the table, so give this case a cost slightly less than a table
- ** scan. */
- pc.rCost = aiRowEst[0]*3 + pProbe->nColumn;
- pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
- }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
- /* The cost of a full table scan is a number of move operations equal
- ** to the number of rows in the table.
- **
- ** We add an additional 4x penalty to full table scans. This causes
- ** the cost function to err on the side of choosing an index over
- ** choosing a full scan. This 4x full-scan penalty is an arguable
- ** decision and one which we expect to revisit in the future. But
- ** it seems to be working well enough at the moment.
- */
- pc.rCost = aiRowEst[0]*4;
- pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
- if( pIdx ){
- pc.plan.wsFlags &= ~WHERE_ORDERED;
- pc.plan.nOBSat = nPriorSat;
- }
- }else{
- log10N = estLog(aiRowEst[0]);
- pc.rCost = pc.plan.nRow;
- if( pIdx ){
- if( bLookup ){
- /* For an index lookup followed by a table lookup:
- ** nInMul index searches to find the start of each index range
- ** + nRow steps through the index
- ** + nRow table searches to lookup the table entry using the rowid
- */
- pc.rCost += (nInMul + pc.plan.nRow)*log10N;
- }else{
- /* For a covering index:
- ** nInMul index searches to find the initial entry
- ** + nRow steps through the index
- */
- pc.rCost += nInMul*log10N;
- }
- }else{
- /* For a rowid primary key lookup:
- ** nInMult table searches to find the initial entry for each range
- ** + nRow steps through the table
- */
- pc.rCost += nInMul*log10N;
- }
- }
-
- /* Add in the estimated cost of sorting the result. Actual experimental
- ** measurements of sorting performance in SQLite show that sorting time
- ** adds C*N*log10(N) to the cost, where N is the number of rows to be
- ** sorted and C is a factor between 1.95 and 4.3. We will split the
- ** difference and select C of 3.0.
- */
- if( bSort ){
- double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy);
- m *= (double)(pc.plan.nOBSat ? 2 : 3);
- pc.rCost += pc.plan.nRow*m;
- }
- if( bDist ){
- pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3;
- }
-
- /**** Cost of using this index has now been computed ****/
-
- /* If there are additional constraints on this table that cannot
- ** be used with the current index, but which might lower the number
- ** of output rows, adjust the nRow value accordingly. This only
- ** matters if the current index is the least costly, so do not bother
- ** with this step if we already know this index will not be chosen.
- ** Also, never reduce the output row count below 2 using this step.
- **
- ** It is critical that the notValid mask be used here instead of
- ** the notReady mask. When computing an "optimal" index, the notReady
- ** mask will only have one bit set - the bit for the current table.
- ** The notValid mask, on the other hand, always has all bits set for
- ** tables that are not in outer loops. If notReady is used here instead
- ** of notValid, then a optimal index that depends on inner joins loops
- ** might be selected even when there exists an optimal index that has
- ** no such dependency.
- */
- if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){
- int k; /* Loop counter */
- int nSkipEq = pc.plan.nEq; /* Number of == constraints to skip */
- int nSkipRange = nBound; /* Number of < constraints to skip */
- Bitmask thisTab; /* Bitmap for pSrc */
-
- thisTab = getMask(pWC->pMaskSet, iCur);
- for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){
- if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
- if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue;
- if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
- if( nSkipEq ){
- /* Ignore the first pc.plan.nEq equality matches since the index
- ** has already accounted for these */
- nSkipEq--;
- }else{
- /* Assume each additional equality match reduces the result
- ** set size by a factor of 10 */
- pc.plan.nRow /= 10;
- }
- }else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
- if( nSkipRange ){
- /* Ignore the first nSkipRange range constraints since the index
- ** has already accounted for these */
- nSkipRange--;
- }else{
- /* Assume each additional range constraint reduces the result
- ** set size by a factor of 3. Indexed range constraints reduce
- ** the search space by a larger factor: 4. We make indexed range
- ** more selective intentionally because of the subjective
- ** observation that indexed range constraints really are more
- ** selective in practice, on average. */
- pc.plan.nRow /= 3;
- }
- }else if( (pTerm->eOperator & WO_NOOP)==0 ){
- /* Any other expression lowers the output row count by half */
- pc.plan.nRow /= 2;
- }
- }
- if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
- }
-
-
- WHERETRACE((
- " nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
- " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
- " used=0x%llx nOBSat=%d\n",
- pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
- p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
- pc.plan.nOBSat
- ));
-
- /* If this index is the best we have seen so far, then record this
- ** index and its cost in the p->cost structure.
- */
- if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
- p->cost = pc;
- p->cost.plan.wsFlags &= wsFlagMask;
- p->cost.plan.u.pIdx = pIdx;
- }
-
- /* If there was an INDEXED BY clause, then only that one index is
- ** considered. */
- if( pSrc->pIndex ) break;
-
- /* Reset masks for the next index in the loop */
- wsFlagMask = ~(WHERE_ROWID_EQ|WHERE_ROWID_RANGE);
- eqTermMask = idxEqTermMask;
- }
-
- /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
- ** is set, then reverse the order that the index will be scanned
- ** in. This is used for application testing, to help find cases
- ** where application behavior depends on the (undefined) order that
- ** SQLite outputs rows in in the absence of an ORDER BY clause. */
- if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
- p->cost.plan.wsFlags |= WHERE_REVERSE;
- }
-
- assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
- assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
- assert( pSrc->pIndex==0
- || p->cost.plan.u.pIdx==0
- || p->cost.plan.u.pIdx==pSrc->pIndex
- );
-
- WHERETRACE((" best index is %s cost=%.1f\n",
- p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
- p->cost.rCost));
-
- bestOrClauseIndex(p);
- bestAutomaticIndex(p);
- p->cost.plan.wsFlags |= eqTermMask;
-}
-
-/*
-** 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.
-**
-** This function does not take ORDER BY or DISTINCT into account. Nor
-** does it remember the virtual table query plan. All it does is compute
-** the cost while determining if an OR optimization is applicable. The
-** details will be reconsidered later if the optimization is found to be
-** applicable.
-*/
-static void bestIndex(WhereBestIdx *p){
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(p->pSrc->pTab) ){
- sqlite3_index_info *pIdxInfo = 0;
- p->ppIdxInfo = &pIdxInfo;
- bestVirtualIndex(p);
- assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
- if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
- sqlite3_free(pIdxInfo->idxStr);
- }
- sqlite3DbFree(p->pParse->db, pIdxInfo);
- }else
-#endif
- {
- bestBtreeIndex(p);
- }
-}
+#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
/*
** Disable a term in the WHERE clause. Except, do not disable the term
@@ -108107,9 +110689,6 @@ static void bestIndex(WhereBestIdx *p){
** in the ON clause. The term is disabled in (3) because it is not part
** of a LEFT OUTER JOIN. In (1), the term is not disabled.
**
-** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are
-** completely satisfied by indices.
-**
** Disabling a term causes that term to not be tested in the inner loop
** of the join. Disabling is an optimization. When terms are satisfied
** by indices, we disable them to prevent redundant tests in the inner
@@ -108122,6 +110701,7 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
if( pTerm
&& (pTerm->wtFlags & TERM_CODED)==0
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
+ && (pLevel->notReady & pTerm->prereqAll)==0
){
pTerm->wtFlags |= TERM_CODED;
if( pTerm->iParent>=0 ){
@@ -108189,6 +110769,7 @@ static int codeEqualityTerm(
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
WhereLevel *pLevel, /* The level of the FROM clause we are working on */
int iEq, /* Index of the equality term within this level */
+ int bRev, /* True for reverse-order IN operations */
int iTarget /* Attempt to leave results in this register */
){
Expr *pX = pTerm->pExpr;
@@ -108206,14 +110787,13 @@ static int codeEqualityTerm(
int eType;
int iTab;
struct InLoop *pIn;
- u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
+ WhereLoop *pLoop = pLevel->pWLoop;
- if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0
- && pLevel->plan.u.pIdx->aSortOrder[iEq]
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+ && pLoop->u.btree.pIndex!=0
+ && pLoop->u.btree.pIndex->aSortOrder[iEq]
){
testcase( iEq==0 );
- testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 );
- testcase( iEq>0 && iEq+1<pLevel->plan.u.pIdx->nColumn );
testcase( bRev );
bRev = !bRev;
}
@@ -108226,7 +110806,8 @@ static int codeEqualityTerm(
}
iTab = pX->iTable;
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
- assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
+ assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
+ pLoop->wsFlags |= WHERE_IN_ABLE;
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
}
@@ -108243,7 +110824,7 @@ static int codeEqualityTerm(
}else{
pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
}
- pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
+ pIn->eEndLoopOp = bRev ? OP_PrevIfOpen : OP_NextIfOpen;
sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
}else{
pLevel->u.in.nIn = 0;
@@ -108256,7 +110837,7 @@ static int codeEqualityTerm(
/*
** Generate code that will evaluate all == and IN constraints for an
-** index.
+** index scan.
**
** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
** Suppose the WHERE clause is this: a==5 AND b IN (1,2,3) AND c>5 AND c<10
@@ -108271,9 +110852,15 @@ static int codeEqualityTerm(
** The only thing it does is allocate the pLevel->iMem memory cell and
** compute the affinity string.
**
-** This routine always allocates at least one memory cell and returns
-** the index of that memory cell. The code that
-** calls this routine will use that memory cell to store the termination
+** The nExtraReg parameter is 0 or 1. It is 0 if all WHERE clause constraints
+** are == or IN and are covered by the nEq. nExtraReg is 1 if there is
+** an inequality constraint (such as the "c>=5 AND c<10" in the example) that
+** occurs after the nEq quality constraints.
+**
+** This routine allocates a range of nEq+nExtraReg memory cells and returns
+** the index of the first memory cell in that range. The code that
+** calls this routine will use that memory range to store keys for
+** start and termination conditions of the loop.
** key value of the loop. If one or more IN operators appear, then
** this routine allocates an additional nEq memory cells for internal
** use.
@@ -108296,29 +110883,33 @@ static int codeEqualityTerm(
static int codeAllEqualityTerms(
Parse *pParse, /* Parsing context */
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
- WhereClause *pWC, /* The WHERE clause */
- Bitmask notReady, /* Which parts of FROM have not yet been coded */
+ int bRev, /* Reverse the order of IN operators */
int nExtraReg, /* Number of extra registers to allocate */
char **pzAff /* OUT: Set to point to affinity string */
){
- int nEq = pLevel->plan.nEq; /* The number of == or IN constraints to code */
+ u16 nEq; /* The number of == or IN constraints to code */
+ u16 nSkip; /* Number of left-most columns to skip */
Vdbe *v = pParse->pVdbe; /* The vm under construction */
Index *pIdx; /* The index being used for this loop */
- int iCur = pLevel->iTabCur; /* The cursor of the table */
WhereTerm *pTerm; /* A single constraint term */
+ WhereLoop *pLoop; /* The WhereLoop object */
int j; /* Loop counter */
int regBase; /* Base register */
int nReg; /* Number of registers to allocate */
char *zAff; /* Affinity string to return */
/* This module is only called on query plans that use an index. */
- assert( pLevel->plan.wsFlags & WHERE_INDEXED );
- pIdx = pLevel->plan.u.pIdx;
+ pLoop = pLevel->pWLoop;
+ assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
+ nEq = pLoop->u.btree.nEq;
+ nSkip = pLoop->u.btree.nSkip;
+ pIdx = pLoop->u.btree.pIndex;
+ assert( pIdx!=0 );
/* Figure out how many memory cells we will need then allocate them.
*/
regBase = pParse->nMem + 1;
- nReg = pLevel->plan.nEq + nExtraReg;
+ nReg = pLoop->u.btree.nEq + nExtraReg;
pParse->nMem += nReg;
zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx));
@@ -108326,19 +110917,33 @@ static int codeAllEqualityTerms(
pParse->db->mallocFailed = 1;
}
+ if( nSkip ){
+ int iIdxCur = pLevel->iIdxCur;
+ sqlite3VdbeAddOp1(v, (bRev?OP_Last:OP_Rewind), iIdxCur);
+ VdbeComment((v, "begin skip-scan on %s", pIdx->zName));
+ j = sqlite3VdbeAddOp0(v, OP_Goto);
+ pLevel->addrSkip = sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLt:OP_SeekGt),
+ iIdxCur, 0, regBase, nSkip);
+ sqlite3VdbeJumpHere(v, j);
+ for(j=0; j<nSkip; j++){
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, j, regBase+j);
+ assert( pIdx->aiColumn[j]>=0 );
+ VdbeComment((v, "%s", pIdx->pTable->aCol[pIdx->aiColumn[j]].zName));
+ }
+ }
+
/* Evaluate the equality constraints
*/
- assert( pIdx->nColumn>=nEq );
- for(j=0; j<nEq; j++){
+ assert( zAff==0 || (int)strlen(zAff)>=nEq );
+ for(j=nSkip; j<nEq; j++){
int r1;
- int k = pIdx->aiColumn[j];
- pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
- if( pTerm==0 ) break;
- /* The following true for indices with redundant columns.
+ pTerm = pLoop->aLTerm[j];
+ assert( pTerm!=0 );
+ /* The following testcase is true for indices with redundant columns.
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
- testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
- r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j);
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
+ r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
sqlite3ReleaseTempReg(pParse, regBase);
@@ -108406,32 +111011,40 @@ static void explainAppendTerm(
** It is the responsibility of the caller to free the buffer when it is
** no longer required.
*/
-static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){
- WherePlan *pPlan = &pLevel->plan;
- Index *pIndex = pPlan->u.pIdx;
- int nEq = pPlan->nEq;
+static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
+ Index *pIndex = pLoop->u.btree.pIndex;
+ u16 nEq = pLoop->u.btree.nEq;
+ u16 nSkip = pLoop->u.btree.nSkip;
int i, j;
Column *aCol = pTab->aCol;
- int *aiColumn = pIndex->aiColumn;
+ i16 *aiColumn = pIndex->aiColumn;
StrAccum txt;
- if( nEq==0 && (pPlan->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
+ if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
return 0;
}
sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
txt.db = db;
sqlite3StrAccumAppend(&txt, " (", 2);
for(i=0; i<nEq; i++){
- explainAppendTerm(&txt, i, aCol[aiColumn[i]].zName, "=");
+ char *z = (i==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[i]].zName;
+ if( i>=nSkip ){
+ explainAppendTerm(&txt, i, z, "=");
+ }else{
+ if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5);
+ sqlite3StrAccumAppend(&txt, "ANY(", 4);
+ sqlite3StrAccumAppend(&txt, z, -1);
+ sqlite3StrAccumAppend(&txt, ")", 1);
+ }
}
j = i;
- if( pPlan->wsFlags&WHERE_BTM_LIMIT ){
- char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
+ if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
+ char *z = (j==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i++, z, ">");
}
- if( pPlan->wsFlags&WHERE_TOP_LIMIT ){
- char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
+ if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
+ char *z = (j==pIndex->nKeyCol ) ? "rowid" : aCol[aiColumn[j]].zName;
explainAppendTerm(&txt, i, z, "<");
}
sqlite3StrAccumAppend(&txt, ")", 1);
@@ -108452,21 +111065,26 @@ static void explainOneScan(
int iFrom, /* Value for "from" column of output */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
- if( pParse->explain==2 ){
- u32 flags = pLevel->plan.wsFlags;
+#ifndef SQLITE_DEBUG
+ if( pParse->explain==2 )
+#endif
+ {
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
char *zMsg; /* Text to add to EQP output */
- sqlite3_int64 nRow; /* Expected number of rows visited by scan */
int iId = pParse->iSelectId; /* Select id (left-most output column) */
int isSearch; /* True for a SEARCH. False for SCAN. */
+ WhereLoop *pLoop; /* The controlling WhereLoop object */
+ u32 flags; /* Flags that describe this loop */
+ pLoop = pLevel->pWLoop;
+ flags = pLoop->wsFlags;
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
- isSearch = (pLevel->plan.nEq>0)
- || (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
- || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
+ isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
+ || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
+ || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
if( pItem->pSelect ){
@@ -108478,43 +111096,37 @@ static void explainOneScan(
if( pItem->zAlias ){
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
}
- if( (flags & WHERE_INDEXED)!=0 ){
- char *zWhere = explainIndexRange(db, pLevel, pItem->pTab);
- zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg,
- ((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""),
- ((flags & WHERE_IDX_ONLY)?"COVERING ":""),
- ((flags & WHERE_TEMP_INDEX)?"":" "),
- ((flags & WHERE_TEMP_INDEX)?"": pLevel->plan.u.pIdx->zName),
- zWhere
- );
+ if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0
+ && ALWAYS(pLoop->u.btree.pIndex!=0)
+ ){
+ char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
+ zMsg = sqlite3MAppendf(db, zMsg,
+ ((flags & WHERE_AUTO_INDEX) ?
+ "%s USING AUTOMATIC %sINDEX%.0s%s" :
+ "%s USING %sINDEX %s%s"),
+ zMsg, ((flags & WHERE_IDX_ONLY) ? "COVERING " : ""),
+ pLoop->u.btree.pIndex->zName, zWhere);
sqlite3DbFree(db, zWhere);
- }else if( flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+ }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
- if( flags&WHERE_ROWID_EQ ){
+ if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg);
}else if( flags&WHERE_BTM_LIMIT ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>?)", zMsg);
- }else if( flags&WHERE_TOP_LIMIT ){
+ }else if( ALWAYS(flags&WHERE_TOP_LIMIT) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid<?)", zMsg);
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
- sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
- pVtabIdx->idxNum, pVtabIdx->idxStr);
+ pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
- if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){
- testcase( wctrlFlags & WHERE_ORDERBY_MIN );
- nRow = 1;
- }else{
- nRow = (sqlite3_int64)pLevel->plan.nRow;
- }
- zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s", zMsg);
sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
}
}
@@ -108530,7 +111142,6 @@ static void explainOneScan(
static Bitmask codeOneLoopStart(
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
- u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
Bitmask notReady /* Which tables are currently available */
){
int j, k; /* Loop counters */
@@ -108539,27 +111150,31 @@ static Bitmask codeOneLoopStart(
int omitTable; /* True if we use the index only */
int bRev; /* True if we need to scan in reverse order */
WhereLevel *pLevel; /* The where level to be coded */
+ WhereLoop *pLoop; /* The WhereLoop object being coded */
WhereClause *pWC; /* Decomposition of the entire WHERE clause */
WhereTerm *pTerm; /* A WHERE clause term */
Parse *pParse; /* Parsing context */
+ sqlite3 *db; /* Database connection */
Vdbe *v; /* The prepared stmt under constructions */
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 iRowidReg = 0; /* Rowid is stored in this register, if not zero */
int iReleaseReg = 0; /* Temp register to free before returning */
- Bitmask newNotReady; /* Return value */
pParse = pWInfo->pParse;
v = pParse->pVdbe;
- pWC = pWInfo->pWC;
+ pWC = &pWInfo->sWC;
+ db = pParse->db;
pLevel = &pWInfo->a[iLevel];
+ pLoop = pLevel->pWLoop;
pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
- bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
- omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0
- && (wctrlFlags & WHERE_FORCE_TABLE)==0;
- VdbeNoopComment((v, "Begin Join Loop %d", iLevel));
+ pLevel->notReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);
+ bRev = (pWInfo->revMask>>iLevel)&1;
+ omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
+ && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
+ VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
/* Create labels for the "break" and "continue" instructions
** for the current loop. Jump to addrBrk to break out of a loop.
@@ -108595,47 +111210,37 @@ static Bitmask codeOneLoopStart(
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
- /* Case 0: The table is a virtual-table. Use the VFilter and VNext
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+ /* Case 1: The table is a virtual-table. Use the VFilter and VNext
** to access the data.
*/
int iReg; /* P3 Value for OP_VFilter */
int addrNotFound;
- sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
- int nConstraint = pVtabIdx->nConstraint;
- struct sqlite3_index_constraint_usage *aUsage =
- pVtabIdx->aConstraintUsage;
- const struct sqlite3_index_constraint *aConstraint =
- pVtabIdx->aConstraint;
+ int nConstraint = pLoop->nLTerm;
sqlite3ExprCachePush(pParse);
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
addrNotFound = pLevel->addrBrk;
- for(j=1; j<=nConstraint; j++){
- for(k=0; k<nConstraint; k++){
- if( aUsage[k].argvIndex==j ){
- int iTarget = iReg+j+1;
- pTerm = &pWC->a[aConstraint[k].iTermOffset];
- if( pTerm->eOperator & WO_IN ){
- codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget);
- addrNotFound = pLevel->addrNxt;
- }else{
- sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
- }
- break;
- }
+ for(j=0; j<nConstraint; j++){
+ int iTarget = iReg+j+2;
+ pTerm = pLoop->aLTerm[j];
+ if( pTerm==0 ) continue;
+ if( pTerm->eOperator & WO_IN ){
+ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
+ addrNotFound = pLevel->addrNxt;
+ }else{
+ sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
}
- if( k==nConstraint ) break;
}
- sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
- sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
- sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
- pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
- pVtabIdx->needToFreeIdxStr = 0;
- for(j=0; j<nConstraint; j++){
- if( aUsage[j].omit ){
- int iTerm = aConstraint[j].iTermOffset;
- disableTerm(pLevel, &pWC->a[iTerm]);
+ sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
+ sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
+ sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
+ pLoop->u.vtab.idxStr,
+ pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC);
+ pLoop->u.vtab.needFree = 0;
+ for(j=0; j<nConstraint && j<16; j++){
+ if( (pLoop->u.vtab.omitMask>>j)&1 ){
+ disableTerm(pLevel, pLoop->aLTerm[j]);
}
}
pLevel->op = OP_VNext;
@@ -108646,19 +111251,22 @@ static Bitmask codeOneLoopStart(
}else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
- if( pLevel->plan.wsFlags & WHERE_ROWID_EQ ){
- /* Case 1: We can directly reference a single row using an
+ if( (pLoop->wsFlags & WHERE_IPK)!=0
+ && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0
+ ){
+ /* Case 2: We can directly reference a single row using an
** equality comparison against the ROWID field. Or
** we reference multiple rows using a "rowid IN (...)"
** construct.
*/
+ assert( pLoop->u.btree.nEq==1 );
iReleaseReg = sqlite3GetTempReg(pParse);
- pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
+ pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
assert( omitTable==0 );
- testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
- iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg);
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
+ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
@@ -108666,8 +111274,10 @@ static Bitmask codeOneLoopStart(
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
- }else if( pLevel->plan.wsFlags & WHERE_ROWID_RANGE ){
- /* Case 2: We have an inequality comparison against the ROWID field.
+ }else if( (pLoop->wsFlags & WHERE_IPK)!=0
+ && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
+ ){
+ /* Case 3: We have an inequality comparison against the ROWID field.
*/
int testOp = OP_Noop;
int start;
@@ -108675,8 +111285,11 @@ static Bitmask codeOneLoopStart(
WhereTerm *pStart, *pEnd;
assert( omitTable==0 );
- pStart = findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0);
- pEnd = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0);
+ j = 0;
+ pStart = pEnd = 0;
+ if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++];
+ if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++];
+ assert( pStart!=0 || pEnd!=0 );
if( bRev ){
pTerm = pStart;
pStart = pEnd;
@@ -108699,10 +111312,11 @@ static Bitmask codeOneLoopStart(
assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */
assert( TK_GE==TK_GT+3 ); /* ... is correcct. */
- testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ assert( (pStart->wtFlags & TERM_VNULL)==0 );
+ testcase( pStart->wtFlags & TERM_VIRTUAL );
pX = pStart->pExpr;
assert( pX!=0 );
- assert( pStart->leftCursor==iCur );
+ testcase( pStart->leftCursor!=iCur ); /* transitive constraints */
r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
VdbeComment((v, "pk"));
@@ -108716,8 +111330,9 @@ static Bitmask codeOneLoopStart(
Expr *pX;
pX = pEnd->pExpr;
assert( pX!=0 );
- assert( pEnd->leftCursor==iCur );
- testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ assert( (pEnd->wtFlags & TERM_VNULL)==0 );
+ testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */
+ testcase( pEnd->wtFlags & TERM_VIRTUAL );
memEndValue = ++pParse->nMem;
sqlite3ExprCode(pParse, pX->pRight, memEndValue);
if( pX->op==TK_LT || pX->op==TK_GT ){
@@ -108731,11 +111346,7 @@ static Bitmask codeOneLoopStart(
pLevel->op = bRev ? OP_Prev : OP_Next;
pLevel->p1 = iCur;
pLevel->p2 = start;
- if( pStart==0 && pEnd==0 ){
- pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
- }else{
- assert( pLevel->p5==0 );
- }
+ assert( pLevel->p5==0 );
if( testOp!=OP_Noop ){
iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
@@ -108743,8 +111354,8 @@ static Bitmask codeOneLoopStart(
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.
+ }else if( pLoop->wsFlags & WHERE_INDEXED ){
+ /* Case 4: A scan using an index.
**
** The WHERE clause may contain zero or more equality
** terms ("==" or "IN" operators) that refer to the N
@@ -108790,7 +111401,7 @@ static Bitmask codeOneLoopStart(
OP_IdxGE, /* 1: (end_constraints && !bRev) */
OP_IdxLT /* 2: (end_constraints && bRev) */
};
- int nEq = pLevel->plan.nEq; /* Number of == or IN terms */
+ u16 nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */
int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
int regBase; /* Base register holding constraint values */
int r1; /* Temp register */
@@ -108805,11 +111416,11 @@ static Bitmask codeOneLoopStart(
int nExtraReg = 0; /* Number of extra registers needed */
int op; /* Instruction opcode */
char *zStartAff; /* Affinity for start of range constraint */
- char *zEndAff; /* Affinity for end of range constraint */
+ char cEndAff = 0; /* Affinity for end of range constraint */
- pIdx = pLevel->plan.u.pIdx;
+ pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
- k = (nEq==pIdx->nColumn ? -1 : pIdx->aiColumn[nEq]);
+ assert( nEq>=pLoop->u.btree.nSkip );
/* If this loop satisfies a sort order (pOrderBy) request that
** was passed to this function to implement a "SELECT min(x) ..."
@@ -108819,12 +111430,11 @@ static Bitmask codeOneLoopStart(
** the first one after the nEq equality constraints in the index,
** this requires some special handling.
*/
- if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
- && (pLevel->plan.wsFlags&WHERE_ORDERED)
- && (pIdx->nColumn>nEq)
+ if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
+ && (pWInfo->bOBSat!=0)
+ && (pIdx->nKeyCol>nEq)
){
- /* assert( pOrderBy->nExpr==1 ); */
- /* assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); */
+ assert( pLoop->u.btree.nSkip==0 );
isMinQuery = 1;
nExtraReg = 1;
}
@@ -108832,12 +111442,13 @@ static Bitmask codeOneLoopStart(
/* Find any inequality constraint terms for the start and end
** of the range.
*/
- if( pLevel->plan.wsFlags & WHERE_TOP_LIMIT ){
- pRangeEnd = findTerm(pWC, iCur, k, notReady, (WO_LT|WO_LE), pIdx);
+ j = nEq;
+ if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
+ pRangeStart = pLoop->aLTerm[j++];
nExtraReg = 1;
}
- if( pLevel->plan.wsFlags & WHERE_BTM_LIMIT ){
- pRangeStart = findTerm(pWC, iCur, k, notReady, (WO_GT|WO_GE), pIdx);
+ if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
+ pRangeEnd = pLoop->aLTerm[j++];
nExtraReg = 1;
}
@@ -108845,26 +111456,25 @@ static Bitmask codeOneLoopStart(
** and store the values of those terms in an array of registers
** starting at regBase.
*/
- regBase = codeAllEqualityTerms(
- pParse, pLevel, pWC, notReady, nExtraReg, &zStartAff
- );
- zEndAff = sqlite3DbStrDup(pParse->db, zStartAff);
+ regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
+ assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
+ if( zStartAff ) cEndAff = zStartAff[nEq];
addrNxt = pLevel->addrNxt;
/* If we are doing a reverse order scan on an ascending index, or
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
- if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
- || (bRev && pIdx->nColumn==nEq)
+ if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
+ || (bRev && pIdx->nKeyCol==nEq)
){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
}
- testcase( pRangeStart && pRangeStart->eOperator & WO_LE );
- testcase( pRangeStart && pRangeStart->eOperator & WO_GE );
- testcase( pRangeEnd && pRangeEnd->eOperator & WO_LE );
- testcase( pRangeEnd && pRangeEnd->eOperator & WO_GE );
+ testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
+ testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
+ testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 );
+ testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 );
startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
start_constraints = pRangeStart || nEq>0;
@@ -108889,7 +111499,7 @@ static Bitmask codeOneLoopStart(
}
}
nConstraint++;
- testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
}else if( isMinQuery ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
nConstraint++;
@@ -108918,23 +111528,15 @@ static Bitmask codeOneLoopStart(
if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
}
- if( zEndAff ){
- if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){
- /* Since the comparison is to be performed with no conversions
- ** applied to the operands, set the affinity to apply to pRight to
- ** SQLITE_AFF_NONE. */
- zEndAff[nEq] = SQLITE_AFF_NONE;
- }
- if( sqlite3ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){
- zEndAff[nEq] = SQLITE_AFF_NONE;
- }
- }
- codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
+ if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE
+ && !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff)
+ ){
+ codeApplyAffinity(pParse, regBase+nEq, 1, &cEndAff);
+ }
nConstraint++;
- testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
+ testcase( pRangeEnd->wtFlags & TERM_VIRTUAL );
}
- sqlite3DbFree(pParse->db, zStartAff);
- sqlite3DbFree(pParse->db, zEndAff);
+ sqlite3DbFree(db, zStartAff);
/* Top of the loop body */
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@@ -108954,10 +111556,15 @@ static Bitmask codeOneLoopStart(
** If it is, jump to the next iteration of the loop.
*/
r1 = sqlite3GetTempReg(pParse);
- testcase( pLevel->plan.wsFlags & WHERE_BTM_LIMIT );
- testcase( pLevel->plan.wsFlags & WHERE_TOP_LIMIT );
- if( (pLevel->plan.wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
+ testcase( pLoop->wsFlags & WHERE_BTM_LIMIT );
+ testcase( pLoop->wsFlags & WHERE_TOP_LIMIT );
+ if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
+ && (j = pIdx->aiColumn[nEq])>=0
+ && pIdx->pTable->aCol[j].notNull==0
+ && (nEq || (pLoop->wsFlags & WHERE_BTM_LIMIT)==0)
+ ){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
+ VdbeComment((v, "%s", pIdx->pTable->aCol[j].zName));
sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
}
sqlite3ReleaseTempReg(pParse, r1);
@@ -108965,17 +111572,28 @@ static Bitmask codeOneLoopStart(
/* Seek the table cursor, if required */
disableTerm(pLevel, pRangeStart);
disableTerm(pLevel, pRangeEnd);
- if( !omitTable ){
+ if( omitTable ){
+ /* pIdx is a covering index. No need to access the main table. */
+ }else if( HasRowid(pIdx->pTable) ){
iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
+ }else{
+ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
+ iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
+ for(j=0; j<pPk->nKeyCol; j++){
+ k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
+ }
+ sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
+ iRowidReg, pPk->nKeyCol);
}
/* Record the instruction used to terminate the loop. Disable
** WHERE clause terms made redundant by the index range scan.
*/
- if( pLevel->plan.wsFlags & WHERE_UNIQUE ){
+ if( pLoop->wsFlags & WHERE_ONEROW ){
pLevel->op = OP_Noop;
}else if( bRev ){
pLevel->op = OP_Prev;
@@ -108983,7 +111601,7 @@ static Bitmask codeOneLoopStart(
pLevel->op = OP_Next;
}
pLevel->p1 = iIdxCur;
- if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){
+ if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}else{
assert( pLevel->p5==0 );
@@ -108991,8 +111609,8 @@ static Bitmask codeOneLoopStart(
}else
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
- if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
- /* Case 4: Two or more separately indexed terms connected by OR
+ if( pLoop->wsFlags & WHERE_MULTI_OR ){
+ /* Case 5: Two or more separately indexed terms connected by OR
**
** Example:
**
@@ -109045,7 +111663,7 @@ static Bitmask codeOneLoopStart(
int ii; /* Loop counter */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
- pTerm = pLevel->plan.u.pTerm;
+ pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
assert( pTerm->eOperator & WO_OR );
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
@@ -109061,10 +111679,10 @@ static Bitmask codeOneLoopStart(
int nNotReady; /* The number of notReady tables */
struct SrcList_item *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
- pOrTab = sqlite3StackAllocRaw(pParse->db,
+ pOrTab = sqlite3StackAllocRaw(db,
sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
if( pOrTab==0 ) return notReady;
- pOrTab->nAlloc = (i16)(nNotReady + 1);
+ pOrTab->nAlloc = (u8)(nNotReady + 1);
pOrTab->nSrc = pOrTab->nAlloc;
memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
origSrc = pWInfo->pTabList->a;
@@ -109086,7 +111704,7 @@ static Bitmask codeOneLoopStart(
** fall through to the next instruction, just as an OP_Next does if
** called on an uninitialized cursor.
*/
- if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
regRowset = ++pParse->nMem;
regRowid = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
@@ -109111,11 +111729,12 @@ static Bitmask codeOneLoopStart(
int iTerm;
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
Expr *pExpr = pWC->a[iTerm].pExpr;
+ if( &pWC->a[iTerm] == pTerm ) continue;
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
- if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue;
+ if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
- pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
- pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr);
+ pExpr = sqlite3ExprDup(db, pExpr, 0);
+ pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
}
if( pAndExpr ){
pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0);
@@ -109135,13 +111754,13 @@ static Bitmask codeOneLoopStart(
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
- assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
+ assert( pSubWInfo || pParse->nErr || db->mallocFailed );
if( pSubWInfo ){
- WhereLevel *pLvl;
+ WhereLoop *pSubLoop;
explainOneScan(
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
);
- if( (wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
+ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
int r;
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
@@ -109170,13 +111789,13 @@ static Bitmask codeOneLoopStart(
** pCov to NULL to indicate that no candidate covering index will
** be available.
*/
- pLvl = &pSubWInfo->a[0];
- if( (pLvl->plan.wsFlags & WHERE_INDEXED)!=0
- && (pLvl->plan.wsFlags & WHERE_TEMP_INDEX)==0
- && (ii==0 || pLvl->plan.u.pIdx==pCov)
+ pSubLoop = pSubWInfo->a[0].pWLoop;
+ assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
+ if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
+ && (ii==0 || pSubLoop->u.btree.pIndex==pCov)
){
- assert( pLvl->iIdxCur==iCovCur );
- pCov = pLvl->plan.u.pIdx;
+ assert( pSubWInfo->a[0].iIdxCur==iCovCur );
+ pCov = pSubLoop->u.btree.pIndex;
}else{
pCov = 0;
}
@@ -109190,45 +111809,39 @@ static Bitmask codeOneLoopStart(
if( pCov ) pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
- sqlite3ExprDelete(pParse->db, pAndExpr);
+ sqlite3ExprDelete(db, pAndExpr);
}
sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
sqlite3VdbeResolveLabel(v, iLoopBody);
- if( pWInfo->nLevel>1 ) sqlite3StackFree(pParse->db, pOrTab);
+ if( pWInfo->nLevel>1 ) sqlite3StackFree(db, pOrTab);
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
{
- /* Case 5: There is no usable index. We must do a complete
+ /* Case 6: There is no usable index. We must do a complete
** scan of the entire table.
*/
static const u8 aStep[] = { OP_Next, OP_Prev };
static const u8 aStart[] = { OP_Rewind, OP_Last };
assert( bRev==0 || bRev==1 );
- assert( omitTable==0 );
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}
- newNotReady = notReady & ~getMask(pWC->pMaskSet, iCur);
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
- **
- ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
- ** the use of indices become tests that are evaluated against each row of
- ** the relevant input tables.
*/
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
Expr *pE;
- testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
- if( (pTerm->prereqAll & newNotReady)!=0 ){
+ if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
testcase( pWInfo->untestedTerms==0
&& (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
pWInfo->untestedTerms = 1;
@@ -109252,22 +111865,28 @@ static Bitmask codeOneLoopStart(
** the implied "t1.a=123" constraint.
*/
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
- Expr *pE;
+ Expr *pE, *pEAlt;
WhereTerm *pAlt;
- Expr sEq;
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue;
if( pTerm->leftCursor!=iCur ) continue;
+ if( pLevel->iLeftJoin ) continue;
pE = pTerm->pExpr;
assert( !ExprHasProperty(pE, EP_FromJoin) );
- assert( (pTerm->prereqRight & newNotReady)!=0 );
+ assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
- VdbeNoopComment((v, "begin transitive constraint"));
- sEq = *pAlt->pExpr;
- sEq.pLeft = pE->pLeft;
- sqlite3ExprIfFalse(pParse, &sEq, addrCont, SQLITE_JUMPIFNULL);
+ testcase( pAlt->eOperator & WO_EQ );
+ testcase( pAlt->eOperator & WO_IN );
+ VdbeModuleComment((v, "begin transitive constraint"));
+ pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
+ if( pEAlt ){
+ *pEAlt = *pAlt->pExpr;
+ pEAlt->pLeft = pE->pLeft;
+ sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL);
+ sqlite3StackFree(db, pEAlt);
+ }
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
@@ -109279,10 +111898,10 @@ static Bitmask codeOneLoopStart(
VdbeComment((v, "record LEFT JOIN hit"));
sqlite3ExprCacheClear(pParse);
for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
- testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
- if( (pTerm->prereqAll & newNotReady)!=0 ){
+ if( (pTerm->prereqAll & pLevel->notReady)!=0 ){
assert( pWInfo->untestedTerms );
continue;
}
@@ -109293,50 +111912,1759 @@ static Bitmask codeOneLoopStart(
}
sqlite3ReleaseTempReg(pParse, iReleaseReg);
- return newNotReady;
+ return pLevel->notReady;
}
-#if defined(SQLITE_TEST)
+#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN)
/*
-** The following variable holds a text description of query plan generated
-** by the most recent call to sqlite3WhereBegin(). Each call to WhereBegin
-** overwrites the previous. This information is used for testing and
-** analysis only.
+** Generate "Explanation" text for a WhereTerm.
*/
-SQLITE_API char sqlite3_query_plan[BMS*2*40]; /* Text of the join */
-static int nQPlan = 0; /* Next free slow in _query_plan[] */
+static void whereExplainTerm(Vdbe *v, WhereTerm *pTerm){
+ char zType[4];
+ memcpy(zType, "...", 4);
+ if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
+ if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
+ if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
+ sqlite3ExplainPrintf(v, "%s ", zType);
+ sqlite3ExplainExpr(v, pTerm->pExpr);
+}
+#endif /* WHERETRACE_ENABLED && SQLITE_ENABLE_TREE_EXPLAIN */
-#endif /* SQLITE_TEST */
+#ifdef WHERETRACE_ENABLED
+/*
+** Print a WhereLoop object for debugging purposes
+*/
+static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
+ WhereInfo *pWInfo = pWC->pWInfo;
+ int nb = 1+(pWInfo->pTabList->nSrc+7)/8;
+ struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
+ Table *pTab = pItem->pTab;
+ sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
+ p->iTab, nb, p->maskSelf, nb, p->prereq);
+ sqlite3DebugPrintf(" %12s",
+ pItem->zAlias ? pItem->zAlias : pTab->zName);
+ if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ const char *zName;
+ if( p->u.btree.pIndex && (zName = p->u.btree.pIndex->zName)!=0 ){
+ if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){
+ int i = sqlite3Strlen30(zName) - 1;
+ while( zName[i]!='_' ) i--;
+ zName += i;
+ }
+ sqlite3DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq);
+ }else{
+ sqlite3DebugPrintf("%20s","");
+ }
+ }else{
+ char *z;
+ if( p->u.vtab.idxStr ){
+ z = sqlite3_mprintf("(%d,\"%s\",%x)",
+ p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
+ }else{
+ z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
+ }
+ sqlite3DebugPrintf(" %-19s", z);
+ sqlite3_free(z);
+ }
+ sqlite3DebugPrintf(" f %04x N %d", p->wsFlags, p->nLTerm);
+ sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
+#ifdef SQLITE_ENABLE_TREE_EXPLAIN
+ /* If the 0x100 bit of wheretracing is set, then show all of the constraint
+ ** expressions in the WhereLoop.aLTerm[] array.
+ */
+ if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){ /* WHERETRACE 0x100 */
+ int i;
+ Vdbe *v = pWInfo->pParse->pVdbe;
+ sqlite3ExplainBegin(v);
+ for(i=0; i<p->nLTerm; i++){
+ WhereTerm *pTerm = p->aLTerm[i];
+ if( pTerm==0 ) continue;
+ sqlite3ExplainPrintf(v, " (%d) #%-2d ", i+1, (int)(pTerm-pWC->a));
+ sqlite3ExplainPush(v);
+ whereExplainTerm(v, pTerm);
+ sqlite3ExplainPop(v);
+ sqlite3ExplainNL(v);
+ }
+ sqlite3ExplainFinish(v);
+ sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v));
+ }
+#endif
+}
+#endif
+
+/*
+** Convert bulk memory into a valid WhereLoop that can be passed
+** to whereLoopClear harmlessly.
+*/
+static void whereLoopInit(WhereLoop *p){
+ p->aLTerm = p->aLTermSpace;
+ p->nLTerm = 0;
+ p->nLSlot = ArraySize(p->aLTermSpace);
+ p->wsFlags = 0;
+}
+
+/*
+** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact.
+*/
+static void whereLoopClearUnion(sqlite3 *db, WhereLoop *p){
+ if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){
+ if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){
+ sqlite3_free(p->u.vtab.idxStr);
+ p->u.vtab.needFree = 0;
+ p->u.vtab.idxStr = 0;
+ }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
+ sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
+ sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo);
+ sqlite3DbFree(db, p->u.btree.pIndex);
+ p->u.btree.pIndex = 0;
+ }
+ }
+}
+
+/*
+** Deallocate internal memory used by a WhereLoop object
+*/
+static void whereLoopClear(sqlite3 *db, WhereLoop *p){
+ if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
+ whereLoopClearUnion(db, p);
+ whereLoopInit(p);
+}
+
+/*
+** Increase the memory allocation for pLoop->aLTerm[] to be at least n.
+*/
+static int whereLoopResize(sqlite3 *db, WhereLoop *p, int n){
+ WhereTerm **paNew;
+ if( p->nLSlot>=n ) return SQLITE_OK;
+ n = (n+7)&~7;
+ paNew = sqlite3DbMallocRaw(db, sizeof(p->aLTerm[0])*n);
+ if( paNew==0 ) return SQLITE_NOMEM;
+ memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
+ if( p->aLTerm!=p->aLTermSpace ) sqlite3DbFree(db, p->aLTerm);
+ p->aLTerm = paNew;
+ p->nLSlot = n;
+ return SQLITE_OK;
+}
+
+/*
+** Transfer content from the second pLoop into the first.
+*/
+static int whereLoopXfer(sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
+ whereLoopClearUnion(db, pTo);
+ if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
+ memset(&pTo->u, 0, sizeof(pTo->u));
+ return SQLITE_NOMEM;
+ }
+ memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
+ memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
+ if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){
+ pFrom->u.vtab.needFree = 0;
+ }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){
+ pFrom->u.btree.pIndex = 0;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Delete a WhereLoop object
+*/
+static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
+ whereLoopClear(db, p);
+ sqlite3DbFree(db, p);
+}
/*
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
if( ALWAYS(pWInfo) ){
- int i;
- for(i=0; i<pWInfo->nLevel; i++){
- sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
- if( pInfo ){
- /* assert( pInfo->needToFreeIdxStr==0 || db->mallocFailed ); */
- if( pInfo->needToFreeIdxStr ){
- sqlite3_free(pInfo->idxStr);
+ whereClauseClear(&pWInfo->sWC);
+ while( pWInfo->pLoops ){
+ WhereLoop *p = pWInfo->pLoops;
+ pWInfo->pLoops = p->pNextLoop;
+ whereLoopDelete(db, p);
+ }
+ sqlite3DbFree(db, pWInfo);
+ }
+}
+
+/*
+** Insert or replace a WhereLoop entry using the template supplied.
+**
+** An existing WhereLoop entry might be overwritten if the new template
+** is better and has fewer dependencies. Or the template will be ignored
+** and no insert will occur if an existing WhereLoop is faster and has
+** fewer dependencies than the template. Otherwise a new WhereLoop is
+** added based on the template.
+**
+** If pBuilder->pOrSet is not NULL then we only care about only the
+** prerequisites and rRun and nOut costs of the N best loops. That
+** information is gathered in the pBuilder->pOrSet object. This special
+** processing mode is used only for OR clause processing.
+**
+** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
+** still might overwrite similar loops with the new template if the
+** template is better. Loops may be overwritten if the following
+** conditions are met:
+**
+** (1) They have the same iTab.
+** (2) They have the same iSortIdx.
+** (3) The template has same or fewer dependencies than the current loop
+** (4) The template has the same or lower cost than the current loop
+** (5) The template uses more terms of the same index but has no additional
+** dependencies
+*/
+static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
+ WhereLoop **ppPrev, *p, *pNext = 0;
+ WhereInfo *pWInfo = pBuilder->pWInfo;
+ sqlite3 *db = pWInfo->pParse->db;
+
+ /* If pBuilder->pOrSet is defined, then only keep track of the costs
+ ** and prereqs.
+ */
+ if( pBuilder->pOrSet!=0 ){
+#if WHERETRACE_ENABLED
+ u16 n = pBuilder->pOrSet->n;
+ int x =
+#endif
+ whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
+ pTemplate->nOut);
+#if WHERETRACE_ENABLED /* 0x8 */
+ if( sqlite3WhereTrace & 0x8 ){
+ sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
+ whereLoopPrint(pTemplate, pBuilder->pWC);
+ }
+#endif
+ return SQLITE_OK;
+ }
+
+ /* Search for an existing WhereLoop to overwrite, or which takes
+ ** priority over pTemplate.
+ */
+ for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){
+ if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){
+ /* If either the iTab or iSortIdx values for two WhereLoop are different
+ ** then those WhereLoops need to be considered separately. Neither is
+ ** a candidate to replace the other. */
+ continue;
+ }
+ /* In the current implementation, the rSetup value is either zero
+ ** or the cost of building an automatic index (NlogN) and the NlogN
+ ** is the same for compatible WhereLoops. */
+ assert( p->rSetup==0 || pTemplate->rSetup==0
+ || p->rSetup==pTemplate->rSetup );
+
+ /* whereLoopAddBtree() always generates and inserts the automatic index
+ ** case first. Hence compatible candidate WhereLoops never have a larger
+ ** rSetup. Call this SETUP-INVARIANT */
+ assert( p->rSetup>=pTemplate->rSetup );
+
+ if( (p->prereq & pTemplate->prereq)==p->prereq
+ && p->rSetup<=pTemplate->rSetup
+ && p->rRun<=pTemplate->rRun
+ && p->nOut<=pTemplate->nOut
+ ){
+ /* This branch taken when p is equal or better than pTemplate in
+ ** all of (1) dependencies (2) setup-cost, (3) run-cost, and
+ ** (4) number of output rows. */
+ assert( p->rSetup==pTemplate->rSetup );
+ if( p->prereq==pTemplate->prereq
+ && p->nLTerm<pTemplate->nLTerm
+ && (p->wsFlags & pTemplate->wsFlags & WHERE_INDEXED)!=0
+ && (p->u.btree.pIndex==pTemplate->u.btree.pIndex
+ || pTemplate->rRun+p->nLTerm<=p->rRun+pTemplate->nLTerm)
+ ){
+ /* Overwrite an existing WhereLoop with an similar one that uses
+ ** more terms of the index */
+ pNext = p->pNextLoop;
+ break;
+ }else{
+ /* pTemplate is not helpful.
+ ** Return without changing or adding anything */
+ goto whereLoopInsert_noop;
+ }
+ }
+ if( (p->prereq & pTemplate->prereq)==pTemplate->prereq
+ && p->rRun>=pTemplate->rRun
+ && p->nOut>=pTemplate->nOut
+ ){
+ /* Overwrite an existing WhereLoop with a better one: one that is
+ ** better at one of (1) dependencies, (2) setup-cost, (3) run-cost
+ ** or (4) number of output rows, and is no worse in any of those
+ ** categories. */
+ assert( p->rSetup>=pTemplate->rSetup ); /* SETUP-INVARIANT above */
+ pNext = p->pNextLoop;
+ break;
+ }
+ }
+
+ /* If we reach this point it means that either p[] should be overwritten
+ ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
+ ** WhereLoop and insert it.
+ */
+#if WHERETRACE_ENABLED /* 0x8 */
+ if( sqlite3WhereTrace & 0x8 ){
+ if( p!=0 ){
+ sqlite3DebugPrintf("ins-del: ");
+ whereLoopPrint(p, pBuilder->pWC);
+ }
+ sqlite3DebugPrintf("ins-new: ");
+ whereLoopPrint(pTemplate, pBuilder->pWC);
+ }
+#endif
+ if( p==0 ){
+ p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
+ if( p==0 ) return SQLITE_NOMEM;
+ whereLoopInit(p);
+ }
+ whereLoopXfer(db, p, pTemplate);
+ p->pNextLoop = pNext;
+ *ppPrev = p;
+ if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
+ Index *pIndex = p->u.btree.pIndex;
+ if( pIndex && pIndex->tnum==0 ){
+ p->u.btree.pIndex = 0;
+ }
+ }
+ return SQLITE_OK;
+
+ /* Jump here if the insert is a no-op */
+whereLoopInsert_noop:
+#if WHERETRACE_ENABLED /* 0x8 */
+ if( sqlite3WhereTrace & 0x8 ){
+ sqlite3DebugPrintf("ins-noop: ");
+ whereLoopPrint(pTemplate, pBuilder->pWC);
+ }
+#endif
+ return SQLITE_OK;
+}
+
+/*
+** Adjust the WhereLoop.nOut value downward to account for terms of the
+** WHERE clause that reference the loop but which are not used by an
+** index.
+**
+** In the current implementation, the first extra WHERE clause term reduces
+** the number of output rows by a factor of 10 and each additional term
+** reduces the number of output rows by sqrt(2).
+*/
+static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
+ WhereTerm *pTerm, *pX;
+ Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
+ int i, j;
+
+ if( !OptimizationEnabled(pWC->pWInfo->pParse->db, SQLITE_AdjustOutEst) ){
+ return;
+ }
+ for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
+ if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
+ if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
+ if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
+ for(j=pLoop->nLTerm-1; j>=0; j--){
+ pX = pLoop->aLTerm[j];
+ if( pX==0 ) continue;
+ if( pX==pTerm ) break;
+ if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
+ }
+ if( j<0 ) pLoop->nOut += pTerm->truthProb;
+ }
+}
+
+/*
+** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex.
+** Try to match one more.
+**
+** If pProbe->tnum==0, that means pIndex is a fake index used for the
+** INTEGER PRIMARY KEY.
+*/
+static int whereLoopAddBtreeIndex(
+ WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
+ struct SrcList_item *pSrc, /* FROM clause term being analyzed */
+ Index *pProbe, /* An index on pSrc */
+ LogEst nInMul /* log(Number of iterations due to IN) */
+){
+ WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */
+ Parse *pParse = pWInfo->pParse; /* Parsing context */
+ sqlite3 *db = pParse->db; /* Database connection malloc context */
+ WhereLoop *pNew; /* Template WhereLoop under construction */
+ WhereTerm *pTerm; /* A WhereTerm under consideration */
+ int opMask; /* Valid operators for constraints */
+ WhereScan scan; /* Iterator for WHERE terms */
+ Bitmask saved_prereq; /* Original value of pNew->prereq */
+ u16 saved_nLTerm; /* Original value of pNew->nLTerm */
+ u16 saved_nEq; /* Original value of pNew->u.btree.nEq */
+ u16 saved_nSkip; /* Original value of pNew->u.btree.nSkip */
+ u32 saved_wsFlags; /* Original value of pNew->wsFlags */
+ LogEst saved_nOut; /* Original value of pNew->nOut */
+ int iCol; /* Index of the column in the table */
+ int rc = SQLITE_OK; /* Return code */
+ LogEst nRowEst; /* Estimated index selectivity */
+ LogEst rLogSize; /* Logarithm of table size */
+ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */
+
+ pNew = pBuilder->pNew;
+ if( db->mallocFailed ) return SQLITE_NOMEM;
+
+ assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
+ assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
+ if( pNew->wsFlags & WHERE_BTM_LIMIT ){
+ opMask = WO_LT|WO_LE;
+ }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){
+ opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE;
+ }else{
+ opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE;
+ }
+ if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
+
+ assert( pNew->u.btree.nEq<=pProbe->nKeyCol );
+ if( pNew->u.btree.nEq < pProbe->nKeyCol ){
+ iCol = pProbe->aiColumn[pNew->u.btree.nEq];
+ nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
+ if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
+ }else{
+ iCol = -1;
+ nRowEst = 0;
+ }
+ pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol,
+ opMask, pProbe);
+ saved_nEq = pNew->u.btree.nEq;
+ saved_nSkip = pNew->u.btree.nSkip;
+ saved_nLTerm = pNew->nLTerm;
+ saved_wsFlags = pNew->wsFlags;
+ saved_prereq = pNew->prereq;
+ saved_nOut = pNew->nOut;
+ pNew->rSetup = 0;
+ rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
+
+ /* Consider using a skip-scan if there are no WHERE clause constraints
+ ** available for the left-most terms of the index, and if the average
+ ** number of repeats in the left-most terms is at least 18. The magic
+ ** number 18 was found by experimentation to be the payoff point where
+ ** skip-scan become faster than a full-scan.
+ */
+ if( pTerm==0
+ && saved_nEq==saved_nSkip
+ && saved_nEq+1<pProbe->nKeyCol
+ && pProbe->aiRowEst[saved_nEq+1]>=18 /* TUNING: Minimum for skip-scan */
+ ){
+ LogEst nIter;
+ pNew->u.btree.nEq++;
+ pNew->u.btree.nSkip++;
+ pNew->aLTerm[pNew->nLTerm++] = 0;
+ pNew->wsFlags |= WHERE_SKIPSCAN;
+ nIter = sqlite3LogEst(pProbe->aiRowEst[0]/pProbe->aiRowEst[saved_nEq+1]);
+ whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter);
+ }
+ for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
+ int nIn = 0;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ int nRecValid = pBuilder->nRecValid;
+#endif
+ if( (pTerm->eOperator==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
+ && (iCol<0 || pSrc->pTab->aCol[iCol].notNull)
+ ){
+ continue; /* ignore IS [NOT] NULL constraints on NOT NULL columns */
+ }
+ if( pTerm->prereqRight & pNew->maskSelf ) continue;
+
+ assert( pNew->nOut==saved_nOut );
+
+ pNew->wsFlags = saved_wsFlags;
+ pNew->u.btree.nEq = saved_nEq;
+ pNew->nLTerm = saved_nLTerm;
+ if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
+ pNew->aLTerm[pNew->nLTerm++] = pTerm;
+ pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;
+ pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */
+ if( pTerm->eOperator & WO_IN ){
+ Expr *pExpr = pTerm->pExpr;
+ pNew->wsFlags |= WHERE_COLUMN_IN;
+ if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
+ nIn = 46; assert( 46==sqlite3LogEst(25) );
+ }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
+ /* "x IN (value, value, ...)" */
+ nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
+ }
+ pNew->rRun += nIn;
+ pNew->u.btree.nEq++;
+ pNew->nOut = nRowEst + nInMul + nIn;
+ }else if( pTerm->eOperator & (WO_EQ) ){
+ assert(
+ (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN|WHERE_SKIPSCAN))!=0
+ || nInMul==0
+ );
+ pNew->wsFlags |= WHERE_COLUMN_EQ;
+ if( iCol<0
+ || (pProbe->onError!=OE_None && nInMul==0
+ && pNew->u.btree.nEq==pProbe->nKeyCol-1)
+ ){
+ assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 );
+ pNew->wsFlags |= WHERE_ONEROW;
+ }
+ pNew->u.btree.nEq++;
+ pNew->nOut = nRowEst + nInMul;
+ }else if( pTerm->eOperator & (WO_ISNULL) ){
+ pNew->wsFlags |= WHERE_COLUMN_NULL;
+ pNew->u.btree.nEq++;
+ /* TUNING: IS NULL selects 2 rows */
+ nIn = 10; assert( 10==sqlite3LogEst(2) );
+ pNew->nOut = nRowEst + nInMul + nIn;
+ }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
+ testcase( pTerm->eOperator & WO_GT );
+ testcase( pTerm->eOperator & WO_GE );
+ pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
+ pBtm = pTerm;
+ pTop = 0;
+ }else{
+ assert( pTerm->eOperator & (WO_LT|WO_LE) );
+ testcase( pTerm->eOperator & WO_LT );
+ testcase( pTerm->eOperator & WO_LE );
+ pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
+ pTop = pTerm;
+ pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
+ pNew->aLTerm[pNew->nLTerm-2] : 0;
+ }
+ if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
+ /* Adjust nOut and rRun for STAT3 range values */
+ assert( pNew->nOut==saved_nOut );
+ whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
+ }
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( nInMul==0
+ && pProbe->nSample
+ && pNew->u.btree.nEq<=pProbe->nSampleCol
+ && OptimizationEnabled(db, SQLITE_Stat3)
+ ){
+ Expr *pExpr = pTerm->pExpr;
+ tRowcnt nOut = 0;
+ if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){
+ testcase( pTerm->eOperator & WO_EQ );
+ testcase( pTerm->eOperator & WO_ISNULL );
+ rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
+ }else if( (pTerm->eOperator & WO_IN)
+ && !ExprHasProperty(pExpr, EP_xIsSelect) ){
+ rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
+ }
+ assert( nOut==0 || rc==SQLITE_OK );
+ if( nOut ){
+ pNew->nOut = sqlite3LogEst(nOut);
+ if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
+ }
+ }
+#endif
+ if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
+ /* Each row involves a step of the index, then a binary search of
+ ** the main table */
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun,rLogSize>27 ? rLogSize-17 : 10);
+ }
+ /* Step cost for each output row */
+ pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
+ whereLoopOutputAdjust(pBuilder->pWC, pNew);
+ rc = whereLoopInsert(pBuilder, pNew);
+ if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
+ && pNew->u.btree.nEq<(pProbe->nKeyCol + (pProbe->zName!=0))
+ ){
+ whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
+ }
+ pNew->nOut = saved_nOut;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ pBuilder->nRecValid = nRecValid;
+#endif
+ }
+ pNew->prereq = saved_prereq;
+ pNew->u.btree.nEq = saved_nEq;
+ pNew->u.btree.nSkip = saved_nSkip;
+ pNew->wsFlags = saved_wsFlags;
+ pNew->nOut = saved_nOut;
+ pNew->nLTerm = saved_nLTerm;
+ return rc;
+}
+
+/*
+** Return True if it is possible that pIndex might be useful in
+** implementing the ORDER BY clause in pBuilder.
+**
+** Return False if pBuilder does not contain an ORDER BY clause or
+** if there is no way for pIndex to be useful in implementing that
+** ORDER BY clause.
+*/
+static int indexMightHelpWithOrderBy(
+ WhereLoopBuilder *pBuilder,
+ Index *pIndex,
+ int iCursor
+){
+ ExprList *pOB;
+ int ii, jj;
+
+ if( pIndex->bUnordered ) return 0;
+ if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
+ for(ii=0; ii<pOB->nExpr; ii++){
+ Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
+ if( pExpr->op!=TK_COLUMN ) return 0;
+ if( pExpr->iTable==iCursor ){
+ for(jj=0; jj<pIndex->nKeyCol; jj++){
+ if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Return a bitmask where 1s indicate that the corresponding column of
+** the table is used by an index. Only the first 63 columns are considered.
+*/
+static Bitmask columnsInIndex(Index *pIdx){
+ Bitmask m = 0;
+ int j;
+ for(j=pIdx->nColumn-1; j>=0; j--){
+ int x = pIdx->aiColumn[j];
+ if( x>=0 ){
+ testcase( x==BMS-1 );
+ testcase( x==BMS-2 );
+ if( x<BMS-1 ) m |= MASKBIT(x);
+ }
+ }
+ return m;
+}
+
+/* Check to see if a partial index with pPartIndexWhere can be used
+** in the current query. Return true if it can be and false if not.
+*/
+static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
+ int i;
+ WhereTerm *pTerm;
+ for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+ if( sqlite3ExprImpliesExpr(pTerm->pExpr, pWhere, iTab) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Add all WhereLoop objects for a single table of the join where the table
+** is idenfied by pBuilder->pNew->iTab. That table is guaranteed to be
+** a b-tree table, not a virtual table.
+*/
+static int whereLoopAddBtree(
+ WhereLoopBuilder *pBuilder, /* WHERE clause information */
+ Bitmask mExtra /* Extra prerequesites for using this table */
+){
+ WhereInfo *pWInfo; /* WHERE analysis context */
+ Index *pProbe; /* An index we are evaluating */
+ Index sPk; /* A fake index object for the primary key */
+ tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
+ i16 aiColumnPk = -1; /* The aColumn[] value for the sPk index */
+ SrcList *pTabList; /* The FROM clause */
+ struct SrcList_item *pSrc; /* The FROM clause btree term to add */
+ WhereLoop *pNew; /* Template WhereLoop object */
+ int rc = SQLITE_OK; /* Return code */
+ int iSortIdx = 1; /* Index number */
+ int b; /* A boolean value */
+ LogEst rSize; /* number of rows in the table */
+ LogEst rLogSize; /* Logarithm of the number of rows in the table */
+ WhereClause *pWC; /* The parsed WHERE clause */
+ Table *pTab; /* Table being queried */
+
+ pNew = pBuilder->pNew;
+ pWInfo = pBuilder->pWInfo;
+ pTabList = pWInfo->pTabList;
+ pSrc = pTabList->a + pNew->iTab;
+ pTab = pSrc->pTab;
+ pWC = pBuilder->pWC;
+ assert( !IsVirtual(pSrc->pTab) );
+
+ if( pSrc->pIndex ){
+ /* An INDEXED BY clause specifies a particular index to use */
+ pProbe = pSrc->pIndex;
+ }else if( !HasRowid(pTab) ){
+ pProbe = pTab->pIndex;
+ }else{
+ /* There is no INDEXED BY clause. Create a fake Index object in local
+ ** variable sPk to represent the rowid primary key index. Make this
+ ** fake index the first in a chain of Index objects with all of the real
+ ** indices to follow */
+ Index *pFirst; /* First of real indices on the table */
+ memset(&sPk, 0, sizeof(Index));
+ sPk.nKeyCol = 1;
+ sPk.aiColumn = &aiColumnPk;
+ sPk.aiRowEst = aiRowEstPk;
+ sPk.onError = OE_Replace;
+ sPk.pTable = pTab;
+ aiRowEstPk[0] = pTab->nRowEst;
+ aiRowEstPk[1] = 1;
+ pFirst = pSrc->pTab->pIndex;
+ if( pSrc->notIndexed==0 ){
+ /* The real indices of the table are only considered if the
+ ** NOT INDEXED qualifier is omitted from the FROM clause */
+ sPk.pNext = pFirst;
+ }
+ pProbe = &sPk;
+ }
+ rSize = sqlite3LogEst(pTab->nRowEst);
+ rLogSize = estLog(rSize);
+
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+ /* Automatic indexes */
+ if( !pBuilder->pOrSet
+ && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
+ && pSrc->pIndex==0
+ && !pSrc->viaCoroutine
+ && !pSrc->notIndexed
+ && HasRowid(pTab)
+ && !pSrc->isCorrelated
+ ){
+ /* Generate auto-index WhereLoops */
+ WhereTerm *pTerm;
+ WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
+ for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
+ if( pTerm->prereqRight & pNew->maskSelf ) continue;
+ if( termCanDriveIndex(pTerm, pSrc, 0) ){
+ pNew->u.btree.nEq = 1;
+ pNew->u.btree.nSkip = 0;
+ pNew->u.btree.pIndex = 0;
+ pNew->nLTerm = 1;
+ pNew->aLTerm[0] = pTerm;
+ /* TUNING: One-time cost for computing the automatic index is
+ ** approximately 7*N*log2(N) where N is the number of rows in
+ ** the table being indexed. */
+ pNew->rSetup = rLogSize + rSize + 28; assert( 28==sqlite3LogEst(7) );
+ /* TUNING: Each index lookup yields 20 rows in the table. This
+ ** is more than the usual guess of 10 rows, since we have no way
+ ** of knowning how selective the index will ultimately be. It would
+ ** not be unreasonable to make this value much larger. */
+ pNew->nOut = 43; assert( 43==sqlite3LogEst(20) );
+ pNew->rRun = sqlite3LogEstAdd(rLogSize,pNew->nOut);
+ pNew->wsFlags = WHERE_AUTO_INDEX;
+ pNew->prereq = mExtra | pTerm->prereqRight;
+ rc = whereLoopInsert(pBuilder, pNew);
+ }
+ }
+ }
+#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+
+ /* Loop over all indices
+ */
+ for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
+ if( pProbe->pPartIdxWhere!=0
+ && !whereUsablePartialIndex(pNew->iTab, pWC, pProbe->pPartIdxWhere) ){
+ continue; /* Partial index inappropriate for this query */
+ }
+ pNew->u.btree.nEq = 0;
+ pNew->u.btree.nSkip = 0;
+ pNew->nLTerm = 0;
+ pNew->iSortIdx = 0;
+ pNew->rSetup = 0;
+ pNew->prereq = mExtra;
+ pNew->nOut = rSize;
+ pNew->u.btree.pIndex = pProbe;
+ b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
+ /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
+ assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
+ if( pProbe->tnum<=0 ){
+ /* Integer primary key index */
+ pNew->wsFlags = WHERE_IPK;
+
+ /* Full table scan */
+ pNew->iSortIdx = b ? iSortIdx : 0;
+ /* TUNING: Cost of full table scan is 3*(N + log2(N)).
+ ** + The extra 3 factor is to encourage the use of indexed lookups
+ ** over full scans. FIXME */
+ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
+ whereLoopOutputAdjust(pWC, pNew);
+ rc = whereLoopInsert(pBuilder, pNew);
+ pNew->nOut = rSize;
+ if( rc ) break;
+ }else{
+ Bitmask m;
+ if( pProbe->isCovering ){
+ pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
+ m = 0;
+ }else{
+ m = pSrc->colUsed & ~columnsInIndex(pProbe);
+ pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
+ }
+
+ /* Full scan via index */
+ if( b
+ || !HasRowid(pTab)
+ || ( m==0
+ && pProbe->bUnordered==0
+ && (pProbe->szIdxRow<pTab->szTabRow)
+ && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+ && sqlite3GlobalConfig.bUseCis
+ && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
+ )
+ ){
+ pNew->iSortIdx = b ? iSortIdx : 0;
+ if( m==0 ){
+ /* TUNING: Cost of a covering index scan is K*(N + log2(N)).
+ ** + The extra factor K of between 1.1 and 3.0 that depends
+ ** on the relative sizes of the table and the index. K
+ ** is smaller for smaller indices, thus favoring them.
+ */
+ pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
+ (15*pProbe->szIdxRow)/pTab->szTabRow;
+ }else{
+ /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
+ ** which we will simplify to just N*log2(N) */
+ pNew->rRun = rSize + rLogSize;
}
- sqlite3DbFree(db, pInfo);
+ whereLoopOutputAdjust(pWC, pNew);
+ rc = whereLoopInsert(pBuilder, pNew);
+ pNew->nOut = rSize;
+ if( rc ) break;
}
- if( pWInfo->a[i].plan.wsFlags & WHERE_TEMP_INDEX ){
- Index *pIdx = pWInfo->a[i].plan.u.pIdx;
- if( pIdx ){
- sqlite3DbFree(db, pIdx->zColAff);
- sqlite3DbFree(db, pIdx);
+ }
+
+ rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ sqlite3Stat4ProbeFree(pBuilder->pRec);
+ pBuilder->nRecValid = 0;
+ pBuilder->pRec = 0;
+#endif
+
+ /* If there was an INDEXED BY clause, then only that one index is
+ ** considered. */
+ if( pSrc->pIndex ) break;
+ }
+ return rc;
+}
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Add all WhereLoop objects for a table of the join identified by
+** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
+*/
+static int whereLoopAddVirtual(
+ WhereLoopBuilder *pBuilder, /* WHERE clause information */
+ Bitmask mExtra
+){
+ WhereInfo *pWInfo; /* WHERE analysis context */
+ Parse *pParse; /* The parsing context */
+ WhereClause *pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc; /* The FROM clause term to search */
+ Table *pTab;
+ sqlite3 *db;
+ sqlite3_index_info *pIdxInfo;
+ struct sqlite3_index_constraint *pIdxCons;
+ struct sqlite3_index_constraint_usage *pUsage;
+ WhereTerm *pTerm;
+ int i, j;
+ int iTerm, mxTerm;
+ int nConstraint;
+ int seenIn = 0; /* True if an IN operator is seen */
+ int seenVar = 0; /* True if a non-constant constraint is seen */
+ int iPhase; /* 0: const w/o IN, 1: const, 2: no IN, 2: IN */
+ WhereLoop *pNew;
+ int rc = SQLITE_OK;
+
+ pWInfo = pBuilder->pWInfo;
+ pParse = pWInfo->pParse;
+ db = pParse->db;
+ pWC = pBuilder->pWC;
+ pNew = pBuilder->pNew;
+ pSrc = &pWInfo->pTabList->a[pNew->iTab];
+ pTab = pSrc->pTab;
+ assert( IsVirtual(pTab) );
+ pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pBuilder->pOrderBy);
+ if( pIdxInfo==0 ) return SQLITE_NOMEM;
+ pNew->prereq = 0;
+ pNew->rSetup = 0;
+ pNew->wsFlags = WHERE_VIRTUALTABLE;
+ pNew->nLTerm = 0;
+ pNew->u.vtab.needFree = 0;
+ pUsage = pIdxInfo->aConstraintUsage;
+ nConstraint = pIdxInfo->nConstraint;
+ if( whereLoopResize(db, pNew, nConstraint) ){
+ sqlite3DbFree(db, pIdxInfo);
+ return SQLITE_NOMEM;
+ }
+
+ for(iPhase=0; iPhase<=3; iPhase++){
+ if( !seenIn && (iPhase&1)!=0 ){
+ iPhase++;
+ if( iPhase>3 ) break;
+ }
+ if( !seenVar && iPhase>1 ) break;
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+ j = pIdxCons->iTermOffset;
+ pTerm = &pWC->a[j];
+ switch( iPhase ){
+ case 0: /* Constants without IN operator */
+ pIdxCons->usable = 0;
+ if( (pTerm->eOperator & WO_IN)!=0 ){
+ seenIn = 1;
+ }
+ if( pTerm->prereqRight!=0 ){
+ seenVar = 1;
+ }else if( (pTerm->eOperator & WO_IN)==0 ){
+ pIdxCons->usable = 1;
+ }
+ break;
+ case 1: /* Constants with IN operators */
+ assert( seenIn );
+ pIdxCons->usable = (pTerm->prereqRight==0);
+ break;
+ case 2: /* Variables without IN */
+ assert( seenVar );
+ pIdxCons->usable = (pTerm->eOperator & WO_IN)==0;
+ break;
+ default: /* Variables with IN */
+ assert( seenVar && seenIn );
+ pIdxCons->usable = 1;
+ break;
+ }
+ }
+ memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+ if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->idxNum = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ pIdxInfo->orderByConsumed = 0;
+ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
+ pIdxInfo->estimatedRows = 25;
+ rc = vtabBestIndex(pParse, pTab, pIdxInfo);
+ if( rc ) goto whereLoopAddVtab_exit;
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ pNew->prereq = mExtra;
+ mxTerm = -1;
+ assert( pNew->nLSlot>=nConstraint );
+ for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
+ pNew->u.vtab.omitMask = 0;
+ for(i=0; i<nConstraint; i++, pIdxCons++){
+ if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
+ j = pIdxCons->iTermOffset;
+ if( iTerm>=nConstraint
+ || j<0
+ || j>=pWC->nTerm
+ || pNew->aLTerm[iTerm]!=0
+ ){
+ rc = SQLITE_ERROR;
+ sqlite3ErrorMsg(pParse, "%s.xBestIndex() malfunction", pTab->zName);
+ goto whereLoopAddVtab_exit;
+ }
+ testcase( iTerm==nConstraint-1 );
+ testcase( j==0 );
+ testcase( j==pWC->nTerm-1 );
+ pTerm = &pWC->a[j];
+ pNew->prereq |= pTerm->prereqRight;
+ assert( iTerm<pNew->nLSlot );
+ pNew->aLTerm[iTerm] = pTerm;
+ if( iTerm>mxTerm ) mxTerm = iTerm;
+ testcase( iTerm==15 );
+ testcase( iTerm==16 );
+ if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
+ if( (pTerm->eOperator & WO_IN)!=0 ){
+ if( pUsage[i].omit==0 ){
+ /* Do not attempt to use an IN constraint if the virtual table
+ ** says that the equivalent EQ constraint cannot be safely omitted.
+ ** If we do attempt to use such a constraint, some rows might be
+ ** repeated in the output. */
+ break;
+ }
+ /* A virtual table that is constrained by an IN clause may not
+ ** consume the ORDER BY clause because (1) the order of IN terms
+ ** is not necessarily related to the order of output terms and
+ ** (2) Multiple outputs from a single IN value will not merge
+ ** together. */
+ pIdxInfo->orderByConsumed = 0;
}
}
}
- whereClauseClear(pWInfo->pWC);
- sqlite3DbFree(db, pWInfo);
+ if( i>=nConstraint ){
+ pNew->nLTerm = mxTerm+1;
+ assert( pNew->nLTerm<=pNew->nLSlot );
+ pNew->u.vtab.idxNum = pIdxInfo->idxNum;
+ pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
+ pIdxInfo->needToFreeIdxStr = 0;
+ pNew->u.vtab.idxStr = pIdxInfo->idxStr;
+ pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
+ && pIdxInfo->orderByConsumed);
+ pNew->rSetup = 0;
+ pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
+ pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
+ whereLoopInsert(pBuilder, pNew);
+ if( pNew->u.vtab.needFree ){
+ sqlite3_free(pNew->u.vtab.idxStr);
+ pNew->u.vtab.needFree = 0;
+ }
+ }
+ }
+
+whereLoopAddVtab_exit:
+ if( pIdxInfo->needToFreeIdxStr ) sqlite3_free(pIdxInfo->idxStr);
+ sqlite3DbFree(db, pIdxInfo);
+ return rc;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+/*
+** Add WhereLoop entries to handle OR terms. This works for either
+** btrees or virtual tables.
+*/
+static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
+ WhereInfo *pWInfo = pBuilder->pWInfo;
+ WhereClause *pWC;
+ WhereLoop *pNew;
+ WhereTerm *pTerm, *pWCEnd;
+ int rc = SQLITE_OK;
+ int iCur;
+ WhereClause tempWC;
+ WhereLoopBuilder sSubBuild;
+ WhereOrSet sSum, sCur, sPrev;
+ struct SrcList_item *pItem;
+
+ pWC = pBuilder->pWC;
+ if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
+ pWCEnd = pWC->a + pWC->nTerm;
+ pNew = pBuilder->pNew;
+ memset(&sSum, 0, sizeof(sSum));
+ pItem = pWInfo->pTabList->a + pNew->iTab;
+ if( !HasRowid(pItem->pTab) ) return SQLITE_OK;
+ iCur = pItem->iCursor;
+
+ for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
+ if( (pTerm->eOperator & WO_OR)!=0
+ && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
+ ){
+ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
+ WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
+ WhereTerm *pOrTerm;
+ int once = 1;
+ int i, j;
+
+ sSubBuild = *pBuilder;
+ sSubBuild.pOrderBy = 0;
+ sSubBuild.pOrSet = &sCur;
+
+ for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
+ if( (pOrTerm->eOperator & WO_AND)!=0 ){
+ sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
+ }else if( pOrTerm->leftCursor==iCur ){
+ tempWC.pWInfo = pWC->pWInfo;
+ tempWC.pOuter = pWC;
+ tempWC.op = TK_AND;
+ tempWC.nTerm = 1;
+ tempWC.a = pOrTerm;
+ sSubBuild.pWC = &tempWC;
+ }else{
+ continue;
+ }
+ sCur.n = 0;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pItem->pTab) ){
+ rc = whereLoopAddVirtual(&sSubBuild, mExtra);
+ }else
+#endif
+ {
+ rc = whereLoopAddBtree(&sSubBuild, mExtra);
+ }
+ assert( rc==SQLITE_OK || sCur.n==0 );
+ if( sCur.n==0 ){
+ sSum.n = 0;
+ break;
+ }else if( once ){
+ whereOrMove(&sSum, &sCur);
+ once = 0;
+ }else{
+ whereOrMove(&sPrev, &sSum);
+ sSum.n = 0;
+ for(i=0; i<sPrev.n; i++){
+ for(j=0; j<sCur.n; j++){
+ whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
+ sqlite3LogEstAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
+ sqlite3LogEstAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
+ }
+ }
+ }
+ }
+ pNew->nLTerm = 1;
+ pNew->aLTerm[0] = pTerm;
+ pNew->wsFlags = WHERE_MULTI_OR;
+ pNew->rSetup = 0;
+ pNew->iSortIdx = 0;
+ memset(&pNew->u, 0, sizeof(pNew->u));
+ for(i=0; rc==SQLITE_OK && i<sSum.n; i++){
+ /* TUNING: Multiple by 3.5 for the secondary table lookup */
+ pNew->rRun = sSum.a[i].rRun + 18;
+ pNew->nOut = sSum.a[i].nOut;
+ pNew->prereq = sSum.a[i].prereq;
+ rc = whereLoopInsert(pBuilder, pNew);
+ }
+ }
+ }
+ return rc;
+}
+
+/*
+** Add all WhereLoop objects for all tables
+*/
+static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
+ WhereInfo *pWInfo = pBuilder->pWInfo;
+ Bitmask mExtra = 0;
+ Bitmask mPrior = 0;
+ int iTab;
+ SrcList *pTabList = pWInfo->pTabList;
+ struct SrcList_item *pItem;
+ sqlite3 *db = pWInfo->pParse->db;
+ int nTabList = pWInfo->nLevel;
+ int rc = SQLITE_OK;
+ u8 priorJoinType = 0;
+ WhereLoop *pNew;
+
+ /* Loop over the tables in the join, from left to right */
+ pNew = pBuilder->pNew;
+ whereLoopInit(pNew);
+ for(iTab=0, pItem=pTabList->a; iTab<nTabList; iTab++, pItem++){
+ pNew->iTab = iTab;
+ pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor);
+ if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){
+ mExtra = mPrior;
+ }
+ priorJoinType = pItem->jointype;
+ if( IsVirtual(pItem->pTab) ){
+ rc = whereLoopAddVirtual(pBuilder, mExtra);
+ }else{
+ rc = whereLoopAddBtree(pBuilder, mExtra);
+ }
+ if( rc==SQLITE_OK ){
+ rc = whereLoopAddOr(pBuilder, mExtra);
+ }
+ mPrior |= pNew->maskSelf;
+ if( rc || db->mallocFailed ) break;
+ }
+ whereLoopClear(db, pNew);
+ return rc;
+}
+
+/*
+** Examine a WherePath (with the addition of the extra WhereLoop of the 5th
+** parameters) to see if it outputs rows in the requested ORDER BY
+** (or GROUP BY) without requiring a separate sort operation. Return:
+**
+** 0: ORDER BY is not satisfied. Sorting required
+** 1: ORDER BY is satisfied. Omit sorting
+** -1: Unknown at this time
+**
+** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
+** strict. With GROUP BY and DISTINCT the only requirement is that
+** equivalent rows appear immediately adjacent to one another. GROUP BY
+** and DISTINT do not require rows to appear in any particular order as long
+** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT
+** the pOrderBy terms can be matched in any order. With ORDER BY, the
+** pOrderBy terms must be matched in strict left-to-right order.
+*/
+static int wherePathSatisfiesOrderBy(
+ WhereInfo *pWInfo, /* The WHERE clause */
+ ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */
+ WherePath *pPath, /* The WherePath to check */
+ u16 wctrlFlags, /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */
+ u16 nLoop, /* Number of entries in pPath->aLoop[] */
+ WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */
+ Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */
+){
+ u8 revSet; /* True if rev is known */
+ u8 rev; /* Composite sort order */
+ u8 revIdx; /* Index sort order */
+ u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */
+ u8 distinctColumns; /* True if the loop has UNIQUE NOT NULL columns */
+ u8 isMatch; /* iColumn matches a term of the ORDER BY clause */
+ u16 nKeyCol; /* Number of key columns in pIndex */
+ u16 nColumn; /* Total number of ordered columns in the index */
+ u16 nOrderBy; /* Number terms in the ORDER BY clause */
+ int iLoop; /* Index of WhereLoop in pPath being processed */
+ int i, j; /* Loop counters */
+ int iCur; /* Cursor number for current WhereLoop */
+ int iColumn; /* A column number within table iCur */
+ WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
+ Expr *pOBExpr; /* An expression from the ORDER BY clause */
+ CollSeq *pColl; /* COLLATE function from an ORDER BY clause term */
+ Index *pIndex; /* The index associated with pLoop */
+ sqlite3 *db = pWInfo->pParse->db; /* Database connection */
+ Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */
+ Bitmask obDone; /* Mask of all ORDER BY terms */
+ Bitmask orderDistinctMask; /* Mask of all well-ordered loops */
+ Bitmask ready; /* Mask of inner loops */
+
+ /*
+ ** We say the WhereLoop is "one-row" if it generates no more than one
+ ** row of output. A WhereLoop is one-row if all of the following are true:
+ ** (a) All index columns match with WHERE_COLUMN_EQ.
+ ** (b) The index is unique
+ ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row.
+ ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags.
+ **
+ ** We say the WhereLoop is "order-distinct" if the set of columns from
+ ** that WhereLoop that are in the ORDER BY clause are different for every
+ ** row of the WhereLoop. Every one-row WhereLoop is automatically
+ ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause
+ ** is not order-distinct. To be order-distinct is not quite the same as being
+ ** UNIQUE since a UNIQUE column or index can have multiple rows that
+ ** are NULL and NULL values are equivalent for the purpose of order-distinct.
+ ** To be order-distinct, the columns must be UNIQUE and NOT NULL.
+ **
+ ** The rowid for a table is always UNIQUE and NOT NULL so whenever the
+ ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is
+ ** automatically order-distinct.
+ */
+
+ assert( pOrderBy!=0 );
+
+ /* Sortability of virtual tables is determined by the xBestIndex method
+ ** of the virtual table itself */
+ if( pLast->wsFlags & WHERE_VIRTUALTABLE ){
+ testcase( nLoop>0 ); /* True when outer loops are one-row and match
+ ** no ORDER BY terms */
+ return pLast->u.vtab.isOrdered;
+ }
+ if( nLoop && OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ) return 0;
+
+ nOrderBy = pOrderBy->nExpr;
+ testcase( nOrderBy==BMS-1 );
+ if( nOrderBy>BMS-1 ) return 0; /* Cannot optimize overly large ORDER BYs */
+ isOrderDistinct = 1;
+ obDone = MASKBIT(nOrderBy)-1;
+ orderDistinctMask = 0;
+ ready = 0;
+ for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
+ if( iLoop>0 ) ready |= pLoop->maskSelf;
+ pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
+ assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
+ iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
+
+ /* Mark off any ORDER BY term X that is a column in the table of
+ ** the current loop for which there is term in the WHERE
+ ** clause of the form X IS NULL or X=? that reference only outer
+ ** loops.
+ */
+ for(i=0; i<nOrderBy; i++){
+ if( MASKBIT(i) & obSat ) continue;
+ pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
+ if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->iTable!=iCur ) continue;
+ pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
+ ~ready, WO_EQ|WO_ISNULL, 0);
+ if( pTerm==0 ) continue;
+ if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){
+ const char *z1, *z2;
+ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ z1 = pColl->zName;
+ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ z2 = pColl->zName;
+ if( sqlite3StrICmp(z1, z2)!=0 ) continue;
+ }
+ obSat |= MASKBIT(i);
+ }
+
+ if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
+ if( pLoop->wsFlags & WHERE_IPK ){
+ pIndex = 0;
+ nKeyCol = 0;
+ nColumn = 1;
+ }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
+ return 0;
+ }else{
+ nKeyCol = pIndex->nKeyCol;
+ nColumn = pIndex->nColumn;
+ assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
+ assert( pIndex->aiColumn[nColumn-1]==(-1) || !HasRowid(pIndex->pTable));
+ isOrderDistinct = pIndex->onError!=OE_None;
+ }
+
+ /* Loop through all columns of the index and deal with the ones
+ ** that are not constrained by == or IN.
+ */
+ rev = revSet = 0;
+ distinctColumns = 0;
+ for(j=0; j<nColumn; j++){
+ u8 bOnce; /* True to run the ORDER BY search loop */
+
+ /* Skip over == and IS NULL terms */
+ if( j<pLoop->u.btree.nEq
+ && pLoop->u.btree.nSkip==0
+ && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0
+ ){
+ if( i & WO_ISNULL ){
+ testcase( isOrderDistinct );
+ isOrderDistinct = 0;
+ }
+ continue;
+ }
+
+ /* Get the column number in the table (iColumn) and sort order
+ ** (revIdx) for the j-th column of the index.
+ */
+ if( pIndex ){
+ iColumn = pIndex->aiColumn[j];
+ revIdx = pIndex->aSortOrder[j];
+ if( iColumn==pIndex->pTable->iPKey ) iColumn = -1;
+ }else{
+ iColumn = -1;
+ revIdx = 0;
+ }
+
+ /* An unconstrained column that might be NULL means that this
+ ** WhereLoop is not well-ordered
+ */
+ if( isOrderDistinct
+ && iColumn>=0
+ && j>=pLoop->u.btree.nEq
+ && pIndex->pTable->aCol[iColumn].notNull==0
+ ){
+ isOrderDistinct = 0;
+ }
+
+ /* Find the ORDER BY term that corresponds to the j-th column
+ ** of the index and and mark that ORDER BY term off
+ */
+ bOnce = 1;
+ isMatch = 0;
+ for(i=0; bOnce && i<nOrderBy; i++){
+ if( MASKBIT(i) & obSat ) continue;
+ pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
+ testcase( wctrlFlags & WHERE_GROUPBY );
+ testcase( wctrlFlags & WHERE_DISTINCTBY );
+ if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
+ if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->iTable!=iCur ) continue;
+ if( pOBExpr->iColumn!=iColumn ) continue;
+ if( iColumn>=0 ){
+ pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
+ }
+ isMatch = 1;
+ break;
+ }
+ if( isMatch ){
+ if( iColumn<0 ){
+ testcase( distinctColumns==0 );
+ distinctColumns = 1;
+ }
+ obSat |= MASKBIT(i);
+ if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
+ /* Make sure the sort order is compatible in an ORDER BY clause.
+ ** Sort order is irrelevant for a GROUP BY clause. */
+ if( revSet ){
+ if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) return 0;
+ }else{
+ rev = revIdx ^ pOrderBy->a[i].sortOrder;
+ if( rev ) *pRevMask |= MASKBIT(iLoop);
+ revSet = 1;
+ }
+ }
+ }else{
+ /* No match found */
+ if( j==0 || j<nKeyCol ){
+ testcase( isOrderDistinct!=0 );
+ isOrderDistinct = 0;
+ }
+ break;
+ }
+ } /* end Loop over all index columns */
+ if( distinctColumns ){
+ testcase( isOrderDistinct==0 );
+ isOrderDistinct = 1;
+ }
+ } /* end-if not one-row */
+
+ /* Mark off any other ORDER BY terms that reference pLoop */
+ if( isOrderDistinct ){
+ orderDistinctMask |= pLoop->maskSelf;
+ for(i=0; i<nOrderBy; i++){
+ Expr *p;
+ if( MASKBIT(i) & obSat ) continue;
+ p = pOrderBy->a[i].pExpr;
+ if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){
+ obSat |= MASKBIT(i);
+ }
+ }
+ }
+ } /* End the loop over all WhereLoops from outer-most down to inner-most */
+ if( obSat==obDone ) return 1;
+ if( !isOrderDistinct ) return 0;
+ return -1;
+}
+
+#ifdef WHERETRACE_ENABLED
+/* For debugging use only: */
+static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
+ static char zName[65];
+ int i;
+ for(i=0; i<nLoop; i++){ zName[i] = pPath->aLoop[i]->cId; }
+ if( pLast ) zName[i++] = pLast->cId;
+ zName[i] = 0;
+ return zName;
+}
+#endif
+
+
+/*
+** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
+** attempts to find the lowest cost path that visits each WhereLoop
+** once. This path is then loaded into the pWInfo->a[].pWLoop fields.
+**
+** Assume that the total number of output rows that will need to be sorted
+** will be nRowEst (in the 10*log2 representation). Or, ignore sorting
+** costs if nRowEst==0.
+**
+** Return SQLITE_OK on success or SQLITE_NOMEM of a memory allocation
+** error occurs.
+*/
+static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
+ int mxChoice; /* Maximum number of simultaneous paths tracked */
+ int nLoop; /* Number of terms in the join */
+ Parse *pParse; /* Parsing context */
+ sqlite3 *db; /* The database connection */
+ int iLoop; /* Loop counter over the terms of the join */
+ int ii, jj; /* Loop counters */
+ int mxI = 0; /* Index of next entry to replace */
+ LogEst rCost; /* Cost of a path */
+ LogEst nOut; /* Number of outputs */
+ LogEst mxCost = 0; /* Maximum cost of a set of paths */
+ LogEst mxOut = 0; /* Maximum nOut value on the set of paths */
+ LogEst rSortCost; /* Cost to do a sort */
+ int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
+ WherePath *aFrom; /* All nFrom paths at the previous level */
+ WherePath *aTo; /* The nTo best paths at the current level */
+ WherePath *pFrom; /* An element of aFrom[] that we are working on */
+ WherePath *pTo; /* An element of aTo[] that we are working on */
+ WhereLoop *pWLoop; /* One of the WhereLoop objects */
+ WhereLoop **pX; /* Used to divy up the pSpace memory */
+ char *pSpace; /* Temporary memory used by this routine */
+
+ pParse = pWInfo->pParse;
+ db = pParse->db;
+ nLoop = pWInfo->nLevel;
+ /* TUNING: For simple queries, only the best path is tracked.
+ ** For 2-way joins, the 5 best paths are followed.
+ ** For joins of 3 or more tables, track the 10 best paths */
+ mxChoice = (nLoop==1) ? 1 : (nLoop==2 ? 5 : 10);
+ assert( nLoop<=pWInfo->pTabList->nSrc );
+ WHERETRACE(0x002, ("---- begin solver\n"));
+
+ /* Allocate and initialize space for aTo and aFrom */
+ ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
+ pSpace = sqlite3DbMallocRaw(db, ii);
+ if( pSpace==0 ) return SQLITE_NOMEM;
+ aTo = (WherePath*)pSpace;
+ aFrom = aTo+mxChoice;
+ memset(aFrom, 0, sizeof(aFrom[0]));
+ pX = (WhereLoop**)(aFrom+mxChoice);
+ for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
+ pFrom->aLoop = pX;
+ }
+
+ /* Seed the search with a single WherePath containing zero WhereLoops.
+ **
+ ** TUNING: Do not let the number of iterations go above 25. If the cost
+ ** of computing an automatic index is not paid back within the first 25
+ ** rows, then do not use the automatic index. */
+ aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
+ nFrom = 1;
+
+ /* Precompute the cost of sorting the final result set, if the caller
+ ** to sqlite3WhereBegin() was concerned about sorting */
+ rSortCost = 0;
+ if( pWInfo->pOrderBy==0 || nRowEst==0 ){
+ aFrom[0].isOrderedValid = 1;
+ }else{
+ /* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
+ ** number of output rows. The 48 is the expected size of a row to sort.
+ ** FIXME: compute a better estimate of the 48 multiplier based on the
+ ** result set expressions. */
+ rSortCost = nRowEst + estLog(nRowEst);
+ WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
+ }
+
+ /* Compute successively longer WherePaths using the previous generation
+ ** of WherePaths as the basis for the next. Keep track of the mxChoice
+ ** best paths at each generation */
+ for(iLoop=0; iLoop<nLoop; iLoop++){
+ nTo = 0;
+ for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+ Bitmask maskNew;
+ Bitmask revMask = 0;
+ u8 isOrderedValid = pFrom->isOrderedValid;
+ u8 isOrdered = pFrom->isOrdered;
+ if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
+ if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
+ /* At this point, pWLoop is a candidate to be the next loop.
+ ** Compute its cost */
+ rCost = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
+ rCost = sqlite3LogEstAdd(rCost, pFrom->rCost);
+ nOut = pFrom->nRow + pWLoop->nOut;
+ maskNew = pFrom->maskLoop | pWLoop->maskSelf;
+ if( !isOrderedValid ){
+ switch( wherePathSatisfiesOrderBy(pWInfo,
+ pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
+ iLoop, pWLoop, &revMask) ){
+ case 1: /* Yes. pFrom+pWLoop does satisfy the ORDER BY clause */
+ isOrdered = 1;
+ isOrderedValid = 1;
+ break;
+ case 0: /* No. pFrom+pWLoop will require a separate sort */
+ isOrdered = 0;
+ isOrderedValid = 1;
+ rCost = sqlite3LogEstAdd(rCost, rSortCost);
+ break;
+ default: /* Cannot tell yet. Try again on the next iteration */
+ break;
+ }
+ }else{
+ revMask = pFrom->revLoop;
+ }
+ /* Check to see if pWLoop should be added to the mxChoice best so far */
+ for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
+ if( pTo->maskLoop==maskNew
+ && pTo->isOrderedValid==isOrderedValid
+ && ((pTo->rCost<=rCost && pTo->nRow<=nOut) ||
+ (pTo->rCost>=rCost && pTo->nRow>=nOut))
+ ){
+ testcase( jj==nTo-1 );
+ break;
+ }
+ }
+ if( jj>=nTo ){
+ if( nTo>=mxChoice && rCost>=mxCost ){
+#ifdef WHERETRACE_ENABLED /* 0x4 */
+ if( sqlite3WhereTrace&0x4 ){
+ sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+ isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
+ }
+#endif
+ continue;
+ }
+ /* Add a new Path to the aTo[] set */
+ if( nTo<mxChoice ){
+ /* Increase the size of the aTo set by one */
+ jj = nTo++;
+ }else{
+ /* New path replaces the prior worst to keep count below mxChoice */
+ jj = mxI;
+ }
+ pTo = &aTo[jj];
+#ifdef WHERETRACE_ENABLED /* 0x4 */
+ if( sqlite3WhereTrace&0x4 ){
+ sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n",
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+ isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
+ }
+#endif
+ }else{
+ if( pTo->rCost<=rCost && pTo->nRow<=nOut ){
+#ifdef WHERETRACE_ENABLED /* 0x4 */
+ if( sqlite3WhereTrace&0x4 ){
+ sqlite3DebugPrintf(
+ "Skip %s cost=%-3d,%3d order=%c",
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+ isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
+ sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
+ wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+ pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
+ }
+#endif
+ testcase( pTo->rCost==rCost );
+ continue;
+ }
+ testcase( pTo->rCost==rCost+1 );
+ /* A new and better score for a previously created equivalent path */
+#ifdef WHERETRACE_ENABLED /* 0x4 */
+ if( sqlite3WhereTrace&0x4 ){
+ sqlite3DebugPrintf(
+ "Update %s cost=%-3d,%3d order=%c",
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
+ isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
+ sqlite3DebugPrintf(" was %s cost=%-3d,%3d order=%c\n",
+ wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+ pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
+ }
+#endif
+ }
+ /* pWLoop is a winner. Add it to the set of best so far */
+ pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
+ pTo->revLoop = revMask;
+ pTo->nRow = nOut;
+ pTo->rCost = rCost;
+ pTo->isOrderedValid = isOrderedValid;
+ pTo->isOrdered = isOrdered;
+ memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
+ pTo->aLoop[iLoop] = pWLoop;
+ if( nTo>=mxChoice ){
+ mxI = 0;
+ mxCost = aTo[0].rCost;
+ mxOut = aTo[0].nRow;
+ for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
+ if( pTo->rCost>mxCost || (pTo->rCost==mxCost && pTo->nRow>mxOut) ){
+ mxCost = pTo->rCost;
+ mxOut = pTo->nRow;
+ mxI = jj;
+ }
+ }
+ }
+ }
+ }
+
+#ifdef WHERETRACE_ENABLED /* >=2 */
+ if( sqlite3WhereTrace>=2 ){
+ sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
+ for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
+ sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
+ wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
+ pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
+ if( pTo->isOrderedValid && pTo->isOrdered ){
+ sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
+ }else{
+ sqlite3DebugPrintf("\n");
+ }
+ }
+ }
+#endif
+
+ /* Swap the roles of aFrom and aTo for the next generation */
+ pFrom = aTo;
+ aTo = aFrom;
+ aFrom = pFrom;
+ nFrom = nTo;
+ }
+
+ if( nFrom==0 ){
+ sqlite3ErrorMsg(pParse, "no query solution");
+ sqlite3DbFree(db, pSpace);
+ return SQLITE_ERROR;
}
+
+ /* Find the lowest cost path. pFrom will be left pointing to that path */
+ pFrom = aFrom;
+ for(ii=1; ii<nFrom; ii++){
+ if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
+ }
+ assert( pWInfo->nLevel==nLoop );
+ /* Load the lowest cost path into pWInfo */
+ for(iLoop=0; iLoop<nLoop; iLoop++){
+ WhereLevel *pLevel = pWInfo->a + iLoop;
+ pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop];
+ pLevel->iFrom = pWLoop->iTab;
+ pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
+ }
+ if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0
+ && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
+ && pWInfo->eDistinct==WHERE_DISTINCT_NOOP
+ && nRowEst
+ ){
+ Bitmask notUsed;
+ int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
+ WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);
+ if( rc==1 ) pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+ }
+ if( pFrom->isOrdered ){
+ if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
+ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+ }else{
+ pWInfo->bOBSat = 1;
+ pWInfo->revMask = pFrom->revLoop;
+ }
+ }
+ pWInfo->nRowOut = pFrom->nRow;
+
+ /* Free temporary memory and return success */
+ sqlite3DbFree(db, pSpace);
+ return SQLITE_OK;
}
+/*
+** Most queries use only a single table (they are not joins) and have
+** simple == constraints against indexed fields. This routine attempts
+** to plan those simple cases using much less ceremony than the
+** general-purpose query planner, and thereby yield faster sqlite3_prepare()
+** times for the common case.
+**
+** Return non-zero on success, if this query can be handled by this
+** no-frills query planner. Return zero if this query needs the
+** general-purpose query planner.
+*/
+static int whereShortCut(WhereLoopBuilder *pBuilder){
+ WhereInfo *pWInfo;
+ struct SrcList_item *pItem;
+ WhereClause *pWC;
+ WhereTerm *pTerm;
+ WhereLoop *pLoop;
+ int iCur;
+ int j;
+ Table *pTab;
+ Index *pIdx;
+
+ pWInfo = pBuilder->pWInfo;
+ if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0;
+ assert( pWInfo->pTabList->nSrc>=1 );
+ pItem = pWInfo->pTabList->a;
+ pTab = pItem->pTab;
+ if( IsVirtual(pTab) ) return 0;
+ if( pItem->zIndex ) return 0;
+ iCur = pItem->iCursor;
+ pWC = &pWInfo->sWC;
+ pLoop = pBuilder->pNew;
+ pLoop->wsFlags = 0;
+ pLoop->u.btree.nSkip = 0;
+ pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0);
+ if( pTerm ){
+ pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
+ pLoop->aLTerm[0] = pTerm;
+ pLoop->nLTerm = 1;
+ pLoop->u.btree.nEq = 1;
+ /* TUNING: Cost of a rowid lookup is 10 */
+ pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */
+ }else{
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ assert( pLoop->aLTermSpace==pLoop->aLTerm );
+ assert( ArraySize(pLoop->aLTermSpace)==4 );
+ if( pIdx->onError==OE_None
+ || pIdx->pPartIdxWhere!=0
+ || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace)
+ ) continue;
+ for(j=0; j<pIdx->nKeyCol; j++){
+ pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
+ if( pTerm==0 ) break;
+ pLoop->aLTerm[j] = pTerm;
+ }
+ if( j!=pIdx->nKeyCol ) continue;
+ pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
+ if( pIdx->isCovering || (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){
+ pLoop->wsFlags |= WHERE_IDX_ONLY;
+ }
+ pLoop->nLTerm = j;
+ pLoop->u.btree.nEq = j;
+ pLoop->u.btree.pIndex = pIdx;
+ /* TUNING: Cost of a unique index lookup is 15 */
+ pLoop->rRun = 39; /* 39==sqlite3LogEst(15) */
+ break;
+ }
+ }
+ if( pLoop->wsFlags ){
+ pLoop->nOut = (LogEst)1;
+ pWInfo->a[0].pWLoop = pLoop;
+ pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
+ pWInfo->a[0].iTabCur = iCur;
+ pWInfo->nRowOut = 1;
+ if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1;
+ if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ }
+#ifdef SQLITE_DEBUG
+ pLoop->cId = '0';
+#endif
+ return 1;
+ }
+ return 0;
+}
/*
** Generate the beginning of the loop used for WHERE clause processing.
@@ -109413,25 +113741,25 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
**
** ORDER BY CLAUSE PROCESSING
**
-** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
+** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause
+** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement
** if there is one. If there is no ORDER BY clause or if this routine
** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
**
-** If an index can be used so that the natural output order of the table
-** scan is correct for the ORDER BY clause, then that index is used and
-** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr. This
-** is an optimization that prevents an unnecessary sort of the result set
-** if an index appropriate for the ORDER BY clause already exists.
-**
-** If the where clause loops cannot be arranged to provide the correct
-** output order, then WhereInfo.nOBSat is 0.
+** The iIdxCur parameter is the cursor number of an index. If
+** WHERE_ONETABLE_ONLY is set, iIdxCur is the cursor number of an index
+** to use for OR clause processing. The WHERE clause should use this
+** specific cursor. If WHERE_ONEPASS_DESIRED is set, then iIdxCur is
+** the first cursor in an array of cursors for all indices. iIdxCur should
+** be used to compute the appropriate cursor depending on which index is
+** used.
*/
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
Parse *pParse, /* The parser context */
- SrcList *pTabList, /* A list of all tables to be scanned */
+ SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY clause, or NULL */
- ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
+ ExprList *pResultSet, /* Result set of the query */
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */
){
@@ -109440,18 +113768,25 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
Bitmask notReady; /* Cursors that are not yet positioned */
- WhereBestIdx sWBI; /* Best index search context */
+ WhereLoopBuilder sWLB; /* The WhereLoop builder */
WhereMaskSet *pMaskSet; /* The expression mask set */
WhereLevel *pLevel; /* A single level in pWInfo->a[] */
- int iFrom; /* First unused FROM clause element */
- int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */
+ WhereLoop *pLoop; /* Pointer to a single WhereLoop object */
int ii; /* Loop counter */
sqlite3 *db; /* Database connection */
+ int rc; /* Return code */
/* Variable initialization */
- memset(&sWBI, 0, sizeof(sWBI));
- sWBI.pParse = pParse;
+ db = pParse->db;
+ memset(&sWLB, 0, sizeof(sWLB));
+ sWLB.pOrderBy = pOrderBy;
+
+ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
+ ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
+ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
+ wctrlFlags &= ~WHERE_WANT_DISTINCT;
+ }
/* The number of tables in the FROM clause is limited by the number of
** bits in a Bitmask
@@ -109476,39 +113811,39 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** field (type Bitmask) it must be aligned on an 8-byte boundary on
** some architectures. Hence the ROUND8() below.
*/
- db = pParse->db;
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
- pWInfo = sqlite3DbMallocZero(db,
- nByteWInfo +
- sizeof(WhereClause) +
- sizeof(WhereMaskSet)
- );
+ pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
if( db->mallocFailed ){
sqlite3DbFree(db, pWInfo);
pWInfo = 0;
goto whereBeginError;
}
+ pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
pWInfo->nLevel = nTabList;
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
+ pWInfo->pOrderBy = pOrderBy;
+ pWInfo->pResultSet = pResultSet;
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
- pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
- pMaskSet = (WhereMaskSet*)&sWBI.pWC[1];
- sWBI.aLevel = pWInfo->a;
-
- /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
- ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
- if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
+ pMaskSet = &pWInfo->sMaskSet;
+ sWLB.pWInfo = pWInfo;
+ sWLB.pWC = &pWInfo->sWC;
+ sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
+ assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
+ whereLoopInit(sWLB.pNew);
+#ifdef SQLITE_DEBUG
+ sWLB.pNew->cId = '*';
+#endif
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator.
*/
initMaskSet(pMaskSet);
- whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags);
- sqlite3ExprCodeConstants(pParse, pWhere);
- whereSplit(sWBI.pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
+ whereClauseInit(&pWInfo->sWC, pWInfo);
+ whereSplit(&pWInfo->sWC, pWhere, TK_AND);
+ sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
@@ -109518,6 +113853,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWhere = 0;
}
+ /* Special case: No FROM clause
+ */
+ if( nTabList==0 ){
+ if( pOrderBy ) pWInfo->bOBSat = 1;
+ if( wctrlFlags & WHERE_WANT_DISTINCT ){
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ }
+ }
+
/* Assign a bit from the bitmask to every term in the FROM clause.
**
** When assigning bitmask values to FROM clause cursors, it must be
@@ -109553,306 +113897,167 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** want to analyze these virtual terms, so start analyzing at the end
** and work forward so that the added virtual terms are never processed.
*/
- exprAnalyzeAll(pTabList, sWBI.pWC);
+ exprAnalyzeAll(pTabList, &pWInfo->sWC);
if( db->mallocFailed ){
goto whereBeginError;
}
- /* Check if the DISTINCT qualifier, if there is one, is redundant.
- ** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
- ** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
+ /* If the ORDER BY (or GROUP BY) clause contains references to general
+ ** expressions, then we won't be able to satisfy it using indices, so
+ ** go ahead and disable it now.
*/
- if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){
- pDistinct = 0;
- pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){
+ for(ii=0; ii<pOrderBy->nExpr; ii++){
+ Expr *pExpr = sqlite3ExprSkipCollate(pOrderBy->a[ii].pExpr);
+ if( pExpr->op!=TK_COLUMN ){
+ pWInfo->pOrderBy = pOrderBy = 0;
+ break;
+ }else if( pExpr->iColumn<0 ){
+ break;
+ }
+ }
}
- /* Chose the best index to use for each table in the FROM clause.
- **
- ** This loop fills in the following fields:
- **
- ** pWInfo->a[].pIdx The index to use for this level of the loop.
- ** pWInfo->a[].wsFlags WHERE_xxx flags associated with pIdx
- ** pWInfo->a[].nEq The number of == and IN constraints
- ** pWInfo->a[].iFrom Which term of the FROM clause is being coded
- ** pWInfo->a[].iTabCur The VDBE cursor for the database table
- ** pWInfo->a[].iIdxCur The VDBE cursor for the index
- ** pWInfo->a[].pTerm When wsFlags==WO_OR, the OR-clause term
- **
- ** This loop also figures out the nesting order of tables in the FROM
- ** clause.
- */
- sWBI.notValid = ~(Bitmask)0;
- sWBI.pOrderBy = pOrderBy;
- sWBI.n = nTabList;
- sWBI.pDistinct = pDistinct;
- andFlags = ~0;
- WHERETRACE(("*** Optimizer Start ***\n"));
- for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){
- WhereCost bestPlan; /* Most efficient plan seen so far */
- Index *pIdx; /* Index for FROM table at pTabItem */
- int j; /* For looping over FROM tables */
- int bestJ = -1; /* The value of j */
- Bitmask m; /* Bitmask value for j or bestJ */
- int isOptimal; /* Iterator for optimal/non-optimal search */
- int ckOptimal; /* Do the optimal scan check */
- int nUnconstrained; /* Number tables without INDEXED BY */
- Bitmask notIndexed; /* Mask of tables that cannot use an index */
-
- memset(&bestPlan, 0, sizeof(bestPlan));
- bestPlan.rCost = SQLITE_BIG_DBL;
- WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));
-
- /* Loop through the remaining entries in the FROM clause to find the
- ** next nested loop. The loop tests all FROM clause entries
- ** either once or twice.
- **
- ** The first test is always performed if there are two or more entries
- ** remaining and never performed if there is only one FROM clause entry
- ** to choose from. The first test looks for an "optimal" scan. In
- ** this context an optimal scan is one that uses the same strategy
- ** for the given FROM clause entry as would be selected if the entry
- ** were used as the innermost nested loop. In other words, a table
- ** is chosen such that the cost of running that table cannot be reduced
- ** by waiting for other tables to run first. This "optimal" test works
- ** by first assuming that the FROM clause is on the inner loop and finding
- ** its query plan, then checking to see if that query plan uses any
- ** other FROM clause terms that are sWBI.notValid. If no notValid terms
- ** are used then the "optimal" query plan works.
- **
- ** Note that the WhereCost.nRow parameter for an optimal scan might
- ** not be as small as it would be if the table really were the innermost
- ** join. The nRow value can be reduced by WHERE clause constraints
- ** that do not use indices. But this nRow reduction only happens if the
- ** table really is the innermost join.
- **
- ** The second loop iteration is only performed if no optimal scan
- ** strategies were found by the first iteration. This second iteration
- ** is used to search for the lowest cost scan overall.
- **
- ** Without the optimal scan step (the first iteration) a suboptimal
- ** plan might be chosen for queries like this:
- **
- ** CREATE TABLE t1(a, b);
- ** CREATE TABLE t2(c, d);
- ** SELECT * FROM t2, t1 WHERE t2.rowid = t1.a;
- **
- ** The best strategy is to iterate through table t1 first. However it
- ** is not possible to determine this with a simple greedy algorithm.
- ** Since the cost of a linear scan through table t2 is the same
- ** as the cost of a linear scan through table t1, a simple greedy
- ** algorithm may choose to use t2 for the outer loop, which is a much
- ** costlier approach.
- */
- nUnconstrained = 0;
- notIndexed = 0;
-
- /* The optimal scan check only occurs if there are two or more tables
- ** available to be reordered */
- if( iFrom==nTabList-1 ){
- ckOptimal = 0; /* Common case of just one table in the FROM clause */
- }else{
- ckOptimal = -1;
- for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
- m = getMask(pMaskSet, sWBI.pSrc->iCursor);
- if( (m & sWBI.notValid)==0 ){
- if( j==iFrom ) iFrom++;
- continue;
- }
- if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
- if( ++ckOptimal ) break;
- if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
- }
+ if( wctrlFlags & WHERE_WANT_DISTINCT ){
+ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
+ /* The DISTINCT marking is pointless. Ignore it. */
+ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
+ }else if( pOrderBy==0 ){
+ /* Try to ORDER BY the result set to make distinct processing easier */
+ pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
+ pWInfo->pOrderBy = pResultSet;
}
- assert( ckOptimal==0 || ckOptimal==1 );
+ }
- for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
- for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
- if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
- /* This break and one like it in the ckOptimal computation loop
- ** above prevent table reordering across LEFT and CROSS JOINs.
- ** The LEFT JOIN case is necessary for correctness. The prohibition
- ** against reordering across a CROSS JOIN is an SQLite feature that
- ** allows the developer to control table reordering */
- break;
- }
- m = getMask(pMaskSet, sWBI.pSrc->iCursor);
- if( (m & sWBI.notValid)==0 ){
- assert( j>iFrom );
- continue;
- }
- sWBI.notReady = (isOptimal ? m : sWBI.notValid);
- if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
-
- WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
- j, sWBI.pSrc->pTab->zName, isOptimal));
- assert( sWBI.pSrc->pTab );
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(sWBI.pSrc->pTab) ){
- sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
- bestVirtualIndex(&sWBI);
- }else
-#endif
- {
- bestBtreeIndex(&sWBI);
- }
- assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 );
-
- /* If an INDEXED BY clause is present, then the plan must use that
- ** index if it uses any index at all */
- assert( sWBI.pSrc->pIndex==0
- || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
- || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
-
- if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
- notIndexed |= m;
- }
- if( isOptimal ){
- pWInfo->a[j].rOptCost = sWBI.cost.rCost;
- }else if( ckOptimal ){
- /* If two or more tables have nearly the same outer loop cost, but
- ** very different inner loop (optimal) cost, we want to choose
- ** for the outer loop that table which benefits the least from
- ** being in the inner loop. The following code scales the
- ** outer loop cost estimate to accomplish that. */
- WHERETRACE((" scaling cost from %.1f to %.1f\n",
- sWBI.cost.rCost,
- sWBI.cost.rCost/pWInfo->a[j].rOptCost));
- sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
- }
-
- /* Conditions under which this table becomes the best so far:
- **
- ** (1) The table must not depend on other tables that have not
- ** yet run. (In other words, it must not depend on tables
- ** in inner loops.)
- **
- ** (2) (This rule was removed on 2012-11-09. The scaling of the
- ** cost using the optimal scan cost made this rule obsolete.)
- **
- ** (3) All tables have an INDEXED BY clause or this table lacks an
- ** INDEXED BY clause or this table uses the specific
- ** index specified by its INDEXED BY clause. This rule ensures
- ** that a best-so-far is always selected even if an impossible
- ** combination of INDEXED BY clauses are given. The error
- ** will be detected and relayed back to the application later.
- ** The NEVER() comes about because rule (2) above prevents
- ** An indexable full-table-scan from reaching rule (3).
- **
- ** (4) The plan cost must be lower than prior plans, where "cost"
- ** is defined by the compareCost() function above.
- */
- if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */
- && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */
- || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
- && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
- ){
- WHERETRACE((" === table %d (%s) is best so far\n"
- " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
- j, sWBI.pSrc->pTab->zName,
- sWBI.cost.rCost, sWBI.cost.plan.nRow,
- sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
- bestPlan = sWBI.cost;
- bestJ = j;
- }
-
- /* In a join like "w JOIN x LEFT JOIN y JOIN z" make sure that
- ** table y (and not table z) is always the next inner loop inside
- ** of table x. */
- if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
- }
- }
- assert( bestJ>=0 );
- assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
- assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
- testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
- testcase( bestJ>iFrom && bestJ<nTabList-1
- && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
- WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
- " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
- bestJ, pTabList->a[bestJ].pTab->zName,
- pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
- bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
- if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
- assert( pWInfo->eDistinct==0 );
- pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
+ /* Construct the WhereLoop objects */
+ WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
+ /* Display all terms of the WHERE clause */
+#if defined(WHERETRACE_ENABLED) && defined(SQLITE_ENABLE_TREE_EXPLAIN)
+ if( sqlite3WhereTrace & 0x100 ){
+ int i;
+ Vdbe *v = pParse->pVdbe;
+ sqlite3ExplainBegin(v);
+ for(i=0; i<sWLB.pWC->nTerm; i++){
+ sqlite3ExplainPrintf(v, "#%-2d ", i);
+ sqlite3ExplainPush(v);
+ whereExplainTerm(v, &sWLB.pWC->a[i]);
+ sqlite3ExplainPop(v);
+ sqlite3ExplainNL(v);
}
- andFlags &= bestPlan.plan.wsFlags;
- pLevel->plan = bestPlan.plan;
- pLevel->iTabCur = pTabList->a[bestJ].iCursor;
- testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
- testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
- if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
- if( (wctrlFlags & WHERE_ONETABLE_ONLY)
- && (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0
- ){
- pLevel->iIdxCur = iIdxCur;
- }else{
- pLevel->iIdxCur = pParse->nTab++;
+ sqlite3ExplainFinish(v);
+ sqlite3DebugPrintf("%s", sqlite3VdbeExplanation(v));
+ }
+#endif
+ if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
+ rc = whereLoopAddAll(&sWLB);
+ if( rc ) goto whereBeginError;
+
+ /* Display all of the WhereLoop objects if wheretrace is enabled */
+#ifdef WHERETRACE_ENABLED /* !=0 */
+ if( sqlite3WhereTrace ){
+ WhereLoop *p;
+ int i;
+ static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
+ "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
+ for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
+ p->cId = zLabel[i%sizeof(zLabel)];
+ whereLoopPrint(p, sWLB.pWC);
}
- }else{
- pLevel->iIdxCur = -1;
}
- sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
- pLevel->iFrom = (u8)bestJ;
- if( bestPlan.plan.nRow>=(double)1 ){
- pParse->nQueryLoop *= bestPlan.plan.nRow;
- }
-
- /* Check that if the table scanned by this loop iteration had an
- ** INDEXED BY clause attached to it, that the named index is being
- ** used for the scan. If not, then query compilation has failed.
- ** Return an error.
- */
- pIdx = pTabList->a[bestJ].pIndex;
- if( pIdx ){
- if( (bestPlan.plan.wsFlags & WHERE_INDEXED)==0 ){
- sqlite3ErrorMsg(pParse, "cannot use index: %s", pIdx->zName);
- goto whereBeginError;
- }else{
- /* If an INDEXED BY clause is used, the bestIndex() function is
- ** guaranteed to find the index specified in the INDEXED BY clause
- ** if it find an index at all. */
- assert( bestPlan.plan.u.pIdx==pIdx );
- }
+#endif
+
+ wherePathSolver(pWInfo, 0);
+ if( db->mallocFailed ) goto whereBeginError;
+ if( pWInfo->pOrderBy ){
+ wherePathSolver(pWInfo, pWInfo->nRowOut+1);
+ if( db->mallocFailed ) goto whereBeginError;
}
}
- WHERETRACE(("*** Optimizer Finished ***\n"));
- if( pParse->nErr || db->mallocFailed ){
+ if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
+ pWInfo->revMask = (Bitmask)(-1);
+ }
+ if( pParse->nErr || NEVER(db->mallocFailed) ){
goto whereBeginError;
}
- if( nTabList ){
- pLevel--;
- pWInfo->nOBSat = pLevel->plan.nOBSat;
- }else{
- pWInfo->nOBSat = 0;
+#ifdef WHERETRACE_ENABLED /* !=0 */
+ if( sqlite3WhereTrace ){
+ int ii;
+ sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
+ if( pWInfo->bOBSat ){
+ sqlite3DebugPrintf(" ORDERBY=0x%llx", pWInfo->revMask);
+ }
+ switch( pWInfo->eDistinct ){
+ case WHERE_DISTINCT_UNIQUE: {
+ sqlite3DebugPrintf(" DISTINCT=unique");
+ break;
+ }
+ case WHERE_DISTINCT_ORDERED: {
+ sqlite3DebugPrintf(" DISTINCT=ordered");
+ break;
+ }
+ case WHERE_DISTINCT_UNORDERED: {
+ sqlite3DebugPrintf(" DISTINCT=unordered");
+ break;
+ }
+ }
+ sqlite3DebugPrintf("\n");
+ for(ii=0; ii<pWInfo->nLevel; ii++){
+ whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
+ }
}
-
- /* If the total query only selects a single row, then the ORDER BY
- ** clause is irrelevant.
- */
- if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){
- assert( nTabList==0 || (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 );
- pWInfo->nOBSat = pOrderBy->nExpr;
+#endif
+ /* Attempt to omit tables from the join that do not effect the result */
+ if( pWInfo->nLevel>=2
+ && pResultSet!=0
+ && OptimizationEnabled(db, SQLITE_OmitNoopJoin)
+ ){
+ Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet);
+ if( sWLB.pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, sWLB.pOrderBy);
+ while( pWInfo->nLevel>=2 ){
+ WhereTerm *pTerm, *pEnd;
+ pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop;
+ if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break;
+ if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
+ && (pLoop->wsFlags & WHERE_ONEROW)==0
+ ){
+ break;
+ }
+ if( (tabUsed & pLoop->maskSelf)!=0 ) break;
+ pEnd = sWLB.pWC->a + sWLB.pWC->nTerm;
+ for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
+ if( (pTerm->prereqAll & pLoop->maskSelf)!=0
+ && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
+ ){
+ break;
+ }
+ }
+ if( pTerm<pEnd ) break;
+ WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
+ pWInfo->nLevel--;
+ nTabList--;
+ }
}
+ WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
+ pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
/* If the caller is an UPDATE or DELETE statement that is requesting
** to use a one-pass algorithm, determine if this is appropriate.
- ** The one-pass algorithm only works if the WHERE clause constraints
+ ** The one-pass algorithm only works if the WHERE clause constrains
** the statement to update a single row.
*/
assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
- if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
+ if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0
+ && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
pWInfo->okOnePass = 1;
- pWInfo->a[0].plan.wsFlags &= ~WHERE_IDX_ONLY;
+ if( HasRowid(pTabList->a[0].pTab) ){
+ pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
+ }
}
/* Open all tables in the pTabList and any indices selected for
** searching those tables.
*/
- sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
notReady = ~(Bitmask)0;
- pWInfo->nRowOut = (double)1;
for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
Table *pTab; /* Table to open */
int iDb; /* Index of database containing table/index */
@@ -109860,13 +114065,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
- pWInfo->nRowOut *= pLevel->plan.nRow;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pLoop = pLevel->pWLoop;
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
/* Do nothing */
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
int iCur = pTabItem->iCursor;
sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
@@ -109874,13 +114079,18 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
/* noop */
}else
#endif
- if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
+ if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
&& (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
- int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
+ int op = OP_OpenRead;
+ if( pWInfo->okOnePass ){
+ op = OP_OpenWrite;
+ pWInfo->aiCurOnePass[0] = pTabItem->iCursor;
+ };
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
- testcase( pTab->nCol==BMS-1 );
- testcase( pTab->nCol==BMS );
- if( !pWInfo->okOnePass && pTab->nCol<BMS ){
+ assert( pTabItem->iCursor==pLevel->iTabCur );
+ testcase( !pWInfo->okOnePass && pTab->nCol==BMS-1 );
+ testcase( !pWInfo->okOnePass && pTab->nCol==BMS );
+ if( !pWInfo->okOnePass && pTab->nCol<BMS && HasRowid(pTab) ){
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
@@ -109891,23 +114101,36 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}else{
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
}
-#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
- if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
- constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel);
- }else
-#endif
- if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
- Index *pIx = pLevel->plan.u.pIdx;
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
- int iIndexCur = pLevel->iIdxCur;
+ if( pLoop->wsFlags & WHERE_INDEXED ){
+ Index *pIx = pLoop->u.btree.pIndex;
+ int iIndexCur;
+ int op = OP_OpenRead;
+ /* iIdxCur is always set if to a positive value if ONEPASS is possible */
+ assert( iIdxCur!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
+ if( pWInfo->okOnePass ){
+ Index *pJ = pTabItem->pTab->pIndex;
+ iIndexCur = iIdxCur;
+ assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
+ while( ALWAYS(pJ) && pJ!=pIx ){
+ iIndexCur++;
+ pJ = pJ->pNext;
+ }
+ op = OP_OpenWrite;
+ pWInfo->aiCurOnePass[1] = iIndexCur;
+ }else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
+ iIndexCur = iIdxCur;
+ }else{
+ iIndexCur = pParse->nTab++;
+ }
+ pLevel->iIdxCur = iIndexCur;
assert( pIx->pSchema==pTab->pSchema );
assert( iIndexCur>=0 );
- sqlite3VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb,
- (char*)pKey, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
+ sqlite3VdbeSetP4KeyInfo(pParse, pIx);
VdbeComment((v, "%s", pIx->zName));
}
sqlite3CodeVerifySchema(pParse, iDb);
- notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor);
+ notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
if( db->mallocFailed ) goto whereBeginError;
@@ -109919,67 +114142,21 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
notReady = ~(Bitmask)0;
for(ii=0; ii<nTabList; ii++){
pLevel = &pWInfo->a[ii];
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+ if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
+ constructAutomaticIndex(pParse, &pWInfo->sWC,
+ &pTabList->a[pLevel->iFrom], notReady, pLevel);
+ if( db->mallocFailed ) goto whereBeginError;
+ }
+#endif
explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
- notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
+ pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
+ notReady = codeOneLoopStart(pWInfo, ii, notReady);
pWInfo->iContinue = pLevel->addrCont;
}
-#ifdef SQLITE_TEST /* For testing and debugging use only */
- /* Record in the query plan information about the current table
- ** and the index used to access it (if any). If the table itself
- ** is not used, its name is just '{}'. If no index is used
- ** the index is listed as "{}". If the primary key is used the
- ** index name is '*'.
- */
- for(ii=0; ii<nTabList; ii++){
- char *z;
- int n;
- int w;
- struct SrcList_item *pTabItem;
-
- pLevel = &pWInfo->a[ii];
- w = pLevel->plan.wsFlags;
- pTabItem = &pTabList->a[pLevel->iFrom];
- z = pTabItem->zAlias;
- if( z==0 ) z = pTabItem->pTab->zName;
- n = sqlite3Strlen30(z);
- if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
- if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
- memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
- nQPlan += 2;
- }else{
- memcpy(&sqlite3_query_plan[nQPlan], z, n);
- nQPlan += n;
- }
- sqlite3_query_plan[nQPlan++] = ' ';
- }
- testcase( w & WHERE_ROWID_EQ );
- testcase( w & WHERE_ROWID_RANGE );
- if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
- memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
- nQPlan += 2;
- }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
- n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
- if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
- memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
- nQPlan += n;
- sqlite3_query_plan[nQPlan++] = ' ';
- }
- }else{
- memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3);
- nQPlan += 3;
- }
- }
- while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
- sqlite3_query_plan[--nQPlan] = 0;
- }
- sqlite3_query_plan[nQPlan] = 0;
- nQPlan = 0;
-#endif /* SQLITE_TEST // Testing and debugging use only */
-
- /* Record the continuation address in the WhereInfo structure. Then
- ** clean up and return.
- */
+ /* Done. */
+ VdbeModuleComment((v, "Begin WHERE-core"));
return pWInfo;
/* Jump here if malloc fails */
@@ -110000,20 +114177,24 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
Vdbe *v = pParse->pVdbe;
int i;
WhereLevel *pLevel;
+ WhereLoop *pLoop;
SrcList *pTabList = pWInfo->pTabList;
sqlite3 *db = pParse->db;
/* Generate loop termination code.
*/
+ VdbeModuleComment((v, "End WHERE-core"));
sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){
+ int addr;
pLevel = &pWInfo->a[i];
+ pLoop = pLevel->pWLoop;
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
sqlite3VdbeChangeP5(v, pLevel->p5);
}
- if( pLevel->plan.wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
+ if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
int j;
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
@@ -110025,15 +114206,20 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3DbFree(db, pLevel->u.in.aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
+ if( pLevel->addrSkip ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrSkip);
+ VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
+ sqlite3VdbeJumpHere(v, pLevel->addrSkip);
+ sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
+ }
if( pLevel->iLeftJoin ){
- int addr;
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
- assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
- || (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 );
- if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 ){
+ assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
+ || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
+ if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
}
- if( pLevel->iIdxCur>=0 ){
+ if( pLoop->wsFlags & WHERE_INDEXED ){
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
if( pLevel->op==OP_Return ){
@@ -110043,6 +114229,8 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
}
sqlite3VdbeJumpHere(v, addr);
}
+ VdbeModuleComment((v, "End WHERE-loop%d: %s", i,
+ pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
}
/* The "break" point is here, just past the end of the outer loop.
@@ -110050,33 +114238,39 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
*/
sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
- /* Close all of the cursors that were opened by sqlite3WhereBegin.
- */
- assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
+ assert( pWInfo->nLevel<=pTabList->nSrc );
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
Index *pIdx = 0;
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
+ pLoop = pLevel->pWLoop;
+
+ /* Close all of the cursors that were opened by sqlite3WhereBegin.
+ ** Except, do not close cursors that will be reused by the OR optimization
+ ** (WHERE_OMIT_OPEN_CLOSE). And do not close the OP_OpenWrite cursors
+ ** created for the ONEPASS optimization.
+ */
if( (pTab->tabFlags & TF_Ephemeral)==0
&& pTab->pSelect==0
&& (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0
){
- int ws = pLevel->plan.wsFlags;
+ int ws = pLoop->wsFlags;
if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
}
- if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_TEMP_INDEX)==0 ){
+ if( (ws & WHERE_INDEXED)!=0
+ && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0
+ && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1]
+ ){
sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
}
}
- /* If this scan uses an index, make code substitutions to read data
- ** from the index in preference to the table. Sometimes, this means
- ** the table need never be read from. This is a performance boost,
- ** as the vdbe level waits until the table is read before actually
- ** seeking the table cursor to the record corresponding to the current
- ** position in the index.
+ /* If this scan uses an index, make VDBE code substitutions to read data
+ ** from the index instead of from the table where possible. In some cases
+ ** this optimization prevents the table from ever being read, which can
+ ** yield a significant performance boost.
**
** Calls to the code generator in between sqlite3WhereBegin and
** sqlite3WhereEnd will have created code that references the table
@@ -110084,29 +114278,33 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
** that reference the table and converts them into opcodes that
** reference the index.
*/
- if( pLevel->plan.wsFlags & WHERE_INDEXED ){
- pIdx = pLevel->plan.u.pIdx;
- }else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
+ if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
+ pIdx = pLoop->u.btree.pIndex;
+ }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
pIdx = pLevel->u.pCovidx;
}
- if( pIdx && !db->mallocFailed){
- int k, j, last;
+ if( pIdx && !db->mallocFailed ){
+ int k, last;
VdbeOp *pOp;
- pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
last = sqlite3VdbeCurrentAddr(v);
- for(k=pWInfo->iTop; k<last; k++, pOp++){
+ k = pLevel->addrBody;
+ pOp = sqlite3VdbeGetOp(v, k);
+ for(; k<last; k++, pOp++){
if( pOp->p1!=pLevel->iTabCur ) continue;
if( pOp->opcode==OP_Column ){
- for(j=0; j<pIdx->nColumn; j++){
- if( pOp->p2==pIdx->aiColumn[j] ){
- pOp->p2 = j;
- pOp->p1 = pLevel->iIdxCur;
- break;
- }
+ int x = pOp->p2;
+ assert( pIdx->pTable==pTab );
+ if( !HasRowid(pTab) ){
+ Index *pPk = sqlite3PrimaryKeyIndex(pTab);
+ x = pPk->aiColumn[x];
+ }
+ x = sqlite3ColumnOfIndex(pIdx, x);
+ if( x>=0 ){
+ pOp->p2 = x;
+ pOp->p1 = pLevel->iIdxCur;
}
- assert( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
- || j<pIdx->nColumn );
+ assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0 );
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;
@@ -110314,28 +114512,28 @@ struct ValueList {
** defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
-#define YYNOCODE 251
+#define YYNOCODE 253
#define YYACTIONTYPE unsigned short int
-#define YYWILDCARD 67
+#define YYWILDCARD 68
#define sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlite3ParserTOKENTYPE yy0;
- struct LimitVal yy64;
- Expr* yy122;
- Select* yy159;
- IdList* yy180;
- struct {int value; int mask;} yy207;
- u8 yy258;
- u16 yy305;
- struct LikeOp yy318;
- TriggerStep* yy327;
- ExprSpan yy342;
- SrcList* yy347;
- int yy392;
- struct TrigEvent yy410;
- ExprList* yy442;
- struct ValueList yy487;
+ int yy4;
+ struct TrigEvent yy90;
+ ExprSpan yy118;
+ u16 yy177;
+ TriggerStep* yy203;
+ u8 yy210;
+ struct {int value; int mask;} yy215;
+ SrcList* yy259;
+ struct ValueList yy260;
+ struct LimitVal yy292;
+ Expr* yy314;
+ ExprList* yy322;
+ struct LikeOp yy342;
+ IdList* yy384;
+ Select* yy387;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -110344,8 +114542,8 @@ typedef union {
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 627
-#define YYNRULE 327
+#define YYNSTATE 631
+#define YYNRULE 329
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
@@ -110415,474 +114613,480 @@ static const YYMINORTYPE yyzerominor = { 0 };
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
-#define YY_ACTTAB_COUNT (1564)
+#define YY_ACTTAB_COUNT (1582)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 309, 955, 184, 417, 2, 171, 624, 594, 56, 56,
- /* 10 */ 56, 56, 49, 54, 54, 54, 54, 53, 53, 52,
- /* 20 */ 52, 52, 51, 233, 620, 619, 298, 620, 619, 234,
- /* 30 */ 587, 581, 56, 56, 56, 56, 19, 54, 54, 54,
- /* 40 */ 54, 53, 53, 52, 52, 52, 51, 233, 605, 57,
- /* 50 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
- /* 60 */ 56, 56, 541, 54, 54, 54, 54, 53, 53, 52,
- /* 70 */ 52, 52, 51, 233, 309, 594, 325, 196, 195, 194,
- /* 80 */ 33, 54, 54, 54, 54, 53, 53, 52, 52, 52,
- /* 90 */ 51, 233, 617, 616, 165, 617, 616, 380, 377, 376,
- /* 100 */ 407, 532, 576, 576, 587, 581, 303, 422, 375, 59,
- /* 110 */ 53, 53, 52, 52, 52, 51, 233, 50, 47, 146,
- /* 120 */ 574, 545, 65, 57, 58, 48, 579, 578, 580, 580,
- /* 130 */ 55, 55, 56, 56, 56, 56, 213, 54, 54, 54,
- /* 140 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 223,
- /* 150 */ 539, 420, 170, 176, 138, 280, 383, 275, 382, 168,
- /* 160 */ 489, 551, 409, 668, 620, 619, 271, 438, 409, 438,
- /* 170 */ 550, 604, 67, 482, 507, 618, 599, 412, 587, 581,
- /* 180 */ 600, 483, 618, 412, 618, 598, 91, 439, 440, 439,
- /* 190 */ 335, 598, 73, 669, 222, 266, 480, 57, 58, 48,
- /* 200 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
- /* 210 */ 670, 54, 54, 54, 54, 53, 53, 52, 52, 52,
- /* 220 */ 51, 233, 309, 279, 232, 231, 1, 132, 200, 385,
- /* 230 */ 620, 619, 617, 616, 278, 435, 289, 563, 175, 262,
- /* 240 */ 409, 264, 437, 497, 436, 166, 441, 568, 336, 568,
- /* 250 */ 201, 537, 587, 581, 599, 412, 165, 594, 600, 380,
- /* 260 */ 377, 376, 597, 598, 92, 523, 618, 569, 569, 592,
- /* 270 */ 375, 57, 58, 48, 579, 578, 580, 580, 55, 55,
- /* 280 */ 56, 56, 56, 56, 597, 54, 54, 54, 54, 53,
- /* 290 */ 53, 52, 52, 52, 51, 233, 309, 463, 617, 616,
- /* 300 */ 590, 590, 590, 174, 272, 396, 409, 272, 409, 548,
- /* 310 */ 397, 620, 619, 68, 326, 620, 619, 620, 619, 618,
- /* 320 */ 546, 412, 618, 412, 471, 594, 587, 581, 472, 598,
- /* 330 */ 92, 598, 92, 52, 52, 52, 51, 233, 513, 512,
- /* 340 */ 206, 322, 363, 464, 221, 57, 58, 48, 579, 578,
- /* 350 */ 580, 580, 55, 55, 56, 56, 56, 56, 529, 54,
- /* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
- /* 370 */ 309, 396, 409, 396, 597, 372, 386, 530, 347, 617,
- /* 380 */ 616, 575, 202, 617, 616, 617, 616, 412, 620, 619,
- /* 390 */ 145, 255, 346, 254, 577, 598, 74, 351, 45, 489,
- /* 400 */ 587, 581, 235, 189, 464, 544, 167, 296, 187, 469,
- /* 410 */ 479, 67, 62, 39, 618, 546, 597, 345, 573, 57,
- /* 420 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
- /* 430 */ 56, 56, 6, 54, 54, 54, 54, 53, 53, 52,
- /* 440 */ 52, 52, 51, 233, 309, 562, 558, 407, 528, 576,
- /* 450 */ 576, 344, 255, 346, 254, 182, 617, 616, 503, 504,
- /* 460 */ 314, 409, 557, 235, 166, 271, 409, 352, 564, 181,
- /* 470 */ 407, 546, 576, 576, 587, 581, 412, 537, 556, 561,
- /* 480 */ 517, 412, 618, 249, 598, 16, 7, 36, 467, 598,
- /* 490 */ 92, 516, 618, 57, 58, 48, 579, 578, 580, 580,
- /* 500 */ 55, 55, 56, 56, 56, 56, 541, 54, 54, 54,
- /* 510 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 327,
- /* 520 */ 572, 571, 525, 558, 560, 394, 871, 246, 409, 248,
- /* 530 */ 171, 392, 594, 219, 407, 409, 576, 576, 502, 557,
- /* 540 */ 364, 145, 510, 412, 407, 229, 576, 576, 587, 581,
- /* 550 */ 412, 598, 92, 381, 269, 556, 166, 400, 598, 69,
- /* 560 */ 501, 419, 945, 199, 945, 198, 546, 57, 58, 48,
- /* 570 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
- /* 580 */ 568, 54, 54, 54, 54, 53, 53, 52, 52, 52,
- /* 590 */ 51, 233, 309, 317, 419, 944, 508, 944, 308, 597,
- /* 600 */ 594, 565, 490, 212, 173, 247, 423, 615, 614, 613,
- /* 610 */ 323, 197, 143, 405, 572, 571, 489, 66, 50, 47,
- /* 620 */ 146, 594, 587, 581, 232, 231, 559, 427, 67, 555,
- /* 630 */ 15, 618, 186, 543, 303, 421, 35, 206, 432, 423,
- /* 640 */ 552, 57, 58, 48, 579, 578, 580, 580, 55, 55,
- /* 650 */ 56, 56, 56, 56, 205, 54, 54, 54, 54, 53,
- /* 660 */ 53, 52, 52, 52, 51, 233, 309, 569, 569, 260,
- /* 670 */ 268, 597, 12, 373, 568, 166, 409, 313, 409, 420,
- /* 680 */ 409, 473, 473, 365, 618, 50, 47, 146, 597, 594,
- /* 690 */ 468, 412, 166, 412, 351, 412, 587, 581, 32, 598,
- /* 700 */ 94, 598, 97, 598, 95, 627, 625, 329, 142, 50,
- /* 710 */ 47, 146, 333, 349, 358, 57, 58, 48, 579, 578,
- /* 720 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54,
- /* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
- /* 740 */ 309, 409, 388, 412, 409, 22, 565, 404, 212, 362,
- /* 750 */ 389, 598, 104, 359, 409, 156, 412, 409, 603, 412,
- /* 760 */ 537, 331, 569, 569, 598, 103, 493, 598, 105, 412,
- /* 770 */ 587, 581, 412, 260, 549, 618, 11, 598, 106, 521,
- /* 780 */ 598, 133, 169, 457, 456, 170, 35, 601, 618, 57,
- /* 790 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56,
- /* 800 */ 56, 56, 409, 54, 54, 54, 54, 53, 53, 52,
- /* 810 */ 52, 52, 51, 233, 309, 409, 259, 412, 409, 50,
- /* 820 */ 47, 146, 357, 318, 355, 598, 134, 527, 352, 337,
- /* 830 */ 412, 409, 356, 412, 357, 409, 357, 618, 598, 98,
- /* 840 */ 129, 598, 102, 618, 587, 581, 412, 21, 235, 618,
- /* 850 */ 412, 618, 211, 143, 598, 101, 30, 167, 598, 93,
- /* 860 */ 350, 535, 203, 57, 58, 48, 579, 578, 580, 580,
- /* 870 */ 55, 55, 56, 56, 56, 56, 409, 54, 54, 54,
- /* 880 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 409,
- /* 890 */ 526, 412, 409, 425, 215, 305, 597, 551, 141, 598,
- /* 900 */ 100, 40, 409, 38, 412, 409, 550, 412, 409, 228,
- /* 910 */ 220, 314, 598, 77, 500, 598, 96, 412, 587, 581,
- /* 920 */ 412, 338, 253, 412, 218, 598, 137, 379, 598, 136,
- /* 930 */ 28, 598, 135, 270, 715, 210, 481, 57, 58, 48,
- /* 940 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56,
- /* 950 */ 409, 54, 54, 54, 54, 53, 53, 52, 52, 52,
- /* 960 */ 51, 233, 309, 409, 272, 412, 409, 315, 147, 597,
- /* 970 */ 272, 626, 2, 598, 76, 209, 409, 127, 412, 618,
- /* 980 */ 126, 412, 409, 621, 235, 618, 598, 90, 374, 598,
- /* 990 */ 89, 412, 587, 581, 27, 260, 350, 412, 618, 598,
- /* 1000 */ 75, 321, 541, 541, 125, 598, 88, 320, 278, 597,
- /* 1010 */ 618, 57, 46, 48, 579, 578, 580, 580, 55, 55,
- /* 1020 */ 56, 56, 56, 56, 409, 54, 54, 54, 54, 53,
- /* 1030 */ 53, 52, 52, 52, 51, 233, 309, 409, 450, 412,
- /* 1040 */ 164, 284, 282, 272, 609, 424, 304, 598, 87, 370,
- /* 1050 */ 409, 477, 412, 409, 608, 409, 607, 602, 618, 618,
- /* 1060 */ 598, 99, 586, 585, 122, 412, 587, 581, 412, 618,
- /* 1070 */ 412, 618, 618, 598, 86, 366, 598, 17, 598, 85,
- /* 1080 */ 319, 185, 519, 518, 583, 582, 58, 48, 579, 578,
- /* 1090 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54,
- /* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233,
- /* 1110 */ 309, 584, 409, 412, 409, 260, 260, 260, 408, 591,
- /* 1120 */ 474, 598, 84, 170, 409, 466, 518, 412, 121, 412,
- /* 1130 */ 618, 618, 618, 618, 618, 598, 83, 598, 72, 412,
- /* 1140 */ 587, 581, 51, 233, 625, 329, 470, 598, 71, 257,
- /* 1150 */ 159, 120, 14, 462, 157, 158, 117, 260, 448, 447,
- /* 1160 */ 446, 48, 579, 578, 580, 580, 55, 55, 56, 56,
- /* 1170 */ 56, 56, 618, 54, 54, 54, 54, 53, 53, 52,
- /* 1180 */ 52, 52, 51, 233, 44, 403, 260, 3, 409, 459,
- /* 1190 */ 260, 413, 619, 118, 398, 10, 25, 24, 554, 348,
- /* 1200 */ 217, 618, 406, 412, 409, 618, 4, 44, 403, 618,
- /* 1210 */ 3, 598, 82, 618, 413, 619, 455, 542, 115, 412,
- /* 1220 */ 538, 401, 536, 274, 506, 406, 251, 598, 81, 216,
- /* 1230 */ 273, 563, 618, 243, 453, 618, 154, 618, 618, 618,
- /* 1240 */ 449, 416, 623, 110, 401, 618, 409, 236, 64, 123,
- /* 1250 */ 487, 41, 42, 531, 563, 204, 409, 267, 43, 411,
- /* 1260 */ 410, 412, 265, 592, 108, 618, 107, 434, 332, 598,
- /* 1270 */ 80, 412, 618, 263, 41, 42, 443, 618, 409, 598,
- /* 1280 */ 70, 43, 411, 410, 433, 261, 592, 149, 618, 597,
- /* 1290 */ 256, 237, 188, 412, 590, 590, 590, 589, 588, 13,
- /* 1300 */ 618, 598, 18, 328, 235, 618, 44, 403, 360, 3,
- /* 1310 */ 418, 461, 339, 413, 619, 227, 124, 590, 590, 590,
- /* 1320 */ 589, 588, 13, 618, 406, 409, 618, 409, 139, 34,
- /* 1330 */ 403, 387, 3, 148, 622, 312, 413, 619, 311, 330,
- /* 1340 */ 412, 460, 412, 401, 180, 353, 412, 406, 598, 79,
- /* 1350 */ 598, 78, 250, 563, 598, 9, 618, 612, 611, 610,
- /* 1360 */ 618, 8, 452, 442, 242, 415, 401, 618, 239, 235,
- /* 1370 */ 179, 238, 428, 41, 42, 288, 563, 618, 618, 618,
- /* 1380 */ 43, 411, 410, 618, 144, 592, 618, 618, 177, 61,
- /* 1390 */ 618, 596, 391, 620, 619, 287, 41, 42, 414, 618,
- /* 1400 */ 293, 30, 393, 43, 411, 410, 292, 618, 592, 31,
- /* 1410 */ 618, 395, 291, 60, 230, 37, 590, 590, 590, 589,
- /* 1420 */ 588, 13, 214, 553, 183, 290, 172, 301, 300, 299,
- /* 1430 */ 178, 297, 595, 563, 451, 29, 285, 390, 540, 590,
- /* 1440 */ 590, 590, 589, 588, 13, 283, 520, 534, 150, 533,
- /* 1450 */ 241, 281, 384, 192, 191, 324, 515, 514, 276, 240,
- /* 1460 */ 510, 523, 307, 511, 128, 592, 509, 225, 226, 486,
- /* 1470 */ 485, 224, 152, 491, 464, 306, 484, 163, 153, 371,
- /* 1480 */ 478, 151, 162, 258, 369, 161, 367, 208, 475, 476,
- /* 1490 */ 26, 160, 465, 140, 361, 131, 590, 590, 590, 116,
- /* 1500 */ 119, 454, 343, 155, 114, 342, 113, 112, 445, 111,
- /* 1510 */ 130, 109, 431, 316, 426, 430, 23, 429, 20, 606,
- /* 1520 */ 190, 507, 255, 341, 244, 63, 294, 593, 310, 570,
- /* 1530 */ 277, 402, 354, 235, 567, 496, 495, 492, 494, 302,
- /* 1540 */ 458, 378, 286, 245, 566, 5, 252, 547, 193, 444,
- /* 1550 */ 233, 340, 207, 524, 368, 505, 334, 522, 499, 399,
- /* 1560 */ 295, 498, 956, 488,
+ /* 0 */ 312, 961, 185, 420, 2, 171, 516, 515, 597, 56,
+ /* 10 */ 56, 56, 56, 49, 54, 54, 54, 54, 53, 53,
+ /* 20 */ 52, 52, 52, 51, 234, 197, 196, 195, 624, 623,
+ /* 30 */ 301, 590, 584, 56, 56, 56, 56, 156, 54, 54,
+ /* 40 */ 54, 54, 53, 53, 52, 52, 52, 51, 234, 628,
+ /* 50 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56,
+ /* 60 */ 56, 56, 56, 466, 54, 54, 54, 54, 53, 53,
+ /* 70 */ 52, 52, 52, 51, 234, 312, 597, 52, 52, 52,
+ /* 80 */ 51, 234, 33, 54, 54, 54, 54, 53, 53, 52,
+ /* 90 */ 52, 52, 51, 234, 624, 623, 621, 620, 165, 624,
+ /* 100 */ 623, 383, 380, 379, 214, 328, 590, 584, 624, 623,
+ /* 110 */ 467, 59, 378, 619, 618, 617, 53, 53, 52, 52,
+ /* 120 */ 52, 51, 234, 506, 507, 57, 58, 48, 582, 581,
+ /* 130 */ 583, 583, 55, 55, 56, 56, 56, 56, 30, 54,
+ /* 140 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
+ /* 150 */ 312, 50, 47, 146, 233, 232, 207, 474, 256, 349,
+ /* 160 */ 255, 475, 621, 620, 554, 438, 298, 621, 620, 236,
+ /* 170 */ 674, 435, 440, 553, 439, 366, 621, 620, 540, 224,
+ /* 180 */ 551, 590, 584, 176, 138, 282, 386, 277, 385, 168,
+ /* 190 */ 600, 422, 951, 548, 622, 951, 273, 572, 572, 566,
+ /* 200 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56,
+ /* 210 */ 56, 56, 56, 354, 54, 54, 54, 54, 53, 53,
+ /* 220 */ 52, 52, 52, 51, 234, 312, 561, 526, 62, 675,
+ /* 230 */ 132, 595, 410, 348, 579, 579, 492, 426, 577, 419,
+ /* 240 */ 627, 65, 329, 560, 441, 237, 676, 123, 607, 67,
+ /* 250 */ 542, 532, 622, 170, 205, 500, 590, 584, 166, 559,
+ /* 260 */ 622, 403, 593, 593, 593, 442, 443, 271, 422, 950,
+ /* 270 */ 166, 223, 950, 483, 190, 57, 58, 48, 582, 581,
+ /* 280 */ 583, 583, 55, 55, 56, 56, 56, 56, 600, 54,
+ /* 290 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
+ /* 300 */ 312, 441, 412, 376, 175, 165, 166, 391, 383, 380,
+ /* 310 */ 379, 342, 412, 203, 426, 66, 392, 622, 415, 378,
+ /* 320 */ 597, 166, 442, 338, 444, 571, 601, 74, 415, 624,
+ /* 330 */ 623, 590, 584, 624, 623, 174, 601, 92, 333, 171,
+ /* 340 */ 1, 410, 597, 579, 579, 624, 623, 600, 306, 425,
+ /* 350 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56,
+ /* 360 */ 56, 56, 56, 580, 54, 54, 54, 54, 53, 53,
+ /* 370 */ 52, 52, 52, 51, 234, 312, 472, 262, 399, 68,
+ /* 380 */ 412, 339, 571, 389, 624, 623, 578, 602, 597, 589,
+ /* 390 */ 588, 603, 412, 622, 423, 533, 415, 621, 620, 513,
+ /* 400 */ 257, 621, 620, 166, 601, 91, 590, 584, 415, 45,
+ /* 410 */ 597, 586, 585, 621, 620, 250, 601, 92, 39, 347,
+ /* 420 */ 576, 336, 597, 547, 567, 57, 58, 48, 582, 581,
+ /* 430 */ 583, 583, 55, 55, 56, 56, 56, 56, 587, 54,
+ /* 440 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
+ /* 450 */ 312, 561, 621, 620, 531, 291, 470, 188, 399, 375,
+ /* 460 */ 247, 492, 249, 350, 412, 476, 476, 368, 560, 299,
+ /* 470 */ 334, 412, 281, 482, 67, 565, 410, 622, 579, 579,
+ /* 480 */ 415, 590, 584, 280, 559, 467, 520, 415, 601, 92,
+ /* 490 */ 597, 167, 544, 36, 877, 601, 16, 519, 564, 6,
+ /* 500 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56,
+ /* 510 */ 56, 56, 56, 200, 54, 54, 54, 54, 53, 53,
+ /* 520 */ 52, 52, 52, 51, 234, 312, 183, 412, 236, 528,
+ /* 530 */ 395, 535, 358, 256, 349, 255, 397, 412, 248, 182,
+ /* 540 */ 353, 359, 549, 415, 236, 317, 563, 50, 47, 146,
+ /* 550 */ 273, 601, 73, 415, 7, 311, 590, 584, 568, 493,
+ /* 560 */ 213, 601, 92, 233, 232, 410, 173, 579, 579, 330,
+ /* 570 */ 575, 574, 631, 629, 332, 57, 58, 48, 582, 581,
+ /* 580 */ 583, 583, 55, 55, 56, 56, 56, 56, 199, 54,
+ /* 590 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
+ /* 600 */ 312, 492, 340, 320, 511, 505, 572, 572, 460, 562,
+ /* 610 */ 549, 170, 145, 430, 67, 558, 410, 622, 579, 579,
+ /* 620 */ 384, 236, 600, 412, 408, 575, 574, 504, 572, 572,
+ /* 630 */ 571, 590, 584, 353, 198, 143, 268, 549, 316, 415,
+ /* 640 */ 306, 424, 207, 50, 47, 146, 167, 601, 69, 546,
+ /* 650 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56,
+ /* 660 */ 56, 56, 56, 555, 54, 54, 54, 54, 53, 53,
+ /* 670 */ 52, 52, 52, 51, 234, 312, 600, 326, 412, 270,
+ /* 680 */ 145, 264, 274, 266, 459, 571, 423, 35, 412, 568,
+ /* 690 */ 407, 213, 428, 388, 415, 308, 212, 143, 622, 354,
+ /* 700 */ 317, 12, 601, 94, 415, 549, 590, 584, 50, 47,
+ /* 710 */ 146, 365, 601, 97, 552, 362, 318, 147, 602, 361,
+ /* 720 */ 325, 15, 603, 187, 206, 57, 58, 48, 582, 581,
+ /* 730 */ 583, 583, 55, 55, 56, 56, 56, 56, 412, 54,
+ /* 740 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
+ /* 750 */ 312, 412, 35, 412, 415, 22, 630, 2, 600, 50,
+ /* 760 */ 47, 146, 601, 95, 412, 485, 510, 415, 412, 415,
+ /* 770 */ 412, 11, 235, 486, 412, 601, 104, 601, 103, 19,
+ /* 780 */ 415, 590, 584, 352, 415, 40, 415, 38, 601, 105,
+ /* 790 */ 415, 32, 601, 106, 601, 133, 544, 169, 601, 134,
+ /* 800 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56,
+ /* 810 */ 56, 56, 56, 412, 54, 54, 54, 54, 53, 53,
+ /* 820 */ 52, 52, 52, 51, 234, 312, 412, 274, 412, 415,
+ /* 830 */ 412, 274, 274, 274, 201, 230, 721, 601, 98, 484,
+ /* 840 */ 427, 307, 415, 622, 415, 540, 415, 622, 622, 622,
+ /* 850 */ 601, 102, 601, 101, 601, 93, 590, 584, 262, 21,
+ /* 860 */ 129, 622, 522, 521, 554, 222, 469, 521, 600, 324,
+ /* 870 */ 323, 322, 211, 553, 622, 57, 58, 48, 582, 581,
+ /* 880 */ 583, 583, 55, 55, 56, 56, 56, 56, 412, 54,
+ /* 890 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
+ /* 900 */ 312, 412, 261, 412, 415, 412, 600, 210, 625, 367,
+ /* 910 */ 51, 234, 601, 100, 538, 606, 142, 415, 355, 415,
+ /* 920 */ 412, 415, 412, 496, 622, 601, 77, 601, 96, 601,
+ /* 930 */ 137, 590, 584, 530, 622, 529, 415, 141, 415, 28,
+ /* 940 */ 524, 600, 229, 544, 601, 136, 601, 135, 604, 204,
+ /* 950 */ 57, 58, 48, 582, 581, 583, 583, 55, 55, 56,
+ /* 960 */ 56, 56, 56, 412, 54, 54, 54, 54, 53, 53,
+ /* 970 */ 52, 52, 52, 51, 234, 312, 412, 360, 412, 415,
+ /* 980 */ 412, 360, 286, 600, 503, 220, 127, 601, 76, 629,
+ /* 990 */ 332, 382, 415, 622, 415, 540, 415, 622, 412, 613,
+ /* 1000 */ 601, 90, 601, 89, 601, 75, 590, 584, 341, 272,
+ /* 1010 */ 377, 622, 126, 27, 415, 622, 164, 544, 125, 280,
+ /* 1020 */ 373, 122, 601, 88, 480, 57, 46, 48, 582, 581,
+ /* 1030 */ 583, 583, 55, 55, 56, 56, 56, 56, 412, 54,
+ /* 1040 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
+ /* 1050 */ 312, 412, 360, 412, 415, 412, 284, 186, 369, 321,
+ /* 1060 */ 477, 170, 601, 87, 121, 473, 221, 415, 622, 415,
+ /* 1070 */ 254, 415, 412, 355, 412, 601, 99, 601, 86, 601,
+ /* 1080 */ 17, 590, 584, 259, 612, 120, 159, 158, 415, 622,
+ /* 1090 */ 415, 14, 465, 157, 462, 25, 601, 85, 601, 84,
+ /* 1100 */ 622, 58, 48, 582, 581, 583, 583, 55, 55, 56,
+ /* 1110 */ 56, 56, 56, 412, 54, 54, 54, 54, 53, 53,
+ /* 1120 */ 52, 52, 52, 51, 234, 312, 412, 262, 412, 415,
+ /* 1130 */ 412, 262, 118, 611, 117, 24, 10, 601, 83, 351,
+ /* 1140 */ 216, 219, 415, 622, 415, 608, 415, 622, 412, 622,
+ /* 1150 */ 601, 72, 601, 71, 601, 82, 590, 584, 262, 4,
+ /* 1160 */ 605, 622, 458, 115, 415, 456, 252, 154, 452, 110,
+ /* 1170 */ 108, 453, 601, 81, 622, 451, 622, 48, 582, 581,
+ /* 1180 */ 583, 583, 55, 55, 56, 56, 56, 56, 412, 54,
+ /* 1190 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 234,
+ /* 1200 */ 44, 406, 450, 3, 415, 412, 262, 107, 416, 623,
+ /* 1210 */ 446, 437, 601, 80, 436, 335, 238, 189, 411, 409,
+ /* 1220 */ 594, 415, 622, 44, 406, 401, 3, 412, 557, 601,
+ /* 1230 */ 70, 416, 623, 412, 622, 149, 622, 421, 404, 64,
+ /* 1240 */ 412, 622, 409, 415, 622, 331, 139, 148, 566, 415,
+ /* 1250 */ 449, 601, 18, 228, 124, 626, 415, 601, 79, 315,
+ /* 1260 */ 181, 404, 412, 545, 601, 78, 262, 541, 41, 42,
+ /* 1270 */ 534, 566, 390, 202, 262, 43, 414, 413, 415, 622,
+ /* 1280 */ 595, 314, 622, 622, 180, 539, 601, 92, 415, 276,
+ /* 1290 */ 622, 41, 42, 509, 616, 615, 601, 9, 43, 414,
+ /* 1300 */ 413, 622, 418, 595, 262, 622, 275, 600, 614, 622,
+ /* 1310 */ 218, 593, 593, 593, 592, 591, 13, 178, 217, 417,
+ /* 1320 */ 622, 236, 622, 44, 406, 490, 3, 269, 399, 267,
+ /* 1330 */ 609, 416, 623, 400, 593, 593, 593, 592, 591, 13,
+ /* 1340 */ 265, 622, 409, 622, 263, 622, 34, 406, 244, 3,
+ /* 1350 */ 258, 363, 464, 463, 416, 623, 622, 356, 251, 8,
+ /* 1360 */ 622, 404, 177, 599, 455, 409, 622, 622, 622, 622,
+ /* 1370 */ 445, 566, 243, 622, 622, 236, 295, 240, 31, 239,
+ /* 1380 */ 622, 431, 30, 396, 404, 290, 622, 294, 622, 293,
+ /* 1390 */ 144, 41, 42, 622, 566, 622, 394, 622, 43, 414,
+ /* 1400 */ 413, 622, 289, 595, 398, 60, 622, 292, 37, 231,
+ /* 1410 */ 598, 172, 622, 29, 41, 42, 393, 523, 622, 556,
+ /* 1420 */ 184, 43, 414, 413, 287, 387, 595, 543, 285, 518,
+ /* 1430 */ 537, 536, 517, 327, 593, 593, 593, 592, 591, 13,
+ /* 1440 */ 215, 283, 278, 514, 513, 304, 303, 302, 179, 300,
+ /* 1450 */ 512, 310, 454, 128, 227, 226, 309, 593, 593, 593,
+ /* 1460 */ 592, 591, 13, 494, 489, 225, 488, 150, 487, 242,
+ /* 1470 */ 163, 61, 374, 481, 162, 161, 624, 623, 241, 372,
+ /* 1480 */ 209, 479, 370, 260, 26, 160, 478, 364, 468, 471,
+ /* 1490 */ 140, 152, 119, 467, 131, 116, 155, 153, 345, 457,
+ /* 1500 */ 151, 346, 130, 114, 113, 112, 111, 448, 319, 23,
+ /* 1510 */ 109, 434, 20, 433, 432, 429, 566, 610, 573, 596,
+ /* 1520 */ 63, 405, 191, 279, 510, 296, 498, 288, 570, 495,
+ /* 1530 */ 499, 497, 461, 194, 5, 305, 193, 192, 381, 569,
+ /* 1540 */ 357, 256, 344, 245, 526, 246, 253, 313, 595, 343,
+ /* 1550 */ 447, 297, 236, 402, 550, 491, 508, 502, 501, 527,
+ /* 1560 */ 234, 208, 525, 962, 962, 962, 371, 962, 962, 962,
+ /* 1570 */ 962, 962, 962, 962, 962, 337, 962, 962, 962, 593,
+ /* 1580 */ 593, 593,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 19, 142, 143, 144, 145, 24, 1, 26, 77, 78,
+ /* 0 */ 19, 143, 144, 145, 146, 24, 7, 8, 27, 78,
/* 10 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
- /* 20 */ 89, 90, 91, 92, 26, 27, 15, 26, 27, 197,
- /* 30 */ 49, 50, 77, 78, 79, 80, 204, 82, 83, 84,
- /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 23, 68,
+ /* 20 */ 89, 90, 91, 92, 93, 106, 107, 108, 27, 28,
+ /* 30 */ 15, 50, 51, 78, 79, 80, 81, 26, 83, 84,
+ /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 1,
/* 50 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- /* 60 */ 79, 80, 166, 82, 83, 84, 85, 86, 87, 88,
- /* 70 */ 89, 90, 91, 92, 19, 94, 19, 105, 106, 107,
- /* 80 */ 25, 82, 83, 84, 85, 86, 87, 88, 89, 90,
- /* 90 */ 91, 92, 94, 95, 96, 94, 95, 99, 100, 101,
- /* 100 */ 112, 205, 114, 115, 49, 50, 22, 23, 110, 54,
- /* 110 */ 86, 87, 88, 89, 90, 91, 92, 221, 222, 223,
- /* 120 */ 23, 120, 25, 68, 69, 70, 71, 72, 73, 74,
- /* 130 */ 75, 76, 77, 78, 79, 80, 22, 82, 83, 84,
- /* 140 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 92,
- /* 150 */ 23, 67, 25, 96, 97, 98, 99, 100, 101, 102,
- /* 160 */ 150, 32, 150, 118, 26, 27, 109, 150, 150, 150,
- /* 170 */ 41, 161, 162, 180, 181, 165, 113, 165, 49, 50,
- /* 180 */ 117, 188, 165, 165, 165, 173, 174, 170, 171, 170,
- /* 190 */ 171, 173, 174, 118, 184, 16, 186, 68, 69, 70,
- /* 200 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
- /* 210 */ 118, 82, 83, 84, 85, 86, 87, 88, 89, 90,
- /* 220 */ 91, 92, 19, 98, 86, 87, 22, 24, 160, 88,
- /* 230 */ 26, 27, 94, 95, 109, 97, 224, 66, 118, 60,
- /* 240 */ 150, 62, 104, 23, 106, 25, 229, 230, 229, 230,
- /* 250 */ 160, 150, 49, 50, 113, 165, 96, 26, 117, 99,
- /* 260 */ 100, 101, 194, 173, 174, 94, 165, 129, 130, 98,
- /* 270 */ 110, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- /* 280 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86,
- /* 290 */ 87, 88, 89, 90, 91, 92, 19, 11, 94, 95,
- /* 300 */ 129, 130, 131, 118, 150, 215, 150, 150, 150, 25,
- /* 310 */ 220, 26, 27, 22, 213, 26, 27, 26, 27, 165,
- /* 320 */ 25, 165, 165, 165, 30, 94, 49, 50, 34, 173,
- /* 330 */ 174, 173, 174, 88, 89, 90, 91, 92, 7, 8,
- /* 340 */ 160, 187, 48, 57, 187, 68, 69, 70, 71, 72,
- /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 23, 82,
- /* 360 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
- /* 370 */ 19, 215, 150, 215, 194, 19, 220, 88, 220, 94,
- /* 380 */ 95, 23, 160, 94, 95, 94, 95, 165, 26, 27,
- /* 390 */ 95, 105, 106, 107, 113, 173, 174, 217, 22, 150,
- /* 400 */ 49, 50, 116, 119, 57, 120, 50, 158, 22, 21,
- /* 410 */ 161, 162, 232, 136, 165, 120, 194, 237, 23, 68,
- /* 420 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- /* 430 */ 79, 80, 22, 82, 83, 84, 85, 86, 87, 88,
- /* 440 */ 89, 90, 91, 92, 19, 23, 12, 112, 23, 114,
- /* 450 */ 115, 63, 105, 106, 107, 23, 94, 95, 97, 98,
- /* 460 */ 104, 150, 28, 116, 25, 109, 150, 150, 23, 23,
- /* 470 */ 112, 25, 114, 115, 49, 50, 165, 150, 44, 11,
- /* 480 */ 46, 165, 165, 16, 173, 174, 76, 136, 100, 173,
- /* 490 */ 174, 57, 165, 68, 69, 70, 71, 72, 73, 74,
- /* 500 */ 75, 76, 77, 78, 79, 80, 166, 82, 83, 84,
- /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 169,
- /* 520 */ 170, 171, 23, 12, 23, 214, 138, 60, 150, 62,
- /* 530 */ 24, 215, 26, 216, 112, 150, 114, 115, 36, 28,
- /* 540 */ 213, 95, 103, 165, 112, 205, 114, 115, 49, 50,
- /* 550 */ 165, 173, 174, 51, 23, 44, 25, 46, 173, 174,
- /* 560 */ 58, 22, 23, 22, 25, 160, 120, 68, 69, 70,
- /* 570 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
- /* 580 */ 230, 82, 83, 84, 85, 86, 87, 88, 89, 90,
- /* 590 */ 91, 92, 19, 215, 22, 23, 23, 25, 163, 194,
- /* 600 */ 94, 166, 167, 168, 25, 138, 67, 7, 8, 9,
- /* 610 */ 108, 206, 207, 169, 170, 171, 150, 22, 221, 222,
- /* 620 */ 223, 26, 49, 50, 86, 87, 23, 161, 162, 23,
- /* 630 */ 22, 165, 24, 120, 22, 23, 25, 160, 241, 67,
- /* 640 */ 176, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- /* 650 */ 77, 78, 79, 80, 160, 82, 83, 84, 85, 86,
- /* 660 */ 87, 88, 89, 90, 91, 92, 19, 129, 130, 150,
- /* 670 */ 23, 194, 35, 23, 230, 25, 150, 155, 150, 67,
- /* 680 */ 150, 105, 106, 107, 165, 221, 222, 223, 194, 94,
- /* 690 */ 23, 165, 25, 165, 217, 165, 49, 50, 25, 173,
- /* 700 */ 174, 173, 174, 173, 174, 0, 1, 2, 118, 221,
- /* 710 */ 222, 223, 193, 219, 237, 68, 69, 70, 71, 72,
- /* 720 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
- /* 730 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
- /* 740 */ 19, 150, 19, 165, 150, 24, 166, 167, 168, 227,
- /* 750 */ 27, 173, 174, 231, 150, 25, 165, 150, 172, 165,
- /* 760 */ 150, 242, 129, 130, 173, 174, 180, 173, 174, 165,
- /* 770 */ 49, 50, 165, 150, 176, 165, 35, 173, 174, 165,
- /* 780 */ 173, 174, 35, 23, 23, 25, 25, 173, 165, 68,
- /* 790 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- /* 800 */ 79, 80, 150, 82, 83, 84, 85, 86, 87, 88,
- /* 810 */ 89, 90, 91, 92, 19, 150, 193, 165, 150, 221,
- /* 820 */ 222, 223, 150, 213, 19, 173, 174, 23, 150, 97,
- /* 830 */ 165, 150, 27, 165, 150, 150, 150, 165, 173, 174,
- /* 840 */ 22, 173, 174, 165, 49, 50, 165, 52, 116, 165,
- /* 850 */ 165, 165, 206, 207, 173, 174, 126, 50, 173, 174,
- /* 860 */ 128, 27, 160, 68, 69, 70, 71, 72, 73, 74,
- /* 870 */ 75, 76, 77, 78, 79, 80, 150, 82, 83, 84,
- /* 880 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 150,
- /* 890 */ 23, 165, 150, 23, 216, 25, 194, 32, 39, 173,
- /* 900 */ 174, 135, 150, 137, 165, 150, 41, 165, 150, 52,
- /* 910 */ 238, 104, 173, 174, 29, 173, 174, 165, 49, 50,
- /* 920 */ 165, 219, 238, 165, 238, 173, 174, 52, 173, 174,
- /* 930 */ 22, 173, 174, 23, 23, 160, 25, 68, 69, 70,
- /* 940 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
- /* 950 */ 150, 82, 83, 84, 85, 86, 87, 88, 89, 90,
- /* 960 */ 91, 92, 19, 150, 150, 165, 150, 245, 246, 194,
- /* 970 */ 150, 144, 145, 173, 174, 160, 150, 22, 165, 165,
- /* 980 */ 22, 165, 150, 150, 116, 165, 173, 174, 52, 173,
- /* 990 */ 174, 165, 49, 50, 22, 150, 128, 165, 165, 173,
- /* 1000 */ 174, 187, 166, 166, 22, 173, 174, 187, 109, 194,
- /* 1010 */ 165, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- /* 1020 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86,
- /* 1030 */ 87, 88, 89, 90, 91, 92, 19, 150, 193, 165,
- /* 1040 */ 102, 205, 205, 150, 150, 247, 248, 173, 174, 19,
- /* 1050 */ 150, 20, 165, 150, 150, 150, 150, 150, 165, 165,
- /* 1060 */ 173, 174, 49, 50, 104, 165, 49, 50, 165, 165,
- /* 1070 */ 165, 165, 165, 173, 174, 43, 173, 174, 173, 174,
- /* 1080 */ 187, 24, 190, 191, 71, 72, 69, 70, 71, 72,
- /* 1090 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82,
- /* 1100 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
- /* 1110 */ 19, 98, 150, 165, 150, 150, 150, 150, 150, 150,
- /* 1120 */ 59, 173, 174, 25, 150, 190, 191, 165, 53, 165,
- /* 1130 */ 165, 165, 165, 165, 165, 173, 174, 173, 174, 165,
- /* 1140 */ 49, 50, 91, 92, 1, 2, 53, 173, 174, 138,
- /* 1150 */ 104, 22, 5, 1, 35, 118, 127, 150, 193, 193,
- /* 1160 */ 193, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- /* 1170 */ 79, 80, 165, 82, 83, 84, 85, 86, 87, 88,
- /* 1180 */ 89, 90, 91, 92, 19, 20, 150, 22, 150, 27,
- /* 1190 */ 150, 26, 27, 108, 150, 22, 76, 76, 150, 25,
- /* 1200 */ 193, 165, 37, 165, 150, 165, 22, 19, 20, 165,
- /* 1210 */ 22, 173, 174, 165, 26, 27, 23, 150, 119, 165,
- /* 1220 */ 150, 56, 150, 150, 150, 37, 16, 173, 174, 193,
- /* 1230 */ 150, 66, 165, 193, 1, 165, 121, 165, 165, 165,
- /* 1240 */ 20, 146, 147, 119, 56, 165, 150, 152, 16, 154,
- /* 1250 */ 150, 86, 87, 88, 66, 160, 150, 150, 93, 94,
- /* 1260 */ 95, 165, 150, 98, 108, 165, 127, 23, 65, 173,
- /* 1270 */ 174, 165, 165, 150, 86, 87, 128, 165, 150, 173,
- /* 1280 */ 174, 93, 94, 95, 23, 150, 98, 15, 165, 194,
- /* 1290 */ 150, 140, 22, 165, 129, 130, 131, 132, 133, 134,
- /* 1300 */ 165, 173, 174, 3, 116, 165, 19, 20, 150, 22,
- /* 1310 */ 4, 150, 217, 26, 27, 179, 179, 129, 130, 131,
- /* 1320 */ 132, 133, 134, 165, 37, 150, 165, 150, 164, 19,
- /* 1330 */ 20, 150, 22, 246, 149, 249, 26, 27, 249, 244,
- /* 1340 */ 165, 150, 165, 56, 6, 150, 165, 37, 173, 174,
- /* 1350 */ 173, 174, 150, 66, 173, 174, 165, 149, 149, 13,
- /* 1360 */ 165, 25, 150, 150, 150, 149, 56, 165, 150, 116,
- /* 1370 */ 151, 150, 150, 86, 87, 150, 66, 165, 165, 165,
- /* 1380 */ 93, 94, 95, 165, 150, 98, 165, 165, 151, 22,
- /* 1390 */ 165, 194, 150, 26, 27, 150, 86, 87, 159, 165,
- /* 1400 */ 199, 126, 123, 93, 94, 95, 200, 165, 98, 124,
- /* 1410 */ 165, 122, 201, 125, 225, 135, 129, 130, 131, 132,
- /* 1420 */ 133, 134, 5, 157, 157, 202, 118, 10, 11, 12,
- /* 1430 */ 13, 14, 203, 66, 17, 104, 210, 121, 211, 129,
- /* 1440 */ 130, 131, 132, 133, 134, 210, 175, 211, 31, 211,
- /* 1450 */ 33, 210, 104, 86, 87, 47, 175, 183, 175, 42,
- /* 1460 */ 103, 94, 178, 177, 22, 98, 175, 92, 228, 175,
- /* 1470 */ 175, 228, 55, 183, 57, 178, 175, 156, 61, 18,
- /* 1480 */ 157, 64, 156, 235, 157, 156, 45, 157, 236, 157,
- /* 1490 */ 135, 156, 189, 68, 157, 218, 129, 130, 131, 22,
- /* 1500 */ 189, 199, 157, 156, 192, 18, 192, 192, 199, 192,
- /* 1510 */ 218, 189, 40, 157, 38, 157, 240, 157, 240, 153,
- /* 1520 */ 196, 181, 105, 106, 107, 243, 198, 166, 111, 230,
- /* 1530 */ 176, 226, 239, 116, 230, 176, 166, 166, 176, 148,
- /* 1540 */ 199, 177, 209, 209, 166, 196, 239, 208, 185, 199,
- /* 1550 */ 92, 209, 233, 173, 234, 182, 139, 173, 182, 191,
- /* 1560 */ 195, 182, 250, 186,
+ /* 60 */ 79, 80, 81, 11, 83, 84, 85, 86, 87, 88,
+ /* 70 */ 89, 90, 91, 92, 93, 19, 95, 89, 90, 91,
+ /* 80 */ 92, 93, 26, 83, 84, 85, 86, 87, 88, 89,
+ /* 90 */ 90, 91, 92, 93, 27, 28, 95, 96, 97, 27,
+ /* 100 */ 28, 100, 101, 102, 22, 19, 50, 51, 27, 28,
+ /* 110 */ 58, 55, 111, 7, 8, 9, 87, 88, 89, 90,
+ /* 120 */ 91, 92, 93, 98, 99, 69, 70, 71, 72, 73,
+ /* 130 */ 74, 75, 76, 77, 78, 79, 80, 81, 127, 83,
+ /* 140 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 150 */ 19, 223, 224, 225, 87, 88, 162, 31, 106, 107,
+ /* 160 */ 108, 35, 95, 96, 33, 98, 23, 95, 96, 117,
+ /* 170 */ 119, 243, 105, 42, 107, 49, 95, 96, 151, 93,
+ /* 180 */ 26, 50, 51, 97, 98, 99, 100, 101, 102, 103,
+ /* 190 */ 196, 22, 23, 121, 167, 26, 110, 130, 131, 67,
+ /* 200 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 210 */ 79, 80, 81, 219, 83, 84, 85, 86, 87, 88,
+ /* 220 */ 89, 90, 91, 92, 93, 19, 12, 95, 234, 119,
+ /* 230 */ 24, 99, 113, 239, 115, 116, 151, 68, 23, 147,
+ /* 240 */ 148, 26, 215, 29, 151, 153, 119, 155, 163, 164,
+ /* 250 */ 23, 23, 167, 26, 162, 23, 50, 51, 26, 45,
+ /* 260 */ 167, 47, 130, 131, 132, 172, 173, 23, 22, 23,
+ /* 270 */ 26, 186, 26, 188, 120, 69, 70, 71, 72, 73,
+ /* 280 */ 74, 75, 76, 77, 78, 79, 80, 81, 196, 83,
+ /* 290 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 300 */ 19, 151, 151, 23, 119, 97, 26, 19, 100, 101,
+ /* 310 */ 102, 219, 151, 162, 68, 22, 28, 167, 167, 111,
+ /* 320 */ 27, 26, 172, 173, 231, 232, 175, 176, 167, 27,
+ /* 330 */ 28, 50, 51, 27, 28, 119, 175, 176, 246, 24,
+ /* 340 */ 22, 113, 27, 115, 116, 27, 28, 196, 22, 23,
+ /* 350 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 360 */ 79, 80, 81, 114, 83, 84, 85, 86, 87, 88,
+ /* 370 */ 89, 90, 91, 92, 93, 19, 21, 151, 217, 22,
+ /* 380 */ 151, 231, 232, 222, 27, 28, 23, 114, 95, 50,
+ /* 390 */ 51, 118, 151, 167, 68, 89, 167, 95, 96, 104,
+ /* 400 */ 23, 95, 96, 26, 175, 176, 50, 51, 167, 22,
+ /* 410 */ 95, 72, 73, 95, 96, 16, 175, 176, 137, 64,
+ /* 420 */ 23, 195, 27, 121, 23, 69, 70, 71, 72, 73,
+ /* 430 */ 74, 75, 76, 77, 78, 79, 80, 81, 99, 83,
+ /* 440 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 450 */ 19, 12, 95, 96, 23, 226, 101, 22, 217, 19,
+ /* 460 */ 61, 151, 63, 222, 151, 106, 107, 108, 29, 159,
+ /* 470 */ 244, 151, 99, 163, 164, 23, 113, 167, 115, 116,
+ /* 480 */ 167, 50, 51, 110, 45, 58, 47, 167, 175, 176,
+ /* 490 */ 95, 51, 168, 137, 139, 175, 176, 58, 11, 22,
+ /* 500 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 510 */ 79, 80, 81, 22, 83, 84, 85, 86, 87, 88,
+ /* 520 */ 89, 90, 91, 92, 93, 19, 23, 151, 117, 23,
+ /* 530 */ 217, 207, 19, 106, 107, 108, 216, 151, 139, 23,
+ /* 540 */ 129, 28, 26, 167, 117, 105, 23, 223, 224, 225,
+ /* 550 */ 110, 175, 176, 167, 77, 165, 50, 51, 168, 169,
+ /* 560 */ 170, 175, 176, 87, 88, 113, 26, 115, 116, 171,
+ /* 570 */ 172, 173, 0, 1, 2, 69, 70, 71, 72, 73,
+ /* 580 */ 74, 75, 76, 77, 78, 79, 80, 81, 162, 83,
+ /* 590 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 600 */ 19, 151, 98, 217, 23, 37, 130, 131, 23, 23,
+ /* 610 */ 26, 26, 96, 163, 164, 23, 113, 167, 115, 116,
+ /* 620 */ 52, 117, 196, 151, 171, 172, 173, 59, 130, 131,
+ /* 630 */ 232, 50, 51, 129, 208, 209, 16, 121, 156, 167,
+ /* 640 */ 22, 23, 162, 223, 224, 225, 51, 175, 176, 121,
+ /* 650 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 660 */ 79, 80, 81, 178, 83, 84, 85, 86, 87, 88,
+ /* 670 */ 89, 90, 91, 92, 93, 19, 196, 109, 151, 23,
+ /* 680 */ 96, 61, 151, 63, 23, 232, 68, 26, 151, 168,
+ /* 690 */ 169, 170, 23, 89, 167, 26, 208, 209, 167, 219,
+ /* 700 */ 105, 36, 175, 176, 167, 121, 50, 51, 223, 224,
+ /* 710 */ 225, 229, 175, 176, 178, 233, 247, 248, 114, 239,
+ /* 720 */ 189, 22, 118, 24, 162, 69, 70, 71, 72, 73,
+ /* 730 */ 74, 75, 76, 77, 78, 79, 80, 81, 151, 83,
+ /* 740 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 750 */ 19, 151, 26, 151, 167, 24, 145, 146, 196, 223,
+ /* 760 */ 224, 225, 175, 176, 151, 182, 183, 167, 151, 167,
+ /* 770 */ 151, 36, 199, 190, 151, 175, 176, 175, 176, 206,
+ /* 780 */ 167, 50, 51, 221, 167, 136, 167, 138, 175, 176,
+ /* 790 */ 167, 26, 175, 176, 175, 176, 168, 36, 175, 176,
+ /* 800 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 810 */ 79, 80, 81, 151, 83, 84, 85, 86, 87, 88,
+ /* 820 */ 89, 90, 91, 92, 93, 19, 151, 151, 151, 167,
+ /* 830 */ 151, 151, 151, 151, 162, 207, 23, 175, 176, 26,
+ /* 840 */ 249, 250, 167, 167, 167, 151, 167, 167, 167, 167,
+ /* 850 */ 175, 176, 175, 176, 175, 176, 50, 51, 151, 53,
+ /* 860 */ 22, 167, 192, 193, 33, 189, 192, 193, 196, 189,
+ /* 870 */ 189, 189, 162, 42, 167, 69, 70, 71, 72, 73,
+ /* 880 */ 74, 75, 76, 77, 78, 79, 80, 81, 151, 83,
+ /* 890 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 900 */ 19, 151, 195, 151, 167, 151, 196, 162, 151, 215,
+ /* 910 */ 92, 93, 175, 176, 28, 174, 119, 167, 151, 167,
+ /* 920 */ 151, 167, 151, 182, 167, 175, 176, 175, 176, 175,
+ /* 930 */ 176, 50, 51, 23, 167, 23, 167, 40, 167, 22,
+ /* 940 */ 167, 196, 53, 168, 175, 176, 175, 176, 175, 162,
+ /* 950 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 960 */ 79, 80, 81, 151, 83, 84, 85, 86, 87, 88,
+ /* 970 */ 89, 90, 91, 92, 93, 19, 151, 151, 151, 167,
+ /* 980 */ 151, 151, 207, 196, 30, 218, 22, 175, 176, 1,
+ /* 990 */ 2, 53, 167, 167, 167, 151, 167, 167, 151, 151,
+ /* 1000 */ 175, 176, 175, 176, 175, 176, 50, 51, 221, 23,
+ /* 1010 */ 53, 167, 22, 22, 167, 167, 103, 168, 22, 110,
+ /* 1020 */ 19, 105, 175, 176, 20, 69, 70, 71, 72, 73,
+ /* 1030 */ 74, 75, 76, 77, 78, 79, 80, 81, 151, 83,
+ /* 1040 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 1050 */ 19, 151, 151, 151, 167, 151, 207, 24, 44, 215,
+ /* 1060 */ 60, 26, 175, 176, 54, 54, 240, 167, 167, 167,
+ /* 1070 */ 240, 167, 151, 151, 151, 175, 176, 175, 176, 175,
+ /* 1080 */ 176, 50, 51, 139, 151, 22, 105, 119, 167, 167,
+ /* 1090 */ 167, 5, 1, 36, 28, 77, 175, 176, 175, 176,
+ /* 1100 */ 167, 70, 71, 72, 73, 74, 75, 76, 77, 78,
+ /* 1110 */ 79, 80, 81, 151, 83, 84, 85, 86, 87, 88,
+ /* 1120 */ 89, 90, 91, 92, 93, 19, 151, 151, 151, 167,
+ /* 1130 */ 151, 151, 109, 151, 128, 77, 22, 175, 176, 26,
+ /* 1140 */ 218, 240, 167, 167, 167, 151, 167, 167, 151, 167,
+ /* 1150 */ 175, 176, 175, 176, 175, 176, 50, 51, 151, 22,
+ /* 1160 */ 151, 167, 23, 120, 167, 1, 16, 122, 20, 120,
+ /* 1170 */ 109, 195, 175, 176, 167, 195, 167, 71, 72, 73,
+ /* 1180 */ 74, 75, 76, 77, 78, 79, 80, 81, 151, 83,
+ /* 1190 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ /* 1200 */ 19, 20, 195, 22, 167, 151, 151, 128, 27, 28,
+ /* 1210 */ 129, 23, 175, 176, 23, 66, 141, 22, 151, 38,
+ /* 1220 */ 151, 167, 167, 19, 20, 151, 22, 151, 151, 175,
+ /* 1230 */ 176, 27, 28, 151, 167, 15, 167, 4, 57, 16,
+ /* 1240 */ 151, 167, 38, 167, 167, 3, 166, 248, 67, 167,
+ /* 1250 */ 195, 175, 176, 181, 181, 150, 167, 175, 176, 251,
+ /* 1260 */ 6, 57, 151, 151, 175, 176, 151, 151, 87, 88,
+ /* 1270 */ 89, 67, 151, 162, 151, 94, 95, 96, 167, 167,
+ /* 1280 */ 99, 251, 167, 167, 152, 151, 175, 176, 167, 151,
+ /* 1290 */ 167, 87, 88, 151, 150, 150, 175, 176, 94, 95,
+ /* 1300 */ 96, 167, 150, 99, 151, 167, 151, 196, 13, 167,
+ /* 1310 */ 195, 130, 131, 132, 133, 134, 135, 152, 195, 160,
+ /* 1320 */ 167, 117, 167, 19, 20, 151, 22, 151, 217, 151,
+ /* 1330 */ 161, 27, 28, 222, 130, 131, 132, 133, 134, 135,
+ /* 1340 */ 151, 167, 38, 167, 151, 167, 19, 20, 195, 22,
+ /* 1350 */ 151, 151, 151, 151, 27, 28, 167, 151, 151, 26,
+ /* 1360 */ 167, 57, 25, 196, 151, 38, 167, 167, 167, 167,
+ /* 1370 */ 151, 67, 151, 167, 167, 117, 201, 151, 125, 151,
+ /* 1380 */ 167, 151, 127, 124, 57, 151, 167, 202, 167, 203,
+ /* 1390 */ 151, 87, 88, 167, 67, 167, 151, 167, 94, 95,
+ /* 1400 */ 96, 167, 151, 99, 123, 126, 167, 204, 136, 227,
+ /* 1410 */ 205, 119, 167, 105, 87, 88, 122, 177, 167, 158,
+ /* 1420 */ 158, 94, 95, 96, 212, 105, 99, 213, 212, 177,
+ /* 1430 */ 213, 213, 185, 48, 130, 131, 132, 133, 134, 135,
+ /* 1440 */ 5, 212, 177, 179, 104, 10, 11, 12, 13, 14,
+ /* 1450 */ 177, 180, 17, 22, 230, 93, 180, 130, 131, 132,
+ /* 1460 */ 133, 134, 135, 185, 177, 230, 177, 32, 177, 34,
+ /* 1470 */ 157, 22, 18, 158, 157, 157, 27, 28, 43, 158,
+ /* 1480 */ 158, 158, 46, 237, 136, 157, 238, 158, 191, 201,
+ /* 1490 */ 69, 56, 191, 58, 220, 22, 157, 62, 18, 201,
+ /* 1500 */ 65, 158, 220, 194, 194, 194, 194, 201, 158, 242,
+ /* 1510 */ 191, 41, 242, 158, 158, 39, 67, 154, 232, 168,
+ /* 1520 */ 245, 228, 198, 178, 183, 200, 168, 211, 232, 168,
+ /* 1530 */ 178, 178, 201, 187, 198, 149, 87, 88, 179, 168,
+ /* 1540 */ 241, 106, 107, 108, 95, 211, 241, 112, 99, 211,
+ /* 1550 */ 201, 197, 117, 193, 210, 188, 184, 184, 184, 175,
+ /* 1560 */ 93, 235, 175, 252, 252, 252, 236, 252, 252, 252,
+ /* 1570 */ 252, 252, 252, 252, 252, 140, 252, 252, 252, 130,
+ /* 1580 */ 131, 132,
};
-#define YY_SHIFT_USE_DFLT (-70)
-#define YY_SHIFT_COUNT (416)
-#define YY_SHIFT_MIN (-69)
-#define YY_SHIFT_MAX (1487)
+#define YY_SHIFT_USE_DFLT (-82)
+#define YY_SHIFT_COUNT (419)
+#define YY_SHIFT_MIN (-81)
+#define YY_SHIFT_MAX (1480)
static const short yy_shift_ofst[] = {
- /* 0 */ 1143, 1188, 1417, 1188, 1287, 1287, 138, 138, -2, -19,
- /* 10 */ 1287, 1287, 1287, 1287, 347, 362, 129, 129, 795, 1165,
- /* 20 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
- /* 30 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
- /* 40 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287,
- /* 50 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287,
- /* 60 */ 1287, 1287, 286, 362, 362, 538, 538, 231, 1253, 55,
- /* 70 */ 721, 647, 573, 499, 425, 351, 277, 203, 869, 869,
- /* 80 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869,
- /* 90 */ 869, 869, 869, 943, 869, 1017, 1091, 1091, -69, -45,
- /* 100 */ -45, -45, -45, -45, -1, 24, 245, 362, 362, 362,
- /* 110 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
- /* 120 */ 362, 362, 362, 388, 356, 362, 362, 362, 362, 362,
- /* 130 */ 732, 868, 231, 1051, 1458, -70, -70, -70, 1367, 57,
- /* 140 */ 434, 434, 289, 291, 285, 1, 204, 572, 539, 362,
- /* 150 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
- /* 160 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
- /* 170 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362,
- /* 180 */ 362, 506, 506, 506, 705, 1253, 1253, 1253, -70, -70,
- /* 190 */ -70, 171, 171, 160, 502, 502, 502, 446, 432, 511,
- /* 200 */ 422, 358, 335, -12, -12, -12, -12, 576, 294, -12,
- /* 210 */ -12, 295, 595, 141, 600, 730, 723, 723, 805, 730,
- /* 220 */ 805, 439, 911, 231, 865, 231, 865, 807, 865, 723,
- /* 230 */ 766, 633, 633, 231, 284, 63, 608, 1476, 1308, 1308,
- /* 240 */ 1472, 1472, 1308, 1477, 1425, 1275, 1487, 1487, 1487, 1487,
- /* 250 */ 1308, 1461, 1275, 1477, 1425, 1425, 1308, 1461, 1355, 1441,
- /* 260 */ 1308, 1308, 1461, 1308, 1461, 1308, 1461, 1442, 1348, 1348,
- /* 270 */ 1348, 1408, 1375, 1375, 1442, 1348, 1357, 1348, 1408, 1348,
- /* 280 */ 1348, 1316, 1331, 1316, 1331, 1316, 1331, 1308, 1308, 1280,
- /* 290 */ 1288, 1289, 1285, 1279, 1275, 1253, 1336, 1346, 1346, 1338,
- /* 300 */ 1338, 1338, 1338, -70, -70, -70, -70, -70, -70, 1013,
- /* 310 */ 467, 612, 84, 179, -28, 870, 410, 761, 760, 667,
- /* 320 */ 650, 531, 220, 361, 331, 125, 127, 97, 1306, 1300,
- /* 330 */ 1270, 1151, 1272, 1203, 1232, 1261, 1244, 1148, 1174, 1139,
- /* 340 */ 1156, 1124, 1220, 1115, 1210, 1233, 1099, 1193, 1184, 1174,
- /* 350 */ 1173, 1029, 1121, 1120, 1085, 1162, 1119, 1037, 1152, 1147,
- /* 360 */ 1129, 1046, 1011, 1093, 1098, 1075, 1061, 1032, 960, 1057,
- /* 370 */ 1031, 1030, 899, 938, 982, 936, 972, 958, 910, 955,
- /* 380 */ 875, 885, 908, 857, 859, 867, 804, 590, 834, 747,
- /* 390 */ 818, 513, 611, 741, 673, 637, 611, 606, 603, 579,
- /* 400 */ 501, 541, 468, 386, 445, 395, 376, 281, 185, 120,
- /* 410 */ 92, 75, 45, 114, 25, 11, 5,
+ /* 0 */ 988, 1204, 1435, 1204, 1304, 1304, 67, 67, 1, -19,
+ /* 10 */ 1304, 1304, 1304, 1304, 427, 81, 131, 131, 806, 1181,
+ /* 20 */ 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304,
+ /* 30 */ 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304,
+ /* 40 */ 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1327, 1304,
+ /* 50 */ 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304, 1304,
+ /* 60 */ 1304, 1304, 52, 81, 81, 476, 476, 395, 1258, 56,
+ /* 70 */ 731, 656, 581, 506, 431, 356, 281, 206, 881, 881,
+ /* 80 */ 881, 881, 881, 881, 881, 881, 881, 881, 881, 881,
+ /* 90 */ 881, 881, 881, 956, 881, 1031, 1106, 1106, -69, -45,
+ /* 100 */ -45, -45, -45, -45, 0, 29, -12, 81, 81, 81,
+ /* 110 */ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ /* 120 */ 81, 81, 81, 355, 440, 81, 81, 81, 81, 81,
+ /* 130 */ 504, 411, 395, 818, 1467, -82, -82, -82, 1449, 86,
+ /* 140 */ 439, 439, 306, 357, 302, 72, 318, 246, 169, 81,
+ /* 150 */ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ /* 160 */ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ /* 170 */ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ /* 180 */ 81, 81, 315, 315, 315, 572, 1258, 1258, 1258, -82,
+ /* 190 */ -82, -82, 132, 132, 208, 568, 568, 568, 516, 503,
+ /* 200 */ 214, 452, 363, 228, 119, 119, 119, 119, 359, 126,
+ /* 210 */ 119, 119, 584, 293, 604, 106, 11, 288, 288, 513,
+ /* 220 */ 11, 513, 295, 813, 395, 831, 395, 831, 595, 831,
+ /* 230 */ 288, 649, 498, 498, 395, 154, 273, 699, 1476, 1292,
+ /* 240 */ 1292, 1470, 1470, 1292, 1473, 1421, 1255, 1480, 1480, 1480,
+ /* 250 */ 1480, 1292, 1454, 1255, 1473, 1421, 1421, 1255, 1292, 1454,
+ /* 260 */ 1348, 1436, 1292, 1292, 1454, 1292, 1454, 1292, 1454, 1431,
+ /* 270 */ 1320, 1320, 1320, 1385, 1362, 1362, 1431, 1320, 1340, 1320,
+ /* 280 */ 1385, 1320, 1320, 1294, 1308, 1294, 1308, 1294, 1308, 1292,
+ /* 290 */ 1292, 1272, 1279, 1281, 1253, 1259, 1255, 1258, 1337, 1333,
+ /* 300 */ 1295, 1295, 1254, 1254, 1254, 1254, -82, -82, -82, -82,
+ /* 310 */ -82, -82, 339, 399, 618, 326, 620, -81, 669, 477,
+ /* 320 */ 661, 585, 377, 280, 244, 232, 25, -1, 373, 227,
+ /* 330 */ 215, 1233, 1242, 1195, 1075, 1220, 1149, 1223, 1191, 1188,
+ /* 340 */ 1081, 1113, 1079, 1061, 1049, 1148, 1045, 1150, 1164, 1043,
+ /* 350 */ 1139, 1137, 1113, 1114, 1006, 1058, 1018, 1023, 1066, 1057,
+ /* 360 */ 968, 1091, 1086, 1063, 981, 944, 1011, 1035, 1010, 1000,
+ /* 370 */ 1014, 916, 1033, 1004, 1001, 909, 913, 996, 957, 991,
+ /* 380 */ 990, 986, 964, 938, 954, 917, 889, 897, 912, 910,
+ /* 390 */ 797, 886, 761, 838, 528, 726, 735, 765, 665, 726,
+ /* 400 */ 592, 586, 540, 523, 491, 487, 435, 401, 397, 387,
+ /* 410 */ 249, 216, 185, 127, 110, 51, 82, 143, 15, 48,
};
-#define YY_REDUCE_USE_DFLT (-169)
-#define YY_REDUCE_COUNT (308)
-#define YY_REDUCE_MIN (-168)
-#define YY_REDUCE_MAX (1391)
+#define YY_REDUCE_USE_DFLT (-143)
+#define YY_REDUCE_COUNT (311)
+#define YY_REDUCE_MIN (-142)
+#define YY_REDUCE_MAX (1387)
static const short yy_reduce_ofst[] = {
- /* 0 */ -141, 90, 1095, 222, 158, 156, 19, 17, 10, -104,
- /* 10 */ 378, 316, 311, 12, 180, 249, 598, 464, 397, 1181,
- /* 20 */ 1177, 1175, 1128, 1106, 1096, 1054, 1038, 974, 964, 962,
- /* 30 */ 948, 905, 903, 900, 887, 874, 832, 826, 816, 813,
- /* 40 */ 800, 758, 755, 752, 742, 739, 726, 685, 681, 668,
- /* 50 */ 665, 652, 607, 604, 594, 591, 578, 530, 528, 526,
- /* 60 */ 385, 18, 477, 466, 519, 444, 350, 435, 405, 488,
- /* 70 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488,
- /* 80 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488,
- /* 90 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488,
- /* 100 */ 488, 488, 488, 488, 488, 488, 488, 1040, 678, 1036,
- /* 110 */ 1007, 967, 966, 965, 845, 686, 610, 684, 317, 672,
- /* 120 */ 893, 327, 623, 522, -7, 820, 814, 157, 154, 101,
- /* 130 */ 702, 494, 580, 488, 488, 488, 488, 488, 614, 586,
- /* 140 */ 935, 892, 968, 1245, 1242, 1234, 1225, 798, 798, 1222,
- /* 150 */ 1221, 1218, 1214, 1213, 1212, 1202, 1195, 1191, 1161, 1158,
- /* 160 */ 1140, 1135, 1123, 1112, 1107, 1100, 1080, 1074, 1073, 1072,
- /* 170 */ 1070, 1067, 1048, 1044, 969, 968, 907, 906, 904, 894,
- /* 180 */ 833, 837, 836, 340, 827, 815, 775, 68, 722, 646,
- /* 190 */ -168, 1384, 1380, 1377, 1379, 1376, 1373, 1339, 1365, 1368,
- /* 200 */ 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1320, 1319, 1365,
- /* 210 */ 1365, 1339, 1378, 1349, 1391, 1350, 1342, 1334, 1307, 1341,
- /* 220 */ 1293, 1364, 1363, 1371, 1362, 1370, 1359, 1340, 1354, 1333,
- /* 230 */ 1305, 1304, 1299, 1361, 1328, 1324, 1366, 1282, 1360, 1358,
- /* 240 */ 1278, 1276, 1356, 1292, 1322, 1309, 1317, 1315, 1314, 1312,
- /* 250 */ 1345, 1347, 1302, 1277, 1311, 1303, 1337, 1335, 1252, 1248,
- /* 260 */ 1332, 1330, 1329, 1327, 1326, 1323, 1321, 1297, 1301, 1295,
- /* 270 */ 1294, 1290, 1243, 1240, 1284, 1291, 1286, 1283, 1274, 1281,
- /* 280 */ 1271, 1238, 1241, 1236, 1235, 1227, 1226, 1267, 1266, 1189,
- /* 290 */ 1229, 1223, 1211, 1206, 1201, 1197, 1239, 1237, 1219, 1216,
- /* 300 */ 1209, 1208, 1185, 1089, 1086, 1087, 1137, 1136, 1164,
+ /* 0 */ -142, 1111, 92, 151, 241, 161, 150, 93, 85, 324,
+ /* 10 */ 386, 313, 320, 229, -6, 310, 536, 485, -72, 1121,
+ /* 20 */ 1089, 1082, 1076, 1054, 1037, 997, 979, 977, 975, 962,
+ /* 30 */ 923, 921, 904, 902, 900, 887, 847, 829, 827, 825,
+ /* 40 */ 812, 771, 769, 754, 752, 750, 737, 679, 677, 675,
+ /* 50 */ 662, 623, 619, 617, 613, 602, 600, 587, 537, 527,
+ /* 60 */ 472, 376, 480, 450, 226, 453, 398, 390, 426, 420,
+ /* 70 */ 420, 420, 420, 420, 420, 420, 420, 420, 420, 420,
+ /* 80 */ 420, 420, 420, 420, 420, 420, 420, 420, 420, 420,
+ /* 90 */ 420, 420, 420, 420, 420, 420, 420, 420, 420, 420,
+ /* 100 */ 420, 420, 420, 420, 420, 420, 420, 1153, 922, 1123,
+ /* 110 */ 1115, 1055, 1007, 980, 976, 901, 844, 830, 767, 826,
+ /* 120 */ 682, 694, 707, 482, 583, 681, 680, 676, 531, 27,
+ /* 130 */ 787, 562, 521, 420, 420, 420, 420, 420, 773, 741,
+ /* 140 */ 674, 670, 1067, 1251, 1245, 1239, 1234, 591, 591, 1230,
+ /* 150 */ 1228, 1226, 1221, 1219, 1213, 1207, 1206, 1202, 1201, 1200,
+ /* 160 */ 1199, 1193, 1189, 1178, 1176, 1174, 1155, 1142, 1138, 1134,
+ /* 170 */ 1116, 1112, 1077, 1074, 1069, 1067, 1009, 994, 982, 933,
+ /* 180 */ 848, 757, 849, 775, 628, 611, 745, 710, 672, 469,
+ /* 190 */ 488, 573, 1387, 1384, 1367, 1374, 1373, 1372, 1344, 1354,
+ /* 200 */ 1360, 1354, 1354, 1354, 1354, 1354, 1354, 1354, 1330, 1326,
+ /* 210 */ 1354, 1354, 1344, 1371, 1336, 1386, 1349, 1338, 1334, 1305,
+ /* 220 */ 1331, 1299, 1359, 1346, 1361, 1353, 1358, 1352, 1341, 1345,
+ /* 230 */ 1316, 1293, 1296, 1286, 1351, 1325, 1324, 1363, 1275, 1356,
+ /* 240 */ 1355, 1270, 1267, 1350, 1282, 1319, 1306, 1312, 1311, 1310,
+ /* 250 */ 1309, 1343, 1339, 1298, 1274, 1301, 1297, 1288, 1329, 1328,
+ /* 260 */ 1248, 1246, 1323, 1322, 1318, 1321, 1317, 1315, 1313, 1276,
+ /* 270 */ 1291, 1289, 1287, 1278, 1235, 1224, 1271, 1273, 1264, 1265,
+ /* 280 */ 1247, 1252, 1240, 1218, 1229, 1217, 1216, 1214, 1212, 1262,
+ /* 290 */ 1261, 1182, 1205, 1203, 1186, 1185, 1175, 1167, 1169, 1159,
+ /* 300 */ 1165, 1132, 1152, 1145, 1144, 1105, 1030, 1008, 999, 1073,
+ /* 310 */ 1072, 1080,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 632, 866, 954, 954, 866, 866, 954, 954, 954, 756,
- /* 10 */ 954, 954, 954, 864, 954, 954, 784, 784, 928, 954,
- /* 20 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 30 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 40 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 50 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 60 */ 954, 954, 954, 954, 954, 954, 954, 671, 760, 790,
- /* 70 */ 954, 954, 954, 954, 954, 954, 954, 954, 927, 929,
- /* 80 */ 798, 797, 907, 771, 795, 788, 792, 867, 860, 861,
- /* 90 */ 859, 863, 868, 954, 791, 827, 844, 826, 838, 843,
- /* 100 */ 850, 842, 839, 829, 828, 830, 831, 954, 954, 954,
- /* 110 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 120 */ 954, 954, 954, 658, 725, 954, 954, 954, 954, 954,
- /* 130 */ 954, 954, 954, 832, 833, 847, 846, 845, 954, 663,
- /* 140 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 150 */ 934, 932, 954, 879, 954, 954, 954, 954, 954, 954,
- /* 160 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 170 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 180 */ 638, 756, 756, 756, 632, 954, 954, 954, 946, 760,
- /* 190 */ 750, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 200 */ 954, 954, 954, 800, 739, 917, 919, 954, 900, 737,
- /* 210 */ 660, 758, 673, 748, 640, 794, 773, 773, 912, 794,
- /* 220 */ 912, 696, 719, 954, 784, 954, 784, 693, 784, 773,
- /* 230 */ 862, 954, 954, 954, 757, 748, 954, 939, 764, 764,
- /* 240 */ 931, 931, 764, 806, 729, 794, 736, 736, 736, 736,
- /* 250 */ 764, 655, 794, 806, 729, 729, 764, 655, 906, 904,
- /* 260 */ 764, 764, 655, 764, 655, 764, 655, 872, 727, 727,
- /* 270 */ 727, 711, 876, 876, 872, 727, 696, 727, 711, 727,
- /* 280 */ 727, 777, 772, 777, 772, 777, 772, 764, 764, 954,
- /* 290 */ 789, 778, 787, 785, 794, 954, 714, 648, 648, 637,
- /* 300 */ 637, 637, 637, 951, 951, 946, 698, 698, 681, 954,
- /* 310 */ 954, 954, 954, 954, 954, 954, 881, 954, 954, 954,
- /* 320 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 633,
- /* 330 */ 941, 954, 954, 938, 954, 954, 954, 954, 799, 954,
- /* 340 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 916,
- /* 350 */ 954, 954, 954, 954, 954, 954, 954, 910, 954, 954,
- /* 360 */ 954, 954, 954, 954, 903, 902, 954, 954, 954, 954,
- /* 370 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 380 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954,
- /* 390 */ 954, 954, 786, 954, 779, 954, 865, 954, 954, 954,
- /* 400 */ 954, 954, 954, 954, 954, 954, 954, 742, 815, 954,
- /* 410 */ 814, 818, 813, 665, 954, 646, 954, 629, 634, 950,
- /* 420 */ 953, 952, 949, 948, 947, 942, 940, 937, 936, 935,
- /* 430 */ 933, 930, 926, 885, 883, 890, 889, 888, 887, 886,
- /* 440 */ 884, 882, 880, 801, 796, 793, 925, 878, 738, 735,
- /* 450 */ 734, 654, 943, 909, 918, 805, 804, 807, 915, 914,
- /* 460 */ 913, 911, 908, 895, 803, 802, 730, 870, 869, 657,
- /* 470 */ 899, 898, 897, 901, 905, 896, 766, 656, 653, 662,
- /* 480 */ 717, 718, 726, 724, 723, 722, 721, 720, 716, 664,
- /* 490 */ 672, 710, 695, 694, 875, 877, 874, 873, 703, 702,
- /* 500 */ 708, 707, 706, 705, 704, 701, 700, 699, 692, 691,
- /* 510 */ 697, 690, 713, 712, 709, 689, 733, 732, 731, 728,
- /* 520 */ 688, 687, 686, 818, 685, 684, 824, 823, 811, 854,
- /* 530 */ 753, 752, 751, 763, 762, 775, 774, 809, 808, 776,
- /* 540 */ 761, 755, 754, 770, 769, 768, 767, 759, 749, 781,
- /* 550 */ 783, 782, 780, 856, 765, 853, 924, 923, 922, 921,
- /* 560 */ 920, 858, 857, 825, 822, 676, 677, 893, 892, 894,
- /* 570 */ 891, 679, 678, 675, 674, 855, 744, 743, 851, 848,
- /* 580 */ 840, 836, 852, 849, 841, 837, 835, 834, 820, 819,
- /* 590 */ 817, 816, 812, 821, 667, 745, 741, 740, 810, 747,
- /* 600 */ 746, 683, 682, 680, 661, 659, 652, 650, 649, 651,
- /* 610 */ 647, 645, 644, 643, 642, 641, 670, 669, 668, 666,
- /* 620 */ 665, 639, 636, 635, 631, 630, 628,
+ /* 0 */ 636, 872, 960, 960, 872, 872, 960, 960, 960, 762,
+ /* 10 */ 960, 960, 960, 870, 960, 960, 790, 790, 934, 960,
+ /* 20 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 30 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 40 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 50 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 60 */ 960, 960, 960, 960, 960, 960, 960, 677, 766, 796,
+ /* 70 */ 960, 960, 960, 960, 960, 960, 960, 960, 933, 935,
+ /* 80 */ 804, 803, 913, 777, 801, 794, 798, 873, 866, 867,
+ /* 90 */ 865, 869, 874, 960, 797, 833, 850, 832, 844, 849,
+ /* 100 */ 856, 848, 845, 835, 834, 836, 837, 960, 960, 960,
+ /* 110 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 120 */ 960, 960, 960, 662, 731, 960, 960, 960, 960, 960,
+ /* 130 */ 960, 960, 960, 838, 839, 853, 852, 851, 960, 669,
+ /* 140 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 150 */ 940, 938, 960, 885, 960, 960, 960, 960, 960, 960,
+ /* 160 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 170 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 180 */ 960, 642, 762, 762, 762, 636, 960, 960, 960, 952,
+ /* 190 */ 766, 756, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 200 */ 960, 960, 960, 960, 806, 745, 923, 925, 960, 906,
+ /* 210 */ 743, 664, 764, 679, 754, 644, 800, 779, 779, 918,
+ /* 220 */ 800, 918, 702, 725, 960, 790, 960, 790, 699, 790,
+ /* 230 */ 779, 868, 960, 960, 960, 763, 754, 960, 945, 770,
+ /* 240 */ 770, 937, 937, 770, 812, 735, 800, 742, 742, 742,
+ /* 250 */ 742, 770, 659, 800, 812, 735, 735, 800, 770, 659,
+ /* 260 */ 912, 910, 770, 770, 659, 770, 659, 770, 659, 878,
+ /* 270 */ 733, 733, 733, 717, 882, 882, 878, 733, 702, 733,
+ /* 280 */ 717, 733, 733, 783, 778, 783, 778, 783, 778, 770,
+ /* 290 */ 770, 960, 795, 784, 793, 791, 800, 960, 665, 720,
+ /* 300 */ 652, 652, 641, 641, 641, 641, 957, 957, 952, 704,
+ /* 310 */ 704, 687, 960, 960, 960, 960, 960, 960, 960, 887,
+ /* 320 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 330 */ 960, 960, 637, 947, 960, 960, 944, 960, 960, 960,
+ /* 340 */ 960, 805, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 350 */ 960, 960, 922, 960, 960, 960, 960, 960, 960, 960,
+ /* 360 */ 916, 960, 960, 960, 960, 960, 960, 909, 908, 960,
+ /* 370 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 380 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 390 */ 960, 960, 960, 960, 960, 792, 960, 785, 960, 871,
+ /* 400 */ 960, 960, 960, 960, 960, 960, 960, 960, 960, 960,
+ /* 410 */ 748, 821, 960, 820, 824, 819, 671, 960, 650, 960,
+ /* 420 */ 633, 638, 956, 959, 958, 955, 954, 953, 948, 946,
+ /* 430 */ 943, 942, 941, 939, 936, 932, 891, 889, 896, 895,
+ /* 440 */ 894, 893, 892, 890, 888, 886, 807, 802, 799, 931,
+ /* 450 */ 884, 744, 741, 740, 658, 949, 915, 924, 811, 810,
+ /* 460 */ 813, 921, 920, 919, 917, 914, 901, 809, 808, 736,
+ /* 470 */ 876, 875, 661, 905, 904, 903, 907, 911, 902, 772,
+ /* 480 */ 660, 657, 668, 723, 724, 732, 730, 729, 728, 727,
+ /* 490 */ 726, 722, 670, 678, 716, 701, 700, 881, 883, 880,
+ /* 500 */ 879, 709, 708, 714, 713, 712, 711, 710, 707, 706,
+ /* 510 */ 705, 698, 697, 703, 696, 719, 718, 715, 695, 739,
+ /* 520 */ 738, 737, 734, 694, 693, 692, 824, 691, 690, 830,
+ /* 530 */ 829, 817, 860, 759, 758, 757, 769, 768, 781, 780,
+ /* 540 */ 815, 814, 782, 767, 761, 760, 776, 775, 774, 773,
+ /* 550 */ 765, 755, 787, 789, 788, 786, 862, 771, 859, 930,
+ /* 560 */ 929, 928, 927, 926, 864, 863, 831, 828, 682, 683,
+ /* 570 */ 899, 898, 900, 897, 685, 684, 681, 680, 861, 750,
+ /* 580 */ 749, 857, 854, 846, 842, 858, 855, 847, 843, 841,
+ /* 590 */ 840, 826, 825, 823, 822, 818, 827, 673, 751, 747,
+ /* 600 */ 746, 816, 753, 752, 689, 688, 686, 667, 666, 663,
+ /* 610 */ 656, 654, 653, 655, 651, 649, 648, 647, 646, 645,
+ /* 620 */ 676, 675, 674, 672, 671, 643, 640, 639, 635, 634,
+ /* 630 */ 632,
};
/* The next table maps tokens into fallback tokens. If a construct
@@ -110899,71 +115103,72 @@ static const YYACTIONTYPE yy_default[] = {
static const YYCODETYPE yyFallback[] = {
0, /* $ => nothing */
0, /* SEMI => nothing */
- 26, /* EXPLAIN => ID */
- 26, /* QUERY => ID */
- 26, /* PLAN => ID */
- 26, /* BEGIN => ID */
+ 27, /* EXPLAIN => ID */
+ 27, /* QUERY => ID */
+ 27, /* PLAN => ID */
+ 27, /* BEGIN => ID */
0, /* TRANSACTION => nothing */
- 26, /* DEFERRED => ID */
- 26, /* IMMEDIATE => ID */
- 26, /* EXCLUSIVE => ID */
+ 27, /* DEFERRED => ID */
+ 27, /* IMMEDIATE => ID */
+ 27, /* EXCLUSIVE => ID */
0, /* COMMIT => nothing */
- 26, /* END => ID */
- 26, /* ROLLBACK => ID */
- 26, /* SAVEPOINT => ID */
- 26, /* RELEASE => ID */
+ 27, /* END => ID */
+ 27, /* ROLLBACK => ID */
+ 27, /* SAVEPOINT => ID */
+ 27, /* RELEASE => ID */
0, /* TO => nothing */
0, /* TABLE => nothing */
0, /* CREATE => nothing */
- 26, /* IF => ID */
+ 27, /* IF => ID */
0, /* NOT => nothing */
0, /* EXISTS => nothing */
- 26, /* TEMP => ID */
+ 27, /* TEMP => ID */
0, /* LP => nothing */
0, /* RP => nothing */
0, /* AS => nothing */
+ 27, /* WITHOUT => ID */
0, /* COMMA => nothing */
0, /* ID => nothing */
0, /* INDEXED => nothing */
- 26, /* ABORT => ID */
- 26, /* ACTION => ID */
- 26, /* AFTER => ID */
- 26, /* ANALYZE => ID */
- 26, /* ASC => ID */
- 26, /* ATTACH => ID */
- 26, /* BEFORE => ID */
- 26, /* BY => ID */
- 26, /* CASCADE => ID */
- 26, /* CAST => ID */
- 26, /* COLUMNKW => ID */
- 26, /* CONFLICT => ID */
- 26, /* DATABASE => ID */
- 26, /* DESC => ID */
- 26, /* DETACH => ID */
- 26, /* EACH => ID */
- 26, /* FAIL => ID */
- 26, /* FOR => ID */
- 26, /* IGNORE => ID */
- 26, /* INITIALLY => ID */
- 26, /* INSTEAD => ID */
- 26, /* LIKE_KW => ID */
- 26, /* MATCH => ID */
- 26, /* NO => ID */
- 26, /* KEY => ID */
- 26, /* OF => ID */
- 26, /* OFFSET => ID */
- 26, /* PRAGMA => ID */
- 26, /* RAISE => ID */
- 26, /* REPLACE => ID */
- 26, /* RESTRICT => ID */
- 26, /* ROW => ID */
- 26, /* TRIGGER => ID */
- 26, /* VACUUM => ID */
- 26, /* VIEW => ID */
- 26, /* VIRTUAL => ID */
- 26, /* REINDEX => ID */
- 26, /* RENAME => ID */
- 26, /* CTIME_KW => ID */
+ 27, /* ABORT => ID */
+ 27, /* ACTION => ID */
+ 27, /* AFTER => ID */
+ 27, /* ANALYZE => ID */
+ 27, /* ASC => ID */
+ 27, /* ATTACH => ID */
+ 27, /* BEFORE => ID */
+ 27, /* BY => ID */
+ 27, /* CASCADE => ID */
+ 27, /* CAST => ID */
+ 27, /* COLUMNKW => ID */
+ 27, /* CONFLICT => ID */
+ 27, /* DATABASE => ID */
+ 27, /* DESC => ID */
+ 27, /* DETACH => ID */
+ 27, /* EACH => ID */
+ 27, /* FAIL => ID */
+ 27, /* FOR => ID */
+ 27, /* IGNORE => ID */
+ 27, /* INITIALLY => ID */
+ 27, /* INSTEAD => ID */
+ 27, /* LIKE_KW => ID */
+ 27, /* MATCH => ID */
+ 27, /* NO => ID */
+ 27, /* KEY => ID */
+ 27, /* OF => ID */
+ 27, /* OFFSET => ID */
+ 27, /* PRAGMA => ID */
+ 27, /* RAISE => ID */
+ 27, /* REPLACE => ID */
+ 27, /* RESTRICT => ID */
+ 27, /* ROW => ID */
+ 27, /* TRIGGER => ID */
+ 27, /* VACUUM => ID */
+ 27, /* VIEW => ID */
+ 27, /* VIRTUAL => ID */
+ 27, /* REINDEX => ID */
+ 27, /* RENAME => ID */
+ 27, /* CTIME_KW => ID */
};
#endif /* YYFALLBACK */
@@ -111048,63 +115253,63 @@ static const char *const yyTokenName[] = {
"ROLLBACK", "SAVEPOINT", "RELEASE", "TO",
"TABLE", "CREATE", "IF", "NOT",
"EXISTS", "TEMP", "LP", "RP",
- "AS", "COMMA", "ID", "INDEXED",
- "ABORT", "ACTION", "AFTER", "ANALYZE",
- "ASC", "ATTACH", "BEFORE", "BY",
- "CASCADE", "CAST", "COLUMNKW", "CONFLICT",
- "DATABASE", "DESC", "DETACH", "EACH",
- "FAIL", "FOR", "IGNORE", "INITIALLY",
- "INSTEAD", "LIKE_KW", "MATCH", "NO",
- "KEY", "OF", "OFFSET", "PRAGMA",
- "RAISE", "REPLACE", "RESTRICT", "ROW",
- "TRIGGER", "VACUUM", "VIEW", "VIRTUAL",
- "REINDEX", "RENAME", "CTIME_KW", "ANY",
- "OR", "AND", "IS", "BETWEEN",
- "IN", "ISNULL", "NOTNULL", "NE",
- "EQ", "GT", "LE", "LT",
- "GE", "ESCAPE", "BITAND", "BITOR",
- "LSHIFT", "RSHIFT", "PLUS", "MINUS",
- "STAR", "SLASH", "REM", "CONCAT",
- "COLLATE", "BITNOT", "STRING", "JOIN_KW",
- "CONSTRAINT", "DEFAULT", "NULL", "PRIMARY",
- "UNIQUE", "CHECK", "REFERENCES", "AUTOINCR",
- "ON", "INSERT", "DELETE", "UPDATE",
- "SET", "DEFERRABLE", "FOREIGN", "DROP",
- "UNION", "ALL", "EXCEPT", "INTERSECT",
- "SELECT", "DISTINCT", "DOT", "FROM",
- "JOIN", "USING", "ORDER", "GROUP",
- "HAVING", "LIMIT", "WHERE", "INTO",
- "VALUES", "INTEGER", "FLOAT", "BLOB",
- "REGISTER", "VARIABLE", "CASE", "WHEN",
- "THEN", "ELSE", "INDEX", "ALTER",
- "ADD", "error", "input", "cmdlist",
- "ecmd", "explain", "cmdx", "cmd",
- "transtype", "trans_opt", "nm", "savepoint_opt",
- "create_table", "create_table_args", "createkw", "temp",
- "ifnotexists", "dbnm", "columnlist", "conslist_opt",
- "select", "column", "columnid", "type",
- "carglist", "id", "ids", "typetoken",
- "typename", "signed", "plus_num", "minus_num",
- "ccons", "term", "expr", "onconf",
- "sortorder", "autoinc", "idxlist_opt", "refargs",
- "defer_subclause", "refarg", "refact", "init_deferred_pred_opt",
- "conslist", "tconscomma", "tcons", "idxlist",
- "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
- "ifexists", "fullname", "oneselect", "multiselect_op",
- "distinct", "selcollist", "from", "where_opt",
- "groupby_opt", "having_opt", "orderby_opt", "limit_opt",
- "sclp", "as", "seltablist", "stl_prefix",
- "joinop", "indexed_opt", "on_opt", "using_opt",
- "joinop2", "inscollist", "sortlist", "nexprlist",
- "setlist", "insert_cmd", "inscollist_opt", "valuelist",
- "exprlist", "likeop", "between_op", "in_op",
- "case_operand", "case_exprlist", "case_else", "uniqueflag",
- "collate", "nmnum", "number", "trigger_decl",
- "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
- "when_clause", "trigger_cmd", "trnm", "tridxby",
- "database_kw_opt", "key_opt", "add_column_fullname", "kwcolumn_opt",
- "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken",
- "lp", "anylist",
+ "AS", "WITHOUT", "COMMA", "ID",
+ "INDEXED", "ABORT", "ACTION", "AFTER",
+ "ANALYZE", "ASC", "ATTACH", "BEFORE",
+ "BY", "CASCADE", "CAST", "COLUMNKW",
+ "CONFLICT", "DATABASE", "DESC", "DETACH",
+ "EACH", "FAIL", "FOR", "IGNORE",
+ "INITIALLY", "INSTEAD", "LIKE_KW", "MATCH",
+ "NO", "KEY", "OF", "OFFSET",
+ "PRAGMA", "RAISE", "REPLACE", "RESTRICT",
+ "ROW", "TRIGGER", "VACUUM", "VIEW",
+ "VIRTUAL", "REINDEX", "RENAME", "CTIME_KW",
+ "ANY", "OR", "AND", "IS",
+ "BETWEEN", "IN", "ISNULL", "NOTNULL",
+ "NE", "EQ", "GT", "LE",
+ "LT", "GE", "ESCAPE", "BITAND",
+ "BITOR", "LSHIFT", "RSHIFT", "PLUS",
+ "MINUS", "STAR", "SLASH", "REM",
+ "CONCAT", "COLLATE", "BITNOT", "STRING",
+ "JOIN_KW", "CONSTRAINT", "DEFAULT", "NULL",
+ "PRIMARY", "UNIQUE", "CHECK", "REFERENCES",
+ "AUTOINCR", "ON", "INSERT", "DELETE",
+ "UPDATE", "SET", "DEFERRABLE", "FOREIGN",
+ "DROP", "UNION", "ALL", "EXCEPT",
+ "INTERSECT", "SELECT", "DISTINCT", "DOT",
+ "FROM", "JOIN", "USING", "ORDER",
+ "GROUP", "HAVING", "LIMIT", "WHERE",
+ "INTO", "VALUES", "INTEGER", "FLOAT",
+ "BLOB", "REGISTER", "VARIABLE", "CASE",
+ "WHEN", "THEN", "ELSE", "INDEX",
+ "ALTER", "ADD", "error", "input",
+ "cmdlist", "ecmd", "explain", "cmdx",
+ "cmd", "transtype", "trans_opt", "nm",
+ "savepoint_opt", "create_table", "create_table_args", "createkw",
+ "temp", "ifnotexists", "dbnm", "columnlist",
+ "conslist_opt", "table_options", "select", "column",
+ "columnid", "type", "carglist", "id",
+ "ids", "typetoken", "typename", "signed",
+ "plus_num", "minus_num", "ccons", "term",
+ "expr", "onconf", "sortorder", "autoinc",
+ "idxlist_opt", "refargs", "defer_subclause", "refarg",
+ "refact", "init_deferred_pred_opt", "conslist", "tconscomma",
+ "tcons", "idxlist", "defer_subclause_opt", "orconf",
+ "resolvetype", "raisetype", "ifexists", "fullname",
+ "oneselect", "multiselect_op", "distinct", "selcollist",
+ "from", "where_opt", "groupby_opt", "having_opt",
+ "orderby_opt", "limit_opt", "sclp", "as",
+ "seltablist", "stl_prefix", "joinop", "indexed_opt",
+ "on_opt", "using_opt", "joinop2", "idlist",
+ "sortlist", "nexprlist", "setlist", "insert_cmd",
+ "inscollist_opt", "valuelist", "exprlist", "likeop",
+ "between_op", "in_op", "case_operand", "case_exprlist",
+ "case_else", "uniqueflag", "collate", "nmnum",
+ "number", "trigger_decl", "trigger_cmd_list", "trigger_time",
+ "trigger_event", "foreach_clause", "when_clause", "trigger_cmd",
+ "trnm", "tridxby", "database_kw_opt", "key_opt",
+ "add_column_fullname", "kwcolumn_opt", "create_vtab", "vtabarglist",
+ "vtabarg", "vtabargtoken", "lp", "anylist",
};
#endif /* NDEBUG */
@@ -111144,301 +115349,303 @@ static const char *const yyRuleName[] = {
/* 29 */ "ifnotexists ::= IF NOT EXISTS",
/* 30 */ "temp ::= TEMP",
/* 31 */ "temp ::=",
- /* 32 */ "create_table_args ::= LP columnlist conslist_opt RP",
+ /* 32 */ "create_table_args ::= LP columnlist conslist_opt RP table_options",
/* 33 */ "create_table_args ::= AS select",
- /* 34 */ "columnlist ::= columnlist COMMA column",
- /* 35 */ "columnlist ::= column",
- /* 36 */ "column ::= columnid type carglist",
- /* 37 */ "columnid ::= nm",
- /* 38 */ "id ::= ID",
- /* 39 */ "id ::= INDEXED",
- /* 40 */ "ids ::= ID|STRING",
- /* 41 */ "nm ::= id",
- /* 42 */ "nm ::= STRING",
- /* 43 */ "nm ::= JOIN_KW",
- /* 44 */ "type ::=",
- /* 45 */ "type ::= typetoken",
- /* 46 */ "typetoken ::= typename",
- /* 47 */ "typetoken ::= typename LP signed RP",
- /* 48 */ "typetoken ::= typename LP signed COMMA signed RP",
- /* 49 */ "typename ::= ids",
- /* 50 */ "typename ::= typename ids",
- /* 51 */ "signed ::= plus_num",
- /* 52 */ "signed ::= minus_num",
- /* 53 */ "carglist ::= carglist ccons",
- /* 54 */ "carglist ::=",
- /* 55 */ "ccons ::= CONSTRAINT nm",
- /* 56 */ "ccons ::= DEFAULT term",
- /* 57 */ "ccons ::= DEFAULT LP expr RP",
- /* 58 */ "ccons ::= DEFAULT PLUS term",
- /* 59 */ "ccons ::= DEFAULT MINUS term",
- /* 60 */ "ccons ::= DEFAULT id",
- /* 61 */ "ccons ::= NULL onconf",
- /* 62 */ "ccons ::= NOT NULL onconf",
- /* 63 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
- /* 64 */ "ccons ::= UNIQUE onconf",
- /* 65 */ "ccons ::= CHECK LP expr RP",
- /* 66 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
- /* 67 */ "ccons ::= defer_subclause",
- /* 68 */ "ccons ::= COLLATE ids",
- /* 69 */ "autoinc ::=",
- /* 70 */ "autoinc ::= AUTOINCR",
- /* 71 */ "refargs ::=",
- /* 72 */ "refargs ::= refargs refarg",
- /* 73 */ "refarg ::= MATCH nm",
- /* 74 */ "refarg ::= ON INSERT refact",
- /* 75 */ "refarg ::= ON DELETE refact",
- /* 76 */ "refarg ::= ON UPDATE refact",
- /* 77 */ "refact ::= SET NULL",
- /* 78 */ "refact ::= SET DEFAULT",
- /* 79 */ "refact ::= CASCADE",
- /* 80 */ "refact ::= RESTRICT",
- /* 81 */ "refact ::= NO ACTION",
- /* 82 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /* 83 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /* 84 */ "init_deferred_pred_opt ::=",
- /* 85 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /* 86 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /* 87 */ "conslist_opt ::=",
- /* 88 */ "conslist_opt ::= COMMA conslist",
- /* 89 */ "conslist ::= conslist tconscomma tcons",
- /* 90 */ "conslist ::= tcons",
- /* 91 */ "tconscomma ::= COMMA",
- /* 92 */ "tconscomma ::=",
- /* 93 */ "tcons ::= CONSTRAINT nm",
- /* 94 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
- /* 95 */ "tcons ::= UNIQUE LP idxlist RP onconf",
- /* 96 */ "tcons ::= CHECK LP expr RP onconf",
- /* 97 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
- /* 98 */ "defer_subclause_opt ::=",
- /* 99 */ "defer_subclause_opt ::= defer_subclause",
- /* 100 */ "onconf ::=",
- /* 101 */ "onconf ::= ON CONFLICT resolvetype",
- /* 102 */ "orconf ::=",
- /* 103 */ "orconf ::= OR resolvetype",
- /* 104 */ "resolvetype ::= raisetype",
- /* 105 */ "resolvetype ::= IGNORE",
- /* 106 */ "resolvetype ::= REPLACE",
- /* 107 */ "cmd ::= DROP TABLE ifexists fullname",
- /* 108 */ "ifexists ::= IF EXISTS",
- /* 109 */ "ifexists ::=",
- /* 110 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
- /* 111 */ "cmd ::= DROP VIEW ifexists fullname",
- /* 112 */ "cmd ::= select",
- /* 113 */ "select ::= oneselect",
- /* 114 */ "select ::= select multiselect_op oneselect",
- /* 115 */ "multiselect_op ::= UNION",
- /* 116 */ "multiselect_op ::= UNION ALL",
- /* 117 */ "multiselect_op ::= EXCEPT|INTERSECT",
- /* 118 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 119 */ "distinct ::= DISTINCT",
- /* 120 */ "distinct ::= ALL",
- /* 121 */ "distinct ::=",
- /* 122 */ "sclp ::= selcollist COMMA",
- /* 123 */ "sclp ::=",
- /* 124 */ "selcollist ::= sclp expr as",
- /* 125 */ "selcollist ::= sclp STAR",
- /* 126 */ "selcollist ::= sclp nm DOT STAR",
- /* 127 */ "as ::= AS nm",
- /* 128 */ "as ::= ids",
- /* 129 */ "as ::=",
- /* 130 */ "from ::=",
- /* 131 */ "from ::= FROM seltablist",
- /* 132 */ "stl_prefix ::= seltablist joinop",
- /* 133 */ "stl_prefix ::=",
- /* 134 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
- /* 135 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
- /* 136 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
- /* 137 */ "dbnm ::=",
- /* 138 */ "dbnm ::= DOT nm",
- /* 139 */ "fullname ::= nm dbnm",
- /* 140 */ "joinop ::= COMMA|JOIN",
- /* 141 */ "joinop ::= JOIN_KW JOIN",
- /* 142 */ "joinop ::= JOIN_KW nm JOIN",
- /* 143 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 144 */ "on_opt ::= ON expr",
- /* 145 */ "on_opt ::=",
- /* 146 */ "indexed_opt ::=",
- /* 147 */ "indexed_opt ::= INDEXED BY nm",
- /* 148 */ "indexed_opt ::= NOT INDEXED",
- /* 149 */ "using_opt ::= USING LP inscollist RP",
- /* 150 */ "using_opt ::=",
- /* 151 */ "orderby_opt ::=",
- /* 152 */ "orderby_opt ::= ORDER BY sortlist",
- /* 153 */ "sortlist ::= sortlist COMMA expr sortorder",
- /* 154 */ "sortlist ::= expr sortorder",
- /* 155 */ "sortorder ::= ASC",
- /* 156 */ "sortorder ::= DESC",
- /* 157 */ "sortorder ::=",
- /* 158 */ "groupby_opt ::=",
- /* 159 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 160 */ "having_opt ::=",
- /* 161 */ "having_opt ::= HAVING expr",
- /* 162 */ "limit_opt ::=",
- /* 163 */ "limit_opt ::= LIMIT expr",
- /* 164 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 165 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 166 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
- /* 167 */ "where_opt ::=",
- /* 168 */ "where_opt ::= WHERE expr",
- /* 169 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
- /* 170 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 171 */ "setlist ::= nm EQ expr",
- /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
- /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
- /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
- /* 175 */ "insert_cmd ::= INSERT orconf",
- /* 176 */ "insert_cmd ::= REPLACE",
- /* 177 */ "valuelist ::= VALUES LP nexprlist RP",
- /* 178 */ "valuelist ::= valuelist COMMA LP exprlist RP",
- /* 179 */ "inscollist_opt ::=",
- /* 180 */ "inscollist_opt ::= LP inscollist RP",
- /* 181 */ "inscollist ::= inscollist COMMA nm",
- /* 182 */ "inscollist ::= nm",
- /* 183 */ "expr ::= term",
- /* 184 */ "expr ::= LP expr RP",
- /* 185 */ "term ::= NULL",
- /* 186 */ "expr ::= id",
- /* 187 */ "expr ::= JOIN_KW",
- /* 188 */ "expr ::= nm DOT nm",
- /* 189 */ "expr ::= nm DOT nm DOT nm",
- /* 190 */ "term ::= INTEGER|FLOAT|BLOB",
- /* 191 */ "term ::= STRING",
- /* 192 */ "expr ::= REGISTER",
- /* 193 */ "expr ::= VARIABLE",
- /* 194 */ "expr ::= expr COLLATE ids",
- /* 195 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 196 */ "expr ::= ID LP distinct exprlist RP",
- /* 197 */ "expr ::= ID LP STAR RP",
- /* 198 */ "term ::= CTIME_KW",
- /* 199 */ "expr ::= expr AND expr",
- /* 200 */ "expr ::= expr OR expr",
- /* 201 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 202 */ "expr ::= expr EQ|NE expr",
- /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 204 */ "expr ::= expr PLUS|MINUS expr",
- /* 205 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 206 */ "expr ::= expr CONCAT expr",
- /* 207 */ "likeop ::= LIKE_KW",
- /* 208 */ "likeop ::= NOT LIKE_KW",
- /* 209 */ "likeop ::= MATCH",
- /* 210 */ "likeop ::= NOT MATCH",
- /* 211 */ "expr ::= expr likeop expr",
- /* 212 */ "expr ::= expr likeop expr ESCAPE expr",
- /* 213 */ "expr ::= expr ISNULL|NOTNULL",
- /* 214 */ "expr ::= expr NOT NULL",
- /* 215 */ "expr ::= expr IS expr",
- /* 216 */ "expr ::= expr IS NOT expr",
- /* 217 */ "expr ::= NOT expr",
- /* 218 */ "expr ::= BITNOT expr",
- /* 219 */ "expr ::= MINUS expr",
- /* 220 */ "expr ::= PLUS expr",
- /* 221 */ "between_op ::= BETWEEN",
- /* 222 */ "between_op ::= NOT BETWEEN",
- /* 223 */ "expr ::= expr between_op expr AND expr",
- /* 224 */ "in_op ::= IN",
- /* 225 */ "in_op ::= NOT IN",
- /* 226 */ "expr ::= expr in_op LP exprlist RP",
- /* 227 */ "expr ::= LP select RP",
- /* 228 */ "expr ::= expr in_op LP select RP",
- /* 229 */ "expr ::= expr in_op nm dbnm",
- /* 230 */ "expr ::= EXISTS LP select RP",
- /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 233 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 234 */ "case_else ::= ELSE expr",
- /* 235 */ "case_else ::=",
- /* 236 */ "case_operand ::= expr",
- /* 237 */ "case_operand ::=",
- /* 238 */ "exprlist ::= nexprlist",
- /* 239 */ "exprlist ::=",
- /* 240 */ "nexprlist ::= nexprlist COMMA expr",
- /* 241 */ "nexprlist ::= expr",
- /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
- /* 243 */ "uniqueflag ::= UNIQUE",
- /* 244 */ "uniqueflag ::=",
- /* 245 */ "idxlist_opt ::=",
- /* 246 */ "idxlist_opt ::= LP idxlist RP",
- /* 247 */ "idxlist ::= idxlist COMMA nm collate sortorder",
- /* 248 */ "idxlist ::= nm collate sortorder",
- /* 249 */ "collate ::=",
- /* 250 */ "collate ::= COLLATE ids",
- /* 251 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 252 */ "cmd ::= VACUUM",
- /* 253 */ "cmd ::= VACUUM nm",
- /* 254 */ "cmd ::= PRAGMA nm dbnm",
- /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 256 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 258 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 259 */ "nmnum ::= plus_num",
- /* 260 */ "nmnum ::= nm",
- /* 261 */ "nmnum ::= ON",
- /* 262 */ "nmnum ::= DELETE",
- /* 263 */ "nmnum ::= DEFAULT",
- /* 264 */ "plus_num ::= PLUS number",
- /* 265 */ "plus_num ::= number",
- /* 266 */ "minus_num ::= MINUS number",
- /* 267 */ "number ::= INTEGER|FLOAT",
- /* 268 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 269 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 270 */ "trigger_time ::= BEFORE",
- /* 271 */ "trigger_time ::= AFTER",
- /* 272 */ "trigger_time ::= INSTEAD OF",
- /* 273 */ "trigger_time ::=",
- /* 274 */ "trigger_event ::= DELETE|INSERT",
- /* 275 */ "trigger_event ::= UPDATE",
- /* 276 */ "trigger_event ::= UPDATE OF inscollist",
- /* 277 */ "foreach_clause ::=",
- /* 278 */ "foreach_clause ::= FOR EACH ROW",
- /* 279 */ "when_clause ::=",
- /* 280 */ "when_clause ::= WHEN expr",
- /* 281 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 283 */ "trnm ::= nm",
- /* 284 */ "trnm ::= nm DOT nm",
- /* 285 */ "tridxby ::=",
- /* 286 */ "tridxby ::= INDEXED BY nm",
- /* 287 */ "tridxby ::= NOT INDEXED",
- /* 288 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
- /* 289 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
- /* 290 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
- /* 291 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
- /* 292 */ "trigger_cmd ::= select",
- /* 293 */ "expr ::= RAISE LP IGNORE RP",
- /* 294 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 295 */ "raisetype ::= ROLLBACK",
- /* 296 */ "raisetype ::= ABORT",
- /* 297 */ "raisetype ::= FAIL",
- /* 298 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 299 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 300 */ "cmd ::= DETACH database_kw_opt expr",
- /* 301 */ "key_opt ::=",
- /* 302 */ "key_opt ::= KEY expr",
- /* 303 */ "database_kw_opt ::= DATABASE",
- /* 304 */ "database_kw_opt ::=",
- /* 305 */ "cmd ::= REINDEX",
- /* 306 */ "cmd ::= REINDEX nm dbnm",
- /* 307 */ "cmd ::= ANALYZE",
- /* 308 */ "cmd ::= ANALYZE nm dbnm",
- /* 309 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 310 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 311 */ "add_column_fullname ::= fullname",
- /* 312 */ "kwcolumn_opt ::=",
- /* 313 */ "kwcolumn_opt ::= COLUMNKW",
- /* 314 */ "cmd ::= create_vtab",
- /* 315 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 316 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 317 */ "vtabarglist ::= vtabarg",
- /* 318 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 319 */ "vtabarg ::=",
- /* 320 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 321 */ "vtabargtoken ::= ANY",
- /* 322 */ "vtabargtoken ::= lp anylist RP",
- /* 323 */ "lp ::= LP",
- /* 324 */ "anylist ::=",
- /* 325 */ "anylist ::= anylist LP anylist RP",
- /* 326 */ "anylist ::= anylist ANY",
+ /* 34 */ "table_options ::=",
+ /* 35 */ "table_options ::= WITHOUT nm",
+ /* 36 */ "columnlist ::= columnlist COMMA column",
+ /* 37 */ "columnlist ::= column",
+ /* 38 */ "column ::= columnid type carglist",
+ /* 39 */ "columnid ::= nm",
+ /* 40 */ "id ::= ID",
+ /* 41 */ "id ::= INDEXED",
+ /* 42 */ "ids ::= ID|STRING",
+ /* 43 */ "nm ::= id",
+ /* 44 */ "nm ::= STRING",
+ /* 45 */ "nm ::= JOIN_KW",
+ /* 46 */ "type ::=",
+ /* 47 */ "type ::= typetoken",
+ /* 48 */ "typetoken ::= typename",
+ /* 49 */ "typetoken ::= typename LP signed RP",
+ /* 50 */ "typetoken ::= typename LP signed COMMA signed RP",
+ /* 51 */ "typename ::= ids",
+ /* 52 */ "typename ::= typename ids",
+ /* 53 */ "signed ::= plus_num",
+ /* 54 */ "signed ::= minus_num",
+ /* 55 */ "carglist ::= carglist ccons",
+ /* 56 */ "carglist ::=",
+ /* 57 */ "ccons ::= CONSTRAINT nm",
+ /* 58 */ "ccons ::= DEFAULT term",
+ /* 59 */ "ccons ::= DEFAULT LP expr RP",
+ /* 60 */ "ccons ::= DEFAULT PLUS term",
+ /* 61 */ "ccons ::= DEFAULT MINUS term",
+ /* 62 */ "ccons ::= DEFAULT id",
+ /* 63 */ "ccons ::= NULL onconf",
+ /* 64 */ "ccons ::= NOT NULL onconf",
+ /* 65 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
+ /* 66 */ "ccons ::= UNIQUE onconf",
+ /* 67 */ "ccons ::= CHECK LP expr RP",
+ /* 68 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
+ /* 69 */ "ccons ::= defer_subclause",
+ /* 70 */ "ccons ::= COLLATE ids",
+ /* 71 */ "autoinc ::=",
+ /* 72 */ "autoinc ::= AUTOINCR",
+ /* 73 */ "refargs ::=",
+ /* 74 */ "refargs ::= refargs refarg",
+ /* 75 */ "refarg ::= MATCH nm",
+ /* 76 */ "refarg ::= ON INSERT refact",
+ /* 77 */ "refarg ::= ON DELETE refact",
+ /* 78 */ "refarg ::= ON UPDATE refact",
+ /* 79 */ "refact ::= SET NULL",
+ /* 80 */ "refact ::= SET DEFAULT",
+ /* 81 */ "refact ::= CASCADE",
+ /* 82 */ "refact ::= RESTRICT",
+ /* 83 */ "refact ::= NO ACTION",
+ /* 84 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /* 85 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /* 86 */ "init_deferred_pred_opt ::=",
+ /* 87 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /* 88 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /* 89 */ "conslist_opt ::=",
+ /* 90 */ "conslist_opt ::= COMMA conslist",
+ /* 91 */ "conslist ::= conslist tconscomma tcons",
+ /* 92 */ "conslist ::= tcons",
+ /* 93 */ "tconscomma ::= COMMA",
+ /* 94 */ "tconscomma ::=",
+ /* 95 */ "tcons ::= CONSTRAINT nm",
+ /* 96 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
+ /* 97 */ "tcons ::= UNIQUE LP idxlist RP onconf",
+ /* 98 */ "tcons ::= CHECK LP expr RP onconf",
+ /* 99 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
+ /* 100 */ "defer_subclause_opt ::=",
+ /* 101 */ "defer_subclause_opt ::= defer_subclause",
+ /* 102 */ "onconf ::=",
+ /* 103 */ "onconf ::= ON CONFLICT resolvetype",
+ /* 104 */ "orconf ::=",
+ /* 105 */ "orconf ::= OR resolvetype",
+ /* 106 */ "resolvetype ::= raisetype",
+ /* 107 */ "resolvetype ::= IGNORE",
+ /* 108 */ "resolvetype ::= REPLACE",
+ /* 109 */ "cmd ::= DROP TABLE ifexists fullname",
+ /* 110 */ "ifexists ::= IF EXISTS",
+ /* 111 */ "ifexists ::=",
+ /* 112 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
+ /* 113 */ "cmd ::= DROP VIEW ifexists fullname",
+ /* 114 */ "cmd ::= select",
+ /* 115 */ "select ::= oneselect",
+ /* 116 */ "select ::= select multiselect_op oneselect",
+ /* 117 */ "multiselect_op ::= UNION",
+ /* 118 */ "multiselect_op ::= UNION ALL",
+ /* 119 */ "multiselect_op ::= EXCEPT|INTERSECT",
+ /* 120 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 121 */ "distinct ::= DISTINCT",
+ /* 122 */ "distinct ::= ALL",
+ /* 123 */ "distinct ::=",
+ /* 124 */ "sclp ::= selcollist COMMA",
+ /* 125 */ "sclp ::=",
+ /* 126 */ "selcollist ::= sclp expr as",
+ /* 127 */ "selcollist ::= sclp STAR",
+ /* 128 */ "selcollist ::= sclp nm DOT STAR",
+ /* 129 */ "as ::= AS nm",
+ /* 130 */ "as ::= ids",
+ /* 131 */ "as ::=",
+ /* 132 */ "from ::=",
+ /* 133 */ "from ::= FROM seltablist",
+ /* 134 */ "stl_prefix ::= seltablist joinop",
+ /* 135 */ "stl_prefix ::=",
+ /* 136 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
+ /* 137 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
+ /* 138 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
+ /* 139 */ "dbnm ::=",
+ /* 140 */ "dbnm ::= DOT nm",
+ /* 141 */ "fullname ::= nm dbnm",
+ /* 142 */ "joinop ::= COMMA|JOIN",
+ /* 143 */ "joinop ::= JOIN_KW JOIN",
+ /* 144 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 145 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 146 */ "on_opt ::= ON expr",
+ /* 147 */ "on_opt ::=",
+ /* 148 */ "indexed_opt ::=",
+ /* 149 */ "indexed_opt ::= INDEXED BY nm",
+ /* 150 */ "indexed_opt ::= NOT INDEXED",
+ /* 151 */ "using_opt ::= USING LP idlist RP",
+ /* 152 */ "using_opt ::=",
+ /* 153 */ "orderby_opt ::=",
+ /* 154 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 155 */ "sortlist ::= sortlist COMMA expr sortorder",
+ /* 156 */ "sortlist ::= expr sortorder",
+ /* 157 */ "sortorder ::= ASC",
+ /* 158 */ "sortorder ::= DESC",
+ /* 159 */ "sortorder ::=",
+ /* 160 */ "groupby_opt ::=",
+ /* 161 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 162 */ "having_opt ::=",
+ /* 163 */ "having_opt ::= HAVING expr",
+ /* 164 */ "limit_opt ::=",
+ /* 165 */ "limit_opt ::= LIMIT expr",
+ /* 166 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 167 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 168 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
+ /* 169 */ "where_opt ::=",
+ /* 170 */ "where_opt ::= WHERE expr",
+ /* 171 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
+ /* 172 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 173 */ "setlist ::= nm EQ expr",
+ /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
+ /* 175 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
+ /* 176 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
+ /* 177 */ "insert_cmd ::= INSERT orconf",
+ /* 178 */ "insert_cmd ::= REPLACE",
+ /* 179 */ "valuelist ::= VALUES LP nexprlist RP",
+ /* 180 */ "valuelist ::= valuelist COMMA LP exprlist RP",
+ /* 181 */ "inscollist_opt ::=",
+ /* 182 */ "inscollist_opt ::= LP idlist RP",
+ /* 183 */ "idlist ::= idlist COMMA nm",
+ /* 184 */ "idlist ::= nm",
+ /* 185 */ "expr ::= term",
+ /* 186 */ "expr ::= LP expr RP",
+ /* 187 */ "term ::= NULL",
+ /* 188 */ "expr ::= id",
+ /* 189 */ "expr ::= JOIN_KW",
+ /* 190 */ "expr ::= nm DOT nm",
+ /* 191 */ "expr ::= nm DOT nm DOT nm",
+ /* 192 */ "term ::= INTEGER|FLOAT|BLOB",
+ /* 193 */ "term ::= STRING",
+ /* 194 */ "expr ::= REGISTER",
+ /* 195 */ "expr ::= VARIABLE",
+ /* 196 */ "expr ::= expr COLLATE ids",
+ /* 197 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 198 */ "expr ::= ID LP distinct exprlist RP",
+ /* 199 */ "expr ::= ID LP STAR RP",
+ /* 200 */ "term ::= CTIME_KW",
+ /* 201 */ "expr ::= expr AND expr",
+ /* 202 */ "expr ::= expr OR expr",
+ /* 203 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 204 */ "expr ::= expr EQ|NE expr",
+ /* 205 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 206 */ "expr ::= expr PLUS|MINUS expr",
+ /* 207 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 208 */ "expr ::= expr CONCAT expr",
+ /* 209 */ "likeop ::= LIKE_KW",
+ /* 210 */ "likeop ::= NOT LIKE_KW",
+ /* 211 */ "likeop ::= MATCH",
+ /* 212 */ "likeop ::= NOT MATCH",
+ /* 213 */ "expr ::= expr likeop expr",
+ /* 214 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 215 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 216 */ "expr ::= expr NOT NULL",
+ /* 217 */ "expr ::= expr IS expr",
+ /* 218 */ "expr ::= expr IS NOT expr",
+ /* 219 */ "expr ::= NOT expr",
+ /* 220 */ "expr ::= BITNOT expr",
+ /* 221 */ "expr ::= MINUS expr",
+ /* 222 */ "expr ::= PLUS expr",
+ /* 223 */ "between_op ::= BETWEEN",
+ /* 224 */ "between_op ::= NOT BETWEEN",
+ /* 225 */ "expr ::= expr between_op expr AND expr",
+ /* 226 */ "in_op ::= IN",
+ /* 227 */ "in_op ::= NOT IN",
+ /* 228 */ "expr ::= expr in_op LP exprlist RP",
+ /* 229 */ "expr ::= LP select RP",
+ /* 230 */ "expr ::= expr in_op LP select RP",
+ /* 231 */ "expr ::= expr in_op nm dbnm",
+ /* 232 */ "expr ::= EXISTS LP select RP",
+ /* 233 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 234 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 235 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 236 */ "case_else ::= ELSE expr",
+ /* 237 */ "case_else ::=",
+ /* 238 */ "case_operand ::= expr",
+ /* 239 */ "case_operand ::=",
+ /* 240 */ "exprlist ::= nexprlist",
+ /* 241 */ "exprlist ::=",
+ /* 242 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 243 */ "nexprlist ::= expr",
+ /* 244 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt",
+ /* 245 */ "uniqueflag ::= UNIQUE",
+ /* 246 */ "uniqueflag ::=",
+ /* 247 */ "idxlist_opt ::=",
+ /* 248 */ "idxlist_opt ::= LP idxlist RP",
+ /* 249 */ "idxlist ::= idxlist COMMA nm collate sortorder",
+ /* 250 */ "idxlist ::= nm collate sortorder",
+ /* 251 */ "collate ::=",
+ /* 252 */ "collate ::= COLLATE ids",
+ /* 253 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 254 */ "cmd ::= VACUUM",
+ /* 255 */ "cmd ::= VACUUM nm",
+ /* 256 */ "cmd ::= PRAGMA nm dbnm",
+ /* 257 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 258 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 259 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 260 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
+ /* 261 */ "nmnum ::= plus_num",
+ /* 262 */ "nmnum ::= nm",
+ /* 263 */ "nmnum ::= ON",
+ /* 264 */ "nmnum ::= DELETE",
+ /* 265 */ "nmnum ::= DEFAULT",
+ /* 266 */ "plus_num ::= PLUS number",
+ /* 267 */ "plus_num ::= number",
+ /* 268 */ "minus_num ::= MINUS number",
+ /* 269 */ "number ::= INTEGER|FLOAT",
+ /* 270 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 271 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 272 */ "trigger_time ::= BEFORE",
+ /* 273 */ "trigger_time ::= AFTER",
+ /* 274 */ "trigger_time ::= INSTEAD OF",
+ /* 275 */ "trigger_time ::=",
+ /* 276 */ "trigger_event ::= DELETE|INSERT",
+ /* 277 */ "trigger_event ::= UPDATE",
+ /* 278 */ "trigger_event ::= UPDATE OF idlist",
+ /* 279 */ "foreach_clause ::=",
+ /* 280 */ "foreach_clause ::= FOR EACH ROW",
+ /* 281 */ "when_clause ::=",
+ /* 282 */ "when_clause ::= WHEN expr",
+ /* 283 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 284 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 285 */ "trnm ::= nm",
+ /* 286 */ "trnm ::= nm DOT nm",
+ /* 287 */ "tridxby ::=",
+ /* 288 */ "tridxby ::= INDEXED BY nm",
+ /* 289 */ "tridxby ::= NOT INDEXED",
+ /* 290 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
+ /* 291 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
+ /* 292 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
+ /* 293 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
+ /* 294 */ "trigger_cmd ::= select",
+ /* 295 */ "expr ::= RAISE LP IGNORE RP",
+ /* 296 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 297 */ "raisetype ::= ROLLBACK",
+ /* 298 */ "raisetype ::= ABORT",
+ /* 299 */ "raisetype ::= FAIL",
+ /* 300 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 301 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 302 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 303 */ "key_opt ::=",
+ /* 304 */ "key_opt ::= KEY expr",
+ /* 305 */ "database_kw_opt ::= DATABASE",
+ /* 306 */ "database_kw_opt ::=",
+ /* 307 */ "cmd ::= REINDEX",
+ /* 308 */ "cmd ::= REINDEX nm dbnm",
+ /* 309 */ "cmd ::= ANALYZE",
+ /* 310 */ "cmd ::= ANALYZE nm dbnm",
+ /* 311 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 312 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 313 */ "add_column_fullname ::= fullname",
+ /* 314 */ "kwcolumn_opt ::=",
+ /* 315 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 316 */ "cmd ::= create_vtab",
+ /* 317 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 318 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 319 */ "vtabarglist ::= vtabarg",
+ /* 320 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 321 */ "vtabarg ::=",
+ /* 322 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 323 */ "vtabargtoken ::= ANY",
+ /* 324 */ "vtabargtoken ::= lp anylist RP",
+ /* 325 */ "lp ::= LP",
+ /* 326 */ "anylist ::=",
+ /* 327 */ "anylist ::= anylist LP anylist RP",
+ /* 328 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */
@@ -111517,76 +115724,76 @@ static void yy_destructor(
** which appear on the RHS of the rule, but which are not used
** inside the C code.
*/
- case 160: /* select */
- case 194: /* oneselect */
+ case 162: /* select */
+ case 196: /* oneselect */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy159));
+sqlite3SelectDelete(pParse->db, (yypminor->yy387));
}
break;
- case 173: /* term */
- case 174: /* expr */
+ case 175: /* term */
+ case 176: /* expr */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr);
+sqlite3ExprDelete(pParse->db, (yypminor->yy118).pExpr);
}
break;
- case 178: /* idxlist_opt */
- case 187: /* idxlist */
- case 197: /* selcollist */
- case 200: /* groupby_opt */
- case 202: /* orderby_opt */
- case 204: /* sclp */
- case 214: /* sortlist */
- case 215: /* nexprlist */
- case 216: /* setlist */
- case 220: /* exprlist */
- case 225: /* case_exprlist */
+ case 180: /* idxlist_opt */
+ case 189: /* idxlist */
+ case 199: /* selcollist */
+ case 202: /* groupby_opt */
+ case 204: /* orderby_opt */
+ case 206: /* sclp */
+ case 216: /* sortlist */
+ case 217: /* nexprlist */
+ case 218: /* setlist */
+ case 222: /* exprlist */
+ case 227: /* case_exprlist */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy442));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy322));
}
break;
- case 193: /* fullname */
- case 198: /* from */
- case 206: /* seltablist */
- case 207: /* stl_prefix */
+ case 195: /* fullname */
+ case 200: /* from */
+ case 208: /* seltablist */
+ case 209: /* stl_prefix */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy347));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy259));
}
break;
- case 199: /* where_opt */
- case 201: /* having_opt */
- case 210: /* on_opt */
- case 224: /* case_operand */
- case 226: /* case_else */
- case 236: /* when_clause */
- case 241: /* key_opt */
+ case 201: /* where_opt */
+ case 203: /* having_opt */
+ case 212: /* on_opt */
+ case 226: /* case_operand */
+ case 228: /* case_else */
+ case 238: /* when_clause */
+ case 243: /* key_opt */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy122));
+sqlite3ExprDelete(pParse->db, (yypminor->yy314));
}
break;
- case 211: /* using_opt */
- case 213: /* inscollist */
- case 218: /* inscollist_opt */
+ case 213: /* using_opt */
+ case 215: /* idlist */
+ case 220: /* inscollist_opt */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy180));
+sqlite3IdListDelete(pParse->db, (yypminor->yy384));
}
break;
- case 219: /* valuelist */
+ case 221: /* valuelist */
{
- sqlite3ExprListDelete(pParse->db, (yypminor->yy487).pList);
- sqlite3SelectDelete(pParse->db, (yypminor->yy487).pSelect);
+ sqlite3ExprListDelete(pParse->db, (yypminor->yy260).pList);
+ sqlite3SelectDelete(pParse->db, (yypminor->yy260).pSelect);
}
break;
- case 232: /* trigger_cmd_list */
- case 237: /* trigger_cmd */
+ case 234: /* trigger_cmd_list */
+ case 239: /* trigger_cmd */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy327));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy203));
}
break;
- case 234: /* trigger_event */
+ case 236: /* trigger_event */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy410).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy90).b);
}
break;
default: break; /* If no destructor action specified: do nothing */
@@ -111831,333 +116038,335 @@ static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
- { 142, 1 },
- { 143, 2 },
{ 143, 1 },
+ { 144, 2 },
{ 144, 1 },
- { 144, 3 },
- { 145, 0 },
{ 145, 1 },
{ 145, 3 },
+ { 146, 0 },
{ 146, 1 },
- { 147, 3 },
+ { 146, 3 },
+ { 147, 1 },
+ { 148, 3 },
+ { 150, 0 },
+ { 150, 1 },
+ { 150, 2 },
{ 149, 0 },
{ 149, 1 },
- { 149, 2 },
- { 148, 0 },
- { 148, 1 },
- { 148, 1 },
- { 148, 1 },
- { 147, 2 },
- { 147, 2 },
- { 147, 2 },
- { 151, 1 },
- { 151, 0 },
- { 147, 2 },
- { 147, 3 },
- { 147, 5 },
- { 147, 2 },
- { 152, 6 },
- { 154, 1 },
- { 156, 0 },
- { 156, 3 },
+ { 149, 1 },
+ { 149, 1 },
+ { 148, 2 },
+ { 148, 2 },
+ { 148, 2 },
+ { 152, 1 },
+ { 152, 0 },
+ { 148, 2 },
+ { 148, 3 },
+ { 148, 5 },
+ { 148, 2 },
+ { 153, 6 },
{ 155, 1 },
- { 155, 0 },
- { 153, 4 },
- { 153, 2 },
- { 158, 3 },
- { 158, 1 },
- { 161, 3 },
- { 162, 1 },
- { 165, 1 },
- { 165, 1 },
- { 166, 1 },
- { 150, 1 },
- { 150, 1 },
- { 150, 1 },
- { 163, 0 },
- { 163, 1 },
+ { 157, 0 },
+ { 157, 3 },
+ { 156, 1 },
+ { 156, 0 },
+ { 154, 5 },
+ { 154, 2 },
+ { 161, 0 },
+ { 161, 2 },
+ { 159, 3 },
+ { 159, 1 },
+ { 163, 3 },
+ { 164, 1 },
+ { 167, 1 },
{ 167, 1 },
- { 167, 4 },
- { 167, 6 },
{ 168, 1 },
- { 168, 2 },
- { 169, 1 },
+ { 151, 1 },
+ { 151, 1 },
+ { 151, 1 },
+ { 165, 0 },
+ { 165, 1 },
{ 169, 1 },
- { 164, 2 },
- { 164, 0 },
- { 172, 2 },
- { 172, 2 },
- { 172, 4 },
- { 172, 3 },
- { 172, 3 },
- { 172, 2 },
- { 172, 2 },
- { 172, 3 },
- { 172, 5 },
- { 172, 2 },
- { 172, 4 },
- { 172, 4 },
- { 172, 1 },
- { 172, 2 },
- { 177, 0 },
- { 177, 1 },
+ { 169, 4 },
+ { 169, 6 },
+ { 170, 1 },
+ { 170, 2 },
+ { 171, 1 },
+ { 171, 1 },
+ { 166, 2 },
+ { 166, 0 },
+ { 174, 2 },
+ { 174, 2 },
+ { 174, 4 },
+ { 174, 3 },
+ { 174, 3 },
+ { 174, 2 },
+ { 174, 2 },
+ { 174, 3 },
+ { 174, 5 },
+ { 174, 2 },
+ { 174, 4 },
+ { 174, 4 },
+ { 174, 1 },
+ { 174, 2 },
{ 179, 0 },
- { 179, 2 },
+ { 179, 1 },
+ { 181, 0 },
{ 181, 2 },
- { 181, 3 },
- { 181, 3 },
- { 181, 3 },
- { 182, 2 },
- { 182, 2 },
- { 182, 1 },
- { 182, 1 },
- { 182, 2 },
- { 180, 3 },
- { 180, 2 },
- { 183, 0 },
- { 183, 2 },
{ 183, 2 },
- { 159, 0 },
- { 159, 2 },
- { 184, 3 },
+ { 183, 3 },
+ { 183, 3 },
+ { 183, 3 },
+ { 184, 2 },
+ { 184, 2 },
{ 184, 1 },
- { 185, 1 },
+ { 184, 1 },
+ { 184, 2 },
+ { 182, 3 },
+ { 182, 2 },
{ 185, 0 },
- { 186, 2 },
- { 186, 7 },
- { 186, 5 },
- { 186, 5 },
- { 186, 10 },
- { 188, 0 },
- { 188, 1 },
- { 175, 0 },
- { 175, 3 },
- { 189, 0 },
- { 189, 2 },
- { 190, 1 },
+ { 185, 2 },
+ { 185, 2 },
+ { 160, 0 },
+ { 160, 2 },
+ { 186, 3 },
+ { 186, 1 },
+ { 187, 1 },
+ { 187, 0 },
+ { 188, 2 },
+ { 188, 7 },
+ { 188, 5 },
+ { 188, 5 },
+ { 188, 10 },
+ { 190, 0 },
{ 190, 1 },
- { 190, 1 },
- { 147, 4 },
- { 192, 2 },
- { 192, 0 },
- { 147, 8 },
- { 147, 4 },
- { 147, 1 },
- { 160, 1 },
- { 160, 3 },
- { 195, 1 },
- { 195, 2 },
- { 195, 1 },
- { 194, 9 },
- { 196, 1 },
- { 196, 1 },
- { 196, 0 },
- { 204, 2 },
- { 204, 0 },
- { 197, 3 },
+ { 177, 0 },
+ { 177, 3 },
+ { 191, 0 },
+ { 191, 2 },
+ { 192, 1 },
+ { 192, 1 },
+ { 192, 1 },
+ { 148, 4 },
+ { 194, 2 },
+ { 194, 0 },
+ { 148, 8 },
+ { 148, 4 },
+ { 148, 1 },
+ { 162, 1 },
+ { 162, 3 },
+ { 197, 1 },
{ 197, 2 },
- { 197, 4 },
- { 205, 2 },
- { 205, 1 },
- { 205, 0 },
+ { 197, 1 },
+ { 196, 9 },
+ { 198, 1 },
+ { 198, 1 },
{ 198, 0 },
- { 198, 2 },
+ { 206, 2 },
+ { 206, 0 },
+ { 199, 3 },
+ { 199, 2 },
+ { 199, 4 },
{ 207, 2 },
+ { 207, 1 },
{ 207, 0 },
- { 206, 7 },
- { 206, 7 },
- { 206, 7 },
- { 157, 0 },
- { 157, 2 },
- { 193, 2 },
- { 208, 1 },
- { 208, 2 },
- { 208, 3 },
- { 208, 4 },
- { 210, 2 },
- { 210, 0 },
- { 209, 0 },
- { 209, 3 },
+ { 200, 0 },
+ { 200, 2 },
{ 209, 2 },
- { 211, 4 },
+ { 209, 0 },
+ { 208, 7 },
+ { 208, 7 },
+ { 208, 7 },
+ { 158, 0 },
+ { 158, 2 },
+ { 195, 2 },
+ { 210, 1 },
+ { 210, 2 },
+ { 210, 3 },
+ { 210, 4 },
+ { 212, 2 },
+ { 212, 0 },
{ 211, 0 },
+ { 211, 3 },
+ { 211, 2 },
+ { 213, 4 },
+ { 213, 0 },
+ { 204, 0 },
+ { 204, 3 },
+ { 216, 4 },
+ { 216, 2 },
+ { 178, 1 },
+ { 178, 1 },
+ { 178, 0 },
{ 202, 0 },
{ 202, 3 },
- { 214, 4 },
- { 214, 2 },
- { 176, 1 },
- { 176, 1 },
- { 176, 0 },
- { 200, 0 },
- { 200, 3 },
- { 201, 0 },
- { 201, 2 },
{ 203, 0 },
{ 203, 2 },
- { 203, 4 },
- { 203, 4 },
- { 147, 5 },
- { 199, 0 },
- { 199, 2 },
- { 147, 7 },
- { 216, 5 },
- { 216, 3 },
- { 147, 5 },
- { 147, 5 },
- { 147, 6 },
- { 217, 2 },
- { 217, 1 },
- { 219, 4 },
- { 219, 5 },
- { 218, 0 },
+ { 205, 0 },
+ { 205, 2 },
+ { 205, 4 },
+ { 205, 4 },
+ { 148, 5 },
+ { 201, 0 },
+ { 201, 2 },
+ { 148, 7 },
+ { 218, 5 },
{ 218, 3 },
- { 213, 3 },
- { 213, 1 },
- { 174, 1 },
- { 174, 3 },
- { 173, 1 },
- { 174, 1 },
- { 174, 1 },
- { 174, 3 },
- { 174, 5 },
- { 173, 1 },
- { 173, 1 },
- { 174, 1 },
- { 174, 1 },
- { 174, 3 },
- { 174, 6 },
- { 174, 5 },
- { 174, 4 },
- { 173, 1 },
- { 174, 3 },
- { 174, 3 },
- { 174, 3 },
- { 174, 3 },
- { 174, 3 },
- { 174, 3 },
- { 174, 3 },
- { 174, 3 },
- { 221, 1 },
- { 221, 2 },
- { 221, 1 },
- { 221, 2 },
- { 174, 3 },
- { 174, 5 },
- { 174, 2 },
- { 174, 3 },
- { 174, 3 },
- { 174, 4 },
- { 174, 2 },
- { 174, 2 },
- { 174, 2 },
- { 174, 2 },
- { 222, 1 },
- { 222, 2 },
- { 174, 5 },
- { 223, 1 },
- { 223, 2 },
- { 174, 5 },
- { 174, 3 },
- { 174, 5 },
- { 174, 4 },
- { 174, 4 },
- { 174, 5 },
- { 225, 5 },
- { 225, 4 },
- { 226, 2 },
- { 226, 0 },
- { 224, 1 },
- { 224, 0 },
- { 220, 1 },
+ { 148, 5 },
+ { 148, 5 },
+ { 148, 6 },
+ { 219, 2 },
+ { 219, 1 },
+ { 221, 4 },
+ { 221, 5 },
{ 220, 0 },
+ { 220, 3 },
{ 215, 3 },
{ 215, 1 },
- { 147, 11 },
- { 227, 1 },
- { 227, 0 },
- { 178, 0 },
- { 178, 3 },
- { 187, 5 },
- { 187, 3 },
- { 228, 0 },
+ { 176, 1 },
+ { 176, 3 },
+ { 175, 1 },
+ { 176, 1 },
+ { 176, 1 },
+ { 176, 3 },
+ { 176, 5 },
+ { 175, 1 },
+ { 175, 1 },
+ { 176, 1 },
+ { 176, 1 },
+ { 176, 3 },
+ { 176, 6 },
+ { 176, 5 },
+ { 176, 4 },
+ { 175, 1 },
+ { 176, 3 },
+ { 176, 3 },
+ { 176, 3 },
+ { 176, 3 },
+ { 176, 3 },
+ { 176, 3 },
+ { 176, 3 },
+ { 176, 3 },
+ { 223, 1 },
+ { 223, 2 },
+ { 223, 1 },
+ { 223, 2 },
+ { 176, 3 },
+ { 176, 5 },
+ { 176, 2 },
+ { 176, 3 },
+ { 176, 3 },
+ { 176, 4 },
+ { 176, 2 },
+ { 176, 2 },
+ { 176, 2 },
+ { 176, 2 },
+ { 224, 1 },
+ { 224, 2 },
+ { 176, 5 },
+ { 225, 1 },
+ { 225, 2 },
+ { 176, 5 },
+ { 176, 3 },
+ { 176, 5 },
+ { 176, 4 },
+ { 176, 4 },
+ { 176, 5 },
+ { 227, 5 },
+ { 227, 4 },
{ 228, 2 },
- { 147, 4 },
- { 147, 1 },
- { 147, 2 },
- { 147, 3 },
- { 147, 5 },
- { 147, 6 },
- { 147, 5 },
- { 147, 6 },
- { 229, 1 },
- { 229, 1 },
- { 229, 1 },
- { 229, 1 },
+ { 228, 0 },
+ { 226, 1 },
+ { 226, 0 },
+ { 222, 1 },
+ { 222, 0 },
+ { 217, 3 },
+ { 217, 1 },
+ { 148, 12 },
{ 229, 1 },
- { 170, 2 },
- { 170, 1 },
- { 171, 2 },
- { 230, 1 },
- { 147, 5 },
- { 231, 11 },
- { 233, 1 },
- { 233, 1 },
- { 233, 2 },
- { 233, 0 },
- { 234, 1 },
- { 234, 1 },
- { 234, 3 },
+ { 229, 0 },
+ { 180, 0 },
+ { 180, 3 },
+ { 189, 5 },
+ { 189, 3 },
+ { 230, 0 },
+ { 230, 2 },
+ { 148, 4 },
+ { 148, 1 },
+ { 148, 2 },
+ { 148, 3 },
+ { 148, 5 },
+ { 148, 6 },
+ { 148, 5 },
+ { 148, 6 },
+ { 231, 1 },
+ { 231, 1 },
+ { 231, 1 },
+ { 231, 1 },
+ { 231, 1 },
+ { 172, 2 },
+ { 172, 1 },
+ { 173, 2 },
+ { 232, 1 },
+ { 148, 5 },
+ { 233, 11 },
+ { 235, 1 },
+ { 235, 1 },
+ { 235, 2 },
{ 235, 0 },
- { 235, 3 },
- { 236, 0 },
- { 236, 2 },
- { 232, 3 },
- { 232, 2 },
- { 238, 1 },
- { 238, 3 },
- { 239, 0 },
- { 239, 3 },
- { 239, 2 },
- { 237, 7 },
- { 237, 5 },
- { 237, 5 },
- { 237, 5 },
- { 237, 1 },
- { 174, 4 },
- { 174, 6 },
- { 191, 1 },
- { 191, 1 },
- { 191, 1 },
- { 147, 4 },
- { 147, 6 },
- { 147, 3 },
+ { 236, 1 },
+ { 236, 1 },
+ { 236, 3 },
+ { 237, 0 },
+ { 237, 3 },
+ { 238, 0 },
+ { 238, 2 },
+ { 234, 3 },
+ { 234, 2 },
+ { 240, 1 },
+ { 240, 3 },
{ 241, 0 },
+ { 241, 3 },
{ 241, 2 },
- { 240, 1 },
- { 240, 0 },
- { 147, 1 },
- { 147, 3 },
- { 147, 1 },
- { 147, 3 },
- { 147, 6 },
- { 147, 6 },
- { 242, 1 },
+ { 239, 7 },
+ { 239, 5 },
+ { 239, 5 },
+ { 239, 5 },
+ { 239, 1 },
+ { 176, 4 },
+ { 176, 6 },
+ { 193, 1 },
+ { 193, 1 },
+ { 193, 1 },
+ { 148, 4 },
+ { 148, 6 },
+ { 148, 3 },
{ 243, 0 },
- { 243, 1 },
- { 147, 1 },
- { 147, 4 },
- { 244, 8 },
+ { 243, 2 },
+ { 242, 1 },
+ { 242, 0 },
+ { 148, 1 },
+ { 148, 3 },
+ { 148, 1 },
+ { 148, 3 },
+ { 148, 6 },
+ { 148, 6 },
+ { 244, 1 },
+ { 245, 0 },
{ 245, 1 },
- { 245, 3 },
- { 246, 0 },
- { 246, 2 },
+ { 148, 1 },
+ { 148, 4 },
+ { 246, 8 },
{ 247, 1 },
{ 247, 3 },
- { 248, 1 },
- { 249, 0 },
- { 249, 4 },
- { 249, 2 },
+ { 248, 0 },
+ { 248, 2 },
+ { 249, 1 },
+ { 249, 3 },
+ { 250, 1 },
+ { 251, 0 },
+ { 251, 4 },
+ { 251, 2 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -112225,17 +116434,17 @@ static void yy_reduce(
{ sqlite3FinishCoding(pParse); }
break;
case 9: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy392);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy4);}
break;
case 13: /* transtype ::= */
-{yygotominor.yy392 = TK_DEFERRED;}
+{yygotominor.yy4 = TK_DEFERRED;}
break;
case 14: /* transtype ::= DEFERRED */
case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
- case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115);
- case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117);
-{yygotominor.yy392 = yymsp[0].major;}
+ case 117: /* multiselect_op ::= UNION */ yytestcase(yyruleno==117);
+ case 119: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==119);
+{yygotominor.yy4 = yymsp[0].major;}
break;
case 17: /* cmd ::= COMMIT trans_opt */
case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
@@ -112261,7 +116470,7 @@ static void yy_reduce(
break;
case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy392,0,0,yymsp[-2].minor.yy392);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4);
}
break;
case 27: /* createkw ::= CREATE */
@@ -112272,697 +116481,706 @@ static void yy_reduce(
break;
case 28: /* ifnotexists ::= */
case 31: /* temp ::= */ yytestcase(yyruleno==31);
- case 69: /* autoinc ::= */ yytestcase(yyruleno==69);
- case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82);
- case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84);
- case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
- case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
- case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
- case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
- case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
-{yygotominor.yy392 = 0;}
+ case 71: /* autoinc ::= */ yytestcase(yyruleno==71);
+ case 84: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==84);
+ case 86: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==86);
+ case 88: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==88);
+ case 100: /* defer_subclause_opt ::= */ yytestcase(yyruleno==100);
+ case 111: /* ifexists ::= */ yytestcase(yyruleno==111);
+ case 223: /* between_op ::= BETWEEN */ yytestcase(yyruleno==223);
+ case 226: /* in_op ::= IN */ yytestcase(yyruleno==226);
+{yygotominor.yy4 = 0;}
break;
case 29: /* ifnotexists ::= IF NOT EXISTS */
case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
- case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
- case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
- case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
- case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
- case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
-{yygotominor.yy392 = 1;}
+ case 72: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==72);
+ case 87: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==87);
+ case 110: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==110);
+ case 224: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==224);
+ case 227: /* in_op ::= NOT IN */ yytestcase(yyruleno==227);
+{yygotominor.yy4 = 1;}
break;
- case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
+ case 32: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
{
- sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
+ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy210,0);
}
break;
case 33: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy159);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
+ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy387);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387);
+}
+ break;
+ case 34: /* table_options ::= */
+{yygotominor.yy210 = 0;}
+ break;
+ case 35: /* table_options ::= WITHOUT nm */
+{
+ if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
+ yygotominor.yy210 = TF_WithoutRowid;
+ }else{
+ yygotominor.yy210 = 0;
+ sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
+ }
}
break;
- case 36: /* column ::= columnid type carglist */
+ case 38: /* column ::= columnid type carglist */
{
yygotominor.yy0.z = yymsp[-2].minor.yy0.z;
yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
}
break;
- case 37: /* columnid ::= nm */
+ case 39: /* columnid ::= nm */
{
sqlite3AddColumn(pParse,&yymsp[0].minor.yy0);
yygotominor.yy0 = yymsp[0].minor.yy0;
pParse->constraintName.n = 0;
}
break;
- case 38: /* id ::= ID */
- case 39: /* id ::= INDEXED */ yytestcase(yyruleno==39);
- case 40: /* ids ::= ID|STRING */ yytestcase(yyruleno==40);
- case 41: /* nm ::= id */ yytestcase(yyruleno==41);
- case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
- case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
- case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
- case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
- case 127: /* as ::= AS nm */ yytestcase(yyruleno==127);
- case 128: /* as ::= ids */ yytestcase(yyruleno==128);
- case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138);
- case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147);
- case 250: /* collate ::= COLLATE ids */ yytestcase(yyruleno==250);
- case 259: /* nmnum ::= plus_num */ yytestcase(yyruleno==259);
- case 260: /* nmnum ::= nm */ yytestcase(yyruleno==260);
- case 261: /* nmnum ::= ON */ yytestcase(yyruleno==261);
- case 262: /* nmnum ::= DELETE */ yytestcase(yyruleno==262);
- case 263: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==263);
- case 264: /* plus_num ::= PLUS number */ yytestcase(yyruleno==264);
- case 265: /* plus_num ::= number */ yytestcase(yyruleno==265);
- case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266);
- case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267);
- case 283: /* trnm ::= nm */ yytestcase(yyruleno==283);
+ case 40: /* id ::= ID */
+ case 41: /* id ::= INDEXED */ yytestcase(yyruleno==41);
+ case 42: /* ids ::= ID|STRING */ yytestcase(yyruleno==42);
+ case 43: /* nm ::= id */ yytestcase(yyruleno==43);
+ case 44: /* nm ::= STRING */ yytestcase(yyruleno==44);
+ case 45: /* nm ::= JOIN_KW */ yytestcase(yyruleno==45);
+ case 48: /* typetoken ::= typename */ yytestcase(yyruleno==48);
+ case 51: /* typename ::= ids */ yytestcase(yyruleno==51);
+ case 129: /* as ::= AS nm */ yytestcase(yyruleno==129);
+ case 130: /* as ::= ids */ yytestcase(yyruleno==130);
+ case 140: /* dbnm ::= DOT nm */ yytestcase(yyruleno==140);
+ case 149: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==149);
+ case 252: /* collate ::= COLLATE ids */ yytestcase(yyruleno==252);
+ case 261: /* nmnum ::= plus_num */ yytestcase(yyruleno==261);
+ case 262: /* nmnum ::= nm */ yytestcase(yyruleno==262);
+ case 263: /* nmnum ::= ON */ yytestcase(yyruleno==263);
+ case 264: /* nmnum ::= DELETE */ yytestcase(yyruleno==264);
+ case 265: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==265);
+ case 266: /* plus_num ::= PLUS number */ yytestcase(yyruleno==266);
+ case 267: /* plus_num ::= number */ yytestcase(yyruleno==267);
+ case 268: /* minus_num ::= MINUS number */ yytestcase(yyruleno==268);
+ case 269: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==269);
+ case 285: /* trnm ::= nm */ yytestcase(yyruleno==285);
{yygotominor.yy0 = yymsp[0].minor.yy0;}
break;
- case 45: /* type ::= typetoken */
+ case 47: /* type ::= typetoken */
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
break;
- case 47: /* typetoken ::= typename LP signed RP */
+ case 49: /* typetoken ::= typename LP signed RP */
{
yygotominor.yy0.z = yymsp[-3].minor.yy0.z;
yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
}
break;
- case 48: /* typetoken ::= typename LP signed COMMA signed RP */
+ case 50: /* typetoken ::= typename LP signed COMMA signed RP */
{
yygotominor.yy0.z = yymsp[-5].minor.yy0.z;
yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
}
break;
- case 50: /* typename ::= typename ids */
+ case 52: /* typename ::= typename ids */
{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
break;
- case 55: /* ccons ::= CONSTRAINT nm */
- case 93: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93);
+ case 57: /* ccons ::= CONSTRAINT nm */
+ case 95: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==95);
{pParse->constraintName = yymsp[0].minor.yy0;}
break;
- case 56: /* ccons ::= DEFAULT term */
- case 58: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==58);
-{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);}
+ case 58: /* ccons ::= DEFAULT term */
+ case 60: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==60);
+{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy118);}
break;
- case 57: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy342);}
+ case 59: /* ccons ::= DEFAULT LP expr RP */
+{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy118);}
break;
- case 59: /* ccons ::= DEFAULT MINUS term */
+ case 61: /* ccons ::= DEFAULT MINUS term */
{
ExprSpan v;
- v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy342.pExpr, 0, 0);
+ v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy118.pExpr, 0, 0);
v.zStart = yymsp[-1].minor.yy0.z;
- v.zEnd = yymsp[0].minor.yy342.zEnd;
+ v.zEnd = yymsp[0].minor.yy118.zEnd;
sqlite3AddDefaultValue(pParse,&v);
}
break;
- case 60: /* ccons ::= DEFAULT id */
+ case 62: /* ccons ::= DEFAULT id */
{
ExprSpan v;
spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0);
sqlite3AddDefaultValue(pParse,&v);
}
break;
- case 62: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy392);}
+ case 64: /* ccons ::= NOT NULL onconf */
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy4);}
break;
- case 63: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy392,yymsp[0].minor.yy392,yymsp[-2].minor.yy392);}
+ case 65: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy4,yymsp[0].minor.yy4,yymsp[-2].minor.yy4);}
break;
- case 64: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy392,0,0,0,0);}
+ case 66: /* ccons ::= UNIQUE onconf */
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy4,0,0,0,0);}
break;
- case 65: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy342.pExpr);}
+ case 67: /* ccons ::= CHECK LP expr RP */
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy118.pExpr);}
break;
- case 66: /* ccons ::= REFERENCES nm idxlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy442,yymsp[0].minor.yy392);}
+ case 68: /* ccons ::= REFERENCES nm idxlist_opt refargs */
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy4);}
break;
- case 67: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy392);}
+ case 69: /* ccons ::= defer_subclause */
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy4);}
break;
- case 68: /* ccons ::= COLLATE ids */
+ case 70: /* ccons ::= COLLATE ids */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
- case 71: /* refargs ::= */
-{ yygotominor.yy392 = OE_None*0x0101; /* EV: R-19803-45884 */}
+ case 73: /* refargs ::= */
+{ yygotominor.yy4 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
- case 72: /* refargs ::= refargs refarg */
-{ yygotominor.yy392 = (yymsp[-1].minor.yy392 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
+ case 74: /* refargs ::= refargs refarg */
+{ yygotominor.yy4 = (yymsp[-1].minor.yy4 & ~yymsp[0].minor.yy215.mask) | yymsp[0].minor.yy215.value; }
break;
- case 73: /* refarg ::= MATCH nm */
- case 74: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==74);
-{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; }
+ case 75: /* refarg ::= MATCH nm */
+ case 76: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==76);
+{ yygotominor.yy215.value = 0; yygotominor.yy215.mask = 0x000000; }
break;
- case 75: /* refarg ::= ON DELETE refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy392; yygotominor.yy207.mask = 0x0000ff; }
+ case 77: /* refarg ::= ON DELETE refact */
+{ yygotominor.yy215.value = yymsp[0].minor.yy4; yygotominor.yy215.mask = 0x0000ff; }
break;
- case 76: /* refarg ::= ON UPDATE refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy392<<8; yygotominor.yy207.mask = 0x00ff00; }
+ case 78: /* refarg ::= ON UPDATE refact */
+{ yygotominor.yy215.value = yymsp[0].minor.yy4<<8; yygotominor.yy215.mask = 0x00ff00; }
break;
- case 77: /* refact ::= SET NULL */
-{ yygotominor.yy392 = OE_SetNull; /* EV: R-33326-45252 */}
+ case 79: /* refact ::= SET NULL */
+{ yygotominor.yy4 = OE_SetNull; /* EV: R-33326-45252 */}
break;
- case 78: /* refact ::= SET DEFAULT */
-{ yygotominor.yy392 = OE_SetDflt; /* EV: R-33326-45252 */}
+ case 80: /* refact ::= SET DEFAULT */
+{ yygotominor.yy4 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
- case 79: /* refact ::= CASCADE */
-{ yygotominor.yy392 = OE_Cascade; /* EV: R-33326-45252 */}
+ case 81: /* refact ::= CASCADE */
+{ yygotominor.yy4 = OE_Cascade; /* EV: R-33326-45252 */}
break;
- case 80: /* refact ::= RESTRICT */
-{ yygotominor.yy392 = OE_Restrict; /* EV: R-33326-45252 */}
+ case 82: /* refact ::= RESTRICT */
+{ yygotominor.yy4 = OE_Restrict; /* EV: R-33326-45252 */}
break;
- case 81: /* refact ::= NO ACTION */
-{ yygotominor.yy392 = OE_None; /* EV: R-33326-45252 */}
+ case 83: /* refact ::= NO ACTION */
+{ yygotominor.yy4 = OE_None; /* EV: R-33326-45252 */}
break;
- case 83: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99);
- case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101);
- case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104);
-{yygotominor.yy392 = yymsp[0].minor.yy392;}
+ case 85: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ case 101: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==101);
+ case 103: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==103);
+ case 106: /* resolvetype ::= raisetype */ yytestcase(yyruleno==106);
+{yygotominor.yy4 = yymsp[0].minor.yy4;}
break;
- case 87: /* conslist_opt ::= */
+ case 89: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
break;
- case 88: /* conslist_opt ::= COMMA conslist */
+ case 90: /* conslist_opt ::= COMMA conslist */
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
break;
- case 91: /* tconscomma ::= COMMA */
+ case 93: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
break;
- case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);}
+ case 96: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy4,yymsp[-2].minor.yy4,0);}
break;
- case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);}
+ case 97: /* tcons ::= UNIQUE LP idxlist RP onconf */
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy4,0,0,0,0);}
break;
- case 96: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);}
+ case 98: /* tcons ::= CHECK LP expr RP onconf */
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy118.pExpr);}
break;
- case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
+ case 99: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy4);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy4);
}
break;
- case 100: /* onconf ::= */
-{yygotominor.yy392 = OE_Default;}
+ case 102: /* onconf ::= */
+{yygotominor.yy4 = OE_Default;}
break;
- case 102: /* orconf ::= */
-{yygotominor.yy258 = OE_Default;}
+ case 104: /* orconf ::= */
+{yygotominor.yy210 = OE_Default;}
break;
- case 103: /* orconf ::= OR resolvetype */
-{yygotominor.yy258 = (u8)yymsp[0].minor.yy392;}
+ case 105: /* orconf ::= OR resolvetype */
+{yygotominor.yy210 = (u8)yymsp[0].minor.yy4;}
break;
- case 105: /* resolvetype ::= IGNORE */
-{yygotominor.yy392 = OE_Ignore;}
+ case 107: /* resolvetype ::= IGNORE */
+{yygotominor.yy4 = OE_Ignore;}
break;
- case 106: /* resolvetype ::= REPLACE */
-{yygotominor.yy392 = OE_Replace;}
+ case 108: /* resolvetype ::= REPLACE */
+{yygotominor.yy4 = OE_Replace;}
break;
- case 107: /* cmd ::= DROP TABLE ifexists fullname */
+ case 109: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0, yymsp[-1].minor.yy4);
}
break;
- case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
+ case 112: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
{
- sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392);
+ sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy387, yymsp[-6].minor.yy4, yymsp[-4].minor.yy4);
}
break;
- case 111: /* cmd ::= DROP VIEW ifexists fullname */
+ case 113: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1, yymsp[-1].minor.yy4);
}
break;
- case 112: /* cmd ::= select */
+ case 114: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy159, &dest);
+ sqlite3Select(pParse, yymsp[0].minor.yy387, &dest);
sqlite3ExplainBegin(pParse->pVdbe);
- sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159);
+ sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy387);
sqlite3ExplainFinish(pParse->pVdbe);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387);
}
break;
- case 113: /* select ::= oneselect */
-{yygotominor.yy159 = yymsp[0].minor.yy159;}
+ case 115: /* select ::= oneselect */
+{yygotominor.yy387 = yymsp[0].minor.yy387;}
break;
- case 114: /* select ::= select multiselect_op oneselect */
+ case 116: /* select ::= select multiselect_op oneselect */
{
- if( yymsp[0].minor.yy159 ){
- yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392;
- yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159;
+ if( yymsp[0].minor.yy387 ){
+ yymsp[0].minor.yy387->op = (u8)yymsp[-1].minor.yy4;
+ yymsp[0].minor.yy387->pPrior = yymsp[-2].minor.yy387;
+ if( yymsp[-1].minor.yy4!=TK_ALL ) pParse->hasCompound = 1;
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159);
+ sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy387);
}
- yygotominor.yy159 = yymsp[0].minor.yy159;
+ yygotominor.yy387 = yymsp[0].minor.yy387;
}
break;
- case 116: /* multiselect_op ::= UNION ALL */
-{yygotominor.yy392 = TK_ALL;}
+ case 118: /* multiselect_op ::= UNION ALL */
+{yygotominor.yy4 = TK_ALL;}
break;
- case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ case 120: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
+ yygotominor.yy387 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy259,yymsp[-4].minor.yy314,yymsp[-3].minor.yy322,yymsp[-2].minor.yy314,yymsp[-1].minor.yy322,yymsp[-7].minor.yy177,yymsp[0].minor.yy292.pLimit,yymsp[0].minor.yy292.pOffset);
}
break;
- case 119: /* distinct ::= DISTINCT */
-{yygotominor.yy305 = SF_Distinct;}
+ case 121: /* distinct ::= DISTINCT */
+{yygotominor.yy177 = SF_Distinct;}
break;
- case 120: /* distinct ::= ALL */
- case 121: /* distinct ::= */ yytestcase(yyruleno==121);
-{yygotominor.yy305 = 0;}
+ case 122: /* distinct ::= ALL */
+ case 123: /* distinct ::= */ yytestcase(yyruleno==123);
+{yygotominor.yy177 = 0;}
break;
- case 122: /* sclp ::= selcollist COMMA */
- case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
-{yygotominor.yy442 = yymsp[-1].minor.yy442;}
+ case 124: /* sclp ::= selcollist COMMA */
+ case 248: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==248);
+{yygotominor.yy322 = yymsp[-1].minor.yy322;}
break;
- case 123: /* sclp ::= */
- case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
- case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158);
- case 239: /* exprlist ::= */ yytestcase(yyruleno==239);
- case 245: /* idxlist_opt ::= */ yytestcase(yyruleno==245);
-{yygotominor.yy442 = 0;}
+ case 125: /* sclp ::= */
+ case 153: /* orderby_opt ::= */ yytestcase(yyruleno==153);
+ case 160: /* groupby_opt ::= */ yytestcase(yyruleno==160);
+ case 241: /* exprlist ::= */ yytestcase(yyruleno==241);
+ case 247: /* idxlist_opt ::= */ yytestcase(yyruleno==247);
+{yygotominor.yy322 = 0;}
break;
- case 124: /* selcollist ::= sclp expr as */
+ case 126: /* selcollist ::= sclp expr as */
{
- yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr);
- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1);
- sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, yymsp[-1].minor.yy118.pExpr);
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[0].minor.yy0, 1);
+ sqlite3ExprListSetSpan(pParse,yygotominor.yy322,&yymsp[-1].minor.yy118);
}
break;
- case 125: /* selcollist ::= sclp STAR */
+ case 127: /* selcollist ::= sclp STAR */
{
Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0);
- yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy322, p);
}
break;
- case 126: /* selcollist ::= sclp nm DOT STAR */
+ case 128: /* selcollist ::= sclp nm DOT STAR */
{
Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, pDot);
}
break;
- case 129: /* as ::= */
+ case 131: /* as ::= */
{yygotominor.yy0.n = 0;}
break;
- case 130: /* from ::= */
-{yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));}
+ case 132: /* from ::= */
+{yygotominor.yy259 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy259));}
break;
- case 131: /* from ::= FROM seltablist */
+ case 133: /* from ::= FROM seltablist */
{
- yygotominor.yy347 = yymsp[0].minor.yy347;
- sqlite3SrcListShiftJoinType(yygotominor.yy347);
+ yygotominor.yy259 = yymsp[0].minor.yy259;
+ sqlite3SrcListShiftJoinType(yygotominor.yy259);
}
break;
- case 132: /* stl_prefix ::= seltablist joinop */
+ case 134: /* stl_prefix ::= seltablist joinop */
{
- yygotominor.yy347 = yymsp[-1].minor.yy347;
- if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392;
+ yygotominor.yy259 = yymsp[-1].minor.yy259;
+ if( ALWAYS(yygotominor.yy259 && yygotominor.yy259->nSrc>0) ) yygotominor.yy259->a[yygotominor.yy259->nSrc-1].jointype = (u8)yymsp[0].minor.yy4;
}
break;
- case 133: /* stl_prefix ::= */
-{yygotominor.yy347 = 0;}
+ case 135: /* stl_prefix ::= */
+{yygotominor.yy259 = 0;}
break;
- case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ case 136: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
- yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
- sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0);
+ yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
+ sqlite3SrcListIndexedBy(pParse, yygotominor.yy259, &yymsp[-2].minor.yy0);
}
break;
- case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ case 137: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
- yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+ yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy387,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
}
break;
- case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ case 138: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
- if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
- yygotominor.yy347 = yymsp[-4].minor.yy347;
- }else if( yymsp[-4].minor.yy347->nSrc==1 ){
- yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
- if( yygotominor.yy347 ){
- struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
- struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
+ if( yymsp[-6].minor.yy259==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy314==0 && yymsp[0].minor.yy384==0 ){
+ yygotominor.yy259 = yymsp[-4].minor.yy259;
+ }else if( yymsp[-4].minor.yy259->nSrc==1 ){
+ yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
+ if( yygotominor.yy259 ){
+ struct SrcList_item *pNew = &yygotominor.yy259->a[yygotominor.yy259->nSrc-1];
+ struct SrcList_item *pOld = yymsp[-4].minor.yy259->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy259);
}else{
Select *pSubquery;
- sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
- yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy259);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy259,0,0,0,0,SF_NestedFrom,0,0);
+ yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy314,yymsp[0].minor.yy384);
}
}
break;
- case 137: /* dbnm ::= */
- case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
+ case 139: /* dbnm ::= */
+ case 148: /* indexed_opt ::= */ yytestcase(yyruleno==148);
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
break;
- case 139: /* fullname ::= nm dbnm */
-{yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
+ case 141: /* fullname ::= nm dbnm */
+{yygotominor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
break;
- case 140: /* joinop ::= COMMA|JOIN */
-{ yygotominor.yy392 = JT_INNER; }
+ case 142: /* joinop ::= COMMA|JOIN */
+{ yygotominor.yy4 = JT_INNER; }
break;
- case 141: /* joinop ::= JOIN_KW JOIN */
-{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+ case 143: /* joinop ::= JOIN_KW JOIN */
+{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
break;
- case 142: /* joinop ::= JOIN_KW nm JOIN */
-{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
+ case 144: /* joinop ::= JOIN_KW nm JOIN */
+{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
break;
- case 143: /* joinop ::= JOIN_KW nm nm JOIN */
-{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
+ case 145: /* joinop ::= JOIN_KW nm nm JOIN */
+{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
break;
- case 144: /* on_opt ::= ON expr */
- case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161);
- case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168);
- case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234);
- case 236: /* case_operand ::= expr */ yytestcase(yyruleno==236);
-{yygotominor.yy122 = yymsp[0].minor.yy342.pExpr;}
+ case 146: /* on_opt ::= ON expr */
+ case 163: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==163);
+ case 170: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==170);
+ case 236: /* case_else ::= ELSE expr */ yytestcase(yyruleno==236);
+ case 238: /* case_operand ::= expr */ yytestcase(yyruleno==238);
+{yygotominor.yy314 = yymsp[0].minor.yy118.pExpr;}
break;
- case 145: /* on_opt ::= */
- case 160: /* having_opt ::= */ yytestcase(yyruleno==160);
- case 167: /* where_opt ::= */ yytestcase(yyruleno==167);
- case 235: /* case_else ::= */ yytestcase(yyruleno==235);
- case 237: /* case_operand ::= */ yytestcase(yyruleno==237);
-{yygotominor.yy122 = 0;}
+ case 147: /* on_opt ::= */
+ case 162: /* having_opt ::= */ yytestcase(yyruleno==162);
+ case 169: /* where_opt ::= */ yytestcase(yyruleno==169);
+ case 237: /* case_else ::= */ yytestcase(yyruleno==237);
+ case 239: /* case_operand ::= */ yytestcase(yyruleno==239);
+{yygotominor.yy314 = 0;}
break;
- case 148: /* indexed_opt ::= NOT INDEXED */
+ case 150: /* indexed_opt ::= NOT INDEXED */
{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
break;
- case 149: /* using_opt ::= USING LP inscollist RP */
- case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180);
-{yygotominor.yy180 = yymsp[-1].minor.yy180;}
+ case 151: /* using_opt ::= USING LP idlist RP */
+ case 182: /* inscollist_opt ::= LP idlist RP */ yytestcase(yyruleno==182);
+{yygotominor.yy384 = yymsp[-1].minor.yy384;}
break;
- case 150: /* using_opt ::= */
- case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179);
-{yygotominor.yy180 = 0;}
+ case 152: /* using_opt ::= */
+ case 181: /* inscollist_opt ::= */ yytestcase(yyruleno==181);
+{yygotominor.yy384 = 0;}
break;
- case 152: /* orderby_opt ::= ORDER BY sortlist */
- case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159);
- case 238: /* exprlist ::= nexprlist */ yytestcase(yyruleno==238);
-{yygotominor.yy442 = yymsp[0].minor.yy442;}
+ case 154: /* orderby_opt ::= ORDER BY sortlist */
+ case 161: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==161);
+ case 240: /* exprlist ::= nexprlist */ yytestcase(yyruleno==240);
+{yygotominor.yy322 = yymsp[0].minor.yy322;}
break;
- case 153: /* sortlist ::= sortlist COMMA expr sortorder */
+ case 155: /* sortlist ::= sortlist COMMA expr sortorder */
{
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr);
- if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322,yymsp[-1].minor.yy118.pExpr);
+ if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4;
}
break;
- case 154: /* sortlist ::= expr sortorder */
+ case 156: /* sortlist ::= expr sortorder */
{
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr);
- if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392;
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy118.pExpr);
+ if( yygotominor.yy322 && ALWAYS(yygotominor.yy322->a) ) yygotominor.yy322->a[0].sortOrder = (u8)yymsp[0].minor.yy4;
}
break;
- case 155: /* sortorder ::= ASC */
- case 157: /* sortorder ::= */ yytestcase(yyruleno==157);
-{yygotominor.yy392 = SQLITE_SO_ASC;}
+ case 157: /* sortorder ::= ASC */
+ case 159: /* sortorder ::= */ yytestcase(yyruleno==159);
+{yygotominor.yy4 = SQLITE_SO_ASC;}
break;
- case 156: /* sortorder ::= DESC */
-{yygotominor.yy392 = SQLITE_SO_DESC;}
+ case 158: /* sortorder ::= DESC */
+{yygotominor.yy4 = SQLITE_SO_DESC;}
break;
- case 162: /* limit_opt ::= */
-{yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;}
+ case 164: /* limit_opt ::= */
+{yygotominor.yy292.pLimit = 0; yygotominor.yy292.pOffset = 0;}
break;
- case 163: /* limit_opt ::= LIMIT expr */
-{yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;}
+ case 165: /* limit_opt ::= LIMIT expr */
+{yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr; yygotominor.yy292.pOffset = 0;}
break;
- case 164: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;}
+ case 166: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yygotominor.yy292.pLimit = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pOffset = yymsp[0].minor.yy118.pExpr;}
break;
- case 165: /* limit_opt ::= LIMIT expr COMMA expr */
-{yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;}
+ case 167: /* limit_opt ::= LIMIT expr COMMA expr */
+{yygotominor.yy292.pOffset = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr;}
break;
- case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
+ case 168: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0);
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy259, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy259,yymsp[0].minor.yy314);
}
break;
- case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
+ case 171: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list");
- sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258);
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy259, &yymsp[-3].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy322,"set list");
+ sqlite3Update(pParse,yymsp[-4].minor.yy259,yymsp[-1].minor.yy322,yymsp[0].minor.yy314,yymsp[-5].minor.yy210);
}
break;
- case 170: /* setlist ::= setlist COMMA nm EQ expr */
+ case 172: /* setlist ::= setlist COMMA nm EQ expr */
{
- yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr);
- sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy118.pExpr);
+ sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1);
}
break;
- case 171: /* setlist ::= nm EQ expr */
+ case 173: /* setlist ::= nm EQ expr */
{
- yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr);
- sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy118.pExpr);
+ sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1);
}
break;
- case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
-{sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
+ case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
+{sqlite3Insert(pParse, yymsp[-2].minor.yy259, yymsp[0].minor.yy260.pList, yymsp[0].minor.yy260.pSelect, yymsp[-1].minor.yy384, yymsp[-4].minor.yy210);}
break;
- case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
-{sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);}
+ case 175: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
+{sqlite3Insert(pParse, yymsp[-2].minor.yy259, 0, yymsp[0].minor.yy387, yymsp[-1].minor.yy384, yymsp[-4].minor.yy210);}
break;
- case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
-{sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);}
+ case 176: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
+{sqlite3Insert(pParse, yymsp[-3].minor.yy259, 0, 0, yymsp[-2].minor.yy384, yymsp[-5].minor.yy210);}
break;
- case 175: /* insert_cmd ::= INSERT orconf */
-{yygotominor.yy258 = yymsp[0].minor.yy258;}
+ case 177: /* insert_cmd ::= INSERT orconf */
+{yygotominor.yy210 = yymsp[0].minor.yy210;}
break;
- case 176: /* insert_cmd ::= REPLACE */
-{yygotominor.yy258 = OE_Replace;}
+ case 178: /* insert_cmd ::= REPLACE */
+{yygotominor.yy210 = OE_Replace;}
break;
- case 177: /* valuelist ::= VALUES LP nexprlist RP */
+ case 179: /* valuelist ::= VALUES LP nexprlist RP */
{
- yygotominor.yy487.pList = yymsp[-1].minor.yy442;
- yygotominor.yy487.pSelect = 0;
+ yygotominor.yy260.pList = yymsp[-1].minor.yy322;
+ yygotominor.yy260.pSelect = 0;
}
break;
- case 178: /* valuelist ::= valuelist COMMA LP exprlist RP */
+ case 180: /* valuelist ::= valuelist COMMA LP exprlist RP */
{
- Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0);
- if( yymsp[-4].minor.yy487.pList ){
- yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0);
- yymsp[-4].minor.yy487.pList = 0;
+ Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy322, 0, 0, 0, 0, 0, 0, 0, 0);
+ if( yymsp[-4].minor.yy260.pList ){
+ yymsp[-4].minor.yy260.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy260.pList, 0, 0, 0, 0, 0, 0, 0, 0);
+ yymsp[-4].minor.yy260.pList = 0;
}
- yygotominor.yy487.pList = 0;
- if( yymsp[-4].minor.yy487.pSelect==0 || pRight==0 ){
+ yygotominor.yy260.pList = 0;
+ if( yymsp[-4].minor.yy260.pSelect==0 || pRight==0 ){
sqlite3SelectDelete(pParse->db, pRight);
- sqlite3SelectDelete(pParse->db, yymsp[-4].minor.yy487.pSelect);
- yygotominor.yy487.pSelect = 0;
+ sqlite3SelectDelete(pParse->db, yymsp[-4].minor.yy260.pSelect);
+ yygotominor.yy260.pSelect = 0;
}else{
pRight->op = TK_ALL;
- pRight->pPrior = yymsp[-4].minor.yy487.pSelect;
+ pRight->pPrior = yymsp[-4].minor.yy260.pSelect;
pRight->selFlags |= SF_Values;
pRight->pPrior->selFlags |= SF_Values;
- yygotominor.yy487.pSelect = pRight;
+ yygotominor.yy260.pSelect = pRight;
}
}
break;
- case 181: /* inscollist ::= inscollist COMMA nm */
-{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);}
+ case 183: /* idlist ::= idlist COMMA nm */
+{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy384,&yymsp[0].minor.yy0);}
break;
- case 182: /* inscollist ::= nm */
-{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
+ case 184: /* idlist ::= nm */
+{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
break;
- case 183: /* expr ::= term */
-{yygotominor.yy342 = yymsp[0].minor.yy342;}
+ case 185: /* expr ::= term */
+{yygotominor.yy118 = yymsp[0].minor.yy118;}
break;
- case 184: /* expr ::= LP expr RP */
-{yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
+ case 186: /* expr ::= LP expr RP */
+{yygotominor.yy118.pExpr = yymsp[-1].minor.yy118.pExpr; spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
break;
- case 185: /* term ::= NULL */
- case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190);
- case 191: /* term ::= STRING */ yytestcase(yyruleno==191);
-{spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
+ case 187: /* term ::= NULL */
+ case 192: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==192);
+ case 193: /* term ::= STRING */ yytestcase(yyruleno==193);
+{spanExpr(&yygotominor.yy118, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
break;
- case 186: /* expr ::= id */
- case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187);
-{spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);}
+ case 188: /* expr ::= id */
+ case 189: /* expr ::= JOIN_KW */ yytestcase(yyruleno==189);
+{spanExpr(&yygotominor.yy118, pParse, TK_ID, &yymsp[0].minor.yy0);}
break;
- case 188: /* expr ::= nm DOT nm */
+ case 190: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
- spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+ spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
}
break;
- case 189: /* expr ::= nm DOT nm DOT nm */
+ case 191: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
- spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
+ spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
}
break;
- case 192: /* expr ::= REGISTER */
+ case 194: /* expr ::= REGISTER */
{
/* When doing a nested parse, one can include terms in an expression
** that look like this: #1 #2 ... These terms refer to registers
** in the virtual machine. #N is the N-th register. */
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0);
- yygotominor.yy342.pExpr = 0;
+ yygotominor.yy118.pExpr = 0;
}else{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
- if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
+ if( yygotominor.yy118.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy118.pExpr->iTable);
}
- spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+ spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 193: /* expr ::= VARIABLE */
+ case 195: /* expr ::= VARIABLE */
{
- spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
- sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr);
- spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+ spanExpr(&yygotominor.yy118, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
+ sqlite3ExprAssignVarNumber(pParse, yygotominor.yy118.pExpr);
+ spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 194: /* expr ::= expr COLLATE ids */
+ case 196: /* expr ::= expr COLLATE ids */
{
- yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
- yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
- yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ yygotominor.yy118.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy118.pExpr, &yymsp[0].minor.yy0);
+ yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart;
+ yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 195: /* expr ::= CAST LP expr AS typetoken RP */
+ case 197: /* expr ::= CAST LP expr AS typetoken RP */
{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0);
- spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy118.pExpr, 0, &yymsp[-1].minor.yy0);
+ spanSet(&yygotominor.yy118,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
}
break;
- case 196: /* expr ::= ID LP distinct exprlist RP */
+ case 198: /* expr ::= ID LP distinct exprlist RP */
{
- if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
+ if( yymsp[-1].minor.yy322 && yymsp[-1].minor.yy322->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
}
- yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
- spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
- if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->flags |= EP_Distinct;
+ yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0);
+ spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+ if( yymsp[-2].minor.yy177 && yygotominor.yy118.pExpr ){
+ yygotominor.yy118.pExpr->flags |= EP_Distinct;
}
}
break;
- case 197: /* expr ::= ID LP STAR RP */
+ case 199: /* expr ::= ID LP STAR RP */
{
- yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
- spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+ spanSet(&yygotominor.yy118,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
break;
- case 198: /* term ::= CTIME_KW */
+ case 200: /* term ::= CTIME_KW */
{
- /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
- ** treated as functions that return constants */
- yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
- if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->op = TK_CONST_FUNC;
- }
- spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
+ yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0);
+ spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 199: /* expr ::= expr AND expr */
- case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200);
- case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201);
- case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202);
- case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203);
- case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204);
- case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205);
- case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206);
-{spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);}
+ case 201: /* expr ::= expr AND expr */
+ case 202: /* expr ::= expr OR expr */ yytestcase(yyruleno==202);
+ case 203: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==203);
+ case 204: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==204);
+ case 205: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==205);
+ case 206: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==206);
+ case 207: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==207);
+ case 208: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==208);
+{spanBinaryExpr(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118);}
break;
- case 207: /* likeop ::= LIKE_KW */
- case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209);
-{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 0;}
+ case 209: /* likeop ::= LIKE_KW */
+ case 211: /* likeop ::= MATCH */ yytestcase(yyruleno==211);
+{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.bNot = 0;}
break;
- case 208: /* likeop ::= NOT LIKE_KW */
- case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210);
-{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 1;}
+ case 210: /* likeop ::= NOT LIKE_KW */
+ case 212: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==212);
+{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.bNot = 1;}
break;
- case 211: /* expr ::= expr likeop expr */
+ case 213: /* expr ::= expr likeop expr */
{
ExprList *pList;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr);
- yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator);
- if( yymsp[-1].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
- yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
- yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
- if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy118.pExpr);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy118.pExpr);
+ yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy342.eOperator);
+ if( yymsp[-1].minor.yy342.bNot ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
+ yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart;
+ yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd;
+ if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc;
}
break;
- case 212: /* expr ::= expr likeop expr ESCAPE expr */
+ case 214: /* expr ::= expr likeop expr ESCAPE expr */
{
ExprList *pList;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
- yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator);
- if( yymsp[-3].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
- yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
- yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
- if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy118.pExpr);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr);
+ yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy342.eOperator);
+ if( yymsp[-3].minor.yy342.bNot ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
+ yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart;
+ yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd;
+ if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc;
}
break;
- case 213: /* expr ::= expr ISNULL|NOTNULL */
-{spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);}
+ case 215: /* expr ::= expr ISNULL|NOTNULL */
+{spanUnaryPostfix(&yygotominor.yy118,pParse,yymsp[0].major,&yymsp[-1].minor.yy118,&yymsp[0].minor.yy0);}
break;
- case 214: /* expr ::= expr NOT NULL */
-{spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);}
+ case 216: /* expr ::= expr NOT NULL */
+{spanUnaryPostfix(&yygotominor.yy118,pParse,TK_NOTNULL,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy0);}
break;
- case 215: /* expr ::= expr IS expr */
+ case 217: /* expr ::= expr IS expr */
{
- spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL);
+ spanBinaryExpr(&yygotominor.yy118,pParse,TK_IS,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_ISNULL);
}
break;
- case 216: /* expr ::= expr IS NOT expr */
+ case 218: /* expr ::= expr IS NOT expr */
{
- spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL);
+ spanBinaryExpr(&yygotominor.yy118,pParse,TK_ISNOT,&yymsp[-3].minor.yy118,&yymsp[0].minor.yy118);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_NOTNULL);
}
break;
- case 217: /* expr ::= NOT expr */
- case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218);
-{spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+ case 219: /* expr ::= NOT expr */
+ case 220: /* expr ::= BITNOT expr */ yytestcase(yyruleno==220);
+{spanUnaryPrefix(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);}
break;
- case 219: /* expr ::= MINUS expr */
-{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+ case 221: /* expr ::= MINUS expr */
+{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UMINUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);}
break;
- case 220: /* expr ::= PLUS expr */
-{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);}
+ case 222: /* expr ::= PLUS expr */
+{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UPLUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);}
break;
- case 223: /* expr ::= expr between_op expr AND expr */
+ case 225: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr);
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0);
- if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->x.pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy118.pExpr, 0, 0);
+ if( yygotominor.yy118.pExpr ){
+ yygotominor.yy118.pExpr->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
- yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
- yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd;
+ if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
+ yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart;
+ yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd;
}
break;
- case 226: /* expr ::= expr in_op LP exprlist RP */
+ case 228: /* expr ::= expr in_op LP exprlist RP */
{
- if( yymsp[-1].minor.yy442==0 ){
+ if( yymsp[-1].minor.yy322==0 ){
/* Expressions of the form
**
** expr1 IN ()
@@ -112971,224 +117189,225 @@ static void yy_reduce(
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy392]);
- sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy342.pExpr);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy4]);
+ sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy118.pExpr);
}else{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
- if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->x.pList = yymsp[-1].minor.yy442;
- sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0);
+ if( yygotominor.yy118.pExpr ){
+ yygotominor.yy118.pExpr->x.pList = yymsp[-1].minor.yy322;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy442);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322);
}
- if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
+ if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
}
- yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
- yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart;
+ yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 227: /* expr ::= LP select RP */
+ case 229: /* expr ::= LP select RP */
{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
- if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
- ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
- sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy118.pExpr ){
+ yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387;
+ ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387);
}
- yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z;
- yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ yygotominor.yy118.zStart = yymsp[-2].minor.yy0.z;
+ yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 228: /* expr ::= expr in_op LP select RP */
+ case 230: /* expr ::= expr in_op LP select RP */
{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0);
- if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159;
- ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
- sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0);
+ if( yygotominor.yy118.pExpr ){
+ yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387;
+ ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387);
}
- if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
- yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart;
- yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
+ yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart;
+ yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 229: /* expr ::= expr in_op nm dbnm */
+ case 231: /* expr ::= expr in_op nm dbnm */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0);
- if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
- ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect);
- sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy118.pExpr, 0, 0);
+ if( yygotominor.yy118.pExpr ){
+ yygotominor.yy118.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
+ ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
}else{
sqlite3SrcListDelete(pParse->db, pSrc);
}
- if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0);
- yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart;
- yygotominor.yy342.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
+ if( yymsp[-2].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0);
+ yygotominor.yy118.zStart = yymsp[-3].minor.yy118.zStart;
+ yygotominor.yy118.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
}
break;
- case 230: /* expr ::= EXISTS LP select RP */
+ case 232: /* expr ::= EXISTS LP select RP */
{
- Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+ Expr *p = yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
if( p ){
- p->x.pSelect = yymsp[-1].minor.yy159;
+ p->x.pSelect = yymsp[-1].minor.yy387;
ExprSetProperty(p, EP_xIsSelect);
sqlite3ExprSetHeight(pParse, p);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387);
}
- yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
- yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z;
+ yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 231: /* expr ::= CASE case_operand case_exprlist case_else END */
+ case 233: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0);
- if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442;
- sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr);
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy314, 0, 0);
+ if( yygotominor.yy118.pExpr ){
+ yygotominor.yy118.pExpr->x.pList = yymsp[-1].minor.yy314 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[-1].minor.yy314) : yymsp[-2].minor.yy322;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy442);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322);
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy314);
}
- yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z;
- yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ yygotominor.yy118.zStart = yymsp[-4].minor.yy0.z;
+ yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ case 234: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr);
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy118.pExpr);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr);
}
break;
- case 233: /* case_exprlist ::= WHEN expr THEN expr */
+ case 235: /* case_exprlist ::= WHEN expr THEN expr */
{
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr);
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr);
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr);
}
break;
- case 240: /* nexprlist ::= nexprlist COMMA expr */
-{yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);}
+ case 242: /* nexprlist ::= nexprlist COMMA expr */
+{yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy118.pExpr);}
break;
- case 241: /* nexprlist ::= expr */
-{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);}
+ case 243: /* nexprlist ::= expr */
+{yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy118.pExpr);}
break;
- case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
+ case 244: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP where_opt */
{
- sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
- sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392,
- &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392);
+ sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
+ sqlite3SrcListAppend(pParse->db,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy4,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy314, SQLITE_SO_ASC, yymsp[-8].minor.yy4);
}
break;
- case 243: /* uniqueflag ::= UNIQUE */
- case 296: /* raisetype ::= ABORT */ yytestcase(yyruleno==296);
-{yygotominor.yy392 = OE_Abort;}
+ case 245: /* uniqueflag ::= UNIQUE */
+ case 298: /* raisetype ::= ABORT */ yytestcase(yyruleno==298);
+{yygotominor.yy4 = OE_Abort;}
break;
- case 244: /* uniqueflag ::= */
-{yygotominor.yy392 = OE_None;}
+ case 246: /* uniqueflag ::= */
+{yygotominor.yy4 = OE_None;}
break;
- case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
+ case 249: /* idxlist ::= idxlist COMMA nm collate sortorder */
{
Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
- sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
- if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, p);
+ sqlite3ExprListSetName(pParse,yygotominor.yy322,&yymsp[-2].minor.yy0,1);
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy322, "index");
+ if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4;
}
break;
- case 248: /* idxlist ::= nm collate sortorder */
+ case 250: /* idxlist ::= nm collate sortorder */
{
Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
- yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
- sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
- if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392;
+ yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, p);
+ sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1);
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy322, "index");
+ if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4;
}
break;
- case 249: /* collate ::= */
+ case 251: /* collate ::= */
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
break;
- case 251: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);}
+ case 253: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy259, yymsp[-1].minor.yy4);}
break;
- case 252: /* cmd ::= VACUUM */
- case 253: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==253);
+ case 254: /* cmd ::= VACUUM */
+ case 255: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==255);
{sqlite3Vacuum(pParse);}
break;
- case 254: /* cmd ::= PRAGMA nm dbnm */
+ case 256: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 255: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 257: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 256: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 258: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 257: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 259: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
- case 258: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ case 260: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
- case 268: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ case 270: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all);
}
break;
- case 269: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 271: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy4, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy259, yymsp[0].minor.yy314, yymsp[-10].minor.yy4, yymsp[-8].minor.yy4);
yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
}
break;
- case 270: /* trigger_time ::= BEFORE */
- case 273: /* trigger_time ::= */ yytestcase(yyruleno==273);
-{ yygotominor.yy392 = TK_BEFORE; }
+ case 272: /* trigger_time ::= BEFORE */
+ case 275: /* trigger_time ::= */ yytestcase(yyruleno==275);
+{ yygotominor.yy4 = TK_BEFORE; }
break;
- case 271: /* trigger_time ::= AFTER */
-{ yygotominor.yy392 = TK_AFTER; }
+ case 273: /* trigger_time ::= AFTER */
+{ yygotominor.yy4 = TK_AFTER; }
break;
- case 272: /* trigger_time ::= INSTEAD OF */
-{ yygotominor.yy392 = TK_INSTEAD;}
+ case 274: /* trigger_time ::= INSTEAD OF */
+{ yygotominor.yy4 = TK_INSTEAD;}
break;
- case 274: /* trigger_event ::= DELETE|INSERT */
- case 275: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==275);
-{yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;}
+ case 276: /* trigger_event ::= DELETE|INSERT */
+ case 277: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==277);
+{yygotominor.yy90.a = yymsp[0].major; yygotominor.yy90.b = 0;}
break;
- case 276: /* trigger_event ::= UPDATE OF inscollist */
-{yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;}
+ case 278: /* trigger_event ::= UPDATE OF idlist */
+{yygotominor.yy90.a = TK_UPDATE; yygotominor.yy90.b = yymsp[0].minor.yy384;}
break;
- case 279: /* when_clause ::= */
- case 301: /* key_opt ::= */ yytestcase(yyruleno==301);
-{ yygotominor.yy122 = 0; }
+ case 281: /* when_clause ::= */
+ case 303: /* key_opt ::= */ yytestcase(yyruleno==303);
+{ yygotominor.yy314 = 0; }
break;
- case 280: /* when_clause ::= WHEN expr */
- case 302: /* key_opt ::= KEY expr */ yytestcase(yyruleno==302);
-{ yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; }
+ case 282: /* when_clause ::= WHEN expr */
+ case 304: /* key_opt ::= KEY expr */ yytestcase(yyruleno==304);
+{ yygotominor.yy314 = yymsp[0].minor.yy118.pExpr; }
break;
- case 281: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 283: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- assert( yymsp[-2].minor.yy327!=0 );
- yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327;
- yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327;
- yygotominor.yy327 = yymsp[-2].minor.yy327;
+ assert( yymsp[-2].minor.yy203!=0 );
+ yymsp[-2].minor.yy203->pLast->pNext = yymsp[-1].minor.yy203;
+ yymsp[-2].minor.yy203->pLast = yymsp[-1].minor.yy203;
+ yygotominor.yy203 = yymsp[-2].minor.yy203;
}
break;
- case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ case 284: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
- assert( yymsp[-1].minor.yy327!=0 );
- yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327;
- yygotominor.yy327 = yymsp[-1].minor.yy327;
+ assert( yymsp[-1].minor.yy203!=0 );
+ yymsp[-1].minor.yy203->pLast = yymsp[-1].minor.yy203;
+ yygotominor.yy203 = yymsp[-1].minor.yy203;
}
break;
- case 284: /* trnm ::= nm DOT nm */
+ case 286: /* trnm ::= nm DOT nm */
{
yygotominor.yy0 = yymsp[0].minor.yy0;
sqlite3ErrorMsg(pParse,
@@ -113196,121 +117415,121 @@ static void yy_reduce(
"statements within triggers");
}
break;
- case 286: /* tridxby ::= INDEXED BY nm */
+ case 288: /* tridxby ::= INDEXED BY nm */
{
sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 287: /* tridxby ::= NOT INDEXED */
+ case 289: /* tridxby ::= NOT INDEXED */
{
sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 288: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
-{ yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); }
+ case 290: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
+{ yygotominor.yy203 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy322, yymsp[0].minor.yy314, yymsp[-5].minor.yy210); }
break;
- case 289: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
-{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);}
+ case 291: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
+{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy384, yymsp[0].minor.yy260.pList, yymsp[0].minor.yy260.pSelect, yymsp[-4].minor.yy210);}
break;
- case 290: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
-{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);}
+ case 292: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
+{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy384, 0, yymsp[0].minor.yy387, yymsp[-4].minor.yy210);}
break;
- case 291: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
-{yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);}
+ case 293: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
+{yygotominor.yy203 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy314);}
break;
- case 292: /* trigger_cmd ::= select */
-{yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); }
+ case 294: /* trigger_cmd ::= select */
+{yygotominor.yy203 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy387); }
break;
- case 293: /* expr ::= RAISE LP IGNORE RP */
+ case 295: /* expr ::= RAISE LP IGNORE RP */
{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
- if( yygotominor.yy342.pExpr ){
- yygotominor.yy342.pExpr->affinity = OE_Ignore;
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
+ if( yygotominor.yy118.pExpr ){
+ yygotominor.yy118.pExpr->affinity = OE_Ignore;
}
- yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z;
- yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z;
+ yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 296: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
- if( yygotominor.yy342.pExpr ) {
- yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392;
+ yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ if( yygotominor.yy118.pExpr ) {
+ yygotominor.yy118.pExpr->affinity = (char)yymsp[-3].minor.yy4;
}
- yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z;
- yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
+ yygotominor.yy118.zStart = yymsp[-5].minor.yy0.z;
+ yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
break;
- case 295: /* raisetype ::= ROLLBACK */
-{yygotominor.yy392 = OE_Rollback;}
+ case 297: /* raisetype ::= ROLLBACK */
+{yygotominor.yy4 = OE_Rollback;}
break;
- case 297: /* raisetype ::= FAIL */
-{yygotominor.yy392 = OE_Fail;}
+ case 299: /* raisetype ::= FAIL */
+{yygotominor.yy4 = OE_Fail;}
break;
- case 298: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 300: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy259,yymsp[-1].minor.yy4);
}
break;
- case 299: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 301: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy118.pExpr, yymsp[-1].minor.yy118.pExpr, yymsp[0].minor.yy314);
}
break;
- case 300: /* cmd ::= DETACH database_kw_opt expr */
+ case 302: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr);
+ sqlite3Detach(pParse, yymsp[0].minor.yy118.pExpr);
}
break;
- case 305: /* cmd ::= REINDEX */
+ case 307: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 306: /* cmd ::= REINDEX nm dbnm */
+ case 308: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 307: /* cmd ::= ANALYZE */
+ case 309: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 308: /* cmd ::= ANALYZE nm dbnm */
+ case 310: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 309: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 311: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy259,&yymsp[0].minor.yy0);
}
break;
- case 310: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+ case 312: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
break;
- case 311: /* add_column_fullname ::= fullname */
+ case 313: /* add_column_fullname ::= fullname */
{
pParse->db->lookaside.bEnabled = 0;
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259);
}
break;
- case 314: /* cmd ::= create_vtab */
+ case 316: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 315: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 317: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 316: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 318: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
- sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392);
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy4);
}
break;
- case 319: /* vtabarg ::= */
+ case 321: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 321: /* vtabargtoken ::= ANY */
- case 322: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==322);
- case 323: /* lp ::= LP */ yytestcase(yyruleno==323);
+ case 323: /* vtabargtoken ::= ANY */
+ case 324: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==324);
+ case 325: /* lp ::= LP */ yytestcase(yyruleno==325);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
default:
@@ -113325,30 +117544,30 @@ static void yy_reduce(
/* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20);
/* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
/* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25);
- /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
- /* (35) columnlist ::= column */ yytestcase(yyruleno==35);
- /* (44) type ::= */ yytestcase(yyruleno==44);
- /* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
- /* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
- /* (53) carglist ::= carglist ccons */ yytestcase(yyruleno==53);
- /* (54) carglist ::= */ yytestcase(yyruleno==54);
- /* (61) ccons ::= NULL onconf */ yytestcase(yyruleno==61);
- /* (89) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==89);
- /* (90) conslist ::= tcons */ yytestcase(yyruleno==90);
- /* (92) tconscomma ::= */ yytestcase(yyruleno==92);
- /* (277) foreach_clause ::= */ yytestcase(yyruleno==277);
- /* (278) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==278);
- /* (285) tridxby ::= */ yytestcase(yyruleno==285);
- /* (303) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==303);
- /* (304) database_kw_opt ::= */ yytestcase(yyruleno==304);
- /* (312) kwcolumn_opt ::= */ yytestcase(yyruleno==312);
- /* (313) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==313);
- /* (317) vtabarglist ::= vtabarg */ yytestcase(yyruleno==317);
- /* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318);
- /* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320);
- /* (324) anylist ::= */ yytestcase(yyruleno==324);
- /* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325);
- /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
+ /* (36) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==36);
+ /* (37) columnlist ::= column */ yytestcase(yyruleno==37);
+ /* (46) type ::= */ yytestcase(yyruleno==46);
+ /* (53) signed ::= plus_num */ yytestcase(yyruleno==53);
+ /* (54) signed ::= minus_num */ yytestcase(yyruleno==54);
+ /* (55) carglist ::= carglist ccons */ yytestcase(yyruleno==55);
+ /* (56) carglist ::= */ yytestcase(yyruleno==56);
+ /* (63) ccons ::= NULL onconf */ yytestcase(yyruleno==63);
+ /* (91) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==91);
+ /* (92) conslist ::= tcons */ yytestcase(yyruleno==92);
+ /* (94) tconscomma ::= */ yytestcase(yyruleno==94);
+ /* (279) foreach_clause ::= */ yytestcase(yyruleno==279);
+ /* (280) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==280);
+ /* (287) tridxby ::= */ yytestcase(yyruleno==287);
+ /* (305) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==305);
+ /* (306) database_kw_opt ::= */ yytestcase(yyruleno==306);
+ /* (314) kwcolumn_opt ::= */ yytestcase(yyruleno==314);
+ /* (315) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==315);
+ /* (319) vtabarglist ::= vtabarg */ yytestcase(yyruleno==319);
+ /* (320) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==320);
+ /* (322) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==322);
+ /* (326) anylist ::= */ yytestcase(yyruleno==326);
+ /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327);
+ /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328);
break;
};
assert( yyruleno>=0 && yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
@@ -113687,20 +117906,20 @@ const unsigned char ebcdicToAscii[] = {
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
-/* Hash score: 175 */
+/* Hash score: 177 */
static int keywordCode(const char *z, int n){
- /* zText[] encodes 811 bytes of keywords in 541 bytes */
+ /* zText[] encodes 819 bytes of keywords in 545 bytes */
/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
/* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */
/* XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY */
- /* UNIQUERYATTACHAVINGROUPDATEBEGINNERELEASEBETWEENOTNULLIKE */
- /* CASCADELETECASECOLLATECREATECURRENT_DATEDETACHIMMEDIATEJOIN */
- /* SERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHENWHERENAME */
- /* AFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */
- /* CURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOBYIF */
- /* ISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUMVIEW */
+ /* UNIQUERYWITHOUTERELEASEATTACHAVINGROUPDATEBEGINNERENAMEBETWEEN */
+ /* OTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATEDETACH */
+ /* IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN */
+ /* WHEREPLACEAFTERESTRICTANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT */
+ /* CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAIL */
+ /* FROMFULLGLOBYIFISNULLORDERIGHTROLLBACKROWUNIONUSINGVACUUMVIEW */
/* INITIALLY */
- static const char zText[540] = {
+ static const char zText[544] = {
'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
@@ -113711,76 +117930,77 @@ static int keywordCode(const char *z, int n){
'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E',
'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T',
'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
- 'U','E','R','Y','A','T','T','A','C','H','A','V','I','N','G','R','O','U',
- 'P','D','A','T','E','B','E','G','I','N','N','E','R','E','L','E','A','S',
- 'E','B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C',
- 'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L',
- 'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D',
- 'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E',
- 'J','O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A',
- 'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U',
- 'E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E','N','W',
- 'H','E','R','E','N','A','M','E','A','F','T','E','R','E','P','L','A','C',
- 'E','A','N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R',
- 'E','M','E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M',
- 'M','I','T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U',
- 'R','R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M',
- 'A','R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T',
- 'D','R','O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L',
- 'O','B','Y','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S',
- 'T','R','I','C','T','O','U','T','E','R','I','G','H','T','R','O','L','L',
- 'B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N','G','V',
- 'A','C','U','U','M','V','I','E','W','I','N','I','T','I','A','L','L','Y',
+ 'U','E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S',
+ 'E','A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A',
+ 'T','E','B','E','G','I','N','N','E','R','E','N','A','M','E','B','E','T',
+ 'W','E','E','N','O','T','N','U','L','L','I','K','E','C','A','S','C','A',
+ 'D','E','L','E','T','E','C','A','S','E','C','O','L','L','A','T','E','C',
+ 'R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E','D',
+ 'E','T','A','C','H','I','M','M','E','D','I','A','T','E','J','O','I','N',
+ 'S','E','R','T','M','A','T','C','H','P','L','A','N','A','L','Y','Z','E',
+ 'P','R','A','G','M','A','B','O','R','T','V','A','L','U','E','S','V','I',
+ 'R','T','U','A','L','I','M','I','T','W','H','E','N','W','H','E','R','E',
+ 'P','L','A','C','E','A','F','T','E','R','E','S','T','R','I','C','T','A',
+ 'N','D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E','M',
+ 'E','N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M','I',
+ 'T','C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R','R',
+ 'E','N','T','_','T','I','M','E','S','T','A','M','P','R','I','M','A','R',
+ 'Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D','R',
+ 'O','P','F','A','I','L','F','R','O','M','F','U','L','L','G','L','O','B',
+ 'Y','I','F','I','S','N','U','L','L','O','R','D','E','R','I','G','H','T',
+ 'R','O','L','L','B','A','C','K','R','O','W','U','N','I','O','N','U','S',
+ 'I','N','G','V','A','C','U','U','M','V','I','E','W','I','N','I','T','I',
+ 'A','L','L','Y',
};
static const unsigned char aHash[127] = {
- 72, 101, 114, 70, 0, 45, 0, 0, 78, 0, 73, 0, 0,
- 42, 12, 74, 15, 0, 113, 81, 50, 108, 0, 19, 0, 0,
- 118, 0, 116, 111, 0, 22, 89, 0, 9, 0, 0, 66, 67,
- 0, 65, 6, 0, 48, 86, 98, 0, 115, 97, 0, 0, 44,
- 0, 99, 24, 0, 17, 0, 119, 49, 23, 0, 5, 106, 25,
- 92, 0, 0, 121, 102, 56, 120, 53, 28, 51, 0, 87, 0,
- 96, 26, 0, 95, 0, 0, 0, 91, 88, 93, 84, 105, 14,
- 39, 104, 0, 77, 0, 18, 85, 107, 32, 0, 117, 76, 109,
- 58, 46, 80, 0, 0, 90, 40, 0, 112, 0, 36, 0, 0,
- 29, 0, 82, 59, 60, 0, 20, 57, 0, 52,
+ 75, 104, 115, 73, 0, 45, 0, 0, 81, 0, 76, 0, 0,
+ 42, 12, 77, 15, 0, 114, 84, 53, 111, 0, 19, 0, 0,
+ 119, 0, 117, 88, 0, 22, 92, 0, 9, 0, 0, 69, 70,
+ 0, 68, 6, 0, 48, 89, 101, 0, 116, 100, 0, 0, 44,
+ 0, 102, 24, 0, 17, 0, 120, 52, 23, 0, 5, 109, 25,
+ 95, 0, 0, 122, 105, 59, 121, 56, 28, 54, 0, 90, 0,
+ 99, 26, 0, 98, 0, 0, 0, 94, 91, 96, 87, 108, 14,
+ 39, 107, 0, 80, 0, 18, 86, 110, 32, 0, 118, 79, 112,
+ 61, 46, 83, 0, 0, 93, 40, 0, 113, 0, 36, 0, 0,
+ 29, 0, 85, 62, 63, 0, 20, 60, 0, 55,
};
- static const unsigned char aNext[121] = {
+ static const unsigned char aNext[122] = {
0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 43, 3, 47,
- 0, 0, 0, 0, 30, 0, 54, 0, 38, 0, 0, 0, 1,
- 62, 0, 0, 63, 0, 41, 0, 0, 0, 0, 0, 0, 0,
- 61, 0, 0, 0, 0, 31, 55, 16, 34, 10, 0, 0, 0,
- 0, 0, 0, 0, 11, 68, 75, 0, 8, 0, 100, 94, 0,
- 103, 0, 83, 0, 71, 0, 0, 110, 27, 37, 69, 79, 0,
- 35, 64, 0, 0,
+ 0, 0, 0, 0, 33, 0, 21, 0, 0, 0, 0, 0, 0,
+ 43, 3, 47, 0, 0, 0, 0, 30, 0, 57, 0, 38, 0,
+ 0, 0, 1, 65, 0, 0, 66, 0, 41, 0, 0, 0, 0,
+ 0, 0, 49, 64, 0, 0, 0, 51, 31, 0, 16, 34, 10,
+ 0, 0, 0, 0, 0, 0, 0, 11, 71, 78, 0, 8, 0,
+ 103, 97, 0, 106, 0, 58, 0, 74, 50, 27, 37, 72, 82,
+ 0, 35, 67, 0, 0,
};
- static const unsigned char aLen[121] = {
+ static const unsigned char aLen[122] = {
7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
11, 6, 2, 7, 5, 5, 9, 6, 9, 9, 7, 10, 10,
- 4, 6, 2, 3, 9, 4, 2, 6, 5, 6, 6, 5, 6,
- 5, 5, 7, 7, 7, 3, 2, 4, 4, 7, 3, 6, 4,
- 7, 6, 12, 6, 9, 4, 6, 5, 4, 7, 6, 5, 6,
- 7, 5, 4, 5, 6, 5, 7, 3, 7, 13, 2, 2, 4,
- 6, 6, 8, 5, 17, 12, 7, 8, 8, 2, 4, 4, 4,
- 4, 4, 2, 2, 6, 5, 8, 5, 5, 8, 3, 5, 5,
- 6, 4, 9, 3,
+ 4, 6, 2, 3, 9, 4, 2, 6, 5, 7, 5, 7, 6,
+ 6, 5, 6, 5, 5, 6, 7, 7, 3, 2, 4, 4, 7,
+ 3, 6, 4, 7, 6, 12, 6, 9, 4, 6, 5, 4, 7,
+ 6, 5, 6, 7, 5, 4, 5, 7, 5, 8, 3, 7, 13,
+ 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, 2,
+ 4, 4, 4, 4, 4, 2, 2, 6, 5, 5, 8, 3, 5,
+ 5, 6, 4, 9, 3,
};
- static const unsigned short int aOffset[121] = {
+ static const unsigned short int aOffset[122] = {
0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
86, 91, 95, 96, 101, 105, 109, 117, 122, 128, 136, 142, 152,
- 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 189, 194, 197,
- 203, 206, 210, 217, 223, 223, 223, 226, 229, 233, 234, 238, 244,
- 248, 255, 261, 273, 279, 288, 290, 296, 301, 303, 310, 315, 320,
- 326, 332, 337, 341, 344, 350, 354, 361, 363, 370, 372, 374, 383,
- 387, 393, 399, 407, 412, 412, 428, 435, 442, 443, 450, 454, 458,
- 462, 466, 469, 471, 473, 479, 483, 491, 495, 500, 508, 511, 516,
- 521, 527, 531, 536,
+ 159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 188, 192, 199,
+ 204, 209, 212, 218, 221, 225, 231, 237, 237, 237, 240, 243, 247,
+ 248, 252, 258, 262, 269, 275, 287, 293, 302, 304, 310, 315, 317,
+ 324, 329, 334, 340, 346, 351, 355, 358, 365, 369, 377, 379, 386,
+ 388, 390, 399, 403, 409, 415, 423, 428, 428, 444, 451, 458, 459,
+ 466, 470, 474, 478, 482, 485, 487, 489, 495, 499, 504, 512, 515,
+ 520, 525, 531, 535, 540,
};
- static const unsigned char aCode[121] = {
+ static const unsigned char aCode[122] = {
TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
@@ -113790,22 +118010,22 @@ static int keywordCode(const char *z, int n){
TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_SAVEPOINT,
TK_INTERSECT, TK_TRIGGER, TK_REFERENCES, TK_CONSTRAINT, TK_INTO,
TK_OFFSET, TK_OF, TK_SET, TK_TEMP, TK_TEMP,
- TK_OR, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING,
- TK_GROUP, TK_UPDATE, TK_BEGIN, TK_JOIN_KW, TK_RELEASE,
- TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL,
- TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DELETE, TK_CASE,
- TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE,
- TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, TK_ANALYZE,
- TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, TK_LIMIT,
- TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, TK_REPLACE,
- TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN,
- TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
- TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, TK_DISTINCT,
- TK_IS, TK_DROP, TK_FAIL, TK_FROM, TK_JOIN_KW,
- TK_LIKE_KW, TK_BY, TK_IF, TK_ISNULL, TK_ORDER,
- TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
- TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY,
- TK_ALL,
+ TK_OR, TK_UNIQUE, TK_QUERY, TK_WITHOUT, TK_JOIN_KW,
+ TK_RELEASE, TK_ATTACH, TK_HAVING, TK_GROUP, TK_UPDATE,
+ TK_BEGIN, TK_JOIN_KW, TK_RENAME, TK_BETWEEN, TK_NOTNULL,
+ TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW, TK_CASCADE,
+ TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE,
+ TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT,
+ TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT,
+ TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_WHERE,
+ TK_REPLACE, TK_AFTER, TK_RESTRICT, TK_AND, TK_DEFAULT,
+ TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, TK_COLUMNKW,
+ TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW,
+ TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP,
+ TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, TK_BY,
+ TK_IF, TK_ISNULL, TK_ORDER, TK_JOIN_KW, TK_ROLLBACK,
+ TK_ROW, TK_UNION, TK_USING, TK_VACUUM, TK_VIEW,
+ TK_INITIALLY, TK_ALL,
};
int h, i;
if( n<2 ) return TK_ID;
@@ -113862,79 +118082,80 @@ static int keywordCode(const char *z, int n){
testcase( i==45 ); /* OR */
testcase( i==46 ); /* UNIQUE */
testcase( i==47 ); /* QUERY */
- testcase( i==48 ); /* ATTACH */
- testcase( i==49 ); /* HAVING */
- testcase( i==50 ); /* GROUP */
- testcase( i==51 ); /* UPDATE */
- testcase( i==52 ); /* BEGIN */
- testcase( i==53 ); /* INNER */
- testcase( i==54 ); /* RELEASE */
- testcase( i==55 ); /* BETWEEN */
- testcase( i==56 ); /* NOTNULL */
- testcase( i==57 ); /* NOT */
- testcase( i==58 ); /* NO */
- testcase( i==59 ); /* NULL */
- testcase( i==60 ); /* LIKE */
- testcase( i==61 ); /* CASCADE */
- testcase( i==62 ); /* ASC */
- testcase( i==63 ); /* DELETE */
- testcase( i==64 ); /* CASE */
- testcase( i==65 ); /* COLLATE */
- testcase( i==66 ); /* CREATE */
- testcase( i==67 ); /* CURRENT_DATE */
- testcase( i==68 ); /* DETACH */
- testcase( i==69 ); /* IMMEDIATE */
- testcase( i==70 ); /* JOIN */
- testcase( i==71 ); /* INSERT */
- testcase( i==72 ); /* MATCH */
- testcase( i==73 ); /* PLAN */
- testcase( i==74 ); /* ANALYZE */
- testcase( i==75 ); /* PRAGMA */
- testcase( i==76 ); /* ABORT */
- testcase( i==77 ); /* VALUES */
- testcase( i==78 ); /* VIRTUAL */
- testcase( i==79 ); /* LIMIT */
- testcase( i==80 ); /* WHEN */
- testcase( i==81 ); /* WHERE */
- testcase( i==82 ); /* RENAME */
- testcase( i==83 ); /* AFTER */
- testcase( i==84 ); /* REPLACE */
- testcase( i==85 ); /* AND */
- testcase( i==86 ); /* DEFAULT */
- testcase( i==87 ); /* AUTOINCREMENT */
- testcase( i==88 ); /* TO */
- testcase( i==89 ); /* IN */
- testcase( i==90 ); /* CAST */
- testcase( i==91 ); /* COLUMN */
- testcase( i==92 ); /* COMMIT */
- testcase( i==93 ); /* CONFLICT */
- testcase( i==94 ); /* CROSS */
- testcase( i==95 ); /* CURRENT_TIMESTAMP */
- testcase( i==96 ); /* CURRENT_TIME */
- testcase( i==97 ); /* PRIMARY */
- testcase( i==98 ); /* DEFERRED */
- testcase( i==99 ); /* DISTINCT */
- testcase( i==100 ); /* IS */
- testcase( i==101 ); /* DROP */
- testcase( i==102 ); /* FAIL */
- testcase( i==103 ); /* FROM */
- testcase( i==104 ); /* FULL */
- testcase( i==105 ); /* GLOB */
- testcase( i==106 ); /* BY */
- testcase( i==107 ); /* IF */
- testcase( i==108 ); /* ISNULL */
- testcase( i==109 ); /* ORDER */
- testcase( i==110 ); /* RESTRICT */
- testcase( i==111 ); /* OUTER */
- testcase( i==112 ); /* RIGHT */
- testcase( i==113 ); /* ROLLBACK */
- testcase( i==114 ); /* ROW */
- testcase( i==115 ); /* UNION */
- testcase( i==116 ); /* USING */
- testcase( i==117 ); /* VACUUM */
- testcase( i==118 ); /* VIEW */
- testcase( i==119 ); /* INITIALLY */
- testcase( i==120 ); /* ALL */
+ testcase( i==48 ); /* WITHOUT */
+ testcase( i==49 ); /* OUTER */
+ testcase( i==50 ); /* RELEASE */
+ testcase( i==51 ); /* ATTACH */
+ testcase( i==52 ); /* HAVING */
+ testcase( i==53 ); /* GROUP */
+ testcase( i==54 ); /* UPDATE */
+ testcase( i==55 ); /* BEGIN */
+ testcase( i==56 ); /* INNER */
+ testcase( i==57 ); /* RENAME */
+ testcase( i==58 ); /* BETWEEN */
+ testcase( i==59 ); /* NOTNULL */
+ testcase( i==60 ); /* NOT */
+ testcase( i==61 ); /* NO */
+ testcase( i==62 ); /* NULL */
+ testcase( i==63 ); /* LIKE */
+ testcase( i==64 ); /* CASCADE */
+ testcase( i==65 ); /* ASC */
+ testcase( i==66 ); /* DELETE */
+ testcase( i==67 ); /* CASE */
+ testcase( i==68 ); /* COLLATE */
+ testcase( i==69 ); /* CREATE */
+ testcase( i==70 ); /* CURRENT_DATE */
+ testcase( i==71 ); /* DETACH */
+ testcase( i==72 ); /* IMMEDIATE */
+ testcase( i==73 ); /* JOIN */
+ testcase( i==74 ); /* INSERT */
+ testcase( i==75 ); /* MATCH */
+ testcase( i==76 ); /* PLAN */
+ testcase( i==77 ); /* ANALYZE */
+ testcase( i==78 ); /* PRAGMA */
+ testcase( i==79 ); /* ABORT */
+ testcase( i==80 ); /* VALUES */
+ testcase( i==81 ); /* VIRTUAL */
+ testcase( i==82 ); /* LIMIT */
+ testcase( i==83 ); /* WHEN */
+ testcase( i==84 ); /* WHERE */
+ testcase( i==85 ); /* REPLACE */
+ testcase( i==86 ); /* AFTER */
+ testcase( i==87 ); /* RESTRICT */
+ testcase( i==88 ); /* AND */
+ testcase( i==89 ); /* DEFAULT */
+ testcase( i==90 ); /* AUTOINCREMENT */
+ testcase( i==91 ); /* TO */
+ testcase( i==92 ); /* IN */
+ testcase( i==93 ); /* CAST */
+ testcase( i==94 ); /* COLUMN */
+ testcase( i==95 ); /* COMMIT */
+ testcase( i==96 ); /* CONFLICT */
+ testcase( i==97 ); /* CROSS */
+ testcase( i==98 ); /* CURRENT_TIMESTAMP */
+ testcase( i==99 ); /* CURRENT_TIME */
+ testcase( i==100 ); /* PRIMARY */
+ testcase( i==101 ); /* DEFERRED */
+ testcase( i==102 ); /* DISTINCT */
+ testcase( i==103 ); /* IS */
+ testcase( i==104 ); /* DROP */
+ testcase( i==105 ); /* FAIL */
+ testcase( i==106 ); /* FROM */
+ testcase( i==107 ); /* FULL */
+ testcase( i==108 ); /* GLOB */
+ testcase( i==109 ); /* BY */
+ testcase( i==110 ); /* IF */
+ testcase( i==111 ); /* ISNULL */
+ testcase( i==112 ); /* ORDER */
+ testcase( i==113 ); /* RIGHT */
+ testcase( i==114 ); /* ROLLBACK */
+ testcase( i==115 ); /* ROW */
+ testcase( i==116 ); /* UNION */
+ testcase( i==117 ); /* USING */
+ testcase( i==118 ); /* VACUUM */
+ testcase( i==119 ); /* VIEW */
+ testcase( i==120 ); /* INITIALLY */
+ testcase( i==121 ); /* ALL */
return aCode[i];
}
}
@@ -113943,7 +118164,7 @@ static int keywordCode(const char *z, int n){
SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char *z, int n){
return keywordCode((char*)z, n);
}
-#define SQLITE_N_KEYWORD 121
+#define SQLITE_N_KEYWORD 122
/************** End of keywordhash.h *****************************************/
/************** Continuing where we left off in tokenize.c *******************/
@@ -114007,7 +118228,6 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
case '-': {
if( z[1]=='-' ){
- /* IMP: R-50417-27976 -- syntax diagram for comments */
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
return i;
@@ -114040,7 +118260,6 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
*tokenType = TK_SLASH;
return 1;
}
- /* IMP: R-50417-27976 -- syntax diagram for comments */
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
@@ -114280,7 +118499,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
- if( db->activeVdbeCnt==0 ){
+ if( db->nVdbeActive==0 ){
db->u1.isInterrupted = 0;
}
pParse->rc = SQLITE_OK;
@@ -114392,7 +118611,6 @@ abort_parse:
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
sqlite3DbFree(db, pParse->azVar);
- sqlite3DbFree(db, pParse->aAlias);
while( pParse->pAinc ){
AutoincInfo *p = pParse->pAinc;
pParse->pAinc = p->pNext;
@@ -114902,6 +119120,9 @@ SQLITE_API char *sqlite3_data_directory = 0;
SQLITE_API int sqlite3_initialize(void){
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
int rc; /* Result code */
+#ifdef SQLITE_EXTRA_INIT
+ int bRunExtraInit = 0; /* Extra initialization needed */
+#endif
#ifdef SQLITE_OMIT_WSD
rc = sqlite3_wsd_init(4096, 24);
@@ -114999,6 +119220,9 @@ SQLITE_API int sqlite3_initialize(void){
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
sqlite3GlobalConfig.isInit = 1;
+#ifdef SQLITE_EXTRA_INIT
+ bRunExtraInit = 1;
+#endif
}
sqlite3GlobalConfig.inProgress = 0;
}
@@ -115039,7 +119263,7 @@ SQLITE_API int sqlite3_initialize(void){
** compile-time option.
*/
#ifdef SQLITE_EXTRA_INIT
- if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
+ if( bRunExtraInit ){
int SQLITE_EXTRA_INIT(const char*);
rc = SQLITE_EXTRA_INIT(0);
}
@@ -115227,8 +119451,8 @@ SQLITE_API int sqlite3_config(int op, ...){
memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
}else{
/* The heap pointer is not NULL, then install one of the
- ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
- ** ENABLE_MEMSYS5 is defined, return an error.
+ ** mem5.c/mem3.c methods. The enclosing #if guarantees at
+ ** least one of these methods is currently enabled.
*/
#ifdef SQLITE_ENABLE_MEMSYS3
sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
@@ -115247,7 +119471,7 @@ SQLITE_API int sqlite3_config(int op, ...){
break;
}
- /* Record a pointer to the logger funcction and its first argument.
+ /* Record a pointer to the logger function and its first argument.
** The default is NULL. Logging is disabled if the function pointer is
** NULL.
*/
@@ -115294,6 +119518,13 @@ SQLITE_API int sqlite3_config(int op, ...){
break;
}
+#if SQLITE_OS_WIN && defined(SQLITE_WIN32_MALLOC)
+ case SQLITE_CONFIG_WIN32_HEAPSIZE: {
+ sqlite3GlobalConfig.nHeap = va_arg(ap, int);
+ break;
+ }
+#endif
+
default: {
rc = SQLITE_ERROR;
break;
@@ -115486,7 +119717,7 @@ static int binCollFunc(
/*
** Another built-in collating sequence: NOCASE.
**
-** This collating sequence is intended to be used for "case independant
+** This collating sequence is intended to be used for "case independent
** comparison". SQLite's knowledge of upper and lower case equivalents
** extends only to the 26 characters used in the English language.
**
@@ -115809,7 +120040,6 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
inTrans = 1;
}
sqlite3BtreeRollback(p, tripCode);
- db->aDb[i].inTrans = 0;
}
}
sqlite3VtabRollback(db);
@@ -115823,6 +120053,8 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
+ db->nDeferredImmCons = 0;
+ db->flags &= ~SQLITE_DeferFKs;
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
@@ -115849,6 +120081,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_ABORT_ROLLBACK: zName = "SQLITE_ABORT_ROLLBACK"; break;
case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
case SQLITE_BUSY_RECOVERY: zName = "SQLITE_BUSY_RECOVERY"; break;
+ case SQLITE_BUSY_SNAPSHOT: zName = "SQLITE_BUSY_SNAPSHOT"; break;
case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
@@ -115883,6 +120116,8 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_IOERR_SEEK: zName = "SQLITE_IOERR_SEEK"; break;
case SQLITE_IOERR_DELETE_NOENT: zName = "SQLITE_IOERR_DELETE_NOENT";break;
case SQLITE_IOERR_MMAP: zName = "SQLITE_IOERR_MMAP"; break;
+ case SQLITE_IOERR_GETTEMPPATH: zName = "SQLITE_IOERR_GETTEMPPATH"; break;
+ case SQLITE_IOERR_CONVPATH: zName = "SQLITE_IOERR_CONVPATH"; break;
case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break;
case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
@@ -115891,6 +120126,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_CANTOPEN_NOTEMPDIR: zName = "SQLITE_CANTOPEN_NOTEMPDIR";break;
case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break;
case SQLITE_CANTOPEN_FULLPATH: zName = "SQLITE_CANTOPEN_FULLPATH"; break;
+ case SQLITE_CANTOPEN_CONVPATH: zName = "SQLITE_CANTOPEN_CONVPATH"; break;
case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
@@ -115909,6 +120145,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_CONSTRAINT_VTAB: zName = "SQLITE_CONSTRAINT_VTAB"; break;
case SQLITE_CONSTRAINT_FUNCTION:
zName = "SQLITE_CONSTRAINT_FUNCTION"; break;
+ case SQLITE_CONSTRAINT_ROWID: zName = "SQLITE_CONSTRAINT_ROWID"; break;
case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
@@ -115922,6 +120159,7 @@ SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
case SQLITE_NOTICE_RECOVER_ROLLBACK:
zName = "SQLITE_NOTICE_RECOVER_ROLLBACK"; break;
case SQLITE_WARNING: zName = "SQLITE_WARNING"; break;
+ case SQLITE_WARNING_AUTOINDEX: zName = "SQLITE_WARNING_AUTOINDEX"; break;
case SQLITE_DONE: zName = "SQLITE_DONE"; break;
}
}
@@ -116082,7 +120320,7 @@ SQLITE_API void sqlite3_progress_handler(
sqlite3_mutex_enter(db->mutex);
if( nOps>0 ){
db->xProgress = xProgress;
- db->nProgressOps = nOps;
+ db->nProgressOps = (unsigned)nOps;
db->pProgressArg = pArg;
}else{
db->xProgress = 0;
@@ -116179,8 +120417,8 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
** operation to continue but invalidate all precompiled statements.
*/
p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0);
- if( p && p->iPrefEnc==enc && p->nArg==nArg ){
- if( db->activeVdbeCnt ){
+ if( p && (p->funcFlags & SQLITE_FUNC_ENCMASK)==enc && p->nArg==nArg ){
+ if( db->nVdbeActive ){
sqlite3Error(db, SQLITE_BUSY,
"unable to delete/modify user-function due to active statements");
assert( !db->mallocFailed );
@@ -116204,7 +120442,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
pDestructor->nRef++;
}
p->pDestructor = pDestructor;
- p->flags = 0;
+ p->funcFlags &= SQLITE_FUNC_ENCMASK;
p->xFunc = xFunc;
p->xStep = xStep;
p->xFinalize = xFinal;
@@ -116724,6 +120962,32 @@ SQLITE_API const char *sqlite3_errstr(int rc){
}
/*
+** Invalidate all cached KeyInfo objects for database connection "db"
+*/
+static void invalidateCachedKeyInfo(sqlite3 *db){
+ Db *pDb; /* A single database */
+ int iDb; /* The database index number */
+ HashElem *k; /* For looping over tables in pDb */
+ Table *pTab; /* A table in the database */
+ Index *pIdx; /* Each index */
+
+ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
+ if( pDb->pBt==0 ) continue;
+ sqlite3BtreeEnter(pDb->pBt);
+ for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
+ pTab = (Table*)sqliteHashData(k);
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){
+ sqlite3KeyInfoUnref(pIdx->pKeyInfo);
+ pIdx->pKeyInfo = 0;
+ }
+ }
+ }
+ sqlite3BtreeLeave(pDb->pBt);
+ }
+}
+
+/*
** Create a new collating function for database "db". The name is zName
** and the encoding is enc.
*/
@@ -116761,12 +121025,13 @@ static int createCollation(
*/
pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, 0);
if( pColl && pColl->xCmp ){
- if( db->activeVdbeCnt ){
+ if( db->nVdbeActive ){
sqlite3Error(db, SQLITE_BUSY,
"unable to delete/modify collation sequence due to active statements");
return SQLITE_BUSY;
}
sqlite3ExpirePreparedStatements(db);
+ invalidateCachedKeyInfo(db);
/* If collation sequence pColl was created directly by a call to
** sqlite3_create_collation, and not generated by synthCollSeq(),
@@ -116959,20 +121224,20 @@ SQLITE_PRIVATE int sqlite3ParseUri(
zFile = sqlite3_malloc(nByte);
if( !zFile ) return SQLITE_NOMEM;
+ iIn = 5;
+#ifndef SQLITE_ALLOW_URI_AUTHORITY
/* Discard the scheme and authority segments of the URI. */
if( zUri[5]=='/' && zUri[6]=='/' ){
iIn = 7;
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
-
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
*pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
iIn-7, &zUri[7]);
rc = SQLITE_ERROR;
goto parse_uri_out;
}
- }else{
- iIn = 5;
}
+#endif
/* Copy the filename and any query parameters into the zFile buffer.
** Decode %HH escape codes along the way.
@@ -117236,7 +121501,10 @@ static int openDatabase(
db->nextAutovac = -1;
db->szMmap = sqlite3GlobalConfig.szMmap;
db->nextPagesize = 0;
- db->flags |= SQLITE_ShortColNames | SQLITE_AutoIndex | SQLITE_EnableTrigger
+ db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill
+#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
+ | SQLITE_AutoIndex
+#endif
#if SQLITE_DEFAULT_FILE_FORMAT<4
| SQLITE_LegacyFileFmt
#endif
@@ -117576,8 +121844,6 @@ SQLITE_API int sqlite3_global_recover(void){
** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on
** by default. Autocommit is disabled by a BEGIN statement and reenabled
** by the next COMMIT or ROLLBACK.
-**
-******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
return db->autoCommit;
@@ -118033,6 +122299,19 @@ SQLITE_API int sqlite3_test_control(int op, ...){
}
#endif
+ /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
+ **
+ ** Set or clear a flag that indicates that the database file is always well-
+ ** formed and never corrupt. This flag is clear by default, indicating that
+ ** database files might have arbitrary corruption. Setting the flag during
+ ** testing causes certain assert() statements in the code to be activated
+ ** that demonstrat invariants on well-formed database files.
+ */
+ case SQLITE_TESTCTRL_NEVER_CORRUPT: {
+ sqlite3Config.neverCorrupt = va_arg(ap, int);
+ break;
+ }
+
}
va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */
@@ -118780,7 +123059,7 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){
/* If not building as part of the core, include sqlite3ext.h. */
#ifndef SQLITE_CORE
-SQLITE_API extern const sqlite3_api_routines *sqlite3_api;
+SQLITE_EXTENSION_INIT3
#endif
/************** Include fts3_tokenizer.h in the middle of fts3Int.h **********/
@@ -119067,6 +123346,18 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
/************** Continuing where we left off in fts3Int.h ********************/
/*
+** This constant determines the maximum depth of an FTS expression tree
+** that the library will create and use. FTS uses recursion to perform
+** various operations on the query tree, so the disadvantage of a large
+** limit is that it may allow very large queries to use large amounts
+** of stack space (perhaps causing a stack overflow).
+*/
+#ifndef SQLITE_FTS3_MAX_EXPR_DEPTH
+# define SQLITE_FTS3_MAX_EXPR_DEPTH 12
+#endif
+
+
+/*
** This constant controls how often segments are merged. Once there are
** FTS3_MERGE_COUNT segments of level N, they are merged into a single
** segment of level N+1.
@@ -119221,6 +123512,7 @@ struct Fts3Table {
const char *zName; /* virtual table name */
int nColumn; /* number of named columns in virtual table */
char **azColumn; /* column names. malloced */
+ u8 *abNotindexed; /* True for 'notindexed' columns */
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
char *zContentTbl; /* content=xxx option, or NULL */
char *zLanguageid; /* languageid=xxx option, or NULL */
@@ -119281,6 +123573,12 @@ struct Fts3Table {
int inTransaction; /* True after xBegin but before xCommit/xRollback */
int mxSavepoint; /* Largest valid xSavepoint integer */
#endif
+
+#ifdef SQLITE_TEST
+ /* True to disable the incremental doclist optimization. This is controled
+ ** by special insert command 'test-no-incr-doclist'. */
+ int bNoIncrDoclist;
+#endif
};
/*
@@ -119306,7 +123604,8 @@ struct Fts3Cursor {
int eEvalmode; /* An FTS3_EVAL_XX constant */
int nRowAvg; /* Average size of database rows, in pages */
sqlite3_int64 nDoc; /* Documents in table */
-
+ i64 iMinDocid; /* Minimum docid to return */
+ i64 iMaxDocid; /* Maximum docid to return */
int isMatchinfoNeeded; /* True when aMatchinfo[] needs filling in */
u32 *aMatchinfo; /* Information about most recent match */
int nMatchinfo; /* Number of elements in aMatchinfo[] */
@@ -119336,6 +123635,15 @@ struct Fts3Cursor {
#define FTS3_DOCID_SEARCH 1 /* Lookup by rowid on %_content table */
#define FTS3_FULLTEXT_SEARCH 2 /* Full-text index search */
+/*
+** The lower 16-bits of the sqlite3_index_info.idxNum value set by
+** the xBestIndex() method contains the Fts3Cursor.eSearch value described
+** above. The upper 16-bits contain a combination of the following
+** bits, used to describe extra constraints on full-text searches.
+*/
+#define FTS3_HAVE_LANGID 0x00010000 /* languageid=? */
+#define FTS3_HAVE_DOCID_GE 0x00020000 /* docid>=? */
+#define FTS3_HAVE_DOCID_LE 0x00040000 /* docid<=? */
struct Fts3Doclist {
char *aAll; /* Array containing doclist (or NULL) */
@@ -119448,7 +123756,6 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderPending(
Fts3Table*,int,const char*,int,int,Fts3SegReader**);
SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *);
SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **);
-SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *);
SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
@@ -119523,6 +123830,10 @@ struct Fts3MultiSegReader {
SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
+#define fts3GetVarint32(p, piVal) ( \
+ (*(u8*)(p)&0x80) ? sqlite3Fts3GetVarint32(p, piVal) : (*piVal=*(u8*)(p), 1) \
+)
+
/* fts3.c */
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
@@ -119630,21 +123941,37 @@ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
return (int) (q - (unsigned char *)p);
}
+#define GETVARINT_STEP(v, ptr, shift, mask1, mask2, var, ret) \
+ v = (v & mask1) | ( (*ptr++) << shift ); \
+ if( (v & mask2)==0 ){ var = v; return ret; }
+#define GETVARINT_INIT(v, ptr, shift, mask1, mask2, var, ret) \
+ v = (*ptr++); \
+ if( (v & mask2)==0 ){ var = v; return ret; }
+
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read, or 0 on error.
** The value is stored in *v.
*/
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
- const unsigned char *q = (const unsigned char *) p;
- sqlite_uint64 x = 0, y = 1;
- while( (*q&0x80)==0x80 && q-(unsigned char *)p<FTS3_VARINT_MAX ){
- x += y * (*q++ & 0x7f);
- y <<= 7;
- }
- x += y * (*q++);
- *v = (sqlite_int64) x;
- return (int) (q - (unsigned char *)p);
+ const char *pStart = p;
+ u32 a;
+ u64 b;
+ int shift;
+
+ GETVARINT_INIT(a, p, 0, 0x00, 0x80, *v, 1);
+ GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *v, 2);
+ GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *v, 3);
+ GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *v, 4);
+ b = (a & 0x0FFFFFFF );
+
+ for(shift=28; shift<=63; shift+=7){
+ u64 c = *p++;
+ b += (c&0x7F) << shift;
+ if( (c & 0x80)==0 ) break;
+ }
+ *v = b;
+ return (int)(p - pStart);
}
/*
@@ -119652,10 +123979,21 @@ SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
** 32-bit integer before it is returned.
*/
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *p, int *pi){
- sqlite_int64 i;
- int ret = sqlite3Fts3GetVarint(p, &i);
- *pi = (int) i;
- return ret;
+ u32 a;
+
+#ifndef fts3GetVarint32
+ GETVARINT_INIT(a, p, 0, 0x00, 0x80, *pi, 1);
+#else
+ a = (*p++);
+ assert( a & 0x80 );
+#endif
+
+ GETVARINT_STEP(a, p, 7, 0x7F, 0x4000, *pi, 2);
+ GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
+ GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
+ a = (a & 0x0FFFFFFF );
+ *pi = (int)(a | ((u32)(*p & 0x0F) << 28));
+ return 5;
}
/*
@@ -120381,6 +124719,8 @@ static int fts3InitVtab(
char *zUncompress = 0; /* uncompress=? parameter (or NULL) */
char *zContent = 0; /* content=? parameter (or NULL) */
char *zLanguageid = 0; /* languageid=? parameter (or NULL) */
+ char **azNotindexed = 0; /* The set of notindexed= columns */
+ int nNotindexed = 0; /* Size of azNotindexed[] array */
assert( strlen(argv[0])==4 );
assert( (sqlite3_strnicmp(argv[0], "fts4", 4)==0 && isFts4)
@@ -120390,9 +124730,19 @@ static int fts3InitVtab(
nDb = (int)strlen(argv[1]) + 1;
nName = (int)strlen(argv[2]) + 1;
- aCol = (const char **)sqlite3_malloc(sizeof(const char *) * (argc-2) );
- if( !aCol ) return SQLITE_NOMEM;
- memset((void *)aCol, 0, sizeof(const char *) * (argc-2));
+ nByte = sizeof(const char *) * (argc-2);
+ aCol = (const char **)sqlite3_malloc(nByte);
+ if( aCol ){
+ memset((void*)aCol, 0, nByte);
+ azNotindexed = (char **)sqlite3_malloc(nByte);
+ }
+ if( azNotindexed ){
+ memset(azNotindexed, 0, nByte);
+ }
+ if( !aCol || !azNotindexed ){
+ rc = SQLITE_NOMEM;
+ goto fts3_init_out;
+ }
/* Loop through all of the arguments passed by the user to the FTS3/4
** module (i.e. all the column names and special arguments). This loop
@@ -120431,7 +124781,8 @@ static int fts3InitVtab(
{ "uncompress", 10 }, /* 3 -> UNCOMPRESS */
{ "order", 5 }, /* 4 -> ORDER */
{ "content", 7 }, /* 5 -> CONTENT */
- { "languageid", 10 } /* 6 -> LANGUAGEID */
+ { "languageid", 10 }, /* 6 -> LANGUAGEID */
+ { "notindexed", 10 } /* 7 -> NOTINDEXED */
};
int iOpt;
@@ -120497,6 +124848,11 @@ static int fts3InitVtab(
zLanguageid = zVal;
zVal = 0;
break;
+
+ case 7: /* NOTINDEXED */
+ azNotindexed[nNotindexed++] = zVal;
+ zVal = 0;
+ break;
}
}
sqlite3_free(zVal);
@@ -120568,6 +124924,7 @@ static int fts3InitVtab(
nByte = sizeof(Fts3Table) + /* Fts3Table */
nCol * sizeof(char *) + /* azColumn */
nIndex * sizeof(struct Fts3Index) + /* aIndex */
+ nCol * sizeof(u8) + /* abNotindexed */
nName + /* zName */
nDb + /* zDb */
nString; /* Space for azColumn strings */
@@ -120601,9 +124958,10 @@ static int fts3InitVtab(
for(i=0; i<nIndex; i++){
fts3HashInit(&p->aIndex[i].hPending, FTS3_HASH_STRING, 1);
}
+ p->abNotindexed = (u8 *)&p->aIndex[nIndex];
/* Fill in the zName and zDb fields of the vtab structure. */
- zCsr = (char *)&p->aIndex[nIndex];
+ zCsr = (char *)&p->abNotindexed[nCol];
p->zName = zCsr;
memcpy(zCsr, argv[2], nName);
zCsr += nName;
@@ -120624,7 +124982,26 @@ static int fts3InitVtab(
assert( zCsr <= &((char *)p)[nByte] );
}
- if( (zCompress==0)!=(zUncompress==0) ){
+ /* Fill in the abNotindexed array */
+ for(iCol=0; iCol<nCol; iCol++){
+ int n = (int)strlen(p->azColumn[iCol]);
+ for(i=0; i<nNotindexed; i++){
+ char *zNot = azNotindexed[i];
+ if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){
+ p->abNotindexed[iCol] = 1;
+ sqlite3_free(zNot);
+ azNotindexed[i] = 0;
+ }
+ }
+ }
+ for(i=0; i<nNotindexed; i++){
+ if( azNotindexed[i] ){
+ *pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]);
+ rc = SQLITE_ERROR;
+ }
+ }
+
+ if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){
char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
rc = SQLITE_ERROR;
*pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss);
@@ -120665,7 +125042,9 @@ fts3_init_out:
sqlite3_free(zUncompress);
sqlite3_free(zContent);
sqlite3_free(zLanguageid);
+ for(i=0; i<nNotindexed; i++) sqlite3_free(azNotindexed[i]);
sqlite3_free((void *)aCol);
+ sqlite3_free((void *)azNotindexed);
if( rc!=SQLITE_OK ){
if( p ){
fts3DisconnectMethod((sqlite3_vtab *)p);
@@ -120716,23 +125095,27 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
Fts3Table *p = (Fts3Table *)pVTab;
int i; /* Iterator variable */
int iCons = -1; /* Index of constraint to use */
+
int iLangidCons = -1; /* Index of langid=x constraint, if present */
+ int iDocidGe = -1; /* Index of docid>=x constraint, if present */
+ int iDocidLe = -1; /* Index of docid<=x constraint, if present */
+ int iIdx;
/* By default use a full table scan. This is an expensive option,
** so search through the constraints to see if a more efficient
** strategy is possible.
*/
pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
- pInfo->estimatedCost = 500000;
+ pInfo->estimatedCost = 5000000;
for(i=0; i<pInfo->nConstraint; i++){
+ int bDocid; /* True if this constraint is on docid */
struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
if( pCons->usable==0 ) continue;
+ bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1);
+
/* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */
- if( iCons<0
- && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ
- && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 )
- ){
+ if( iCons<0 && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && bDocid ){
pInfo->idxNum = FTS3_DOCID_SEARCH;
pInfo->estimatedCost = 1.0;
iCons = i;
@@ -120761,14 +125144,38 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
){
iLangidCons = i;
}
+
+ if( bDocid ){
+ switch( pCons->op ){
+ case SQLITE_INDEX_CONSTRAINT_GE:
+ case SQLITE_INDEX_CONSTRAINT_GT:
+ iDocidGe = i;
+ break;
+
+ case SQLITE_INDEX_CONSTRAINT_LE:
+ case SQLITE_INDEX_CONSTRAINT_LT:
+ iDocidLe = i;
+ break;
+ }
+ }
}
+ iIdx = 1;
if( iCons>=0 ){
- pInfo->aConstraintUsage[iCons].argvIndex = 1;
+ pInfo->aConstraintUsage[iCons].argvIndex = iIdx++;
pInfo->aConstraintUsage[iCons].omit = 1;
}
if( iLangidCons>=0 ){
- pInfo->aConstraintUsage[iLangidCons].argvIndex = 2;
+ pInfo->idxNum |= FTS3_HAVE_LANGID;
+ pInfo->aConstraintUsage[iLangidCons].argvIndex = iIdx++;
+ }
+ if( iDocidGe>=0 ){
+ pInfo->idxNum |= FTS3_HAVE_DOCID_GE;
+ pInfo->aConstraintUsage[iDocidGe].argvIndex = iIdx++;
+ }
+ if( iDocidLe>=0 ){
+ pInfo->idxNum |= FTS3_HAVE_DOCID_LE;
+ pInfo->aConstraintUsage[iDocidLe].argvIndex = iIdx++;
}
/* Regardless of the strategy selected, FTS can deliver rows in rowid (or
@@ -120946,10 +125353,10 @@ static int fts3ScanInteriorNode(
/* Load the next term on the node into zBuffer. Use realloc() to expand
** the size of zBuffer if required. */
if( !isFirstTerm ){
- zCsr += sqlite3Fts3GetVarint32(zCsr, &nPrefix);
+ zCsr += fts3GetVarint32(zCsr, &nPrefix);
}
isFirstTerm = 0;
- zCsr += sqlite3Fts3GetVarint32(zCsr, &nSuffix);
+ zCsr += fts3GetVarint32(zCsr, &nSuffix);
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
rc = FTS_CORRUPT_VTAB;
@@ -121037,7 +125444,7 @@ static int fts3SelectLeaf(
assert( piLeaf || piLeaf2 );
- sqlite3Fts3GetVarint32(zNode, &iHeight);
+ fts3GetVarint32(zNode, &iHeight);
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
@@ -121239,11 +125646,11 @@ static void fts3PoslistMerge(
int iCol1; /* The current column index in pp1 */
int iCol2; /* The current column index in pp2 */
- if( *p1==POS_COLUMN ) sqlite3Fts3GetVarint32(&p1[1], &iCol1);
+ if( *p1==POS_COLUMN ) fts3GetVarint32(&p1[1], &iCol1);
else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
else iCol1 = 0;
- if( *p2==POS_COLUMN ) sqlite3Fts3GetVarint32(&p2[1], &iCol2);
+ if( *p2==POS_COLUMN ) fts3GetVarint32(&p2[1], &iCol2);
else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
else iCol2 = 0;
@@ -121336,11 +125743,11 @@ static int fts3PoslistPhraseMerge(
assert( p!=0 && *p1!=0 && *p2!=0 );
if( *p1==POS_COLUMN ){
p1++;
- p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+ p1 += fts3GetVarint32(p1, &iCol1);
}
if( *p2==POS_COLUMN ){
p2++;
- p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+ p2 += fts3GetVarint32(p2, &iCol2);
}
while( 1 ){
@@ -121390,9 +125797,9 @@ static int fts3PoslistPhraseMerge(
if( 0==*p1 || 0==*p2 ) break;
p1++;
- p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+ p1 += fts3GetVarint32(p1, &iCol1);
p2++;
- p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+ p2 += fts3GetVarint32(p2, &iCol2);
}
/* Advance pointer p1 or p2 (whichever corresponds to the smaller of
@@ -121404,12 +125811,12 @@ static int fts3PoslistPhraseMerge(
fts3ColumnlistCopy(0, &p1);
if( 0==*p1 ) break;
p1++;
- p1 += sqlite3Fts3GetVarint32(p1, &iCol1);
+ p1 += fts3GetVarint32(p1, &iCol1);
}else{
fts3ColumnlistCopy(0, &p2);
if( 0==*p2 ) break;
p2++;
- p2 += sqlite3Fts3GetVarint32(p2, &iCol2);
+ p2 += fts3GetVarint32(p2, &iCol2);
}
}
@@ -122216,6 +126623,33 @@ static int fts3NextMethod(sqlite3_vtab_cursor *pCursor){
}
/*
+** The following are copied from sqliteInt.h.
+**
+** Constants for the largest and smallest possible 64-bit signed integers.
+** These macros are designed to work correctly on both 32-bit and 64-bit
+** compilers.
+*/
+#ifndef SQLITE_AMALGAMATION
+# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
+# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
+#endif
+
+/*
+** If the numeric type of argument pVal is "integer", then return it
+** converted to a 64-bit signed integer. Otherwise, return a copy of
+** the second parameter, iDefault.
+*/
+static sqlite3_int64 fts3DocidRange(sqlite3_value *pVal, i64 iDefault){
+ if( pVal ){
+ int eType = sqlite3_value_numeric_type(pVal);
+ if( eType==SQLITE_INTEGER ){
+ return sqlite3_value_int64(pVal);
+ }
+ }
+ return iDefault;
+}
+
+/*
** This is the xFilter interface for the virtual table. See
** the virtual table xFilter method documentation for additional
** information.
@@ -122240,40 +126674,58 @@ static int fts3FilterMethod(
){
int rc;
char *zSql; /* SQL statement used to access %_content */
+ int eSearch;
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
+ sqlite3_value *pCons = 0; /* The MATCH or rowid constraint, if any */
+ sqlite3_value *pLangid = 0; /* The "langid = ?" constraint, if any */
+ sqlite3_value *pDocidGe = 0; /* The "docid >= ?" constraint, if any */
+ sqlite3_value *pDocidLe = 0; /* The "docid <= ?" constraint, if any */
+ int iIdx;
+
UNUSED_PARAMETER(idxStr);
UNUSED_PARAMETER(nVal);
- assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
- assert( nVal==0 || nVal==1 || nVal==2 );
- assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) );
+ eSearch = (idxNum & 0x0000FFFF);
+ assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
assert( p->pSegments==0 );
+ /* Collect arguments into local variables */
+ iIdx = 0;
+ if( eSearch!=FTS3_FULLSCAN_SEARCH ) pCons = apVal[iIdx++];
+ if( idxNum & FTS3_HAVE_LANGID ) pLangid = apVal[iIdx++];
+ if( idxNum & FTS3_HAVE_DOCID_GE ) pDocidGe = apVal[iIdx++];
+ if( idxNum & FTS3_HAVE_DOCID_LE ) pDocidLe = apVal[iIdx++];
+ assert( iIdx==nVal );
+
/* In case the cursor has been used before, clear it now. */
sqlite3_finalize(pCsr->pStmt);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
+ /* Set the lower and upper bounds on docids to return */
+ pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
+ pCsr->iMaxDocid = fts3DocidRange(pDocidLe, LARGEST_INT64);
+
if( idxStr ){
pCsr->bDesc = (idxStr[0]=='D');
}else{
pCsr->bDesc = p->bDescIdx;
}
- pCsr->eSearch = (i16)idxNum;
+ pCsr->eSearch = (i16)eSearch;
- if( idxNum!=FTS3_DOCID_SEARCH && idxNum!=FTS3_FULLSCAN_SEARCH ){
- int iCol = idxNum-FTS3_FULLTEXT_SEARCH;
- const char *zQuery = (const char *)sqlite3_value_text(apVal[0]);
+ if( eSearch!=FTS3_DOCID_SEARCH && eSearch!=FTS3_FULLSCAN_SEARCH ){
+ int iCol = eSearch-FTS3_FULLTEXT_SEARCH;
+ const char *zQuery = (const char *)sqlite3_value_text(pCons);
- if( zQuery==0 && sqlite3_value_type(apVal[0])!=SQLITE_NULL ){
+ if( zQuery==0 && sqlite3_value_type(pCons)!=SQLITE_NULL ){
return SQLITE_NOMEM;
}
pCsr->iLangid = 0;
- if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]);
+ if( pLangid ) pCsr->iLangid = sqlite3_value_int(pLangid);
assert( p->base.zErrMsg==0 );
rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid,
@@ -122284,11 +126736,7 @@ static int fts3FilterMethod(
return rc;
}
- rc = sqlite3Fts3ReadLock(p);
- if( rc!=SQLITE_OK ) return rc;
-
rc = fts3EvalStart(pCsr);
-
sqlite3Fts3SegmentsClose(p);
if( rc!=SQLITE_OK ) return rc;
pCsr->pNextId = pCsr->aDoclist;
@@ -122300,7 +126748,7 @@ static int fts3FilterMethod(
** full-text query or docid lookup, the statement retrieves a single
** row by docid.
*/
- if( idxNum==FTS3_FULLSCAN_SEARCH ){
+ if( eSearch==FTS3_FULLSCAN_SEARCH ){
zSql = sqlite3_mprintf(
"SELECT %s ORDER BY rowid %s",
p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
@@ -122311,10 +126759,10 @@ static int fts3FilterMethod(
}else{
rc = SQLITE_NOMEM;
}
- }else if( idxNum==FTS3_DOCID_SEARCH ){
+ }else if( eSearch==FTS3_DOCID_SEARCH ){
rc = fts3CursorSeekStmt(pCsr, &pCsr->pStmt);
if( rc==SQLITE_OK ){
- rc = sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
+ rc = sqlite3_bind_value(pCsr->pStmt, 1, pCons);
}
}
if( rc!=SQLITE_OK ) return rc;
@@ -123206,6 +127654,12 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
}
/*
+** Maximum number of tokens a phrase may have to be considered for the
+** incremental doclists strategy.
+*/
+#define MAX_INCR_PHRASE_TOKENS 4
+
+/*
** This function is called for each Fts3Phrase in a full-text query
** expression to initialize the mechanism for returning rows. Once this
** function has been called successfully on an Fts3Phrase, it may be
@@ -123218,23 +127672,43 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
** SQLITE_OK is returned if no error occurs, otherwise an SQLite error code.
*/
static int fts3EvalPhraseStart(Fts3Cursor *pCsr, int bOptOk, Fts3Phrase *p){
- int rc; /* Error code */
- Fts3PhraseToken *pFirst = &p->aToken[0];
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ int rc = SQLITE_OK; /* Error code */
+ int i;
- if( pCsr->bDesc==pTab->bDescIdx
- && bOptOk==1
- && p->nToken==1
- && pFirst->pSegcsr
- && pFirst->pSegcsr->bLookup
- && pFirst->bFirst==0
- ){
+ /* Determine if doclists may be loaded from disk incrementally. This is
+ ** possible if the bOptOk argument is true, the FTS doclists will be
+ ** scanned in forward order, and the phrase consists of
+ ** MAX_INCR_PHRASE_TOKENS or fewer tokens, none of which are are "^first"
+ ** tokens or prefix tokens that cannot use a prefix-index. */
+ int bHaveIncr = 0;
+ int bIncrOk = (bOptOk
+ && pCsr->bDesc==pTab->bDescIdx
+ && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
+ && p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
+#ifdef SQLITE_TEST
+ && pTab->bNoIncrDoclist==0
+#endif
+ );
+ for(i=0; bIncrOk==1 && i<p->nToken; i++){
+ Fts3PhraseToken *pToken = &p->aToken[i];
+ if( pToken->bFirst || (pToken->pSegcsr!=0 && !pToken->pSegcsr->bLookup) ){
+ bIncrOk = 0;
+ }
+ if( pToken->pSegcsr ) bHaveIncr = 1;
+ }
+
+ if( bIncrOk && bHaveIncr ){
/* Use the incremental approach. */
int iCol = (p->iColumn >= pTab->nColumn ? -1 : p->iColumn);
- rc = sqlite3Fts3MsrIncrStart(
- pTab, pFirst->pSegcsr, iCol, pFirst->z, pFirst->n);
+ for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
+ Fts3PhraseToken *pToken = &p->aToken[i];
+ Fts3MultiSegReader *pSegcsr = pToken->pSegcsr;
+ if( pSegcsr ){
+ rc = sqlite3Fts3MsrIncrStart(pTab, pSegcsr, iCol, pToken->z, pToken->n);
+ }
+ }
p->bIncr = 1;
-
}else{
/* Load the full doclist for the phrase into memory. */
rc = fts3EvalPhraseLoad(pCsr, p);
@@ -123344,15 +127818,125 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistNext(
}
/*
-** Attempt to move the phrase iterator to point to the next matching docid.
+** Advance the iterator pDL to the next entry in pDL->aAll/nAll. Set *pbEof
+** to true if EOF is reached.
+*/
+static void fts3EvalDlPhraseNext(
+ Fts3Table *pTab,
+ Fts3Doclist *pDL,
+ u8 *pbEof
+){
+ char *pIter; /* Used to iterate through aAll */
+ char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
+
+ if( pDL->pNextDocid ){
+ pIter = pDL->pNextDocid;
+ }else{
+ pIter = pDL->aAll;
+ }
+
+ if( pIter>=pEnd ){
+ /* We have already reached the end of this doclist. EOF. */
+ *pbEof = 1;
+ }else{
+ sqlite3_int64 iDelta;
+ pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
+ if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
+ pDL->iDocid += iDelta;
+ }else{
+ pDL->iDocid -= iDelta;
+ }
+ pDL->pList = pIter;
+ fts3PoslistCopy(0, &pIter);
+ pDL->nList = (int)(pIter - pDL->pList);
+
+ /* pIter now points just past the 0x00 that terminates the position-
+ ** list for document pDL->iDocid. However, if this position-list was
+ ** edited in place by fts3EvalNearTrim(), then pIter may not actually
+ ** point to the start of the next docid value. The following line deals
+ ** with this case by advancing pIter past the zero-padding added by
+ ** fts3EvalNearTrim(). */
+ while( pIter<pEnd && *pIter==0 ) pIter++;
+
+ pDL->pNextDocid = pIter;
+ assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
+ *pbEof = 0;
+ }
+}
+
+/*
+** Helper type used by fts3EvalIncrPhraseNext() and incrPhraseTokenNext().
+*/
+typedef struct TokenDoclist TokenDoclist;
+struct TokenDoclist {
+ int bIgnore;
+ sqlite3_int64 iDocid;
+ char *pList;
+ int nList;
+};
+
+/*
+** Token pToken is an incrementally loaded token that is part of a
+** multi-token phrase. Advance it to the next matching document in the
+** database and populate output variable *p with the details of the new
+** entry. Or, if the iterator has reached EOF, set *pbEof to true.
+**
** If an error occurs, return an SQLite error code. Otherwise, return
** SQLITE_OK.
+*/
+static int incrPhraseTokenNext(
+ Fts3Table *pTab, /* Virtual table handle */
+ Fts3Phrase *pPhrase, /* Phrase to advance token of */
+ int iToken, /* Specific token to advance */
+ TokenDoclist *p, /* OUT: Docid and doclist for new entry */
+ u8 *pbEof /* OUT: True if iterator is at EOF */
+){
+ int rc = SQLITE_OK;
+
+ if( pPhrase->iDoclistToken==iToken ){
+ assert( p->bIgnore==0 );
+ assert( pPhrase->aToken[iToken].pSegcsr==0 );
+ fts3EvalDlPhraseNext(pTab, &pPhrase->doclist, pbEof);
+ p->pList = pPhrase->doclist.pList;
+ p->nList = pPhrase->doclist.nList;
+ p->iDocid = pPhrase->doclist.iDocid;
+ }else{
+ Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
+ assert( pToken->pDeferred==0 );
+ assert( pToken->pSegcsr || pPhrase->iDoclistToken>=0 );
+ if( pToken->pSegcsr ){
+ assert( p->bIgnore==0 );
+ rc = sqlite3Fts3MsrIncrNext(
+ pTab, pToken->pSegcsr, &p->iDocid, &p->pList, &p->nList
+ );
+ if( p->pList==0 ) *pbEof = 1;
+ }else{
+ p->bIgnore = 1;
+ }
+ }
+
+ return rc;
+}
+
+
+/*
+** The phrase iterator passed as the second argument:
+**
+** * features at least one token that uses an incremental doclist, and
+**
+** * does not contain any deferred tokens.
+**
+** Advance it to the next matching documnent in the database and populate
+** the Fts3Doclist.pList and nList fields.
**
** If there is no "next" entry and no error occurs, then *pbEof is set to
** 1 before returning. Otherwise, if no error occurs and the iterator is
** successfully advanced, *pbEof is set to 0.
+**
+** If an error occurs, return an SQLite error code. Otherwise, return
+** SQLITE_OK.
*/
-static int fts3EvalPhraseNext(
+static int fts3EvalIncrPhraseNext(
Fts3Cursor *pCsr, /* FTS Cursor handle */
Fts3Phrase *p, /* Phrase object to advance to next docid */
u8 *pbEof /* OUT: Set to 1 if EOF */
@@ -123360,57 +127944,116 @@ static int fts3EvalPhraseNext(
int rc = SQLITE_OK;
Fts3Doclist *pDL = &p->doclist;
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+ u8 bEof = 0;
- if( p->bIncr ){
- assert( p->nToken==1 );
- assert( pDL->pNextDocid==0 );
+ /* This is only called if it is guaranteed that the phrase has at least
+ ** one incremental token. In which case the bIncr flag is set. */
+ assert( p->bIncr==1 );
+
+ if( p->nToken==1 && p->bIncr ){
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
&pDL->iDocid, &pDL->pList, &pDL->nList
);
- if( rc==SQLITE_OK && !pDL->pList ){
- *pbEof = 1;
+ if( pDL->pList==0 ) bEof = 1;
+ }else{
+ int bDescDoclist = pCsr->bDesc;
+ struct TokenDoclist a[MAX_INCR_PHRASE_TOKENS];
+
+ memset(a, 0, sizeof(a));
+ assert( p->nToken<=MAX_INCR_PHRASE_TOKENS );
+ assert( p->iDoclistToken<MAX_INCR_PHRASE_TOKENS );
+
+ while( bEof==0 ){
+ int bMaxSet = 0;
+ sqlite3_int64 iMax = 0; /* Largest docid for all iterators */
+ int i; /* Used to iterate through tokens */
+
+ /* Advance the iterator for each token in the phrase once. */
+ for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){
+ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
+ if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
+ iMax = a[i].iDocid;
+ bMaxSet = 1;
+ }
+ }
+ assert( rc!=SQLITE_OK || a[p->nToken-1].bIgnore==0 );
+ assert( rc!=SQLITE_OK || bMaxSet );
+
+ /* Keep advancing iterators until they all point to the same document */
+ for(i=0; i<p->nToken; i++){
+ while( rc==SQLITE_OK && bEof==0
+ && a[i].bIgnore==0 && DOCID_CMP(a[i].iDocid, iMax)<0
+ ){
+ rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
+ if( DOCID_CMP(a[i].iDocid, iMax)>0 ){
+ iMax = a[i].iDocid;
+ i = 0;
+ }
+ }
+ }
+
+ /* Check if the current entries really are a phrase match */
+ if( bEof==0 ){
+ int nList = 0;
+ int nByte = a[p->nToken-1].nList;
+ char *aDoclist = sqlite3_malloc(nByte+1);
+ if( !aDoclist ) return SQLITE_NOMEM;
+ memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
+
+ for(i=0; i<(p->nToken-1); i++){
+ if( a[i].bIgnore==0 ){
+ char *pL = a[i].pList;
+ char *pR = aDoclist;
+ char *pOut = aDoclist;
+ int nDist = p->nToken-1-i;
+ int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR);
+ if( res==0 ) break;
+ nList = (int)(pOut - aDoclist);
+ }
+ }
+ if( i==(p->nToken-1) ){
+ pDL->iDocid = iMax;
+ pDL->pList = aDoclist;
+ pDL->nList = nList;
+ pDL->bFreeList = 1;
+ break;
+ }
+ sqlite3_free(aDoclist);
+ }
}
+ }
+
+ *pbEof = bEof;
+ return rc;
+}
+
+/*
+** Attempt to move the phrase iterator to point to the next matching docid.
+** If an error occurs, return an SQLite error code. Otherwise, return
+** SQLITE_OK.
+**
+** If there is no "next" entry and no error occurs, then *pbEof is set to
+** 1 before returning. Otherwise, if no error occurs and the iterator is
+** successfully advanced, *pbEof is set to 0.
+*/
+static int fts3EvalPhraseNext(
+ Fts3Cursor *pCsr, /* FTS Cursor handle */
+ Fts3Phrase *p, /* Phrase object to advance to next docid */
+ u8 *pbEof /* OUT: Set to 1 if EOF */
+){
+ int rc = SQLITE_OK;
+ Fts3Doclist *pDL = &p->doclist;
+ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
+
+ if( p->bIncr ){
+ rc = fts3EvalIncrPhraseNext(pCsr, p, pbEof);
}else if( pCsr->bDesc!=pTab->bDescIdx && pDL->nAll ){
sqlite3Fts3DoclistPrev(pTab->bDescIdx, pDL->aAll, pDL->nAll,
&pDL->pNextDocid, &pDL->iDocid, &pDL->nList, pbEof
);
pDL->pList = pDL->pNextDocid;
}else{
- char *pIter; /* Used to iterate through aAll */
- char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
- if( pDL->pNextDocid ){
- pIter = pDL->pNextDocid;
- }else{
- pIter = pDL->aAll;
- }
-
- if( pIter>=pEnd ){
- /* We have already reached the end of this doclist. EOF. */
- *pbEof = 1;
- }else{
- sqlite3_int64 iDelta;
- pIter += sqlite3Fts3GetVarint(pIter, &iDelta);
- if( pTab->bDescIdx==0 || pDL->pNextDocid==0 ){
- pDL->iDocid += iDelta;
- }else{
- pDL->iDocid -= iDelta;
- }
- pDL->pList = pIter;
- fts3PoslistCopy(0, &pIter);
- pDL->nList = (int)(pIter - pDL->pList);
-
- /* pIter now points just past the 0x00 that terminates the position-
- ** list for document pDL->iDocid. However, if this position-list was
- ** edited in place by fts3EvalNearTrim(), then pIter may not actually
- ** point to the start of the next docid value. The following line deals
- ** with this case by advancing pIter past the zero-padding added by
- ** fts3EvalNearTrim(). */
- while( pIter<pEnd && *pIter==0 ) pIter++;
-
- pDL->pNextDocid = pIter;
- assert( pIter>=&pDL->aAll[pDL->nAll] || *pIter );
- *pbEof = 0;
- }
+ fts3EvalDlPhraseNext(pTab, pDL, pbEof);
}
return rc;
@@ -123435,7 +128078,6 @@ static int fts3EvalPhraseNext(
static void fts3EvalStartReaders(
Fts3Cursor *pCsr, /* FTS Cursor handle */
Fts3Expr *pExpr, /* Expression to initialize phrases in */
- int bOptOk, /* True to enable incremental loading */
int *pRc /* IN/OUT: Error code */
){
if( pExpr && SQLITE_OK==*pRc ){
@@ -123446,10 +128088,10 @@ static void fts3EvalStartReaders(
if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
}
pExpr->bDeferred = (i==nToken);
- *pRc = fts3EvalPhraseStart(pCsr, bOptOk, pExpr->pPhrase);
+ *pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
}else{
- fts3EvalStartReaders(pCsr, pExpr->pLeft, bOptOk, pRc);
- fts3EvalStartReaders(pCsr, pExpr->pRight, bOptOk, pRc);
+ fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
+ fts3EvalStartReaders(pCsr, pExpr->pRight, pRc);
pExpr->bDeferred = (pExpr->pLeft->bDeferred && pExpr->pRight->bDeferred);
}
}
@@ -123691,7 +128333,7 @@ static int fts3EvalSelectDeferred(
** overflowing the 32-bit integer it is stored in. */
if( ii<12 ) nLoad4 = nLoad4*4;
- if( ii==0 || pTC->pPhrase->nToken>1 ){
+ if( ii==0 || (pTC->pPhrase->nToken>1 && ii!=nToken-1) ){
/* Either this is the cheapest token in the entire query, or it is
** part of a multi-token phrase. Either way, the entire doclist will
** (eventually) be loaded into memory. It may as well be now. */
@@ -123771,7 +128413,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
}
#endif
- fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
+ fts3EvalStartReaders(pCsr, pCsr->pExpr, &rc);
return rc;
}
@@ -124254,6 +128896,16 @@ static int fts3EvalNext(Fts3Cursor *pCsr){
pCsr->iPrevId = pExpr->iDocid;
}while( pCsr->isEof==0 && fts3EvalTestDeferredAndNear(pCsr, &rc) );
}
+
+ /* Check if the cursor is past the end of the docid range specified
+ ** by Fts3Cursor.iMinDocid/iMaxDocid. If so, set the EOF flag. */
+ if( rc==SQLITE_OK && (
+ (pCsr->bDesc==0 && pCsr->iPrevId>pCsr->iMaxDocid)
+ || (pCsr->bDesc!=0 && pCsr->iPrevId<pCsr->iMinDocid)
+ )){
+ pCsr->isEof = 1;
+ }
+
return rc;
}
@@ -124277,12 +128929,16 @@ static void fts3EvalRestart(
if( pPhrase ){
fts3EvalInvalidatePoslist(pPhrase);
if( pPhrase->bIncr ){
- assert( pPhrase->nToken==1 );
- assert( pPhrase->aToken[0].pSegcsr );
- sqlite3Fts3MsrIncrRestart(pPhrase->aToken[0].pSegcsr);
+ int i;
+ for(i=0; i<pPhrase->nToken; i++){
+ Fts3PhraseToken *pToken = &pPhrase->aToken[i];
+ assert( pToken->pDeferred==0 );
+ if( pToken->pSegcsr ){
+ sqlite3Fts3MsrIncrRestart(pToken->pSegcsr);
+ }
+ }
*pRc = fts3EvalPhraseStart(pCsr, 0, pPhrase);
}
-
pPhrase->doclist.pNextDocid = 0;
pPhrase->doclist.iDocid = 0;
}
@@ -124327,7 +128983,7 @@ static void fts3EvalUpdateCounts(Fts3Expr *pExpr){
pExpr->aMI[iCol*3 + 2] += (iCnt>0);
if( *p==0x00 ) break;
p++;
- p += sqlite3Fts3GetVarint32(p, &iCol);
+ p += fts3GetVarint32(p, &iCol);
}
}
@@ -124531,15 +129187,23 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
pIter = pPhrase->doclist.pList;
if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
+ int iMul; /* +1 if csr dir matches index dir, else -1 */
int bOr = 0;
u8 bEof = 0;
- Fts3Expr *p;
+ u8 bTreeEof = 0;
+ Fts3Expr *p; /* Used to iterate from pExpr to root */
+ Fts3Expr *pNear; /* Most senior NEAR ancestor (or pExpr) */
/* Check if this phrase descends from an OR expression node. If not,
** return NULL. Otherwise, the entry that corresponds to docid
- ** pCsr->iPrevId may lie earlier in the doclist buffer. */
+ ** pCsr->iPrevId may lie earlier in the doclist buffer. Or, if the
+ ** tree that the node is part of has been marked as EOF, but the node
+ ** itself is not EOF, then it may point to an earlier entry. */
+ pNear = pExpr;
for(p=pExpr->pParent; p; p=p->pParent){
if( p->eType==FTSQUERY_OR ) bOr = 1;
+ if( p->eType==FTSQUERY_NEAR ) pNear = p;
+ if( p->bEof ) bTreeEof = 1;
}
if( bOr==0 ) return SQLITE_OK;
@@ -124558,29 +129222,59 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
if( rc!=SQLITE_OK ) return rc;
}
-
- if( pExpr->bEof ){
- pIter = 0;
- iDocid = 0;
+
+ iMul = ((pCsr->bDesc==bDescDoclist) ? 1 : -1);
+ while( bTreeEof==1
+ && pNear->bEof==0
+ && (DOCID_CMP(pNear->iDocid, pCsr->iPrevId) * iMul)<0
+ ){
+ int rc = SQLITE_OK;
+ fts3EvalNextRow(pCsr, pExpr, &rc);
+ if( rc!=SQLITE_OK ) return rc;
+ iDocid = pExpr->iDocid;
+ pIter = pPhrase->doclist.pList;
}
+
bEof = (pPhrase->doclist.nAll==0);
assert( bDescDoclist==0 || bDescDoclist==1 );
assert( pCsr->bDesc==0 || pCsr->bDesc==1 );
- if( pCsr->bDesc==bDescDoclist ){
- int dummy;
- while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
- sqlite3Fts3DoclistPrev(
- bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
- &pIter, &iDocid, &dummy, &bEof
- );
- }
- }else{
- while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
- sqlite3Fts3DoclistNext(
- bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
- &pIter, &iDocid, &bEof
- );
+ if( bEof==0 ){
+ if( pCsr->bDesc==bDescDoclist ){
+ int dummy;
+ if( pNear->bEof ){
+ /* This expression is already at EOF. So position it to point to the
+ ** last entry in the doclist at pPhrase->doclist.aAll[]. Variable
+ ** iDocid is already set for this entry, so all that is required is
+ ** to set pIter to point to the first byte of the last position-list
+ ** in the doclist.
+ **
+ ** It would also be correct to set pIter and iDocid to zero. In
+ ** this case, the first call to sqltie3Fts4DoclistPrev() below
+ ** would also move the iterator to point to the last entry in the
+ ** doclist. However, this is expensive, as to do so it has to
+ ** iterate through the entire doclist from start to finish (since
+ ** it does not know the docid for the last entry). */
+ pIter = &pPhrase->doclist.aAll[pPhrase->doclist.nAll-1];
+ fts3ReversePoslist(pPhrase->doclist.aAll, &pIter);
+ }
+ while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){
+ sqlite3Fts3DoclistPrev(
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
+ &pIter, &iDocid, &dummy, &bEof
+ );
+ }
+ }else{
+ if( pNear->bEof ){
+ pIter = 0;
+ iDocid = 0;
+ }
+ while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
+ sqlite3Fts3DoclistNext(
+ bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
+ &pIter, &iDocid, &bEof
+ );
+ }
}
}
@@ -124590,7 +129284,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
if( *pIter==0x01 ){
pIter++;
- pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
+ pIter += fts3GetVarint32(pIter, &iThis);
}else{
iThis = 0;
}
@@ -124598,7 +129292,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
fts3ColumnlistCopy(0, &pIter);
if( *pIter==0x00 ) return 0;
pIter++;
- pIter += sqlite3Fts3GetVarint32(pIter, &iThis);
+ pIter += fts3GetVarint32(pIter, &iThis);
}
*ppOut = ((iCol==iThis)?pIter:0);
@@ -124639,7 +129333,10 @@ SQLITE_PRIVATE int sqlite3Fts3Corrupt(){
/*
** Initialize API pointer table, if required.
*/
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_fts3_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
@@ -124685,6 +129382,7 @@ struct Fts3auxCursor {
Fts3SegFilter filter;
char *zStop;
int nStop; /* Byte-length of string zStop */
+ int iLangid; /* Language id to query */
int isEof; /* True if cursor is at EOF */
sqlite3_int64 iRowid; /* Current rowid */
@@ -124699,7 +129397,8 @@ struct Fts3auxCursor {
/*
** Schema of the terms table.
*/
-#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)"
+#define FTS3_AUX_SCHEMA \
+ "CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)"
/*
** This function does all the work for both the xConnect and xCreate methods.
@@ -124746,7 +129445,7 @@ static int fts3auxConnectMethod(
}
nFts3 = (int)strlen(zFts3);
- rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
+ rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA);
if( rc!=SQLITE_OK ) return rc;
nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
@@ -124806,6 +129505,8 @@ static int fts3auxBestIndexMethod(
int iEq = -1;
int iGe = -1;
int iLe = -1;
+ int iLangid = -1;
+ int iNext = 1; /* Next free argvIndex value */
UNUSED_PARAMETER(pVTab);
@@ -124817,36 +129518,48 @@ static int fts3auxBestIndexMethod(
pInfo->orderByConsumed = 1;
}
- /* Search for equality and range constraints on the "term" column. */
+ /* Search for equality and range constraints on the "term" column.
+ ** And equality constraints on the hidden "languageid" column. */
for(i=0; i<pInfo->nConstraint; i++){
- if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){
+ if( pInfo->aConstraint[i].usable ){
int op = pInfo->aConstraint[i].op;
- if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
- if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
- if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
- if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
- if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
+ int iCol = pInfo->aConstraint[i].iColumn;
+
+ if( iCol==0 ){
+ if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
+ if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
+ if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
+ if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
+ if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
+ }
+ if( iCol==4 ){
+ if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i;
+ }
}
}
if( iEq>=0 ){
pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
- pInfo->aConstraintUsage[iEq].argvIndex = 1;
+ pInfo->aConstraintUsage[iEq].argvIndex = iNext++;
pInfo->estimatedCost = 5;
}else{
pInfo->idxNum = 0;
pInfo->estimatedCost = 20000;
if( iGe>=0 ){
pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
- pInfo->aConstraintUsage[iGe].argvIndex = 1;
+ pInfo->aConstraintUsage[iGe].argvIndex = iNext++;
pInfo->estimatedCost /= 2;
}
if( iLe>=0 ){
pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
- pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0);
+ pInfo->aConstraintUsage[iLe].argvIndex = iNext++;
pInfo->estimatedCost /= 2;
}
}
+ if( iLangid>=0 ){
+ pInfo->aConstraintUsage[iLangid].argvIndex = iNext++;
+ pInfo->estimatedCost--;
+ }
return SQLITE_OK;
}
@@ -125006,7 +129719,14 @@ static int fts3auxFilterMethod(
Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
int rc;
- int isScan;
+ int isScan = 0;
+ int iLangVal = 0; /* Language id to query */
+
+ int iEq = -1; /* Index of term=? value in apVal */
+ int iGe = -1; /* Index of term>=? value in apVal */
+ int iLe = -1; /* Index of term<=? value in apVal */
+ int iLangid = -1; /* Index of languageid=? value in apVal */
+ int iNext = 0;
UNUSED_PARAMETER(nVal);
UNUSED_PARAMETER(idxStr);
@@ -125016,7 +129736,21 @@ static int fts3auxFilterMethod(
|| idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
|| idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
);
- isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT);
+
+ if( idxNum==FTS4AUX_EQ_CONSTRAINT ){
+ iEq = iNext++;
+ }else{
+ isScan = 1;
+ if( idxNum & FTS4AUX_GE_CONSTRAINT ){
+ iGe = iNext++;
+ }
+ if( idxNum & FTS4AUX_LE_CONSTRAINT ){
+ iLe = iNext++;
+ }
+ }
+ if( iNext<nVal ){
+ iLangid = iNext++;
+ }
/* In case this cursor is being reused, close and zero it. */
testcase(pCsr->filter.zTerm);
@@ -125028,22 +129762,35 @@ static int fts3auxFilterMethod(
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
- if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){
+ if( iEq>=0 || iGe>=0 ){
const unsigned char *zStr = sqlite3_value_text(apVal[0]);
+ assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
if( zStr ){
pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
}
}
- if( idxNum&FTS4AUX_LE_CONSTRAINT ){
- int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0;
- pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
- pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
+
+ if( iLe>=0 ){
+ pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
+ pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
}
+
+ if( iLangid>=0 ){
+ iLangVal = sqlite3_value_int(apVal[iLangid]);
+
+ /* If the user specified a negative value for the languageid, use zero
+ ** instead. This works, as the "languageid=?" constraint will also
+ ** be tested by the VDBE layer. The test will always be false (since
+ ** this module will not return a row with a negative languageid), and
+ ** so the overall query will return zero rows. */
+ if( iLangVal<0 ) iLangVal = 0;
+ }
+ pCsr->iLangid = iLangVal;
- rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL,
+ rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL,
pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
);
if( rc==SQLITE_OK ){
@@ -125067,24 +129814,37 @@ static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){
*/
static int fts3auxColumnMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
- sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
+ sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
assert( p->isEof==0 );
- if( iCol==0 ){ /* Column "term" */
- sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
- }else if( iCol==1 ){ /* Column "col" */
- if( p->iCol ){
- sqlite3_result_int(pContext, p->iCol-1);
- }else{
- sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC);
- }
- }else if( iCol==2 ){ /* Column "documents" */
- sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc);
- }else{ /* Column "occurrences" */
- sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc);
+ switch( iCol ){
+ case 0: /* term */
+ sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
+ break;
+
+ case 1: /* col */
+ if( p->iCol ){
+ sqlite3_result_int(pCtx, p->iCol-1);
+ }else{
+ sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC);
+ }
+ break;
+
+ case 2: /* documents */
+ sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc);
+ break;
+
+ case 3: /* occurrences */
+ sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc);
+ break;
+
+ default: /* languageid */
+ assert( iCol==4 );
+ sqlite3_result_int(pCtx, p->iLangid);
+ break;
}
return SQLITE_OK;
@@ -125298,6 +130058,11 @@ SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(
return rc;
}
+/*
+** Function getNextNode(), which is called by fts3ExprParse(), may itself
+** call fts3ExprParse(). So this forward declaration is required.
+*/
+static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
/*
** Extract the next token from buffer z (length n) using the tokenizer
@@ -125332,7 +130097,31 @@ static int getNextToken(
int nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
- if( rc==SQLITE_OK ){
+
+ if( (rc==SQLITE_OK || rc==SQLITE_DONE) && sqlite3_fts3_enable_parentheses ){
+ int i;
+ if( rc==SQLITE_DONE ) iStart = n;
+ for(i=0; i<iStart; i++){
+ if( z[i]=='(' ){
+ pParse->nNest++;
+ rc = fts3ExprParse(pParse, &z[i+1], n-i-1, &pRet, &nConsumed);
+ if( rc==SQLITE_OK && !pRet ){
+ rc = SQLITE_DONE;
+ }
+ nConsumed = (int)(i + 1 + nConsumed);
+ break;
+ }
+
+ if( z[i]==')' ){
+ rc = SQLITE_DONE;
+ pParse->nNest--;
+ nConsumed = i+1;
+ break;
+ }
+ }
+ }
+
+ if( nConsumed==0 && rc==SQLITE_OK ){
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
pRet = (Fts3Expr *)fts3MallocZero(nByte);
if( !pRet ){
@@ -125513,12 +130302,6 @@ no_mem:
}
/*
-** Function getNextNode(), which is called by fts3ExprParse(), may itself
-** call fts3ExprParse(). So this forward declaration is required.
-*/
-static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
-
-/*
** The output variable *ppExpr is populated with an allocated Fts3Expr
** structure, or set to 0 if the end of the input buffer is reached.
**
@@ -125614,27 +130397,6 @@ static int getNextNode(
}
}
- /* Check for an open bracket. */
- if( sqlite3_fts3_enable_parentheses ){
- if( *zInput=='(' ){
- int nConsumed;
- pParse->nNest++;
- rc = fts3ExprParse(pParse, &zInput[1], nInput-1, ppExpr, &nConsumed);
- if( rc==SQLITE_OK && !*ppExpr ){
- rc = SQLITE_DONE;
- }
- *pnConsumed = (int)((zInput - z) + 1 + nConsumed);
- return rc;
- }
-
- /* Check for a close bracket. */
- if( *zInput==')' ){
- pParse->nNest--;
- *pnConsumed = (int)((zInput - z) + 1);
- return SQLITE_DONE;
- }
- }
-
/* See if we are dealing with a quoted phrase. If this is the case, then
** search for the closing quote and pass the whole string to getNextString()
** for processing. This is easy to do, as fts3 has no syntax for escaping
@@ -126143,17 +130905,16 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
Fts3Expr **ppExpr, /* OUT: Parsed query structure */
char **pzErr /* OUT: Error message (sqlite3_malloc) */
){
- static const int MAX_EXPR_DEPTH = 12;
int rc = fts3ExprParseUnbalanced(
pTokenizer, iLangid, azCol, bFts4, nCol, iDefaultCol, z, n, ppExpr
);
/* Rebalance the expression. And check that its depth does not exceed
- ** MAX_EXPR_DEPTH. */
+ ** SQLITE_FTS3_MAX_EXPR_DEPTH. */
if( rc==SQLITE_OK && *ppExpr ){
- rc = fts3ExprBalance(ppExpr, MAX_EXPR_DEPTH);
+ rc = fts3ExprBalance(ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH);
if( rc==SQLITE_OK ){
- rc = fts3ExprCheckDepth(*ppExpr, MAX_EXPR_DEPTH);
+ rc = fts3ExprCheckDepth(*ppExpr, SQLITE_FTS3_MAX_EXPR_DEPTH);
}
}
@@ -126162,7 +130923,8 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
*ppExpr = 0;
if( rc==SQLITE_TOOBIG ){
*pzErr = sqlite3_mprintf(
- "FTS expression tree is too large (maximum depth %d)", MAX_EXPR_DEPTH
+ "FTS expression tree is too large (maximum depth %d)",
+ SQLITE_FTS3_MAX_EXPR_DEPTH
);
rc = SQLITE_ERROR;
}else if( rc==SQLITE_ERROR ){
@@ -127657,7 +132419,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
#ifdef SQLITE_TEST
-/* #include <tcl.h> */
+#include <tcl.h>
/* #include <string.h> */
/*
@@ -129124,37 +133886,30 @@ static void fts3SqlExec(
/*
-** This function ensures that the caller has obtained a shared-cache
-** table-lock on the %_content table. This is required before reading
-** data from the fts3 table. If this lock is not acquired first, then
-** the caller may end up holding read-locks on the %_segments and %_segdir
-** tables, but no read-lock on the %_content table. If this happens
-** a second connection will be able to write to the fts3 table, but
-** attempting to commit those writes might return SQLITE_LOCKED or
-** SQLITE_LOCKED_SHAREDCACHE (because the commit attempts to obtain
-** write-locks on the %_segments and %_segdir ** tables).
-**
-** We try to avoid this because if FTS3 returns any error when committing
-** a transaction, the whole transaction will be rolled back. And this is
-** not what users expect when they get SQLITE_LOCKED_SHAREDCACHE. It can
-** still happen if the user reads data directly from the %_segments or
-** %_segdir tables instead of going through FTS3 though.
+** This function ensures that the caller has obtained an exclusive
+** shared-cache table-lock on the %_segdir table. This is required before
+** writing data to the fts3 table. If this lock is not acquired first, then
+** the caller may end up attempting to take this lock as part of committing
+** a transaction, causing SQLite to return SQLITE_LOCKED or
+** LOCKED_SHAREDCACHEto a COMMIT command.
**
-** This reasoning does not apply to a content=xxx table.
+** It is best to avoid this because if FTS3 returns any error when
+** committing a transaction, the whole transaction will be rolled back.
+** And this is not what users expect when they get SQLITE_LOCKED_SHAREDCACHE.
+** It can still happen if the user locks the underlying tables directly
+** instead of accessing them via FTS.
*/
-SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *p){
- int rc; /* Return code */
- sqlite3_stmt *pStmt; /* Statement used to obtain lock */
-
- if( p->zContentTbl==0 ){
- rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pStmt, 0);
+static int fts3Writelock(Fts3Table *p){
+ int rc = SQLITE_OK;
+
+ if( p->nPendingData==0 ){
+ sqlite3_stmt *pStmt;
+ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_null(pStmt, 1);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
}
- }else{
- rc = SQLITE_OK;
}
return rc;
@@ -129542,12 +134297,15 @@ static int fts3InsertTerms(
){
int i; /* Iterator variable */
for(i=2; i<p->nColumn+2; i++){
- const char *zText = (const char *)sqlite3_value_text(apVal[i]);
- int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]);
- if( rc!=SQLITE_OK ){
- return rc;
+ int iCol = i-2;
+ if( p->abNotindexed[iCol]==0 ){
+ const char *zText = (const char *)sqlite3_value_text(apVal[i]);
+ int rc = fts3PendingTermsAdd(p, iLangid, zText, iCol, &aSz[iCol]);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
}
- aSz[p->nColumn] += sqlite3_value_bytes(apVal[i]);
}
return SQLITE_OK;
}
@@ -129694,9 +134452,12 @@ static void fts3DeleteTerms(
int iLangid = langidFromSelect(p, pSelect);
rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0));
for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){
- const char *zText = (const char *)sqlite3_column_text(pSelect, i);
- rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]);
- aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
+ int iCol = i-1;
+ if( p->abNotindexed[iCol]==0 ){
+ const char *zText = (const char *)sqlite3_column_text(pSelect, i);
+ rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[iCol]);
+ aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i);
+ }
}
if( rc!=SQLITE_OK ){
sqlite3_reset(pSelect);
@@ -129980,8 +134741,8 @@ static int fts3SegReaderNext(
/* Because of the FTS3_NODE_PADDING bytes of padding, the following is
** safe (no risk of overread) even if the node data is corrupted. */
- pNext += sqlite3Fts3GetVarint32(pNext, &nPrefix);
- pNext += sqlite3Fts3GetVarint32(pNext, &nSuffix);
+ pNext += fts3GetVarint32(pNext, &nPrefix);
+ pNext += fts3GetVarint32(pNext, &nSuffix);
if( nPrefix<0 || nSuffix<=0
|| &pNext[nSuffix]>&pReader->aNode[pReader->nNode]
){
@@ -130004,7 +134765,7 @@ static int fts3SegReaderNext(
memcpy(&pReader->zTerm[nPrefix], pNext, nSuffix);
pReader->nTerm = nPrefix+nSuffix;
pNext += nSuffix;
- pNext += sqlite3Fts3GetVarint32(pNext, &pReader->nDoclist);
+ pNext += fts3GetVarint32(pNext, &pReader->nDoclist);
pReader->aDoclist = pNext;
pReader->pOffsetList = 0;
@@ -130097,7 +134858,7 @@ static int fts3SegReaderNextDocid(
/* The following line of code (and the "p++" below the while() loop) is
** normally all that is required to move pointer p to the desired
** position. The exception is if this node is being loaded from disk
- ** incrementally and pointer "p" now points to the first byte passed
+ ** incrementally and pointer "p" now points to the first byte past
** the populated part of pReader->aNode[].
*/
while( *p | c ) c = *p++ & 0x80;
@@ -131165,7 +135926,7 @@ static void fts3ColumnFilter(
break;
}
p = &pList[1];
- p += sqlite3Fts3GetVarint32(p, &iCurrent);
+ p += fts3GetVarint32(p, &iCurrent);
}
if( bZero && &pList[nList]!=pEnd ){
@@ -131484,8 +136245,8 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
fts3SegReaderSort(apSegment, nMerge, nMerge, xCmp);
while( apSegment[0]->pOffsetList ){
int j; /* Number of segments that share a docid */
- char *pList;
- int nList;
+ char *pList = 0;
+ int nList = 0;
int nByte;
sqlite3_int64 iDocid = apSegment[0]->iDocid;
fts3SegReaderNextDocid(p, apSegment[0], &pList, &nList);
@@ -131938,9 +136699,11 @@ static int fts3DoRebuild(Fts3Table *p){
rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
- const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
- rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
- aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
+ if( p->abNotindexed[iCol]==0 ){
+ const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
+ rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
+ aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1);
+ }
}
if( p->bHasDocsize ){
fts3InsertDocsize(&rc, p, aSz);
@@ -132128,9 +136891,9 @@ static int nodeReaderNext(NodeReader *p){
p->aNode = 0;
}else{
if( bFirst==0 ){
- p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
+ p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nPrefix);
}
- p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
+ p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &nSuffix);
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
if( rc==SQLITE_OK ){
@@ -132138,7 +136901,7 @@ static int nodeReaderNext(NodeReader *p){
p->term.n = nPrefix+nSuffix;
p->iOff += nSuffix;
if( p->iChild==0 ){
- p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
+ p->iOff += fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist);
p->aDoclist = &p->aNode[p->iOff];
p->iOff += p->nDoclist;
}
@@ -133190,7 +137953,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
pHint->n = i;
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
- i += sqlite3Fts3GetVarint32(&pHint->a[i], pnInput);
+ i += fts3GetVarint32(&pHint->a[i], pnInput);
if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
return SQLITE_OK;
@@ -133414,7 +138177,7 @@ static int fts3DoAutoincrmerge(
if( rc ) return rc;
}
rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
- if( rc ) return rc;;
+ if( rc ) return rc;
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
sqlite3_step(pStmt);
@@ -133684,6 +138447,9 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
}else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
p->nMaxPendingData = atoi(&zVal[11]);
rc = SQLITE_OK;
+ }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
+ p->bNoIncrDoclist = atoi(&zVal[21]);
+ rc = SQLITE_OK;
#endif
}else{
rc = SQLITE_ERROR;
@@ -133743,32 +138509,34 @@ SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
iDocid = sqlite3_column_int64(pCsr->pStmt, 0);
for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){
- const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
- sqlite3_tokenizer_cursor *pTC = 0;
-
- rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
- while( rc==SQLITE_OK ){
- char const *zToken; /* Buffer containing token */
- int nToken = 0; /* Number of bytes in token */
- int iDum1 = 0, iDum2 = 0; /* Dummy variables */
- int iPos = 0; /* Position of token in zText */
-
- rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
- for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
- Fts3PhraseToken *pPT = pDef->pToken;
- if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
- && (pPT->bFirst==0 || iPos==0)
- && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
- && (0==memcmp(zToken, pPT->z, pPT->n))
- ){
- fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
+ if( p->abNotindexed[i]==0 ){
+ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1);
+ sqlite3_tokenizer_cursor *pTC = 0;
+
+ rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
+ while( rc==SQLITE_OK ){
+ char const *zToken; /* Buffer containing token */
+ int nToken = 0; /* Number of bytes in token */
+ int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+ int iPos = 0; /* Position of token in zText */
+
+ rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
+ for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
+ Fts3PhraseToken *pPT = pDef->pToken;
+ if( (pDef->iCol>=p->nColumn || pDef->iCol==i)
+ && (pPT->bFirst==0 || iPos==0)
+ && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken))
+ && (0==memcmp(zToken, pPT->z, pPT->n))
+ ){
+ fts3PendingListAppend(&pDef->pList, iDocid, i, iPos, &rc);
+ }
}
}
+ if( pTC ) pModule->xClose(pTC);
+ if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
- if( pTC ) pModule->xClose(pTC);
- if( rc==SQLITE_DONE ) rc = SQLITE_OK;
}
-
+
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
if( pDef->pList ){
rc = fts3PendingListAppendVarint(&pDef->pList, 0);
@@ -133932,6 +138700,9 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
aSzIns = &aSzDel[p->nColumn+1];
memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
+ rc = fts3Writelock(p);
+ if( rc!=SQLITE_OK ) goto update_out;
+
/* If this is an INSERT operation, or an UPDATE that modifies the rowid
** value, then this operation requires constraint handling.
**
@@ -134175,7 +138946,7 @@ struct StrBuffer {
*/
static void fts3GetDeltaPosition(char **pp, int *piPos){
int iVal;
- *pp += sqlite3Fts3GetVarint32(*pp, &iVal);
+ *pp += fts3GetVarint32(*pp, &iVal);
*piPos += (iVal-2);
}
@@ -134551,6 +139322,7 @@ static int fts3StringAppend(
pStr->z = zNew;
pStr->nAlloc = nAlloc;
}
+ assert( pStr->z!=0 && (pStr->nAlloc >= pStr->n+nAppend+1) );
/* Append the data to the string buffer. */
memcpy(&pStr->z[pStr->n], zAppend, nAppend);
@@ -136065,28 +140837,27 @@ SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){
0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
- 0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810,
- 0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023,
- 0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
- 0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
- 0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E,
- 0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01,
- 0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01,
- 0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016,
- 0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
- 0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004,
- 0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5,
- 0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
- 0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
- 0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064,
- 0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F,
- 0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009,
- 0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014,
- 0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001,
- 0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018,
- 0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401,
- 0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001,
- 0x43FFF401,
+ 0x037FFC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, 0x03F4F802,
+ 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, 0x03F95013,
+ 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, 0x03FCEC06,
+ 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, 0x04040003,
+ 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, 0x040E7C01,
+ 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, 0x04280403,
+ 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, 0x04294009,
+ 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, 0x04420003,
+ 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, 0x04460003,
+ 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, 0x05BD442E,
+ 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, 0x07480046,
+ 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, 0x075C5401,
+ 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, 0x075EA401,
+ 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, 0x07C2800F,
+ 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, 0x07C4C03C,
+ 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, 0x07C94002,
+ 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, 0x07CE8025,
+ 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, 0x07D108B6,
+ 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, 0x07D7EC46,
+ 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, 0x38008060,
+ 0x380400F0,
};
static const unsigned int aAscii[4] = {
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
@@ -136468,6 +141239,16 @@ typedef union RtreeCoord RtreeCoord;
*/
#define HASHSIZE 128
+/* The xBestIndex method of this virtual table requires an estimate of
+** the number of rows in the virtual table to calculate the costs of
+** various strategies. If possible, this estimate is loaded from the
+** sqlite_stat1 table (with RTREE_MIN_ROWEST as a hard-coded minimum).
+** Otherwise, if no sqlite_stat1 entry is available, use
+** RTREE_DEFAULT_ROWEST.
+*/
+#define RTREE_DEFAULT_ROWEST 1048576
+#define RTREE_MIN_ROWEST 100
+
/*
** An rtree virtual-table object.
*/
@@ -136482,6 +141263,7 @@ struct Rtree {
char *zName; /* Name of r-tree table */
RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
int nBusy; /* Current number of users of this structure */
+ i64 nRowEst; /* Estimated number of rows in this table */
/* List of nodes removed during a CondenseTree operation. List is
** linked together via the pointer normally used for hash chains -
@@ -137675,6 +142457,19 @@ static int rtreeFilter(
}
/*
+** Set the pIdxInfo->estimatedRows variable to nRow. Unless this
+** extension is currently being used by a version of SQLite too old to
+** support estimatedRows. In that case this function is a no-op.
+*/
+static void setEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
+#if SQLITE_VERSION_NUMBER>=3008002
+ if( sqlite3_libversion_number()>=3008002 ){
+ pIdxInfo->estimatedRows = nRow;
+ }
+#endif
+}
+
+/*
** Rtree virtual table module xBestIndex method. There are three
** table scan strategies to choose from (in order from most to
** least desirable):
@@ -137709,13 +142504,14 @@ static int rtreeFilter(
** is 'a', the second from the left 'b' etc.
*/
static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+ Rtree *pRtree = (Rtree*)tab;
int rc = SQLITE_OK;
int ii;
+ i64 nRow; /* Estimated rows returned by this scan */
int iIdx = 0;
char zIdxStr[RTREE_MAX_DIMENSIONS*8+1];
memset(zIdxStr, 0, sizeof(zIdxStr));
- UNUSED_PARAMETER(tab);
assert( pIdxInfo->idxStr==0 );
for(ii=0; ii<pIdxInfo->nConstraint && iIdx<(int)(sizeof(zIdxStr)-1); ii++){
@@ -137735,9 +142531,11 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
/* This strategy involves a two rowid lookups on an B-Tree structures
** and then a linear search of an R-Tree node. This should be
** considered almost as quick as a direct rowid lookup (for which
- ** sqlite uses an internal cost of 0.0).
+ ** sqlite uses an internal cost of 0.0). It is expected to return
+ ** a single row.
*/
- pIdxInfo->estimatedCost = 10.0;
+ pIdxInfo->estimatedCost = 30.0;
+ setEstimatedRows(pIdxInfo, 1);
return SQLITE_OK;
}
@@ -137766,8 +142564,11 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
return SQLITE_NOMEM;
}
- assert( iIdx>=0 );
- pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1));
+
+ nRow = pRtree->nRowEst / (iIdx + 1);
+ pIdxInfo->estimatedCost = (double)6.0 * (double)nRow;
+ setEstimatedRows(pIdxInfo, nRow);
+
return rc;
}
@@ -139242,6 +144043,37 @@ static int rtreeRename(sqlite3_vtab *pVtab, const char *zNewName){
return rc;
}
+/*
+** This function populates the pRtree->nRowEst variable with an estimate
+** of the number of rows in the virtual table. If possible, this is based
+** on sqlite_stat1 data. Otherwise, use RTREE_DEFAULT_ROWEST.
+*/
+static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
+ const char *zSql = "SELECT stat FROM sqlite_stat1 WHERE tbl= ? || '_rowid'";
+ sqlite3_stmt *p;
+ int rc;
+ i64 nRow = 0;
+
+ rc = sqlite3_prepare_v2(db, zSql, -1, &p, 0);
+ if( rc==SQLITE_OK ){
+ sqlite3_bind_text(p, 1, pRtree->zName, -1, SQLITE_STATIC);
+ if( sqlite3_step(p)==SQLITE_ROW ) nRow = sqlite3_column_int64(p, 0);
+ rc = sqlite3_finalize(p);
+ }else if( rc!=SQLITE_NOMEM ){
+ rc = SQLITE_OK;
+ }
+
+ if( rc==SQLITE_OK ){
+ if( nRow==0 ){
+ pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
+ }else{
+ pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
+ }
+ }
+
+ return rc;
+}
+
static sqlite3_module rtreeModule = {
0, /* iVersion */
rtreeCreate, /* xCreate - create a table */
@@ -139327,6 +144159,7 @@ static int rtreeSqlInit(
appStmt[7] = &pRtree->pWriteParent;
appStmt[8] = &pRtree->pDeleteParent;
+ rc = rtreeQueryStat1(db, pRtree);
for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
if( zSql ){
@@ -139681,7 +144514,10 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
}
#if !SQLITE_CORE
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_rtree_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
@@ -139719,7 +144555,7 @@ SQLITE_API int sqlite3_extension_init(
** * Implementations of the SQL scalar upper() and lower() functions
** for case mapping.
**
-** * Integration of ICU and SQLite collation seqences.
+** * Integration of ICU and SQLite collation sequences.
**
** * An implementation of the LIKE operator that uses ICU to
** provide case-independent matching.
@@ -140183,7 +145019,10 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
}
#if !SQLITE_CORE
-SQLITE_API int sqlite3_extension_init(
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+SQLITE_API int sqlite3_icu_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi