diff --git a/uppsrc/plugin/sqlite3/lib/readme-amalgamation.md b/uppsrc/plugin/sqlite3/lib/readme-amalgamation.md
new file mode 100644
index 000000000..476a9969c
--- /dev/null
+++ b/uppsrc/plugin/sqlite3/lib/readme-amalgamation.md
@@ -0,0 +1,24 @@
+# Release notes
+
+# SQLite3 Multiple Ciphers amalgamation
+
+This archive contains the source code amalgamation of _SQLite3 Multiple Ciphers_.
+Additionally, the original SQLite sources are included.
+
+## Archive content
+
+File name | Description
+:----------------------- | :----------
+sqlite3mc_amalgamation.c | C source, SQLite3 Multiple Ciphers amalgamation
+sqlite3mc_amalgamation.h | C header, SQLite3 Multiple Ciphers amalgamation
+shell3mc_amalgamation.c | C source of the SQLite shell, SQLite3 Multiple Ciphers amalgamation
+sqlite3mc.def | Exported Symbols for Windows DLL builds
+sqlite3.c | C source, original SQLite amalgamation
+sqlite3.h | C header, original SQLite amalgamation
+sqlite3ext.h | C header for extensions, original SQLite
+shell.c | C source of the original SQLite shell
+
+## Support
+
+If you have any comments or problems open an issue on the _SQLite3 Multiple Ciphers_ github page:
+https://github.com/utelle/SQLite3MultipleCiphers/issues
diff --git a/uppsrc/plugin/sqlite3/lib/sqlite3mc_amalgamation.c b/uppsrc/plugin/sqlite3/lib/sqlite3mc_amalgamation.c
index aa80f13dd..7abc1087e 100644
--- a/uppsrc/plugin/sqlite3/lib/sqlite3mc_amalgamation.c
+++ b/uppsrc/plugin/sqlite3/lib/sqlite3mc_amalgamation.c
@@ -3,7 +3,7 @@
** Purpose: Amalgamation of the SQLite3 Multiple Ciphers encryption extension for SQLite
** Author: Ulrich Telle
** Created: 2020-02-28
-** Copyright: (c) 2006-2024 Ulrich Telle
+** Copyright: (c) 2006-2025 Ulrich Telle
** License: MIT
*/
@@ -11,15 +11,12 @@
** Force some options required for WASM builds
*/
-#define SQLITE3MC_OMIT_AES_HARDWARE_SUPPORT 1
-
#ifdef __WASM__
/* Disable User Authentication Extension */
#ifdef SQLITE_USER_AUTHENTICATION
#undef SQLITE_USER_AUTHENTICATION
#endif
-#define SQLITE_USER_AUTHENTICATION 0
/* Disable AES hardware support */
/* Note: this may be changed in the future depending on available support */
@@ -40,19 +37,6 @@
#endif
#endif
-/*
-** Define function for extra initialization and extra shutdown
-**
-** The extra initialization function registers an extension function
-** which will be automatically executed for each new database connection.
-**
-** The extra shutdown function will be executed on the invocation of sqlite3_shutdown.
-** All created multiple ciphers VFSs will be unregistered and destroyed.
-*/
-
-#define SQLITE_EXTRA_INIT sqlite3mc_initialize
-#define SQLITE_EXTRA_SHUTDOWN sqlite3mc_shutdown
-
/*
** Declare all internal functions as 'static' unless told otherwise
*/
@@ -67,21 +51,22 @@ SQLITE_PRIVATE void sqlite3mc_shutdown(void);
** To enable the extension functions define SQLITE_ENABLE_EXTFUNC on compiling this module
** To enable the reading CSV files define SQLITE_ENABLE_CSV on compiling this module
** To enable the SHA3 support define SQLITE_ENABLE_SHA3 on compiling this module
-** To enable the CARRAY support define SQLITE_ENABLE_CARRAY on compiling this module
** To enable the FILEIO support define SQLITE_ENABLE_FILEIO on compiling this module
** To enable the SERIES support define SQLITE_ENABLE_SERIES on compiling this module
** To enable the UUID support define SQLITE_ENABLE_UUID on compiling this module
+**
+** Extensions for which the SQLite amalgamation contains now the sources:
+** To enable the CARRAY support define SQLITE_ENABLE_CARRAY on compiling this module
+** To enable the PERCENTILE support define SQLITE_ENABLE_PERCENTILE on compiling this module
*/
/*
** Disable the user authentication feature by default
*/
#ifdef SQLITE_USER_AUTHENTICATION
-#if !SQLITE_USER_AUTHENTICATION
/* Option defined and disabled, therefore undefine option */
#undef SQLITE_USER_AUTHENTICATION
#endif
-#endif
#if defined(_WIN32) || defined(WIN32)
@@ -138,7 +123,7 @@ SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
/*** Begin of #include "sqlite3patched.c" ***/
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.46.0. By combining all the individual C code files into this
+** version 3.51.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
@@ -156,8 +141,11 @@ SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
-** 96c92aba00c8375bc32fafcdf12429c58bd8.
+** b270f8339eb13b504d0b2ba154ebca966b7d with changes in files:
+**
+**
*/
+#ifndef SQLITE_AMALGAMATION
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
@@ -305,7 +293,9 @@ SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
#define HAVE_UTIME 1
#else
/* This is not VxWorks. */
-#define OS_VXWORKS 0
+#ifndef OS_VXWORKS
+# define OS_VXWORKS 0
+#endif
#define HAVE_FCHOWN 1
#define HAVE_READLINK 1
#define HAVE_LSTAT 1
@@ -394,10 +384,13 @@ SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char*);
/*
** Macro to disable warnings about missing "break" at the end of a "case".
*/
-#if GCC_VERSION>=7000000
-# define deliberate_fall_through __attribute__((fallthrough));
-#else
-# define deliberate_fall_through
+#if defined(__has_attribute)
+# if __has_attribute(fallthrough)
+# define deliberate_fall_through __attribute__((fallthrough));
+# endif
+#endif
+#if !defined(deliberate_fall_through)
+# define deliberate_fall_through
#endif
/*
@@ -584,7 +577,7 @@ extern "C" {
**
** Since [version 3.6.18] ([dateof:3.6.18]),
** SQLite source code has been stored in the
-** Fossil configuration management
+** Fossil configuration management
** system. ^The SQLITE_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
** within its configuration management system. ^The SQLITE_SOURCE_ID
@@ -597,9 +590,12 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.46.0"
-#define SQLITE_VERSION_NUMBER 3046000
-#define SQLITE_SOURCE_ID "2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e"
+#define SQLITE_VERSION "3.51.2"
+#define SQLITE_VERSION_NUMBER 3051002
+#define SQLITE_SOURCE_ID "2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075"
+#define SQLITE_SCM_BRANCH "branch-3.51"
+#define SQLITE_SCM_TAGS "release version-3.51.2"
+#define SQLITE_SCM_DATETIME "2026-01-09T17:27:48.405Z"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -619,9 +615,9 @@ extern "C" {
** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
** )^
**
-** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION]
-** macro. ^The sqlite3_libversion() function returns a pointer to the
-** to the sqlite3_version[] string constant. The sqlite3_libversion()
+** ^The sqlite3_version[] string constant contains the text of the
+** [SQLITE_VERSION] macro. ^The sqlite3_libversion() function returns a
+** pointer to the sqlite3_version[] string constant. The sqlite3_libversion()
** function is provided for use in DLLs since DLL users usually do not have
** direct access to string constants within the DLL. ^The
** sqlite3_libversion_number() function returns an integer equal to
@@ -821,7 +817,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** without having to use a lot of C code.
**
** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
-** semicolon-separate SQL statements passed into its 2nd argument,
+** semicolon-separated SQL statements passed into its 2nd argument,
** in the context of the [database connection] passed in as its 1st
** argument. ^If the callback function of the 3rd argument to
** sqlite3_exec() is not NULL, then it is invoked for each result row
@@ -854,7 +850,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** result row is NULL then the corresponding string pointer for the
** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the
** sqlite3_exec() callback is an array of pointers to strings where each
-** entry represents the name of corresponding result column as obtained
+** entry represents the name of a corresponding result column as obtained
** from [sqlite3_column_name()].
**
** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
@@ -948,6 +944,9 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8))
+#define SQLITE_ERROR_RESERVESIZE (SQLITE_ERROR | (4<<8))
+#define SQLITE_ERROR_KEY (SQLITE_ERROR | (5<<8))
+#define SQLITE_ERROR_UNABLE (SQLITE_ERROR | (6<<8))
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
@@ -982,6 +981,8 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8))
+#define SQLITE_IOERR_BADKEY (SQLITE_IOERR | (35<<8))
+#define SQLITE_IOERR_CODEC (SQLITE_IOERR | (36<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
@@ -1040,7 +1041,7 @@ SQLITE_API int sqlite3_exec(
** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into
** [sqlite3_open_v2()] does *not* cause the underlying database file
** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into
-** [sqlite3_open_v2()] has historically be a no-op and might become an
+** [sqlite3_open_v2()] has historically been a no-op and might become an
** error in future versions of SQLite.
*/
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
@@ -1103,6 +1104,13 @@ SQLITE_API int sqlite3_exec(
** filesystem supports doing multiple write operations atomically when those
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
+**
+** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read
+** from the database file in amounts that are not a multiple of the
+** page size and that do not begin at a page boundary. Without this
+** property, SQLite is careful to only do full-page reads and write
+** on aligned pages, with the one exception that it will do a sub-page
+** read of the first page to access the database header.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -1119,6 +1127,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
+#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000
/*
** CAPI3REF: File Locking Levels
@@ -1126,7 +1135,7 @@ SQLITE_API int sqlite3_exec(
** SQLite uses one of these integer values as the second
** argument to calls it makes to the xLock() and xUnlock() methods
** of an [sqlite3_io_methods] object. These values are ordered from
-** lest restrictive to most restrictive.
+** least restrictive to most restrictive.
**
** The argument to xLock() is always SHARED or higher. The argument to
** xUnlock is either SHARED or NONE.
@@ -1223,8 +1232,8 @@ struct sqlite3_file {
** to xUnlock() is a no-op.
** The xCheckReservedLock() method checks whether any database connection,
** either in this process or in some other process, is holding a RESERVED,
-** PENDING, or EXCLUSIVE lock on the file. It returns true
-** if such a lock exists and false otherwise.
+** PENDING, or EXCLUSIVE lock on the file. It returns, via its output
+** pointer parameter, true if such a lock exists and false otherwise.
**
** The xFileControl() method is a generic interface that allows custom
** VFS implementations to directly control an open file using the
@@ -1265,6 +1274,7 @@ struct sqlite3_file {
**
[SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** [SQLITE_IOCAP_IMMUTABLE]
** [SQLITE_IOCAP_BATCH_ATOMIC]
+** [SQLITE_IOCAP_SUBPAGE_READ]
**
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
@@ -1366,7 +1376,7 @@ struct sqlite3_io_methods {
** connection. See also [SQLITE_FCNTL_FILE_POINTER].
**
** [[SQLITE_FCNTL_SYNC_OMITTED]]
-** No longer in use.
+** The SQLITE_FCNTL_SYNC_OMITTED file-control is no longer used.
**
** [[SQLITE_FCNTL_SYNC]]
** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
@@ -1441,7 +1451,7 @@ struct sqlite3_io_methods {
**
** [[SQLITE_FCNTL_VFSNAME]]
** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
-** all [VFSes] in the VFS stack. The names are of all VFS shims and the
+** all [VFSes] in the VFS stack. The names of all VFS shims and the
** final bottom-level VFS are written into memory obtained from
** [sqlite3_malloc()] and the result is stored in the char* variable
** that the fourth parameter of [sqlite3_file_control()] points to.
@@ -1455,7 +1465,7 @@ struct sqlite3_io_methods {
** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level
** [VFSes] currently in use. ^(The argument X in
** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be
-** of type "[sqlite3_vfs] **". This opcodes will set *X
+** of type "[sqlite3_vfs] **". This opcode will set *X
** to a pointer to the top-level VFS.)^
** ^When there are multiple VFS shims in the stack, this opcode finds the
** upper-most shim only.
@@ -1542,6 +1552,11 @@ struct sqlite3_io_methods {
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
+** [[SQLITE_FCNTL_NULL_IO]]
+** The [SQLITE_FCNTL_NULL_IO] opcode sets the low-level file descriptor
+** or file handle for the [sqlite3_file] object such that it will no longer
+** read or write to the database file.
+**
** [[SQLITE_FCNTL_WAL_BLOCK]]
** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
** be advantageous to block on the next WAL lock if the lock is not immediately
@@ -1600,6 +1615,12 @@ struct sqlite3_io_methods {
** the value that M is to be set to. Before returning, the 32-bit signed
** integer is overwritten with the previous value of M.
**
+** [[SQLITE_FCNTL_BLOCK_ON_CONNECT]]
+** The [SQLITE_FCNTL_BLOCK_ON_CONNECT] opcode is used to configure the
+** VFS to block when taking a SHARED lock to connect to a wal mode database.
+** This is used to implement the functionality associated with
+** SQLITE_SETLK_BLOCK_ON_CONNECT.
+**
** [[SQLITE_FCNTL_DATA_VERSION]]
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
** a database file. The argument is a pointer to a 32-bit unsigned integer.
@@ -1634,7 +1655,7 @@ struct sqlite3_io_methods {
** [[SQLITE_FCNTL_EXTERNAL_READER]]
** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
** whether or not there is a database client in another process with a wal-mode
-** transaction open on the database or not. It is only available on unix.The
+** transaction open on the database or not. It is only available on unix. The
** (void*) argument passed with this file-control should be a pointer to a
** value of type (int). The integer value is set to 1 if the database is a wal
** mode database and there exists at least one client in another process that
@@ -1652,6 +1673,15 @@ struct sqlite3_io_methods {
** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control
** purges the contents of the in-memory page cache. If there is an open
** transaction, or if the db is a temp-db, this opcode is a no-op, not an error.
+**
+** [[SQLITE_FCNTL_FILESTAT]]
+** The [SQLITE_FCNTL_FILESTAT] opcode returns low-level diagnostic information
+** about the [sqlite3_file] objects used access the database and journal files
+** for the given schema. The fourth parameter to [sqlite3_file_control()]
+** should be an initialized [sqlite3_str] pointer. JSON text describing
+** various aspects of the sqlite3_file object is appended to the sqlite3_str.
+** The SQLITE_FCNTL_FILESTAT opcode is usually a no-op, unless compile-time
+** options are used to enable it.
**
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -1695,6 +1725,9 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_EXTERNAL_READER 40
#define SQLITE_FCNTL_CKSM_FILE 41
#define SQLITE_FCNTL_RESET_CACHE 42
+#define SQLITE_FCNTL_NULL_IO 43
+#define SQLITE_FCNTL_BLOCK_ON_CONNECT 44
+#define SQLITE_FCNTL_FILESTAT 45
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2057,7 +2090,7 @@ struct sqlite3_vfs {
** SQLite interfaces so that an application usually does not need to
** invoke sqlite3_initialize() directly. For example, [sqlite3_open()]
** calls sqlite3_initialize() so the SQLite library will be automatically
-** initialized when [sqlite3_open()] is called if it has not be initialized
+** initialized when [sqlite3_open()] is called if it has not been initialized
** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT]
** compile-time option, then the automatic calls to sqlite3_initialize()
** are omitted and the application must call sqlite3_initialize() directly
@@ -2314,21 +2347,21 @@ struct sqlite3_mem_methods {
** The [sqlite3_mem_methods]
** structure is filled with the currently defined memory allocation routines.)^
** This option can be used to overload the default memory allocation
-** routines with a wrapper that simulations memory allocation failure or
+** routines with a wrapper that simulates memory allocation failure or
** tracks memory usage, for example.
**
** [[SQLITE_CONFIG_SMALL_MALLOC]] SQLITE_CONFIG_SMALL_MALLOC
-** ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of
+** ^The SQLITE_CONFIG_SMALL_MALLOC option takes a single argument of
** type int, interpreted as a boolean, which if true provides a hint to
** SQLite that it should avoid large memory allocations if possible.
** SQLite will run faster if it is free to make large memory allocations,
-** but some application might prefer to run slower in exchange for
+** but some applications might prefer to run slower in exchange for
** guarantees about memory fragmentation that are possible if large
** allocations are avoided. This hint is normally off.
**
**
** [[SQLITE_CONFIG_MEMSTATUS]] SQLITE_CONFIG_MEMSTATUS
-** ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
+** ^The SQLITE_CONFIG_MEMSTATUS option takes a single argument of type int,
** interpreted as a boolean, which enables or disables the collection of
** memory allocation statistics. ^(When memory allocation statistics are
** disabled, the following SQLite interfaces become non-operational:
@@ -2373,7 +2406,7 @@ struct sqlite3_mem_methods {
** ^If pMem is NULL and N is non-zero, then each database connection
** does an initial bulk allocation for page cache memory
** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or
-** of -1024*N bytes if N is negative, . ^If additional
+** of -1024*N bytes if N is negative. ^If additional
** page cache memory is needed beyond what is provided by the initial
** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
** additional cache line.
@@ -2402,7 +2435,7 @@ struct sqlite3_mem_methods {
** ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a
** pointer to an instance of the [sqlite3_mutex_methods] structure.
** The argument specifies alternative low-level mutex routines to be used
-** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of
+** in place of the mutex routines built into SQLite.)^ ^SQLite makes a copy of
** the content of the [sqlite3_mutex_methods] structure before the call to
** [sqlite3_config()] returns. ^If SQLite is compiled with
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
@@ -2425,13 +2458,16 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_CONFIG_LOOKASIDE]] SQLITE_CONFIG_LOOKASIDE
** ^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine
-** the default size of lookaside memory on each [database connection].
+** the default size of [lookaside memory] on each [database connection].
** The first argument is the
-** size of each lookaside buffer slot and the second is the number of
-** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE
-** sets the default lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
-** option to [sqlite3_db_config()] can be used to change the lookaside
-** configuration on individual connections.)^
+** size of each lookaside buffer slot ("sz") and the second is the number of
+** slots allocated to each database connection ("cnt").)^
+** ^(SQLITE_CONFIG_LOOKASIDE sets the default lookaside size.
+** The [SQLITE_DBCONFIG_LOOKASIDE] option to [sqlite3_db_config()] can
+** be used to change the lookaside configuration on individual connections.)^
+** The [-DSQLITE_DEFAULT_LOOKASIDE] option can be used to change the
+** default lookaside configuration at compile-time.
+**
**
** [[SQLITE_CONFIG_PCACHE2]] SQLITE_CONFIG_PCACHE2
** ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is
@@ -2441,7 +2477,7 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_CONFIG_GETPCACHE2]] SQLITE_CONFIG_GETPCACHE2
** ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which
-** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of
+** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies off
** the current page cache implementation into that object.)^
**
** [[SQLITE_CONFIG_LOG]] SQLITE_CONFIG_LOG
@@ -2458,7 +2494,7 @@ struct sqlite3_mem_methods {
** the logger function is a copy of the first parameter to the corresponding
** [sqlite3_log()] call and is intended to be a [result code] or an
** [extended result code]. ^The third parameter passed to the logger is
-** log message after formatting via [sqlite3_snprintf()].
+** a log message after formatting via [sqlite3_snprintf()].
** The SQLite logging interface is not reentrant; the logger function
** supplied by the application must not invoke any SQLite interface.
** In a multi-threaded application, the application-defined logger
@@ -2647,7 +2683,15 @@ struct sqlite3_mem_methods {
** CAPI3REF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
-** can be passed as the second argument to the [sqlite3_db_config()] interface.
+** can be passed as the second parameter to the [sqlite3_db_config()] interface.
+**
+** The [sqlite3_db_config()] interface is a var-args function. It takes a
+** variable number of parameters, though always at least two. The number of
+** parameters passed into sqlite3_db_config() depends on which of these
+** constants is given as the second parameter. This documentation page
+** refers to parameters beyond the second as "arguments". Thus, when this
+** page says "the N-th argument" it means "the N-th parameter past the
+** configuration option" or "the (N+2)-th parameter to sqlite3_db_config()".
**
** New configuration options may be added in future releases of SQLite.
** Existing configuration options might be discontinued. Applications
@@ -2659,31 +2703,57 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_DBCONFIG_LOOKASIDE]]
** - SQLITE_DBCONFIG_LOOKASIDE
-** - ^This option takes three additional arguments that determine the
-** [lookaside memory allocator] configuration for the [database connection].
-** ^The first argument (the third parameter to [sqlite3_db_config()] is a
+**
- The SQLITE_DBCONFIG_LOOKASIDE option is used to adjust the
+** configuration of the [lookaside memory allocator] within a database
+** connection.
+** The arguments to the SQLITE_DBCONFIG_LOOKASIDE option are not
+** in the [DBCONFIG arguments|usual format].
+** The SQLITE_DBCONFIG_LOOKASIDE option takes three arguments, not two,
+** so that a call to [sqlite3_db_config()] that uses SQLITE_DBCONFIG_LOOKASIDE
+** should have a total of five parameters.
+**
+** The first argument ("buf") is a
** pointer to a memory buffer to use for lookaside memory.
-** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
-** may be NULL in which case SQLite will allocate the
-** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
-** size of each lookaside buffer slot. ^The third argument is the number of
-** slots. The size of the buffer in the first argument must be greater than
-** or equal to the product of the second and third arguments. The buffer
-** must be aligned to an 8-byte boundary. ^If the second argument to
-** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
-** rounded down to the next smaller multiple of 8. ^(The lookaside memory
+** The first argument may be NULL in which case SQLite will allocate the
+** lookaside buffer itself using [sqlite3_malloc()].
+**
The second argument ("sz") is the
+** size of each lookaside buffer slot. Lookaside is disabled if "sz"
+** is less than 8. The "sz" argument should be a multiple of 8 less than
+** 65536. If "sz" does not meet this constraint, it is reduced in size until
+** it does.
+**
The third argument ("cnt") is the number of slots. Lookaside is disabled
+** if "cnt"is less than 1. The "cnt" value will be reduced, if necessary, so
+** that the product of "sz" and "cnt" does not exceed 2,147,418,112. The "cnt"
+** parameter is usually chosen so that the product of "sz" and "cnt" is less
+** than 1,000,000.
+**
+** If the "buf" argument is not NULL, then it must
+** point to a memory buffer with a size that is greater than
+** or equal to the product of "sz" and "cnt".
+** The buffer must be aligned to an 8-byte boundary.
+** The lookaside memory
** configuration for a database connection can only be changed when that
** connection is not currently using lookaside memory, or in other words
-** when the "current value" returned by
-** [sqlite3_db_status](D,[SQLITE_DBSTATUS_LOOKASIDE_USED],...) is zero.
+** when the value returned by [SQLITE_DBSTATUS_LOOKASIDE_USED] is zero.
** Any attempt to change the lookaside memory configuration when lookaside
** memory is in use leaves the configuration unchanged and returns
-** [SQLITE_BUSY].)^
+** [SQLITE_BUSY].
+** If the "buf" argument is NULL and an attempt
+** to allocate memory based on "sz" and "cnt" fails, then
+** lookaside is silently disabled.
+**
+** The [SQLITE_CONFIG_LOOKASIDE] configuration option can be used to set the
+** default lookaside configuration at initialization. The
+** [-DSQLITE_DEFAULT_LOOKASIDE] option can be used to set the default lookaside
+** configuration at compile-time. Typical values for lookaside are 1200 for
+** "sz" and 40 to 100 for "cnt".
+**
**
** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
** - SQLITE_DBCONFIG_ENABLE_FKEY
** - ^This option is used to enable or disable the enforcement of
-** [foreign key constraints]. There should be two additional arguments.
+** [foreign key constraints]. This is the same setting that is
+** enabled or disabled by the [PRAGMA foreign_keys] statement.
** The first argument is an integer which is 0 to disable FK enforcement,
** positive to enable FK enforcement or negative to leave FK enforcement
** unchanged. The second parameter is a pointer to an integer into which
@@ -2705,13 +2775,13 @@ struct sqlite3_mem_methods {
**
Originally this option disabled all triggers. ^(However, since
** SQLite version 3.35.0, TEMP triggers are still allowed even if
** this option is off. So, in other words, this option now only disables
-** triggers in the main database schema or in the schemas of ATTACH-ed
+** triggers in the main database schema or in the schemas of [ATTACH]-ed
** databases.)^
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** - SQLITE_DBCONFIG_ENABLE_VIEW
** - ^This option is used to enable or disable [CREATE VIEW | views].
-** There should be two additional arguments.
+** There must be two additional arguments.
** The first argument is an integer which is 0 to disable views,
** positive to enable views or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
@@ -2727,17 +2797,20 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
**
- SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
-** - ^This option is used to enable or disable the
-** [fts3_tokenizer()] function which is part of the
-** [FTS3] full-text search engine extension.
-** There should be two additional arguments.
-** The first argument is an integer which is 0 to disable fts3_tokenizer() or
-** positive to enable fts3_tokenizer() or negative to leave the setting
-** unchanged.
-** The second parameter is a pointer to an integer into which
-** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
-** following this call. The second parameter may be a NULL pointer, in
-** which case the new setting is not reported back.
+** - ^This option is used to enable or disable using the
+** [fts3_tokenizer()] function - part of the [FTS3] full-text search engine
+** extension - without using bound parameters as the parameters. Doing so
+** is disabled by default. There must be two additional arguments. The first
+** argument is an integer. If it is passed 0, then using fts3_tokenizer()
+** without bound parameters is disabled. If it is passed a positive value,
+** then calling fts3_tokenizer without bound parameters is enabled. If it
+** is passed a negative value, this setting is not modified - this can be
+** used to query for the current setting. The second parameter is a pointer
+** to an integer into which is written 0 or 1 to indicate the current value
+** of this setting (after it is modified, if applicable). The second
+** parameter may be a NULL pointer, in which case the value of the setting
+** is not reported back. Refer to [FTS3] documentation for further details.
+**
**
** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
** - SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION
@@ -2745,12 +2818,12 @@ struct sqlite3_mem_methods {
** interface independently of the [load_extension()] SQL function.
** The [sqlite3_enable_load_extension()] API enables or disables both the
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
-** There should be two additional arguments.
+** There must be two additional arguments.
** When the first argument to this interface is 1, then only the C-API is
** enabled and the SQL function remains disabled. If the first argument to
** this interface is 0, then both the C-API and the SQL function are disabled.
-** If the first argument is -1, then no changes are made to state of either the
-** C-API or the SQL function.
+** If the first argument is -1, then no changes are made to the state of either
+** the C-API or the SQL function.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface
** is disabled or enabled following this call. The second parameter may
@@ -2759,23 +2832,30 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_DBCONFIG_MAINDBNAME]] - SQLITE_DBCONFIG_MAINDBNAME
** - ^This option is used to change the name of the "main" database
-** schema. ^The sole argument is a pointer to a constant UTF8 string
-** which will become the new schema name in place of "main". ^SQLite
-** does not make a copy of the new main schema name string, so the application
-** must ensure that the argument passed into this DBCONFIG option is unchanged
-** until after the database connection closes.
+** schema. This option does not follow the
+** [DBCONFIG arguments|usual SQLITE_DBCONFIG argument format].
+** This option takes exactly one additional argument so that the
+** [sqlite3_db_config()] call has a total of three parameters. The
+** extra argument must be a pointer to a constant UTF8 string which
+** will become the new schema name in place of "main". ^SQLite does
+** not make a copy of the new main schema name string, so the application
+** must ensure that the argument passed into SQLITE_DBCONFIG MAINDBNAME
+** is unchanged until after the database connection closes.
**
**
** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
** - SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
-** - Usually, when a database in wal mode is closed or detached from a
-** database handle, SQLite checks if this will mean that there are now no
-** connections at all to the database. If so, it performs a checkpoint
-** operation before closing the connection. This option may be used to
-** override this behavior. The first parameter passed to this operation
-** is an integer - positive to disable checkpoints-on-close, or zero (the
-** default) to enable them, and negative to leave the setting unchanged.
-** The second parameter is a pointer to an integer
+**
- Usually, when a database in [WAL mode] is closed or detached from a
+** database handle, SQLite checks if if there are other connections to the
+** same database, and if there are no other database connection (if the
+** connection being closed is the last open connection to the database),
+** then SQLite performs a [checkpoint] before closing the connection and
+** deletes the WAL file. The SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE option can
+** be used to override that behavior. The first argument passed to this
+** operation (the third parameter to [sqlite3_db_config()]) is an integer
+** which is positive to disable checkpoints-on-close, or zero (the default)
+** to enable them, and negative to leave the setting unchanged.
+** The second argument (the fourth parameter) is a pointer to an integer
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
**
@@ -2861,7 +2941,7 @@ struct sqlite3_mem_methods {
** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]]
** - SQLITE_DBCONFIG_LEGACY_ALTER_TABLE
** - The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates
-** the legacy behavior of the [ALTER TABLE RENAME] command such it
+** the legacy behavior of the [ALTER TABLE RENAME] command such that it
** behaves as it did prior to [version 3.24.0] (2018-06-04). See the
** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for
** additional information. This feature can also be turned on and off
@@ -2910,7 +2990,7 @@ struct sqlite3_mem_methods {
**
- SQLITE_DBCONFIG_LEGACY_FILE_FORMAT
** - The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
** the legacy file format flag. When activated, this flag causes all newly
-** created database file to have a schema format version number (the 4-byte
+** created database files to have a schema format version number (the 4-byte
** integer found at offset 44 into the database header) of 1. This in turn
** means that the resulting database file will be readable and writable by
** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
@@ -2936,8 +3016,8 @@ struct sqlite3_mem_methods {
** statistics. For statistics to be collected, the flag must be set on
** the database handle both when the SQL statement is prepared and when it
** is stepped. The flag is set (collection of statistics is enabled)
-** by default. This option takes two arguments: an integer and a pointer to
-** an integer.. The first argument is 1, 0, or -1 to enable, disable, or
+** by default.
This option takes two arguments: an integer and a pointer to
+** an integer. The first argument is 1, 0, or -1 to enable, disable, or
** leave unchanged the statement scanstatus option. If the second argument
** is not NULL, then the value of the statement scanstatus setting after
** processing the first argument is written into the integer that the second
@@ -2950,7 +3030,7 @@ struct sqlite3_mem_methods {
** in which tables and indexes are scanned so that the scans start at the end
** and work toward the beginning rather than starting at the beginning and
** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
-** same as setting [PRAGMA reverse_unordered_selects]. This option takes
+** same as setting [PRAGMA reverse_unordered_selects].
This option takes
** two arguments which are an integer and a pointer to an integer. The first
** argument is 1, 0, or -1 to enable, disable, or leave unchanged the
** reverse scan order flag, respectively. If the second argument is not NULL,
@@ -2959,7 +3039,76 @@ struct sqlite3_mem_methods {
** first argument.
**
**
+** [[SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]]
+** - SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE
+** - The SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE option enables or disables
+** the ability of the [ATTACH DATABASE] SQL command to create a new database
+** file if the database filed named in the ATTACH command does not already
+** exist. This ability of ATTACH to create a new database is enabled by
+** default. Applications can disable or reenable the ability for ATTACH to
+** create new database files using this DBCONFIG option.
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the attach-create flag, respectively. If the second
+** argument is not NULL, then 0 or 1 is written into the integer that the
+** second argument points to depending on if the attach-create flag is set
+** after processing the first argument.
+**
+**
+** [[SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE]]
+** - SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE
+** - The SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE option enables or disables the
+** ability of the [ATTACH DATABASE] SQL command to open a database for writing.
+** This capability is enabled by default. Applications can disable or
+** reenable this capability using the current DBCONFIG option. If
+** this capability is disabled, the [ATTACH] command will still work,
+** but the database will be opened read-only. If this option is disabled,
+** then the ability to create a new database using [ATTACH] is also disabled,
+** regardless of the value of the [SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE]
+** option.
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the ability to ATTACH another database for writing,
+** respectively. If the second argument is not NULL, then 0 or 1 is written
+** into the integer to which the second argument points, depending on whether
+** the ability to ATTACH a read/write database is enabled or disabled
+** after processing the first argument.
+**
+**
+** [[SQLITE_DBCONFIG_ENABLE_COMMENTS]]
+** - SQLITE_DBCONFIG_ENABLE_COMMENTS
+** - The SQLITE_DBCONFIG_ENABLE_COMMENTS option enables or disables the
+** ability to include comments in SQL text. Comments are enabled by default.
+** An application can disable or reenable comments in SQL text using this
+** DBCONFIG option.
+** This option takes two arguments which are an integer and a pointer
+** to an integer. The first argument is 1, 0, or -1 to enable, disable, or
+** leave unchanged the ability to use comments in SQL text,
+** respectively. If the second argument is not NULL, then 0 or 1 is written
+** into the integer that the second argument points to depending on if
+** comments are allowed in SQL text after processing the first argument.
+**
+**
**
+**
+** [[DBCONFIG arguments]] Arguments To SQLITE_DBCONFIG Options
+**
+** Most of the SQLITE_DBCONFIG options take two arguments, so that the
+** overall call to [sqlite3_db_config()] has a total of four parameters.
+** The first argument (the third parameter to sqlite3_db_config()) is an integer.
+** The second argument is a pointer to an integer. If the first argument is 1,
+** then the option becomes enabled. If the first integer argument is 0, then the
+** option is disabled. If the first argument is -1, then the option setting
+** is unchanged. The second argument, the pointer to an integer, may be NULL.
+** If the second argument is not NULL, then a value of 0 or 1 is written into
+** the integer to which the second argument points, depending on whether the
+** setting is disabled or enabled after applying any changes specified by
+** the first argument.
+**
+**
While most SQLITE_DBCONFIG options use the argument format
+** described in the previous paragraph, the [SQLITE_DBCONFIG_MAINDBNAME]
+** and [SQLITE_DBCONFIG_LOOKASIDE] options are different. See the
+** documentation of those exceptional options for details.
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
@@ -2981,7 +3130,10 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */
#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1019 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_ENABLE_ATTACH_CREATE 1020 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_ATTACH_WRITE 1021 /* int int* */
+#define SQLITE_DBCONFIG_ENABLE_COMMENTS 1022 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1022 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
@@ -3073,10 +3225,14 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter.
** The two functions are identical except for the type of the return value
-** and that if the number of rows modified by the most recent INSERT, UPDATE
+** and that if the number of rows modified by the most recent INSERT, UPDATE,
** or DELETE is greater than the maximum value supported by type "int", then
** the return value of sqlite3_changes() is undefined. ^Executing any other
** type of SQL statement does not modify the value returned by these functions.
+** For the purposes of this interface, a CREATE TABLE AS SELECT statement
+** does not count as an INSERT, UPDATE or DELETE statement and hence the rows
+** added to the new table by the CREATE TABLE AS SELECT statement are not
+** counted.
**
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
@@ -3229,7 +3385,7 @@ SQLITE_API int sqlite3_is_interrupted(sqlite3*);
** ^These routines return 0 if the statement is incomplete. ^If a
** memory allocation fails, then SQLITE_NOMEM is returned.
**
-** ^These routines do not parse the SQL statements thus
+** ^These routines do not parse the SQL statements and thus
** will not detect syntactically incorrect SQL.
**
** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
@@ -3331,6 +3487,44 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
*/
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
+/*
+** CAPI3REF: Set the Setlk Timeout
+** METHOD: sqlite3
+**
+** This routine is only useful in SQLITE_ENABLE_SETLK_TIMEOUT builds. If
+** the VFS supports blocking locks, it sets the timeout in ms used by
+** eligible locks taken on wal mode databases by the specified database
+** handle. In non-SQLITE_ENABLE_SETLK_TIMEOUT builds, or if the VFS does
+** not support blocking locks, this function is a no-op.
+**
+** Passing 0 to this function disables blocking locks altogether. Passing
+** -1 to this function requests that the VFS blocks for a long time -
+** indefinitely if possible. The results of passing any other negative value
+** are undefined.
+**
+** Internally, each SQLite database handle stores two timeout values - the
+** busy-timeout (used for rollback mode databases, or if the VFS does not
+** support blocking locks) and the setlk-timeout (used for blocking locks
+** on wal-mode databases). The sqlite3_busy_timeout() method sets both
+** values, this function sets only the setlk-timeout value. Therefore,
+** to configure separate busy-timeout and setlk-timeout values for a single
+** database handle, call sqlite3_busy_timeout() followed by this function.
+**
+** Whenever the number of connections to a wal mode database falls from
+** 1 to 0, the last connection takes an exclusive lock on the database,
+** then checkpoints and deletes the wal file. While it is doing this, any
+** new connection that tries to read from the database fails with an
+** SQLITE_BUSY error. Or, if the SQLITE_SETLK_BLOCK_ON_CONNECT flag is
+** passed to this API, the new connection blocks until the exclusive lock
+** has been released.
+*/
+SQLITE_API int sqlite3_setlk_timeout(sqlite3*, int ms, int flags);
+
+/*
+** CAPI3REF: Flags for sqlite3_setlk_timeout()
+*/
+#define SQLITE_SETLK_BLOCK_ON_CONNECT 0x01
+
/*
** CAPI3REF: Convenience Routines For Running Queries
** METHOD: sqlite3
@@ -3338,7 +3532,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
** This is a legacy interface that is preserved for backwards compatibility.
** Use of this interface is not recommended.
**
-** Definition: A result table is memory data structure created by the
+** Definition: A result table is a memory data structure created by the
** [sqlite3_get_table()] interface. A result table records the
** complete query results from one or more queries.
**
@@ -3481,7 +3675,7 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** ^Calling sqlite3_free() with a pointer previously returned
** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
** that it might be reused. ^The sqlite3_free() routine is
-** a no-op if is called with a NULL pointer. Passing a NULL pointer
+** a no-op if it is called with a NULL pointer. Passing a NULL pointer
** to sqlite3_free() is harmless. After being freed, memory
** should neither be read nor written. Even reading previously freed
** memory might result in a segmentation fault or other severe error.
@@ -3499,13 +3693,13 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** sqlite3_free(X).
** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation
** of at least N bytes in size or NULL if insufficient memory is available.
-** ^If M is the size of the prior allocation, then min(N,M) bytes
-** of the prior allocation are copied into the beginning of buffer returned
+** ^If M is the size of the prior allocation, then min(N,M) bytes of the
+** prior allocation are copied into the beginning of the buffer returned
** by sqlite3_realloc(X,N) and the prior allocation is freed.
** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the
** prior allocation is not freed.
**
-** ^The sqlite3_realloc64(X,N) interfaces works the same as
+** ^The sqlite3_realloc64(X,N) interface works the same as
** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead
** of a 32-bit signed integer.
**
@@ -3555,7 +3749,7 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void*);
** was last reset. ^The values returned by [sqlite3_memory_used()] and
** [sqlite3_memory_highwater()] include any overhead
** added by SQLite in its implementation of [sqlite3_malloc()],
-** but not overhead added by the any underlying system library
+** but not overhead added by any underlying system library
** routines that [sqlite3_malloc()] may call.
**
** ^The memory high-water mark is reset to the current value of
@@ -4007,7 +4201,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** there is no harm in trying.)
**
** ^(
[SQLITE_OPEN_SHAREDCACHE]
-** The database is opened [shared cache] enabled, overriding
+** The database is opened with [shared cache] enabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
** The [use of shared cache mode is discouraged] and hence shared cache
@@ -4015,14 +4209,14 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** this option is a no-op.
**
** ^([SQLITE_OPEN_PRIVATECACHE]
-** The database is opened [shared cache] disabled, overriding
+** The database is opened with [shared cache] disabled, overriding
** the default shared cache setting provided by
** [sqlite3_enable_shared_cache()].)^
**
** [[OPEN_EXRESCODE]] ^([SQLITE_OPEN_EXRESCODE]
** The database connection comes up in "extended result code mode".
-** In other words, the database behaves has if
-** [sqlite3_extended_result_codes(db,1)] where called on the database
+** In other words, the database behaves as if
+** [sqlite3_extended_result_codes(db,1)] were called on the database
** connection as soon as the connection is created. In addition to setting
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
** to return an extended result code.
@@ -4350,7 +4544,7 @@ SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
**
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
** database filename D with corresponding journal file J and WAL file W and
-** with N URI parameters key/values pairs in the array P. The result from
+** an array P of N URI Key/Value pairs. The result from
** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
** is safe to pass to routines like:
**
@@ -4433,7 +4627,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename);
** subsequent calls to other SQLite interface functions.)^
**
** ^The sqlite3_errstr(E) interface returns the English-language text
-** that describes the [result code] E, as UTF-8, or NULL if E is not an
+** that describes the [result code] E, as UTF-8, or NULL if E is not a
** result code for which a text error message is available.
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
@@ -4441,7 +4635,7 @@ SQLITE_API void sqlite3_free_filename(sqlite3_filename);
** ^If the most recent error references a specific token in the input
** SQL, the sqlite3_error_offset() interface returns the byte offset
** of the start of that token. ^The byte offset returned by
-** sqlite3_error_offset() assumes that the input SQL is UTF8.
+** sqlite3_error_offset() assumes that the input SQL is UTF-8.
** ^If the most recent error does not reference a specific token in the input
** SQL, then the sqlite3_error_offset() function returns -1.
**
@@ -4466,6 +4660,34 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
SQLITE_API const char *sqlite3_errstr(int);
SQLITE_API int sqlite3_error_offset(sqlite3 *db);
+/*
+** CAPI3REF: Set Error Codes And Message
+** METHOD: sqlite3
+**
+** Set the error code of the database handle passed as the first argument
+** to errcode, and the error message to a copy of nul-terminated string
+** zErrMsg. If zErrMsg is passed NULL, then the error message is set to
+** the default message associated with the supplied error code. Subsequent
+** calls to [sqlite3_errcode()] and [sqlite3_errmsg()] and similar will
+** return the values set by this routine in place of what was previously
+** set by SQLite itself.
+**
+** This function returns SQLITE_OK if the error code and error message are
+** successfully set, SQLITE_NOMEM if an OOM occurs, and SQLITE_MISUSE if
+** the database handle is NULL or invalid.
+**
+** The error code and message set by this routine remains in effect until
+** they are changed, either by another call to this routine or until they are
+** changed to by SQLite itself to reflect the result of some subsquent
+** API call.
+**
+** This function is intended for use by SQLite extensions or wrappers. The
+** idea is that an extension or wrapper can use this routine to set error
+** messages and error codes and thus behave more like a core SQLite
+** feature from the point of view of an application.
+*/
+SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zErrMsg);
+
/*
** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
@@ -4540,8 +4762,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
**
** These constants define various performance limits
** that can be lowered at run-time using [sqlite3_limit()].
-** The synopsis of the meanings of the various limits is shown below.
-** Additional information is available at [limits | Limits in SQLite].
+** A concise description of these limits follows, and additional information
+** is available at [limits | Limits in SQLite].
**
**
** [[SQLITE_LIMIT_LENGTH]] ^(- SQLITE_LIMIT_LENGTH
@@ -4606,7 +4828,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Prepare Flags
**
-** These constants define various flags that can be passed into
+** These constants define various flags that can be passed into the
** "prepFlags" parameter of the [sqlite3_prepare_v3()] and
** [sqlite3_prepare16_v3()] interfaces.
**
@@ -4636,11 +4858,22 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** - The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
** to return an error (error code SQLITE_ERROR) if the statement uses
** any virtual tables.
+**
+** [[SQLITE_PREPARE_DONT_LOG]]
- SQLITE_PREPARE_DONT_LOG
+** - The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
+** errors from being sent to the error log defined by
+** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
+** compiles to see if some SQL syntax is well-formed, without generating
+** messages on the global error log when it is not. If the test compile
+** fails, the sqlite3_prepare_v3() call returns the same error indications
+** with or without this flag; it just omits the call to [sqlite3_log()] that
+** logs the error.
**
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
#define SQLITE_PREPARE_NORMALIZE 0x02
#define SQLITE_PREPARE_NO_VTAB 0x04
+#define SQLITE_PREPARE_DONT_LOG 0x10
/*
** CAPI3REF: Compiling An SQL Statement
@@ -4673,13 +4906,17 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** and sqlite3_prepare16_v3() use UTF-16.
**
** ^If the nByte argument is negative, then zSql is read up to the
-** first zero terminator. ^If nByte is positive, then it is the
-** number of bytes read from zSql. ^If nByte is zero, then no prepared
+** first zero terminator. ^If nByte is positive, then it is the maximum
+** number of bytes read from zSql. When nByte is positive, zSql is read
+** up to the first zero terminator or until the nByte bytes have been read,
+** whichever comes first. ^If nByte is zero, then no prepared
** statement is generated.
** If the caller knows that the supplied string is nul-terminated, then
** there is a small performance advantage to passing an nByte parameter that
** is the number of bytes in the input string including
** the nul-terminator.
+** Note that nByte measures the length of the input in bytes, not
+** characters, even for the UTF-16 interfaces.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only
@@ -4812,7 +5049,7 @@ SQLITE_API int sqlite3_prepare16_v3(
**
** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory
** is available to hold the result, or if the result would exceed the
-** the maximum string length determined by the [SQLITE_LIMIT_LENGTH].
+** maximum string length determined by the [SQLITE_LIMIT_LENGTH].
**
** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of
** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
@@ -5000,7 +5237,7 @@ typedef struct sqlite3_value sqlite3_value;
**
** The context in which an SQL function executes is stored in an
** sqlite3_context object. ^A pointer to an sqlite3_context object
-** is always first parameter to [application-defined SQL functions].
+** is always the first parameter to [application-defined SQL functions].
** The application-defined SQL function implementation will pass this
** pointer through into calls to [sqlite3_result_int | sqlite3_result()],
** [sqlite3_aggregate_context()], [sqlite3_user_data()],
@@ -5016,7 +5253,7 @@ typedef struct sqlite3_context sqlite3_context;
** METHOD: sqlite3_stmt
**
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
-** literals may be replaced by a [parameter] that matches one of following
+** literals may be replaced by a [parameter] that matches one of the following
** templates:
**
**
@@ -5061,7 +5298,7 @@ typedef struct sqlite3_context sqlite3_context;
**
** [[byte-order determination rules]] ^The byte-order of
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
-** found in first character, which is removed, or in the absence of a BOM
+** found in the first character, which is removed, or in the absence of a BOM
** the byte order is the native byte order of the host
** machine for sqlite3_bind_text16() or the byte order specified in
** the 6th parameter for sqlite3_bind_text64().)^
@@ -5081,7 +5318,7 @@ typedef struct sqlite3_context sqlite3_context;
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
** that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
-** terminated. If any NUL characters occurs at byte offsets less than
+** terminated. If any NUL characters occur at byte offsets less than
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
@@ -5124,9 +5361,11 @@ typedef struct sqlite3_context sqlite3_context;
** associated with the pointer P of type T. ^D is either a NULL pointer or
** a pointer to a destructor function for P. ^SQLite will invoke the
** destructor D with a single argument of P when it is finished using
-** P. The T parameter should be a static string, preferably a string
-** literal. The sqlite3_bind_pointer() routine is part of the
-** [pointer passing interface] added for SQLite 3.20.0.
+** P, even if the call to sqlite3_bind_pointer() fails. Due to a
+** historical design quirk, results are undefined if D is
+** SQLITE_TRANSIENT. The T parameter should be a static string,
+** preferably a string literal. The sqlite3_bind_pointer() routine is
+** part of the [pointer passing interface] added for SQLite 3.20.0.
**
** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
** for the [prepared statement] or with a prepared statement for which
@@ -5293,7 +5532,7 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
** METHOD: sqlite3_stmt
**
** ^These routines provide a means to determine the database, table, and
-** table column that is the origin of a particular result column in
+** table column that is the origin of a particular result column in a
** [SELECT] statement.
** ^The name of the database or table or column can be returned as
** either a UTF-8 or UTF-16 string. ^The _database_ routines return
@@ -5431,7 +5670,7 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** other than [SQLITE_ROW] before any subsequent invocation of
** sqlite3_step(). Failure to reset the prepared statement using
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
-** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
+** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1]),
** sqlite3_step() began
** calling [sqlite3_reset()] automatically in this circumstance rather
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
@@ -5737,7 +5976,7 @@ SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors
-** or if the statement is never been evaluated, then sqlite3_finalize() returns
+** or if the statement has never been evaluated, then sqlite3_finalize() returns
** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
** sqlite3_finalize(S) returns the appropriate [error code] or
** [extended error code].
@@ -5862,8 +6101,8 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
**
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be
-** used inside of triggers, view, CHECK constraints, or other elements of
-** the database schema. This flags is especially recommended for SQL
+** used inside of triggers, views, CHECK constraints, or other elements of
+** the database schema. This flag is especially recommended for SQL
** functions that have side effects or reveal internal application state.
** Without this flag, an attacker might be able to modify the schema of
** a database file to include invocations of the function with parameters
@@ -5894,7 +6133,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** [user-defined window functions|available here].
**
** ^(If the final parameter to sqlite3_create_function_v2() or
-** sqlite3_create_window_function() is not NULL, then it is destructor for
+** sqlite3_create_window_function() is not NULL, then it is the destructor for
** the application data pointer. The destructor is invoked when the function
** is deleted, either by being overloaded or when the database connection
** closes.)^ ^The destructor is also invoked if the call to
@@ -5969,7 +6208,7 @@ SQLITE_API int sqlite3_create_window_function(
/*
** CAPI3REF: Text Encodings
**
-** These constant define integer codes that represent the various
+** These constants define integer codes that represent the various
** text encodings supported by SQLite.
*/
#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
@@ -6050,7 +6289,7 @@ SQLITE_API int sqlite3_create_window_function(
** This flag instructs SQLite to omit some corner-case optimizations that
** might disrupt the operation of the [sqlite3_value_subtype()] function,
** causing it to return zero rather than the correct subtype().
-** SQL functions that invokes [sqlite3_value_subtype()] should have this
+** All SQL functions that invoke [sqlite3_value_subtype()] should have this
** property. If the SQLITE_SUBTYPE property is omitted, then the return
** value from [sqlite3_value_subtype()] might sometimes be zero even though
** a non-zero subtype was specified by the function argument expression.
@@ -6061,11 +6300,20 @@ SQLITE_API int sqlite3_create_window_function(
** result.
** Every function that invokes [sqlite3_result_subtype()] should have this
** property. If it does not, then the call to [sqlite3_result_subtype()]
-** might become a no-op if the function is used as term in an
+** might become a no-op if the function is used as a term in an
** [expression index]. On the other hand, SQL functions that never invoke
** [sqlite3_result_subtype()] should avoid setting this property, as the
** purpose of this property is to disable certain optimizations that are
** incompatible with subtypes.
+**
+** [[SQLITE_SELFORDER1]] - SQLITE_SELFORDER1
-
+** The SQLITE_SELFORDER1 flag indicates that the function is an aggregate
+** that internally orders the values provided to the first argument. The
+** ordered-set aggregate SQL notation with a single ORDER BY term can be
+** used to invoke this function. If the ordered-set aggregate notation is
+** used on a function that lacks this flag, then an error is raised. Note
+** that the ordered-set aggregate syntax is only available if SQLite is
+** built using the -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES compile-time option.
**
**
*/
@@ -6074,6 +6322,7 @@ SQLITE_API int sqlite3_create_window_function(
#define SQLITE_SUBTYPE 0x000100000
#define SQLITE_INNOCUOUS 0x000200000
#define SQLITE_RESULT_SUBTYPE 0x001000000
+#define SQLITE_SELFORDER1 0x002000000
/*
** CAPI3REF: Deprecated Functions
@@ -6178,7 +6427,7 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** sqlite3_value_nochange(X) interface returns true if and only if
** the column corresponding to X is unchanged by the UPDATE operation
** that the xUpdate method call was invoked to implement and if
-** and the prior [xColumn] method call that was invoked to extracted
+** the prior [xColumn] method call that was invoked to extract
** the value for that column returned without setting a result (probably
** because it queried [sqlite3_vtab_nochange()] and found that the column
** was unchanging). ^Within an [xUpdate] method, any value for which
@@ -6271,7 +6520,7 @@ SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
** one SQL function to another. Use the [sqlite3_result_subtype()]
** routine to set the subtype for the return value of an SQL function.
**
-** Every [application-defined SQL function] that invoke this interface
+** Every [application-defined SQL function] that invokes this interface
** should include the [SQLITE_SUBTYPE] property in the text
** encoding argument when the function is [sqlite3_create_function|registered].
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
@@ -6284,7 +6533,7 @@ SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
** METHOD: sqlite3_value
**
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
-** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
+** object V and returns a pointer to that copy. ^The [sqlite3_value] returned
** is a [protected sqlite3_value] object even if the input is not.
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
** memory allocation fails. ^If V is a [pointer value], then the result
@@ -6322,7 +6571,7 @@ SQLITE_API void sqlite3_value_free(sqlite3_value*);
** allocation error occurs.
**
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
-** determined by the N parameter on first successful call. Changing the
+** determined by the N parameter on the first successful call. Changing the
** value of N in any subsequent call to sqlite3_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^ Within the xFinal callback, it is customary to set
@@ -6451,6 +6700,7 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi
** or a NULL pointer if there were no prior calls to
** sqlite3_set_clientdata() with the same values of D and N.
** Names are compared using strcmp() and are thus case sensitive.
+** It returns 0 on success and SQLITE_NOMEM on allocation failure.
**
** If P and X are both non-NULL, then the destructor X is invoked with
** argument P on the first of the following occurrences:
@@ -6484,7 +6734,7 @@ SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(voi
**
** Security Warning: These interfaces should not be exposed in scripting
** languages or in other circumstances where it might be possible for an
-** an attacker to invoke them. Any agent that can invoke these interfaces
+** attacker to invoke them. Any agent that can invoke these interfaces
** can probably also take control of the process.
**
** Database connection client data is only available for SQLite
@@ -6598,7 +6848,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** pointed to by the 2nd parameter are taken as the application-defined
** function result. If the 3rd parameter is non-negative, then it
** must be the byte offset into the string where the NUL terminator would
-** appear if the string where NUL terminated. If any NUL characters occur
+** appear if the string were NUL terminated. If any NUL characters occur
** in the string at a byte offset that is less than the value of the 3rd
** parameter, then the resulting string will contain embedded NULs and the
** result of expressions operating on strings with embedded NULs is undefined.
@@ -6656,7 +6906,7 @@ typedef void (*sqlite3_destructor_type)(void*);
** string and preferably a string literal. The sqlite3_result_pointer()
** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
**
-** If these routines are called from within the different thread
+** If these routines are called from within a different thread
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
@@ -7062,7 +7312,7 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** METHOD: sqlite3
**
** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name
-** for the N-th database on database connection D, or a NULL pointer of N is
+** for the N-th database on database connection D, or a NULL pointer if N is
** out of range. An N value of 0 means the main database file. An N of 1 is
** the "temp" schema. Larger values of N correspond to various ATTACH-ed
** databases.
@@ -7157,7 +7407,7 @@ SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
** - The SQLITE_TXN_READ state means that the database is currently
** in a read transaction. Content has been read from the database file
** but nothing in the database file has changed. The transaction state
-** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
+** will be advanced to SQLITE_TXN_WRITE if any changes occur and there are
** no other conflicting concurrent write transactions. The transaction
** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
** [COMMIT].
@@ -7166,7 +7416,7 @@ SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
** - The SQLITE_TXN_WRITE state means that the database is currently
** in a write transaction. Content has been written to the database file
** but has not yet committed. The transaction state will change to
-** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].
+** SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].
*/
#define SQLITE_TXN_NONE 0
#define SQLITE_TXN_READ 1
@@ -7317,6 +7567,8 @@ SQLITE_API int sqlite3_autovacuum_pages(
**
** ^The second argument is a pointer to the function to invoke when a
** row is updated, inserted or deleted in a rowid table.
+** ^The update hook is disabled by invoking sqlite3_update_hook()
+** with a NULL pointer as the second parameter.
** ^The first argument to the callback is a copy of the third argument
** to sqlite3_update_hook().
** ^The second callback argument is one of [SQLITE_INSERT], [SQLITE_DELETE],
@@ -7445,7 +7697,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** CAPI3REF: Impose A Limit On Heap Size
**
** These interfaces impose limits on the amount of heap memory that will be
-** by all database connections within a single process.
+** used by all database connections within a single process.
**
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
** soft limit on the amount of heap memory that may be allocated by SQLite.
@@ -7503,7 +7755,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
**
)^
**
** The circumstances under which SQLite will enforce the heap limits may
-** changes in future releases of SQLite.
+** change in future releases of SQLite.
*/
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
@@ -7618,8 +7870,8 @@ SQLITE_API int sqlite3_table_column_metadata(
** ^The entry point is zProc.
** ^(zProc may be 0, in which case SQLite will try to come up with an
** entry point name on its own. It first tries "sqlite3_extension_init".
-** If that does not work, it constructs a name "sqlite3_X_init" where the
-** X is consists of the lower-case equivalent of all ASCII alphabetic
+** If that does not work, it constructs a name "sqlite3_X_init" where
+** X consists of the lower-case equivalent of all ASCII alphabetic
** characters in the filename from the last "/" to the first following
** "." and omitting any initial "lib".)^
** ^The sqlite3_load_extension() interface returns
@@ -7690,7 +7942,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** ^(Even though the function prototype shows that xEntryPoint() takes
** no arguments and returns void, SQLite invokes xEntryPoint() with three
** arguments and expects an integer result as if the signature of the
-** entry point where as follows:
+** entry point were as follows:
**
**
** int xEntryPoint(
@@ -7854,7 +8106,7 @@ struct sqlite3_module {
** virtual table and might not be checked again by the byte code.)^ ^(The
** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
** is left in its default setting of false, the constraint will always be
-** checked separately in byte code. If the omit flag is change to true, then
+** checked separately in byte code. If the omit flag is changed to true, then
** the constraint may or may not be checked in byte code. In other words,
** when the omit flag is true there is no guarantee that the constraint will
** not be checked again using byte code.)^
@@ -7878,9 +8130,11 @@ struct sqlite3_module {
** will be returned by the strategy.
**
** The xBestIndex method may optionally populate the idxFlags field with a
-** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
-** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
-** assumes that the strategy may visit at most one row.
+** mask of SQLITE_INDEX_SCAN_* flags. One such flag is
+** [SQLITE_INDEX_SCAN_HEX], which if set causes the [EXPLAIN QUERY PLAN]
+** output to show the idxNum as hex instead of as decimal. Another flag is
+** SQLITE_INDEX_SCAN_UNIQUE, which if set indicates that the query plan will
+** return at most one row.
**
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
** SQLite also assumes that if a call to the xUpdate() method is made as
@@ -7944,7 +8198,9 @@ struct sqlite3_index_info {
** [sqlite3_index_info].idxFlags field to some combination of
** these bits.
*/
-#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
+#define SQLITE_INDEX_SCAN_UNIQUE 0x00000001 /* Scan visits at most 1 row */
+#define SQLITE_INDEX_SCAN_HEX 0x00000002 /* Display idxNum as hex */
+ /* in EXPLAIN QUERY PLAN */
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
@@ -8017,7 +8273,7 @@ struct sqlite3_index_info {
** the implementation of the [virtual table module]. ^The fourth
** parameter is an arbitrary client data pointer that is passed through
** into the [xCreate] and [xConnect] methods of the virtual table module
-** when a new virtual table is be being created or reinitialized.
+** when a new virtual table is being created or reinitialized.
**
** ^The sqlite3_create_module_v2() interface has a fifth parameter which
** is a pointer to a destructor for the pClientData. ^SQLite will
@@ -8182,7 +8438,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** in *ppBlob. Otherwise an [error code] is returned and, unless the error
** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided
** the API is not misused, it is always safe to call [sqlite3_blob_close()]
-** on *ppBlob after this function it returns.
+** on *ppBlob after this function returns.
**
** This function fails with SQLITE_ERROR if any of the following are true:
**
@@ -8302,7 +8558,7 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
**
** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
-** incremental blob I/O routines can only read or overwriting existing
+** incremental blob I/O routines can only read or overwrite existing
** blob content; they cannot change the size of a blob.
**
** This routine only works on a [BLOB handle] which has been created
@@ -8452,7 +8708,7 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
** ^The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc()
** routine returns NULL if it is unable to allocate the requested
-** mutex. The argument to sqlite3_mutex_alloc() must one of these
+** mutex. The argument to sqlite3_mutex_alloc() must be one of these
** integer constants:
**
**
@@ -8685,7 +8941,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
** CAPI3REF: Retrieve the mutex for a database connection
** METHOD: sqlite3
**
-** ^This interface returns a pointer the [sqlite3_mutex] object that
+** ^This interface returns a pointer to the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.
** ^If the [threading mode] is Single-thread or Multi-thread then this
@@ -8781,6 +9037,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_JSON_SELFCHECK 14
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
+#define SQLITE_TESTCTRL_GETOPT 16
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
@@ -8800,14 +9057,14 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_TRACEFLAGS 31
#define SQLITE_TESTCTRL_TUNE 32
#define SQLITE_TESTCTRL_LOGEST 33
-#define SQLITE_TESTCTRL_USELONGDOUBLE 34
+#define SQLITE_TESTCTRL_USELONGDOUBLE 34 /* NOT USED */
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
**
** These routines provide access to the set of SQL language keywords
-** recognized by SQLite. Applications can uses these routines to determine
+** recognized by SQLite. Applications can use these routines to determine
** whether or not a specific identifier needs to be escaped (for example,
** by enclosing in double-quotes) so as not to confuse the parser.
**
@@ -8975,7 +9232,7 @@ SQLITE_API void sqlite3_str_reset(sqlite3_str*);
** content of the dynamic string under construction in X. The value
** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
** and might be freed or altered by any subsequent method on the same
-** [sqlite3_str] object. Applications must not used the pointer returned
+** [sqlite3_str] object. Applications must not use the pointer returned by
** [sqlite3_str_value(X)] after any subsequent method call on the same
** object. ^Applications may change the content of the string returned
** by [sqlite3_str_value(X)] as long as they do not write into any bytes
@@ -9061,7 +9318,7 @@ SQLITE_API int sqlite3_status64(
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
** buffer and where forced to overflow to [sqlite3_malloc()]. The
** returned value includes allocations that overflowed because they
-** where too large (they were larger than the "sz" parameter to
+** were too large (they were larger than the "sz" parameter to
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
** no space was left in the page cache.)^
**
@@ -9120,9 +9377,18 @@ SQLITE_API int sqlite3_status64(
** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a
** non-zero [error code] on failure.
**
+** ^The sqlite3_db_status64(D,O,C,H,R) routine works exactly the same
+** way as sqlite3_db_status(D,O,C,H,R) routine except that the C and H
+** parameters are pointer to 64-bit integers (type: sqlite3_int64) instead
+** of pointers to 32-bit integers, which allows larger status values
+** to be returned. If a status value exceeds 2,147,483,647 then
+** sqlite3_db_status() will truncate the value whereas sqlite3_db_status64()
+** will return the full value.
+**
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
*/
SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API int sqlite3_db_status64(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
/*
** CAPI3REF: Status Parameters for database connections
@@ -9145,28 +9411,29 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(- SQLITE_DBSTATUS_LOOKASIDE_HIT
** - This parameter returns the number of malloc attempts that were
** satisfied using lookaside memory. Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.
)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(- SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE
-** - This parameter returns the number malloc attempts that might have
+**
- This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
** memory requested being larger than the lookaside slot size.
** Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.
)^
**
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^( - SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL
-** - This parameter returns the number malloc attempts that might have
+**
- This parameter returns the number of malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
-** the current value is always zero.)^
+** the current value is always zero.
)^
**
** [[SQLITE_DBSTATUS_CACHE_USED]] ^( - SQLITE_DBSTATUS_CACHE_USED
** - This parameter returns the approximate number of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
+**
**
** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]]
** ^(- SQLITE_DBSTATUS_CACHE_USED_SHARED
@@ -9175,10 +9442,10 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** memory used by that pager cache is divided evenly between the attached
** connections.)^ In other words, if none of the pager caches associated
** with the database connection are shared, this request returns the same
-** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are
+** value as DBSTATUS_CACHE_USED. Or, if one or more of the pager caches are
** shared, the value returned by this call will be smaller than that returned
** by DBSTATUS_CACHE_USED. ^The highwater mark associated with
-** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
+** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
**
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(- SQLITE_DBSTATUS_SCHEMA_USED
** - This parameter returns the approximate number of bytes of heap
@@ -9188,6 +9455,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
+**
**
** [[SQLITE_DBSTATUS_STMT_USED]] ^(- SQLITE_DBSTATUS_STMT_USED
** - This parameter returns the approximate number of bytes of heap
@@ -9217,6 +9485,10 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** If an IO or other error occurs while writing a page to disk, the effect
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
+**
+** ^(There is overlap between the quantities measured by this parameter
+** (SQLITE_DBSTATUS_CACHE_WRITE) and SQLITE_DBSTATUS_TEMPBUF_SPILL.
+** Resetting one will reduce the other.)^
**
**
** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(- SQLITE_DBSTATUS_CACHE_SPILL
@@ -9224,7 +9496,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** been written to disk in the middle of a transaction due to the page
** cache overflowing. Transactions are more efficient if they are written
** to disk all at once. When pages spill mid-transaction, that introduces
-** additional overhead. This parameter can be used help identify
+** additional overhead. This parameter can be used to help identify
** inefficiencies that can be resolved by increasing the cache size.
**
**
@@ -9232,6 +9504,18 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
** - 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.
+**
+** [[SQLITE_DBSTATUS_TEMPBUF_SPILL] ^(
- SQLITE_DBSTATUS_TEMPBUF_SPILL
+** - ^(This parameter returns the number of bytes written to temporary
+** files on disk that could have been kept in memory had sufficient memory
+** been available. This value includes writes to intermediate tables that
+** are part of complex queries, external sorts that spill to disk, and
+** writes to TEMP tables.)^
+** ^The highwater mark is always 0.
+**
+** ^(There is overlap between the quantities measured by this parameter
+** (SQLITE_DBSTATUS_TEMPBUF_SPILL) and SQLITE_DBSTATUS_CACHE_WRITE.
+** Resetting one will reduce the other.)^
**
**
*/
@@ -9248,7 +9532,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
#define SQLITE_DBSTATUS_DEFERRED_FKS 10
#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11
#define SQLITE_DBSTATUS_CACHE_SPILL 12
-#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */
+#define SQLITE_DBSTATUS_TEMPBUF_SPILL 13
+#define SQLITE_DBSTATUS_MAX 13 /* Largest defined DBSTATUS */
/*
@@ -9295,13 +9580,13 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** [[SQLITE_STMTSTATUS_SORT]] - SQLITE_STMTSTATUS_SORT
** - ^This is the number of sort operations that have occurred.
** A non-zero value in this counter may indicate an opportunity to
-** improvement performance through careful use of indices.
+** improve performance through careful use of indices.
**
** [[SQLITE_STMTSTATUS_AUTOINDEX]] - SQLITE_STMTSTATUS_AUTOINDEX
** - ^This is the number of rows inserted into transient indices that
** were created automatically in order to help joins run faster.
** A non-zero value in this counter may indicate an opportunity to
-** improvement performance by adding permanent indices that do not
+** improve performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.
**
** [[SQLITE_STMTSTATUS_VM_STEP]] - SQLITE_STMTSTATUS_VM_STEP
@@ -9310,19 +9595,19 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** 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.
+** then the value returned by this statement status code is undefined.
**
** [[SQLITE_STMTSTATUS_REPREPARE]] - SQLITE_STMTSTATUS_REPREPARE
** - ^This is the number of times that the prepare statement has been
** automatically regenerated due to schema changes or changes to
-** [bound parameters] that might affect the query plan.
+** [bound parameters] that might affect the query plan.
**
** [[SQLITE_STMTSTATUS_RUN]] - SQLITE_STMTSTATUS_RUN
** - ^This is the number of times that the prepared statement has
** been run. A single "run" for the purposes of this counter is one
** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
** The counter is incremented on the first [sqlite3_step()] call of each
-** cycle.
+** cycle.
**
** [[SQLITE_STMTSTATUS_FILTER_MISS]]
** [[SQLITE_STMTSTATUS_FILTER HIT]]
@@ -9332,7 +9617,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
** step was bypassed because a Bloom filter returned not-found. The
** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
** times that the Bloom filter returned a find, and thus the join step
-** had to be processed as normal.
+** had to be processed as normal.
**
** [[SQLITE_STMTSTATUS_MEMUSED]] - SQLITE_STMTSTATUS_MEMUSED
** - ^This is the approximate number of bytes of heap memory
@@ -9437,9 +9722,9 @@ struct sqlite3_pcache_page {
** SQLite will typically create one cache instance for each open database file,
** though this is not guaranteed. ^The
** first parameter, szPage, is the size in bytes of the pages that must
-** be allocated by the cache. ^szPage will always a power of two. ^The
+** be allocated by the cache. ^szPage will always be a power of two. ^The
** second parameter szExtra is a number of bytes of extra storage
-** associated with each page cache entry. ^The szExtra parameter will
+** associated with each page cache entry. ^The szExtra parameter will be
** a number less than 250. SQLite will use the
** extra szExtra bytes on each page to store metadata about the underlying
** database page on disk. The value passed into szExtra depends
@@ -9447,17 +9732,17 @@ struct sqlite3_pcache_page {
** ^The third argument to xCreate(), bPurgeable, is true if the cache being
** created will be used to cache database pages of a file stored on disk, or
** false if it is used for an in-memory database. The cache implementation
-** does not have to do anything special based with the value of bPurgeable;
+** does not have to do anything special based upon the value of bPurgeable;
** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
** never invoke xUnpin() except to deliberately delete a page.
** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
** false will always have the "discard" flag set to true.
-** ^Hence, a cache created with bPurgeable false will
+** ^Hence, a cache created with bPurgeable set to false will
** never contain any unpinned pages.
**
** [[the xCachesize() page cache method]]
** ^(The xCachesize() method may be called at any time by SQLite to set the
-** suggested maximum cache-size (number of pages stored by) the cache
+** suggested maximum cache-size (number of pages stored) for the cache
** instance passed as the first argument. This is the value configured using
** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
** parameter, the implementation is not required to do anything with this
@@ -9484,12 +9769,12 @@ struct sqlite3_pcache_page {
** implementation must return a pointer to the page buffer with its content
** intact. If the requested page is not already in the cache, then the
** cache implementation should use the value of the createFlag
-** parameter to help it determined what action to take:
+** parameter to help it determine what action to take:
**
**
** | createFlag | Behavior when page is not already in cache
** |
|---|
| 0 | Do not allocate a new page. Return NULL.
-** |
| 1 | Allocate a new page if it easy and convenient to do so.
+** |
| 1 | Allocate a new page if it is easy and convenient to do so.
** Otherwise return NULL.
** |
| 2 | Make every effort to allocate a new page. Only return
** NULL if allocating a new page is effectively impossible.
@@ -9506,7 +9791,7 @@ struct sqlite3_pcache_page {
** as its second argument. If the third parameter, discard, is non-zero,
** then the page must be evicted from the cache.
** ^If the discard parameter is
-** zero, then the page may be discarded or retained at the discretion of
+** zero, then the page may be discarded or retained at the discretion of the
** page cache implementation. ^The page cache implementation
** may choose to evict unpinned pages at any time.
**
@@ -9524,7 +9809,7 @@ struct sqlite3_pcache_page {
** When SQLite calls the xTruncate() method, the cache must discard all
** existing cache entries with page numbers (keys) greater than or equal
** to the value of the iLimit parameter passed to xTruncate(). If any
-** of these pages are pinned, they are implicitly unpinned, meaning that
+** of these pages are pinned, they become implicitly unpinned, meaning that
** they can be safely discarded.
**
** [[the xDestroy() page cache method]]
@@ -9704,7 +9989,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** external process or via a database connection other than the one being
** used by the backup operation, then the backup will be automatically
** restarted by the next call to sqlite3_backup_step(). ^If the source
-** database is modified by the using the same database connection as is used
+** database is modified by using the same database connection as is used
** by the backup operation, then the backup database is automatically
** updated at the same time.
**
@@ -9721,7 +10006,7 @@ typedef struct sqlite3_backup sqlite3_backup;
** and may not be used following a call to sqlite3_backup_finish().
**
** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
-** sqlite3_backup_step() errors occurred, regardless or whether or not
+** sqlite3_backup_step() errors occurred, regardless of whether or not
** sqlite3_backup_step() completed.
** ^If an out-of-memory condition or IO error occurred during any prior
** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
@@ -9776,6 +10061,16 @@ typedef struct sqlite3_backup sqlite3_backup;
** APIs are not strictly speaking threadsafe. If they are invoked at the
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
+**
+** Alternatives To Using The Backup API
+**
+** Other techniques for safely creating a consistent backup of an SQLite
+** database include:
+**
+**
+** - The [VACUUM INTO] command.
+**
- The [sqlite3_rsync] utility program.
+**
*/
SQLITE_API sqlite3_backup *sqlite3_backup_init(
sqlite3 *pDest, /* Destination database handle */
@@ -9813,7 +10108,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** application receives an SQLITE_LOCKED error, it may call the
** sqlite3_unlock_notify() method with the blocked connection handle as
** the first argument to register for a callback that will be invoked
-** when the blocking connections current transaction is concluded. ^The
+** when the blocking connection's current transaction is concluded. ^The
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
** call that concludes the blocking connection's transaction.
**
@@ -9833,7 +10128,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** blocked connection already has a registered unlock-notify callback,
** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
** called with a NULL pointer as its second argument, then any existing
-** unlock-notify callback is canceled. ^The blocked connections
+** unlock-notify callback is canceled. ^The blocked connection's
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite3_close()].
**
@@ -10003,7 +10298,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** is the number of pages currently in the write-ahead log file,
** including those that were just committed.
**
-** The callback function should normally return [SQLITE_OK]. ^If an error
+** ^The callback function should normally return [SQLITE_OK]. ^If an error
** code is returned, that error will propagate back up through the
** SQLite code base to cause the statement that provoked the callback
** to report an error, though the commit will have still occurred. If the
@@ -10011,13 +10306,26 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** that does not correspond to any valid SQLite error code, the results
** are undefined.
**
-** A single database handle may have at most a single write-ahead log callback
-** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
-** previously registered write-ahead log callback. ^The return value is
-** a copy of the third parameter from the previous call, if any, or 0.
-** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
-** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
-** overwrite any prior [sqlite3_wal_hook()] settings.
+** ^A single database handle may have at most a single write-ahead log
+** callback registered at one time. ^Calling [sqlite3_wal_hook()]
+** replaces the default behavior or previously registered write-ahead
+** log callback.
+**
+** ^The return value is a copy of the third parameter from the
+** previous call, if any, or 0.
+**
+** ^The [sqlite3_wal_autocheckpoint()] interface and the
+** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and
+** will overwrite any prior [sqlite3_wal_hook()] settings.
+**
+** ^If a write-ahead log callback is set using this function then
+** [sqlite3_wal_checkpoint_v2()] or [PRAGMA wal_checkpoint]
+** should be invoked periodically to keep the write-ahead log file
+** from growing without bound.
+**
+** ^Passing a NULL pointer for the callback disables automatic
+** checkpointing entirely. To re-enable the default behavior, call
+** sqlite3_wal_autocheckpoint(db,1000) or use [PRAGMA wal_checkpoint].
*/
SQLITE_API void *sqlite3_wal_hook(
sqlite3*,
@@ -10034,7 +10342,7 @@ SQLITE_API void *sqlite3_wal_hook(
** to automatically [checkpoint]
** after committing a transaction if there are N or
** more frames in the [write-ahead log] file. ^Passing zero or
-** a negative value as the nFrame parameter disables automatic
+** a negative value as the N parameter disables automatic
** checkpoints entirely.
**
** ^The callback registered by this function replaces any existing callback
@@ -10050,9 +10358,10 @@ SQLITE_API void *sqlite3_wal_hook(
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
-** pages. The use of this interface
-** is only necessary if the default setting is found to be suboptimal
-** for a particular application.
+** pages.
+**
+** ^The use of this interface is only necessary if the default setting
+** is found to be suboptimal for a particular application.
*/
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
@@ -10117,6 +10426,11 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
** addition that it also truncates the log file to zero bytes just prior
** to a successful return.
+**
+** - SQLITE_CHECKPOINT_NOOP
-
+** ^This mode always checkpoints zero frames. The only reason to invoke
+** a NOOP checkpoint is to access the values returned by
+** sqlite3_wal_checkpoint_v2() via output parameters *pnLog and *pnCkpt.
**
**
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
@@ -10187,6 +10501,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
** meaning of each of these checkpoint modes.
*/
+#define SQLITE_CHECKPOINT_NOOP -1 /* Do no work at all */
#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */
#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */
#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */
@@ -10231,7 +10546,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** support constraints. In this configuration (which is the default) if
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
-** specified as part of the users SQL statement, regardless of the actual
+** specified as part of the user's SQL statement, regardless of the actual
** ON CONFLICT mode specified.
**
** If X is non-zero, then the virtual table implementation guarantees
@@ -10265,7 +10580,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** [[SQLITE_VTAB_INNOCUOUS]]
- SQLITE_VTAB_INNOCUOUS
** - Calls of the form
** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
-** the [xConnect] or [xCreate] methods of a [virtual table] implementation
+** [xConnect] or [xCreate] methods of a [virtual table] implementation
** identify that virtual table as being safe to use from within triggers
** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
** virtual table can do no serious harm even if it is controlled by a
@@ -10433,7 +10748,7 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
**
|
**
** ^For the purposes of comparing virtual table output values to see if the
-** values are same value for sorting purposes, two NULL values are considered
+** values are the same value for sorting purposes, two NULL values are considered
** to be the same. In other words, the comparison operator is "IS"
** (or "IS NOT DISTINCT FROM") and not "==".
**
@@ -10443,7 +10758,7 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
**
** ^A virtual table implementation is always free to return rows in any order
** it wants, as long as the "orderByConsumed" flag is not set. ^When the
-** the "orderByConsumed" flag is unset, the query planner will add extra
+** "orderByConsumed" flag is unset, the query planner will add extra
** [bytecode] to ensure that the final results returned by the SQL query are
** ordered correctly. The use of the "orderByConsumed" flag and the
** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
@@ -10540,7 +10855,7 @@ SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
** sqlite3_vtab_in_next(X,P) should be one of the parameters to the
** xFilter method which invokes these routines, and specifically
** a parameter that was previously selected for all-at-once IN constraint
-** processing use the [sqlite3_vtab_in()] interface in the
+** processing using the [sqlite3_vtab_in()] interface in the
** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
** an xFilter argument that was selected for all-at-once IN constraint
** processing, then these routines return [SQLITE_ERROR].)^
@@ -10555,7 +10870,7 @@ SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
** ){
** // do something with pVal
** }
-** if( rc!=SQLITE_OK ){
+** if( rc!=SQLITE_DONE ){
** // an error has occurred
** }
**
)^
@@ -10595,7 +10910,7 @@ SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);
** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V)
** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
** constraint is not available. ^The sqlite3_vtab_rhs_value() interface
-** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if
+** can return a result code other than SQLITE_OK or SQLITE_NOTFOUND if
** something goes wrong.
**
** The sqlite3_vtab_rhs_value() interface is usually only successful if
@@ -10623,8 +10938,8 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **
** KEYWORDS: {conflict resolution mode}
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
-** inform a [virtual table] implementation what the [ON CONFLICT] mode
-** is for the SQL statement being evaluated.
+** inform a [virtual table] implementation of the [ON CONFLICT] mode
+** for the SQL statement being evaluated.
**
** Note that the [SQLITE_IGNORE] constant is also used as a potential
** return value from the [sqlite3_set_authorizer()] callback and that
@@ -10664,39 +10979,39 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **
** [[SQLITE_SCANSTAT_EST]] - SQLITE_SCANSTAT_EST
** - ^The "double" variable pointed to by the V parameter will be set to the
** query planner's estimate for the average number of rows output from each
-** iteration of the X-th loop. If the query planner's estimates was accurate,
+** iteration of the X-th loop. If the query planner's estimate was accurate,
** then this value will approximate the quotient NVISIT/NLOOP and the
** product of this value for all prior loops with the same SELECTID will
-** be the NLOOP value for the current loop.
+** be the NLOOP value for the current loop.
**
** [[SQLITE_SCANSTAT_NAME]] - SQLITE_SCANSTAT_NAME
** - ^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the name of the index or table
-** used for the X-th loop.
+** used for the X-th loop.
**
** [[SQLITE_SCANSTAT_EXPLAIN]] - SQLITE_SCANSTAT_EXPLAIN
** - ^The "const char *" variable pointed to by the V parameter will be set
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
-** description for the X-th loop.
+** description for the X-th loop.
**
** [[SQLITE_SCANSTAT_SELECTID]] - SQLITE_SCANSTAT_SELECTID
** - ^The "int" variable pointed to by the V parameter will be set to the
** id for the X-th query plan element. The id value is unique within the
** statement. The select-id is the same value as is output in the first
-** column of an [EXPLAIN QUERY PLAN] query.
+** column of an [EXPLAIN QUERY PLAN] query.
**
** [[SQLITE_SCANSTAT_PARENTID]] - SQLITE_SCANSTAT_PARENTID
** - The "int" variable pointed to by the V parameter will be set to the
-** the id of the parent of the current query element, if applicable, or
+** id of the parent of the current query element, if applicable, or
** to zero if the query element has no parent. This is the same value as
-** returned in the second column of an [EXPLAIN QUERY PLAN] query.
+** returned in the second column of an [EXPLAIN QUERY PLAN] query.
**
** [[SQLITE_SCANSTAT_NCYCLE]] - SQLITE_SCANSTAT_NCYCLE
** - The sqlite3_int64 output value is set to the number of cycles,
** according to the processor time-stamp counter, that elapsed while the
** query element was being processed. This value is not available for
** all query elements - if it is unavailable the output variable is
-** set to -1.
+** set to -1.
**
*/
#define SQLITE_SCANSTAT_NLOOP 0
@@ -10737,8 +11052,8 @@ SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **
** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter.
**
** Parameter "idx" identifies the specific query element to retrieve statistics
-** for. Query elements are numbered starting from zero. A value of -1 may be
-** to query for statistics regarding the entire query. ^If idx is out of range
+** for. Query elements are numbered starting from zero. A value of -1 may
+** retrieve statistics for the entire query. ^If idx is out of range
** - less than -1 or greater than or equal to the total number of query
** elements used to implement the statement - a non-zero value is returned and
** the variable that pOut points to is unchanged.
@@ -10781,7 +11096,7 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
** METHOD: sqlite3
**
** ^If a write-transaction is open on [database connection] D when the
-** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
+** [sqlite3_db_cacheflush(D)] interface is invoked, any dirty
** pages in the pager-cache that are not currently in use are written out
** to disk. A dirty page may be in use if a database cursor created by an
** active SQL statement is reading from it, or if it is page 1 of a database
@@ -10895,8 +11210,8 @@ SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
** triggers; and so forth.
**
** When the [sqlite3_blob_write()] API is used to update a blob column,
-** the pre-update hook is invoked with SQLITE_DELETE. This is because the
-** in this case the new values are not available. In this case, when a
+** the pre-update hook is invoked with SQLITE_DELETE, because
+** the new values are not yet available. In this case, when a
** callback made with op==SQLITE_DELETE is actually a write using the
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
** the index of the column being written. In other cases, where the
@@ -10975,6 +11290,14 @@ typedef struct sqlite3_snapshot {
** If there is not already a read-transaction open on schema S when
** this function is called, one is opened automatically.
**
+** If a read-transaction is opened by this function, then it is guaranteed
+** that the returned snapshot object may not be invalidated by a database
+** writer or checkpointer until after the read-transaction is closed. This
+** is not guaranteed if a read-transaction is already open when this
+** function is called. In that case, any subsequent write or checkpoint
+** operation on the database may invalidate the returned snapshot handle,
+** even while the read-transaction remains open.
+**
** The following must be true for this function to succeed. If any of
** the following statements are false when sqlite3_snapshot_get() is
** called, SQLITE_ERROR is returned. The final value of *P is undefined
@@ -11006,7 +11329,7 @@ typedef struct sqlite3_snapshot {
** The [sqlite3_snapshot_get()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
+SQLITE_API int sqlite3_snapshot_get(
sqlite3 *db,
const char *zSchema,
sqlite3_snapshot **ppSnapshot
@@ -11055,7 +11378,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
** The [sqlite3_snapshot_open()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
+SQLITE_API int sqlite3_snapshot_open(
sqlite3 *db,
const char *zSchema,
sqlite3_snapshot *pSnapshot
@@ -11072,7 +11395,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
** The [sqlite3_snapshot_free()] interface is only available when the
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
*/
-SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
+SQLITE_API void sqlite3_snapshot_free(sqlite3_snapshot*);
/*
** CAPI3REF: Compare the ages of two snapshot handles.
@@ -11099,7 +11422,7 @@ SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
+SQLITE_API int sqlite3_snapshot_cmp(
sqlite3_snapshot *p1,
sqlite3_snapshot *p2
);
@@ -11127,20 +11450,21 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
** This interface is only available if SQLite is compiled with the
** [SQLITE_ENABLE_SNAPSHOT] option.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
+SQLITE_API int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
/*
** CAPI3REF: Serialize a database
**
-** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
-** that is a serialization of the S database on [database connection] D.
+** The sqlite3_serialize(D,S,P,F) interface returns a pointer to
+** memory that is a serialization of the S database on
+** [database connection] D. If S is a NULL pointer, the main database is used.
** If P is not a NULL pointer, then the size of the database in bytes
** is written into *P.
**
** For an ordinary on-disk database file, the serialization is just a
** copy of the disk file. For an in-memory database or a "TEMP" database,
** the serialization is the same sequence of bytes which would be written
-** to disk if that database where backed up to disk.
+** to disk if that database were backed up to disk.
**
** The usual case is that sqlite3_serialize() copies the serialization of
** the database into memory obtained from [sqlite3_malloc64()] and returns
@@ -11149,7 +11473,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const c
** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations
** are made, and the sqlite3_serialize() function will return a pointer
** to the contiguous memory representation of the database that SQLite
-** is currently using for that database, or NULL if the no such contiguous
+** is currently using for that database, or NULL if no such contiguous
** memory representation of the database exists. A contiguous memory
** representation of the database will usually only exist if there has
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
@@ -11200,12 +11524,13 @@ SQLITE_API unsigned char *sqlite3_serialize(
**
** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
** [database connection] D to disconnect from database S and then
-** reopen S as an in-memory database based on the serialization contained
-** in P. The serialized database P is N bytes in size. M is the size of
-** the buffer P, which might be larger than N. If M is larger than N, and
-** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
-** permitted to add content to the in-memory database as long as the total
-** size does not exceed M bytes.
+** reopen S as an in-memory database based on the serialization
+** contained in P. If S is a NULL pointer, the main database is
+** used. The serialized database P is N bytes in size. M is the size
+** of the buffer P, which might be larger than N. If M is larger than
+** N, and the SQLITE_DESERIALIZE_READONLY bit is not set in F, then
+** SQLite is permitted to add content to the in-memory database as
+** long as the total size does not exceed M bytes.
**
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
** invoke sqlite3_free() on the serialization buffer when the database
@@ -11220,7 +11545,7 @@ SQLITE_API unsigned char *sqlite3_serialize(
** database is currently in a read transaction or is involved in a backup
** operation.
**
-** It is not possible to deserialized into the TEMP database. If the
+** It is not possible to deserialize into the TEMP database. If the
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
** function returns SQLITE_ERROR.
**
@@ -11242,7 +11567,7 @@ SQLITE_API int sqlite3_deserialize(
sqlite3 *db, /* The database connection */
const char *zSchema, /* Which DB to reopen with the deserialization */
unsigned char *pData, /* The serialized database content */
- sqlite3_int64 szDb, /* Number bytes in the deserialization */
+ sqlite3_int64 szDb, /* Number of bytes in the deserialization */
sqlite3_int64 szBuf, /* Total size of buffer pData[] */
unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
);
@@ -11250,7 +11575,7 @@ SQLITE_API int sqlite3_deserialize(
/*
** CAPI3REF: Flags for sqlite3_deserialize()
**
-** The following are allowed values for 6th argument (the F argument) to
+** The following are allowed values for the 6th argument (the F argument) to
** the [sqlite3_deserialize(D,S,P,N,M,F)] interface.
**
** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization
@@ -11272,6 +11597,54 @@ SQLITE_API int sqlite3_deserialize(
#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */
#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
+/*
+** CAPI3REF: Bind array values to the CARRAY table-valued function
+**
+** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to
+** one of the first argument of the [carray() table-valued function]. The
+** S parameter is a pointer to the [prepared statement] that uses the carray()
+** functions. I is the parameter index to be bound. P is a pointer to the
+** array to be bound, and N is the number of eements in the array. The
+** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64],
+** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to
+** indicate the datatype of the array being bound. The X argument is not a
+** NULL pointer, then SQLite will invoke the function X on the P parameter
+** after it has finished using P, even if the call to
+** sqlite3_carray_bind() fails. The special-case finalizer
+** SQLITE_TRANSIENT has no effect here.
+*/
+SQLITE_API int sqlite3_carray_bind(
+ sqlite3_stmt *pStmt, /* Statement to be bound */
+ int i, /* Parameter index */
+ void *aData, /* Pointer to array data */
+ int nData, /* Number of data elements */
+ int mFlags, /* CARRAY flags */
+ void (*xDel)(void*) /* Destructor for aData */
+);
+
+/*
+** CAPI3REF: Datatypes for the CARRAY table-valued function
+**
+** The fifth argument to the [sqlite3_carray_bind()] interface musts be
+** one of the following constants, to specify the datatype of the array
+** that is being bound into the [carray table-valued function].
+*/
+#define SQLITE_CARRAY_INT32 0 /* Data is 32-bit signed integers */
+#define SQLITE_CARRAY_INT64 1 /* Data is 64-bit signed integers */
+#define SQLITE_CARRAY_DOUBLE 2 /* Data is doubles */
+#define SQLITE_CARRAY_TEXT 3 /* Data is char* */
+#define SQLITE_CARRAY_BLOB 4 /* Data is struct iovec */
+
+/*
+** Versions of the above #defines that omit the initial SQLITE_, for
+** legacy compatibility.
+*/
+#define CARRAY_INT32 0 /* Data is 32-bit signed integers */
+#define CARRAY_INT64 1 /* Data is 64-bit signed integers */
+#define CARRAY_DOUBLE 2 /* Data is doubles */
+#define CARRAY_TEXT 3 /* Data is char* */
+#define CARRAY_BLOB 4 /* Data is struct iovec */
+
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
@@ -11283,8 +11656,6 @@ SQLITE_API int sqlite3_deserialize(
#if defined(__wasi__)
# undef SQLITE_WASI
# define SQLITE_WASI 1
-# undef SQLITE_OMIT_WAL
-# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
# ifndef SQLITE_OMIT_LOAD_EXTENSION
# define SQLITE_OMIT_LOAD_EXTENSION
# endif
@@ -11296,19 +11667,7 @@ SQLITE_API int sqlite3_deserialize(
#if 0
} /* End of the 'extern "C"' block */
#endif
-#endif /* SQLITE3_H */
-
-/* Function prototypes of SQLite3 Multiple Ciphers */
-SQLITE_PRIVATE int sqlite3mcCheckVfs(const char*);
-SQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3*, const char*, int, void*);
-SQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**);
-SQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3*, const char*);
-typedef struct PgHdr PgHdrMC;
-SQLITE_PRIVATE void* sqlite3mcPagerCodec(PgHdrMC* pPg);
-typedef struct Pager PagerMC;
-SQLITE_PRIVATE int sqlite3mcPagerHasCodec(PagerMC* pPager);
-SQLITE_PRIVATE void sqlite3mcInitMemoryMethods();
-SQLITE_PRIVATE int sqlite3mcIsBackupSupported(sqlite3*, const char*, sqlite3*, const char*);
+/* #endif for SQLITE3_H will be added by mksqlite3.tcl */
/******** Begin file sqlite3rtree.h *********/
/*
@@ -11789,9 +12148,10 @@ SQLITE_API void sqlite3session_table_filter(
** is inserted while a session object is enabled, then later deleted while
** the same session object is disabled, no INSERT record will appear in the
** changeset, even though the delete took place while the session was disabled.
-** Or, if one field of a row is updated while a session is disabled, and
-** another field of the same row is updated while the session is enabled, the
-** resulting changeset will contain an UPDATE change that updates both fields.
+** Or, if one field of a row is updated while a session is enabled, and
+** then another field of the same row is updated while the session is disabled,
+** the resulting changeset will contain an UPDATE change that updates both
+** fields.
*/
SQLITE_API int sqlite3session_changeset(
sqlite3_session *pSession, /* Session object */
@@ -11863,8 +12223,9 @@ SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession
** database zFrom the contents of the two compatible tables would be
** identical.
**
-** It an error if database zFrom does not exist or does not contain the
-** required compatible table.
+** Unless the call to this function is a no-op as described above, it is an
+** error if database zFrom does not exist or does not contain the required
+** compatible table.
**
** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
@@ -11999,7 +12360,7 @@ SQLITE_API int sqlite3changeset_start_v2(
** The following flags may passed via the 4th parameter to
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
**
-** - SQLITE_CHANGESETAPPLY_INVERT
-
+**
- SQLITE_CHANGESETSTART_INVERT
-
** Invert the changeset while iterating through it. This is equivalent to
** inverting a changeset using sqlite3changeset_invert() before applying it.
** It is an error to specify this flag with a patchset.
@@ -12314,19 +12675,6 @@ SQLITE_API int sqlite3changeset_concat(
void **ppOut /* OUT: Buffer containing output changeset */
);
-
-/*
-** CAPI3REF: Upgrade the Schema of a Changeset/Patchset
-*/
-SQLITE_API int sqlite3changeset_upgrade(
- sqlite3 *db,
- const char *zDb,
- int nIn, const void *pIn, /* Input changeset */
- int *pnOut, void **ppOut /* OUT: Inverse of input */
-);
-
-
-
/*
** CAPI3REF: Changegroup Handle
**
@@ -12556,14 +12904,32 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** update the "main" database attached to handle db with the changes found in
** the changeset passed via the second and third arguments.
**
+** All changes made by these functions are enclosed in a savepoint transaction.
+** If any other error (aside from a constraint failure when attempting to
+** write to the target database) occurs, then the savepoint transaction is
+** rolled back, restoring the target database to its original state, and an
+** SQLite error code returned. Additionally, starting with version 3.51.0,
+** an error code and error message that may be accessed using the
+** [sqlite3_errcode()] and [sqlite3_errmsg()] APIs are left in the database
+** handle.
+**
** The fourth argument (xFilter) passed to these functions is the "filter
-** callback". If it is not NULL, then for each table affected by at least one
-** change in the changeset, the filter callback is invoked with
-** the table name as the second argument, and a copy of the context pointer
-** passed as the sixth argument as the first. If the "filter callback"
-** returns zero, then no attempt is made to apply any changes to the table.
-** Otherwise, if the return value is non-zero or the xFilter argument to
-** is NULL, all changes related to the table are attempted.
+** callback". This may be passed NULL, in which case all changes in the
+** changeset are applied to the database. For sqlite3changeset_apply() and
+** sqlite3_changeset_apply_v2(), if it is not NULL, then it is invoked once
+** for each table affected by at least one change in the changeset. In this
+** case the table name is passed as the second argument, and a copy of
+** the context pointer passed as the sixth argument to apply() or apply_v2()
+** as the first. If the "filter callback" returns zero, then no attempt is
+** made to apply any changes to the table. Otherwise, if the return value is
+** non-zero, all changes related to the table are attempted.
+**
+** For sqlite3_changeset_apply_v3(), the xFilter callback is invoked once
+** per change. The second argument in this case is an sqlite3_changeset_iter
+** that may be queried using the usual APIs for the details of the current
+** change. If the "filter callback" returns zero in this case, then no attempt
+** is made to apply the current change. If it returns non-zero, the change
+** is applied.
**
** For each table that is not excluded by the filter callback, this function
** tests that the target database contains a compatible table. A table is
@@ -12584,11 +12950,11 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** one such warning is issued for each table in the changeset.
**
** For each change for which there is a compatible table, an attempt is made
-** to modify the table contents according to the UPDATE, INSERT or DELETE
-** change. If a change cannot be applied cleanly, the conflict handler
-** function passed as the fifth argument to sqlite3changeset_apply() may be
-** invoked. A description of exactly when the conflict handler is invoked for
-** each type of change is below.
+** to modify the table contents according to each UPDATE, INSERT or DELETE
+** change that is not excluded by a filter callback. If a change cannot be
+** applied cleanly, the conflict handler function passed as the fifth argument
+** to sqlite3changeset_apply() may be invoked. A description of exactly when
+** the conflict handler is invoked for each type of change is below.
**
** Unlike the xFilter argument, xConflict may not be passed NULL. The results
** of passing anything other than a valid function pointer as the xConflict
@@ -12684,12 +13050,6 @@ SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
** This can be used to further customize the application's conflict
** resolution strategy.
**
-** All changes made by these functions are enclosed in a savepoint transaction.
-** If any other error (aside from a constraint failure when attempting to
-** write to the target database) occurs, then the savepoint transaction is
-** rolled back, restoring the target database to its original state, and an
-** SQLite error code returned.
-**
** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
** may set (*ppRebase) to point to a "rebase" that may be used with the
@@ -12739,6 +13099,23 @@ SQLITE_API int sqlite3changeset_apply_v2(
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
int flags /* SESSION_CHANGESETAPPLY_* flags */
);
+SQLITE_API int sqlite3changeset_apply_v3(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int nChangeset, /* Size of changeset in bytes */
+ void *pChangeset, /* Changeset blob */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ sqlite3_changeset_iter *p /* Handle describing change */
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase, /* OUT: Rebase data */
+ int flags /* SESSION_CHANGESETAPPLY_* flags */
+);
/*
** CAPI3REF: Flags for sqlite3changeset_apply_v2
@@ -13158,6 +13535,23 @@ SQLITE_API int sqlite3changeset_apply_v2_strm(
void **ppRebase, int *pnRebase,
int flags
);
+SQLITE_API int sqlite3changeset_apply_v3_strm(
+ sqlite3 *db, /* Apply change to "main" db of this handle */
+ int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
+ void *pIn, /* First arg for xInput */
+ int(*xFilter)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ sqlite3_changeset_iter *p
+ ),
+ int(*xConflict)(
+ void *pCtx, /* Copy of sixth arg to _apply() */
+ int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
+ sqlite3_changeset_iter *p /* Handle describing change and conflict */
+ ),
+ void *pCtx, /* First argument passed to xConflict */
+ void **ppRebase, int *pnRebase,
+ int flags
+);
SQLITE_API int sqlite3changeset_concat_strm(
int (*xInputA)(void *pIn, void *pData, int *pnData),
void *pInA,
@@ -13499,6 +13893,10 @@ struct Fts5PhraseIter {
** (i.e. if it is a contentless table), then this API always iterates
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
**
+** In all cases, matches are visited in (column ASC, offset ASC) order.
+** i.e. all those in column 0, sorted by offset, followed by those in
+** column 1, etc.
+**
** xPhraseNext()
** See xPhraseFirst above.
**
@@ -13555,19 +13953,57 @@ struct Fts5PhraseIter {
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
** output variable (*ppToken) is set to point to a buffer containing the
** matching document token, and (*pnToken) to the size of that buffer in
-** bytes. This API is not available if the specified token matches a
-** prefix query term. In that case both output variables are always set
-** to 0.
+** bytes.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
+** This API may be slow in some cases if the token identified by parameters
+** iIdx and iToken matched a prefix token in the query. In most cases, the
+** first call to this API for each prefix token in the query is forced
+** to scan the portion of the full-text index that matches the prefix
+** token to collect the extra data required by this API. If the prefix
+** token matches a large number of token instances in the document set,
+** this may be a performance problem.
+**
+** If the user knows in advance that a query may use this API for a
+** prefix token, FTS5 may be configured to collect all required data as part
+** of the initial querying of the full-text index, avoiding the second scan
+** entirely. This also causes prefix queries that do not use this API to
+** run more slowly and use more memory. FTS5 may be configured in this way
+** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
+** option, or on a per-query basis using the
+** [fts5_insttoken | fts5_insttoken()] user function.
+**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
+**
+** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
+** If parameter iCol is less than zero, or greater than or equal to the
+** number of columns in the table, SQLITE_RANGE is returned.
+**
+** Otherwise, this function attempts to retrieve the locale associated
+** with column iCol of the current row. Usually, there is no associated
+** locale, and output parameters (*pzLocale) and (*pnLocale) are set
+** to NULL and 0, respectively. However, if the fts5_locale() function
+** was used to associate a locale with the value when it was inserted
+** into the fts5 table, then (*pzLocale) is set to point to a nul-terminated
+** buffer containing the name of the locale in utf-8 encoding. (*pnLocale)
+** is set to the size in bytes of the buffer, not including the
+** nul-terminator.
+**
+** If successful, SQLITE_OK is returned. Or, if an error occurs, an
+** SQLite error code is returned. The final value of the output parameters
+** is undefined in this case.
+**
+** xTokenize_v2:
+** Tokenize text using the tokenizer belonging to the FTS5 table. This
+** API is the same as the xTokenize() API, except that it allows a tokenizer
+** locale to be specified.
*/
struct Fts5ExtensionApi {
- int iVersion; /* Currently always set to 3 */
+ int iVersion; /* Currently always set to 4 */
void *(*xUserData)(Fts5Context*);
@@ -13609,6 +14045,15 @@ struct Fts5ExtensionApi {
const char **ppToken, int *pnToken
);
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
+
+ /* Below this point are iVersion>=4 only */
+ int (*xColumnLocale)(Fts5Context*, int iCol, const char **pz, int *pn);
+ int (*xTokenize_v2)(Fts5Context*,
+ const char *pText, int nText, /* Text to tokenize */
+ const char *pLocale, int nLocale, /* Locale to pass to tokenizer */
+ void *pCtx, /* Context passed to xToken() */
+ int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
+ );
};
/*
@@ -13629,7 +14074,7 @@ struct Fts5ExtensionApi {
** A tokenizer instance is required to actually tokenize text.
**
** The first argument passed to this function is a copy of the (void*)
-** pointer provided by the application when the fts5_tokenizer object
+** pointer provided by the application when the fts5_tokenizer_v2 object
** was registered with FTS5 (the third argument to xCreateTokenizer()).
** The second and third arguments are an array of nul-terminated strings
** containing the tokenizer arguments, if any, specified following the
@@ -13653,7 +14098,7 @@ struct Fts5ExtensionApi {
** argument passed to this function is a pointer to an Fts5Tokenizer object
** returned by an earlier call to xCreate().
**
-** The second argument indicates the reason that FTS5 is requesting
+** The third argument indicates the reason that FTS5 is requesting
** tokenization of the supplied text. This is always one of the following
** four values:
**
@@ -13677,6 +14122,13 @@ struct Fts5ExtensionApi {
** on a columnsize=0 database.
**
**
+** The sixth and seventh arguments passed to xTokenize() - pLocale and
+** nLocale - are a pointer to a buffer containing the locale to use for
+** tokenization (e.g. "en_US") and its size in bytes, respectively. The
+** pLocale buffer is not nul-terminated. pLocale may be passed NULL (in
+** which case nLocale is always 0) to indicate that the tokenizer should
+** use its default locale.
+**
** For each token in the input string, the supplied callback xToken() must
** be invoked. The first argument to it should be a copy of the pointer
** passed as the second argument to xTokenize(). The third and fourth
@@ -13700,6 +14152,30 @@ struct Fts5ExtensionApi {
** may abandon the tokenization and return any error code other than
** SQLITE_OK or SQLITE_DONE.
**
+** If the tokenizer is registered using an fts5_tokenizer_v2 object,
+** then the xTokenize() method has two additional arguments - pLocale
+** and nLocale. These specify the locale that the tokenizer should use
+** for the current request. If pLocale and nLocale are both 0, then the
+** tokenizer should use its default locale. Otherwise, pLocale points to
+** an nLocale byte buffer containing the name of the locale to use as utf-8
+** text. pLocale is not nul-terminated.
+**
+** FTS5_TOKENIZER
+**
+** There is also an fts5_tokenizer object. This is an older, deprecated,
+** version of fts5_tokenizer_v2. It is similar except that:
+**
+**
+** - There is no "iVersion" field, and
+**
- The xTokenize() method does not take a locale argument.
+**
+**
+** Legacy fts5_tokenizer tokenizers must be registered using the
+** legacy xCreateTokenizer() function, instead of xCreateTokenizer_v2().
+**
+** Tokenizer implementations registered using either API may be retrieved
+** using both xFindTokenizer() and xFindTokenizer_v2().
+**
** SYNONYM SUPPORT
**
** Custom tokenizers may also support synonyms. Consider a case in which a
@@ -13808,6 +14284,33 @@ struct Fts5ExtensionApi {
** inefficient.
*/
typedef struct Fts5Tokenizer Fts5Tokenizer;
+typedef struct fts5_tokenizer_v2 fts5_tokenizer_v2;
+struct fts5_tokenizer_v2 {
+ int iVersion; /* Currently always 2 */
+
+ int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
+ void (*xDelete)(Fts5Tokenizer*);
+ int (*xTokenize)(Fts5Tokenizer*,
+ void *pCtx,
+ int flags, /* Mask of FTS5_TOKENIZE_* flags */
+ const char *pText, int nText,
+ const char *pLocale, int nLocale,
+ int (*xToken)(
+ void *pCtx, /* Copy of 2nd argument to xTokenize() */
+ int tflags, /* Mask of FTS5_TOKEN_* flags */
+ const char *pToken, /* Pointer to buffer containing token */
+ int nToken, /* Size of token in bytes */
+ int iStart, /* Byte offset of token within input text */
+ int iEnd /* Byte offset of end of token within input text */
+ )
+ );
+};
+
+/*
+** New code should use the fts5_tokenizer_v2 type to define tokenizer
+** implementations. The following type is included for legacy applications
+** that still use it.
+*/
typedef struct fts5_tokenizer fts5_tokenizer;
struct fts5_tokenizer {
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
@@ -13827,6 +14330,7 @@ struct fts5_tokenizer {
);
};
+
/* Flags that may be passed as the third argument to xTokenize() */
#define FTS5_TOKENIZE_QUERY 0x0001
#define FTS5_TOKENIZE_PREFIX 0x0002
@@ -13846,7 +14350,7 @@ struct fts5_tokenizer {
*/
typedef struct fts5_api fts5_api;
struct fts5_api {
- int iVersion; /* Currently always set to 2 */
+ int iVersion; /* Currently always set to 3 */
/* Create a new tokenizer */
int (*xCreateTokenizer)(
@@ -13873,6 +14377,25 @@ struct fts5_api {
fts5_extension_function xFunction,
void (*xDestroy)(void*)
);
+
+ /* APIs below this point are only available if iVersion>=3 */
+
+ /* Create a new tokenizer */
+ int (*xCreateTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void *pUserData,
+ fts5_tokenizer_v2 *pTokenizer,
+ void (*xDestroy)(void*)
+ );
+
+ /* Find an existing tokenizer */
+ int (*xFindTokenizer_v2)(
+ fts5_api *pApi,
+ const char *zName,
+ void **ppUserData,
+ fts5_tokenizer_v2 **ppTokenizer
+ );
};
/*
@@ -13886,6 +14409,21 @@ struct fts5_api {
#endif /* _FTS5_H */
/******** End of fts5.h *********/
+#endif /* SQLITE3_H */
+
+/* Function prototypes of SQLite3 Multiple Ciphers */
+SQLITE_PRIVATE int sqlite3mcCheckVfs(const char*);
+SQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3*, const char*, int, void*);
+SQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**);
+SQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3*, const char*);
+typedef struct PgHdr PgHdrMC;
+SQLITE_PRIVATE void* sqlite3mcPagerCodec(PgHdrMC* pPg);
+typedef struct Pager PagerMC;
+SQLITE_PRIVATE int sqlite3mcPagerHasCodec(PagerMC* pPager);
+SQLITE_PRIVATE void sqlite3mcInitMemoryMethods();
+SQLITE_PRIVATE int sqlite3mcIsBackupSupported(sqlite3*, const char*, sqlite3*, const char*);
+SQLITE_PRIVATE void sqlite3mcCodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey);
+SQLITE_PRIVATE int sqlite3mc_builtin_extensions(sqlite3* db);
/************** End of sqlite3.h *********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -13931,6 +14469,7 @@ struct fts5_api {
#ifndef SQLITE_MAX_LENGTH
# define SQLITE_MAX_LENGTH 1000000000
#endif
+#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
/*
** This is the maximum number of
@@ -13943,14 +14482,22 @@ struct fts5_api {
** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
** * Terms in the VALUES clause of an INSERT statement
**
-** The hard upper limit here is 32676. Most database people will
+** The hard upper limit here is 32767. Most database people will
** tell you that in a well-normalized database, you usually should
** not have more than a dozen or so columns in any table. And if
** that is the case, there is no point in having more than a few
** dozen values in any of the other situations described above.
+**
+** An index can only have SQLITE_MAX_COLUMN columns from the user
+** point of view, but the underlying b-tree that implements the index
+** might have up to twice as many columns in a WITHOUT ROWID table,
+** since must also store the primary key at the end. Hence the
+** column count for Index is u16 instead of i16.
*/
-#ifndef SQLITE_MAX_COLUMN
+#if !defined(SQLITE_MAX_COLUMN)
# define SQLITE_MAX_COLUMN 2000
+#elif SQLITE_MAX_COLUMN>32767
+# error SQLITE_MAX_COLUMN may not exceed 32767
#endif
/*
@@ -13996,9 +14543,13 @@ struct fts5_api {
/*
** The maximum number of arguments to an SQL function.
+**
+** This value has a hard upper limit of 32767 due to storage
+** constraints (it needs to fit inside a i16). We keep it
+** lower than that to prevent abuse.
*/
#ifndef SQLITE_MAX_FUNCTION_ARG
-# define SQLITE_MAX_FUNCTION_ARG 127
+# define SQLITE_MAX_FUNCTION_ARG 1000
#endif
/*
@@ -14091,7 +14642,7 @@ struct fts5_api {
** 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
+** This value can be lowered (or raised) at run-time using the
** max_page_count macro.
*/
#ifndef SQLITE_MAX_PAGE_COUNT
@@ -14598,6 +15149,7 @@ struct HashElem {
HashElem *next, *prev; /* Next and previous elements in the table */
void *data; /* Data associated with this element */
const char *pKey; /* Key associated with this element */
+ unsigned int h; /* hash for pKey */
};
/*
@@ -14682,132 +15234,132 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_OR 43
#define TK_AND 44
#define TK_IS 45
-#define TK_MATCH 46
-#define TK_LIKE_KW 47
-#define TK_BETWEEN 48
-#define TK_IN 49
-#define TK_ISNULL 50
-#define TK_NOTNULL 51
-#define TK_NE 52
-#define TK_EQ 53
-#define TK_GT 54
-#define TK_LE 55
-#define TK_LT 56
-#define TK_GE 57
-#define TK_ESCAPE 58
-#define TK_ID 59
-#define TK_COLUMNKW 60
-#define TK_DO 61
-#define TK_FOR 62
-#define TK_IGNORE 63
-#define TK_INITIALLY 64
-#define TK_INSTEAD 65
-#define TK_NO 66
-#define TK_KEY 67
-#define TK_OF 68
-#define TK_OFFSET 69
-#define TK_PRAGMA 70
-#define TK_RAISE 71
-#define TK_RECURSIVE 72
-#define TK_REPLACE 73
-#define TK_RESTRICT 74
-#define TK_ROW 75
-#define TK_ROWS 76
-#define TK_TRIGGER 77
-#define TK_VACUUM 78
-#define TK_VIEW 79
-#define TK_VIRTUAL 80
-#define TK_WITH 81
-#define TK_NULLS 82
-#define TK_FIRST 83
-#define TK_LAST 84
-#define TK_CURRENT 85
-#define TK_FOLLOWING 86
-#define TK_PARTITION 87
-#define TK_PRECEDING 88
-#define TK_RANGE 89
-#define TK_UNBOUNDED 90
-#define TK_EXCLUDE 91
-#define TK_GROUPS 92
-#define TK_OTHERS 93
-#define TK_TIES 94
-#define TK_GENERATED 95
-#define TK_ALWAYS 96
-#define TK_MATERIALIZED 97
-#define TK_REINDEX 98
-#define TK_RENAME 99
-#define TK_CTIME_KW 100
-#define TK_ANY 101
-#define TK_BITAND 102
-#define TK_BITOR 103
-#define TK_LSHIFT 104
-#define TK_RSHIFT 105
-#define TK_PLUS 106
-#define TK_MINUS 107
-#define TK_STAR 108
-#define TK_SLASH 109
-#define TK_REM 110
-#define TK_CONCAT 111
-#define TK_PTR 112
-#define TK_COLLATE 113
-#define TK_BITNOT 114
-#define TK_ON 115
-#define TK_INDEXED 116
-#define TK_STRING 117
-#define TK_JOIN_KW 118
-#define TK_CONSTRAINT 119
-#define TK_DEFAULT 120
-#define TK_NULL 121
-#define TK_PRIMARY 122
-#define TK_UNIQUE 123
-#define TK_CHECK 124
-#define TK_REFERENCES 125
-#define TK_AUTOINCR 126
-#define TK_INSERT 127
-#define TK_DELETE 128
-#define TK_UPDATE 129
-#define TK_SET 130
-#define TK_DEFERRABLE 131
-#define TK_FOREIGN 132
-#define TK_DROP 133
-#define TK_UNION 134
-#define TK_ALL 135
-#define TK_EXCEPT 136
-#define TK_INTERSECT 137
-#define TK_SELECT 138
-#define TK_VALUES 139
-#define TK_DISTINCT 140
-#define TK_DOT 141
-#define TK_FROM 142
-#define TK_JOIN 143
-#define TK_USING 144
-#define TK_ORDER 145
-#define TK_GROUP 146
-#define TK_HAVING 147
-#define TK_LIMIT 148
-#define TK_WHERE 149
-#define TK_RETURNING 150
-#define TK_INTO 151
-#define TK_NOTHING 152
-#define TK_FLOAT 153
-#define TK_BLOB 154
-#define TK_INTEGER 155
-#define TK_VARIABLE 156
-#define TK_CASE 157
-#define TK_WHEN 158
-#define TK_THEN 159
-#define TK_ELSE 160
-#define TK_INDEX 161
-#define TK_ALTER 162
-#define TK_ADD 163
-#define TK_WINDOW 164
-#define TK_OVER 165
-#define TK_FILTER 166
-#define TK_COLUMN 167
-#define TK_AGG_FUNCTION 168
-#define TK_AGG_COLUMN 169
-#define TK_TRUEFALSE 170
-#define TK_ISNOT 171
+#define TK_ISNOT 46
+#define TK_MATCH 47
+#define TK_LIKE_KW 48
+#define TK_BETWEEN 49
+#define TK_IN 50
+#define TK_ISNULL 51
+#define TK_NOTNULL 52
+#define TK_NE 53
+#define TK_EQ 54
+#define TK_GT 55
+#define TK_LE 56
+#define TK_LT 57
+#define TK_GE 58
+#define TK_ESCAPE 59
+#define TK_ID 60
+#define TK_COLUMNKW 61
+#define TK_DO 62
+#define TK_FOR 63
+#define TK_IGNORE 64
+#define TK_INITIALLY 65
+#define TK_INSTEAD 66
+#define TK_NO 67
+#define TK_KEY 68
+#define TK_OF 69
+#define TK_OFFSET 70
+#define TK_PRAGMA 71
+#define TK_RAISE 72
+#define TK_RECURSIVE 73
+#define TK_REPLACE 74
+#define TK_RESTRICT 75
+#define TK_ROW 76
+#define TK_ROWS 77
+#define TK_TRIGGER 78
+#define TK_VACUUM 79
+#define TK_VIEW 80
+#define TK_VIRTUAL 81
+#define TK_WITH 82
+#define TK_NULLS 83
+#define TK_FIRST 84
+#define TK_LAST 85
+#define TK_CURRENT 86
+#define TK_FOLLOWING 87
+#define TK_PARTITION 88
+#define TK_PRECEDING 89
+#define TK_RANGE 90
+#define TK_UNBOUNDED 91
+#define TK_EXCLUDE 92
+#define TK_GROUPS 93
+#define TK_OTHERS 94
+#define TK_TIES 95
+#define TK_GENERATED 96
+#define TK_ALWAYS 97
+#define TK_MATERIALIZED 98
+#define TK_REINDEX 99
+#define TK_RENAME 100
+#define TK_CTIME_KW 101
+#define TK_ANY 102
+#define TK_BITAND 103
+#define TK_BITOR 104
+#define TK_LSHIFT 105
+#define TK_RSHIFT 106
+#define TK_PLUS 107
+#define TK_MINUS 108
+#define TK_STAR 109
+#define TK_SLASH 110
+#define TK_REM 111
+#define TK_CONCAT 112
+#define TK_PTR 113
+#define TK_COLLATE 114
+#define TK_BITNOT 115
+#define TK_ON 116
+#define TK_INDEXED 117
+#define TK_STRING 118
+#define TK_JOIN_KW 119
+#define TK_CONSTRAINT 120
+#define TK_DEFAULT 121
+#define TK_NULL 122
+#define TK_PRIMARY 123
+#define TK_UNIQUE 124
+#define TK_CHECK 125
+#define TK_REFERENCES 126
+#define TK_AUTOINCR 127
+#define TK_INSERT 128
+#define TK_DELETE 129
+#define TK_UPDATE 130
+#define TK_SET 131
+#define TK_DEFERRABLE 132
+#define TK_FOREIGN 133
+#define TK_DROP 134
+#define TK_UNION 135
+#define TK_ALL 136
+#define TK_EXCEPT 137
+#define TK_INTERSECT 138
+#define TK_SELECT 139
+#define TK_VALUES 140
+#define TK_DISTINCT 141
+#define TK_DOT 142
+#define TK_FROM 143
+#define TK_JOIN 144
+#define TK_USING 145
+#define TK_ORDER 146
+#define TK_GROUP 147
+#define TK_HAVING 148
+#define TK_LIMIT 149
+#define TK_WHERE 150
+#define TK_RETURNING 151
+#define TK_INTO 152
+#define TK_NOTHING 153
+#define TK_FLOAT 154
+#define TK_BLOB 155
+#define TK_INTEGER 156
+#define TK_VARIABLE 157
+#define TK_CASE 158
+#define TK_WHEN 159
+#define TK_THEN 160
+#define TK_ELSE 161
+#define TK_INDEX 162
+#define TK_ALTER 163
+#define TK_ADD 164
+#define TK_WINDOW 165
+#define TK_OVER 166
+#define TK_FILTER 167
+#define TK_COLUMN 168
+#define TK_AGG_FUNCTION 169
+#define TK_AGG_COLUMN 170
+#define TK_TRUEFALSE 171
#define TK_FUNCTION 172
#define TK_UPLUS 173
#define TK_UMINUS 174
@@ -14821,7 +15373,8 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_ERROR 182
#define TK_QNUMBER 183
#define TK_SPACE 184
-#define TK_ILLEGAL 185
+#define TK_COMMENT 185
+#define TK_ILLEGAL 186
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -14830,6 +15383,7 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#include
#include
#include
+#include
/*
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
@@ -14850,7 +15404,8 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64
# define float sqlite_int64
-# define LONGDOUBLE_TYPE sqlite_int64
+# define fabs(X) ((X)<0?-(X):(X))
+# define sqlite3IsOverflow(X) 0
# ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
# endif
@@ -14955,7 +15510,17 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
** ourselves.
*/
#ifndef offsetof
-#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
+# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
+#endif
+
+/*
+** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
+** to avoid complaints from -fsanitize=strict-bounds.
+*/
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
#endif
/*
@@ -15025,9 +15590,6 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
# define INT8_TYPE signed char
# endif
#endif
-#ifndef LONGDOUBLE_TYPE
-# define LONGDOUBLE_TYPE long double
-#endif
typedef sqlite_int64 i64; /* 8-byte signed integer */
typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
@@ -15036,6 +15598,11 @@ typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef INT8_TYPE i8; /* 1-byte signed integer */
+/* A bitfield type for use inside of structures. Always follow with :N where
+** N is the number of bits.
+*/
+typedef unsigned bft; /* Bit Field Type */
+
/*
** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
** that can be stored in a u32 without loss of data. The value
@@ -15074,6 +15641,8 @@ typedef u64 tRowcnt;
** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
*/
typedef INT16_TYPE LogEst;
+#define LOGEST_MIN (-32768)
+#define LOGEST_MAX (32767)
/*
** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
@@ -15202,6 +15771,14 @@ typedef INT16_TYPE LogEst;
#define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
+/*
+** Macro SMXV(n) return the maximum value that can be held in variable n,
+** assuming n is a signed integer type. UMXV(n) is similar for unsigned
+** integer types.
+*/
+#define SMXV(n) ((((i64)1)<<(sizeof(n)*8-1))-1)
+#define UMXV(n) ((((i64)1)<<(sizeof(n)*8))-1)
+
/*
** Round up a number to the next larger multiple of 8. This is used
** to force 8-byte alignment on 64-bit architectures.
@@ -15321,6 +15898,8 @@ SQLITE_PRIVATE u32 sqlite3TreeTrace;
** 0x00020000 Transform DISTINCT into GROUP BY
** 0x00040000 SELECT tree dump after all code has been generated
** 0x00080000 NOT NULL strength reduction
+** 0x00100000 Pointers are all shown as zero
+** 0x00200000 EXISTS-to-JOIN optimization
*/
/*
@@ -15344,7 +15923,7 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace;
** 0xFFFF---- Low-level debug messages
**
** 0x00000001 Code generation
-** 0x00000002 Solver
+** 0x00000002 Solver (Use 0x40000 for less detail)
** 0x00000004 Solver costs
** 0x00000008 WhereLoop inserts
**
@@ -15363,6 +15942,9 @@ SQLITE_PRIVATE u32 sqlite3WhereTrace;
**
** 0x00010000 Show more detail when printing WHERE terms
** 0x00020000 Show WHERE terms returned from whereScanNext()
+** 0x00040000 Solver overview messages
+** 0x00080000 Star-query heuristic
+** 0x00100000 Pointers are all shown as zero
*/
@@ -15435,7 +16017,7 @@ struct BusyHandler {
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
-#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomClear)
+#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3RowSetClear)
/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
@@ -15527,6 +16109,7 @@ typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
+typedef struct Subquery Subquery;
typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
@@ -15655,8 +16238,8 @@ typedef int VList;
** must provide its own VFS implementation together with sqlite3_os_init()
** and sqlite3_os_end() routines.
*/
-#if !defined(SQLITE_OS_KV) && !defined(SQLITE_OS_OTHER) && \
- !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_WIN)
+#if SQLITE_OS_KV+1<=1 && SQLITE_OS_OTHER+1<=1 && \
+ SQLITE_OS_WIN+1<=1 && SQLITE_OS_UNIX+1<=1
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
defined(__MINGW32__) || defined(__BORLANDC__)
# define SQLITE_OS_WIN 1
@@ -16000,6 +16583,22 @@ typedef struct PgHdr DbPage;
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
+#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL)
+
+/*
+** The argument to this macro is a file descriptor (type sqlite3_file*).
+** Return 0 if it is not open, or non-zero (but not 1) if it is.
+**
+** This is so that expressions can be written as:
+**
+** if( isOpen(pPager->jfd) ){ ...
+**
+** instead of
+**
+** if( pPager->jfd->pMethods ){ ...
+*/
+#define isOpen(pFd) ((pFd)->pMethods!=0)
+
/*
** Flags that make up the mask passed to sqlite3PagerGet().
*/
@@ -16409,6 +17008,9 @@ SQLITE_PRIVATE int sqlite3BtreeCursor(
);
SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(Btree*,BtCursor*);
+#endif
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
@@ -16483,6 +17085,7 @@ struct BtreePayload {
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
int flags, int seekResult);
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
+SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags);
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
@@ -16627,6 +17230,20 @@ typedef struct Vdbe Vdbe;
*/
typedef struct sqlite3_value Mem;
typedef struct SubProgram SubProgram;
+typedef struct SubrtnSig SubrtnSig;
+
+/*
+** A signature for a reusable subroutine that materializes the RHS of
+** an IN operator.
+*/
+struct SubrtnSig {
+ int selId; /* SELECT-id for the SELECT statement on the RHS */
+ u8 bComplete; /* True if fully coded and available for reusable */
+ char *zAff; /* Affinity of the overall IN expression */
+ int iTable; /* Ephemeral table generated by the subroutine */
+ int iAddr; /* Subroutine entry address */
+ int regReturn; /* Register used to hold return address */
+};
/*
** A single instruction of the virtual machine has an opcode
@@ -16655,6 +17272,7 @@ struct VdbeOp {
u32 *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
Table *pTab; /* Used when p4type is P4_TABLE */
+ SubrtnSig *pSubrtnSig; /* Used when p4type is P4_SUBRTNSIG */
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
@@ -16722,6 +17340,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
+#define P4_SUBRTNSIG (-17) /* P4 is a SubrtnSig pointer */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -16800,159 +17419,160 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_SorterSort 34 /* jump */
#define OP_Sort 35 /* jump */
#define OP_Rewind 36 /* jump0 */
-#define OP_SorterNext 37 /* jump */
-#define OP_Prev 38 /* jump */
-#define OP_Next 39 /* jump */
-#define OP_IdxLE 40 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGT 41 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxLT 42 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IfEmpty 37 /* jump, synopsis: if( empty(P1) ) goto P2 */
+#define OP_SorterNext 38 /* jump */
+#define OP_Prev 39 /* jump */
+#define OP_Next 40 /* jump */
+#define OP_IdxLE 41 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGT 42 /* jump, synopsis: key=r[P3@P4] */
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */
-#define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */
-#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
-#define OP_Program 48 /* jump0 */
-#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
-#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
-#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
-#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
-#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
-#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
-#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */
-#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
-#define OP_IfPos 59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
-#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
-#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */
-#define OP_IncrVacuum 62 /* jump */
-#define OP_VNext 63 /* jump */
-#define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
-#define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */
-#define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */
-#define OP_Return 67
-#define OP_EndCoroutine 68
-#define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */
-#define OP_Halt 70
-#define OP_Integer 71 /* synopsis: r[P2]=P1 */
-#define OP_Int64 72 /* synopsis: r[P2]=P4 */
-#define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */
-#define OP_BeginSubrtn 74 /* synopsis: r[P2]=NULL */
-#define OP_Null 75 /* synopsis: r[P2..P3]=NULL */
-#define OP_SoftNull 76 /* synopsis: r[P1]=NULL */
-#define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1) */
-#define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
-#define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */
-#define OP_IntCopy 82 /* synopsis: r[P2]=r[P1] */
-#define OP_FkCheck 83
-#define OP_ResultRow 84 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 85
-#define OP_AddImm 86 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_RealAffinity 87
-#define OP_Cast 88 /* synopsis: affinity(r[P1]) */
-#define OP_Permutation 89
-#define OP_Compare 90 /* synopsis: r[P1@P3] <-> r[P2@P3] */
-#define OP_IsTrue 91 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
-#define OP_ZeroOrNull 92 /* synopsis: r[P2] = 0 OR NULL */
-#define OP_Offset 93 /* synopsis: r[P3] = sqlite_offset(P1) */
-#define OP_Column 94 /* synopsis: r[P3]=PX cursor P1 column P2 */
-#define OP_TypeCheck 95 /* synopsis: typecheck(r[P1@P2]) */
-#define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */
-#define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_Count 98 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 99
-#define OP_SetCookie 100
-#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
-#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
-#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
-#define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-#define OP_OpenDup 115
-#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
-#define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */
-#define OP_SorterOpen 119
-#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
-#define OP_Close 122
-#define OP_ColumnsUsed 123
-#define OP_SeekScan 124 /* synopsis: Scan-ahead up to P1 rows */
-#define OP_SeekHit 125 /* synopsis: set P2<=seekHit<=P3 */
-#define OP_Sequence 126 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 127 /* synopsis: r[P2]=rowid */
-#define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_RowCell 129
-#define OP_Delete 130
-#define OP_ResetCount 131
-#define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 133 /* synopsis: r[P2]=data */
-#define OP_RowData 134 /* synopsis: r[P2]=data */
-#define OP_Rowid 135 /* synopsis: r[P2]=PX rowid of P1 */
-#define OP_NullRow 136
-#define OP_SeekEnd 137
-#define OP_IdxInsert 138 /* synopsis: key=r[P2] */
-#define OP_SorterInsert 139 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 140 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 141 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 142 /* synopsis: r[P2]=rowid */
-#define OP_FinishSeek 143
-#define OP_Destroy 144
-#define OP_Clear 145
-#define OP_ResetSorter 146
-#define OP_CreateBtree 147 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
-#define OP_SqlExec 148
-#define OP_ParseSchema 149
-#define OP_LoadAnalysis 150
-#define OP_DropTable 151
-#define OP_DropIndex 152
-#define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_DropTrigger 154
-#define OP_IntegrityCk 155
-#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 157
-#define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 160 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggInverse 161 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
-#define OP_AggStep 162 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep1 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggValue 164 /* synopsis: r[P3]=value N=P2 */
-#define OP_AggFinal 165 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 166
-#define OP_CursorLock 167
-#define OP_CursorUnlock 168
-#define OP_TableLock 169 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 170
-#define OP_VCreate 171
-#define OP_VDestroy 172
-#define OP_VOpen 173
-#define OP_VCheck 174
-#define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */
-#define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 177
-#define OP_Pagecount 178
-#define OP_MaxPgcnt 179
-#define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */
-#define OP_GetSubtype 181 /* synopsis: r[P2] = r[P1].subtype */
-#define OP_SetSubtype 182 /* synopsis: r[P2].subtype = r[P1] */
-#define OP_FilterAdd 183 /* synopsis: filter(P1) += key(P3@P4) */
-#define OP_Trace 184
-#define OP_CursorHint 185
-#define OP_ReleaseReg 186 /* synopsis: release r[P1@P2] mask P3 */
-#define OP_Noop 187
-#define OP_Explain 188
-#define OP_Abortable 189
+#define OP_IdxLT 45 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGE 46 /* jump, synopsis: key=r[P3@P4] */
+#define OP_RowSetRead 47 /* jump, synopsis: r[P3]=rowset(P1) */
+#define OP_RowSetTest 48 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 49 /* jump0 */
+#define OP_FkIfZero 50 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_IsNull 51 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull 52 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne 53 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
+#define OP_Eq 54 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
+#define OP_Gt 55 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
+#define OP_Le 56 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
+#define OP_Lt 57 /* jump, same as TK_LT, synopsis: IF r[P3]=r[P1] */
+#define OP_ElseEq 59 /* jump, same as TK_ESCAPE */
+#define OP_IfPos 60 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfNotZero 61 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_DecrJumpZero 62 /* jump, synopsis: if (--r[P1])==0 goto P2 */
+#define OP_IncrVacuum 63 /* jump */
+#define OP_VNext 64 /* jump */
+#define OP_Filter 65 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
+#define OP_PureFunc 66 /* synopsis: r[P3]=func(r[P2@NP]) */
+#define OP_Function 67 /* synopsis: r[P3]=func(r[P2@NP]) */
+#define OP_Return 68
+#define OP_EndCoroutine 69
+#define OP_HaltIfNull 70 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 71
+#define OP_Integer 72 /* synopsis: r[P2]=P1 */
+#define OP_Int64 73 /* synopsis: r[P2]=P4 */
+#define OP_String 74 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_BeginSubrtn 75 /* synopsis: r[P2]=NULL */
+#define OP_Null 76 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 77 /* synopsis: r[P1]=NULL */
+#define OP_Blob 78 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 79 /* synopsis: r[P2]=parameter(P1) */
+#define OP_Move 80 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 81 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 82 /* synopsis: r[P2]=r[P1] */
+#define OP_IntCopy 83 /* synopsis: r[P2]=r[P1] */
+#define OP_FkCheck 84
+#define OP_ResultRow 85 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 86
+#define OP_AddImm 87 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_RealAffinity 88
+#define OP_Cast 89 /* synopsis: affinity(r[P1]) */
+#define OP_Permutation 90
+#define OP_Compare 91 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_IsTrue 92 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
+#define OP_ZeroOrNull 93 /* synopsis: r[P2] = 0 OR NULL */
+#define OP_Offset 94 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_Column 95 /* synopsis: r[P3]=PX cursor P1 column P2 */
+#define OP_TypeCheck 96 /* synopsis: typecheck(r[P1@P2]) */
+#define OP_Affinity 97 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 98 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 99 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 100
+#define OP_SetCookie 101
+#define OP_ReopenIdx 102 /* synopsis: root=P2 iDb=P3 */
+#define OP_BitAnd 103 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 104 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 105 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<>r[P1] */
+#define OP_Add 107 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 108 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 109 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 110 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 111 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 112 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_OpenRead 113 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 114 /* synopsis: root=P2 iDb=P3 */
+#define OP_BitNot 115 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
+#define OP_OpenDup 116
+#define OP_OpenAutoindex 117 /* synopsis: nColumn=P2 */
+#define OP_String8 118 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_OpenEphemeral 119 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 120
+#define OP_SequenceTest 121 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 122 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 123
+#define OP_ColumnsUsed 124
+#define OP_SeekScan 125 /* synopsis: Scan-ahead up to P1 rows */
+#define OP_SeekHit 126 /* synopsis: set P2<=seekHit<=P3 */
+#define OP_Sequence 127 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 128 /* synopsis: r[P2]=rowid */
+#define OP_Insert 129 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_RowCell 130
+#define OP_Delete 131
+#define OP_ResetCount 132
+#define OP_SorterCompare 133 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 134 /* synopsis: r[P2]=data */
+#define OP_RowData 135 /* synopsis: r[P2]=data */
+#define OP_Rowid 136 /* synopsis: r[P2]=PX rowid of P1 */
+#define OP_NullRow 137
+#define OP_SeekEnd 138
+#define OP_IdxInsert 139 /* synopsis: key=r[P2] */
+#define OP_SorterInsert 140 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 141 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 142 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 143 /* synopsis: r[P2]=rowid */
+#define OP_FinishSeek 144
+#define OP_Destroy 145
+#define OP_Clear 146
+#define OP_ResetSorter 147
+#define OP_CreateBtree 148 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 149
+#define OP_ParseSchema 150
+#define OP_LoadAnalysis 151
+#define OP_DropTable 152
+#define OP_DropIndex 153
+#define OP_Real 154 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_DropTrigger 155
+#define OP_IntegrityCk 156
+#define OP_RowSetAdd 157 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 158
+#define OP_FkCounter 159 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 160 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 161 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggInverse 162 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
+#define OP_AggStep 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep1 164 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggValue 165 /* synopsis: r[P3]=value N=P2 */
+#define OP_AggFinal 166 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 167
+#define OP_CursorLock 168
+#define OP_CursorUnlock 169
+#define OP_TableLock 170 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 171
+#define OP_VCreate 172
+#define OP_VDestroy 173
+#define OP_VOpen 174
+#define OP_VCheck 175
+#define OP_VInitIn 176 /* synopsis: r[P2]=ValueList(P1,P3) */
+#define OP_VColumn 177 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 178
+#define OP_Pagecount 179
+#define OP_MaxPgcnt 180
+#define OP_ClrSubtype 181 /* synopsis: r[P1].subtype = 0 */
+#define OP_GetSubtype 182 /* synopsis: r[P2] = r[P1].subtype */
+#define OP_SetSubtype 183 /* synopsis: r[P2].subtype = r[P1] */
+#define OP_FilterAdd 184 /* synopsis: filter(P1) += key(P3@P4) */
+#define OP_Trace 185
+#define OP_CursorHint 186
+#define OP_ReleaseReg 187 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 188
+#define OP_Explain 189
+#define OP_Abortable 190
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -16971,26 +17591,26 @@ typedef struct VdbeOpList VdbeOpList;
/* 8 */ 0x81, 0x01, 0x01, 0x81, 0x83, 0x83, 0x01, 0x01,\
/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0xc9, 0xc9, 0xc9,\
/* 24 */ 0xc9, 0x01, 0x49, 0x49, 0x49, 0x49, 0xc9, 0x49,\
-/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x41, 0x41,\
-/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
-/* 48 */ 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\
-/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
-/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
-/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
-/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\
-/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26, 0x26,\
+/* 32 */ 0xc1, 0x01, 0x41, 0x41, 0xc1, 0x01, 0x01, 0x41,\
+/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x41, 0x23,\
+/* 48 */ 0x0b, 0x81, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
+/* 56 */ 0x0b, 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01,\
+/* 64 */ 0x41, 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00,\
+/* 72 */ 0x10, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\
+/* 80 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02,\
+/* 88 */ 0x02, 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40,\
+/* 96 */ 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26,\
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\
-/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
-/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
-/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
-/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
-/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
-/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\
-/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\
-/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}
+/* 112 */ 0x26, 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40,\
+/* 120 */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10,\
+/* 128 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,\
+/* 136 */ 0x50, 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50,\
+/* 144 */ 0x40, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\
+/* 152 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00,\
+/* 160 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10,\
+/* 176 */ 0x50, 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12,\
+/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}
/* The resolve3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
@@ -16998,7 +17618,7 @@ typedef struct VdbeOpList VdbeOpList;
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
-#define SQLITE_MX_JUMP_OPCODE 64 /* Maximum JUMP opcode */
+#define SQLITE_MX_JUMP_OPCODE 65 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -17007,7 +17627,7 @@ typedef struct VdbeOpList VdbeOpList;
** Additional non-public SQLITE_PREPARE_* flags
*/
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
-#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
+#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
/*
** Prototypes for the VDBE interface. See comments on the implementation
@@ -17121,8 +17741,11 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
#endif
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*);
+#ifdef SQLITE_ENABLE_PERCENTILE
+SQLITE_PRIVATE const char *sqlite3VdbeFuncName(const sqlite3_context*);
+#endif
-SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
+SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
@@ -17135,13 +17758,15 @@ SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
SQLITE_PRIVATE void sqlite3MemSetArrayInt64(sqlite3_value *aMem, int iIdx, i64 val);
+#ifndef SQLITE_OMIT_DATETIME_FUNCS
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
+#endif
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
#endif
-/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
-** each VDBE opcode.
+/* Use SQLITE_ENABLE_EXPLAIN_COMMENTS to enable generation of extra
+** comments on each VDBE opcode.
**
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
** comments in VDBE programs that show key decision points in the code
@@ -17722,47 +18347,11 @@ struct FuncDefHash {
};
#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
-#if defined(SQLITE_USER_AUTHENTICATION)
-# warning "The SQLITE_USER_AUTHENTICATION extension is deprecated. \
- See ext/userauth/user-auth.txt for details."
-#endif
-#ifdef SQLITE_USER_AUTHENTICATION
-/*
-** Information held in the "sqlite3" database connection object and used
-** to manage user authentication.
-*/
-typedef struct sqlite3_userauth sqlite3_userauth;
-struct sqlite3_userauth {
- u8 authLevel; /* Current authentication level */
- int nAuthPW; /* Size of the zAuthPW in bytes */
- char *zAuthPW; /* Password used to authenticate */
- char *zAuthUser; /* User name used to authenticate */
-};
-
-/* Allowed values for sqlite3_userauth.authLevel */
-#define UAUTH_Unknown 0 /* Authentication not yet checked */
-#define UAUTH_Fail 1 /* User authentication failed */
-#define UAUTH_User 2 /* Authenticated as a normal user */
-#define UAUTH_Admin 3 /* Authenticated as an administrator */
-
-/* Functions used only by user authorization logic */
-SQLITE_PRIVATE int sqlite3UserAuthTable(const char*);
-SQLITE_PRIVATE int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
-SQLITE_PRIVATE void sqlite3UserAuthInit(sqlite3*);
-SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
-
-#endif /* SQLITE_USER_AUTHENTICATION */
-
/*
** typedef for the authorization callback function.
*/
-#ifdef SQLITE_USER_AUTHENTICATION
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*, const char*);
-#else
- typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*);
-#endif
+typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
+ const char*);
#ifndef SQLITE_OMIT_DEPRECATED
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
@@ -17827,7 +18416,7 @@ struct sqlite3 {
u8 iDb; /* Which db file is being initialized */
u8 busy; /* TRUE if currently initializing */
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
- unsigned imposterTable : 1; /* Building an imposter table */
+ unsigned imposterTable : 2; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
const char **azInit; /* "type", "name", and "tbl_name" columns */
} init;
@@ -17900,12 +18489,17 @@ struct sqlite3 {
Savepoint *pSavepoint; /* List of active savepoints */
int nAnalysisLimit; /* Number of index rows to ANALYZE */
int busyTimeout; /* Busy handler timeout, in msec */
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ int setlkTimeout; /* Blocking lock timeout, in msec. -1 -> inf. */
+ int setlkFlags; /* Flags passed to setlk_timeout() */
+#endif
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
i64 nDeferredCons; /* Net deferred constraints this transaction. */
i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
DbClientData *pDbData; /* sqlite3_set_clientdata() content */
+ u64 nSpill; /* TEMP content spilled to disk */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
/* The following variables are all protected by the STATIC_MAIN
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
@@ -17923,9 +18517,6 @@ struct sqlite3 {
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
#endif
-#ifdef SQLITE_USER_AUTHENTICATION
- sqlite3_userauth auth; /* User authentication information */
-#endif
};
/*
@@ -17989,6 +18580,9 @@ struct sqlite3 {
#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */
#define SQLITE_ReadUncommit HI(0x00004) /* READ UNCOMMITTED in shared-cache */
#define SQLITE_FkNoAction HI(0x00008) /* Treat all FK as NO ACTION */
+#define SQLITE_AttachCreate HI(0x00010) /* ATTACH allowed to create new dbs */
+#define SQLITE_AttachWrite HI(0x00020) /* ATTACH allowed to open for write */
+#define SQLITE_Comments HI(0x00040) /* Enable SQL comments */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
@@ -18047,6 +18641,9 @@ struct sqlite3 {
#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */
#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */
+#define SQLITE_OrderBySubq 0x10000000 /* ORDER BY in subquery helps outer */
+#define SQLITE_StarQuery 0x20000000 /* Heurists for star queries */
+#define SQLITE_ExistsToJoin 0x40000000 /* The EXISTS-to-JOIN optimization */
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
@@ -18083,7 +18680,7 @@ struct sqlite3 {
** field is used by per-connection app-def functions.
*/
struct FuncDef {
- i8 nArg; /* Number of arguments. -1 means unlimited */
+ i16 nArg; /* Number of arguments. -1 means unlimited */
u32 funcFlags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
@@ -18285,7 +18882,7 @@ struct FuncDestructor {
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
{nArg, SQLITE_FUNC_BUILTIN|\
SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
- pArg, 0, xFunc, 0, 0, 0, #zName, }
+ pArg, 0, xFunc, 0, 0, 0, #zName, {0} }
#define LIKEFUNC(zName, nArg, arg, flags) \
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
(void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
@@ -18452,6 +19049,7 @@ struct CollSeq {
#define SQLITE_AFF_INTEGER 0x44 /* 'D' */
#define SQLITE_AFF_REAL 0x45 /* 'E' */
#define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */
+#define SQLITE_AFF_DEFER 0x58 /* 'X' - defer computation until later */
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
@@ -18576,6 +19174,7 @@ struct Table {
} u;
Trigger *pTrigger; /* List of triggers on this object */
Schema *pSchema; /* Schema that contains this table */
+ u8 aHx[16]; /* Column aHt[K%sizeof(aHt)] might have hash K */
};
/*
@@ -18611,6 +19210,7 @@ struct Table {
#define TF_Ephemeral 0x00004000 /* An ephemeral table */
#define TF_Eponymous 0x00008000 /* An eponymous virtual table */
#define TF_Strict 0x00010000 /* STRICT mode */
+#define TF_Imposter 0x00020000 /* An imposter table */
/*
** Allowed values for Table.eTabType
@@ -18709,9 +19309,13 @@ struct FKey {
struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
int iFrom; /* Index of column in pFrom */
char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
- } aCol[1]; /* One entry for each of nCol columns */
+ } aCol[FLEXARRAY]; /* One entry for each of nCol columns */
};
+/* The size (in bytes) of an FKey object holding N columns. The answer
+** does NOT include space to hold the zTo name. */
+#define SZ_FKEY(N) (offsetof(FKey,aCol)+(N)*sizeof(struct sColMap))
+
/*
** SQLite supports many different ways to resolve a constraint
** error. ROLLBACK processing means that a constraint violation
@@ -18762,9 +19366,15 @@ struct FKey {
** 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.
+** The aSortOrder[] and aColl[] arrays have nAllField slots each. There
+** are nKeyField slots for the columns of an index then extra slots
+** for the rowid or key at the end. The aSortOrder array is located after
+** the aColl[] array.
+**
+** If SQLITE_ENABLE_PREUPDATE_HOOK is defined, then aSortFlags might be NULL
+** to indicate that this object is for use by a preupdate hook. When aSortFlags
+** is NULL, then nAllField is uninitialized and no space is allocated for
+** aColl[], so those fields may not be used.
*/
struct KeyInfo {
u32 nRef; /* Number of references to this KeyInfo object */
@@ -18773,9 +19383,21 @@ struct KeyInfo {
u16 nAllField; /* Total columns, including key plus others */
sqlite3 *db; /* The database connection */
u8 *aSortFlags; /* Sort order for each column. */
- CollSeq *aColl[1]; /* Collating sequence for each term of the key */
+ CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
};
+/* The size (in bytes) of a KeyInfo object with up to N fields. This includes
+** the main body of the KeyInfo object and the aColl[] array of N elements,
+** but does not count the memory used to hold aSortFlags[]. */
+#define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*))
+
+/* The size of a bare KeyInfo with no aColl[] entries */
+#if FLEXARRAY+1 > 1
+# define SZ_KEYINFO_0 offsetof(KeyInfo,aColl)
+#else
+# define SZ_KEYINFO_0 sizeof(KeyInfo)
+#endif
+
/*
** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
*/
@@ -18794,9 +19416,8 @@ struct KeyInfo {
**
** An instance of this object serves as a "key" for doing a search on
** an index b+tree. The goal of the search is to find the entry that
-** is closed to the key described by this object. This object might hold
-** just a prefix of the key. The number of fields is given by
-** pKeyInfo->nField.
+** is closest to the key described by this object. This object might hold
+** just a prefix of the key. The number of fields is given by nField.
**
** The r1 and r2 fields are the values to return if this key is less than
** or greater than a key in the btree, respectively. These are normally
@@ -18806,7 +19427,7 @@ struct KeyInfo {
** The key comparison functions actually return default_rc when they find
** an equals comparison. default_rc can be -1, 0, or +1. If there are
** multiple entries in the b-tree with the same key (when only looking
-** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to
+** at the first nField elements) then default_rc can be set to -1 to
** cause the search to find the last match, or +1 to cause the search to
** find the first match.
**
@@ -18818,8 +19439,8 @@ struct KeyInfo {
** b-tree.
*/
struct UnpackedRecord {
- KeyInfo *pKeyInfo; /* Collation and sort-order information */
- Mem *aMem; /* Values */
+ KeyInfo *pKeyInfo; /* Comparison info for the index that is unpacked */
+ Mem *aMem; /* Values for columns of the index */
union {
char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */
i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */
@@ -18895,7 +19516,7 @@ struct Index {
Pgno tnum; /* DB Page containing root of this index */
LogEst szIdxRow; /* Estimated average row size in bytes */
u16 nKeyCol; /* Number of columns forming the key */
- u16 nColumn; /* Number of columns stored in the index */
+ u16 nColumn; /* Nr columns in btree. Can be 2*Table.nCol */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
@@ -18904,7 +19525,6 @@ struct Index {
unsigned isCovering:1; /* True if this is a covering index */
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
- unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
@@ -18994,7 +19614,7 @@ struct AggInfo {
** from source tables rather than from accumulators */
u8 useSortingIdx; /* In direct mode, reference the sorting index rather
** than the source table */
- u16 nSortingColumn; /* Number of columns in the sorting index */
+ u32 nSortingColumn; /* Number of columns in the sorting index */
int sortingIdx; /* Cursor number of the sorting index */
int sortingIdxPTab; /* Cursor number of pseudo-table */
int iFirstReg; /* First register in range for aCol[] and aFunc[] */
@@ -19003,8 +19623,8 @@ struct AggInfo {
Table *pTab; /* Source table */
Expr *pCExpr; /* The original expression */
int iTable; /* Cursor number of the source table */
- i16 iColumn; /* Column number within the source table */
- i16 iSorterColumn; /* Column number in the sorting index */
+ int iColumn; /* Column number within the source table */
+ int iSorterColumn; /* Column number in the sorting index */
} *aCol;
int nColumn; /* Number of used entries in aCol[] */
int nAccumulator; /* Number of columns that show through to the output.
@@ -19034,9 +19654,15 @@ struct AggInfo {
** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg.
** The assert()s that are part of this macro verify that constraint.
*/
+#ifndef NDEBUG
#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I))
#define AggInfoFuncReg(A,I) \
(assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I))
+#else
+#define AggInfoColumnReg(A,I) ((A)->iFirstReg+(I))
+#define AggInfoFuncReg(A,I) \
+ ((A)->iFirstReg+(A)->nColumn+(I))
+#endif
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
@@ -19173,6 +19799,7 @@ struct Expr {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
** for a column of an index on an expression */
Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
+ int nReg; /* TK_NULLS: Number of registers to NULL out */
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
int iAddr; /* Subroutine entry address */
int regReturn; /* Register used to hold return address */
@@ -19217,7 +19844,7 @@ struct Expr {
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
- /* 0x80000000 // Available */
+#define EP_SubtArg 0x80000000 /* Is argument to SQLITE_SUBTYPE function */
/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
@@ -19227,10 +19854,10 @@ struct Expr {
/* Macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
-#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
-#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
-#define ExprSetProperty(E,P) (E)->flags|=(P)
-#define ExprClearProperty(E,P) (E)->flags&=~(P)
+#define ExprHasProperty(E,P) (((E)->flags&(u32)(P))!=0)
+#define ExprHasAllProperty(E,P) (((E)->flags&(u32)(P))==(u32)(P))
+#define ExprSetProperty(E,P) (E)->flags|=(u32)(P)
+#define ExprClearProperty(E,P) (E)->flags&=~(u32)(P)
#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue)
#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse)
#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0)
@@ -19342,9 +19969,14 @@ struct ExprList {
int iConstExprReg; /* Register in which Expr value is cached. Used only
** by Parse.pConstExpr */
} u;
- } a[1]; /* One slot for each expression in the list */
+ } a[FLEXARRAY]; /* One slot for each expression in the list */
};
+/* The size (in bytes) of an ExprList object that is big enough to hold
+** as many as N expressions. */
+#define SZ_EXPRLIST(N) \
+ (offsetof(ExprList,a) + (N)*sizeof(struct ExprList_item))
+
/*
** Allowed values for Expr.a.eEName
*/
@@ -19370,16 +20002,14 @@ struct ExprList {
*/
struct IdList {
int nId; /* Number of identifiers on the list */
- u8 eU4; /* Which element of a.u4 is valid */
struct IdList_item {
char *zName; /* Name of the identifier */
- union {
- int idx; /* Index in some Table.aCol[] of a column named zName */
- Expr *pExpr; /* Expr to implement a USING variable -- NOT USED */
- } u4;
- } a[1];
+ } a[FLEXARRAY];
};
+/* The size (in bytes) of an IdList object that can hold up to N IDs. */
+#define SZ_IDLIST(N) (offsetof(IdList,a)+(N)*sizeof(struct IdList_item))
+
/*
** Allowed values for IdList.eType, which determines which value of the a.u4
** is valid.
@@ -19388,6 +20018,16 @@ struct IdList {
#define EU4_IDX 1 /* Uses IdList.a.u4.idx */
#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */
+/*
+** Details of the implementation of a subquery.
+*/
+struct Subquery {
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int addrFillSub; /* Address of subroutine to initialize a subquery */
+ int regReturn; /* Register holding return address of addrFillSub */
+ int regResult; /* Registers holding results of a co-routine */
+};
+
/*
** The SrcItem object represents a single term in the FROM clause of a query.
** The SrcList object is mostly an array of SrcItems.
@@ -19400,29 +20040,40 @@ struct IdList {
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
**
-** Union member validity:
+** Aggressive use of "union" helps keep the size of the object small. This
+** has been shown to boost performance, in addition to saving memory.
+** Access to union elements is gated by the following rules which should
+** always be checked, either by an if-statement or by an assert().
**
-** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
-** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
+** Field Only access if this is true
+** --------------- -----------------------------------
+** u1.zIndexedBy fg.isIndexedBy
+** u1.pFuncArg fg.isTabFunc
** u1.nRow !fg.isTabFunc && !fg.isIndexedBy
**
-** u2.pIBIndex fg.isIndexedBy && !fg.isCte
-** u2.pCteUse fg.isCte && !fg.isIndexedBy
+** u2.pIBIndex fg.isIndexedBy
+** u2.pCteUse fg.isCte
+**
+** u3.pOn !fg.isUsing
+** u3.pUsing fg.isUsing
+**
+** u4.zDatabase !fg.fixedSchema && !fg.isSubquery
+** u4.pSchema fg.fixedSchema
+** u4.pSubq fg.isSubquery
+**
+** See also the sqlite3SrcListDelete() routine for assert() statements that
+** check invariants on the fields of this object, especially the flags
+** inside the fg struct.
*/
struct SrcItem {
- Schema *pSchema; /* Schema to which this item is fixed */
- char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int addrFillSub; /* Address of subroutine to manifest a subquery */
- int regReturn; /* Register holding return address of addrFillSub */
- int regResult; /* Registers holding results of a co-routine */
+ Table *pSTab; /* Table object for zName. Mnemonic: Srcitem-TABle */
struct {
u8 jointype; /* Type of join between this table and the previous */
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
+ unsigned isSubquery :1; /* True if this term is a subquery */
unsigned isTabFunc :1; /* True if table-valued-function syntax */
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned isMaterialized:1; /* This is a materialized view */
@@ -19436,12 +20087,11 @@ struct SrcItem {
unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
unsigned rowidUsed :1; /* The ROWID of this table is referenced */
+ unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */
+ unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */
+ unsigned fromExists :1; /* Comes from WHERE EXISTS(...) */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
- union {
- Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
- IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
- } u3;
Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */
union {
char *zIndexedBy; /* Identifier from "INDEXED BY " clause */
@@ -19452,6 +20102,15 @@ struct SrcItem {
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */
} u2;
+ union {
+ Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
+ IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
+ } u3;
+ union {
+ Schema *pSchema; /* Schema to which this item is fixed */
+ char *zDatabase; /* Name of database holding this table */
+ Subquery *pSubq; /* Description of a subquery */
+ } u4;
};
/*
@@ -19471,11 +20130,19 @@ struct OnOrUsing {
**
*/
struct SrcList {
- int nSrc; /* Number of tables or subqueries in the FROM clause */
- u32 nAlloc; /* Number of entries allocated in a[] below */
- SrcItem a[1]; /* One entry for each identifier on the list */
+ int nSrc; /* Number of tables or subqueries in the FROM clause */
+ u32 nAlloc; /* Number of entries allocated in a[] below */
+ SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */
};
+/* Size (in bytes) of a SrcList object that can hold as many as N
+** SrcItem objects. */
+#define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem))
+
+/* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a
+** special case of SZ_SRCITEM(1) that comes up often. */
+#define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem))
+
/*
** Permitted values of the SrcList.a.jointype field
*/
@@ -19511,7 +20178,7 @@ struct SrcList {
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
- /* 0x2000 not currently used */
+#define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -19583,7 +20250,7 @@ struct NameContext {
#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
-#define NC_Complex 0x002000 /* True if a function or subquery seen */
+/* 0x002000 // available for reuse */
#define NC_AllowWin 0x004000 /* Window functions are allowed here */
#define NC_HasWin 0x008000 /* One or more window functions seen */
#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
@@ -19710,9 +20377,12 @@ struct Select {
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
#define SF_Correlated 0x20000000 /* True if references the outer context */
+#define SF_OnToWhere 0x40000000 /* One or more ON clauses moved to WHERE */
-/* True if S exists and has SF_NestedFrom */
-#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
+/* True if SrcItem X is a subquery that has SF_NestedFrom */
+#define IsNestedFrom(X) \
+ ((X)->fg.isSubquery && \
+ ((X)->u4.pSubq->pSelect->selFlags&SF_NestedFrom)!=0)
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -19742,7 +20412,11 @@ struct Select {
** SRT_Set The result must be a single column. Store each
** row of result as the key in table pDest->iSDParm.
** Apply the affinity pDest->affSdst before storing
-** results. Used to implement "IN (SELECT ...)".
+** results. if pDest->iSDParm2 is positive, then it is
+** a register holding a Bloom filter for the IN operator
+** that should be populated in addition to the
+** pDest->iSDParm table. This SRT is used to
+** implement "IN (SELECT ...)".
**
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
** the result there. The cursor is left open after
@@ -19938,24 +20612,33 @@ struct Parse {
char *zErrMsg; /* An error message */
Vdbe *pVdbe; /* An engine for executing database bytecode */
int rc; /* Return code from execution */
- u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
- u8 checkSchema; /* Causes schema cookie check after an error */
+ LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
u8 nested; /* Number of nested calls to the parser/code generator */
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
- u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
- u8 bHasWith; /* True if statement contains WITH */
+ u8 bHasExists; /* Has a correlated "EXISTS (SELECT ....)" expression */
+ u8 mSubrtnSig; /* mini Bloom filter on available SubrtnSig.selId */
+ u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
+ u8 bReturning; /* Coding a RETURNING trigger */
+ u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
+ u8 disableTriggers; /* True to disable triggers */
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
#endif
#ifdef SQLITE_DEBUG
u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */
+ u8 isCreate; /* CREATE TABLE, INDEX, or VIEW (but not TRIGGER)
+ ** and ALTER TABLE ADD COLUMN. */
#endif
+ bft colNamesSet :1; /* TRUE after OP_ColumnName has been issued to pVdbe */
+ bft bHasWith :1; /* True if statement contains WITH */
+ bft okConstFactor :1; /* OK to factor out constants */
+ bft checkSchema :1; /* Causes schema cookie check after an error */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -19970,12 +20653,9 @@ struct Parse {
ExprList *pConstExpr;/* Constant expressions */
IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */
IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */
- Token constraintName;/* Name of the constraint currently being parsed */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
- int regRowid; /* Register holding rowid of CREATE TABLE entry */
- int regRoot; /* Register holding root page number for new objects */
- int nMaxArg; /* Max args passed to user function by sub-program */
+ int nMaxArg; /* Max args to xUpdate and xFilter vtab methods */
int nSelect; /* Number of SELECT stmts. Counter for Select.selId */
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */
@@ -19989,17 +20669,6 @@ struct Parse {
Table *pTriggerTab; /* Table triggers are being coded for */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
- union {
- int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
- Returning *pReturning; /* The RETURNING clause */
- } u1;
- u32 oldmask; /* Mask of old.* columns referenced */
- u32 newmask; /* Mask of new.* columns referenced */
- LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
- u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
- u8 bReturning; /* Coding a RETURNING trigger */
- u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
- u8 disableTriggers; /* True to disable triggers */
/**************************************************************************
** Fields above must be initialized to zero. The fields that follow,
@@ -20011,6 +20680,19 @@ struct Parse {
int aTempReg[8]; /* Holding area for temporary registers */
Parse *pOuterParse; /* Outer Parse object when nested */
Token sNameToken; /* Token with unqualified schema object name */
+ u32 oldmask; /* Mask of old.* columns referenced */
+ u32 newmask; /* Mask of new.* columns referenced */
+ union {
+ struct { /* These fields available when isCreate is true */
+ int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
+ int regRowid; /* Register holding rowid of CREATE TABLE entry */
+ int regRoot; /* Register holding root page for new objects */
+ Token constraintName; /* Name of the constraint currently being parsed */
+ } cr;
+ struct { /* These fields available to all other statements */
+ Returning *pReturning; /* The RETURNING clause */
+ } d;
+ } u1;
/************************************************************************
** Above is constant between recursions. Below is reset before and after
@@ -20028,9 +20710,7 @@ struct Parse {
int nVtabLock; /* Number of virtual tables to lock */
#endif
int nHeight; /* Expression tree height of current sub-select */
-#ifndef SQLITE_OMIT_EXPLAIN
int addrExplain; /* Address of current OP_Explain opcode */
-#endif
VList *pVList; /* Mapping between variable names and numbers */
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
const char *zTail; /* All SQL text past the last semicolon parsed */
@@ -20245,7 +20925,7 @@ struct Returning {
};
/*
-** An objected used to accumulate the text of a string where we
+** An object used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end.
*/
struct sqlite3_str {
@@ -20259,7 +20939,7 @@ struct sqlite3_str {
};
#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
-#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
+#define SQLITE_PRINTF_MALLOCED 0x04 /* True if zText is allocated space */
#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
@@ -20337,7 +21017,6 @@ struct Sqlite3Config {
u8 bUseCis; /* Use covering indices for full-scans */
u8 bSmallMalloc; /* Avoid large memory allocations if true */
u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
- u8 bUseLongDouble; /* Make use of long double */
#ifdef SQLITE_DEBUG
u8 bJsonSelfcheck; /* Double-check JSON parsing */
#endif
@@ -20452,6 +21131,7 @@ struct Walker {
SrcItem *pSrcItem; /* A single FROM clause item */
DbFixer *pFix; /* See sqlite3FixSelect() */
Mem *aMem; /* See sqlite3BtreeCursorHint() */
+ struct CheckOnCtx *pCheckOnCtx; /* See selectCheckOnClauses() */
} u;
};
@@ -20529,9 +21209,13 @@ struct With {
int nCte; /* Number of CTEs in the WITH clause */
int bView; /* Belongs to the outermost Select of a view */
With *pOuter; /* Containing WITH clause, or NULL */
- Cte a[1]; /* For each CTE in the WITH clause.... */
+ Cte a[FLEXARRAY]; /* For each CTE in the WITH clause.... */
};
+/* The size (in bytes) of a With object that can hold as many
+** as N different CTEs. */
+#define SZ_WITH(N) (offsetof(With,a) + (N)*sizeof(Cte))
+
/*
** The Cte object is not guaranteed to persist for the entire duration
** of code generation. (The query flattener or other parser tree
@@ -20560,9 +21244,13 @@ struct DbClientData {
DbClientData *pNext; /* Next in a linked list */
void *pData; /* The data */
void (*xDestructor)(void*); /* Destructor. Might be NULL */
- char zName[1]; /* Name of this client data. MUST BE LAST */
+ char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */
};
+/* The size (in bytes) of a DbClientData object that can has a name
+** that is N bytes long, including the zero-terminator. */
+#define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N))
+
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
@@ -20712,15 +21400,6 @@ SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
# define SQLITE_ENABLE_FTS3 1
#endif
-/*
-** The ctype.h header is needed for non-ASCII systems. It is also
-** needed by FTS3 when FTS3 is included in the amalgamation.
-*/
-#if !defined(SQLITE_ASCII) || \
- (defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
-# include
-#endif
-
/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
@@ -20940,6 +21619,7 @@ SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger*);
SQLITE_PRIVATE void sqlite3ShowWindow(const Window*);
SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*);
#endif
+SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec*);
#endif
SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
@@ -21014,7 +21694,7 @@ SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char);
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int);
SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
-SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16);
+SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index*, int);
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
@@ -21099,6 +21779,9 @@ SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
+SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3*,Subquery*);
+SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3*,SrcItem*);
+SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(Parse*, SrcItem*, Select*, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
@@ -21109,7 +21792,7 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
-SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
+SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**);
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
@@ -21148,6 +21831,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
+SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg);
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
@@ -21155,6 +21839,7 @@ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int)
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
+SQLITE_PRIVATE void sqlite3ExprNullRegisterRange(Parse*, int, int);
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
@@ -21210,7 +21895,7 @@ SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,i
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
#endif
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*);
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
@@ -21244,19 +21929,24 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,const Select*,int);
SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*);
SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
-SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*);
+SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*,int);
+SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char*, u32);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void);
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void);
SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void);
SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
-SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3*);
+SQLITE_PRIVATE Module *sqlite3JsonVtabRegister(sqlite3*,const char*);
#endif
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p);
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_CARRAY)
+SQLITE_PRIVATE Module *sqlite3CarrayRegister(sqlite3*);
+#endif
+
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
#endif
@@ -21338,7 +22028,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
#ifndef SQLITE_OMIT_UTF16
-SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
+SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nByte, int nChar);
#endif
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
@@ -21477,7 +22167,7 @@ SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
-SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
+SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
@@ -22109,6 +22799,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_BUG_COMPATIBLE_20160819
"BUG_COMPATIBLE_20160819",
#endif
+#ifdef SQLITE_BUG_COMPATIBLE_20250510
+ "BUG_COMPATIBLE_20250510",
+#endif
#ifdef SQLITE_CASE_SENSITIVE_LIKE
"CASE_SENSITIVE_LIKE",
#endif
@@ -22240,6 +22933,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
"ENABLE_BYTECODE_VTAB",
#endif
+#ifdef SQLITE_ENABLE_CARRAY
+ "ENABLE_CARRAY",
+#endif
#ifdef SQLITE_ENABLE_CEROD
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
@@ -22324,9 +23020,15 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
"ENABLE_OFFSET_SQL_FUNC",
#endif
+#ifdef SQLITE_ENABLE_ORDERED_SET_AGGREGATES
+ "ENABLE_ORDERED_SET_AGGREGATES",
+#endif
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
"ENABLE_OVERSIZE_CELL_CHECK",
#endif
+#ifdef SQLITE_ENABLE_PERCENTILE
+ "ENABLE_PERCENTILE",
+#endif
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
"ENABLE_PREUPDATE_HOOK",
#endif
@@ -22342,6 +23044,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_ENABLE_SESSION
"ENABLE_SESSION",
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ "ENABLE_SETLK_TIMEOUT",
+#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
"ENABLE_SNAPSHOT",
#endif
@@ -22396,6 +23101,9 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_EXTRA_INIT
"EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
#endif
+#ifdef SQLITE_EXTRA_INIT_MUTEXED
+ "EXTRA_INIT_MUTEXED=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT_MUTEXED),
+#endif
#ifdef SQLITE_EXTRA_SHUTDOWN
"EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
#endif
@@ -22793,9 +23501,6 @@ static const char * const sqlite3azCompileOpt[] = {
#ifdef SQLITE_UNTESTABLE
"UNTESTABLE",
#endif
-#ifdef SQLITE_USER_AUTHENTICATION
- "USER_AUTHENTICATION",
-#endif
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
@@ -23071,7 +23776,6 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0, /* bSmallMalloc */
1, /* bExtraSchemaChecks */
- sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
#ifdef SQLITE_DEBUG
0, /* bJsonSelfcheck */
#endif
@@ -23384,12 +24088,19 @@ struct VdbeCursor {
#endif
VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
- /* 2*nField extra array elements allocated for aType[], beyond the one
- ** static element declared in the structure. nField total array slots for
- ** aType[] and nField+1 array slots for aOffset[] */
- u32 aType[1]; /* Type values record decode. MUST BE LAST */
+ /* Space is allocated for aType to hold at least 2*nField+1 entries:
+ ** nField slots for aType[] and nField+1 array slots for aOffset[] */
+ u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */
};
+/*
+** The size (in bytes) of a VdbeCursor object that has an nField value of N
+** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple
+** of 8.
+*/
+#define SZ_VDBECURSOR(N) \
+ (ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64))
+
/* Return true if P is a null-only cursor
*/
#define IsNullCursor(P) \
@@ -23495,6 +24206,7 @@ struct sqlite3_value {
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
u16 mScopyFlags; /* flags value immediately after the shallow copy */
+ u8 bScopy; /* The pScopyFrom of some other Mem *might* point here */
#endif
};
@@ -23531,7 +24243,7 @@ struct sqlite3_value {
** MEM_Int, MEM_Real, and MEM_IntReal.
**
** * MEM_Blob|MEM_Zero A blob in Mem.z of length Mem.n plus
-** MEM.u.i extra 0x00 bytes at the end.
+** Mem.u.nZero extra 0x00 bytes at the end.
**
** * MEM_Int Integer stored in Mem.u.i.
**
@@ -23644,14 +24356,17 @@ struct sqlite3_context {
int isError; /* Error code returned by the function. */
u8 enc; /* Encoding to use for results */
u8 skipFlag; /* Skip accumulator loading if true */
- u8 argc; /* Number of arguments */
- sqlite3_value *argv[1]; /* Argument set */
+ u16 argc; /* Number of arguments */
+ sqlite3_value *argv[FLEXARRAY]; /* Argument set */
};
-/* A bitfield type for use inside of structures. Always follow with :N where
-** N is the number of bits.
+/*
+** The size (in bytes) of an sqlite3_context object that holds N
+** argv[] arguments.
*/
-typedef unsigned bft; /* Bit Field Type */
+#define SZ_CONTEXT(N) \
+ (offsetof(sqlite3_context,argv)+(N)*sizeof(sqlite3_value*))
+
/* The ScanStatus object holds a single value for the
** sqlite3_stmt_scanstatus() interface.
@@ -23712,7 +24427,7 @@ struct Vdbe {
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
Mem *aMem; /* The memory locations */
- Mem **apArg; /* Arguments to currently executing user function */
+ Mem **apArg; /* Arguments xUpdate and xFilter vtab methods */
VdbeCursor **apCsr; /* One element of this array for each open cursor */
Mem *aVar; /* Values for the OP_Variable opcode. */
@@ -23732,6 +24447,7 @@ struct Vdbe {
#ifdef SQLITE_DEBUG
int rcApp; /* errcode set by sqlite3_result_error_code() */
u32 nWrite; /* Number of write operations that have occurred */
+ int napArg; /* Size of the apArg[] array */
#endif
u16 nResColumn; /* Number of columns in one row of the result set */
u16 nResAlloc; /* Column slots allocated to aColName[] */
@@ -23784,16 +24500,21 @@ struct PreUpdate {
VdbeCursor *pCsr; /* Cursor to read old values from */
int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
u8 *aRecord; /* old.* database record */
- KeyInfo keyinfo;
+ KeyInfo *pKeyinfo; /* Key information */
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
int iNewReg; /* Register for new.* values */
int iBlobWrite; /* Value returned by preupdate_blobwrite() */
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
+ Mem oldipk; /* Memory cell holding "old" IPK value */
Mem *aNew; /* Array of new.* values */
Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
+ sqlite3_value **apDflt; /* Array of default values, if required */
+ struct {
+ u8 keyinfoSpace[SZ_KEYINFO_0]; /* Space to hold pKeyinfo[0] content */
+ } uKey;
};
/*
@@ -23957,9 +24678,11 @@ SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*);
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
-SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
+SQLITE_PRIVATE int sqlite3VdbeCheckFkImmediate(Vdbe*);
+SQLITE_PRIVATE int sqlite3VdbeCheckFkDeferred(Vdbe*);
#else
-# define sqlite3VdbeCheckFk(p,i) 0
+# define sqlite3VdbeCheckFkImmediate(p) 0
+# define sqlite3VdbeCheckFkDeferred(p) 0
#endif
#ifdef SQLITE_DEBUG
@@ -24160,30 +24883,33 @@ SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
nInit += countLookasideSlots(db->lookaside.pSmallInit);
nFree += countLookasideSlots(db->lookaside.pSmallFree);
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
- if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
- return db->lookaside.nSlot - (nInit+nFree);
+ assert( db->lookaside.nSlot >= nInit+nFree );
+ if( pHighwater ) *pHighwater = (int)(db->lookaside.nSlot - nInit);
+ return (int)(db->lookaside.nSlot - (nInit+nFree));
}
/*
** Query status information for a single database connection
*/
-SQLITE_API int sqlite3_db_status(
- sqlite3 *db, /* The database connection whose status is desired */
- int op, /* Status verb */
- int *pCurrent, /* Write current value here */
- int *pHighwater, /* Write high-water mark here */
- int resetFlag /* Reset high-water mark if true */
+SQLITE_API int sqlite3_db_status64(
+ sqlite3 *db, /* The database connection whose status is desired */
+ int op, /* Status verb */
+ sqlite3_int64 *pCurrent, /* Write current value here */
+ sqlite3_int64 *pHighwtr, /* Write high-water mark here */
+ int resetFlag /* Reset high-water mark if true */
){
int rc = SQLITE_OK; /* Return code */
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){
+ if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwtr==0 ){
return SQLITE_MISUSE_BKPT;
}
#endif
sqlite3_mutex_enter(db->mutex);
switch( op ){
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
- *pCurrent = sqlite3LookasideUsed(db, pHighwater);
+ int H = 0;
+ *pCurrent = sqlite3LookasideUsed(db, &H);
+ *pHighwtr = H;
if( resetFlag ){
LookasideSlot *p = db->lookaside.pFree;
if( p ){
@@ -24214,7 +24940,7 @@ SQLITE_API int sqlite3_db_status(
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
*pCurrent = 0;
- *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
+ *pHighwtr = db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT];
if( resetFlag ){
db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
}
@@ -24228,7 +24954,7 @@ SQLITE_API int sqlite3_db_status(
*/
case SQLITE_DBSTATUS_CACHE_USED_SHARED:
case SQLITE_DBSTATUS_CACHE_USED: {
- int totalUsed = 0;
+ sqlite3_int64 totalUsed = 0;
int i;
sqlite3BtreeEnterAll(db);
for(i=0; inDb; i++){
@@ -24244,18 +24970,18 @@ SQLITE_API int sqlite3_db_status(
}
sqlite3BtreeLeaveAll(db);
*pCurrent = totalUsed;
- *pHighwater = 0;
+ *pHighwtr = 0;
break;
}
/*
** *pCurrent gets an accurate estimate of the amount of memory used
** to store the schema for all databases (main, temp, and any ATTACHed
- ** databases. *pHighwater is set to zero.
+ ** databases. *pHighwtr is set to zero.
*/
case SQLITE_DBSTATUS_SCHEMA_USED: {
- int i; /* Used to iterate through schemas */
- int nByte = 0; /* Used to accumulate return value */
+ int i; /* Used to iterate through schemas */
+ int nByte = 0; /* Used to accumulate return value */
sqlite3BtreeEnterAll(db);
db->pnBytesFreed = &nByte;
@@ -24289,7 +25015,7 @@ SQLITE_API int sqlite3_db_status(
db->lookaside.pEnd = db->lookaside.pTrueEnd;
sqlite3BtreeLeaveAll(db);
- *pHighwater = 0;
+ *pHighwtr = 0;
*pCurrent = nByte;
break;
}
@@ -24297,7 +25023,7 @@ SQLITE_API int sqlite3_db_status(
/*
** *pCurrent gets an accurate estimate of the amount of memory used
** to store all prepared statements.
- ** *pHighwater is set to zero.
+ ** *pHighwtr is set to zero.
*/
case SQLITE_DBSTATUS_STMT_USED: {
struct Vdbe *pVdbe; /* Used to iterate through VMs */
@@ -24312,7 +25038,7 @@ SQLITE_API int sqlite3_db_status(
db->lookaside.pEnd = db->lookaside.pTrueEnd;
db->pnBytesFreed = 0;
- *pHighwater = 0; /* IMP: R-64479-57858 */
+ *pHighwtr = 0; /* IMP: R-64479-57858 */
*pCurrent = nByte;
break;
@@ -24320,7 +25046,7 @@ SQLITE_API int sqlite3_db_status(
/*
** Set *pCurrent to the total cache hits or misses encountered by all
- ** pagers the database handle is connected to. *pHighwater is always set
+ ** pagers the database handle is connected to. *pHighwtr is always set
** to zero.
*/
case SQLITE_DBSTATUS_CACHE_SPILL:
@@ -24340,19 +25066,39 @@ SQLITE_API int sqlite3_db_status(
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
}
}
- *pHighwater = 0; /* IMP: R-42420-56072 */
+ *pHighwtr = 0; /* IMP: R-42420-56072 */
/* IMP: R-54100-20147 */
/* IMP: R-29431-39229 */
- *pCurrent = (int)nRet & 0x7fffffff;
+ *pCurrent = nRet;
+ break;
+ }
+
+ /* Set *pCurrent to the number of bytes that the db database connection
+ ** has spilled to the filesystem in temporary files that could have been
+ ** stored in memory, had sufficient memory been available.
+ ** The *pHighwater is always set to zero.
+ */
+ case SQLITE_DBSTATUS_TEMPBUF_SPILL: {
+ u64 nRet = 0;
+ if( db->aDb[1].pBt ){
+ Pager *pPager = sqlite3BtreePager(db->aDb[1].pBt);
+ sqlite3PagerCacheStat(pPager, SQLITE_DBSTATUS_CACHE_WRITE,
+ resetFlag, &nRet);
+ nRet *= sqlite3BtreeGetPageSize(db->aDb[1].pBt);
+ }
+ nRet += db->nSpill;
+ if( resetFlag ) db->nSpill = 0;
+ *pHighwtr = 0;
+ *pCurrent = nRet;
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.
+ ** have been satisfied. The *pHighwtr is always set to zero.
*/
case SQLITE_DBSTATUS_DEFERRED_FKS: {
- *pHighwater = 0; /* IMP: R-11967-56545 */
+ *pHighwtr = 0; /* IMP: R-11967-56545 */
*pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
break;
}
@@ -24365,6 +25111,31 @@ SQLITE_API int sqlite3_db_status(
return rc;
}
+/*
+** 32-bit variant of sqlite3_db_status64()
+*/
+SQLITE_API int sqlite3_db_status(
+ sqlite3 *db, /* The database connection whose status is desired */
+ int op, /* Status verb */
+ int *pCurrent, /* Write current value here */
+ int *pHighwtr, /* Write high-water mark here */
+ int resetFlag /* Reset high-water mark if true */
+){
+ sqlite3_int64 C = 0, H = 0;
+ int rc;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwtr==0 ){
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+ rc = sqlite3_db_status64(db, op, &C, &H, resetFlag);
+ if( rc==0 ){
+ *pCurrent = C & 0x7fffffff;
+ *pHighwtr = H & 0x7fffffff;
+ }
+ return rc;
+}
+
/************** End of status.c **********************************************/
/************** Begin file date.c ********************************************/
/*
@@ -24557,6 +25328,10 @@ static int parseTimezone(const char *zDate, DateTime *p){
}
zDate += 5;
p->tz = sgn*(nMn + nHr*60);
+ if( p->tz==0 ){ /* Forum post 2025-09-17T10:12:14z */
+ p->isLocal = 0;
+ p->isUtc = 1;
+ }
zulu_time:
while( sqlite3Isspace(*zDate) ){ zDate++; }
return *zDate!=0;
@@ -24591,6 +25366,9 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
zDate++;
}
ms /= rScale;
+ /* Truncate to avoid problems with sub-milliseconds
+ ** rounding. https://sqlite.org/forum/forumpost/766a2c9231 */
+ if( ms>0.999 ) ms = 0.999;
}
}else{
s = 0;
@@ -24640,8 +25418,8 @@ static void computeJD(DateTime *p){
Y--;
M += 12;
}
- A = Y/100;
- B = 2 - A + (A/4);
+ A = (Y+4800)/100;
+ B = 38 - A + (A/4);
X1 = 36525*(Y+4716)/100;
X2 = 306001*(M+1)/10000;
p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
@@ -24825,7 +25603,7 @@ static int validJulianDay(sqlite3_int64 iJD){
** Compute the Year, Month, and Day from the julian day number.
*/
static void computeYMD(DateTime *p){
- int Z, A, B, C, D, E, X1;
+ int Z, alpha, A, B, C, D, E, X1;
if( p->validYMD ) return;
if( !p->validJD ){
p->Y = 2000;
@@ -24836,8 +25614,8 @@ static void computeYMD(DateTime *p){
return;
}else{
Z = (int)((p->iJD + 43200000)/86400000);
- A = (int)((Z - 1867216.25)/36524.25);
- A = Z + 1 + A - (A/4);
+ alpha = (int)((Z + 32044.75)/36524.25) - 52;
+ A = Z + 1 + alpha - ((alpha+100)/4) + 25;
B = A + 1524;
C = (int)((B - 122.1)/365.25);
D = (36525*(C&32767))/100;
@@ -25036,8 +25814,8 @@ static const struct {
/* 1 */ { 6, "minute", 7.7379e+12, 60.0 },
/* 2 */ { 4, "hour", 1.2897e+11, 3600.0 },
/* 3 */ { 3, "day", 5373485.0, 86400.0 },
- /* 4 */ { 5, "month", 176546.0, 30.0*86400.0 },
- /* 5 */ { 4, "year", 14713.0, 365.0*86400.0 },
+ /* 4 */ { 5, "month", 176546.0, 2592000.0 },
+ /* 5 */ { 4, "year", 14713.0, 31536000.0 },
};
/*
@@ -25723,7 +26501,7 @@ static int daysAfterMonday(DateTime *pDate){
** In other words, return the day of the week according
** to this code:
**
-** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday
+** 0=Sunday, 1=Monday, 2=Tuesday, ..., 6=Saturday
*/
static int daysAfterSunday(DateTime *pDate){
assert( pDate->validJD );
@@ -25749,8 +26527,8 @@ static int daysAfterSunday(DateTime *pDate){
** %l hour 1-12 (leading zero converted to space)
** %m month 01-12
** %M minute 00-59
-** %p "am" or "pm"
-** %P "AM" or "PM"
+** %p "AM" or "PM"
+** %P "am" or "pm"
** %R time as HH:MM
** %s seconds since 1970-01-01
** %S seconds 00-59
@@ -25798,7 +26576,7 @@ static void strftimeFunc(
}
case 'f': { /* Fractional seconds. (Non-standard) */
double s = x.s;
- if( s>59.999 ) s = 59.999;
+ if( NEVER(s>59.999) ) s = 59.999;
sqlite3_str_appendf(&sRes, "%06.3f", s);
break;
}
@@ -29239,16 +30017,29 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
+**
+** Because these routines raise false-positive alerts in TSAN, disable
+** them (make them always return 1) when compiling with TSAN.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
+# if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+ p = 0;
+# endif
+# endif
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
+# if defined(__has_feature)
+# if __has_feature(thread_sanitizer)
+ p = 0;
+# endif
+# endif
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
-#endif
+#endif /* NDEBUG */
#endif /* !defined(SQLITE_MUTEX_OMIT) */
@@ -29919,6 +30710,8 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
#ifdef __CYGWIN__
# include
+# include /* amalgamator: dontcache */
+# include /* amalgamator: dontcache */
# include /* amalgamator: dontcache */
#endif
@@ -31319,17 +32112,17 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
#define etPERCENT 7 /* Percent symbol. %% */
#define etCHARX 8 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
-#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
-#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
- NULL pointers replaced by SQL NULL. %Q */
-#define etTOKEN 11 /* a pointer to a Token structure */
-#define etSRCITEM 12 /* a pointer to a SrcItem */
-#define etPOINTER 13 /* The %p conversion */
-#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
-#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
-#define etDECIMAL 16 /* %d or %u, but not %x, %o */
+#define etESCAPE_q 9 /* Strings with '\'' doubled. %q */
+#define etESCAPE_Q 10 /* Strings with '\'' doubled and enclosed in '',
+ NULL pointers replaced by SQL NULL. %Q */
+#define etTOKEN 11 /* a pointer to a Token structure */
+#define etSRCITEM 12 /* a pointer to a SrcItem */
+#define etPOINTER 13 /* The %p conversion */
+#define etESCAPE_w 14 /* %w -> Strings with '\"' doubled */
+#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
+#define etDECIMAL 16 /* %d or %u, but not %x, %o */
-#define etINVALID 17 /* Any unrecognized conversion type */
+#define etINVALID 17 /* Any unrecognized conversion type */
/*
@@ -31348,6 +32141,7 @@ typedef struct et_info { /* Information about each format field */
etByte type; /* Conversion paradigm */
etByte charset; /* Offset into aDigits[] of the digits string */
etByte prefix; /* Offset into aPrefix[] of the prefix string */
+ char iNxt; /* Next with same hash, or 0 for end of chain */
} et_info;
/*
@@ -31356,44 +32150,61 @@ typedef struct et_info { /* Information about each format field */
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_STRING 4 /* Allow infinite precision */
-
/*
-** The following table is searched linearly, so it is good to put the
-** most frequently used conversion types first.
+** The table is searched by hash. In the case of %C where C is the character
+** and that character has ASCII value j, then the hash is j%23.
+**
+** The order of the entries in fmtinfo[] and the hash chain was entered
+** manually, but based on the output of the following TCL script:
*/
+#if 0 /***** Beginning of script ******/
+foreach c {d s g z q Q w c o u x X f e E G i n % p T S r} {
+ scan $c %c x
+ set n($c) $x
+}
+set mx [llength [array names n]]
+puts "count: $mx"
+
+set mx 27
+puts "*********** mx=$mx ************"
+for {set r 0} {$r<$mx} {incr r} {
+ puts -nonewline [format %2d: $r]
+ foreach c [array names n] {
+ if {($n($c))%$mx==$r} {puts -nonewline " $c"}
+ }
+ puts ""
+}
+#endif /***** End of script ********/
+
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
-static const et_info fmtinfo[] = {
- { 'd', 10, 1, etDECIMAL, 0, 0 },
- { 's', 0, 4, etSTRING, 0, 0 },
- { 'g', 0, 1, etGENERIC, 30, 0 },
- { 'z', 0, 4, etDYNSTRING, 0, 0 },
- { 'q', 0, 4, etSQLESCAPE, 0, 0 },
- { 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
- { 'w', 0, 4, etSQLESCAPE3, 0, 0 },
- { 'c', 0, 0, etCHARX, 0, 0 },
- { 'o', 8, 0, etRADIX, 0, 2 },
- { 'u', 10, 0, etDECIMAL, 0, 0 },
- { 'x', 16, 0, etRADIX, 16, 1 },
- { 'X', 16, 0, etRADIX, 0, 4 },
-#ifndef SQLITE_OMIT_FLOATING_POINT
- { 'f', 0, 1, etFLOAT, 0, 0 },
- { 'e', 0, 1, etEXP, 30, 0 },
- { 'E', 0, 1, etEXP, 14, 0 },
- { 'G', 0, 1, etGENERIC, 14, 0 },
-#endif
- { 'i', 10, 1, etDECIMAL, 0, 0 },
- { 'n', 0, 0, etSIZE, 0, 0 },
- { '%', 0, 0, etPERCENT, 0, 0 },
- { 'p', 16, 0, etPOINTER, 0, 1 },
-
- /* All the rest are undocumented and are for internal use only */
- { 'T', 0, 0, etTOKEN, 0, 0 },
- { 'S', 0, 0, etSRCITEM, 0, 0 },
- { 'r', 10, 1, etORDINAL, 0, 0 },
+static const et_info fmtinfo[23] = {
+ /* 0 */ { 's', 0, 4, etSTRING, 0, 0, 1 },
+ /* 1 */ { 'E', 0, 1, etEXP, 14, 0, 0 }, /* Hash: 0 */
+ /* 2 */ { 'u', 10, 0, etDECIMAL, 0, 0, 3 },
+ /* 3 */ { 'G', 0, 1, etGENERIC, 14, 0, 0 }, /* Hash: 2 */
+ /* 4 */ { 'w', 0, 4, etESCAPE_w, 0, 0, 0 },
+ /* 5 */ { 'x', 16, 0, etRADIX, 16, 1, 0 },
+ /* 6 */ { 'c', 0, 0, etCHARX, 0, 0, 0 }, /* Hash: 7 */
+ /* 7 */ { 'z', 0, 4, etDYNSTRING, 0, 0, 6 },
+ /* 8 */ { 'd', 10, 1, etDECIMAL, 0, 0, 0 },
+ /* 9 */ { 'e', 0, 1, etEXP, 30, 0, 0 },
+ /* 10 */ { 'f', 0, 1, etFLOAT, 0, 0, 0 },
+ /* 11 */ { 'g', 0, 1, etGENERIC, 30, 0, 0 },
+ /* 12 */ { 'Q', 0, 4, etESCAPE_Q, 0, 0, 0 },
+ /* 13 */ { 'i', 10, 1, etDECIMAL, 0, 0, 0 },
+ /* 14 */ { '%', 0, 0, etPERCENT, 0, 0, 16 },
+ /* 15 */ { 'T', 0, 0, etTOKEN, 0, 0, 0 },
+ /* 16 */ { 'S', 0, 0, etSRCITEM, 0, 0, 0 }, /* Hash: 14 */
+ /* 17 */ { 'X', 16, 0, etRADIX, 0, 4, 0 }, /* Hash: 19 */
+ /* 18 */ { 'n', 0, 0, etSIZE, 0, 0, 0 },
+ /* 19 */ { 'o', 8, 0, etRADIX, 0, 2, 17 },
+ /* 20 */ { 'p', 16, 0, etPOINTER, 0, 1, 0 },
+ /* 21 */ { 'q', 0, 4, etESCAPE_q, 0, 0, 0 },
+ /* 22 */ { 'r', 10, 1, etORDINAL, 0, 0, 0 }
};
-/* Notes:
+/* Additional Notes:
**
** %S Takes a pointer to SrcItem. Shows name or database.name
** %!S Like %S but prefer the zName over the zAlias
@@ -31520,7 +32331,10 @@ SQLITE_API void sqlite3_str_vappendf(
#if HAVE_STRCHRNUL
fmt = strchrnul(fmt, '%');
#else
- do{ fmt++; }while( *fmt && *fmt != '%' );
+ fmt = strchr(fmt, '%');
+ if( fmt==0 ){
+ fmt = bufpt + strlen(bufpt);
+ }
#endif
sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt));
if( *fmt==0 ) break;
@@ -31634,6 +32448,9 @@ SQLITE_API void sqlite3_str_vappendf(
}while( !done && (c=(*++fmt))!=0 );
/* Fetch the info entry for the field */
+#ifdef SQLITE_EBCDIC
+ /* The hash table only works for ASCII. For EBCDIC, we need to do
+ ** a linear search of the table */
infop = &fmtinfo[0];
xtype = etINVALID;
for(idx=0; idxtype;
+ }else{
+ infop = &fmtinfo[0];
+ xtype = etINVALID;
+ }
+#endif
/*
** At this point, variables are initialized as follows:
@@ -31710,6 +32541,14 @@ SQLITE_API void sqlite3_str_vappendf(
}
prefix = 0;
}
+
+#if WHERETRACE_ENABLED
+ if( xtype==etPOINTER && sqlite3WhereTrace & 0x100000 ) longvalue = 0;
+#endif
+#if TREETRACE_ENABLED
+ if( xtype==etPOINTER && sqlite3TreeTrace & 0x100000 ) longvalue = 0;
+#endif
+
if( longvalue==0 ) flag_alternateform = 0;
if( flag_zeropad && precision>6)&0x1f);
- buf[1] = 0x80 + (u8)(ch & 0x3f);
- length = 2;
- }else if( ch<0x10000 ){
- buf[0] = 0xe0 + (u8)((ch>>12)&0x0f);
- buf[1] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[2] = 0x80 + (u8)(ch & 0x3f);
- length = 3;
- }else{
- buf[0] = 0xf0 + (u8)((ch>>18) & 0x07);
- buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
- buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
- buf[3] = 0x80 + (u8)(ch & 0x3f);
- length = 4;
- }
+ length = sqlite3AppendOneUtf8Character(buf, ch);
}
if( precision>1 ){
i64 nPrior = 1;
@@ -32065,22 +32900,31 @@ SQLITE_API void sqlite3_str_vappendf(
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
}
break;
- case etSQLESCAPE: /* %q: Escape ' characters */
- case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
- case etSQLESCAPE3: { /* %w: Escape " characters */
+ case etESCAPE_q: /* %q: Escape ' characters */
+ case etESCAPE_Q: /* %Q: Escape ' and enclose in '...' */
+ case etESCAPE_w: { /* %w: Escape " characters */
i64 i, j, k, n;
- int needQuote, isnull;
+ int needQuote = 0;
char ch;
- char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg;
+ char q;
if( bArgList ){
escarg = getTextArg(pArgList);
}else{
escarg = va_arg(ap,char*);
}
- isnull = escarg==0;
- if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
+ if( escarg==0 ){
+ escarg = (xtype==etESCAPE_Q ? "NULL" : "(NULL)");
+ }else if( xtype==etESCAPE_Q ){
+ needQuote = 1;
+ }
+ if( xtype==etESCAPE_w ){
+ q = '"';
+ flag_alternateform = 0;
+ }else{
+ q = '\'';
+ }
/* For %q, %Q, and %w, the precision is the number of bytes (or
** characters if the ! flags is present) to use from the input.
** Because of the extra quoting characters inserted, the number
@@ -32093,7 +32937,30 @@ SQLITE_API void sqlite3_str_vappendf(
while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
}
}
- needQuote = !isnull && xtype==etSQLESCAPE2;
+ if( flag_alternateform ){
+ /* For %#q, do unistr()-style backslash escapes for
+ ** all control characters, and for backslash itself.
+ ** For %#Q, do the same but only if there is at least
+ ** one control character. */
+ u32 nBack = 0;
+ u32 nCtrl = 0;
+ for(k=0; ketBUFSIZE ){
bufpt = zExtra = printfTempBuf(pAccum, n);
@@ -32102,13 +32969,41 @@ SQLITE_API void sqlite3_str_vappendf(
bufpt = buf;
}
j = 0;
- if( needQuote ) bufpt[j++] = q;
- k = i;
- for(i=0; i=0x10 ? '1' : '0';
+ bufpt[j++] = "0123456789abcdef"[ch&0xf];
+ }
+ }
+ }else{
+ for(i=0; izAlias && !flag_altform2 ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
}else if( pItem->zName ){
- if( pItem->zDatabase ){
- sqlite3_str_appendall(pAccum, pItem->zDatabase);
+ if( pItem->fg.fixedSchema==0
+ && pItem->fg.isSubquery==0
+ && pItem->u4.zDatabase!=0
+ ){
+ sqlite3_str_appendall(pAccum, pItem->u4.zDatabase);
sqlite3_str_append(pAccum, ".", 1);
}
sqlite3_str_appendall(pAccum, pItem->zName);
}else if( pItem->zAlias ){
sqlite3_str_appendall(pAccum, pItem->zAlias);
- }else{
- Select *pSel = pItem->pSelect;
- assert( pSel!=0 ); /* Because of tag-20240424-1 */
+ }else if( ALWAYS(pItem->fg.isSubquery) ){/* Because of tag-20240424-1 */
+ Select *pSel = pItem->u4.pSubq->pSelect;
+ assert( pSel!=0 );
if( pSel->selFlags & SF_NestedFrom ){
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
}else if( pSel->selFlags & SF_MultiValue ){
@@ -32229,6 +33127,7 @@ SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExp
pExpr = pExpr->pLeft;
}
if( pExpr==0 ) return;
+ if( ExprHasProperty(pExpr, EP_FromDDL) ) return;
db->errByteOffset = pExpr->w.iOfst;
}
@@ -32347,7 +33246,7 @@ SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){
static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
char *zText;
assert( p->mxAlloc>0 && !isMalloced(p) );
- zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
+ zText = sqlite3DbMallocRaw(p->db, 1+(u64)p->nChar );
if( zText ){
memcpy(zText, p->zText, p->nChar+1);
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
@@ -32592,6 +33491,15 @@ SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
return zBuf;
}
+/* Maximum size of an sqlite3_log() message. */
+#if defined(SQLITE_MAX_LOG_MESSAGE)
+ /* Leave the definition as supplied */
+#elif SQLITE_PRINT_BUF_SIZE*10>10000
+# define SQLITE_MAX_LOG_MESSAGE 10000
+#else
+# define SQLITE_MAX_LOG_MESSAGE (SQLITE_PRINT_BUF_SIZE*10)
+#endif
+
/*
** This is the routine that actually formats the sqlite3_log() message.
** We house it in a separate routine from sqlite3_log() to avoid using
@@ -32608,7 +33516,7 @@ SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
*/
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */
- char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
+ char zMsg[SQLITE_MAX_LOG_MESSAGE]; /* Complete log message */
sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
sqlite3_str_vappendf(&acc, zFormat, ap);
@@ -32933,9 +33841,9 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
- if( pItem->pTab ){
+ if( pItem->pSTab ){
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx%s",
- pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab,
+ pItem->pSTab->zName, pItem->pSTab->nCol, pItem->pSTab,
pItem->colUsed,
pItem->fg.rowidUsed ? "+rowid" : "");
}
@@ -32955,10 +33863,13 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
sqlite3_str_appendf(&x, " DDL");
}
if( pItem->fg.isCte ){
- sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
+ static const char *aMat[] = {",MAT", "", ",NO-MAT"};
+ sqlite3_str_appendf(&x, " CteUse=%d%s",
+ pItem->u2.pCteUse->nUse,
+ aMat[pItem->u2.pCteUse->eM10d]);
}
if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
- sqlite3_str_appendf(&x, " ON");
+ sqlite3_str_appendf(&x, " isOn");
}
if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
@@ -32966,25 +33877,31 @@ SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc)
if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte");
if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom");
+ if( pItem->fg.fixedSchema ) sqlite3_str_appendf(&x, " fixedSchema");
+ if( pItem->fg.hadSchema ) sqlite3_str_appendf(&x, " hadSchema");
+ if( pItem->fg.isSubquery ) sqlite3_str_appendf(&x, " isSubquery");
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, inSrc-1);
n = 0;
- if( pItem->pSelect ) n++;
+ if( pItem->fg.isSubquery ) n++;
if( pItem->fg.isTabFunc ) n++;
- if( pItem->fg.isUsing ) n++;
+ if( pItem->fg.isUsing || pItem->u3.pOn!=0 ) n++;
if( pItem->fg.isUsing ){
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
+ }else if( pItem->u3.pOn!=0 ){
+ sqlite3TreeViewItem(pView, "ON", (--n)>0);
+ sqlite3TreeViewExpr(pView, pItem->u3.pOn, 0);
+ sqlite3TreeViewPop(&pView);
}
- if( pItem->pSelect ){
- sqlite3TreeViewPush(&pView, i+1nSrc);
- if( pItem->pTab ){
- Table *pTab = pItem->pTab;
+ if( pItem->fg.isSubquery ){
+ assert( n==1 );
+ if( pItem->pSTab ){
+ Table *pTab = pItem->pSTab;
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
}
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
- sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
- sqlite3TreeViewPop(&pView);
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
+ sqlite3TreeViewSelect(pView, pItem->u4.pSubq->pSelect, 0);
}
if( pItem->fg.isTabFunc ){
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
@@ -33026,7 +33943,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
n = 1000;
}else{
n = 0;
- if( p->pSrc && p->pSrc->nSrc ) n++;
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
@@ -33052,7 +33969,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
sqlite3TreeViewPop(&pView);
}
#endif
- if( p->pSrc && p->pSrc->nSrc ){
+ if( p->pSrc && p->pSrc->nSrc && p->pSrc->nAlloc ){
sqlite3TreeViewPush(&pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
sqlite3TreeViewSrcList(pView, p->pSrc);
@@ -33560,7 +34477,8 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
case OE_Ignore: zType = "ignore"; break;
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
- sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
+ sqlite3TreeViewLine(pView, "RAISE %s", zType);
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif
@@ -33640,9 +34558,10 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; inExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
+ u8 sortFlags = pList->a[i].fg.sortFlags;
char *zName = pList->a[i].zEName;
int moreToFollow = inExpr - 1;
- if( j || zName ){
+ if( j || zName || sortFlags ){
sqlite3TreeViewPush(&pView, moreToFollow);
moreToFollow = 0;
sqlite3TreeViewLine(pView, 0);
@@ -33663,13 +34582,18 @@ SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
}
}
if( j ){
- fprintf(stdout, "iOrderByCol=%d", j);
+ fprintf(stdout, "iOrderByCol=%d ", j);
+ }
+ if( sortFlags & KEYINFO_ORDER_DESC ){
+ fprintf(stdout, "DESC ");
+ }else if( sortFlags & KEYINFO_ORDER_BIGNULL ){
+ fprintf(stdout, "NULLS-LAST");
}
fprintf(stdout, "\n");
fflush(stdout);
}
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
- if( j || zName ){
+ if( j || zName || sortFlags ){
sqlite3TreeViewPop(&pView);
}
}
@@ -33706,21 +34630,7 @@ SQLITE_PRIVATE void sqlite3TreeViewBareIdList(
if( zName==0 ) zName = "(null)";
sqlite3TreeViewPush(&pView, moreToFollow);
sqlite3TreeViewLine(pView, 0);
- if( pList->eU4==EU4_NONE ){
- fprintf(stdout, "%s\n", zName);
- }else if( pList->eU4==EU4_IDX ){
- fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx);
- }else{
- assert( pList->eU4==EU4_EXPR );
- if( pList->a[i].u4.pExpr==0 ){
- fprintf(stdout, "%s (pExpr=NULL)\n", zName);
- }else{
- fprintf(stdout, "%s\n", zName);
- sqlite3TreeViewPush(&pView, inId-1);
- sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0);
- sqlite3TreeViewPop(&pView);
- }
- }
+ fprintf(stdout, "%s\n", zName);
sqlite3TreeViewPop(&pView);
}
}
@@ -34030,6 +34940,10 @@ SQLITE_PRIVATE void sqlite3TreeViewTrigger(
** accessible to the debugging, and to avoid warnings about unused
** functions. But these routines only exist in debugging builds, so they
** do not contaminate the interface.
+**
+** See Also:
+**
+** sqlite3ShowWhereTerm() in where.c
*/
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
@@ -34601,6 +35515,35 @@ static const unsigned char sqlite3Utf8Trans1[] = {
} \
}
+/*
+** Write a single UTF8 character whose value is v into the
+** buffer starting at zOut. zOut must be sized to hold at
+** least four bytes. Return the number of bytes needed
+** to encode the new character.
+*/
+SQLITE_PRIVATE int sqlite3AppendOneUtf8Character(char *zOut, u32 v){
+ if( v<0x00080 ){
+ zOut[0] = (u8)(v & 0xff);
+ return 1;
+ }
+ if( v<0x00800 ){
+ zOut[0] = 0xc0 + (u8)((v>>6) & 0x1f);
+ zOut[1] = 0x80 + (u8)(v & 0x3f);
+ return 2;
+ }
+ if( v<0x10000 ){
+ zOut[0] = 0xe0 + (u8)((v>>12) & 0x0f);
+ zOut[1] = 0x80 + (u8)((v>>6) & 0x3f);
+ zOut[2] = 0x80 + (u8)(v & 0x3f);
+ return 3;
+ }
+ zOut[0] = 0xf0 + (u8)((v>>18) & 0x07);
+ zOut[1] = 0x80 + (u8)((v>>12) & 0x3f);
+ zOut[2] = 0x80 + (u8)((v>>6) & 0x3f);
+ zOut[3] = 0x80 + (u8)(v & 0x3f);
+ return 4;
+}
+
/*
** Translate a single UTF-8 character. Return the unicode value.
**
@@ -34632,7 +35575,7 @@ static const unsigned char sqlite3Utf8Trans1[] = {
c = *(zIn++); \
if( c>=0xc0 ){ \
c = sqlite3Utf8Trans1[c-0xc0]; \
- while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ while( zIn=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
+ if( c>=0xd8 && c<0xdc && z<=zEnd && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
n++;
}
return (int)(z-(unsigned char const *)zIn)
@@ -35604,6 +36549,8 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
int eValid = 1; /* True exponent is either not used or is well-formed */
int nDigit = 0; /* Number of digits processed */
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
+ u64 s2; /* round-tripped significand */
+ double rr[2];
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
@@ -35706,7 +36653,7 @@ do_atof_calc:
e = (e*esign) + d;
/* Try to adjust the exponent to make it smaller */
- while( e>0 && s<(LARGEST_UINT64/10) ){
+ while( e>0 && s<((LARGEST_UINT64-0x7ff)/10) ){
s *= 10;
e--;
}
@@ -35715,68 +36662,52 @@ do_atof_calc:
e++;
}
- if( e==0 ){
- *pResult = s;
- }else if( sqlite3Config.bUseLongDouble ){
- LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s;
- if( e>0 ){
- while( e>=100 ){ e-=100; r *= 1.0e+100L; }
- while( e>=10 ){ e-=10; r *= 1.0e+10L; }
- while( e>=1 ){ e-=1; r *= 1.0e+01L; }
- }else{
- while( e<=-100 ){ e+=100; r *= 1.0e-100L; }
- while( e<=-10 ){ e+=10; r *= 1.0e-10L; }
- while( e<=-1 ){ e+=1; r *= 1.0e-01L; }
- }
- assert( r>=0.0 );
- if( r>+1.7976931348623157081452742373e+308L ){
-#ifdef INFINITY
- *pResult = +INFINITY;
-#else
- *pResult = 1.0e308*10.0;
+ rr[0] = (double)s;
+ assert( sizeof(s2)==sizeof(rr[0]) );
+#ifdef SQLITE_DEBUG
+ rr[1] = 18446744073709549568.0;
+ memcpy(&s2, &rr[1], sizeof(s2));
+ assert( s2==0x43efffffffffffffLL );
#endif
- }else{
- *pResult = (double)r;
+ /* Largest double that can be safely converted to u64
+ ** vvvvvvvvvvvvvvvvvvvvvv */
+ if( rr[0]<=18446744073709549568.0 ){
+ s2 = (u64)rr[0];
+ rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
+ }else{
+ rr[1] = 0.0;
+ }
+ assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */
+
+ if( e>0 ){
+ while( e>=100 ){
+ e -= 100;
+ dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+ }
+ while( e>=10 ){
+ e -= 10;
+ dekkerMul2(rr, 1.0e+10, 0.0);
+ }
+ while( e>=1 ){
+ e -= 1;
+ dekkerMul2(rr, 1.0e+01, 0.0);
}
}else{
- double rr[2];
- u64 s2;
- rr[0] = (double)s;
- s2 = (u64)rr[0];
-#if defined(_MSC_VER) && _MSC_VER<1700
- if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
-#endif
- rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
- if( e>0 ){
- while( e>=100 ){
- e -= 100;
- dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
- }
- while( e>=10 ){
- e -= 10;
- dekkerMul2(rr, 1.0e+10, 0.0);
- }
- while( e>=1 ){
- e -= 1;
- dekkerMul2(rr, 1.0e+01, 0.0);
- }
- }else{
- while( e<=-100 ){
- e += 100;
- dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
- }
- while( e<=-10 ){
- e += 10;
- dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
- }
- while( e<=-1 ){
- e += 1;
- dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
- }
+ while( e<=-100 ){
+ e += 100;
+ dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+ }
+ while( e<=-10 ){
+ e += 10;
+ dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+ }
+ while( e<=-1 ){
+ e += 1;
+ dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
}
- *pResult = rr[0]+rr[1];
- if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
}
+ *pResult = rr[0]+rr[1];
+ if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
if( sign<0 ) *pResult = -*pResult;
assert( !sqlite3IsNaN(*pResult) );
@@ -36080,10 +37011,13 @@ SQLITE_PRIVATE int sqlite3Atoi(const char *z){
** Decode a floating-point value into an approximate decimal
** representation.
**
-** Round the decimal representation to n significant digits if
-** n is positive. Or round to -n signficant digits after the
-** decimal point if n is negative. No rounding is performed if
-** n is zero.
+** If iRound<=0 then round to -iRound significant digits to the
+** the left of the decimal point, or to a maximum of mxRound total
+** significant digits.
+**
+** If iRound>0 round to min(iRound,mxRound) significant digits total.
+**
+** mxRound must be positive.
**
** The significant digits of the decimal representation are
** stored in p->z[] which is a often (but not always) a pointer
@@ -36094,8 +37028,11 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
int i;
u64 v;
int e, exp = 0;
+ double rr[2];
+
p->isSpecial = 0;
p->z = p->zBuf;
+ assert( mxRound>0 );
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
** NaN. */
@@ -36122,62 +37059,45 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
/* Multiply r by powers of ten until it lands somewhere in between
** 1.0e+19 and 1.0e+17.
+ **
+ ** Use Dekker-style double-double computation to increase the
+ ** precision.
+ **
+ ** The error terms on constants like 1.0e+100 computed using the
+ ** decimal extension, for example as follows:
+ **
+ ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
*/
- if( sqlite3Config.bUseLongDouble ){
- LONGDOUBLE_TYPE rr = r;
- if( rr>=1.0e+19 ){
- while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; }
- while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; }
- while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; }
- }else{
- while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; }
- while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; }
- while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; }
+ rr[0] = r;
+ rr[1] = 0.0;
+ if( rr[0]>9.223372036854774784e+18 ){
+ while( rr[0]>9.223372036854774784e+118 ){
+ exp += 100;
+ dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
+ }
+ while( rr[0]>9.223372036854774784e+28 ){
+ exp += 10;
+ dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
+ }
+ while( rr[0]>9.223372036854774784e+18 ){
+ exp += 1;
+ dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
}
- v = (u64)rr;
}else{
- /* If high-precision floating point is not available using "long double",
- ** then use Dekker-style double-double computation to increase the
- ** precision.
- **
- ** The error terms on constants like 1.0e+100 computed using the
- ** decimal extension, for example as follows:
- **
- ** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
- */
- double rr[2];
- rr[0] = r;
- rr[1] = 0.0;
- if( rr[0]>9.223372036854774784e+18 ){
- while( rr[0]>9.223372036854774784e+118 ){
- exp += 100;
- dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
- }
- while( rr[0]>9.223372036854774784e+28 ){
- exp += 10;
- dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
- }
- while( rr[0]>9.223372036854774784e+18 ){
- exp += 1;
- dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
- }
- }else{
- while( rr[0]<9.223372036854774784e-83 ){
- exp -= 100;
- dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
- }
- while( rr[0]<9.223372036854774784e+07 ){
- exp -= 10;
- dekkerMul2(rr, 1.0e+10, 0.0);
- }
- while( rr[0]<9.22337203685477478e+17 ){
- exp -= 1;
- dekkerMul2(rr, 1.0e+01, 0.0);
- }
+ while( rr[0]<9.223372036854774784e-83 ){
+ exp -= 100;
+ dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
+ }
+ while( rr[0]<9.223372036854774784e+07 ){
+ exp -= 10;
+ dekkerMul2(rr, 1.0e+10, 0.0);
+ }
+ while( rr[0]<9.22337203685477478e+17 ){
+ exp -= 1;
+ dekkerMul2(rr, 1.0e+01, 0.0);
}
- v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
}
-
+ v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
/* Extract significant digits. */
i = sizeof(p->zBuf)-1;
@@ -36220,7 +37140,11 @@ SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRou
}
p->z = &p->zBuf[i+1];
assert( i+p->n < sizeof(p->zBuf) );
- while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; }
+ assert( p->n>0 );
+ while( p->z[p->n-1]=='0' ){
+ p->n--;
+ assert( p->n>0 );
+ }
}
/*
@@ -36725,7 +37649,7 @@ SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
}
/*
-** Compute the absolute value of a 32-bit signed integer, of possible. Or
+** Compute the absolute value of a 32-bit signed integer, if possible. Or
** if the integer has a value of -2147483648, return +2147483647
*/
SQLITE_PRIVATE int sqlite3AbsInt32(int x){
@@ -36948,104 +37872,6 @@ SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nNam
return 0;
}
-/*
-** High-resolution hardware timer used for debugging and testing only.
-*/
-#if defined(VDBE_PROFILE) \
- || defined(SQLITE_PERFORMANCE_TRACE) \
- || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-/************** Include hwtime.h in the middle of util.c *********************/
-/************** Begin file hwtime.h ******************************************/
-/*
-** 2008 May 27
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 and x86_64 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_HWTIME_H
-
-/*
-** The following routine only works on Pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if !defined(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long long retval;
- unsigned long junk;
- __asm__ __volatile__ ("\n\
- 1: mftbu %1\n\
- mftb %L0\n\
- mftbu %0\n\
- cmpw %0,%1\n\
- bne 1b"
- : "=r" (retval), "=r" (junk));
- return retval;
- }
-
-#else
-
- /*
- ** asm() is needed for hardware timing support. Without asm(),
- ** disable the sqlite3Hwtime() routine.
- **
- ** sqlite3Hwtime() is only used for some obscure debugging
- ** and analysis configurations, not in any deliverable, so this
- ** should not be a great loss.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
-
-/************** End of hwtime.h **********************************************/
-/************** Continuing where we left off in util.c ***********************/
-#endif
-
/************** End of util.c ************************************************/
/************** Begin file hash.c ********************************************/
/*
@@ -37104,12 +37930,19 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
*/
static unsigned int strHash(const char *z){
unsigned int h = 0;
- unsigned char c;
- while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
+ while( z[0] ){ /*OPTIMIZATION-IF-TRUE*/
/* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
** 0x9e3779b1 is 2654435761 which is the closest prime number to
- ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
- h += sqlite3UpperToLower[c];
+ ** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2.
+ **
+ ** Only bits 0xdf for ASCII and bits 0xbf for EBCDIC each octet are
+ ** hashed since the omitted bits determine the upper/lower case difference.
+ */
+#ifdef SQLITE_EBCDIC
+ h += 0xbf & (unsigned char)*(z++);
+#else
+ h += 0xdf & (unsigned char)*(z++);
+#endif
h *= 0x9e3779b1;
}
return h;
@@ -37182,9 +38015,8 @@ static int rehash(Hash *pH, unsigned int new_size){
pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
memset(new_ht, 0, new_size*sizeof(struct _ht));
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- unsigned int h = strHash(elem->pKey) % new_size;
next_elem = elem->next;
- insertElement(pH, &new_ht[h], elem);
+ insertElement(pH, &new_ht[elem->h % new_size], elem);
}
return 1;
}
@@ -37202,23 +38034,22 @@ static HashElem *findElementWithHash(
HashElem *elem; /* Used to loop thru the element list */
unsigned int count; /* Number of elements left to test */
unsigned int h; /* The computed hash */
- static HashElem nullElement = { 0, 0, 0, 0 };
+ static HashElem nullElement = { 0, 0, 0, 0, 0 };
+ h = strHash(pKey);
if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
struct _ht *pEntry;
- h = strHash(pKey) % pH->htsize;
- pEntry = &pH->ht[h];
+ pEntry = &pH->ht[h % pH->htsize];
elem = pEntry->chain;
count = pEntry->count;
}else{
- h = 0;
elem = pH->first;
count = pH->count;
}
if( pHash ) *pHash = h;
while( count ){
assert( elem!=0 );
- if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
+ if( h==elem->h && sqlite3StrICmp(elem->pKey,pKey)==0 ){
return elem;
}
elem = elem->next;
@@ -37230,10 +38061,9 @@ static HashElem *findElementWithHash(
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
-static void removeElementGivenHash(
+static void removeElement(
Hash *pH, /* The pH containing "elem" */
- HashElem* elem, /* The element to be removed from the pH */
- unsigned int h /* Hash value for the element */
+ HashElem *elem /* The element to be removed from the pH */
){
struct _ht *pEntry;
if( elem->prev ){
@@ -37245,7 +38075,7 @@ static void removeElementGivenHash(
elem->next->prev = elem->prev;
}
if( pH->ht ){
- pEntry = &pH->ht[h];
+ pEntry = &pH->ht[elem->h % pH->htsize];
if( pEntry->chain==elem ){
pEntry->chain = elem->next;
}
@@ -37296,7 +38126,7 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
if( elem->data ){
void *old_data = elem->data;
if( data==0 ){
- removeElementGivenHash(pH,elem,h);
+ removeElement(pH,elem);
}else{
elem->data = data;
elem->pKey = pKey;
@@ -37307,18 +38137,17 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
new_elem->pKey = pKey;
+ new_elem->h = h;
new_elem->data = data;
pH->count++;
- if( pH->count>=10 && pH->count > 2*pH->htsize ){
- if( rehash(pH, pH->count*2) ){
- assert( pH->htsize>0 );
- h = strHash(pKey) % pH->htsize;
- }
+ if( pH->count>=5 && pH->count > 2*pH->htsize ){
+ rehash(pH, pH->count*3);
}
- insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem);
+ insertElement(pH, pH->ht ? &pH->ht[new_elem->h % pH->htsize] : 0, new_elem);
return 0;
}
+
/************** End of hash.c ************************************************/
/************** Begin file opcodes.c *****************************************/
/* Automatically generated. Do not edit */
@@ -37370,159 +38199,160 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 34 */ "SorterSort" OpHelp(""),
/* 35 */ "Sort" OpHelp(""),
/* 36 */ "Rewind" OpHelp(""),
- /* 37 */ "SorterNext" OpHelp(""),
- /* 38 */ "Prev" OpHelp(""),
- /* 39 */ "Next" OpHelp(""),
- /* 40 */ "IdxLE" OpHelp("key=r[P3@P4]"),
- /* 41 */ "IdxGT" OpHelp("key=r[P3@P4]"),
- /* 42 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 37 */ "IfEmpty" OpHelp("if( empty(P1) ) goto P2"),
+ /* 38 */ "SorterNext" OpHelp(""),
+ /* 39 */ "Prev" OpHelp(""),
+ /* 40 */ "Next" OpHelp(""),
+ /* 41 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 42 */ "IdxGT" OpHelp("key=r[P3@P4]"),
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"),
- /* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
- /* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
- /* 48 */ "Program" OpHelp(""),
- /* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
- /* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
- /* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
- /* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
- /* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
- /* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
- /* 56 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
- /* 58 */ "ElseEq" OpHelp(""),
- /* 59 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
- /* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
- /* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
- /* 62 */ "IncrVacuum" OpHelp(""),
- /* 63 */ "VNext" OpHelp(""),
- /* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
- /* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
- /* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
- /* 67 */ "Return" OpHelp(""),
- /* 68 */ "EndCoroutine" OpHelp(""),
- /* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
- /* 70 */ "Halt" OpHelp(""),
- /* 71 */ "Integer" OpHelp("r[P2]=P1"),
- /* 72 */ "Int64" OpHelp("r[P2]=P4"),
- /* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
- /* 74 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
- /* 75 */ "Null" OpHelp("r[P2..P3]=NULL"),
- /* 76 */ "SoftNull" OpHelp("r[P1]=NULL"),
- /* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1)"),
- /* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
- /* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"),
- /* 82 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
- /* 83 */ "FkCheck" OpHelp(""),
- /* 84 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 85 */ "CollSeq" OpHelp(""),
- /* 86 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 87 */ "RealAffinity" OpHelp(""),
- /* 88 */ "Cast" OpHelp("affinity(r[P1])"),
- /* 89 */ "Permutation" OpHelp(""),
- /* 90 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
- /* 91 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
- /* 92 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
- /* 93 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
- /* 94 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"),
- /* 95 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
- /* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 98 */ "Count" OpHelp("r[P2]=count()"),
- /* 99 */ "ReadCookie" OpHelp(""),
- /* 100 */ "SetCookie" OpHelp(""),
- /* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
- /* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
- /* 115 */ "OpenDup" OpHelp(""),
- /* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 117 */ "String8" OpHelp("r[P2]='P4'"),
- /* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 119 */ "SorterOpen" OpHelp(""),
- /* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 122 */ "Close" OpHelp(""),
- /* 123 */ "ColumnsUsed" OpHelp(""),
- /* 124 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
- /* 125 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
- /* 126 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 127 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 129 */ "RowCell" OpHelp(""),
- /* 130 */ "Delete" OpHelp(""),
- /* 131 */ "ResetCount" OpHelp(""),
- /* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 133 */ "SorterData" OpHelp("r[P2]=data"),
- /* 134 */ "RowData" OpHelp("r[P2]=data"),
- /* 135 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
- /* 136 */ "NullRow" OpHelp(""),
- /* 137 */ "SeekEnd" OpHelp(""),
- /* 138 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 139 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 140 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 141 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 142 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 143 */ "FinishSeek" OpHelp(""),
- /* 144 */ "Destroy" OpHelp(""),
- /* 145 */ "Clear" OpHelp(""),
- /* 146 */ "ResetSorter" OpHelp(""),
- /* 147 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
- /* 148 */ "SqlExec" OpHelp(""),
- /* 149 */ "ParseSchema" OpHelp(""),
- /* 150 */ "LoadAnalysis" OpHelp(""),
- /* 151 */ "DropTable" OpHelp(""),
- /* 152 */ "DropIndex" OpHelp(""),
- /* 153 */ "Real" OpHelp("r[P2]=P4"),
- /* 154 */ "DropTrigger" OpHelp(""),
- /* 155 */ "IntegrityCk" OpHelp(""),
- /* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 157 */ "Param" OpHelp(""),
- /* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 160 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 161 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
- /* 162 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 163 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 164 */ "AggValue" OpHelp("r[P3]=value N=P2"),
- /* 165 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 166 */ "Expire" OpHelp(""),
- /* 167 */ "CursorLock" OpHelp(""),
- /* 168 */ "CursorUnlock" OpHelp(""),
- /* 169 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 170 */ "VBegin" OpHelp(""),
- /* 171 */ "VCreate" OpHelp(""),
- /* 172 */ "VDestroy" OpHelp(""),
- /* 173 */ "VOpen" OpHelp(""),
- /* 174 */ "VCheck" OpHelp(""),
- /* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
- /* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 177 */ "VRename" OpHelp(""),
- /* 178 */ "Pagecount" OpHelp(""),
- /* 179 */ "MaxPgcnt" OpHelp(""),
- /* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
- /* 181 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"),
- /* 182 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"),
- /* 183 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
- /* 184 */ "Trace" OpHelp(""),
- /* 185 */ "CursorHint" OpHelp(""),
- /* 186 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
- /* 187 */ "Noop" OpHelp(""),
- /* 188 */ "Explain" OpHelp(""),
- /* 189 */ "Abortable" OpHelp(""),
+ /* 45 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 46 */ "IdxGE" OpHelp("key=r[P3@P4]"),
+ /* 47 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 48 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 49 */ "Program" OpHelp(""),
+ /* 50 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 51 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
+ /* 52 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
+ /* 53 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
+ /* 54 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
+ /* 55 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
+ /* 56 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
+ /* 57 */ "Lt" OpHelp("IF r[P3]=r[P1]"),
+ /* 59 */ "ElseEq" OpHelp(""),
+ /* 60 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+ /* 61 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+ /* 62 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 63 */ "IncrVacuum" OpHelp(""),
+ /* 64 */ "VNext" OpHelp(""),
+ /* 65 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
+ /* 66 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
+ /* 67 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
+ /* 68 */ "Return" OpHelp(""),
+ /* 69 */ "EndCoroutine" OpHelp(""),
+ /* 70 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 71 */ "Halt" OpHelp(""),
+ /* 72 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 73 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 74 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 75 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
+ /* 76 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 77 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 78 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 79 */ "Variable" OpHelp("r[P2]=parameter(P1)"),
+ /* 80 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 81 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 82 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 83 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 84 */ "FkCheck" OpHelp(""),
+ /* 85 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 86 */ "CollSeq" OpHelp(""),
+ /* 87 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 88 */ "RealAffinity" OpHelp(""),
+ /* 89 */ "Cast" OpHelp("affinity(r[P1])"),
+ /* 90 */ "Permutation" OpHelp(""),
+ /* 91 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 92 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
+ /* 93 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
+ /* 94 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 95 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"),
+ /* 96 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
+ /* 97 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 98 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 99 */ "Count" OpHelp("r[P2]=count()"),
+ /* 100 */ "ReadCookie" OpHelp(""),
+ /* 101 */ "SetCookie" OpHelp(""),
+ /* 102 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 103 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 104 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 105 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<>r[P1]"),
+ /* 107 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 108 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 109 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 110 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 111 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 112 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 113 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 114 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 115 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
+ /* 116 */ "OpenDup" OpHelp(""),
+ /* 117 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 118 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 119 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 120 */ "SorterOpen" OpHelp(""),
+ /* 121 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 122 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 123 */ "Close" OpHelp(""),
+ /* 124 */ "ColumnsUsed" OpHelp(""),
+ /* 125 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
+ /* 126 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
+ /* 127 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 128 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 129 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 130 */ "RowCell" OpHelp(""),
+ /* 131 */ "Delete" OpHelp(""),
+ /* 132 */ "ResetCount" OpHelp(""),
+ /* 133 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 134 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 135 */ "RowData" OpHelp("r[P2]=data"),
+ /* 136 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
+ /* 137 */ "NullRow" OpHelp(""),
+ /* 138 */ "SeekEnd" OpHelp(""),
+ /* 139 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 140 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 141 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 142 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 143 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 144 */ "FinishSeek" OpHelp(""),
+ /* 145 */ "Destroy" OpHelp(""),
+ /* 146 */ "Clear" OpHelp(""),
+ /* 147 */ "ResetSorter" OpHelp(""),
+ /* 148 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 149 */ "SqlExec" OpHelp(""),
+ /* 150 */ "ParseSchema" OpHelp(""),
+ /* 151 */ "LoadAnalysis" OpHelp(""),
+ /* 152 */ "DropTable" OpHelp(""),
+ /* 153 */ "DropIndex" OpHelp(""),
+ /* 154 */ "Real" OpHelp("r[P2]=P4"),
+ /* 155 */ "DropTrigger" OpHelp(""),
+ /* 156 */ "IntegrityCk" OpHelp(""),
+ /* 157 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 158 */ "Param" OpHelp(""),
+ /* 159 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 160 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 161 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 162 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
+ /* 163 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 164 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 165 */ "AggValue" OpHelp("r[P3]=value N=P2"),
+ /* 166 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 167 */ "Expire" OpHelp(""),
+ /* 168 */ "CursorLock" OpHelp(""),
+ /* 169 */ "CursorUnlock" OpHelp(""),
+ /* 170 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 171 */ "VBegin" OpHelp(""),
+ /* 172 */ "VCreate" OpHelp(""),
+ /* 173 */ "VDestroy" OpHelp(""),
+ /* 174 */ "VOpen" OpHelp(""),
+ /* 175 */ "VCheck" OpHelp(""),
+ /* 176 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
+ /* 177 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 178 */ "VRename" OpHelp(""),
+ /* 179 */ "Pagecount" OpHelp(""),
+ /* 180 */ "MaxPgcnt" OpHelp(""),
+ /* 181 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
+ /* 182 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"),
+ /* 183 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"),
+ /* 184 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
+ /* 185 */ "Trace" OpHelp(""),
+ /* 186 */ "CursorHint" OpHelp(""),
+ /* 187 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 188 */ "Noop" OpHelp(""),
+ /* 189 */ "Explain" OpHelp(""),
+ /* 190 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -37706,7 +38536,7 @@ static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
#define KVSTORAGE_KEY_SZ 32
/* Expand the key name with an appropriate prefix and put the result
-** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
+** in zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
** KVSTORAGE_KEY_SZ bytes.
*/
static void kvstorageMakeKey(
@@ -37765,10 +38595,12 @@ static int kvstorageDelete(const char *zClass, const char *zKey){
**
** Return the total number of bytes in the data, without truncation, and
** not counting the final zero terminator. Return -1 if the key does
-** not exist.
+** not exist or its key cannot be read.
**
-** If nBuf<=0 then this routine simply returns the size of the data without
-** actually reading it.
+** If nBuf<=0 then this routine simply returns the size of the data
+** without actually reading it. Similarly, if nBuf==1 then it
+** zero-terminates zBuf at zBuf[0] and returns the size of the data
+** without reading it.
*/
static int kvstorageRead(
const char *zClass,
@@ -37817,11 +38649,9 @@ static int kvstorageRead(
** kvvfs i/o methods with JavaScript implementations in WASM builds.
** Maintenance reminder: if this struct changes in any way, the JSON
** rendering of its structure must be updated in
-** sqlite3_wasm_enum_json(). There are no binary compatibility
-** concerns, so it does not need an iVersion member. This file is
-** necessarily always compiled together with sqlite3_wasm_enum_json(),
-** and JS code dynamically creates the mapping of members based on
-** that JSON description.
+** sqlite3-wasm.c:sqlite3__wasm_enum_json(). There are no binary
+** compatibility concerns, so it does not need an iVersion
+** member.
*/
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
struct sqlite3_kvvfs_methods {
@@ -37838,8 +38668,8 @@ struct sqlite3_kvvfs_methods {
** the compiler can hopefully optimize this level of indirection out.
** That said, kvvfs is intended primarily for use in WASM builds.
**
-** Note that this is not explicitly flagged as static because the
-** amalgamation build will tag it with SQLITE_PRIVATE.
+** This is not explicitly flagged as static because the amalgamation
+** build will tag it with SQLITE_PRIVATE.
*/
#ifndef SQLITE_WASM
const
@@ -38731,7 +39561,7 @@ SQLITE_PRIVATE int sqlite3KvvfsInit(void){
# endif
#else /* !SQLITE_WASI */
# ifndef HAVE_FCHMOD
-# define HAVE_FCHMOD
+# define HAVE_FCHMOD 1
# endif
#endif /* SQLITE_WASI */
@@ -38802,6 +39632,7 @@ struct unixFile {
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
unsigned iBusyTimeout; /* Wait this many millisec on locks */
+ int bBlockOnConnect; /* True to block for SHARED locks */
#endif
#if OS_VXWORKS
struct vxworksFileId *pId; /* Unique file ID */
@@ -38840,7 +39671,7 @@ static pid_t randomnessPid = 0;
#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
-#ifndef SQLITE_DISABLE_DIRSYNC
+#if !defined(SQLITE_DISABLE_DIRSYNC) && !defined(_AIX)
# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
#else
# define UNIXFILE_DIRSYNC 0x00
@@ -39015,10 +39846,11 @@ static struct unix_syscall {
#if defined(HAVE_FCHMOD)
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
+#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
#else
{ "fchmod", (sqlite3_syscall_ptr)0, 0 },
+#define osFchmod(FID,MODE) 0
#endif
-#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
{ "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
@@ -39112,6 +39944,119 @@ static struct unix_syscall {
}; /* End of the overrideable system calls */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+/*
+** Extract Posix Advisory Locking information about file description fd
+** from the /proc/PID/fdinfo/FD pseudo-file. Fill the string buffer a[16]
+** with characters to indicate which SQLite-relevant locks are held.
+** a[16] will be a 15-character zero-terminated string with the following
+** schema:
+**
+** AAA/B.DDD.DDDDD
+**
+** Each of character A-D will be "w" or "r" or "-" to indicate either a
+** write-lock, a read-lock, or no-lock, respectively. The "." and "/"
+** characters are delimiters intended to make the string more easily
+** readable by humans. Here are the meaning of the specific letters:
+**
+** AAA -> The main database locks. PENDING_BYTE, RESERVED_BYTE,
+** and SHARED_FIRST, respectively.
+**
+** B -> The deadman switch lock. Offset 128 of the -shm file.
+**
+** CCC -> WAL locks: WRITE, CKPT, RECOVER
+**
+** DDDDD -> WAL read-locks 0 through 5
+**
+** Note that elements before the "/" apply to the main database file and
+** elements after the "/" apply to the -shm file in WAL mode.
+**
+** Here is another way of thinking about the meaning of the result string:
+**
+** AAA/B.CCC.DDDDD
+** ||| | ||| \___/
+** PENDING--'|| | ||| `----- READ 0-5
+** RESERVED--'| | ||`---- RECOVER
+** SHARED ----' | |`----- CKPT
+** DMS ------' `------ WRITE
+**
+** Return SQLITE_OK on success and SQLITE_ERROR_UNABLE if the /proc
+** pseudo-filesystem is unavailable.
+*/
+static int unixPosixAdvisoryLocks(
+ int fd, /* The file descriptor to analyze */
+ char a[16] /* Write a text description of PALs here */
+){
+ int in;
+ ssize_t n;
+ char *p, *pNext, *x;
+ char z[2000];
+
+ /* 1 */
+ /* 012 4 678 01234 */
+ memcpy(a, "---/-.---.-----", 16);
+ sqlite3_snprintf(sizeof(z), z, "/proc/%d/fdinfo/%d", getpid(), fd);
+ in = osOpen(z, O_RDONLY, 0);
+ if( in<0 ){
+ return SQLITE_ERROR_UNABLE;
+ }
+ n = osRead(in, z, sizeof(z)-1);
+ osClose(in);
+ if( n<=0 ) return SQLITE_ERROR_UNABLE;
+ z[n] = 0;
+
+ /* We are looking for lines that begin with "lock:\t". Examples:
+ **
+ ** lock: 1: POSIX ADVISORY READ 494716 08:02:5277597 1073741826 1073742335
+ ** lock: 1: POSIX ADVISORY WRITE 494716 08:02:5282282 120 120
+ ** lock: 2: POSIX ADVISORY READ 494716 08:02:5282282 123 123
+ ** lock: 3: POSIX ADVISORY READ 494716 08:02:5282282 128 128
+ */
+ pNext = strstr(z, "lock:\t");
+ while( pNext ){
+ char cType = 0;
+ sqlite3_int64 iFirst, iLast;
+ p = pNext+6;
+ pNext = strstr(p, "lock:\t");
+ if( pNext ) pNext[-1] = 0;
+ if( (x = strstr(p, " READ "))!=0 ){
+ cType = 'r';
+ x += 6;
+ }else if( (x = strstr(p, " WRITE "))!=0 ){
+ cType = 'w';
+ x += 7;
+ }else{
+ continue;
+ }
+ x = strrchr(x, ' ');
+ if( x==0 ) continue;
+ iLast = strtoll(x+1, 0, 10);
+ *x = 0;
+ x = strrchr(p, ' ');
+ if( x==0 ) continue;
+ iFirst = strtoll(x+1, 0, 10);
+ if( iLast>=PENDING_BYTE ){
+ if( iFirst<=PENDING_BYTE && iLast>=PENDING_BYTE ) a[0] = cType;
+ if( iFirst<=PENDING_BYTE+1 && iLast>=PENDING_BYTE+1 ) a[1] = cType;
+ if( iFirst<=PENDING_BYTE+2 && iLast>=PENDING_BYTE+510 ) a[2] = cType;
+ }else if( iLast<=128 ){
+ if( iFirst<=128 && iLast>=128 ) a[4] = cType;
+ if( iFirst<=120 && iLast>=120 ) a[6] = cType;
+ if( iFirst<=121 && iLast>=121 ) a[7] = cType;
+ if( iFirst<=122 && iLast>=122 ) a[8] = cType;
+ if( iFirst<=123 && iLast>=123 ) a[10] = cType;
+ if( iFirst<=124 && iLast>=124 ) a[11] = cType;
+ if( iFirst<=125 && iLast>=125 ) a[12] = cType;
+ if( iFirst<=126 && iLast>=126 ) a[13] = cType;
+ if( iFirst<=127 && iLast>=127 ) a[14] = cType;
+ }
+ }
+ return SQLITE_OK;
+}
+#else
+# define unixPosixAdvisoryLocks(A,B) SQLITE_ERROR_UNABLE
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
+
/*
** On some systems, calls to fchown() will trigger a message in a security
** log if they come from non-root processes. So avoid calling fchown() if
@@ -39276,9 +40221,8 @@ static int robust_open(const char *z, int f, mode_t m){
/*
** Helper functions to obtain and relinquish the global mutex. The
-** global mutex is used to protect the unixInodeInfo and
-** vxworksFileId objects used by this file, all of which may be
-** shared by multiple threads.
+** global mutex is used to protect the unixInodeInfo objects used by
+** this file, all of which may be shared by multiple threads.
**
** Function unixMutexHeld() is used to assert() that the global mutex
** is held when required. This function is only used as part of assert()
@@ -39480,6 +40424,7 @@ struct vxworksFileId {
** variable:
*/
static struct vxworksFileId *vxworksFileList = 0;
+static sqlite3_mutex *vxworksMutex = 0;
/*
** Simplify a filename into its canonical form
@@ -39545,14 +40490,14 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
** If found, increment the reference count and return a pointer to
** the existing file ID.
*/
- unixEnterMutex();
+ sqlite3_mutex_enter(vxworksMutex);
for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
if( pCandidate->nName==n
&& memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
){
sqlite3_free(pNew);
pCandidate->nRef++;
- unixLeaveMutex();
+ sqlite3_mutex_leave(vxworksMutex);
return pCandidate;
}
}
@@ -39562,7 +40507,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
pNew->nName = n;
pNew->pNext = vxworksFileList;
vxworksFileList = pNew;
- unixLeaveMutex();
+ sqlite3_mutex_leave(vxworksMutex);
return pNew;
}
@@ -39571,7 +40516,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
** the object when the reference count reaches zero.
*/
static void vxworksReleaseFileId(struct vxworksFileId *pId){
- unixEnterMutex();
+ sqlite3_mutex_enter(vxworksMutex);
assert( pId->nRef>0 );
pId->nRef--;
if( pId->nRef==0 ){
@@ -39581,7 +40526,7 @@ static void vxworksReleaseFileId(struct vxworksFileId *pId){
*pp = pId->pNext;
sqlite3_free(pId);
}
- unixLeaveMutex();
+ sqlite3_mutex_leave(vxworksMutex);
}
#endif /* OS_VXWORKS */
/*************** End of Unique File ID Utility Used By VxWorks ****************
@@ -39969,6 +40914,10 @@ static int findInodeInfo(
storeLastErrno(pFile, errno);
return SQLITE_IOERR;
}
+ if( fsync(fd) ){
+ storeLastErrno(pFile, errno);
+ return SQLITE_IOERR_FSYNC;
+ }
rc = osFstat(fd, &statbuf);
if( rc!=0 ){
storeLastErrno(pFile, errno);
@@ -40138,18 +41087,42 @@ static int osSetPosixAdvisoryLock(
struct flock *pLock, /* The description of the lock */
unixFile *pFile /* Structure holding timeout value */
){
- int tm = pFile->iBusyTimeout;
- int rc = osFcntl(h,F_SETLK,pLock);
- while( rc<0 && tm>0 ){
- /* On systems that support some kind of blocking file lock with a timeout,
- ** make appropriate changes here to invoke that blocking file lock. On
- ** generic posix, however, there is no such API. So we simply try the
- ** lock once every millisecond until either the timeout expires, or until
- ** the lock is obtained. */
- unixSleep(0,1000);
+ int rc = 0;
+
+ if( pFile->iBusyTimeout==0 ){
+ /* unixFile->iBusyTimeout is set to 0. In this case, attempt a
+ ** non-blocking lock. */
rc = osFcntl(h,F_SETLK,pLock);
- tm--;
+ }else{
+ /* unixFile->iBusyTimeout is set to greater than zero. In this case,
+ ** attempt a blocking-lock with a unixFile->iBusyTimeout ms timeout.
+ **
+ ** On systems that support some kind of blocking file lock operation,
+ ** this block should be replaced by code to attempt a blocking lock
+ ** with a timeout of unixFile->iBusyTimeout ms. The code below is
+ ** placeholder code. If SQLITE_TEST is defined, the placeholder code
+ ** retries the lock once every 1ms until it succeeds or the timeout
+ ** is reached. Or, if SQLITE_TEST is not defined, the placeholder
+ ** code attempts a non-blocking lock and sets unixFile->iBusyTimeout
+ ** to 0. This causes the caller to return SQLITE_BUSY, instead of
+ ** SQLITE_BUSY_TIMEOUT to SQLite - as required by a VFS that does not
+ ** support blocking locks.
+ */
+#ifdef SQLITE_TEST
+ int tm = pFile->iBusyTimeout;
+ while( tm>0 ){
+ rc = osFcntl(h,F_SETLK,pLock);
+ if( rc==0 ) break;
+ unixSleep(0,1000);
+ tm--;
+ }
+#else
+ rc = osFcntl(h,F_SETLK,pLock);
+ pFile->iBusyTimeout = 0;
+#endif
+ /* End of code to replace with real blocking-locks code. */
}
+
return rc;
}
#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
@@ -40182,7 +41155,7 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
if( pInode->bProcessLock==0 ){
struct flock lock;
- assert( pInode->nLock==0 );
+ /* assert( pInode->nLock==0 ); <-- Not true if unix-excl READONLY used */
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
@@ -40195,11 +41168,25 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
rc = 0;
}
}else{
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( pFile->bBlockOnConnect && pLock->l_type==F_RDLCK
+ && pLock->l_start==SHARED_FIRST && pLock->l_len==SHARED_SIZE
+ ){
+ rc = osFcntl(pFile->h, F_SETLKW, pLock);
+ }else
+#endif
rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
}
return rc;
}
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
+/* Forward reference */
+static int unixIsSharingShmNode(unixFile*);
+#else
+#define unixIsSharingShmNode(pFile) (0)
+#endif
+
/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
@@ -40392,6 +41379,14 @@ static int unixLock(sqlite3_file *id, int eFileLock){
/* We are trying for an exclusive lock but another thread in this
** same process is still holding a shared lock. */
rc = SQLITE_BUSY;
+ }else if( unixIsSharingShmNode(pFile) ){
+ /* We are in WAL mode and attempting to delete the SHM and WAL
+ ** files due to closing the connection or changing out of WAL mode,
+ ** but another process still holds locks on the SHM file, thus
+ ** indicating that database locks have been broken, perhaps due
+ ** to a rogue close(open(dbFile)) or similar.
+ */
+ rc = SQLITE_BUSY;
}else{
/* The request was for a RESERVED or EXCLUSIVE lock. It is
** assumed that there is a SHARED or greater lock on the file
@@ -40797,26 +41792,22 @@ static int nolockClose(sqlite3_file *id) {
/*
** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, set *pResOut
-** to a non-zero value otherwise *pResOut is set to zero. The return value
-** is set to SQLITE_OK unless an I/O error occurs during lock checking.
-**
-** In dotfile locking, either a lock exists or it does not. So in this
-** variation of CheckReservedLock(), *pResOut is set to true if any lock
-** is held on the file and false if the file is unlocked.
+** file by this or any other process. If the caller holds a SHARED
+** or greater lock when it is called, then it is assumed that no other
+** client may hold RESERVED. Or, if the caller holds no lock, then it
+** is assumed another client holds RESERVED if the lock-file exists.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
unixFile *pFile = (unixFile*)id;
-
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
- assert( pFile );
- reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
- OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
- *pResOut = reserved;
- return rc;
+ if( pFile->eFileLock>=SHARED_LOCK ){
+ *pResOut = 0;
+ }else{
+ *pResOut = osAccess((const char*)pFile->lockingContext, 0)==0;
+ }
+ OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, 0, *pResOut));
+ return SQLITE_OK;
}
/*
@@ -40986,54 +41977,33 @@ static int robust_flock(int fd, int op){
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
+#ifdef SQLITE_DEBUG
unixFile *pFile = (unixFile*)id;
+#else
+ UNUSED_PARAMETER(id);
+#endif
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
+ assert( pFile->eFileLock<=SHARED_LOCK );
- /* Check if a thread in this process holds such a lock */
- if( pFile->eFileLock>SHARED_LOCK ){
- reserved = 1;
- }
+ /* The flock VFS only ever takes exclusive locks (see function flockLock).
+ ** Therefore, if this connection is holding any lock at all, no other
+ ** connection may be holding a RESERVED lock. So set *pResOut to 0
+ ** in this case.
+ **
+ ** Or, this connection may be holding no lock. In that case, set *pResOut to
+ ** 0 as well. The caller will then attempt to take an EXCLUSIVE lock on the
+ ** db in order to roll the hot journal back. If there is another connection
+ ** holding a lock, that attempt will fail and an SQLITE_BUSY returned to
+ ** the user. With other VFS, we try to avoid this, in order to allow a reader
+ ** to proceed while a writer is preparing its transaction. But that won't
+ ** work with the flock VFS - as it always takes EXCLUSIVE locks - so it is
+ ** not a problem in this case. */
+ *pResOut = 0;
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- /* attempt to get the lock */
- int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
- if( !lrc ){
- /* got the lock, unlock it */
- lrc = robust_flock(pFile->h, LOCK_UN);
- if ( lrc ) {
- int tErrno = errno;
- /* unlock failed with an error */
- lrc = SQLITE_IOERR_UNLOCK;
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- } else {
- int tErrno = errno;
- reserved = 1;
- /* someone else might have it reserved */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(lrc) ){
- storeLastErrno(pFile, tErrno);
- rc = lrc;
- }
- }
- }
- OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
-
-#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- if( (rc & 0xff) == SQLITE_IOERR ){
- rc = SQLITE_OK;
- reserved=1;
- }
-#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
- *pResOut = reserved;
- return rc;
+ return SQLITE_OK;
}
/*
@@ -42505,9 +43475,13 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
static int unixFcntlExternalReader(unixFile*, int*);
#endif
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+ static void unixDescribeShm(sqlite3_str*,unixShm*);
+#endif
+
/*
** Information and control of an open file handle.
@@ -42530,6 +43504,11 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
+ case SQLITE_FCNTL_NULL_IO: {
+ osClose(pFile->h);
+ pFile->h = -1;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
@@ -42576,8 +43555,9 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
case SQLITE_FCNTL_LOCK_TIMEOUT: {
int iOld = pFile->iBusyTimeout;
+ int iNew = *(int*)pArg;
#if SQLITE_ENABLE_SETLK_TIMEOUT==1
- pFile->iBusyTimeout = *(int*)pArg;
+ pFile->iBusyTimeout = iNew<0 ? 0x7FFFFFFF : (unsigned)iNew;
#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
pFile->iBusyTimeout = !!(*(int*)pArg);
#else
@@ -42586,7 +43566,12 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = iOld;
return SQLITE_OK;
}
-#endif
+ case SQLITE_FCNTL_BLOCK_ON_CONNECT: {
+ int iNew = *(int*)pArg;
+ pFile->bBlockOnConnect = iNew;
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
#if SQLITE_MAX_MMAP_SIZE>0
case SQLITE_FCNTL_MMAP_SIZE: {
i64 newLimit = *(i64*)pArg;
@@ -42632,13 +43617,73 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
case SQLITE_FCNTL_EXTERNAL_READER: {
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
#else
*(int*)pArg = 0;
return SQLITE_OK;
#endif
}
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+ case SQLITE_FCNTL_FILESTAT: {
+ sqlite3_str *pStr = (sqlite3_str*)pArg;
+ char aLck[16];
+ unixInodeInfo *pInode;
+ static const char *azLock[] = { "SHARED", "RESERVED",
+ "PENDING", "EXCLUSIVE" };
+ sqlite3_str_appendf(pStr, "{\"h\":%d", pFile->h);
+ sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName);
+ if( pFile->eFileLock ){
+ sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"",
+ azLock[pFile->eFileLock-1]);
+ if( unixPosixAdvisoryLocks(pFile->h, aLck)==SQLITE_OK ){
+ sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
+ }
+ }
+ unixEnterMutex();
+ if( pFile->pShm ){
+ sqlite3_str_appendall(pStr, ",\"shm\":");
+ unixDescribeShm(pStr, pFile->pShm);
+ }
+#if SQLITE_MAX_MMAP_SIZE>0
+ if( pFile->mmapSize ){
+ sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize);
+ sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut);
+ }
+#endif
+ if( (pInode = pFile->pInode)!=0 ){
+ sqlite3_str_appendf(pStr, ",\"inode\":{\"nRef\":%d",pInode->nRef);
+ sqlite3_mutex_enter(pInode->pLockMutex);
+ sqlite3_str_appendf(pStr, ",\"nShared\":%d", pInode->nShared);
+ if( pInode->eFileLock ){
+ sqlite3_str_appendf(pStr, ",\"eFileLock\":\"%s\"",
+ azLock[pInode->eFileLock-1]);
+ }
+ if( pInode->pUnused ){
+ char cSep = '[';
+ UnixUnusedFd *pUFd = pFile->pInode->pUnused;
+ sqlite3_str_appendall(pStr, ",\"unusedFd\":");
+ while( pUFd ){
+ sqlite3_str_appendf(pStr, "%c{\"fd\":%d,\"flags\":%d",
+ cSep, pUFd->fd, pUFd->flags);
+ cSep = ',';
+ if( unixPosixAdvisoryLocks(pUFd->fd, aLck)==SQLITE_OK ){
+ sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
+ }
+ sqlite3_str_append(pStr, "}", 1);
+ pUFd = pUFd->pNext;
+ }
+ sqlite3_str_append(pStr, "]", 1);
+ }
+ sqlite3_mutex_leave(pInode->pLockMutex);
+ sqlite3_str_append(pStr, "}", 1);
+ }
+ unixLeaveMutex();
+ sqlite3_str_append(pStr, "}", 1);
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
}
return SQLITE_NOTFOUND;
}
@@ -42671,6 +43716,7 @@ static void setDeviceCharacteristics(unixFile *pFd){
if( pFd->ctrlFlags & UNIXFILE_PSOW ){
pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
+ pFd->deviceCharacteristics |= SQLITE_IOCAP_SUBPAGE_READ;
pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
@@ -42721,7 +43767,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
@@ -42729,7 +43775,7 @@ static void setDeviceCharacteristics(unixFile *pFile){
pFile->sectorSize = fsInfo.f_bsize;
pFile->deviceCharacteristics =
/* full bitset of atomics from max sector size and smaller */
- ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ (((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2) |
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
** so it is ordered */
0;
@@ -42805,7 +43851,7 @@ static int unixGetpagesize(void){
#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
-#ifndef SQLITE_OMIT_WAL
+#if !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL)
/*
** Object used to represent an shared memory buffer.
@@ -42904,6 +43950,26 @@ struct unixShm {
#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+/*
+** Describe the pShm object using JSON. Used for diagnostics only.
+*/
+static void unixDescribeShm(sqlite3_str *pStr, unixShm *pShm){
+ unixShmNode *pNode = pShm->pShmNode;
+ char aLck[16];
+ sqlite3_str_appendf(pStr, "{\"h\":%d", pNode->hShm);
+ assert( unixMutexHeld() );
+ sqlite3_str_appendf(pStr, ",\"nRef\":%d", pNode->nRef);
+ sqlite3_str_appendf(pStr, ",\"id\":%d", pShm->id);
+ sqlite3_str_appendf(pStr, ",\"sharedMask\":%d", pShm->sharedMask);
+ sqlite3_str_appendf(pStr, ",\"exclMask\":%d", pShm->exclMask);
+ if( unixPosixAdvisoryLocks(pNode->hShm, aLck)==SQLITE_OK ){
+ sqlite3_str_appendf(pStr, ",\"pal\":\"%s\"", aLck);
+ }
+ sqlite3_str_append(pStr, "}", 1);
+}
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
+
/*
** Use F_GETLK to check whether or not there are any readers with open
** wal-mode transactions in other processes on database file pFile. If
@@ -42937,6 +44003,44 @@ static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
return rc;
}
+/*
+** If pFile has a -shm file open and it is sharing that file with some
+** other connection, either in the same process or in a separate process,
+** then return true. Return false if either pFile does not have a -shm
+** file open or if it is the only connection to that -shm file across the
+** entire system.
+**
+** This routine is not required for correct operation. It can always return
+** false and SQLite will continue to operate according to spec. However,
+** when this routine does its job, it adds extra robustness in cases
+** where database file locks have been erroneously deleted in a WAL-mode
+** database by doing close(open(DATABASE_PATHNAME)) or similar.
+**
+** With false negatives, SQLite still operates to spec, though with less
+** robustness. With false positives, the last database connection on a
+** WAL-mode database will fail to unlink the -wal and -shm files, which
+** is annoying but harmless. False positives will also prevent a database
+** connection from running "PRAGMA journal_mode=DELETE" in order to take
+** the database out of WAL mode, which is perhaps more serious, but is
+** still not a disaster.
+*/
+static int unixIsSharingShmNode(unixFile *pFile){
+ unixShmNode *pShmNode;
+ struct flock lock;
+ if( pFile->pShm==0 ) return 0;
+ if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0;
+ pShmNode = pFile->pShm->pShmNode;
+#if SQLITE_ATOMIC_INTRINSICS
+ assert( AtomicLoad(&pShmNode->nRef)==1 );
+#endif
+ memset(&lock, 0, sizeof(lock));
+ lock.l_whence = SEEK_SET;
+ lock.l_start = UNIX_SHM_DMS;
+ lock.l_len = 1;
+ lock.l_type = F_WRLCK;
+ osFcntl(pShmNode->hShm, F_GETLK, &lock);
+ return (lock.l_type!=F_UNLCK);
+}
/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
@@ -42982,7 +44086,8 @@ static int unixShmSystemLock(
/* Locks are within range */
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
- assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) );
+ assert( ofst>=UNIX_SHM_BASE && ofst<=UNIX_SHM_DMS );
+ assert( ofst+n-1<=UNIX_SHM_DMS );
if( pShmNode->hShm>=0 ){
int res;
@@ -43514,7 +44619,7 @@ static int assertLockingArrayOk(unixShmNode *pShmNode){
return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
#endif
}
-#endif
+#endif /* !defined(SQLITE_WASI) && !defined(SQLITE_OMIT_WAL) */
/*
** Change the lock state for a shared-memory segment.
@@ -43558,21 +44663,20 @@ static int unixShmLock(
/* Check that, if this to be a blocking lock, no locks that occur later
** in the following list than the lock being obtained are already held:
**
- ** 1. Checkpointer lock (ofst==1).
- ** 2. Write lock (ofst==0).
- ** 3. Read locks (ofst>=3 && ofst=3 && ofstexclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
- (ofst!=2) /* not RECOVER */
+ (ofst!=2 || lockMask==0)
&& (ofst!=1 || lockMask==0 || lockMask==2)
&& (ofst!=0 || lockMask<3)
&& (ofst<3 || lockMask<(1<=0 ) robust_close(pNew, h, __LINE__);
- h = -1;
- osUnlink(zFilename);
- pNew->ctrlFlags |= UNIXFILE_DELETE;
+ if( h>=0 ){
+ robust_close(pNew, h, __LINE__);
+ h = -1;
+ }
+ if( pNew->ctrlFlags & UNIXFILE_DELETE ){
+ osUnlink(zFilename);
+ }
+ if( pNew->pId ){
+ vxworksReleaseFileId(pNew->pId);
+ pNew->pId = 0;
+ }
}
#endif
if( rc!=SQLITE_OK ){
@@ -44524,6 +45635,9 @@ static const char *unixTempFileDir(void){
while(1){
if( zDir!=0
+#if OS_VXWORKS
+ && zDir[0]=='/'
+#endif
&& osStat(zDir, &buf)==0
&& S_ISDIR(buf.st_mode)
&& osAccess(zDir, 03)==0
@@ -44838,6 +45952,12 @@ static int unixOpen(
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
+#if OS_VXWORKS
+ /* The file-ID mechanism used in Vxworks requires that all pathnames
+ ** provided to unixOpen must be absolute pathnames. */
+ if( zPath!=0 && zPath[0]!='/' ){ return SQLITE_CANTOPEN; }
+#endif
+
/* Detect a pid change and reset the PRNG. There is a race condition
** here such that two or more threads all trying to open databases at
** the same instant might all reset the PRNG. But multiple resets
@@ -45038,8 +46158,11 @@ static int unixOpen(
}
#endif
- assert( zPath==0 || zPath[0]=='/'
- || eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
+ assert( zPath==0
+ || zPath[0]=='/'
+ || eType==SQLITE_OPEN_SUPER_JOURNAL
+ || eType==SQLITE_OPEN_MAIN_JOURNAL
+ || eType==SQLITE_OPEN_TEMP_JOURNAL
);
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
@@ -45377,7 +46500,7 @@ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
/* Almost all modern unix systems support nanosleep(). But if you are
** compiling for one of the rare exceptions, you can use
- ** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if
+ ** -DHAVE_NANOSLEEP=0 (perhaps in conjunction with -DHAVE_USLEEP if
** usleep() is available) in order to bypass the use of nanosleep() */
nanosleep(&sp, NULL);
@@ -46768,6 +47891,9 @@ SQLITE_API int sqlite3_os_init(void){
sqlite3KvvfsInit();
#endif
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#if OS_VXWORKS
+ vxworksMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS2);
+#endif
#ifndef SQLITE_OMIT_WAL
/* Validate lock assumptions */
@@ -46802,6 +47928,9 @@ SQLITE_API int sqlite3_os_init(void){
*/
SQLITE_API int sqlite3_os_end(void){
unixBigLock = 0;
+#if OS_VXWORKS
+ vxworksMutex = 0;
+#endif
return SQLITE_OK;
}
@@ -47098,8 +48227,18 @@ struct winFile {
sqlite3_int64 mmapSize; /* Size of mapped region */
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ DWORD iBusyTimeout; /* Wait this many millisec on locks */
+ int bBlockOnConnect;
+#endif
};
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+# define winFileBusyTimeout(pDbFd) pDbFd->iBusyTimeout
+#else
+# define winFileBusyTimeout(pDbFd) 0
+#endif
+
/*
** The winVfsAppData structure is used for the pAppData member for all of the
** Win32 VFS variants.
@@ -47418,7 +48557,7 @@ static struct win_syscall {
{ "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
#endif
-#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(const FILETIME*, \
LPFILETIME))aSyscall[11].pCurrent)
#if SQLITE_OS_WINCE
@@ -47427,7 +48566,7 @@ static struct win_syscall {
{ "FileTimeToSystemTime", (SYSCALL)0, 0 },
#endif
-#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
+#define osFileTimeToSystemTime ((BOOL(WINAPI*)(const FILETIME*, \
LPSYSTEMTIME))aSyscall[12].pCurrent)
{ "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
@@ -47533,6 +48672,12 @@ static struct win_syscall {
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
LPWSTR*))aSyscall[25].pCurrent)
+/*
+** For GetLastError(), MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
{ "GetLastError", (SYSCALL)GetLastError, 0 },
#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
@@ -47701,7 +48846,7 @@ static struct win_syscall {
{ "LockFile", (SYSCALL)0, 0 },
#endif
-#ifndef osLockFile
+#if !defined(osLockFile) && defined(SQLITE_WIN32_HAS_ANSI)
#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
DWORD))aSyscall[47].pCurrent)
#endif
@@ -47765,7 +48910,7 @@ static struct win_syscall {
{ "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
-#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
+#define osSystemTimeToFileTime ((BOOL(WINAPI*)(const SYSTEMTIME*, \
LPFILETIME))aSyscall[56].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
@@ -47774,7 +48919,7 @@ static struct win_syscall {
{ "UnlockFile", (SYSCALL)0, 0 },
#endif
-#ifndef osUnlockFile
+#if !defined(osUnlockFile) && defined(SQLITE_WIN32_HAS_ANSI)
#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
DWORD))aSyscall[57].pCurrent)
#endif
@@ -47815,11 +48960,13 @@ static struct win_syscall {
#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
DWORD,DWORD))aSyscall[62].pCurrent)
-#if !SQLITE_OS_WINRT
+/*
+** For WaitForSingleObject(), MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
-#else
- { "WaitForSingleObject", (SYSCALL)0, 0 },
-#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
DWORD))aSyscall[63].pCurrent)
@@ -47966,6 +49113,97 @@ static struct win_syscall {
#define osFlushViewOfFile \
((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
+/*
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CreateEvent()
+** to implement blocking locks with timeouts. MSDN says:
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ { "CreateEvent", (SYSCALL)CreateEvent, 0 },
+#else
+ { "CreateEvent", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateEvent ( \
+ (HANDLE(WINAPI*) (LPSECURITY_ATTRIBUTES,BOOL,BOOL,LPCSTR)) \
+ aSyscall[80].pCurrent \
+)
+
+/*
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined, we require CancelIo()
+** for the case where a timeout expires and a lock request must be
+** cancelled.
+**
+** Minimum supported client: Windows XP [desktop apps | UWP apps]
+** Minimum supported server: Windows Server 2003 [desktop apps | UWP apps]
+*/
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ { "CancelIo", (SYSCALL)CancelIo, 0 },
+#else
+ { "CancelIo", (SYSCALL)0, 0 },
+#endif
+
+#define osCancelIo ((BOOL(WINAPI*)(HANDLE))aSyscall[81].pCurrent)
+
+#if defined(SQLITE_WIN32_HAS_WIDE) && defined(_WIN32)
+ { "GetModuleHandleW", (SYSCALL)GetModuleHandleW, 0 },
+#else
+ { "GetModuleHandleW", (SYSCALL)0, 0 },
+#endif
+
+#define osGetModuleHandleW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[82].pCurrent)
+
+#ifndef _WIN32
+ { "getenv", (SYSCALL)getenv, 0 },
+#else
+ { "getenv", (SYSCALL)0, 0 },
+#endif
+
+#define osGetenv ((const char *(*)(const char *))aSyscall[83].pCurrent)
+
+#ifndef _WIN32
+ { "getcwd", (SYSCALL)getcwd, 0 },
+#else
+ { "getcwd", (SYSCALL)0, 0 },
+#endif
+
+#define osGetcwd ((char*(*)(char*,size_t))aSyscall[84].pCurrent)
+
+#ifndef _WIN32
+ { "readlink", (SYSCALL)readlink, 0 },
+#else
+ { "readlink", (SYSCALL)0, 0 },
+#endif
+
+#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[85].pCurrent)
+
+#ifndef _WIN32
+ { "lstat", (SYSCALL)lstat, 0 },
+#else
+ { "lstat", (SYSCALL)0, 0 },
+#endif
+
+#define osLstat ((int(*)(const char*,struct stat*))aSyscall[86].pCurrent)
+
+#ifndef _WIN32
+ { "__errno", (SYSCALL)__errno, 0 },
+#else
+ { "__errno", (SYSCALL)0, 0 },
+#endif
+
+#define osErrno (*((int*(*)(void))aSyscall[87].pCurrent)())
+
+#ifndef _WIN32
+ { "cygwin_conv_path", (SYSCALL)cygwin_conv_path, 0 },
+#else
+ { "cygwin_conv_path", (SYSCALL)0, 0 },
+#endif
+
+#define osCygwin_conv_path ((size_t(*)(unsigned int, \
+ const void *, void *, size_t))aSyscall[88].pCurrent)
+
}; /* End of the overrideable system calls */
/*
@@ -48139,6 +49377,7 @@ SQLITE_API int sqlite3_win32_reset_heap(){
}
#endif /* SQLITE_WIN32_MALLOC */
+#ifdef _WIN32
/*
** This function outputs the specified (ANSI) string to the Win32 debugger
** (if available).
@@ -48181,6 +49420,7 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
}
#endif
}
+#endif /* _WIN32 */
/*
** The following routine suspends the current thread for at least ms
@@ -48264,7 +49504,9 @@ SQLITE_API int sqlite3_win32_is_nt(void){
}
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#elif SQLITE_TEST
- return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
+ return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2
+ || osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0
+ ;
#else
/*
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
@@ -48479,6 +49721,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
}
#endif /* SQLITE_WIN32_MALLOC */
+#ifdef _WIN32
/*
** Convert a UTF-8 string to Microsoft Unicode.
**
@@ -48504,6 +49747,7 @@ static LPWSTR winUtf8ToUnicode(const char *zText){
}
return zWideText;
}
+#endif /* _WIN32 */
/*
** Convert a Microsoft Unicode string to UTF-8.
@@ -48538,28 +49782,29 @@ static char *winUnicodeToUtf8(LPCWSTR zWideText){
** Space to hold the returned string is obtained from sqlite3_malloc().
*/
static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){
- int nByte;
+ int nWideChar;
LPWSTR zMbcsText;
int codepage = useAnsi ? CP_ACP : CP_OEMCP;
- nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
- 0)*sizeof(WCHAR);
- if( nByte==0 ){
+ nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
+ 0);
+ if( nWideChar==0 ){
return 0;
}
- zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) );
+ zMbcsText = sqlite3MallocZero( nWideChar*sizeof(WCHAR) );
if( zMbcsText==0 ){
return 0;
}
- nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
- nByte);
- if( nByte==0 ){
+ nWideChar = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
+ nWideChar);
+ if( nWideChar==0 ){
sqlite3_free(zMbcsText);
zMbcsText = 0;
}
return zMbcsText;
}
+#ifdef _WIN32
/*
** Convert a Microsoft Unicode string to a multi-byte character string,
** using the ANSI or OEM code page.
@@ -48587,6 +49832,7 @@ static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){
}
return zText;
}
+#endif /* _WIN32 */
/*
** Convert a multi-byte character string to UTF-8.
@@ -48606,6 +49852,7 @@ static char *winMbcsToUtf8(const char *zText, int useAnsi){
return zTextUtf8;
}
+#ifdef _WIN32
/*
** Convert a UTF-8 string to a multi-byte character string.
**
@@ -48655,6 +49902,7 @@ SQLITE_API char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){
#endif
return winUnicodeToUtf8(zWideText);
}
+#endif /* _WIN32 */
/*
** This is a public wrapper for the winMbcsToUtf8() function.
@@ -48672,6 +49920,7 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zText){
return winMbcsToUtf8(zText, osAreFileApisANSI());
}
+#ifdef _WIN32
/*
** This is a public wrapper for the winMbcsToUtf8() function.
*/
@@ -48796,6 +50045,7 @@ SQLITE_API int sqlite3_win32_set_directory(
){
return sqlite3_win32_set_directory16(type, zValue);
}
+#endif /* _WIN32 */
/*
** The return value of winGetLastErrorMsg
@@ -49344,13 +50594,100 @@ static BOOL winLockFile(
ovlp.Offset = offsetLow;
ovlp.OffsetHigh = offsetHigh;
return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
+#ifdef SQLITE_WIN32_HAS_ANSI
}else{
return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
numBytesHigh);
+#endif
}
#endif
}
+#ifndef SQLITE_OMIT_WAL
+/*
+** Lock a region of nByte bytes starting at offset offset of file hFile.
+** Take an EXCLUSIVE lock if parameter bExclusive is true, or a SHARED lock
+** otherwise. If nMs is greater than zero and the lock cannot be obtained
+** immediately, block for that many ms before giving up.
+**
+** This function returns SQLITE_OK if the lock is obtained successfully. If
+** some other process holds the lock, SQLITE_BUSY is returned if nMs==0, or
+** SQLITE_BUSY_TIMEOUT otherwise. Or, if an error occurs, SQLITE_IOERR.
+*/
+static int winHandleLockTimeout(
+ HANDLE hFile,
+ DWORD offset,
+ DWORD nByte,
+ int bExcl,
+ DWORD nMs
+){
+ DWORD flags = LOCKFILE_FAIL_IMMEDIATELY | (bExcl?LOCKFILE_EXCLUSIVE_LOCK:0);
+ int rc = SQLITE_OK;
+ BOOL ret;
+
+ if( !osIsNT() ){
+ ret = winLockFile(&hFile, flags, offset, 0, nByte, 0);
+ }else{
+ OVERLAPPED ovlp;
+ memset(&ovlp, 0, sizeof(OVERLAPPED));
+ ovlp.Offset = offset;
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( nMs!=0 ){
+ flags &= ~LOCKFILE_FAIL_IMMEDIATELY;
+ }
+ ovlp.hEvent = osCreateEvent(NULL, TRUE, FALSE, NULL);
+ if( ovlp.hEvent==NULL ){
+ return SQLITE_IOERR_LOCK;
+ }
+#endif
+
+ ret = osLockFileEx(hFile, flags, 0, nByte, 0, &ovlp);
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ /* If SQLITE_ENABLE_SETLK_TIMEOUT is defined, then the file-handle was
+ ** opened with FILE_FLAG_OVERHEAD specified. In this case, the call to
+ ** LockFileEx() may fail because the request is still pending. This can
+ ** happen even if LOCKFILE_FAIL_IMMEDIATELY was specified.
+ **
+ ** If nMs is 0, then LOCKFILE_FAIL_IMMEDIATELY was set in the flags
+ ** passed to LockFileEx(). In this case, if the operation is pending,
+ ** block indefinitely until it is finished.
+ **
+ ** Otherwise, wait for up to nMs ms for the operation to finish. nMs
+ ** may be set to INFINITE.
+ */
+ if( !ret && GetLastError()==ERROR_IO_PENDING ){
+ DWORD nDelay = (nMs==0 ? INFINITE : nMs);
+ DWORD res = osWaitForSingleObject(ovlp.hEvent, nDelay);
+ if( res==WAIT_OBJECT_0 ){
+ ret = TRUE;
+ }else if( res==WAIT_TIMEOUT ){
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
+ rc = SQLITE_BUSY_TIMEOUT;
+#else
+ rc = SQLITE_BUSY;
+#endif
+ }else{
+ /* Some other error has occurred */
+ rc = SQLITE_IOERR_LOCK;
+ }
+
+ /* If it is still pending, cancel the LockFileEx() call. */
+ osCancelIo(hFile);
+ }
+
+ osCloseHandle(ovlp.hEvent);
+#endif
+ }
+
+ if( rc==SQLITE_OK && !ret ){
+ rc = SQLITE_BUSY;
+ }
+ return rc;
+}
+#endif /* #ifndef SQLITE_OMIT_WAL */
+
/*
** Unlock a file region.
*/
@@ -49375,13 +50712,25 @@ static BOOL winUnlockFile(
ovlp.Offset = offsetLow;
ovlp.OffsetHigh = offsetHigh;
return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
+#ifdef SQLITE_WIN32_HAS_ANSI
}else{
return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
numBytesHigh);
+#endif
}
#endif
}
+#ifndef SQLITE_OMIT_WAL
+/*
+** Remove an nByte lock starting at offset iOff from HANDLE h.
+*/
+static int winHandleUnlock(HANDLE h, int iOff, int nByte){
+ BOOL ret = winUnlockFile(&h, iOff, 0, nByte, 0);
+ return (ret ? SQLITE_OK : SQLITE_IOERR_UNLOCK);
+}
+#endif
+
/*****************************************************************************
** The next group of routines implement the I/O methods specified
** by the sqlite3_io_methods object.
@@ -49395,66 +50744,70 @@ static BOOL winUnlockFile(
#endif
/*
-** Move the current position of the file handle passed as the first
-** argument to offset iOffset within the file. If successful, return 0.
-** Otherwise, set pFile->lastErrno and return non-zero.
+** Seek the file handle h to offset nByte of the file.
+**
+** If successful, return SQLITE_OK. Or, if an error occurs, return an SQLite
+** error code.
*/
-static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
+static int winHandleSeek(HANDLE h, sqlite3_int64 iOffset){
+ int rc = SQLITE_OK; /* Return value */
+
#if !SQLITE_OS_WINRT
LONG upperBits; /* Most sig. 32 bits of new offset */
LONG lowerBits; /* Least sig. 32 bits of new offset */
DWORD dwRet; /* Value returned by SetFilePointer() */
- DWORD lastErrno; /* Value returned by GetLastError() */
-
- OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
lowerBits = (LONG)(iOffset & 0xffffffff);
+ dwRet = osSetFilePointer(h, lowerBits, &upperBits, FILE_BEGIN);
+
/* API oddity: If successful, SetFilePointer() returns a dword
** containing the lower 32-bits of the new file-offset. Or, if it fails,
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
** whether an error has actually occurred, it is also necessary to call
- ** GetLastError().
- */
- dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
-
- if( (dwRet==INVALID_SET_FILE_POINTER
- && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
- pFile->lastErrno = lastErrno;
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
+ ** GetLastError(). */
+ if( dwRet==INVALID_SET_FILE_POINTER ){
+ DWORD lastErrno = osGetLastError();
+ if( lastErrno!=NO_ERROR ){
+ rc = SQLITE_IOERR_SEEK;
+ }
}
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
#else
- /*
- ** Same as above, except that this implementation works for WinRT.
- */
-
+ /* This implementation works for WinRT. */
LARGE_INTEGER x; /* The new offset */
BOOL bRet; /* Value returned by SetFilePointerEx() */
x.QuadPart = iOffset;
- bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
+ bRet = osSetFilePointerEx(h, x, 0, FILE_BEGIN);
if(!bRet){
- pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
- "winSeekFile", pFile->zPath);
- OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
- return 1;
+ rc = SQLITE_IOERR_SEEK;
}
-
- OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
- return 0;
#endif
+
+ OSTRACE(("SEEK file=%p, offset=%lld rc=%s\n", h, iOffset, sqlite3ErrName(rc)));
+ return rc;
}
+/*
+** Move the current position of the file handle passed as the first
+** argument to offset iOffset within the file. If successful, return 0.
+** Otherwise, set pFile->lastErrno and return non-zero.
+*/
+static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
+ int rc;
+
+ rc = winHandleSeek(pFile->h, iOffset);
+ if( rc!=SQLITE_OK ){
+ pFile->lastErrno = osGetLastError();
+ winLogError(rc, pFile->lastErrno, "winSeekFile", pFile->zPath);
+ }
+ return rc;
+}
+
+
#if SQLITE_MAX_MMAP_SIZE>0
/* Forward references to VFS helper methods used for memory mapped files */
static int winMapfile(winFile*, sqlite3_int64);
@@ -49714,6 +51067,62 @@ static int winWrite(
return SQLITE_OK;
}
+#ifndef SQLITE_OMIT_WAL
+/*
+** Truncate the file opened by handle h to nByte bytes in size.
+*/
+static int winHandleTruncate(HANDLE h, sqlite3_int64 nByte){
+ int rc = SQLITE_OK; /* Return code */
+ rc = winHandleSeek(h, nByte);
+ if( rc==SQLITE_OK ){
+ if( 0==osSetEndOfFile(h) ){
+ rc = SQLITE_IOERR_TRUNCATE;
+ }
+ }
+ return rc;
+}
+
+/*
+** Determine the size in bytes of the file opened by the handle passed as
+** the first argument.
+*/
+static int winHandleSize(HANDLE h, sqlite3_int64 *pnByte){
+ int rc = SQLITE_OK;
+
+#if SQLITE_OS_WINRT
+ FILE_STANDARD_INFO info;
+ BOOL b;
+ b = osGetFileInformationByHandleEx(h, FileStandardInfo, &info, sizeof(info));
+ if( b ){
+ *pnByte = info.EndOfFile.QuadPart;
+ }else{
+ rc = SQLITE_IOERR_FSTAT;
+ }
+#else
+ DWORD upperBits = 0;
+ DWORD lowerBits = 0;
+
+ assert( pnByte );
+ lowerBits = osGetFileSize(h, &upperBits);
+ *pnByte = (((sqlite3_int64)upperBits)<<32) + lowerBits;
+ if( lowerBits==INVALID_FILE_SIZE && osGetLastError()!=NO_ERROR ){
+ rc = SQLITE_IOERR_FSTAT;
+ }
+#endif
+
+ return rc;
+}
+
+/*
+** Close the handle passed as the only argument.
+*/
+static void winHandleClose(HANDLE h){
+ if( h!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(h);
+ }
+}
+#endif /* #ifndef SQLITE_OMIT_WAL */
+
/*
** Truncate an open file to a specified size
*/
@@ -49969,8 +51378,9 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
** Different API routines are called depending on whether or not this
** is Win9x or WinNT.
*/
-static int winGetReadLock(winFile *pFile){
+static int winGetReadLock(winFile *pFile, int bBlock){
int res;
+ DWORD mask = ~(bBlock ? LOCKFILE_FAIL_IMMEDIATELY : 0);
OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
if( osIsNT() ){
#if SQLITE_OS_WINCE
@@ -49980,7 +51390,7 @@ static int winGetReadLock(winFile *pFile){
*/
res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
#else
- res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS&mask, SHARED_FIRST, 0,
SHARED_SIZE, 0);
#endif
}
@@ -49989,7 +51399,7 @@ static int winGetReadLock(winFile *pFile){
int lk;
sqlite3_randomness(sizeof(lk), &lk);
pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
- res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
+ res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS&mask,
SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
}
#endif
@@ -50084,46 +51494,62 @@ static int winLock(sqlite3_file *id, int locktype){
assert( locktype!=PENDING_LOCK );
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
- /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
+ /* Lock the PENDING_LOCK byte if we need to acquire an EXCLUSIVE lock or
** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
** the PENDING_LOCK byte is temporary.
*/
newLocktype = pFile->locktype;
- if( pFile->locktype==NO_LOCK
- || (locktype==EXCLUSIVE_LOCK && pFile->locktype<=RESERVED_LOCK)
+ if( locktype==SHARED_LOCK
+ || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
){
int cnt = 3;
- while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
- PENDING_BYTE, 0, 1, 0))==0 ){
+
+ /* Flags for the LockFileEx() call. This should be an exclusive lock if
+ ** this call is to obtain EXCLUSIVE, or a shared lock if this call is to
+ ** obtain SHARED. */
+ int flags = LOCKFILE_FAIL_IMMEDIATELY;
+ if( locktype==EXCLUSIVE_LOCK ){
+ flags |= LOCKFILE_EXCLUSIVE_LOCK;
+ }
+ while( cnt>0 ){
/* Try 3 times to get the pending lock. This is needed to work
** around problems caused by indexing and/or anti-virus software on
** Windows systems.
+ **
** If you are using this code as a model for alternative VFSes, do not
- ** copy this retry logic. It is a hack intended for Windows only.
- */
+ ** copy this retry logic. It is a hack intended for Windows only. */
+ res = winLockFile(&pFile->h, flags, PENDING_BYTE, 0, 1, 0);
+ if( res ) break;
+
lastErrno = osGetLastError();
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
- pFile->h, cnt, res));
+ pFile->h, cnt, res
+ ));
+
if( lastErrno==ERROR_INVALID_HANDLE ){
pFile->lastErrno = lastErrno;
rc = SQLITE_IOERR_LOCK;
OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
- pFile->h, cnt, sqlite3ErrName(rc)));
+ pFile->h, cnt, sqlite3ErrName(rc)
+ ));
return rc;
}
- if( cnt ) sqlite3_win32_sleep(1);
+
+ cnt--;
+ if( cnt>0 ) sqlite3_win32_sleep(1);
}
gotPendingLock = res;
- if( !res ){
- lastErrno = osGetLastError();
- }
}
/* Acquire a shared lock
*/
if( locktype==SHARED_LOCK && res ){
assert( pFile->locktype==NO_LOCK );
- res = winGetReadLock(pFile);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ res = winGetReadLock(pFile, pFile->bBlockOnConnect);
+#else
+ res = winGetReadLock(pFile, 0);
+#endif
if( res ){
newLocktype = SHARED_LOCK;
}else{
@@ -50161,7 +51587,7 @@ static int winLock(sqlite3_file *id, int locktype){
newLocktype = EXCLUSIVE_LOCK;
}else{
lastErrno = osGetLastError();
- winGetReadLock(pFile);
+ winGetReadLock(pFile, 0);
}
}
@@ -50241,7 +51667,7 @@ static int winUnlock(sqlite3_file *id, int locktype){
type = pFile->locktype;
if( type>=EXCLUSIVE_LOCK ){
winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
- if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
+ if( locktype==SHARED_LOCK && !winGetReadLock(pFile, 0) ){
/* This should never happen. We should always be able to
** reacquire the read lock */
rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
@@ -50410,6 +51836,11 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
#endif
+ case SQLITE_FCNTL_NULL_IO: {
+ (void)osCloseHandle(pFile->h);
+ pFile->h = NULL;
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = 0;
int rc = winGetTempname(pFile->pVfs, &zTFile);
@@ -50446,6 +51877,50 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
return rc;
}
#endif
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ case SQLITE_FCNTL_LOCK_TIMEOUT: {
+ int iOld = pFile->iBusyTimeout;
+ int iNew = *(int*)pArg;
+#if SQLITE_ENABLE_SETLK_TIMEOUT==1
+ pFile->iBusyTimeout = (iNew < 0) ? INFINITE : (DWORD)iNew;
+#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
+ pFile->iBusyTimeout = (DWORD)(!!iNew);
+#else
+# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
+#endif
+ *(int*)pArg = iOld;
+ return SQLITE_OK;
+ }
+ case SQLITE_FCNTL_BLOCK_ON_CONNECT: {
+ int iNew = *(int*)pArg;
+ pFile->bBlockOnConnect = iNew;
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+ case SQLITE_FCNTL_FILESTAT: {
+ sqlite3_str *pStr = (sqlite3_str*)pArg;
+ sqlite3_str_appendf(pStr, "{\"h\":%llu", (sqlite3_uint64)pFile->h);
+ sqlite3_str_appendf(pStr, ",\"vfs\":\"%s\"", pFile->pVfs->zName);
+ if( pFile->locktype ){
+ static const char *azLock[] = { "SHARED", "RESERVED",
+ "PENDING", "EXCLUSIVE" };
+ sqlite3_str_appendf(pStr, ",\"locktype\":\"%s\"",
+ azLock[pFile->locktype-1]);
+ }
+#if SQLITE_MAX_MMAP_SIZE>0
+ if( pFile->mmapSize ){
+ sqlite3_str_appendf(pStr, ",\"mmapSize\":%lld", pFile->mmapSize);
+ sqlite3_str_appendf(pStr, ",\"nFetchOut\":%d", pFile->nFetchOut);
+ }
+#endif
+ sqlite3_str_append(pStr, "}", 1);
+ return SQLITE_OK;
+ }
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
+
}
OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
return SQLITE_NOTFOUND;
@@ -50471,7 +51946,7 @@ static int winSectorSize(sqlite3_file *id){
*/
static int winDeviceCharacteristics(sqlite3_file *id){
winFile *p = (winFile*)id;
- return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
+ return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_SUBPAGE_READ |
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
}
@@ -50483,6 +51958,103 @@ static int winDeviceCharacteristics(sqlite3_file *id){
*/
static SYSTEM_INFO winSysInfo;
+/*
+** Convert a UTF-8 filename into whatever form the underlying
+** operating system wants filenames in. Space to hold the result
+** is obtained from malloc and must be freed by the calling
+** function
+**
+** On Cygwin, 3 possible input forms are accepted:
+** - If the filename starts with ":/" or ":\",
+** it is converted to UTF-16 as-is.
+** - If the filename contains '/', it is assumed to be a
+** Cygwin absolute path, it is converted to a win32
+** absolute path in UTF-16.
+** - Otherwise it must be a filename only, the win32 filename
+** is returned in UTF-16.
+** Note: If the function cygwin_conv_path() fails, only
+** UTF-8 -> UTF-16 conversion will be done. This can only
+** happen when the file path >32k, in which case winUtf8ToUnicode()
+** will fail too.
+*/
+static void *winConvertFromUtf8Filename(const char *zFilename){
+ void *zConverted = 0;
+ if( osIsNT() ){
+#ifdef __CYGWIN__
+ int nChar;
+ LPWSTR zWideFilename;
+
+ if( osCygwin_conv_path && !(winIsDriveLetterAndColon(zFilename)
+ && winIsDirSep(zFilename[2])) ){
+ i64 nByte;
+ int convertflag = CCP_POSIX_TO_WIN_W;
+ if( !strchr(zFilename, '/') ) convertflag |= CCP_RELATIVE;
+ nByte = (i64)osCygwin_conv_path(convertflag,
+ zFilename, 0, 0);
+ if( nByte>0 ){
+ zConverted = sqlite3MallocZero(12+(u64)nByte);
+ if ( zConverted==0 ){
+ return zConverted;
+ }
+ zWideFilename = zConverted;
+ /* Filenames should be prefixed, except when converted
+ * full path already starts with "\\?\". */
+ if( osCygwin_conv_path(convertflag, zFilename,
+ zWideFilename+4, nByte)==0 ){
+ if( (convertflag&CCP_RELATIVE) ){
+ memmove(zWideFilename, zWideFilename+4, nByte);
+ }else if( memcmp(zWideFilename+4, L"\\\\", 4) ){
+ memcpy(zWideFilename, L"\\\\?\\", 8);
+ }else if( zWideFilename[6]!='?' ){
+ memmove(zWideFilename+6, zWideFilename+4, nByte);
+ memcpy(zWideFilename, L"\\\\?\\UNC", 14);
+ }else{
+ memmove(zWideFilename, zWideFilename+4, nByte);
+ }
+ return zConverted;
+ }
+ sqlite3_free(zConverted);
+ }
+ }
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
+ if( nChar==0 ){
+ return 0;
+ }
+ zWideFilename = sqlite3MallocZero( nChar*sizeof(WCHAR)+12 );
+ if( zWideFilename==0 ){
+ return 0;
+ }
+ nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1,
+ zWideFilename, nChar);
+ if( nChar==0 ){
+ sqlite3_free(zWideFilename);
+ zWideFilename = 0;
+ }else if( nChar>MAX_PATH
+ && winIsDriveLetterAndColon(zFilename)
+ && winIsDirSep(zFilename[2]) ){
+ memmove(zWideFilename+4, zWideFilename, nChar*sizeof(WCHAR));
+ zWideFilename[2] = '\\';
+ memcpy(zWideFilename, L"\\\\?\\", 8);
+ }else if( nChar>MAX_PATH
+ && winIsDirSep(zFilename[0]) && winIsDirSep(zFilename[1])
+ && zFilename[2] != '?' ){
+ memmove(zWideFilename+6, zWideFilename, nChar*sizeof(WCHAR));
+ memcpy(zWideFilename, L"\\\\?\\UNC", 14);
+ }
+ zConverted = zWideFilename;
+#else
+ zConverted = winUtf8ToUnicode(zFilename);
+#endif /* __CYGWIN__ */
+ }
+#if defined(SQLITE_WIN32_HAS_ANSI) && defined(_WIN32)
+ else{
+ zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
+ }
+#endif
+ /* caller will handle out of memory */
+ return zConverted;
+}
+
#ifndef SQLITE_OMIT_WAL
/*
@@ -50519,30 +52091,40 @@ static int winShmMutexHeld(void) {
** log-summary is opened only once per process.
**
** winShmMutexHeld() must be true when creating or destroying
-** this object or while reading or writing the following fields:
+** this object, or while editing the global linked list that starts
+** at winShmNodeList.
**
-** nRef
-** pNext
+** When reading or writing the linked list starting at winShmNode.pWinShmList,
+** pShmNode->mutex must be held.
**
-** The following fields are read-only after the object is created:
+** The following fields are constant after the object is created:
**
-** fid
** zFilename
+** hSharedShm
+** mutex
+** bUseSharedLockHandle
**
-** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
+** Either winShmNode.mutex must be held or winShmNode.pWinShmList==0 and
** winShmMutexHeld() is true when reading or writing any other field
** in this structure.
**
+** File-handle hSharedShm is always used to (a) take the DMS lock, (b)
+** truncate the *-shm file if the DMS-locking protocol demands it, and
+** (c) map regions of the *-shm file into memory using MapViewOfFile()
+** or similar. If bUseSharedLockHandle is true, then other locks are also
+** taken on hSharedShm. Or, if bUseSharedLockHandle is false, then other
+** locks are taken using each connection's winShm.hShm handles.
*/
struct winShmNode {
sqlite3_mutex *mutex; /* Mutex to access this object */
char *zFilename; /* Name of the file */
- winFile hFile; /* File handle from winOpen */
+ HANDLE hSharedShm; /* File handle open on zFilename */
+ int bUseSharedLockHandle; /* True to use hSharedShm for everything */
+ int isUnlocked; /* DMS lock has not yet been obtained */
+ int isReadonly; /* True if read-only */
int szRegion; /* Size of shared-memory regions */
int nRegion; /* Size of array apRegion */
- u8 isReadonly; /* True if read-only */
- u8 isUnlocked; /* True if no DMS lock held */
struct ShmRegion {
HANDLE hMap; /* File handle from CreateFileMapping */
@@ -50550,8 +52132,8 @@ struct winShmNode {
} *aRegion;
DWORD lastErrno; /* The Windows errno from the last I/O error */
- int nRef; /* Number of winShm objects pointing to this */
- winShm *pFirst; /* All winShm objects pointing to this */
+ winShm *pWinShmList; /* List of winShm objects with ptrs to this */
+
winShmNode *pNext; /* Next in list of all winShmNode objects */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 nextShmId; /* Next available winShm.id value */
@@ -50567,26 +52149,19 @@ static winShmNode *winShmNodeList = 0;
/*
** Structure used internally by this VFS to record the state of an
-** open shared memory connection.
-**
-** The following fields are initialized when this object is created and
-** are read-only thereafter:
-**
-** winShm.pShmNode
-** winShm.id
-**
-** All other fields are read/write. The winShm.pShmNode->mutex must be held
-** while accessing any read/write fields.
+** open shared memory connection. There is one such structure for each
+** winFile open on a wal mode database.
*/
struct winShm {
winShmNode *pShmNode; /* The underlying winShmNode object */
- winShm *pNext; /* Next winShm with the same winShmNode */
- u8 hasMutex; /* True if holding the winShmNode mutex */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
+ HANDLE hShm; /* File-handle on *-shm file. For locking. */
+ int bReadonly; /* True if hShm is opened read-only */
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 id; /* Id of this connection with its winShmNode */
#endif
+ winShm *pWinShmNext; /* Next winShm object on same winShmNode */
};
/*
@@ -50595,56 +52170,12 @@ struct winShm {
#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
-/*
-** Apply advisory locks for all n bytes beginning at ofst.
-*/
-#define WINSHM_UNLCK 1
-#define WINSHM_RDLCK 2
-#define WINSHM_WRLCK 3
-static int winShmSystemLock(
- winShmNode *pFile, /* Apply locks to this open shared-memory segment */
- int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */
- int ofst, /* Offset to first byte to be locked/unlocked */
- int nByte /* Number of bytes to lock or unlock */
-){
- int rc = 0; /* Result code form Lock/UnlockFileEx() */
-
- /* Access to the winShmNode object is serialized by the caller */
- assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );
-
- OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
- pFile->hFile.h, lockType, ofst, nByte));
-
- /* Release/Acquire the system-level lock */
- if( lockType==WINSHM_UNLCK ){
- rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
- }else{
- /* Initialize the locking parameters */
- DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
- if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
- rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
- }
-
- if( rc!= 0 ){
- rc = SQLITE_OK;
- }else{
- pFile->lastErrno = osGetLastError();
- rc = SQLITE_BUSY;
- }
-
- OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
- pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" :
- "winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
-
- return rc;
-}
-
/* Forward references to VFS methods */
static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
static int winDelete(sqlite3_vfs *,const char*,int);
/*
-** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
+** Purge the winShmNodeList list of all entries with winShmNode.pWinShmList==0.
**
** This is not a VFS shared-memory method; it is a utility function called
** by VFS shared-memory methods.
@@ -50657,7 +52188,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
osGetCurrentProcessId(), deleteFlag));
pp = &winShmNodeList;
while( (p = *pp)!=0 ){
- if( p->nRef==0 ){
+ if( p->pWinShmList==0 ){
int i;
if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
for(i=0; inRegion; i++){
@@ -50670,11 +52201,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
UNUSED_VARIABLE_VALUE(bRc);
}
- if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
- SimulateIOErrorBenign(1);
- winClose((sqlite3_file *)&p->hFile);
- SimulateIOErrorBenign(0);
- }
+ winHandleClose(p->hSharedShm);
if( deleteFlag ){
SimulateIOErrorBenign(1);
sqlite3BeginBenignMalloc();
@@ -50692,42 +52219,196 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
}
/*
-** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
-** take it now. Return SQLITE_OK if successful, or an SQLite error
-** code otherwise.
-**
-** If the DMS cannot be locked because this is a readonly_shm=1
-** connection and no other process already holds a lock, return
-** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
+** The DMS lock has not yet been taken on the shm file associated with
+** pShmNode. Take the lock. Truncate the *-shm file if required.
+** Return SQLITE_OK if successful, or an SQLite error code otherwise.
*/
-static int winLockSharedMemory(winShmNode *pShmNode){
- int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
+static int winLockSharedMemory(winShmNode *pShmNode, DWORD nMs){
+ HANDLE h = pShmNode->hSharedShm;
+ int rc = SQLITE_OK;
+
+ assert( sqlite3_mutex_held(pShmNode->mutex) );
+ rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 1, 0);
+ if( rc==SQLITE_OK ){
+ /* We have an EXCLUSIVE lock on the DMS byte. This means that this
+ ** is the first process to open the file. Truncate it to zero bytes
+ ** in this case. */
+ if( pShmNode->isReadonly ){
+ rc = SQLITE_READONLY_CANTINIT;
+ }else{
+ rc = winHandleTruncate(h, 0);
+ }
+
+ /* Release the EXCLUSIVE lock acquired above. */
+ winUnlockFile(&h, WIN_SHM_DMS, 0, 1, 0);
+ }else if( (rc & 0xFF)==SQLITE_BUSY ){
+ rc = SQLITE_OK;
+ }
if( rc==SQLITE_OK ){
- if( pShmNode->isReadonly ){
- pShmNode->isUnlocked = 1;
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return SQLITE_READONLY_CANTINIT;
- }else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
- "winLockSharedMemory", pShmNode->zFilename);
+ /* Take a SHARED lock on the DMS byte. */
+ rc = winHandleLockTimeout(h, WIN_SHM_DMS, 1, 0, nMs);
+ if( rc==SQLITE_OK ){
+ pShmNode->isUnlocked = 0;
}
}
- if( rc==SQLITE_OK ){
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
+ return rc;
+}
+
+
+/*
+** This function is used to open a handle on a *-shm file.
+**
+** If SQLITE_ENABLE_SETLK_TIMEOUT is defined at build time, then the file
+** is opened with FILE_FLAG_OVERLAPPED specified. If not, it is not.
+*/
+static int winHandleOpen(
+ const char *zUtf8, /* File to open */
+ int *pbReadonly, /* IN/OUT: True for readonly handle */
+ HANDLE *ph /* OUT: New HANDLE for file */
+){
+ int rc = SQLITE_OK;
+ void *zConverted = 0;
+ int bReadonly = *pbReadonly;
+ HANDLE h = INVALID_HANDLE_VALUE;
+
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ const DWORD flag_overlapped = FILE_FLAG_OVERLAPPED;
+#else
+ const DWORD flag_overlapped = 0;
+#endif
+
+ /* Convert the filename to the system encoding. */
+ zConverted = winConvertFromUtf8Filename(zUtf8);
+ if( zConverted==0 ){
+ OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8));
+ rc = SQLITE_IOERR_NOMEM_BKPT;
+ goto winopenfile_out;
}
- return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
+ /* Ensure the file we are trying to open is not actually a directory. */
+ if( winIsDir(zConverted) ){
+ OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8));
+ rc = SQLITE_CANTOPEN_ISDIR;
+ goto winopenfile_out;
+ }
+
+ /* TODO: platforms.
+ ** TODO: retry-on-ioerr.
+ */
+ if( osIsNT() ){
+#if SQLITE_OS_WINRT
+ CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
+ memset(&extendedParameters, 0, sizeof(extendedParameters));
+ extendedParameters.dwSize = sizeof(extendedParameters);
+ extendedParameters.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+ extendedParameters.dwFileFlags = flag_overlapped;
+ extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
+ h = osCreateFile2((LPCWSTR)zConverted,
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)),/* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ &extendedParameters
+ );
+#else
+ h = osCreateFileW((LPCWSTR)zConverted, /* lpFileName */
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL|flag_overlapped,
+ NULL
+ );
+#endif
+ }else{
+ /* Due to pre-processor directives earlier in this file,
+ ** SQLITE_WIN32_HAS_ANSI is always defined if osIsNT() is false. */
+#ifdef SQLITE_WIN32_HAS_ANSI
+ h = osCreateFileA((LPCSTR)zConverted,
+ (GENERIC_READ | (bReadonly ? 0 : GENERIC_WRITE)), /* dwDesiredAccess */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode */
+ NULL, /* lpSecurityAttributes */
+ OPEN_ALWAYS, /* dwCreationDisposition */
+ FILE_ATTRIBUTE_NORMAL|flag_overlapped,
+ NULL
+ );
+#endif
+ }
+
+ if( h==INVALID_HANDLE_VALUE ){
+ if( bReadonly==0 ){
+ bReadonly = 1;
+ rc = winHandleOpen(zUtf8, &bReadonly, &h);
+ }else{
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+ }
+
+ winopenfile_out:
+ sqlite3_free(zConverted);
+ *pbReadonly = bReadonly;
+ *ph = h;
+ return rc;
+}
+
+/*
+** Close pDbFd's connection to shared-memory. Delete the underlying
+** *-shm file if deleteFlag is true.
+*/
+static int winCloseSharedMemory(winFile *pDbFd, int deleteFlag){
+ winShm *p; /* The connection to be closed */
+ winShm **pp; /* Iterator for pShmNode->pWinShmList */
+ winShmNode *pShmNode; /* The underlying shared-memory file */
+
+ p = pDbFd->pShm;
+ if( p==0 ) return SQLITE_OK;
+ if( p->hShm!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(p->hShm);
+ }
+
+ winShmEnterMutex();
+ pShmNode = p->pShmNode;
+
+ /* Remove this connection from the winShmNode.pWinShmList list */
+ sqlite3_mutex_enter(pShmNode->mutex);
+ for(pp=&pShmNode->pWinShmList; *pp!=p; pp=&(*pp)->pWinShmNext){}
+ *pp = p->pWinShmNext;
+ sqlite3_mutex_leave(pShmNode->mutex);
+
+ winShmPurge(pDbFd->pVfs, deleteFlag);
+ winShmLeaveMutex();
+
+ /* Free the connection p */
+ sqlite3_free(p);
+ pDbFd->pShm = 0;
+ return SQLITE_OK;
+}
+
+/*
+** testfixture builds may set this global variable to true via a
+** Tcl interface. This forces the VFS to use the locking normally
+** only used for UNC paths for all files.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_win_test_unc_locking = 0;
+#else
+# define sqlite3_win_test_unc_locking 0
+#endif
+
+/*
+** Return true if the string passed as the only argument is likely
+** to be a UNC path. In other words, if it starts with "\\".
+*/
+static int winIsUNCPath(const char *zFile){
+ if( zFile[0]=='\\' && zFile[1]=='\\' ){
+ return 1;
+ }
+ return sqlite3_win_test_unc_locking;
}
/*
** Open the shared-memory area associated with database file pDbFd.
-**
-** When opening a new shared-memory file, if no other instances of that
-** file are currently open, in this process or in other processes, then
-** the file must be truncated to zero length or have its header cleared.
*/
static int winOpenSharedMemory(winFile *pDbFd){
struct winShm *p; /* The connection to be opened */
@@ -50739,98 +52420,93 @@ static int winOpenSharedMemory(winFile *pDbFd){
assert( pDbFd->pShm==0 ); /* Not previously opened */
/* Allocate space for the new sqlite3_shm object. Also speculatively
- ** allocate space for a new winShmNode and filename.
- */
+ ** allocate space for a new winShmNode and filename. */
p = sqlite3MallocZero( sizeof(*p) );
if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT;
nName = sqlite3Strlen30(pDbFd->zPath);
- pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
+ pNew = sqlite3MallocZero( sizeof(*pShmNode) + (i64)nName + 17 );
if( pNew==0 ){
sqlite3_free(p);
return SQLITE_IOERR_NOMEM_BKPT;
}
pNew->zFilename = (char*)&pNew[1];
+ pNew->hSharedShm = INVALID_HANDLE_VALUE;
+ pNew->isUnlocked = 1;
+ pNew->bUseSharedLockHandle = winIsUNCPath(pDbFd->zPath);
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
/* Look to see if there is an existing winShmNode that can be used.
- ** If no matching winShmNode currently exists, create a new one.
- */
+ ** If no matching winShmNode currently exists, then create a new one. */
winShmEnterMutex();
for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
/* TBD need to come up with better match here. Perhaps
- ** use FILE_ID_BOTH_DIR_INFO Structure.
- */
+ ** use FILE_ID_BOTH_DIR_INFO Structure. */
if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
}
- if( pShmNode ){
- sqlite3_free(pNew);
- }else{
- int inFlags = SQLITE_OPEN_WAL;
- int outFlags = 0;
-
+ if( pShmNode==0 ){
pShmNode = pNew;
- pNew = 0;
- ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
- pShmNode->pNext = winShmNodeList;
- winShmNodeList = pShmNode;
+ /* Allocate a mutex for this winShmNode object, if one is required. */
if( sqlite3GlobalConfig.bCoreMutex ){
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- if( pShmNode->mutex==0 ){
- rc = SQLITE_IOERR_NOMEM_BKPT;
- goto shm_open_err;
+ if( pShmNode->mutex==0 ) rc = SQLITE_IOERR_NOMEM_BKPT;
+ }
+
+ /* Open a file-handle to use for mappings, and for the DMS lock. */
+ if( rc==SQLITE_OK ){
+ HANDLE h = INVALID_HANDLE_VALUE;
+ pShmNode->isReadonly = sqlite3_uri_boolean(pDbFd->zPath,"readonly_shm",0);
+ rc = winHandleOpen(pNew->zFilename, &pShmNode->isReadonly, &h);
+ pShmNode->hSharedShm = h;
+ }
+
+ /* If successful, link the new winShmNode into the global list. If an
+ ** error occurred, free the object. */
+ if( rc==SQLITE_OK ){
+ pShmNode->pNext = winShmNodeList;
+ winShmNodeList = pShmNode;
+ pNew = 0;
+ }else{
+ sqlite3_mutex_free(pShmNode->mutex);
+ if( pShmNode->hSharedShm!=INVALID_HANDLE_VALUE ){
+ osCloseHandle(pShmNode->hSharedShm);
}
}
-
- if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
- inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
- }else{
- inFlags |= SQLITE_OPEN_READONLY;
- }
- rc = winOpen(pDbFd->pVfs, pShmNode->zFilename,
- (sqlite3_file*)&pShmNode->hFile,
- inFlags, &outFlags);
- if( rc!=SQLITE_OK ){
- rc = winLogError(rc, osGetLastError(), "winOpenShm",
- pShmNode->zFilename);
- goto shm_open_err;
- }
- if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1;
-
- rc = winLockSharedMemory(pShmNode);
- if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
}
- /* Make the new connection a child of the winShmNode */
- p->pShmNode = pShmNode;
+ /* If no error has occurred, link the winShm object to the winShmNode and
+ ** the winShm to pDbFd. */
+ if( rc==SQLITE_OK ){
+ sqlite3_mutex_enter(pShmNode->mutex);
+ p->pShmNode = pShmNode;
+ p->pWinShmNext = pShmNode->pWinShmList;
+ pShmNode->pWinShmList = p;
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
- p->id = pShmNode->nextShmId++;
+ p->id = pShmNode->nextShmId++;
#endif
- pShmNode->nRef++;
- pDbFd->pShm = p;
+ pDbFd->pShm = p;
+ sqlite3_mutex_leave(pShmNode->mutex);
+ }else if( p ){
+ sqlite3_free(p);
+ }
+
+ assert( rc!=SQLITE_OK || pShmNode->isUnlocked==0 || pShmNode->nRegion==0 );
winShmLeaveMutex();
-
- /* The reference count on pShmNode has already been incremented under
- ** the cover of the winShmEnterMutex() mutex and the pointer from the
- ** new (struct winShm) object to the pShmNode has been set. All that is
- ** left to do is to link the new object into the linked list starting
- ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
- ** mutex.
- */
- sqlite3_mutex_enter(pShmNode->mutex);
- p->pNext = pShmNode->pFirst;
- pShmNode->pFirst = p;
- sqlite3_mutex_leave(pShmNode->mutex);
- return rc;
-
- /* Jump here on any error */
-shm_open_err:
- winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
- winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
- sqlite3_free(p);
sqlite3_free(pNew);
- winShmLeaveMutex();
+
+ /* Open a file-handle on the *-shm file for this connection. This file-handle
+ ** is only used for locking. The mapping of the *-shm file is created using
+ ** the shared file handle in winShmNode.hSharedShm. */
+ if( rc==SQLITE_OK && pShmNode->bUseSharedLockHandle==0 ){
+ p->bReadonly = sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0);
+ rc = winHandleOpen(pShmNode->zFilename, &p->bReadonly, &p->hShm);
+ if( rc!=SQLITE_OK ){
+ assert( p->hShm==INVALID_HANDLE_VALUE );
+ winCloseSharedMemory(pDbFd, 0);
+ }
+ }
+
return rc;
}
@@ -50842,38 +52518,7 @@ static int winShmUnmap(
sqlite3_file *fd, /* Database holding shared memory */
int deleteFlag /* Delete after closing if true */
){
- winFile *pDbFd; /* Database holding shared-memory */
- winShm *p; /* The connection to be closed */
- winShmNode *pShmNode; /* The underlying shared-memory file */
- winShm **pp; /* For looping over sibling connections */
-
- pDbFd = (winFile*)fd;
- p = pDbFd->pShm;
- if( p==0 ) return SQLITE_OK;
- pShmNode = p->pShmNode;
-
- /* Remove connection p from the set of connections associated
- ** with pShmNode */
- sqlite3_mutex_enter(pShmNode->mutex);
- for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
- *pp = p->pNext;
-
- /* Free the connection p */
- sqlite3_free(p);
- pDbFd->pShm = 0;
- sqlite3_mutex_leave(pShmNode->mutex);
-
- /* If pShmNode->nRef has reached 0, then close the underlying
- ** shared-memory file, too */
- winShmEnterMutex();
- assert( pShmNode->nRef>0 );
- pShmNode->nRef--;
- if( pShmNode->nRef==0 ){
- winShmPurge(pDbFd->pVfs, deleteFlag);
- }
- winShmLeaveMutex();
-
- return SQLITE_OK;
+ return winCloseSharedMemory((winFile*)fd, deleteFlag);
}
/*
@@ -50887,10 +52532,9 @@ static int winShmLock(
){
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
winShm *p = pDbFd->pShm; /* The shared memory being locked */
- winShm *pX; /* For looping over all siblings */
winShmNode *pShmNode;
int rc = SQLITE_OK; /* Result code */
- u16 mask; /* Mask of locks to take or release */
+ u16 mask = (u16)((1U<<(ofst+n)) - (1U<pShmNode;
@@ -50904,85 +52548,127 @@ static int winShmLock(
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
- mask = (u16)((1U<<(ofst+n)) - (1U<1 || mask==(1<mutex);
- if( flags & SQLITE_SHM_UNLOCK ){
- u16 allMask = 0; /* Mask of locks held by siblings */
+ /* Check that, if this to be a blocking lock, no locks that occur later
+ ** in the following list than the lock being obtained are already held:
+ **
+ ** 1. Recovery lock (ofst==2).
+ ** 2. Checkpointer lock (ofst==1).
+ ** 3. Write lock (ofst==0).
+ ** 4. Read locks (ofst>=3 && ofstexclMask|p->sharedMask);
+ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
+ (ofst!=2 || lockMask==0)
+ && (ofst!=1 || lockMask==0 || lockMask==2)
+ && (ofst!=0 || lockMask<3)
+ && (ofst<3 || lockMask<(1<pFirst; pX; pX=pX->pNext){
- if( pX==p ) continue;
- assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
- allMask |= pX->sharedMask;
- }
+ /* Check if there is any work to do. There are three cases:
+ **
+ ** a) An unlock operation where there are locks to unlock,
+ ** b) An shared lock where the requested lock is not already held
+ ** c) An exclusive lock where the requested lock is not already held
+ **
+ ** The SQLite core never requests an exclusive lock that it already holds.
+ ** This is assert()ed immediately below. */
+ assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
+ || 0==(p->exclMask & mask)
+ );
+ if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
+ || (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
+ || (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
+ ){
+ HANDLE h = p->hShm;
- /* Unlock the system-level locks */
- if( (mask & allMask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
- }
+ if( flags & SQLITE_SHM_UNLOCK ){
+ /* Case (a) - unlock. */
- /* Undo the local locks */
- if( rc==SQLITE_OK ){
- p->exclMask &= ~mask;
- p->sharedMask &= ~mask;
- }
- }else if( flags & SQLITE_SHM_SHARED ){
- u16 allShared = 0; /* Union of locks held by connections other than "p" */
+ assert( (p->exclMask & p->sharedMask)==0 );
+ assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
+ assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
- /* Find out which shared locks are already held by sibling connections.
- ** If any sibling already holds an exclusive lock, go ahead and return
- ** SQLITE_BUSY.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
+ assert( !(flags & SQLITE_SHM_SHARED) || n==1 );
+ if( pShmNode->bUseSharedLockHandle ){
+ h = pShmNode->hSharedShm;
+ if( flags & SQLITE_SHM_SHARED ){
+ winShm *pShm;
+ sqlite3_mutex_enter(pShmNode->mutex);
+ for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){
+ if( pShm!=p && (pShm->sharedMask & mask) ){
+ /* Another connection within this process is also holding this
+ ** SHARED lock. So do not actually release the OS lock. */
+ h = INVALID_HANDLE_VALUE;
+ break;
+ }
+ }
+ sqlite3_mutex_leave(pShmNode->mutex);
+ }
}
- allShared |= pX->sharedMask;
- }
- /* Get shared locks at the system level, if necessary */
- if( rc==SQLITE_OK ){
- if( (allShared & mask)==0 ){
- rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n);
- }else{
- rc = SQLITE_OK;
+ if( h!=INVALID_HANDLE_VALUE ){
+ rc = winHandleUnlock(h, ofst+WIN_SHM_BASE, n);
}
- }
- /* Get the local shared locks */
- if( rc==SQLITE_OK ){
- p->sharedMask |= mask;
- }
- }else{
- /* Make sure no sibling connections hold locks that will block this
- ** lock. If any do, return SQLITE_BUSY right away.
- */
- for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
- if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
- rc = SQLITE_BUSY;
- break;
- }
- }
-
- /* Get the exclusive locks at the system level. Then if successful
- ** also mark the local connection as being locked.
- */
- if( rc==SQLITE_OK ){
- rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n);
+ /* If successful, also clear the bits in sharedMask/exclMask */
if( rc==SQLITE_OK ){
- assert( (p->sharedMask & mask)==0 );
- p->exclMask |= mask;
+ p->exclMask = (p->exclMask & ~mask);
+ p->sharedMask = (p->sharedMask & ~mask);
+ }
+ }else{
+ int bExcl = ((flags & SQLITE_SHM_EXCLUSIVE) ? 1 : 0);
+ DWORD nMs = winFileBusyTimeout(pDbFd);
+
+ if( pShmNode->bUseSharedLockHandle ){
+ winShm *pShm;
+ h = pShmNode->hSharedShm;
+ sqlite3_mutex_enter(pShmNode->mutex);
+ for(pShm=pShmNode->pWinShmList; pShm; pShm=pShm->pWinShmNext){
+ if( bExcl ){
+ if( (pShm->sharedMask|pShm->exclMask) & mask ){
+ rc = SQLITE_BUSY;
+ h = INVALID_HANDLE_VALUE;
+ }
+ }else{
+ if( pShm->sharedMask & mask ){
+ h = INVALID_HANDLE_VALUE;
+ }else if( pShm->exclMask & mask ){
+ rc = SQLITE_BUSY;
+ h = INVALID_HANDLE_VALUE;
+ }
+ }
+ }
+ sqlite3_mutex_leave(pShmNode->mutex);
+ }
+
+ if( h!=INVALID_HANDLE_VALUE ){
+ rc = winHandleLockTimeout(h, ofst+WIN_SHM_BASE, n, bExcl, nMs);
+ }
+ if( rc==SQLITE_OK ){
+ if( bExcl ){
+ p->exclMask = (p->exclMask | mask);
+ }else{
+ p->sharedMask = (p->sharedMask | mask);
+ }
}
}
}
- sqlite3_mutex_leave(pShmNode->mutex);
- OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
- osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
- sqlite3ErrName(rc)));
+
+ OSTRACE((
+ "SHM-LOCK(%d,%d,%d) pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x,"
+ " rc=%s\n",
+ ofst, n, flags,
+ osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
+ sqlite3ErrName(rc))
+ );
return rc;
}
@@ -51044,13 +52730,15 @@ static int winShmMap(
sqlite3_mutex_enter(pShmNode->mutex);
if( pShmNode->isUnlocked ){
- rc = winLockSharedMemory(pShmNode);
+ /* Take the DMS lock. */
+ assert( pShmNode->nRegion==0 );
+ rc = winLockSharedMemory(pShmNode, winFileBusyTimeout(pDbFd));
if( rc!=SQLITE_OK ) goto shmpage_out;
- pShmNode->isUnlocked = 0;
}
- assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
+ assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
if( pShmNode->nRegion<=iRegion ){
+ HANDLE hShared = pShmNode->hSharedShm;
struct ShmRegion *apNew; /* New aRegion[] array */
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
sqlite3_int64 sz; /* Current size of wal-index file */
@@ -51061,10 +52749,9 @@ static int winShmMap(
** Check to see if it has been allocated (i.e. if the wal-index file is
** large enough to contain the requested region).
*/
- rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
+ rc = winHandleSize(hShared, &sz);
if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap1", pDbFd->zPath);
+ rc = winLogError(rc, osGetLastError(), "winShmMap1", pDbFd->zPath);
goto shmpage_out;
}
@@ -51073,19 +52760,17 @@ static int winShmMap(
** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
**
** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
- ** the requested memory region.
- */
+ ** the requested memory region. */
if( !isWrite ) goto shmpage_out;
- rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
+ rc = winHandleTruncate(hShared, nByte);
if( rc!=SQLITE_OK ){
- rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
- "winShmMap2", pDbFd->zPath);
+ rc = winLogError(rc, osGetLastError(), "winShmMap2", pDbFd->zPath);
goto shmpage_out;
}
}
/* Map the requested memory region into this processes address space. */
- apNew = (struct ShmRegion *)sqlite3_realloc64(
+ apNew = (struct ShmRegion*)sqlite3_realloc64(
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
@@ -51104,18 +52789,13 @@ static int winShmMap(
void *pMap = 0; /* Mapped memory region */
#if SQLITE_OS_WINRT
- hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
- NULL, protect, nByte, NULL
- );
+ hMap = osCreateFileMappingFromApp(hShared, NULL, protect, nByte, NULL);
#elif defined(SQLITE_WIN32_HAS_WIDE)
- hMap = osCreateFileMappingW(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
+ hMap = osCreateFileMappingW(hShared, NULL, protect, 0, nByte, NULL);
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
- hMap = osCreateFileMappingA(pShmNode->hFile.h,
- NULL, protect, 0, nByte, NULL
- );
+ hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL);
#endif
+
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
hMap ? "ok" : "failed"));
@@ -51158,7 +52838,9 @@ shmpage_out:
}else{
*pp = 0;
}
- if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
+ if( pShmNode->isReadonly && rc==SQLITE_OK ){
+ rc = SQLITE_READONLY;
+ }
sqlite3_mutex_leave(pShmNode->mutex);
return rc;
}
@@ -51478,47 +53160,6 @@ static winVfsAppData winNolockAppData = {
** sqlite3_vfs object.
*/
-#if defined(__CYGWIN__)
-/*
-** Convert a filename from whatever the underlying operating system
-** supports for filenames into UTF-8. Space to hold the result is
-** obtained from malloc and must be freed by the calling function.
-*/
-static char *winConvertToUtf8Filename(const void *zFilename){
- char *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUnicodeToUtf8(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-#endif
-
-/*
-** Convert a UTF-8 filename into whatever form the underlying
-** operating system wants filenames in. Space to hold the result
-** is obtained from malloc and must be freed by the calling
-** function.
-*/
-static void *winConvertFromUtf8Filename(const char *zFilename){
- void *zConverted = 0;
- if( osIsNT() ){
- zConverted = winUtf8ToUnicode(zFilename);
- }
-#ifdef SQLITE_WIN32_HAS_ANSI
- else{
- zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
- }
-#endif
- /* caller will handle out of memory */
- return zConverted;
-}
-
/*
** This function returns non-zero if the specified UTF-8 string buffer
** ends with a directory separator character or one was successfully
@@ -51531,7 +53172,14 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){
if( winIsDirSep(zBuf[nLen-1]) ){
return 1;
}else if( nLen+1mxPathname; nBuf = nMax + 2;
+ nMax = pVfs->mxPathname;
+ nBuf = 2 + (i64)nMax;
zBuf = sqlite3MallocZero( nBuf );
if( !zBuf ){
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
@@ -51608,7 +53257,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
}
#if defined(__CYGWIN__)
- else{
+ else if( osGetenv!=NULL ){
static const char *azDirs[] = {
0, /* getenv("SQLITE_TMPDIR") */
0, /* getenv("TMPDIR") */
@@ -51624,11 +53273,11 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
unsigned int i;
const char *zDir = 0;
- if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
- if( !azDirs[2] ) azDirs[2] = getenv("TMP");
- if( !azDirs[3] ) azDirs[3] = getenv("TEMP");
- if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE");
+ if( !azDirs[0] ) azDirs[0] = osGetenv("SQLITE_TMPDIR");
+ if( !azDirs[1] ) azDirs[1] = osGetenv("TMPDIR");
+ if( !azDirs[2] ) azDirs[2] = osGetenv("TMP");
+ if( !azDirs[3] ) azDirs[3] = osGetenv("TEMP");
+ if( !azDirs[4] ) azDirs[4] = osGetenv("USERPROFILE");
for(i=0; inOut ){
+ /* SQLite assumes that xFullPathname() nul-terminates the output buffer
+ ** even if it returns an error. */
+ zOut[iOff] = '\0';
+ return SQLITE_CANTOPEN_BKPT;
+ }
+ sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
+ return SQLITE_OK;
+}
+#endif /* __CYGWIN__ */
/*
** Turn a relative pathname into a full pathname. Write the full
@@ -52411,8 +54109,8 @@ static int winFullPathnameNoMutex(
int nFull, /* Size of output buffer in bytes */
char *zFull /* Output buffer */
){
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
- DWORD nByte;
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+ int nByte;
void *zConverted;
char *zOut;
#endif
@@ -52425,64 +54123,82 @@ static int winFullPathnameNoMutex(
zRelative++;
}
-#if defined(__CYGWIN__)
SimulateIOError( return SQLITE_ERROR );
- UNUSED_PARAMETER(nFull);
- assert( nFull>=pVfs->mxPathname );
- if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
- /*
- ** NOTE: We are dealing with a relative path name and the data
- ** directory has been set. Therefore, use it as the basis
- ** for converting the relative path name to an absolute
- ** one by prepending the data directory and a slash.
- */
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) |
- CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname1", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
- sqlite3_data_directory, winGetDirSep(), zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
- }
- }else{
- char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
- if( !zOut ){
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- if( cygwin_conv_path(
- (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A),
- zRelative, zOut, pVfs->mxPathname+1)<0 ){
- sqlite3_free(zOut);
- return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
- "winFullPathname2", zRelative);
- }else{
- char *zUtf8 = winConvertToUtf8Filename(zOut);
- if( !zUtf8 ){
- sqlite3_free(zOut);
- return SQLITE_IOERR_NOMEM_BKPT;
- }
- sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
- sqlite3_free(zUtf8);
- sqlite3_free(zOut);
+
+#ifdef __CYGWIN__
+ if( osGetcwd ){
+ zFull[nFull-1] = '\0';
+ if( !winIsDriveLetterAndColon(zRelative) || !winIsDirSep(zRelative[2]) ){
+ int rc = SQLITE_OK;
+ int nLink = 1; /* Number of symbolic links followed so far */
+ const char *zIn = zRelative; /* Input path for each iteration of loop */
+ char *zDel = 0;
+ struct stat buf;
+
+ UNUSED_PARAMETER(pVfs);
+
+ do {
+ /* Call lstat() on path zIn. Set bLink to true if the path is a symbolic
+ ** link, or false otherwise. */
+ int bLink = 0;
+ if( osLstat && osReadlink ) {
+ if( osLstat(zIn, &buf)!=0 ){
+ int myErrno = osErrno;
+ if( myErrno!=ENOENT ){
+ rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)myErrno, "lstat", zIn);
+ }
+ }else{
+ bLink = ((buf.st_mode & 0170000) == 0120000);
+ }
+
+ if( bLink ){
+ if( zDel==0 ){
+ zDel = sqlite3MallocZero(nFull);
+ if( zDel==0 ) rc = SQLITE_NOMEM;
+ }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ }
+
+ if( rc==SQLITE_OK ){
+ nByte = osReadlink(zIn, zDel, nFull-1);
+ if( nByte ==(DWORD)-1 ){
+ rc = winLogError(SQLITE_CANTOPEN_BKPT, (DWORD)osErrno, "readlink", zIn);
+ }else{
+ if( zDel[0]!='/' ){
+ int n;
+ for(n = sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
+ if( nByte+n+1>nFull ){
+ rc = SQLITE_CANTOPEN_BKPT;
+ }else{
+ memmove(&zDel[n], zDel, nByte+1);
+ memcpy(zDel, zIn, n);
+ nByte += n;
+ }
+ }
+ zDel[nByte] = '\0';
+ }
+ }
+
+ zIn = zDel;
+ }
+ }
+
+ assert( rc!=SQLITE_OK || zIn!=zFull || zIn[0]=='/' );
+ if( rc==SQLITE_OK && zIn!=zFull ){
+ rc = mkFullPathname(zIn, zFull, nFull);
+ }
+ if( bLink==0 ) break;
+ zIn = zFull;
+ }while( rc==SQLITE_OK );
+
+ sqlite3_free(zDel);
+ winSimplifyName(zFull);
+ return rc;
}
}
- return SQLITE_OK;
-#endif
+#endif /* __CYGWIN__ */
-#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
+#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && defined(_WIN32)
SimulateIOError( return SQLITE_ERROR );
/* WinCE has no concept of a relative pathname, or so I am told. */
/* WinRT has no way to convert a relative path to an absolute one. */
@@ -52501,7 +54217,8 @@ static int winFullPathnameNoMutex(
return SQLITE_OK;
#endif
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+#if defined(_WIN32)
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
** function failing. This function could fail if, for example, the
@@ -52519,6 +54236,7 @@ static int winFullPathnameNoMutex(
sqlite3_data_directory, winGetDirSep(), zRelative);
return SQLITE_OK;
}
+#endif
zConverted = winConvertFromUtf8Filename(zRelative);
if( zConverted==0 ){
return SQLITE_IOERR_NOMEM_BKPT;
@@ -52557,13 +54275,12 @@ static int winFullPathnameNoMutex(
return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
"winFullPathname3", zRelative);
}
- nByte += 3;
- zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
+ zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) + 3*sizeof(zTemp[0]) );
if( zTemp==0 ){
sqlite3_free(zConverted);
return SQLITE_IOERR_NOMEM_BKPT;
}
- nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+ nByte = osGetFullPathNameA((char*)zConverted, nByte+3, zTemp, 0);
if( nByte==0 ){
sqlite3_free(zConverted);
sqlite3_free(zTemp);
@@ -52576,7 +54293,26 @@ static int winFullPathnameNoMutex(
}
#endif
if( zOut ){
+#ifdef __CYGWIN__
+ if( memcmp(zOut, "\\\\?\\", 4) ){
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
+ }else if( memcmp(zOut+4, "UNC\\", 4) ){
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+4);
+ }else{
+ char *p = zOut+6;
+ *p = '\\';
+ if( osGetcwd ){
+ /* On Cygwin, UNC paths use forward slashes */
+ while( *p ){
+ if( *p=='\\' ) *p = '/';
+ ++p;
+ }
+ }
+ sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut+6);
+ }
+#else
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
+#endif /* __CYGWIN__ */
sqlite3_free(zOut);
return SQLITE_OK;
}else{
@@ -52606,25 +54342,8 @@ static int winFullPathname(
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
-#if defined(__CYGWIN__)
- int nFull = pVfs->mxPathname+1;
- char *zFull = sqlite3MallocZero( nFull );
- void *zConverted = 0;
- if( zFull==0 ){
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
- sqlite3_free(zFull);
- OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
- return 0;
- }
- zConverted = winConvertFromUtf8Filename(zFull);
- sqlite3_free(zFull);
-#else
void *zConverted = winConvertFromUtf8Filename(zFilename);
UNUSED_PARAMETER(pVfs);
-#endif
if( zConverted==0 ){
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
return 0;
@@ -52973,7 +54692,7 @@ SQLITE_API int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==80 );
+ assert( ArraySize(aSyscall)==89 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
@@ -53592,13 +55311,13 @@ static int memdbOpen(
}
if( p==0 ){
MemStore **apNew;
- p = sqlite3Malloc( sizeof(*p) + szName + 3 );
+ p = sqlite3Malloc( sizeof(*p) + (i64)szName + 3 );
if( p==0 ){
sqlite3_mutex_leave(pVfsMutex);
return SQLITE_NOMEM;
}
apNew = sqlite3Realloc(memdb_g.apMemStore,
- sizeof(apNew[0])*(memdb_g.nMemStore+1) );
+ sizeof(apNew[0])*(1+(i64)memdb_g.nMemStore) );
if( apNew==0 ){
sqlite3_free(p);
sqlite3_mutex_leave(pVfsMutex);
@@ -54031,7 +55750,7 @@ SQLITE_PRIVATE int sqlite3MemdbInit(void){
** no fewer collisions than the no-op *1. */
#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
-#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
+#define BITVEC_NPTR ((u32)(BITVEC_USIZE/sizeof(Bitvec *)))
/*
@@ -54071,6 +55790,7 @@ struct Bitvec {
} u;
};
+
/*
** Create a new bitmap object able to handle bits between 0 and iSize,
** inclusive. Return a pointer to the new object. Return NULL if
@@ -54180,7 +55900,9 @@ bitvec_set_rehash:
}else{
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
memset(p->u.apSub, 0, sizeof(p->u.apSub));
- p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
+ p->iDivisor = p->iSize/BITVEC_NPTR;
+ if( (p->iSize%BITVEC_NPTR)!=0 ) p->iDivisor++;
+ if( p->iDivisoriDivisor = BITVEC_NBIT;
rc = sqlite3BitvecSet(p, i);
for(j=0; jiSize<=BITVEC_NBIT ){
- p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
+ p->u.aBitmap[i/BITVEC_SZELEM] &= ~(BITVEC_TELEM)(1<<(i&(BITVEC_SZELEM-1)));
}else{
unsigned int j;
u32 *aiValues = pBuf;
@@ -54257,6 +55979,52 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
return p->iSize;
}
+#ifdef SQLITE_DEBUG
+/*
+** Show the content of a Bitvec option and its children. Indent
+** everything by n spaces. Add x to each bitvec value.
+**
+** From a debugger such as gdb, one can type:
+**
+** call sqlite3ShowBitvec(p)
+**
+** For some Bitvec p and see a recursive view of the Bitvec's content.
+*/
+static void showBitvec(Bitvec *p, int n, unsigned x){
+ int i;
+ if( p==0 ){
+ printf("NULL\n");
+ return;
+ }
+ printf("Bitvec 0x%p iSize=%u", p, p->iSize);
+ if( p->iSize<=BITVEC_NBIT ){
+ printf(" bitmap\n");
+ printf("%*s bits:", n, "");
+ for(i=1; i<=BITVEC_NBIT; i++){
+ if( sqlite3BitvecTest(p,i) ) printf(" %u", x+(unsigned)i);
+ }
+ printf("\n");
+ }else if( p->iDivisor==0 ){
+ printf(" hash with %u entries\n", p->nSet);
+ printf("%*s bits:", n, "");
+ for(i=0; iu.aHash[i] ) printf(" %u", x+(unsigned)p->u.aHash[i]);
+ }
+ printf("\n");
+ }else{
+ printf(" sub-bitvec with iDivisor=%u\n", p->iDivisor);
+ for(i=0; iu.apSub[i]==0 ) continue;
+ printf("%*s apSub[%d]=", n, "", i);
+ showBitvec(p->u.apSub[i], n+4, i*p->iDivisor);
+ }
+ }
+}
+SQLITE_PRIVATE void sqlite3ShowBitvec(Bitvec *p){
+ showBitvec(p, 0, 0);
+}
+#endif
+
#ifndef SQLITE_UNTESTABLE
/*
** Let V[] be an array of unsigned characters sufficient to hold
@@ -54265,9 +56033,10 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
** individual bits within V.
*/
#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
-#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
+#define CLEARBIT(V,I) V[I>>3] &= ~(BITVEC_TELEM)(1<<(I&7))
#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
+
/*
** This routine runs an extensive test of the Bitvec code.
**
@@ -54276,7 +56045,7 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
** by 0, 1, or 3 operands, depending on the opcode. Another
** opcode follows immediately after the last operand.
**
-** There are 6 opcodes numbered from 0 through 5. 0 is the
+** There are opcodes numbered starting with 0. 0 is the
** "halt" opcode and causes the test to end.
**
** 0 Halt and return the number of errors
@@ -54285,18 +56054,25 @@ SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
** 3 N Set N randomly chosen bits
** 4 N Clear N randomly chosen bits
** 5 N S X Set N bits from S increment X in array only, not in bitvec
+** 6 Invoice sqlite3ShowBitvec() on the Bitvec object so far
+** 7 X Show compile-time parameters and the hash of X
**
** The opcodes 1 through 4 perform set and clear operations are performed
** on both a Bitvec object and on a linear array of bits obtained from malloc.
** Opcode 5 works on the linear array only, not on the Bitvec.
** Opcode 5 is used to deliberately induce a fault in order to
-** confirm that error detection works.
+** confirm that error detection works. Opcodes 6 and greater are
+** state output opcodes. Opcodes 6 and greater are no-ops unless
+** SQLite has been compiled with SQLITE_DEBUG.
**
** At the conclusion of the test the linear array is compared
** against the Bitvec object. If there are any differences,
** an error is returned. If they are the same, zero is returned.
**
** If a memory allocation error occurs, return -1.
+**
+** sz is the size of the Bitvec. Or if sz is negative, make the size
+** 2*(unsigned)(-sz) and disabled the linear vector check.
*/
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
Bitvec *pBitvec = 0;
@@ -54307,10 +56083,15 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
/* Allocate the Bitvec to be tested and a linear array of
** bits to act as the reference */
- pBitvec = sqlite3BitvecCreate( sz );
- pV = sqlite3MallocZero( (sz+7)/8 + 1 );
+ if( sz<=0 ){
+ pBitvec = sqlite3BitvecCreate( 2*(unsigned)(-sz) );
+ pV = 0;
+ }else{
+ pBitvec = sqlite3BitvecCreate( sz );
+ pV = sqlite3MallocZero( (7+(i64)sz)/8 + 1 );
+ }
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
- if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
+ if( pBitvec==0 || pTmpSpace==0 || (pV==0 && sz>0) ) goto bitvec_end;
/* NULL pBitvec tests */
sqlite3BitvecSet(0, 1);
@@ -54319,6 +56100,24 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
/* Run the program */
pc = i = 0;
while( (op = aOp[pc])!=0 ){
+ if( op>=6 ){
+#ifdef SQLITE_DEBUG
+ if( op==6 ){
+ sqlite3ShowBitvec(pBitvec);
+ }else if( op==7 ){
+ printf("BITVEC_SZ = %d (%d by sizeof)\n",
+ BITVEC_SZ, (int)sizeof(Bitvec));
+ printf("BITVEC_USIZE = %d\n", (int)BITVEC_USIZE);
+ printf("BITVEC_NELEM = %d\n", (int)BITVEC_NELEM);
+ printf("BITVEC_NBIT = %d\n", (int)BITVEC_NBIT);
+ printf("BITVEC_NINT = %d\n", (int)BITVEC_NINT);
+ printf("BITVEC_MXHASH = %d\n", (int)BITVEC_MXHASH);
+ printf("BITVEC_NPTR = %d\n", (int)BITVEC_NPTR);
+ }
+#endif
+ pc++;
+ continue;
+ }
switch( op ){
case 1:
case 2:
@@ -54340,12 +56139,12 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
pc += nx;
i = (i & 0x7fffffff)%sz;
if( (op & 1)!=0 ){
- SETBIT(pV, (i+1));
+ if( pV ) SETBIT(pV, (i+1));
if( op!=5 ){
if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
}
}else{
- CLEARBIT(pV, (i+1));
+ if( pV ) CLEARBIT(pV, (i+1));
sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
}
}
@@ -54355,14 +56154,18 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
** match (rc==0). Change rc to non-zero if a discrepancy
** is found.
*/
- rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
- + sqlite3BitvecTest(pBitvec, 0)
- + (sqlite3BitvecSize(pBitvec) - sz);
- for(i=1; i<=sz; i++){
- if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
- rc = i;
- break;
+ if( pV ){
+ rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
+ + sqlite3BitvecTest(pBitvec, 0)
+ + (sqlite3BitvecSize(pBitvec) - sz);
+ for(i=1; i<=sz; i++){
+ if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
+ rc = i;
+ break;
+ }
}
+ }else{
+ rc = 0;
}
/* Free allocated structure */
@@ -54890,6 +56693,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
pPgHdr->pData = pPage->pBuf;
pPgHdr->pExtra = (void *)&pPgHdr[1];
memset(pPgHdr->pExtra, 0, 8);
+ assert( EIGHT_BYTE_ALIGNMENT( pPgHdr->pExtra ) );
pPgHdr->pCache = pCache;
pPgHdr->pgno = pgno;
pPgHdr->flags = PGHDR_CLEAN;
@@ -55548,10 +57352,6 @@ static SQLITE_WSD struct PCacheGlobal {
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
PgFreeslot *pFree; /* Free page blocks */
int nFreeSlot; /* Number of unused pcache slots */
- /* The following value requires a mutex to change. We skip the mutex on
- ** reading because (1) most platforms read a 32-bit integer atomically and
- ** (2) even if an incorrect value is read, no great harm is done since this
- ** is really just an optimization. */
int bUnderPressure; /* True if low on PAGECACHE memory */
} pcache1_g;
@@ -55599,7 +57399,7 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
pcache1.pStart = pBuf;
pcache1.pFree = 0;
- pcache1.bUnderPressure = 0;
+ AtomicStore(&pcache1.bUnderPressure,0);
while( n-- ){
p = (PgFreeslot*)pBuf;
p->pNext = pcache1.pFree;
@@ -55636,7 +57436,8 @@ static int pcache1InitBulk(PCache1 *pCache){
do{
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
pX->page.pBuf = zBulk;
- pX->page.pExtra = &pX[1];
+ pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
+ assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
pX->isBulkLocal = 1;
pX->isAnchor = 0;
pX->pNext = pCache->pFree;
@@ -55666,7 +57467,7 @@ static void *pcache1Alloc(int nByte){
if( p ){
pcache1.pFree = pcache1.pFree->pNext;
pcache1.nFreeSlot--;
- pcache1.bUnderPressure = pcache1.nFreeSlot=0 );
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
@@ -55705,7 +57506,7 @@ static void pcache1Free(void *p){
pSlot->pNext = pcache1.pFree;
pcache1.pFree = pSlot;
pcache1.nFreeSlot++;
- pcache1.bUnderPressure = pcache1.nFreeSlotszPage];
p->page.pBuf = pPg;
- p->page.pExtra = &p[1];
+ p->page.pExtra = (u8*)p + ROUND8(sizeof(*p));
+ assert( EIGHT_BYTE_ALIGNMENT( p->page.pExtra ) );
p->isBulkLocal = 0;
p->isAnchor = 0;
p->pLruPrev = 0; /* Initializing this saves a valgrind error */
@@ -55835,7 +57637,7 @@ SQLITE_PRIVATE void sqlite3PageFree(void *p){
*/
static int pcache1UnderMemoryPressure(PCache1 *pCache){
if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
- return pcache1.bUnderPressure;
+ return AtomicLoad(&pcache1.bUnderPressure);
}else{
return sqlite3HeapNearlyFull();
}
@@ -55852,12 +57654,12 @@ static int pcache1UnderMemoryPressure(PCache1 *pCache){
*/
static void pcache1ResizeHash(PCache1 *p){
PgHdr1 **apNew;
- unsigned int nNew;
- unsigned int i;
+ u64 nNew;
+ u32 i;
assert( sqlite3_mutex_held(p->pGroup->mutex) );
- nNew = p->nHash*2;
+ nNew = 2*(u64)p->nHash;
if( nNew<256 ){
nNew = 256;
}
@@ -56080,7 +57882,7 @@ static void pcache1Destroy(sqlite3_pcache *p);
static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
PCache1 *pCache; /* The newly created page cache */
PGroup *pGroup; /* The group the new page cache will belong to */
- int sz; /* Bytes of memory required to allocate the new cache */
+ i64 sz; /* Bytes of memory required to allocate the new cache */
assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
assert( szExtra < 300 );
@@ -57968,6 +59770,9 @@ struct Pager {
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
char *zWal; /* File name for write-ahead log */
#endif
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ sqlite3 *dbWal;
+#endif
};
/*
@@ -58057,40 +59862,34 @@ static const unsigned char aJournalMagic[] = {
# define USEFETCH(x) 0
#endif
-/*
-** The argument to this macro is a file descriptor (type sqlite3_file*).
-** Return 0 if it is not open, or non-zero (but not 1) if it is.
-**
-** This is so that expressions can be written as:
-**
-** if( isOpen(pPager->jfd) ){ ...
-**
-** instead of
-**
-** if( pPager->jfd->pMethods ){ ...
-*/
-#define isOpen(pFd) ((pFd)->pMethods!=0)
-
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
** Return true if page pgno can be read directly from the database file
** by the b-tree layer. This is the case if:
**
-** * the database file is open,
-** * there are no dirty pages in the cache, and
-** * the desired page is not currently in the wal file.
+** (1) the database file is open
+** (2) the VFS for the database is able to do unaligned sub-page reads
+** (3) there are no dirty pages in the cache, and
+** (4) the desired page is not currently in the wal file.
*/
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
- if( pPager->fd->pMethods==0 ) return 0;
- if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
+ assert( pPager!=0 );
+ assert( pPager->fd!=0 );
+ if( pPager->fd->pMethods==0 ) return 0; /* Case (1) */
+ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; /* Failed (3) */
if( sqlite3mcPagerHasCodec(pPager) != 0 ) return 0;
#ifndef SQLITE_OMIT_WAL
if( pPager->pWal ){
u32 iRead = 0;
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return iRead==0;
+ if( iRead ) return 0; /* Case (4) */
}
#endif
+ assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 );
+ if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd)
+ & SQLITE_IOCAP_SUBPAGE_READ)==0 ){
+ return 0; /* Case (2) */
+ }
return 1;
}
#endif
@@ -58566,7 +60365,7 @@ static void checkPage(PgHdr *pPg){
** If an error occurs while reading from the journal file, an SQLite
** error code is returned.
*/
-static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){
+static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
int rc; /* Return code */
u32 len; /* Length in bytes of super-journal name */
i64 szJ; /* Total size in bytes of journal file pJrnl */
@@ -59121,6 +60920,15 @@ static void pager_unlock(Pager *pPager){
if( pagerUseWal(pPager) ){
assert( !isOpen(pPager->jfd) );
+ if( pPager->eState==PAGER_ERROR ){
+ /* If an IO error occurs in wal.c while attempting to wrap the wal file,
+ ** then the Wal object may be holding a write-lock but no read-lock.
+ ** This call ensures that the write-lock is dropped as well. We cannot
+ ** have sqlite3WalEndReadTransaction() drop the write-lock, as it once
+ ** did, because this would break "BEGIN EXCLUSIVE" handling for
+ ** SQLITE_ENABLE_SETLK_TIMEOUT builds. */
+ (void)sqlite3WalEndWriteTransaction(pPager->pWal);
+ }
sqlite3WalEndReadTransaction(pPager->pWal);
pPager->eState = PAGER_OPEN;
}else if( !pPager->exclusiveMode ){
@@ -59349,7 +61157,7 @@ static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
}
pPager->journalOff = 0;
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
- || (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
+ || (pPager->exclusiveMode && pPager->journalModetempFile);
pPager->journalOff = 0;
@@ -59802,12 +61610,12 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
char *zJournal; /* Pointer to one journal within MJ file */
char *zSuperPtr; /* Space to hold super-journal filename */
char *zFree = 0; /* Free this buffer */
- int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
+ i64 nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
/* Allocate space for both the pJournal and pSuper file descriptors.
** If successful, open the super-journal file for reading.
*/
- pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
+ pSuper = (sqlite3_file *)sqlite3MallocZero(2 * (i64)pVfs->szOsFile);
if( !pSuper ){
rc = SQLITE_NOMEM_BKPT;
pJournal = 0;
@@ -59825,11 +61633,14 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
*/
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
- nSuperPtr = pVfs->mxPathname+1;
+ nSuperPtr = 1 + (i64)pVfs->mxPathname;
+ assert( nSuperJournal>=0 && nSuperPtr>0 );
zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
+ }else{
+ assert( nSuperJournal<=0x7fffffff );
}
zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
zSuperJournal = &zFree[4];
@@ -60090,7 +61901,7 @@ static int pager_playback(Pager *pPager, int isHot){
** for pageSize.
*/
zSuper = pPager->pTmpSpace;
- rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
+ rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
if( rc==SQLITE_OK && zSuper[0] ){
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
}
@@ -60229,7 +62040,7 @@ end_playback:
** which case it requires 4 0x00 bytes in memory immediately before
** the filename. */
zSuper = &pPager->pTmpSpace[4];
- rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
+ rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK
@@ -60872,14 +62683,27 @@ SQLITE_PRIVATE void sqlite3PagerSetFlags(
unsigned pgFlags /* Various flags */
){
unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
- if( pPager->tempFile ){
+ if( pPager->tempFile || level==PAGER_SYNCHRONOUS_OFF ){
pPager->noSync = 1;
pPager->fullSync = 0;
pPager->extraSync = 0;
}else{
- pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0;
+ pPager->noSync = 0;
pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0;
- pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0;
+
+ /* Set Pager.extraSync if "PRAGMA synchronous=EXTRA" is requested, or
+ ** if the file-system supports F2FS style atomic writes. If this flag
+ ** is set, SQLite syncs the directory to disk immediately after deleting
+ ** a journal file in "PRAGMA journal_mode=DELETE" mode. */
+ if( level==PAGER_SYNCHRONOUS_EXTRA
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ || (sqlite3OsDeviceCharacteristics(pPager->fd) & SQLITE_IOCAP_BATCH_ATOMIC)
+#endif
+ ){
+ pPager->extraSync = 1;
+ }else{
+ pPager->extraSync = 0;
+ }
}
if( pPager->noSync ){
pPager->syncFlags = 0;
@@ -61333,6 +63157,7 @@ static int pagerAcquireMapPage(
return SQLITE_NOMEM_BKPT;
}
p->pExtra = (void *)&p[1];
+ assert( EIGHT_BYTE_ALIGNMENT( p->pExtra ) );
p->flags = PGHDR_MMAP;
p->nRef = 1;
p->pPager = pPager;
@@ -61999,6 +63824,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
const char *zUri = 0; /* URI args to copy */
int nUriByte = 1; /* Number of bytes of URI args at *zUri */
+
/* Figure out how much space is required for each journal file-handle
** (there are two of them, the main journal and the sub-journal). */
journalFileSize = ROUND8(sqlite3JournalSize(pVfs));
@@ -62024,8 +63850,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
*/
if( zFilename && zFilename[0] ){
const char *z;
- nPathname = pVfs->mxPathname+1;
- zPathname = sqlite3DbMallocRaw(0, nPathname*2);
+ nPathname = pVfs->mxPathname + 1;
+ zPathname = sqlite3DbMallocRaw(0, 2*(i64)nPathname);
if( zPathname==0 ){
return SQLITE_NOMEM_BKPT;
}
@@ -62112,14 +63938,14 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
ROUND8(sizeof(*pPager)) + /* Pager structure */
ROUND8(pcacheSize) + /* PCache object */
ROUND8(pVfs->szOsFile) + /* The main db file */
- journalFileSize * 2 + /* The two journal files */
+ (u64)journalFileSize * 2 + /* The two journal files */
SQLITE_PTRSIZE + /* Space to hold a pointer */
4 + /* Database prefix */
- nPathname + 1 + /* database filename */
- nUriByte + /* query parameters */
- nPathname + 8 + 1 + /* Journal filename */
+ (u64)nPathname + 1 + /* database filename */
+ (u64)nUriByte + /* query parameters */
+ (u64)nPathname + 8 + 1 + /* Journal filename */
#ifndef SQLITE_OMIT_WAL
- nPathname + 4 + 1 + /* WAL filename */
+ (u64)nPathname + 4 + 1 + /* WAL filename */
#endif
3 /* Terminator */
);
@@ -64770,7 +66596,7 @@ SQLITE_PRIVATE int sqlite3PagerCheckpoint(
}
if( pPager->pWal ){
rc = sqlite3WalCheckpoint(pPager->pWal, db, eMode,
- (eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
+ (eMode<=SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
pPager->pBusyHandlerArg,
pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
pnLog, pnCkpt
@@ -64842,6 +66668,11 @@ static int pagerOpenWal(Pager *pPager){
pPager->fd, pPager->zWal, pPager->exclusiveMode,
pPager->journalSizeLimit, &pPager->pWal
);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_OK ){
+ sqlite3WalDb(pPager->pWal, pPager->dbWal);
+ }
+#endif
}
pagerFixMaplimit(pPager);
@@ -64961,6 +66792,7 @@ SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
** blocking locks are required.
*/
SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
+ pPager->dbWal = db;
if( pagerUseWal(pPager) ){
sqlite3WalDb(pPager->pWal, db);
}
@@ -65116,7 +66948,7 @@ SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager *pPager){
** 28: Checksum-2 (second part of checksum for first 24 bytes of header).
**
** Immediately following the wal-header are zero or more frames. Each
-** frame consists of a 24-byte frame-header followed by a bytes
+** frame consists of a 24-byte frame-header followed by bytes
** of page data. The frame-header is six big-endian 32-bit unsigned
** integer values, as follows:
**
@@ -65574,6 +67406,11 @@ struct WalCkptInfo {
/*
** An open write-ahead log file is represented by an instance of the
** following object.
+**
+** writeLock:
+** This is usually set to 1 whenever the WRITER lock is held. However,
+** if it is set to 2, then the WRITER lock is held but must be released
+** by walHandleException() if a SEH exception is thrown.
*/
struct Wal {
sqlite3_vfs *pVfs; /* The VFS used to create pDbFd */
@@ -65613,6 +67450,7 @@ struct Wal {
#endif
#ifdef SQLITE_ENABLE_SNAPSHOT
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
+ int bGetSnapshot; /* Transaction opened for sqlite3_get_snapshot() */
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
sqlite3 *db;
@@ -65663,9 +67501,13 @@ struct WalIterator {
u32 *aPgno; /* Array of page numbers. */
int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
int iZero; /* Frame number associated with aPgno[0] */
- } aSegment[1]; /* One for every 32KB page in the wal-index */
+ } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */
};
+/* Size (in bytes) of a WalIterator object suitable for N or fewer segments */
+#define SZ_WALITERATOR(N) \
+ (offsetof(WalIterator,aSegment)+(N)*sizeof(struct WalSegment))
+
/*
** Define the parameters of the hash tables in the wal-index file. There
** is a hash-table following every HASHTABLE_NPAGE page numbers in the
@@ -65824,7 +67666,7 @@ static SQLITE_NOINLINE int walIndexPageRealloc(
/* Enlarge the pWal->apWiData[] array if required */
if( pWal->nWiData<=iPage ){
- sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
+ sqlite3_int64 nByte = sizeof(u32*)*(1+(i64)iPage);
volatile u32 **apNew;
apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
if( !apNew ){
@@ -65933,10 +67775,8 @@ static void walChecksumBytes(
s1 = s2 = 0;
}
- assert( nByte>=8 );
- assert( (nByte&0x00000007)==0 );
- assert( nByte<=65536 );
- assert( nByte%4==0 );
+ /* nByte is a multiple of 8 between 8 and 65536 */
+ assert( nByte>=8 && (nByte&7)==0 && nByte<=65536 );
if( !nativeCksum ){
do {
@@ -67026,8 +68866,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
/* Allocate space for the WalIterator object. */
nSegment = walFramePage(iLast) + 1;
- nByte = sizeof(WalIterator)
- + (nSegment-1)*sizeof(struct WalSegment)
+ nByte = SZ_WALITERATOR(nSegment)
+ iLast*sizeof(ht_slot);
p = (WalIterator *)sqlite3_malloc64(nByte
+ sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
@@ -67098,7 +68937,7 @@ static int walEnableBlockingMs(Wal *pWal, int nMs){
static int walEnableBlocking(Wal *pWal){
int res = 0;
if( pWal->db ){
- int tmout = pWal->db->busyTimeout;
+ int tmout = pWal->db->setlkTimeout;
if( tmout ){
res = walEnableBlockingMs(pWal, tmout);
}
@@ -67484,7 +69323,9 @@ static int walHandleException(Wal *pWal){
static const int S = 1;
static const int E = (1<lockMask & ~(
+ u32 mUnlock;
+ if( pWal->writeLock==2 ) pWal->writeLock = 0;
+ mUnlock = pWal->lockMask & ~(
(pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock)))
| (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0)
| (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0)
@@ -67505,7 +69346,7 @@ static int walHandleException(Wal *pWal){
/*
** Assert that the Wal.lockMask mask, which indicates the locks held
-** by the connenction, is consistent with the Wal.readLock, Wal.writeLock
+** by the connection, is consistent with the Wal.readLock, Wal.writeLock
** and Wal.ckptLock variables. To be used as:
**
** assert( walAssertLockmask(pWal) );
@@ -67756,7 +69597,12 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
if( bWriteLock
|| SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1))
){
- pWal->writeLock = 1;
+ /* If the write-lock was just obtained, set writeLock to 2 instead of
+ ** the usual 1. This causes walIndexPage() to behave as if the
+ ** write-lock were held (so that it allocates new pages as required),
+ ** and walHandleException() to unlock the write-lock if a SEH exception
+ ** is thrown. */
+ if( !bWriteLock ) pWal->writeLock = 2;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
if( badHdr ){
@@ -68057,11 +69903,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
*/
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
- u32 mxReadMark; /* Largest aReadMark[] value */
- int mxI; /* Index of largest aReadMark[] value */
- int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
- u32 mxFrame; /* Wal frame to lock to */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int nBlockTmout = 0;
#endif
@@ -68124,7 +69966,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = walIndexReadHdr(pWal, pChanged);
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- walDisableBlocking(pWal);
if( rc==SQLITE_BUSY_TIMEOUT ){
rc = SQLITE_BUSY;
*pCnt |= WAL_RETRY_BLOCKED_MASK;
@@ -68139,6 +69980,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
** WAL_RETRY this routine will be called again and will probably be
** right on the second iteration.
*/
+ (void)walEnableBlocking(pWal);
if( pWal->apWiData[0]==0 ){
/* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
** We assume this is a transient condition, so return WAL_RETRY. The
@@ -68155,6 +69997,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = SQLITE_BUSY_RECOVERY;
}
}
+ walDisableBlocking(pWal);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -68167,141 +70010,147 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
assert( pWal->apWiData[0]!=0 );
pInfo = walCkptInfo(pWal);
SEH_INJECT_FAULT;
- if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
+ {
+ u32 mxReadMark; /* Largest aReadMark[] value */
+ int mxI; /* Index of largest aReadMark[] value */
+ int i; /* Loop counter */
+ u32 mxFrame; /* Wal frame to lock to */
+ if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
#ifdef SQLITE_ENABLE_SNAPSHOT
- && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
+ && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0)
#endif
- ){
- /* The WAL has been completely backfilled (or it is empty).
- ** and can be safely ignored.
- */
- rc = walLockShared(pWal, WAL_READ_LOCK(0));
- walShmBarrier(pWal);
- if( rc==SQLITE_OK ){
- if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
- /* It is not safe to allow the reader to continue here if frames
- ** may have been appended to the log before READ_LOCK(0) was obtained.
- ** When holding READ_LOCK(0), the reader ignores the entire log file,
- ** which implies that the database file contains a trustworthy
- ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
- ** happening, this is usually correct.
- **
- ** However, if frames have been appended to the log (or if the log
- ** is wrapped and written for that matter) before the READ_LOCK(0)
- ** is obtained, that is not necessarily true. A checkpointer may
- ** have started to backfill the appended frames but crashed before
- ** it finished. Leaving a corrupt image in the database file.
- */
- walUnlockShared(pWal, WAL_READ_LOCK(0));
- return WAL_RETRY;
- }
- pWal->readLock = 0;
- return SQLITE_OK;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
- }
- }
-
- /* If we get this far, it means that the reader will want to use
- ** the WAL to get at content from recent commits. The job now is
- ** to select one of the aReadMark[] entries that is closest to
- ** but not exceeding pWal->hdr.mxFrame and lock that entry.
- */
- mxReadMark = 0;
- mxI = 0;
- mxFrame = pWal->hdr.mxFrame;
-#ifdef SQLITE_ENABLE_SNAPSHOT
- if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame;
- }
-#endif
- for(i=1; iaReadMark+i); SEH_INJECT_FAULT;
- if( mxReadMark<=thisMark && thisMark<=mxFrame ){
- assert( thisMark!=READMARK_NOT_USED );
- mxReadMark = thisMark;
- mxI = i;
- }
- }
- if( (pWal->readOnly & WAL_SHM_RDONLY)==0
- && (mxReadMarkaReadMark+i,mxFrame);
- mxReadMark = mxFrame;
- mxI = i;
- walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
- break;
+ if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr,sizeof(WalIndexHdr)) ){
+ /* It is not safe to allow the reader to continue here if frames
+ ** may have been appended to the log before READ_LOCK(0) was obtained.
+ ** When holding READ_LOCK(0), the reader ignores the entire log file,
+ ** which implies that the database file contains a trustworthy
+ ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
+ ** happening, this is usually correct.
+ **
+ ** However, if frames have been appended to the log (or if the log
+ ** is wrapped and written for that matter) before the READ_LOCK(0)
+ ** is obtained, that is not necessarily true. A checkpointer may
+ ** have started to backfill the appended frames but crashed before
+ ** it finished. Leaving a corrupt image in the database file.
+ */
+ walUnlockShared(pWal, WAL_READ_LOCK(0));
+ return WAL_RETRY;
+ }
+ pWal->readLock = 0;
+ return SQLITE_OK;
}else if( rc!=SQLITE_BUSY ){
return rc;
}
}
- }
- if( mxI==0 ){
- assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
- return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
- }
- (void)walEnableBlockingMs(pWal, nBlockTmout);
- rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
- walDisableBlocking(pWal);
- if( rc ){
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- if( rc==SQLITE_BUSY_TIMEOUT ){
- *pCnt |= WAL_RETRY_BLOCKED_MASK;
+ /* If we get this far, it means that the reader will want to use
+ ** the WAL to get at content from recent commits. The job now is
+ ** to select one of the aReadMark[] entries that is closest to
+ ** but not exceeding pWal->hdr.mxFrame and lock that entry.
+ */
+ mxReadMark = 0;
+ mxI = 0;
+ mxFrame = pWal->hdr.mxFrame;
+#ifdef SQLITE_ENABLE_SNAPSHOT
+ if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame;
}
-#else
- assert( rc!=SQLITE_BUSY_TIMEOUT );
#endif
- assert( (rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT );
- return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
- }
- /* Now that the read-lock has been obtained, check that neither the
- ** value in the aReadMark[] array or the contents of the wal-index
- ** header have changed.
- **
- ** It is necessary to check that the wal-index header did not change
- ** between the time it was read and when the shared-lock was obtained
- ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
- ** that the log file may have been wrapped by a writer, or that frames
- ** that occur later in the log than pWal->hdr.mxFrame may have been
- ** copied into the database by a checkpointer. If either of these things
- ** happened, then reading the database with the current value of
- ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
- ** instead.
- **
- ** Before checking that the live wal-index header has not changed
- ** since it was read, set Wal.minFrame to the first frame in the wal
- ** file that has not yet been checkpointed. This client will not need
- ** to read any frames earlier than minFrame from the wal file - they
- ** can be safely read directly from the database file.
- **
- ** Because a ShmBarrier() call is made between taking the copy of
- ** nBackfill and checking that the wal-header in shared-memory still
- ** matches the one cached in pWal->hdr, it is guaranteed that the
- ** checkpointer that set nBackfill was not working with a wal-index
- ** header newer than that cached in pWal->hdr. If it were, that could
- ** cause a problem. The checkpointer could omit to checkpoint
- ** a version of page X that lies before pWal->minFrame (call that version
- ** A) on the basis that there is a newer version (version B) of the same
- ** page later in the wal file. But if version B happens to like past
- ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
- ** that it can read version A from the database file. However, since
- ** we can guarantee that the checkpointer that set nBackfill could not
- ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
- */
- pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT;
- walShmBarrier(pWal);
- if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
- || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
- ){
- walUnlockShared(pWal, WAL_READ_LOCK(mxI));
- return WAL_RETRY;
- }else{
- assert( mxReadMark<=pWal->hdr.mxFrame );
- pWal->readLock = (i16)mxI;
+ for(i=1; iaReadMark+i); SEH_INJECT_FAULT;
+ if( mxReadMark<=thisMark && thisMark<=mxFrame ){
+ assert( thisMark!=READMARK_NOT_USED );
+ mxReadMark = thisMark;
+ mxI = i;
+ }
+ }
+ if( (pWal->readOnly & WAL_SHM_RDONLY)==0
+ && (mxReadMarkaReadMark+i,mxFrame);
+ mxReadMark = mxFrame;
+ mxI = i;
+ walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ break;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+ }
+ if( mxI==0 ){
+ assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
+ return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
+ }
+
+ (void)walEnableBlockingMs(pWal, nBlockTmout);
+ rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
+ walDisableBlocking(pWal);
+ if( rc ){
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ *pCnt |= WAL_RETRY_BLOCKED_MASK;
+ }
+#else
+ assert( rc!=SQLITE_BUSY_TIMEOUT );
+#endif
+ assert((rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT);
+ return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
+ }
+ /* Now that the read-lock has been obtained, check that neither the
+ ** value in the aReadMark[] array or the contents of the wal-index
+ ** header have changed.
+ **
+ ** It is necessary to check that the wal-index header did not change
+ ** between the time it was read and when the shared-lock was obtained
+ ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
+ ** that the log file may have been wrapped by a writer, or that frames
+ ** that occur later in the log than pWal->hdr.mxFrame may have been
+ ** copied into the database by a checkpointer. If either of these things
+ ** happened, then reading the database with the current value of
+ ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
+ ** instead.
+ **
+ ** Before checking that the live wal-index header has not changed
+ ** since it was read, set Wal.minFrame to the first frame in the wal
+ ** file that has not yet been checkpointed. This client will not need
+ ** to read any frames earlier than minFrame from the wal file - they
+ ** can be safely read directly from the database file.
+ **
+ ** Because a ShmBarrier() call is made between taking the copy of
+ ** nBackfill and checking that the wal-header in shared-memory still
+ ** matches the one cached in pWal->hdr, it is guaranteed that the
+ ** checkpointer that set nBackfill was not working with a wal-index
+ ** header newer than that cached in pWal->hdr. If it were, that could
+ ** cause a problem. The checkpointer could omit to checkpoint
+ ** a version of page X that lies before pWal->minFrame (call that version
+ ** A) on the basis that there is a newer version (version B) of the same
+ ** page later in the wal file. But if version B happens to like past
+ ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
+ ** that it can read version A from the database file. However, since
+ ** we can guarantee that the checkpointer that set nBackfill could not
+ ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
+ */
+ pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT;
+ walShmBarrier(pWal);
+ if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
+ || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
+ ){
+ walUnlockShared(pWal, WAL_READ_LOCK(mxI));
+ return WAL_RETRY;
+ }else{
+ assert( mxReadMark<=pWal->hdr.mxFrame );
+ pWal->readLock = (i16)mxI;
+ }
}
return rc;
}
@@ -68539,8 +70388,11 @@ SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
** read-lock.
*/
SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal){
- sqlite3WalEndWriteTransaction(pWal);
+#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
+ assert( pWal->writeLock==0 || pWal->readLock<0 );
+#endif
if( pWal->readLock>=0 ){
+ (void)sqlite3WalEndWriteTransaction(pWal);
walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
pWal->readLock = -1;
}
@@ -68733,7 +70585,7 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
** read-transaction was even opened, making this call a no-op.
** Return early. */
if( pWal->writeLock ){
- assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) );
+ assert( !memcmp(&pWal->hdr,(void*)pWal->apWiData[0],sizeof(WalIndexHdr)) );
return SQLITE_OK;
}
#endif
@@ -68833,6 +70685,7 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
}
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+ pWal->iReCksum = 0;
}
return rc;
}
@@ -68880,6 +70733,9 @@ SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){
walCleanupHash(pWal);
}
SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; )
+ if( pWal->iReCksum>pWal->hdr.mxFrame ){
+ pWal->iReCksum = 0;
+ }
}
return rc;
@@ -69345,7 +71201,8 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
- assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
+ assert( SQLITE_CHECKPOINT_NOOPSQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
if( pWal->readOnly ) return SQLITE_READONLY;
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
@@ -69362,31 +71219,35 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
** it will not be invoked in this case.
*/
- rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
- testcase( rc==SQLITE_BUSY );
- testcase( rc!=SQLITE_OK && xBusy2!=0 );
- if( rc==SQLITE_OK ){
- pWal->ckptLock = 1;
+ if( eMode!=SQLITE_CHECKPOINT_NOOP ){
+ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ testcase( rc==SQLITE_BUSY );
+ testcase( rc!=SQLITE_OK && xBusy2!=0 );
+ if( rc==SQLITE_OK ){
+ pWal->ckptLock = 1;
- /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
- ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
- ** file.
- **
- ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
- ** immediately, and a busy-handler is configured, it is invoked and the
- ** writer lock retried until either the busy-handler returns 0 or the
- ** lock is successfully obtained.
- */
- if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
- rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
- if( rc==SQLITE_OK ){
- pWal->writeLock = 1;
- }else if( rc==SQLITE_BUSY ){
- eMode2 = SQLITE_CHECKPOINT_PASSIVE;
- xBusy2 = 0;
- rc = SQLITE_OK;
+ /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART
+ ** and TRUNCATE modes also obtain the exclusive "writer" lock on the
+ ** database file.
+ **
+ ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
+ ** immediately, and a busy-handler is configured, it is invoked and the
+ ** writer lock retried until either the busy-handler returns 0 or the
+ ** lock is successfully obtained.
+ */
+ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
+ rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
+ if( rc==SQLITE_OK ){
+ pWal->writeLock = 1;
+ }else if( rc==SQLITE_BUSY ){
+ eMode2 = SQLITE_CHECKPOINT_PASSIVE;
+ xBusy2 = 0;
+ rc = SQLITE_OK;
+ }
}
}
+ }else{
+ rc = SQLITE_OK;
}
@@ -69400,7 +71261,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
** immediately and do a partial checkpoint if it cannot obtain it. */
walDisableBlocking(pWal);
rc = walIndexReadHdr(pWal, &isChanged);
- if( eMode2!=SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal);
+ if( eMode2>SQLITE_CHECKPOINT_PASSIVE ) (void)walEnableBlocking(pWal);
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
}
@@ -69410,7 +71271,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
if( rc==SQLITE_OK ){
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
rc = SQLITE_CORRUPT_BKPT;
- }else{
+ }else if( eMode2!=SQLITE_CHECKPOINT_NOOP ){
rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf);
}
@@ -69438,7 +71299,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
sqlite3WalDb(pWal, 0);
/* Release the locks. */
- sqlite3WalEndWriteTransaction(pWal);
+ (void)sqlite3WalEndWriteTransaction(pWal);
if( pWal->ckptLock ){
walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
pWal->ckptLock = 0;
@@ -69569,7 +71430,20 @@ SQLITE_PRIVATE void sqlite3WalSnapshotOpen(
Wal *pWal,
sqlite3_snapshot *pSnapshot
){
- pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
+ if( pSnapshot && ((WalIndexHdr*)pSnapshot)->iVersion==0 ){
+ /* iVersion==0 means that this is a call to sqlite3_snapshot_get(). In
+ ** this case set the bGetSnapshot flag so that if the call to
+ ** sqlite3_snapshot_get() is about to read transaction on this wal
+ ** file, it does not take read-lock 0 if the wal file has been completely
+ ** checkpointed. Taking read-lock 0 would work, but then it would be
+ ** possible for a subsequent writer to destroy the snapshot even while
+ ** this connection is holding its read-transaction open. This is contrary
+ ** to user expectations, so we avoid it by not taking read-lock 0. */
+ pWal->bGetSnapshot = 1;
+ }else{
+ pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
+ pWal->bGetSnapshot = 0;
+ }
}
/*
@@ -70169,6 +72043,12 @@ struct CellInfo {
*/
#define BTCURSOR_MAX_DEPTH 20
+/*
+** Maximum amount of storage local to a database page, regardless of
+** page size.
+*/
+#define BT_MAX_LOCAL 65501 /* 65536 - 35 */
+
/*
** A cursor is a pointer to a particular entry within a particular
** b-tree within a database file.
@@ -70577,7 +72457,7 @@ SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){
*/
static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
int i;
- int skipOk = 1;
+ u8 skipOk = 1;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; inDb; i++){
@@ -71433,7 +73313,7 @@ static int saveCursorKey(BtCursor *pCur){
** below. */
void *pKey;
pCur->nKey = sqlite3BtreePayloadSize(pCur);
- pKey = sqlite3Malloc( pCur->nKey + 9 + 8 );
+ pKey = sqlite3Malloc( ((i64)pCur->nKey) + 9 + 8 );
if( pKey ){
rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
@@ -71576,7 +73456,7 @@ static int btreeMoveto(
assert( nKey==(i64)(int)nKey );
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
- sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+ sqlite3VdbeRecordUnpack((int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
}else{
@@ -71723,7 +73603,7 @@ SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
*/
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
- pCur->hints = x;
+ pCur->hints = (u8)x;
}
@@ -71917,14 +73797,15 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
int maxLocal; /* Maximum amount of payload held locally */
maxLocal = pPage->maxLocal;
+ assert( nPayload>=0 );
if( nPayload<=maxLocal ){
- return nPayload;
+ return (int)nPayload;
}else{
int minLocal; /* Minimum amount of payload held locally */
int surplus; /* Overflow payload available for local storage */
minLocal = pPage->minLocal;
- surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
- return ( surplus <= maxLocal ) ? surplus : minLocal;
+ surplus = (int)(minLocal +(nPayload - minLocal)%(pPage->pBt->usableSize-4));
+ return (surplus <= maxLocal) ? surplus : minLocal;
}
}
@@ -72034,11 +73915,13 @@ static void btreeParseCellPtr(
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
testcase( nPayload==(u32)pPage->maxLocal+1 );
+ assert( nPayload>=0 );
+ assert( pPage->maxLocal <= BT_MAX_LOCAL );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
*/
- pInfo->nSize = nPayload + (u16)(pIter - pCell);
+ pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell);
if( pInfo->nSize<4 ) pInfo->nSize = 4;
pInfo->nLocal = (u16)nPayload;
}else{
@@ -72071,11 +73954,13 @@ static void btreeParseCellPtrIndex(
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
testcase( nPayload==(u32)pPage->maxLocal+1 );
+ assert( nPayload>=0 );
+ assert( pPage->maxLocal <= BT_MAX_LOCAL );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
*/
- pInfo->nSize = nPayload + (u16)(pIter - pCell);
+ pInfo->nSize = (u16)nPayload + (u16)(pIter - pCell);
if( pInfo->nSize<4 ) pInfo->nSize = 4;
pInfo->nLocal = (u16)nPayload;
}else{
@@ -72614,24 +74499,24 @@ static SQLITE_INLINE int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** at the end of the page. So do additional corruption checks inside this
** routine and return SQLITE_CORRUPT if any problems are found.
*/
-static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
- u16 iPtr; /* Address of ptr to next freeblock */
- u16 iFreeBlk; /* Address of the next freeblock */
+static int freeSpace(MemPage *pPage, int iStart, int iSize){
+ int iPtr; /* Address of ptr to next freeblock */
+ int iFreeBlk; /* Address of the next freeblock */
u8 hdr; /* Page header size. 0 or 100 */
- u8 nFrag = 0; /* Reduction in fragmentation */
- u16 iOrigSize = iSize; /* Original value of iSize */
- u16 x; /* Offset to cell content area */
- u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
+ int nFrag = 0; /* Reduction in fragmentation */
+ int iOrigSize = iSize; /* Original value of iSize */
+ int x; /* Offset to cell content area */
+ int iEnd = iStart + iSize; /* First byte past the iStart buffer */
unsigned char *data = pPage->aData; /* Page content */
u8 *pTmp; /* Temporary ptr into data[] */
assert( pPage->pBt!=0 );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize );
- assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize );
+ assert( CORRUPT_DB || iEnd <= (int)pPage->pBt->usableSize );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( iSize>=4 ); /* Minimum cell size is 4 */
- assert( CORRUPT_DB || iStart<=pPage->pBt->usableSize-4 );
+ assert( CORRUPT_DB || iStart<=(int)pPage->pBt->usableSize-4 );
/* The list of freeblocks must be in ascending order. Find the
** spot on the list where iStart should be inserted.
@@ -72648,7 +74533,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}
iPtr = iFreeBlk;
}
- if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
+ if( iFreeBlk>(int)pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB );
@@ -72663,7 +74548,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
nFrag = iFreeBlk - iEnd;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage);
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
- if( iEnd > pPage->pBt->usableSize ){
+ if( iEnd > (int)pPage->pBt->usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
iSize = iEnd - iStart;
@@ -72684,7 +74569,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
}
}
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage);
- data[hdr+7] -= nFrag;
+ data[hdr+7] -= (u8)nFrag;
}
pTmp = &data[hdr+5];
x = get2byte(pTmp);
@@ -72705,7 +74590,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
/* Insert the new freeblock into the freelist */
put2byte(&data[iPtr], iStart);
put2byte(&data[iStart], iFreeBlk);
- put2byte(&data[iStart+2], iSize);
+ assert( iSize>=0 && iSize<=0xffff );
+ put2byte(&data[iStart+2], (u16)iSize);
}
pPage->nFree += iOrigSize;
return SQLITE_OK;
@@ -72931,7 +74817,7 @@ static int btreeInitPage(MemPage *pPage){
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
pPage->maskPage = (u16)(pBt->pageSize - 1);
pPage->nOverflow = 0;
- pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
+ pPage->cellOffset = (u16)(pPage->hdrOffset + 8 + pPage->childPtrSize);
pPage->aCellIdx = data + pPage->childPtrSize + 8;
pPage->aDataEnd = pPage->aData + pBt->pageSize;
pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
@@ -72965,8 +74851,8 @@ static int btreeInitPage(MemPage *pPage){
static void zeroPage(MemPage *pPage, int flags){
unsigned char *data = pPage->aData;
BtShared *pBt = pPage->pBt;
- u8 hdr = pPage->hdrOffset;
- u16 first;
+ int hdr = pPage->hdrOffset;
+ int first;
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
@@ -72983,7 +74869,7 @@ static void zeroPage(MemPage *pPage, int flags){
put2byte(&data[hdr+5], pBt->usableSize);
pPage->nFree = (u16)(pBt->usableSize - first);
decodeFlags(pPage, flags);
- pPage->cellOffset = first;
+ pPage->cellOffset = (u16)first;
pPage->aDataEnd = &data[pBt->pageSize];
pPage->aCellIdx = &data[first];
pPage->aDataOfst = &data[pPage->childPtrSize];
@@ -73554,6 +75440,7 @@ static int removeFromSharingList(BtShared *pBt){
sqlite3_mutex_leave(pMainMtx);
return removed;
#else
+ UNUSED_PARAMETER( pBt );
return 1;
#endif
}
@@ -73769,8 +75656,12 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve,
BtShared *pBt = p->pBt;
assert( nReserve>=0 && nReserve<=255 );
sqlite3BtreeEnter(p);
- pBt->nReserveWanted = nReserve;
+ pBt->nReserveWanted = (u8)nReserve;
x = pBt->pageSize - pBt->usableSize;
+ if( x==nReserve && (pageSize==0 || (u32)pageSize==pBt->pageSize) ){
+ sqlite3BtreeLeave(p);
+ return SQLITE_OK;
+ }
if( nReservebtsFlags & BTS_PAGESIZE_FIXED ){
sqlite3BtreeLeave(p);
@@ -73875,7 +75766,7 @@ SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
assert( BTS_FAST_SECURE==(BTS_OVERWRITE|BTS_SECURE_DELETE) );
if( newFlag>=0 ){
p->pBt->btsFlags &= ~BTS_FAST_SECURE;
- p->pBt->btsFlags |= BTS_SECURE_DELETE*newFlag;
+ p->pBt->btsFlags |= (u16)(BTS_SECURE_DELETE*newFlag);
}
b = (p->pBt->btsFlags & BTS_FAST_SECURE)/BTS_SECURE_DELETE;
sqlite3BtreeLeave(p);
@@ -74395,6 +76286,13 @@ static SQLITE_NOINLINE int btreeBeginTrans(
(void)sqlite3PagerWalWriteLock(pPager, 0);
unlockBtreeIfUnused(pBt);
}
+#if defined(SQLITE_ENABLE_SETLK_TIMEOUT)
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ /* If a blocking lock timed out, break out of the loop here so that
+ ** the busy-handler is not invoked. */
+ break;
+ }
+#endif
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
btreeInvokeBusyHandler(pBt) );
sqlite3PagerWalDb(pPager, 0);
@@ -75450,6 +77348,25 @@ SQLITE_PRIVATE int sqlite3BtreeCursorSize(void){
return ROUND8(sizeof(BtCursor));
}
+#ifdef SQLITE_DEBUG
+/*
+** Return true if and only if the Btree object will be automatically
+** closed with the BtCursor closes. This is used within assert() statements
+** only.
+*/
+SQLITE_PRIVATE int sqlite3BtreeClosesWithCursor(
+ Btree *pBtree, /* the btree object */
+ BtCursor *pCur /* Corresponding cursor */
+){
+ BtShared *pBt = pBtree->pBt;
+ if( (pBt->openFlags & BTREE_SINGLE)==0 ) return 0;
+ if( pBt->pCursor!=pCur ) return 0;
+ if( pCur->pNext!=0 ) return 0;
+ if( pCur->pBtree!=pBtree ) return 0;
+ return 1;
+}
+#endif
+
/*
** Initialize memory that will be converted into a BtCursor object.
**
@@ -76334,6 +78251,30 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
return rc;
}
+/* Set *pRes to 1 (true) if the BTree pointed to by cursor pCur contains zero
+** rows of content. Set *pRes to 0 (false) if the table contains content.
+** Return SQLITE_OK on success or some error code (ex: SQLITE_NOMEM) if
+** something goes wrong.
+*/
+SQLITE_PRIVATE int sqlite3BtreeIsEmpty(BtCursor *pCur, int *pRes){
+ int rc;
+
+ assert( cursorOwnsBtShared(pCur) );
+ assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+ if( pCur->eState==CURSOR_VALID ){
+ *pRes = 0;
+ return SQLITE_OK;
+ }
+ rc = moveToRoot(pCur);
+ if( rc==SQLITE_EMPTY ){
+ *pRes = 1;
+ rc = SQLITE_OK;
+ }else{
+ *pRes = 0;
+ }
+ return rc;
+}
+
#ifdef SQLITE_DEBUG
/* The cursors is CURSOR_VALID and has BTCF_AtLast set. Verify that
** this flags are true for a consistent database.
@@ -76553,8 +78494,8 @@ moveto_table_finish:
}
/*
-** Compare the "idx"-th cell on the page the cursor pCur is currently
-** pointing to to pIdxKey using xRecordCompare. Return negative or
+** Compare the "idx"-th cell on the page pPage against the key
+** pointing to by pIdxKey using xRecordCompare. Return negative or
** zero if the cell is less than or equal pIdxKey. Return positive
** if unknown.
**
@@ -76569,12 +78510,11 @@ moveto_table_finish:
** a positive value as that will cause the optimization to be skipped.
*/
static int indexCellCompare(
- BtCursor *pCur,
+ MemPage *pPage,
int idx,
UnpackedRecord *pIdxKey,
RecordCompare xRecordCompare
){
- MemPage *pPage = pCur->pPage;
int c;
int nCell; /* Size of the pCell cell in bytes */
u8 *pCell = findCellPastPtr(pPage, idx);
@@ -76683,17 +78623,17 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
){
int c;
if( pCur->ix==pCur->pPage->nCell-1
- && (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0
+ && (c = indexCellCompare(pCur->pPage,pCur->ix,pIdxKey,xRecordCompare))<=0
&& pIdxKey->errCode==SQLITE_OK
){
*pRes = c;
return SQLITE_OK; /* Cursor already pointing at the correct spot */
}
if( pCur->iPage>0
- && indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
+ && indexCellCompare(pCur->pPage, 0, pIdxKey, xRecordCompare)<=0
&& pIdxKey->errCode==SQLITE_OK
){
- pCur->curFlags &= ~BTCF_ValidOvfl;
+ pCur->curFlags &= ~(BTCF_ValidOvfl|BTCF_AtLast);
if( !pCur->pPage->isInit ){
return SQLITE_CORRUPT_BKPT;
}
@@ -76785,7 +78725,7 @@ bypass_moveto_root:
rc = SQLITE_CORRUPT_PAGE(pPage);
goto moveto_index_finish;
}
- pCellKey = sqlite3Malloc( nCell+nOverrun );
+ pCellKey = sqlite3Malloc( (u64)nCell+(u64)nOverrun );
if( pCellKey==0 ){
rc = SQLITE_NOMEM_BKPT;
goto moveto_index_finish;
@@ -76907,7 +78847,7 @@ SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
n = pCur->pPage->nCell;
for(i=0; iiPage; i++){
- n *= pCur->apPage[i]->nCell;
+ n *= pCur->apPage[i]->nCell+1;
}
return n;
}
@@ -78271,7 +80211,8 @@ static int rebuildPage(
if( j>(u32)usableSize ){ j = 0; }
memcpy(&pTmp[j], &aData[j], usableSize - j);
- for(k=0; ALWAYS(kixNx[k]<=i; k++){}
+ assert( pCArray->ixNx[NB*2-1]>i );
+ for(k=0; pCArray->ixNx[k]<=i; k++){}
pSrcEnd = pCArray->apEnd[k];
pData = pEnd;
@@ -78303,7 +80244,8 @@ static int rebuildPage(
}
/* The pPg->nFree field is now set incorrectly. The caller will fix it. */
- pPg->nCell = nCell;
+ assert( nCell < 10922 );
+ pPg->nCell = (u16)nCell;
pPg->nOverflow = 0;
put2byte(&aData[hdr+1], 0);
@@ -78354,7 +80296,8 @@ static int pageInsertArray(
u8 *pEnd; /* Maximum extent of cell data */
assert( CORRUPT_DB || pPg->hdrOffset==0 ); /* Never called on page 1 */
if( iEnd<=iFirst ) return 0;
- for(k=0; ALWAYS(kixNx[k]<=i ; k++){}
+ assert( pCArray->ixNx[NB*2-1]>i );
+ for(k=0; pCArray->ixNx[k]<=i ; k++){}
pEnd = pCArray->apEnd[k];
while( 1 /*Exit by break*/ ){
int sz, rc;
@@ -78549,9 +80492,13 @@ static int editPage(
if( pageInsertArray(
pPg, pBegin, &pData, pCellptr,
iNew+nCell, nNew-nCell, pCArray
- ) ) goto editpage_fail;
+ )
+ ){
+ goto editpage_fail;
+ }
- pPg->nCell = nNew;
+ assert( nNew < 10922 );
+ pPg->nCell = (u16)nNew;
pPg->nOverflow = 0;
put2byte(&aData[hdr+3], pPg->nCell);
@@ -78639,6 +80586,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
b.szCell = &szCell;
b.apEnd[0] = pPage->aDataEnd;
b.ixNx[0] = 2;
+ b.ixNx[NB*2-1] = 0x7fffffff;
rc = rebuildPage(&b, 0, 1, pNew);
if( NEVER(rc) ){
releasePage(pNew);
@@ -78859,7 +80807,7 @@ static int balance_nonroot(
int pageFlags; /* Value of pPage->aData[0] */
int iSpace1 = 0; /* First unused byte of aSpace1[] */
int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */
- int szScratch; /* Size of scratch memory requested */
+ u64 szScratch; /* Size of scratch memory requested */
MemPage *apOld[NB]; /* pPage and up to two siblings */
MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */
u8 *pRight; /* Location in parent of right-sibling pointer */
@@ -78874,7 +80822,9 @@ static int balance_nonroot(
CellArray b; /* Parsed information on cells being balanced */
memset(abDone, 0, sizeof(abDone));
- memset(&b, 0, sizeof(b));
+ assert( sizeof(b) - sizeof(b.ixNx) == offsetof(CellArray,ixNx) );
+ memset(&b, 0, sizeof(b)-sizeof(b.ixNx[0]));
+ b.ixNx[NB*2-1] = 0x7fffffff;
pBt = pParent->pBt;
assert( sqlite3_mutex_held(pBt->mutex) );
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -79354,7 +81304,12 @@ static int balance_nonroot(
** of the right-most new sibling page is set to the value that was
** originally in the same field of the right-most old sibling page. */
if( (pageFlags & PTF_LEAF)==0 && nOld!=nNew ){
- MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1];
+ MemPage *pOld;
+ if( nNew>nOld ){
+ pOld = apNew[nOld-1];
+ }else{
+ pOld = apOld[nOld-1];
+ }
memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4);
}
@@ -79465,7 +81420,8 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
- for(k=0; ALWAYS(kj );
+ for(k=0; b.ixNx[k]<=j; k++){}
pSrcEnd = b.apEnd[k];
if( SQLITE_OVERFLOW(pSrcEnd, pCell, pCell+sz) ){
rc = SQLITE_CORRUPT_BKPT;
@@ -80141,7 +82097,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( pCur->info.nKey==pX->nKey ){
BtreePayload x2;
x2.pData = pX->pKey;
- x2.nData = pX->nKey;
+ x2.nData = (int)pX->nKey; assert( pX->nKey<=0x7fffffff );
x2.nZero = 0;
return btreeOverwriteCell(pCur, &x2);
}
@@ -80322,7 +82278,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
getCellInfo(pSrc);
if( pSrc->info.nPayload<0x80 ){
- *(aOut++) = pSrc->info.nPayload;
+ *(aOut++) = (u8)pSrc->info.nPayload;
}else{
aOut += sqlite3PutVarint(aOut, pSrc->info.nPayload);
}
@@ -80335,7 +82291,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
nRem = pSrc->info.nPayload;
if( nIn==nRem && nInpPage->maxLocal ){
memcpy(aOut, aIn, nIn);
- pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+ pBt->nPreformatSize = nIn + (int)(aOut - pBt->pTmpSpace);
return SQLITE_OK;
}else{
int rc = SQLITE_OK;
@@ -80347,7 +82303,7 @@ SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64
u32 nOut; /* Size of output buffer aOut[] */
nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
- pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+ pBt->nPreformatSize = (int)nOut + (int)(aOut - pBt->pTmpSpace);
if( nOutinfo.nPayload ){
pPgnoOut = &aOut[nOut];
pBt->nPreformatSize += 4;
@@ -81968,6 +83924,7 @@ SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree *p){
*/
SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
BtShared *pBt = p->pBt;
+ assert( nBytes==0 || nBytes==sizeof(Schema) );
sqlite3BtreeEnter(p);
if( !pBt->pSchema && nBytes ){
pBt->pSchema = sqlite3DbMallocZero(0, nBytes);
@@ -81984,6 +83941,7 @@ SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void
*/
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *p){
int rc;
+ UNUSED_PARAMETER(p); /* only used in DEBUG builds */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
@@ -83090,7 +85048,7 @@ static void vdbeMemRenderNum(int sz, char *zBuf, Mem *p){
** corresponding string value, then it is important that the string be
** derived from the numeric value, not the other way around, to ensure
** that the index and table are consistent. See ticket
-** https://www.sqlite.org/src/info/343634942dd54ab (2018-01-31) for
+** https://sqlite.org/src/info/343634942dd54ab (2018-01-31) for
** an example.
**
** This routine looks at pMem to verify that if it has both a numeric
@@ -83276,7 +85234,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem *pMem){
return;
}
if( pMem->enc!=SQLITE_UTF8 ) return;
- if( NEVER(pMem->z==0) ) return;
+ assert( pMem->z!=0 );
if( pMem->flags & MEM_Dyn ){
if( pMem->xDel==sqlite3_free
&& sqlite3_msize(pMem->z) >= (u64)(pMem->n+1)
@@ -83995,27 +85953,30 @@ SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
int i;
Mem *pX;
- for(i=1, pX=pVdbe->aMem+1; inMem; i++, pX++){
- if( pX->pScopyFrom==pMem ){
- u16 mFlags;
- if( pVdbe->db->flags & SQLITE_VdbeTrace ){
- sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
- (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
- }
- /* If pX is marked as a shallow copy of pMem, then try to verify that
- ** no significant changes have been made to pX since the OP_SCopy.
- ** A significant change would indicated a missed call to this
- ** function for pX. Minor changes, such as adding or removing a
- ** dual type, are allowed, as long as the underlying value is the
- ** same. */
- mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
- assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
+ if( pMem->bScopy ){
+ for(i=1, pX=pVdbe->aMem+1; inMem; i++, pX++){
+ if( pX->pScopyFrom==pMem ){
+ u16 mFlags;
+ if( pVdbe->db->flags & SQLITE_VdbeTrace ){
+ sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
+ (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
+ }
+ /* If pX is marked as a shallow copy of pMem, then try to verify that
+ ** no significant changes have been made to pX since the OP_SCopy.
+ ** A significant change would indicated a missed call to this
+ ** function for pX. Minor changes, such as adding or removing a
+ ** dual type, are allowed, as long as the underlying value is the
+ ** same. */
+ mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
+ assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
- /* pMem is the register that is changing. But also mark pX as
- ** undefined so that we can quickly detect the shallow-copy error */
- pX->flags = MEM_Undefined;
- pX->pScopyFrom = 0;
+ /* pMem is the register that is changing. But also mark pX as
+ ** undefined so that we can quickly detect the shallow-copy error */
+ pX->flags = MEM_Undefined;
+ pX->pScopyFrom = 0;
+ }
}
+ pMem->bScopy = 0;
}
pMem->pScopyFrom = 0;
}
@@ -84172,6 +86133,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
if( sqlite3VdbeMemClearAndResize(pMem, (int)MAX(nAlloc,32)) ){
return SQLITE_NOMEM_BKPT;
}
+ assert( pMem->z!=0 );
memcpy(pMem->z, z, nAlloc);
}else{
sqlite3VdbeMemRelease(pMem);
@@ -84386,7 +86348,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
if( pRec==0 ){
Index *pIdx = p->pIdx; /* Index being probed */
- int nByte; /* Bytes of space to allocate */
+ i64 nByte; /* Bytes of space to allocate */
int i; /* Counter variable */
int nCol = pIdx->nColumn; /* Number of index columns including rowid */
@@ -84452,7 +86414,7 @@ static int valueFromFunction(
){
sqlite3_context ctx; /* Context object for function invocation */
sqlite3_value **apVal = 0; /* Function arguments */
- int nVal = 0; /* Size of apVal[] array */
+ int nVal = 0; /* Number of function arguments */
FuncDef *pFunc = 0; /* Function definition */
sqlite3_value *pVal = 0; /* New value */
int rc = SQLITE_OK; /* Return code */
@@ -84483,7 +86445,8 @@ static int valueFromFunction(
goto value_from_function_out;
}
for(i=0; ia[i].pExpr, enc, aff, &apVal[i]);
+ rc = sqlite3Stat4ValueFromExpr(pCtx->pParse, pList->a[i].pExpr, aff,
+ &apVal[i]);
if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
}
}
@@ -85449,12 +87412,10 @@ SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(
int eCallCtx /* Calling context */
){
Vdbe *v = pParse->pVdbe;
- int nByte;
int addr;
sqlite3_context *pCtx;
assert( v );
- nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
- pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
+ pCtx = sqlite3DbMallocRawNN(pParse->db, SZ_CONTEXT(nArg));
if( pCtx==0 ){
assert( pParse->db->mallocFailed );
freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
@@ -85730,7 +87691,7 @@ static Op *opIterNext(VdbeOpIter *p){
}
if( pRet->p4type==P4_SUBPROGRAM ){
- int nByte = (p->nSub+1)*sizeof(SubProgram*);
+ i64 nByte = (1+(u64)p->nSub)*sizeof(SubProgram*);
int j;
for(j=0; jnSub; j++){
if( p->apSub[j]==pRet->p4.pProgram ) break;
@@ -85860,8 +87821,8 @@ SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){
** (1) For each jump instruction with a negative P2 value (a label)
** resolve the P2 value to an actual address.
**
-** (2) Compute the maximum number of arguments used by any SQL function
-** and store that value in *pMaxFuncArgs.
+** (2) Compute the maximum number of arguments used by the xUpdate/xFilter
+** methods of any virtual table and store that value in *pMaxVtabArgs.
**
** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
** indicate what the prepared statement actually does.
@@ -85874,8 +87835,8 @@ SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe *p){
** script numbers the opcodes correctly. Changes to this routine must be
** coordinated with changes to mkopcodeh.tcl.
*/
-static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
- int nMaxArgs = *pMaxFuncArgs;
+static void resolveP2Values(Vdbe *p, int *pMaxVtabArgs){
+ int nMaxVtabArgs = *pMaxVtabArgs;
Op *pOp;
Parse *pParse = p->pParse;
int *aLabel = pParse->aLabel;
@@ -85920,15 +87881,19 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
case OP_VUpdate: {
- if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
+ if( pOp->p2>nMaxVtabArgs ) nMaxVtabArgs = pOp->p2;
break;
}
case OP_VFilter: {
int n;
+ /* The instruction immediately prior to VFilter will be an
+ ** OP_Integer that sets the "argc" value for the VFilter. See
+ ** the code where OP_VFilter is generated at tag-20250207a. */
assert( (pOp - p->aOp) >= 3 );
assert( pOp[-1].opcode==OP_Integer );
+ assert( pOp[-1].p2==pOp->p3+1 );
n = pOp[-1].p1;
- if( n>nMaxArgs ) nMaxArgs = n;
+ if( n>nMaxVtabArgs ) nMaxVtabArgs = n;
/* Fall through into the default case */
/* no break */ deliberate_fall_through
}
@@ -85969,7 +87934,7 @@ resolve_p2_values_loop_exit:
pParse->aLabel = 0;
}
pParse->nLabel = 0;
- *pMaxFuncArgs = nMaxArgs;
+ *pMaxVtabArgs = nMaxVtabArgs;
assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
}
@@ -86198,7 +88163,7 @@ SQLITE_PRIVATE void sqlite3VdbeScanStatus(
const char *zName /* Name of table or index being scanned */
){
if( IS_STMT_SCANSTATUS(p->db) ){
- sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus);
+ i64 nByte = (1+(i64)p->nScan) * sizeof(ScanStatus);
ScanStatus *aNew;
aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
if( aNew ){
@@ -86308,6 +88273,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
*/
SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){
VdbeOp *pOp = sqlite3VdbeGetLastOp(p);
+#ifdef SQLITE_DEBUG
+ while( pOp->opcode==OP_ReleaseReg ) pOp--;
+#endif
if( pOp->p3==iDest && pOp->opcode==OP_Column ){
pOp->p5 |= OPFLAG_TYPEOFARG;
}
@@ -86417,6 +88385,12 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
if( db->pnBytesFreed==0 ) sqlite3DeleteTable(db, (Table*)p4);
break;
}
+ case P4_SUBRTNSIG: {
+ SubrtnSig *pSig = (SubrtnSig*)p4;
+ sqlite3DbFree(db, pSig->zAff);
+ sqlite3DbFree(db, pSig);
+ break;
+ }
}
}
@@ -86996,6 +88970,11 @@ SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
zP4 = pOp->p4.pTab->zName;
break;
}
+ case P4_SUBRTNSIG: {
+ SubrtnSig *pSig = pOp->p4.pSubrtnSig;
+ sqlite3_str_appendf(&x, "subrtnsig:%d,%s", pSig->selId, pSig->zAff);
+ break;
+ }
default: {
zP4 = pOp->p4.z;
}
@@ -87137,6 +89116,7 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
** will be initialized before use.
*/
static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
+ assert( db!=0 );
if( N>0 ){
do{
p->flags = flags;
@@ -87144,6 +89124,7 @@ static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
p->szMalloc = 0;
#ifdef SQLITE_DEBUG
p->pScopyFrom = 0;
+ p->bScopy = 0;
#endif
p++;
}while( (--N)>0 );
@@ -87162,6 +89143,7 @@ static void releaseMemArray(Mem *p, int N){
if( p && N ){
Mem *pEnd = &p[N];
sqlite3 *db = p->db;
+ assert( db!=0 );
if( db->pnBytesFreed ){
do{
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
@@ -87633,7 +89615,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
int nVar; /* Number of parameters */
int nMem; /* Number of VM memory registers */
int nCursor; /* Number of cursors required */
- int nArg; /* Number of arguments in subprograms */
+ int nArg; /* Max number args to xFilter or xUpdate */
int n; /* Loop counter */
struct ReusableSpace x; /* Reusable bulk memory */
@@ -87642,6 +89624,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
assert( pParse!=0 );
assert( p->eVdbeState==VDBE_INIT_STATE );
assert( pParse==p->pParse );
+ assert( pParse->db==p->db );
p->pVList = pParse->pVList;
pParse->pVList = 0;
db = p->db;
@@ -87704,6 +89687,9 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
}
}
+#ifdef SQLITE_DEBUG
+ p->napArg = nArg;
+#endif
if( db->mallocFailed ){
p->nVar = 0;
@@ -87975,10 +89961,12 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt))
|| nTrans<=1
){
- for(i=0; rc==SQLITE_OK && inDb; i++){
- Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
- rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
+ if( needXcommit ){
+ for(i=0; rc==SQLITE_OK && inDb; i++){
+ Btree *pBt = db->aDb[i].pBt;
+ if( sqlite3BtreeTxnState(pBt)>=SQLITE_TXN_WRITE ){
+ rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
+ }
}
}
@@ -87989,7 +89977,9 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
*/
for(i=0; rc==SQLITE_OK && inDb; i++){
Btree *pBt = db->aDb[i].pBt;
- if( pBt ){
+ int txn = sqlite3BtreeTxnState(pBt);
+ if( txn!=SQLITE_TXN_NONE ){
+ assert( needXcommit || txn==SQLITE_TXN_READ );
rc = sqlite3BtreeCommitPhaseTwo(pBt, 0);
}
}
@@ -88244,28 +90234,31 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
/*
-** This function is called when a transaction opened by the database
+** These functions are called when a transaction opened by the database
** handle associated with the VM passed as an argument is about to be
-** committed. If there are outstanding deferred foreign key constraint
-** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
+** committed. If there are outstanding foreign key constraint violations
+** return an error code. Otherwise, SQLITE_OK.
**
** If there are outstanding FK violations and this function returns
-** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
-** and write an error message to it. Then return SQLITE_ERROR.
+** non-zero, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
+** and write an error message to it.
*/
#ifndef SQLITE_OMIT_FOREIGN_KEY
-SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
+static SQLITE_NOINLINE int vdbeFkError(Vdbe *p){
+ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
+ p->errorAction = OE_Abort;
+ sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
+ if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR;
+ return SQLITE_CONSTRAINT_FOREIGNKEY;
+}
+SQLITE_PRIVATE int sqlite3VdbeCheckFkImmediate(Vdbe *p){
+ if( p->nFkConstraint==0 ) return SQLITE_OK;
+ return vdbeFkError(p);
+}
+SQLITE_PRIVATE int sqlite3VdbeCheckFkDeferred(Vdbe *p){
sqlite3 *db = p->db;
- if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0)
- || (!deferred && p->nFkConstraint>0)
- ){
- p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
- p->errorAction = OE_Abort;
- sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
- if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR;
- return SQLITE_CONSTRAINT_FOREIGNKEY;
- }
- return SQLITE_OK;
+ if( (db->nDeferredCons+db->nDeferredImmCons)==0 ) return SQLITE_OK;
+ return vdbeFkError(p);
}
#endif
@@ -88359,7 +90352,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
/* Check for immediate foreign key violations. */
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
- (void)sqlite3VdbeCheckFk(p, 0);
+ (void)sqlite3VdbeCheckFkImmediate(p);
}
/* If the auto-commit flag is set and this is the only active writer
@@ -88373,7 +90366,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
&& db->nVdbeWrite==(p->readOnly==0)
){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
- rc = sqlite3VdbeCheckFk(p, 1);
+ rc = sqlite3VdbeCheckFkDeferred(p);
if( rc!=SQLITE_OK ){
if( NEVER(p->readOnly) ){
sqlite3VdbeLeave(p);
@@ -89183,29 +91176,22 @@ SQLITE_PRIVATE void sqlite3VdbeSerialGet(
return;
}
/*
-** This routine is used to allocate sufficient space for an UnpackedRecord
-** structure large enough to be used with sqlite3VdbeRecordUnpack() if
-** the first argument is a pointer to KeyInfo structure pKeyInfo.
+** Allocate sufficient space for an UnpackedRecord structure large enough
+** to hold a decoded index record for pKeyInfo.
**
-** The space is either allocated using sqlite3DbMallocRaw() or from within
-** the unaligned buffer passed via the second and third arguments (presumably
-** stack space). If the former, then *ppFree is set to a pointer that should
-** be eventually freed by the caller using sqlite3DbFree(). Or, if the
-** allocation comes from the pSpace/szSpace buffer, *ppFree is set to NULL
-** before returning.
-**
-** If an OOM error occurs, NULL is returned.
+** The space is allocated using sqlite3DbMallocRaw(). If an OOM error
+** occurs, NULL is returned.
*/
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
KeyInfo *pKeyInfo /* Description of the record */
){
UnpackedRecord *p; /* Unpacked record to return */
- int nByte; /* Number of bytes required for *p */
+ u64 nByte; /* Number of bytes required for *p */
+ assert( sizeof(UnpackedRecord) + sizeof(Mem)*65536 < 0x7fffffff );
nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))];
- assert( pKeyInfo->aSortFlags!=0 );
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nKeyField + 1;
return p;
@@ -89217,7 +91203,6 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
** contents of the decoded record.
*/
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
- KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
const void *pKey, /* The binary record */
UnpackedRecord *p /* Populate this structure before returning. */
@@ -89228,6 +91213,7 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
u16 u; /* Unsigned loop counter */
u32 szHdr;
Mem *pMem = p->aMem;
+ KeyInfo *pKeyInfo = p->pKeyInfo;
p->default_rc = 0;
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -89245,16 +91231,18 @@ SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(
pMem->z = 0;
sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
d += sqlite3VdbeSerialTypeLen(serial_type);
- pMem++;
if( (++u)>=p->nField ) break;
+ pMem++;
}
if( d>(u32)nKey && u ){
assert( CORRUPT_DB );
/* In a corrupt record entry, the last pMem might have been set up using
** uninitialized memory. Overwrite its value with NULL, to prevent
** warnings from MSAN. */
- sqlite3VdbeMemSetNull(pMem-1);
+ sqlite3VdbeMemSetNull(pMem-(unField));
}
+ testcase( u == pKeyInfo->nKeyField + 1 );
+ testcase( u < pKeyInfo->nKeyField + 1 );
assert( u<=pKeyInfo->nKeyField + 1 );
p->nField = u;
}
@@ -89422,6 +91410,32 @@ static void vdbeAssertFieldCountWithinLimits(
** or positive value if *pMem1 is less than, equal to or greater than
** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
*/
+static SQLITE_NOINLINE int vdbeCompareMemStringWithEncodingChange(
+ const Mem *pMem1,
+ const Mem *pMem2,
+ const CollSeq *pColl,
+ u8 *prcErr /* If an OOM occurs, set to SQLITE_NOMEM */
+){
+ int rc;
+ const void *v1, *v2;
+ Mem c1;
+ Mem c2;
+ sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
+ sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null);
+ sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
+ sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
+ v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
+ v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
+ if( (v1==0 || v2==0) ){
+ if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
+ rc = 0;
+ }else{
+ rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2);
+ }
+ sqlite3VdbeMemReleaseMalloc(&c1);
+ sqlite3VdbeMemReleaseMalloc(&c2);
+ return rc;
+}
static int vdbeCompareMemString(
const Mem *pMem1,
const Mem *pMem2,
@@ -89433,25 +91447,7 @@ static int vdbeCompareMemString(
** comparison function directly */
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
}else{
- int rc;
- const void *v1, *v2;
- Mem c1;
- Mem c2;
- sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
- sqlite3VdbeMemInit(&c2, pMem1->db, MEM_Null);
- sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
- sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
- v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
- v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
- if( (v1==0 || v2==0) ){
- if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
- rc = 0;
- }else{
- rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2);
- }
- sqlite3VdbeMemReleaseMalloc(&c1);
- sqlite3VdbeMemReleaseMalloc(&c2);
- return rc;
+ return vdbeCompareMemStringWithEncodingChange(pMem1,pMem2,pColl,prcErr);
}
}
@@ -89505,7 +91501,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem
** We must use separate SQLITE_NOINLINE functions here, since otherwise
** optimizer code movement causes gcov to become very confused.
*/
-#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
static int SQLITE_NOINLINE doubleLt(double a, double b){ return ar );
- testcase( x==r );
- return (xr);
}else{
i64 y;
if( r<-9223372036854775808.0 ) return +1;
@@ -90121,6 +92110,7 @@ SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
** The easiest way to enforce this limit is to consider only records with
** 13 fields or less. If the first field is an integer, the maximum legal
** header size is (12*5 + 1 + 1) bytes. */
+ assert( p->pKeyInfo->aSortFlags!=0 );
if( p->pKeyInfo->nAllField<=13 ){
int flags = p->aMem[0].flags;
if( p->pKeyInfo->aSortFlags[0] ){
@@ -90340,7 +92330,8 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
assert( iVar>0 );
if( v ){
Mem *pMem = &v->aVar[iVar-1];
- assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0
+ || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
if( 0==(pMem->flags & MEM_Null) ){
sqlite3_value *pRet = sqlite3ValueNew(v->db);
if( pRet ){
@@ -90360,7 +92351,8 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
*/
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
assert( iVar>0 );
- assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
+ assert( (v->db->flags & SQLITE_EnableQPSG)==0
+ || (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
if( iVar>=32 ){
v->expmask |= 0x80000000;
}else{
@@ -90368,6 +92360,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
}
}
+#ifndef SQLITE_OMIT_DATETIME_FUNCS
/*
** Cause a function to throw an error if it was call from OP_PureFunc
** rather than OP_Function.
@@ -90401,6 +92394,7 @@ SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){
}
return 1;
}
+#endif /* SQLITE_OMIT_DATETIME_FUNCS */
#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
/*
@@ -90477,7 +92471,6 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
i64 iKey2;
PreUpdate preupdate;
const char *zTbl = pTab->zName;
- static const u8 fakeSortOrder = 0;
#ifdef SQLITE_DEBUG
int nRealCol;
if( pTab->tabFlags & TF_WithoutRowid ){
@@ -90512,10 +92505,11 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
preupdate.pCsr = pCsr;
preupdate.op = op;
preupdate.iNewReg = iReg;
- preupdate.keyinfo.db = db;
- preupdate.keyinfo.enc = ENC(db);
- preupdate.keyinfo.nKeyField = pTab->nCol;
- preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
+ preupdate.pKeyinfo = (KeyInfo*)&preupdate.uKey;
+ preupdate.pKeyinfo->db = db;
+ preupdate.pKeyinfo->enc = ENC(db);
+ preupdate.pKeyinfo->nKeyField = pTab->nCol;
+ preupdate.pKeyinfo->aSortFlags = 0; /* Indicate .aColl, .nAllField uninit */
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
@@ -90525,8 +92519,9 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
+ vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pUnpacked);
+ vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pNewUnpacked);
+ sqlite3VdbeMemRelease(&preupdate.oldipk);
if( preupdate.aNew ){
int i;
for(i=0; inField; i++){
@@ -90534,9 +92529,27 @@ SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
}
sqlite3DbNNFreeNN(db, preupdate.aNew);
}
+ if( preupdate.apDflt ){
+ int i;
+ for(i=0; inCol; i++){
+ sqlite3ValueFree(preupdate.apDflt[i]);
+ }
+ sqlite3DbFree(db, preupdate.apDflt);
+ }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
+#ifdef SQLITE_ENABLE_PERCENTILE
+/*
+** Return the name of an SQL function associated with the sqlite3_context.
+*/
+SQLITE_PRIVATE const char *sqlite3VdbeFuncName(const sqlite3_context *pCtx){
+ assert( pCtx!=0 );
+ assert( pCtx->pFunc!=0 );
+ return pCtx->pFunc->zName;
+}
+#endif /* SQLITE_ENABLE_PERCENTILE */
+
/************** End of vdbeaux.c *********************************************/
/************** Begin file vdbeapi.c *****************************************/
/*
@@ -90604,7 +92617,6 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
sqlite3_int64 iNow;
sqlite3_int64 iElapse;
assert( p->startTime>0 );
- assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
assert( db->init.busy==0 );
assert( p->zSql!=0 );
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
@@ -91324,7 +93336,7 @@ static int sqlite3Step(Vdbe *p){
}
assert( db->nVdbeWrite>0 || db->autoCommit==0
- || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
+ || ((db->nDeferredCons + db->nDeferredImmCons)==0)
);
#ifndef SQLITE_OMIT_TRACE
@@ -91835,6 +93847,7 @@ static const Mem *columnNullValue(void){
#ifdef SQLITE_DEBUG
/* .pScopyFrom = */ (Mem*)0,
/* .mScopyFlags= */ 0,
+ /* .bScopy = */ 0,
#endif
};
return &nullMem;
@@ -91876,7 +93889,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
** sqlite3_column_int64()
** sqlite3_column_text()
** sqlite3_column_text16()
-** sqlite3_column_real()
+** sqlite3_column_double()
** sqlite3_column_bytes()
** sqlite3_column_bytes16()
** sqlite3_column_blob()
@@ -92162,6 +94175,17 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
+**
+** (tag-20240917-01) If vdbeUnbind(p,(u32)(i-1)) returns SQLITE_OK,
+** that means all of the the following will be true:
+**
+** p!=0
+** p->pVar!=0
+** i>0
+** i<=p->nVar
+**
+** An assert() is normally added after vdbeUnbind() to help static analyzers
+** realize this.
*/
static int vdbeUnbind(Vdbe *p, unsigned int i){
Mem *pVar;
@@ -92219,11 +94243,16 @@ static int bindText(
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
if( zData!=0 ){
pVar = &p->aVar[i-1];
rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
- if( rc==SQLITE_OK && encoding!=0 ){
- rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
+ if( rc==SQLITE_OK ){
+ if( encoding==0 ){
+ pVar->enc = ENC(p->db);
+ }else{
+ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
+ }
}
if( rc ){
sqlite3Error(p->db, rc);
@@ -92268,6 +94297,7 @@ SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
sqlite3_mutex_leave(p->db->mutex);
}
@@ -92281,6 +94311,7 @@ SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValu
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
sqlite3_mutex_leave(p->db->mutex);
}
@@ -92291,6 +94322,7 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3_mutex_leave(p->db->mutex);
}
return rc;
@@ -92306,6 +94338,7 @@ SQLITE_API int sqlite3_bind_pointer(
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
sqlite3_mutex_leave(p->db->mutex);
}else if( xDestructor ){
@@ -92333,7 +94366,7 @@ SQLITE_API int sqlite3_bind_text64(
assert( xDel!=SQLITE_DYNAMIC );
if( enc!=SQLITE_UTF8 ){
if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
- nData &= ~(u16)1;
+ nData &= ~(u64)1;
}
return bindText(pStmt, i, zData, nData, xDel, enc);
}
@@ -92387,6 +94420,7 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, (u32)(i-1));
if( rc==SQLITE_OK ){
+ assert( p!=0 && p->aVar!=0 && i>0 && i<=p->nVar ); /* tag-20240917-01 */
#ifndef SQLITE_OMIT_INCRBLOB
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
#else
@@ -92687,7 +94721,7 @@ static UnpackedRecord *vdbeUnpackRecord(
pRet = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
if( pRet ){
memset(pRet->aMem, 0, sizeof(Mem)*(pKeyInfo->nKeyField+1));
- sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, pRet);
+ sqlite3VdbeRecordUnpack(nKey, pKey, pRet);
}
return pRet;
}
@@ -92700,6 +94734,7 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
PreUpdate *p;
Mem *pMem;
int rc = SQLITE_OK;
+ int iStore = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( db==0 || ppValue==0 ){
@@ -92714,44 +94749,78 @@ SQLITE_API int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_old_out;
}
if( p->pPk ){
- iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ }else if( iIdx >= p->pTab->nCol ){
+ rc = SQLITE_MISUSE_BKPT;
+ goto preupdate_old_out;
+ }else{
+ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx);
}
- if( iIdx>=p->pCsr->nField || iIdx<0 ){
+ if( iStore>=p->pCsr->nField || iStore<0 ){
rc = SQLITE_RANGE;
goto preupdate_old_out;
}
- /* If the old.* record has not yet been loaded into memory, do so now. */
- if( p->pUnpacked==0 ){
- u32 nRec;
- u8 *aRec;
-
- assert( p->pCsr->eCurType==CURTYPE_BTREE );
- nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
- aRec = sqlite3DbMallocRaw(db, nRec);
- if( !aRec ) goto preupdate_old_out;
- rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
- if( rc==SQLITE_OK ){
- p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
- if( !p->pUnpacked ) rc = SQLITE_NOMEM;
- }
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, aRec);
- goto preupdate_old_out;
- }
- p->aRecord = aRec;
- }
-
- pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
+ *ppValue = pMem = &p->oldipk;
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
- }else if( iIdx>=p->pUnpacked->nField ){
- *ppValue = (sqlite3_value *)columnNullValue();
- }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
- if( pMem->flags & (MEM_Int|MEM_IntReal) ){
- testcase( pMem->flags & MEM_Int );
- testcase( pMem->flags & MEM_IntReal );
- sqlite3VdbeMemRealify(pMem);
+ }else{
+
+ /* If the old.* record has not yet been loaded into memory, do so now. */
+ if( p->pUnpacked==0 ){
+ u32 nRec;
+ u8 *aRec;
+
+ assert( p->pCsr->eCurType==CURTYPE_BTREE );
+ nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
+ aRec = sqlite3DbMallocRaw(db, nRec);
+ if( !aRec ) goto preupdate_old_out;
+ rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
+ if( rc==SQLITE_OK ){
+ p->pUnpacked = vdbeUnpackRecord(p->pKeyinfo, nRec, aRec);
+ if( !p->pUnpacked ) rc = SQLITE_NOMEM;
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(db, aRec);
+ goto preupdate_old_out;
+ }
+ p->aRecord = aRec;
+ }
+
+ pMem = *ppValue = &p->pUnpacked->aMem[iStore];
+ if( iStore>=p->pUnpacked->nField ){
+ /* This occurs when the table has been extended using ALTER TABLE
+ ** ADD COLUMN. The value to return is the default value of the column. */
+ Column *pCol = &p->pTab->aCol[iIdx];
+ if( pCol->iDflt>0 ){
+ if( p->apDflt==0 ){
+ int nByte;
+ assert( sizeof(sqlite3_value*)*UMXV(p->pTab->nCol) < 0x7fffffff );
+ nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
+ p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
+ if( p->apDflt==0 ) goto preupdate_old_out;
+ }
+ if( p->apDflt[iIdx]==0 ){
+ sqlite3_value *pVal = 0;
+ Expr *pDflt;
+ assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
+ pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
+ rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
+ if( rc==SQLITE_OK && pVal==0 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
+ p->apDflt[iIdx] = pVal;
+ }
+ *ppValue = p->apDflt[iIdx];
+ }else{
+ *ppValue = (sqlite3_value *)columnNullValue();
+ }
+ }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
+ if( pMem->flags & (MEM_Int|MEM_IntReal) ){
+ testcase( pMem->flags & MEM_Int );
+ testcase( pMem->flags & MEM_IntReal );
+ sqlite3VdbeMemRealify(pMem);
+ }
}
}
@@ -92773,7 +94842,7 @@ SQLITE_API int sqlite3_preupdate_count(sqlite3 *db){
#else
p = db->pPreUpdate;
#endif
- return (p ? p->keyinfo.nKeyField : 0);
+ return (p ? p->pKeyinfo->nKeyField : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -92825,6 +94894,7 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
PreUpdate *p;
int rc = SQLITE_OK;
Mem *pMem;
+ int iStore = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( db==0 || ppValue==0 ){
@@ -92837,9 +94907,14 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
goto preupdate_new_out;
}
if( p->pPk && p->op!=SQLITE_UPDATE ){
- iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ iStore = sqlite3TableColumnToIndex(p->pPk, iIdx);
+ }else if( iIdx >= p->pTab->nCol ){
+ return SQLITE_MISUSE_BKPT;
+ }else{
+ iStore = sqlite3TableColumnToStorage(p->pTab, iIdx);
}
- if( iIdx>=p->pCsr->nField || iIdx<0 ){
+
+ if( iStore>=p->pCsr->nField || iStore<0 ){
rc = SQLITE_RANGE;
goto preupdate_new_out;
}
@@ -92852,40 +94927,41 @@ SQLITE_API int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppVa
Mem *pData = &p->v->aMem[p->iNewReg];
rc = ExpandBlob(pData);
if( rc!=SQLITE_OK ) goto preupdate_new_out;
- pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z);
+ pUnpack = vdbeUnpackRecord(p->pKeyinfo, pData->n, pData->z);
if( !pUnpack ){
rc = SQLITE_NOMEM;
goto preupdate_new_out;
}
p->pNewUnpacked = pUnpack;
}
- pMem = &pUnpack->aMem[iIdx];
+ pMem = &pUnpack->aMem[iStore];
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
- }else if( iIdx>=pUnpack->nField ){
+ }else if( iStore>=pUnpack->nField ){
pMem = (sqlite3_value *)columnNullValue();
}
}else{
- /* For an UPDATE, memory cell (p->iNewReg+1+iIdx) contains the required
+ /* For an UPDATE, memory cell (p->iNewReg+1+iStore) contains the required
** value. Make a copy of the cell contents and return a pointer to it.
** It is not safe to return a pointer to the memory cell itself as the
** caller may modify the value text encoding.
*/
assert( p->op==SQLITE_UPDATE );
if( !p->aNew ){
- p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem) * p->pCsr->nField);
+ assert( sizeof(Mem)*UMXV(p->pCsr->nField) < 0x7fffffff );
+ p->aNew = (Mem *)sqlite3DbMallocZero(db, sizeof(Mem)*p->pCsr->nField);
if( !p->aNew ){
rc = SQLITE_NOMEM;
goto preupdate_new_out;
}
}
- assert( iIdx>=0 && iIdxpCsr->nField );
- pMem = &p->aNew[iIdx];
+ assert( iStore>=0 && iStorepCsr->nField );
+ pMem = &p->aNew[iStore];
if( pMem->flags==0 ){
if( iIdx==p->pTab->iPKey ){
sqlite3VdbeMemSetInt64(pMem, p->iKey2);
}else{
- rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iIdx]);
+ rc = sqlite3VdbeMemCopy(pMem, &p->v->aMem[p->iNewReg+1+iStore]);
if( rc!=SQLITE_OK ) goto preupdate_new_out;
}
}
@@ -93109,10 +95185,10 @@ SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
** a host parameter. If the text contains no host parameters, return
** the total number of bytes in the text.
*/
-static int findNextHostParameter(const char *zSql, int *pnToken){
+static i64 findNextHostParameter(const char *zSql, i64 *pnToken){
int tokenType;
- int nTotal = 0;
- int n;
+ i64 nTotal = 0;
+ i64 n;
*pnToken = 0;
while( zSql[0] ){
@@ -93159,8 +95235,8 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
sqlite3 *db; /* The database connection */
int idx = 0; /* Index of a host parameter */
int nextIndex = 1; /* Index of next ? host parameter */
- int n; /* Length of a token prefix */
- int nToken; /* Length of the parameter token */
+ i64 n; /* Length of a token prefix */
+ i64 nToken; /* Length of the parameter token */
int i; /* Loop counter */
Mem *pVar; /* Value of a host parameter */
StrAccum out; /* Accumulate the output here */
@@ -93299,6 +95375,104 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
/* #include "sqliteInt.h" */
/* #include "vdbeInt.h" */
+/*
+** High-resolution hardware timer used for debugging and testing only.
+*/
+#if defined(VDBE_PROFILE) \
+ || defined(SQLITE_PERFORMANCE_TRACE) \
+ || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
+/************** Include hwtime.h in the middle of vdbe.c *********************/
+/************** Begin file hwtime.h ******************************************/
+/*
+** 2008 May 27
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains inline asm code for retrieving "high-performance"
+** counters for x86 and x86_64 class CPUs.
+*/
+#ifndef SQLITE_HWTIME_H
+#define SQLITE_HWTIME_H
+
+/*
+** The following routine only works on Pentium-class (or newer) processors.
+** It uses the RDTSC opcode to read the cycle count value out of the
+** processor and returns that value. This can be used for high-res
+** profiling.
+*/
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
+
+ #if defined(__GNUC__)
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+ #elif defined(_MSC_VER)
+
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
+ __asm {
+ rdtsc
+ ret ; return value at EDX:EAX
+ }
+ }
+
+ #endif
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
+
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
+ }
+
+#else
+
+ /*
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlite3Hwtime() routine.
+ **
+ ** sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
+ */
+SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
+
+#endif
+
+#endif /* !defined(SQLITE_HWTIME_H) */
+
+/************** End of hwtime.h **********************************************/
+/************** Continuing where we left off in vdbe.c ***********************/
+#endif
+
/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell. This macro verifies that shallow copies are
@@ -93545,11 +95719,11 @@ static VdbeCursor *allocateCursor(
*/
Mem *pMem = iCur>0 ? &p->aMem[p->nMem-iCur] : p->aMem;
- int nByte;
+ i64 nByte;
VdbeCursor *pCx = 0;
- nByte =
- ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
- (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
+ nByte = SZ_VDBECURSOR(nField);
+ assert( ROUND8(nByte)==nByte );
+ if( eCurType==CURTYPE_BTREE ) nByte += sqlite3BtreeCursorSize();
assert( iCur>=0 && iCurnCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
@@ -93573,7 +95747,7 @@ static VdbeCursor *allocateCursor(
pMem->szMalloc = 0;
return 0;
}
- pMem->szMalloc = nByte;
+ pMem->szMalloc = (int)nByte;
}
p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
@@ -93582,8 +95756,8 @@ static VdbeCursor *allocateCursor(
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+ assert( ROUND8(SZ_VDBECURSOR(nField))==SZ_VDBECURSOR(nField) );
+ pCx->uc.pCursor = (BtCursor*)&pMem->z[SZ_VDBECURSOR(nField)];
sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
@@ -93876,6 +96050,7 @@ static void registerTrace(int iReg, Mem *p){
printf("R[%d] = ", iReg);
memTracePrint(p);
if( p->pScopyFrom ){
+ assert( p->pScopyFrom->bScopy );
printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
}
printf("\n");
@@ -93985,7 +96160,7 @@ static u64 filterHash(const Mem *aMem, const Op *pOp){
static SQLITE_NOINLINE int vdbeColumnFromOverflow(
VdbeCursor *pC, /* The BTree cursor from which we are reading */
int iCol, /* The column to read */
- int t, /* The serial-type code for the column value */
+ u32 t, /* The serial-type code for the column value */
i64 iOffset, /* Offset to the start of the content value */
u32 cacheStatus, /* Current Vdbe.cacheCtr value */
u32 colCacheCtr, /* Current value of the column cache counter */
@@ -94060,6 +96235,36 @@ static SQLITE_NOINLINE int vdbeColumnFromOverflow(
return rc;
}
+/*
+** Send a "statement aborts" message to the error log.
+*/
+static SQLITE_NOINLINE void sqlite3VdbeLogAbort(
+ Vdbe *p, /* The statement that is running at the time of failure */
+ int rc, /* Error code */
+ Op *pOp, /* Opcode that filed */
+ Op *aOp /* All opcodes */
+){
+ const char *zSql = p->zSql; /* Original SQL text */
+ const char *zPrefix = ""; /* Prefix added to SQL text */
+ int pc; /* Opcode address */
+ char zXtra[100]; /* Buffer space to store zPrefix */
+
+ if( p->pFrame ){
+ assert( aOp[0].opcode==OP_Init );
+ if( aOp[0].p4.z!=0 ){
+ assert( aOp[0].p4.z[0]=='-'
+ && aOp[0].p4.z[1]=='-'
+ && aOp[0].p4.z[2]==' ' );
+ sqlite3_snprintf(sizeof(zXtra), zXtra,"/* %s */ ",aOp[0].p4.z+3);
+ zPrefix = zXtra;
+ }else{
+ zPrefix = "/* unknown trigger */ ";
+ }
+ }
+ pc = (int)(pOp - aOp);
+ sqlite3_log(rc, "statement aborts at %d: %s; [%s%s]",
+ pc, p->zErrMsg, zPrefix, zSql);
+}
/*
** Return the symbolic name for the data type of a pMem
@@ -94492,7 +96697,7 @@ case OP_HaltIfNull: { /* in3 */
/* no break */ deliberate_fall_through
}
-/* Opcode: Halt P1 P2 * P4 P5
+/* Opcode: Halt P1 P2 P3 P4 P5
**
** Exit immediately. All open cursors, etc are closed
** automatically.
@@ -94505,18 +96710,22 @@ case OP_HaltIfNull: { /* in3 */
** then back out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction.
**
-** If P4 is not null then it is an error message string.
+** If P3 is not zero and P4 is NULL, then P3 is a register that holds the
+** text of an error message.
**
-** P5 is a value between 0 and 4, inclusive, that modifies the P4 string.
+** If P3 is zero and P4 is not null then the error message string is held
+** in P4.
+**
+** P5 is a value between 1 and 4, inclusive, then the P4 error message
+** string is modified as follows:
**
-** 0: (no change)
** 1: NOT NULL constraint failed: P4
** 2: UNIQUE constraint failed: P4
** 3: CHECK constraint failed: P4
** 4: FOREIGN KEY constraint failed: P4
**
-** If P5 is not zero and P4 is NULL, then everything after the ":" is
-** omitted.
+** If P3 is zero and P5 is not zero and P4 is NULL, then everything after
+** the ":" is omitted.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program. So a jump past the last instruction of the program
@@ -94529,6 +96738,9 @@ case OP_Halt: {
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
#endif
+ assert( pOp->p4type==P4_NOTUSED
+ || pOp->p4type==P4_STATIC
+ || pOp->p4type==P4_DYNAMIC );
/* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates
** something is wrong with the code generator. Raise an assertion in order
@@ -94559,7 +96771,12 @@ case OP_Halt: {
p->errorAction = (u8)pOp->p2;
assert( pOp->p5<=4 );
if( p->rc ){
- if( pOp->p5 ){
+ if( pOp->p3>0 && pOp->p4type==P4_NOTUSED ){
+ const char *zErr;
+ assert( pOp->p3<=(p->nMem + 1 - p->nCursor) );
+ zErr = sqlite3ValueText(&aMem[pOp->p3], SQLITE_UTF8);
+ sqlite3VdbeError(p, "%s", zErr);
+ }else if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
"FOREIGN KEY" };
testcase( pOp->p5==1 );
@@ -94573,8 +96790,7 @@ case OP_Halt: {
}else{
sqlite3VdbeError(p, "%s", pOp->p4.z);
}
- pcx = (int)(pOp - aOp);
- sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
+ sqlite3VdbeLogAbort(p, pOp->p1, pOp, aOp);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -94847,6 +97063,7 @@ case OP_Move: {
{ int i;
for(i=1; inMem; i++){
if( aMem[i].pScopyFrom==pIn1 ){
+ assert( aMem[i].bScopy );
aMem[i].pScopyFrom = pOut;
}
}
@@ -94919,6 +97136,7 @@ case OP_SCopy: { /* out2 */
#ifdef SQLITE_DEBUG
pOut->pScopyFrom = pIn1;
pOut->mScopyFlags = pIn1->flags;
+ pIn1->bScopy = 1;
#endif
break;
}
@@ -94951,7 +97169,7 @@ case OP_IntCopy: { /* out2 */
** RETURNING clause.
*/
case OP_FkCheck: {
- if( (rc = sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){
+ if( (rc = sqlite3VdbeCheckFkImmediate(p))!=SQLITE_OK ){
goto abort_due_to_error;
}
break;
@@ -95043,10 +97261,14 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem;
flags2 = pIn2->flags & ~MEM_Str;
}
- nByte = pIn1->n + pIn2->n;
+ nByte = pIn1->n;
+ nByte += pIn2->n;
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
+#if SQLITE_MAX_LENGTH>2147483645
+ if( nByte>2147483645 ){ goto too_big; }
+#endif
if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
goto no_mem;
}
@@ -95362,7 +97584,7 @@ case OP_RealAffinity: { /* in1 */
}
#endif
-#if !defined(SQLITE_OMIT_CAST) && !defined(SQLITE_OMIT_ANALYZE)
+#if !defined(SQLITE_OMIT_CAST) || !defined(SQLITE_OMIT_ANALYZE)
/* Opcode: Cast P1 P2 * * *
** Synopsis: affinity(r[P1])
**
@@ -95730,6 +97952,7 @@ case OP_Compare: {
pKeyInfo = pOp->p4.pKeyInfo;
assert( n>0 );
assert( pKeyInfo!=0 );
+ assert( pKeyInfo->aSortFlags!=0 );
p1 = pOp->p1;
p2 = pOp->p2;
#ifdef SQLITE_DEBUG
@@ -95898,7 +98121,7 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
break;
}
-/* Opcode: Once P1 P2 * * *
+/* Opcode: Once P1 P2 P3 * *
**
** Fall through to the next instruction the first time this opcode is
** encountered on each invocation of the byte-code program. Jump to P2
@@ -95914,6 +98137,12 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
** whether or not the jump should be taken. The bitmask is necessary
** because the self-altering code trick does not work for recursive
** triggers.
+**
+** The P3 operand is not used directly by this opcode. However P3 is
+** used by the code generator as follows: If this opcode is the start
+** of a subroutine and that subroutine uses a Bloom filter, then P3 will
+** be the register that holds that Bloom filter. See tag-202407032019
+** in the source code for implementation details.
*/
case OP_Once: { /* jump */
u32 iAddr; /* Address of this instruction */
@@ -96486,6 +98715,15 @@ op_column_corrupt:
** Take the affinities from the Table object in P4. If any value
** cannot be coerced into the correct type, then raise an error.
**
+** If P3==0, then omit checking of VIRTUAL columns.
+**
+** If P3==1, then omit checking of all generated column, both VIRTUAL
+** and STORED.
+**
+** If P3>=2, then only check column number P3-2 in the table (which will
+** be a VIRTUAL column) against the value in reg[P1]. In this case,
+** P2 will be 1.
+**
** This opcode is similar to OP_Affinity except that this opcode
** forces the register type to the Table column type. This is used
** to implement "strict affinity".
@@ -96499,8 +98737,8 @@ op_column_corrupt:
**
**
** - P2 should be the number of non-virtual columns in the
-** table of P4.
-**
- Table P4 should be a STRICT table.
+** table of P4 unless P3>1, in which case P2 will be 1.
+**
- Table P4 is a STRICT table.
**
**
** If any precondition is false, an assertion fault occurs.
@@ -96509,16 +98747,28 @@ case OP_TypeCheck: {
Table *pTab;
Column *aCol;
int i;
+ int nCol;
assert( pOp->p4type==P4_TABLE );
pTab = pOp->p4.pTab;
assert( pTab->tabFlags & TF_Strict );
- assert( pTab->nNVCol==pOp->p2 );
+ assert( pOp->p3>=0 && pOp->p3nCol+2 );
aCol = pTab->aCol;
pIn1 = &aMem[pOp->p1];
- for(i=0; inCol; i++){
- if( aCol[i].colFlags & COLFLAG_GENERATED ){
- if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue;
+ if( pOp->p3<2 ){
+ assert( pTab->nNVCol==pOp->p2 );
+ i = 0;
+ nCol = pTab->nCol;
+ }else{
+ i = pOp->p3-2;
+ nCol = i+1;
+ assert( inCol );
+ assert( aCol[i].colFlags & COLFLAG_VIRTUAL );
+ assert( pOp->p2==1 );
+ }
+ for(; ip3<2 ){
+ if( (aCol[i].colFlags & COLFLAG_VIRTUAL)!=0 ) continue;
if( pOp->p3 ){ pIn1++; continue; }
}
assert( pIn1 < &aMem[pOp->p1+pOp->p2] );
@@ -96840,7 +99090,7 @@ case OP_MakeRecord: {
len = (u32)pRec->n;
serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0);
if( pRec->flags & MEM_Zero ){
- serial_type += pRec->u.nZero*2;
+ serial_type += (u32)pRec->u.nZero*2;
if( nData ){
if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
len += pRec->u.nZero;
@@ -96959,6 +99209,7 @@ case OP_MakeRecord: {
zHdr += sqlite3PutVarint(zHdr, serial_type);
if( pRec->n ){
assert( pRec->z!=0 );
+ assert( pRec->z!=(const char*)sqlite3CtypeMap );
memcpy(zPayload, pRec->z, pRec->n);
zPayload += pRec->n;
}
@@ -97106,7 +99357,7 @@ case OP_Savepoint: {
*/
int isTransaction = pSavepoint->pNext==0 && db->isTransactionSavepoint;
if( isTransaction && p1==SAVEPOINT_RELEASE ){
- if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
+ if( (rc = sqlite3VdbeCheckFkDeferred(p))!=SQLITE_OK ){
goto vdbe_return;
}
db->autoCommit = 1;
@@ -97224,7 +99475,7 @@ case OP_AutoCommit: {
"SQL statements in progress");
rc = SQLITE_BUSY;
goto abort_due_to_error;
- }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
+ }else if( (rc = sqlite3VdbeCheckFkDeferred(p))!=SQLITE_OK ){
goto vdbe_return;
}else{
db->autoCommit = (u8)desiredAutoCommit;
@@ -97602,23 +99853,23 @@ case OP_OpenWrite:
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
p->minWriteFileFormat = pDb->pSchema->file_format;
}
+ if( pOp->p5 & OPFLAG_P2ISREG ){
+ assert( p2>0 );
+ assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
+ pIn2 = &aMem[p2];
+ assert( memIsValid(pIn2) );
+ assert( (pIn2->flags & MEM_Int)!=0 );
+ sqlite3VdbeMemIntegerify(pIn2);
+ p2 = (int)pIn2->u.i;
+ /* The p2 value always comes from a prior OP_CreateBtree opcode and
+ ** that opcode will always set the p2 value to 2 or more or else fail.
+ ** If there were a failure, the prepared statement would have halted
+ ** before reaching this instruction. */
+ assert( p2>=2 );
+ }
}else{
wrFlag = 0;
- }
- if( pOp->p5 & OPFLAG_P2ISREG ){
- assert( p2>0 );
- assert( p2<=(u32)(p->nMem+1 - p->nCursor) );
- assert( pOp->opcode==OP_OpenWrite );
- pIn2 = &aMem[p2];
- assert( memIsValid(pIn2) );
- assert( (pIn2->flags & MEM_Int)!=0 );
- sqlite3VdbeMemIntegerify(pIn2);
- p2 = (int)pIn2->u.i;
- /* The p2 value always comes from a prior OP_CreateBtree opcode and
- ** that opcode will always set the p2 value to 2 or more or else fail.
- ** If there were a failure, the prepared statement would have halted
- ** before reaching this instruction. */
- assert( p2>=2 );
+ assert( (pOp->p5 & OPFLAG_P2ISREG)==0 );
}
if( pOp->p4type==P4_KEYINFO ){
pKeyInfo = pOp->p4.pKeyInfo;
@@ -97795,8 +100046,13 @@ case OP_OpenEphemeral: { /* ncycle */
}
}
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ assert( p->apCsr[pOp->p1]==pCx );
if( rc ){
+ assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
sqlite3BtreeClose(pCx->ub.pBtx);
+ p->apCsr[pOp->p1] = 0; /* Not required; helps with static analysis */
+ }else{
+ assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
}
}
}
@@ -98574,6 +100830,7 @@ case OP_Found: { /* jump, in3, ncycle */
r.pKeyInfo = pC->pKeyInfo;
r.default_rc = 0;
#ifdef SQLITE_DEBUG
+ (void)sqlite3FaultSim(50); /* For use by --counter in TH3 */
for(ii=0; iipKeyInfo);
if( pIdxKey==0 ) goto no_mem;
- sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey);
+ sqlite3VdbeRecordUnpack(r.aMem->n, r.aMem->z, pIdxKey);
pIdxKey->default_rc = 0;
rc = sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
sqlite3DbFreeNN(db, pIdxKey);
@@ -99304,7 +101561,7 @@ case OP_RowData: {
/* The OP_RowData opcodes always follow OP_NotExists or
** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
** that might invalidate the cursor.
- ** If this where not the case, on of the following assert()s
+ ** If this were not the case, one of the following assert()s
** would fail. Should this ever change (because of changes in the code
** generator) then the fix would be to insert a call to
** sqlite3VdbeCursorMoveto().
@@ -99588,6 +101845,32 @@ case OP_Rewind: { /* jump0, ncycle */
break;
}
+/* Opcode: IfEmpty P1 P2 * * *
+** Synopsis: if( empty(P1) ) goto P2
+**
+** Check to see if the b-tree table that cursor P1 references is empty
+** and jump to P2 if it is.
+*/
+case OP_IfEmpty: { /* jump */
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+
+ assert( pOp->p1>=0 && pOp->p1nCursor );
+ assert( pOp->p2>=0 && pOp->p2nOp );
+
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ pCrsr = pC->uc.pCursor;
+ assert( pCrsr );
+ rc = sqlite3BtreeIsEmpty(pCrsr, &res);
+ if( rc ) goto abort_due_to_error;
+ VdbeBranchTaken(res!=0,2);
+ if( res ) goto jump_to_p2;
+ break;
+}
+
/* Opcode: Next P1 P2 P3 * P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
@@ -100573,7 +102856,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
*/
case OP_Program: { /* jump0 */
int nMem; /* Number of memory registers for sub-program */
- int nByte; /* Bytes of runtime space required for sub-program */
+ i64 nByte; /* Bytes of runtime space required for sub-program */
Mem *pRt; /* Register to allocate runtime space */
Mem *pMem; /* Used to iterate through memory cells */
Mem *pEnd; /* Last memory cell in new array */
@@ -100624,7 +102907,7 @@ case OP_Program: { /* jump0 */
nByte = ROUND8(sizeof(VdbeFrame))
+ nMem * sizeof(Mem)
+ pProgram->nCsr * sizeof(VdbeCursor*)
- + (pProgram->nOp + 7)/8;
+ + (7 + (i64)pProgram->nOp)/8;
pFrame = sqlite3DbMallocZero(db, nByte);
if( !pFrame ){
goto no_mem;
@@ -100632,7 +102915,7 @@ case OP_Program: { /* jump0 */
sqlite3VdbeMemRelease(pRt);
pRt->flags = MEM_Blob|MEM_Dyn;
pRt->z = (char*)pFrame;
- pRt->n = nByte;
+ pRt->n = (int)nByte;
pRt->xDel = sqlite3VdbeFrameMemDel;
pFrame->v = p;
@@ -100731,12 +103014,14 @@ case OP_Param: { /* out2 */
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
- if( db->flags & SQLITE_DeferFKs ){
- db->nDeferredImmCons += pOp->p2;
- }else if( pOp->p1 ){
+ if( pOp->p1 ){
db->nDeferredCons += pOp->p2;
}else{
- p->nFkConstraint += pOp->p2;
+ if( db->flags & SQLITE_DeferFKs ){
+ db->nDeferredImmCons += pOp->p2;
+ }else{
+ p->nFkConstraint += pOp->p2;
+ }
}
break;
}
@@ -100936,18 +103221,29 @@ case OP_AggInverse:
case OP_AggStep: {
int n;
sqlite3_context *pCtx;
+ u64 nAlloc;
assert( pOp->p4type==P4_FUNCDEF );
n = pOp->p5;
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
assert( pOp->p3p2 || pOp->p3>=pOp->p2+n );
- pCtx = sqlite3DbMallocRawNN(db, n*sizeof(sqlite3_value*) +
- (sizeof(pCtx[0]) + sizeof(Mem) - sizeof(sqlite3_value*)));
+
+ /* Allocate space for (a) the context object and (n-1) extra pointers
+ ** to append to the sqlite3_context.argv[1] array, and (b) a memory
+ ** cell in which to store the accumulation. Be careful that the memory
+ ** cell is 8-byte aligned, even on platforms where a pointer is 32-bits.
+ **
+ ** Note: We could avoid this by using a regular memory cell from aMem[] for
+ ** the accumulator, instead of allocating one here. */
+ nAlloc = ROUND8P( SZ_CONTEXT(n) );
+ pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
if( pCtx==0 ) goto no_mem;
- pCtx->pMem = 0;
- pCtx->pOut = (Mem*)&(pCtx->argv[n]);
+ pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
+ assert( EIGHT_BYTE_ALIGNMENT(pCtx->pOut) );
+
sqlite3VdbeMemInit(pCtx->pOut, db, MEM_Null);
+ pCtx->pMem = 0;
pCtx->pFunc = pOp->p4.pFunc;
pCtx->iOp = (int)(pOp - aOp);
pCtx->pVdbe = p;
@@ -101111,6 +103407,7 @@ case OP_Checkpoint: {
|| pOp->p2==SQLITE_CHECKPOINT_FULL
|| pOp->p2==SQLITE_CHECKPOINT_RESTART
|| pOp->p2==SQLITE_CHECKPOINT_TRUNCATE
+ || pOp->p2==SQLITE_CHECKPOINT_NOOP
);
rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &aRes[1], &aRes[2]);
if( rc ){
@@ -101446,7 +103743,14 @@ case OP_VOpen: { /* ncycle */
const sqlite3_module *pModule;
assert( p->bIsReader );
- pCur = 0;
+ pCur = p->apCsr[pOp->p1];
+ if( pCur!=0
+ && ALWAYS( pCur->eCurType==CURTYPE_VTAB )
+ && ALWAYS( pCur->uc.pVCur->pVtab==pOp->p4.pVtab->pVtab )
+ ){
+ /* This opcode is a no-op if the cursor is already open */
+ break;
+ }
pVCur = 0;
pVtab = pOp->p4.pVtab->pVtab;
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
@@ -101600,6 +103904,7 @@ case OP_VFilter: { /* jump, ncycle */
/* Invoke the xFilter method */
apArg = p->apArg;
+ assert( nArg<=p->napArg );
for(i = 0; ivtabOnConflict;
apArg = p->apArg;
pX = &aMem[pOp->p3];
+ assert( nArg<=p->napArg );
for(i=0; iopcode==OP_Noop || pOp->opcode==OP_Explain );
@@ -102371,8 +104692,7 @@ abort_due_to_error:
p->rc = rc;
sqlite3SystemError(db, rc);
testcase( sqlite3GlobalConfig.xLog!=0 );
- sqlite3_log(rc, "statement aborts at %d: [%s] %s",
- (int)(pOp - aOp), p->zSql, p->zErrMsg);
+ sqlite3VdbeLogAbort(p, rc, pOp, aOp);
if( p->eVdbeState==VDBE_RUN_STATE ) sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) sqlite3OomFault(db);
if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
@@ -102581,6 +104901,7 @@ SQLITE_API int sqlite3_blob_open(
char *zErr = 0;
Table *pTab;
Incrblob *pBlob = 0;
+ int iDb;
Parse sParse;
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -102615,13 +104936,21 @@ SQLITE_API int sqlite3_blob_open(
pTab = 0;
sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
}
+ if( pTab && (pTab->tabFlags&TF_HasGenerated)!=0 ){
+ pTab = 0;
+ sqlite3ErrorMsg(&sParse, "cannot open table with generated columns: %s",
+ zTable);
+ }
#ifndef SQLITE_OMIT_VIEW
if( pTab && IsView(pTab) ){
pTab = 0;
sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
}
#endif
- if( !pTab ){
+ if( pTab==0
+ || ((iDb = sqlite3SchemaToIndex(db, pTab->pSchema))==1 &&
+ sqlite3OpenTempDatabase(&sParse))
+ ){
if( sParse.zErrMsg ){
sqlite3DbFree(db, zErr);
zErr = sParse.zErrMsg;
@@ -102632,15 +104961,11 @@ SQLITE_API int sqlite3_blob_open(
goto blob_open_out;
}
pBlob->pTab = pTab;
- pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
+ pBlob->zDb = db->aDb[iDb].zDbSName;
/* Now search pTab for the exact column. */
- for(iCol=0; iColnCol; iCol++) {
- if( sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){
- break;
- }
- }
- if( iCol==pTab->nCol ){
+ iCol = sqlite3ColumnIndex(pTab, zColumn);
+ if( iCol<0 ){
sqlite3DbFree(db, zErr);
zErr = sqlite3MPrintf(db, "no such column: \"%s\"", zColumn);
rc = SQLITE_ERROR;
@@ -102720,7 +105045,6 @@ SQLITE_API int sqlite3_blob_open(
{OP_Halt, 0, 0, 0}, /* 5 */
};
Vdbe *v = (Vdbe *)pBlob->pStmt;
- int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
VdbeOp *aOp;
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
@@ -102829,7 +105153,7 @@ static int blobReadWrite(
int iOffset,
int (*xCall)(BtCursor*, u32, u32, void*)
){
- int rc;
+ int rc = SQLITE_OK;
Incrblob *p = (Incrblob *)pBlob;
Vdbe *v;
sqlite3 *db;
@@ -102869,17 +105193,32 @@ static int blobReadWrite(
** using the incremental-blob API, this works. For the sessions module
** anyhow.
*/
- sqlite3_int64 iKey;
- iKey = sqlite3BtreeIntegerKey(p->pCsr);
- assert( v->apCsr[0]!=0 );
- assert( v->apCsr[0]->eCurType==CURTYPE_BTREE );
- sqlite3VdbePreUpdateHook(
- v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
- );
+ if( sqlite3BtreeCursorIsValidNN(p->pCsr)==0 ){
+ /* If the cursor is not currently valid, try to reseek it. This
+ ** always either fails or finds the correct row - the cursor will
+ ** have been marked permanently CURSOR_INVALID if the open row has
+ ** been deleted. */
+ int bDiff = 0;
+ rc = sqlite3BtreeCursorRestore(p->pCsr, &bDiff);
+ assert( bDiff==0 || sqlite3BtreeCursorIsValidNN(p->pCsr)==0 );
+ }
+ if( sqlite3BtreeCursorIsValidNN(p->pCsr) ){
+ sqlite3_int64 iKey;
+ iKey = sqlite3BtreeIntegerKey(p->pCsr);
+ assert( v->apCsr[0]!=0 );
+ assert( v->apCsr[0]->eCurType==CURTYPE_BTREE );
+ sqlite3VdbePreUpdateHook(
+ v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
+ );
+ }
}
+ if( rc==SQLITE_OK ){
+ rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
+ }
+#else
+ rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
#endif
- rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
sqlite3BtreeLeaveCursor(p->pCsr);
if( rc==SQLITE_ABORT ){
sqlite3VdbeFinalize(v);
@@ -103268,6 +105607,7 @@ struct SortSubtask {
SorterCompare xCompare; /* Compare function to use */
SorterFile file; /* Temp file for level-0 PMAs */
SorterFile file2; /* Space for other PMAs */
+ u64 nSpill; /* Total bytes written by this task */
};
@@ -103298,9 +105638,12 @@ struct VdbeSorter {
u8 iPrev; /* Previous thread used to flush PMA */
u8 nTask; /* Size of aTask[] array */
u8 typeMask;
- SortSubtask aTask[1]; /* One or more subtasks */
+ SortSubtask aTask[FLEXARRAY]; /* One or more subtasks */
};
+/* Size (in bytes) of a VdbeSorter object that works with N or fewer subtasks */
+#define SZ_VDBESORTER(N) (offsetof(VdbeSorter,aTask)+(N)*sizeof(SortSubtask))
+
#define SORTER_TYPE_INTEGER 0x01
#define SORTER_TYPE_TEXT 0x02
@@ -103385,6 +105728,7 @@ struct PmaWriter {
int iBufEnd; /* Last byte of buffer to write */
i64 iWriteOff; /* Offset of start of buffer in file */
sqlite3_file *pFd; /* File handle to write to */
+ u64 nPmaSpill; /* Total number of bytes written */
};
/*
@@ -103522,13 +105866,14 @@ static int vdbePmaReadBlob(
while( nRem>0 ){
int rc; /* vdbePmaReadBlob() return code */
int nCopy; /* Number of bytes to copy */
- u8 *aNext; /* Pointer to buffer to copy data from */
+ u8 *aNext = 0; /* Pointer to buffer to copy data from */
nCopy = nRem;
if( nRem>p->nBuffer ) nCopy = p->nBuffer;
rc = vdbePmaReadBlob(p, nCopy, &aNext);
if( rc!=SQLITE_OK ) return rc;
assert( aNext!=p->aAlloc );
+ assert( aNext!=0 );
memcpy(&p->aAlloc[nByte - nRem], aNext, nCopy);
nRem -= nCopy;
}
@@ -103728,7 +106073,7 @@ static int vdbeSorterCompareTail(
){
UnpackedRecord *r2 = pTask->pUnpacked;
if( *pbKey2Cached==0 ){
- sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
+ sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
*pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
@@ -103755,7 +106100,7 @@ static int vdbeSorterCompare(
){
UnpackedRecord *r2 = pTask->pUnpacked;
if( !*pbKey2Cached ){
- sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
+ sqlite3VdbeRecordUnpack(nKey2, pKey2, r2);
*pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
@@ -103795,6 +106140,7 @@ static int vdbeSorterCompareText(
);
}
}else{
+ assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
res = res * -1;
@@ -103858,6 +106204,7 @@ static int vdbeSorterCompareInt(
}
}
+ assert( pTask->pSorter->pKeyInfo->aSortFlags!=0 );
if( res==0 ){
if( pTask->pSorter->pKeyInfo->nKeyField>1 ){
res = vdbeSorterCompareTail(
@@ -103901,7 +106248,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
VdbeSorter *pSorter; /* The new sorter */
KeyInfo *pKeyInfo; /* Copy of pCsr->pKeyInfo with db==0 */
int szKeyInfo; /* Size of pCsr->pKeyInfo in bytes */
- int sz; /* Size of pSorter in bytes */
+ i64 sz; /* Size of pSorter in bytes */
int rc = SQLITE_OK;
#if SQLITE_MAX_WORKER_THREADS==0
# define nWorker 0
@@ -103929,8 +106276,11 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
assert( pCsr->pKeyInfo );
assert( !pCsr->isEphemeral );
assert( pCsr->eCurType==CURTYPE_SORTER );
- szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
- sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
+ assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
+ < 0x7fffffff );
+ assert( pCsr->pKeyInfo->nKeyField<=pCsr->pKeyInfo->nAllField );
+ szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nAllField);
+ sz = SZ_VDBESORTER(nWorker+1);
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
pCsr->uc.pSorter = pSorter;
@@ -103943,7 +106293,12 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
pKeyInfo->db = 0;
if( nField && nWorker==0 ){
pKeyInfo->nKeyField = nField;
+ assert( nField<=pCsr->pKeyInfo->nAllField );
}
+ /* It is OK that pKeyInfo reuses the aSortFlags field from pCsr->pKeyInfo,
+ ** since the pCsr->pKeyInfo->aSortFlags[] array is invariant and lives
+ ** longer that pSorter. */
+ assert( pKeyInfo->aSortFlags==pCsr->pKeyInfo->aSortFlags );
sqlite3BtreeEnter(pBt);
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(pBt);
sqlite3BtreeLeave(pBt);
@@ -104142,7 +106497,7 @@ static int vdbeSorterJoinAll(VdbeSorter *pSorter, int rcin){
*/
static MergeEngine *vdbeMergeEngineNew(int nReader){
int N = 2; /* Smallest power of two >= nReader */
- int nByte; /* Total bytes of space to allocate */
+ i64 nByte; /* Total bytes of space to allocate */
MergeEngine *pNew; /* Pointer to allocated object to return */
assert( nReader<=SORTER_MAX_MERGE_COUNT );
@@ -104232,6 +106587,12 @@ SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *db, VdbeCursor *pCsr){
assert( pCsr->eCurType==CURTYPE_SORTER );
pSorter = pCsr->uc.pSorter;
if( pSorter ){
+ /* Increment db->nSpill by the total number of bytes of data written
+ ** to temp files by this sort operation. */
+ int ii;
+ for(ii=0; iinTask; ii++){
+ db->nSpill += pSorter->aTask[ii].nSpill;
+ }
sqlite3VdbeSorterReset(db, pSorter);
sqlite3_free(pSorter->list.aMemory);
sqlite3DbFree(db, pSorter);
@@ -104394,6 +106755,10 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
p->u.pNext = 0;
for(i=0; aSlot[i]; i++){
p = vdbeSorterMerge(pTask, p, aSlot[i]);
+ /* ,--Each aSlot[] holds twice as much as the previous. So we cannot use
+ ** | up all 64 aSlots[] with only a 64-bit address space.
+ ** v */
+ assert( iaBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
p->iWriteOff + p->iBufStart
);
+ p->nPmaSpill += (p->iBufEnd - p->iBufStart);
p->iBufStart = p->iBufEnd = 0;
p->iWriteOff += p->nBuffer;
}
@@ -104469,17 +106835,20 @@ static void vdbePmaWriteBlob(PmaWriter *p, u8 *pData, int nData){
** required. Otherwise, return an SQLite error code.
**
** Before returning, set *piEof to the offset immediately following the
-** last byte written to the file.
+** last byte written to the file. Also, increment (*pnSpill) by the total
+** number of bytes written to the file.
*/
-static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof){
+static int vdbePmaWriterFinish(PmaWriter *p, i64 *piEof, u64 *pnSpill){
int rc;
if( p->eFWErr==0 && ALWAYS(p->aBuffer) && p->iBufEnd>p->iBufStart ){
p->eFWErr = sqlite3OsWrite(p->pFd,
&p->aBuffer[p->iBufStart], p->iBufEnd - p->iBufStart,
p->iWriteOff + p->iBufStart
);
+ p->nPmaSpill += (p->iBufEnd - p->iBufStart);
}
*piEof = (p->iWriteOff + p->iBufEnd);
+ *pnSpill += p->nPmaSpill;
sqlite3_free(p->aBuffer);
rc = p->eFWErr;
memset(p, 0, sizeof(PmaWriter));
@@ -104559,7 +106928,7 @@ static int vdbeSorterListToPMA(SortSubtask *pTask, SorterList *pList){
if( pList->aMemory==0 ) sqlite3_free(p);
}
pList->pList = p;
- rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof);
+ rc = vdbePmaWriterFinish(&writer, &pTask->file.iEof, &pTask->nSpill);
}
vdbeSorterWorkDebug(pTask, "exit");
@@ -104873,7 +107242,7 @@ static int vdbeIncrPopulate(IncrMerger *pIncr){
rc = vdbeMergeEngineStep(pIncr->pMerger, &dummy);
}
- rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof);
+ rc2 = vdbePmaWriterFinish(&writer, &pOut->iEof, &pTask->nSpill);
if( rc==SQLITE_OK ) rc = rc2;
vdbeSorterPopulateDebug(pTask, "exit");
return rc;
@@ -105719,7 +108088,7 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
assert( r2->nField==nKeyCol );
pKey = vdbeSorterRowkey(pSorter, &nKey);
- sqlite3VdbeRecordUnpack(pKeyInfo, nKey, pKey, r2);
+ sqlite3VdbeRecordUnpack(nKey, pKey, r2);
for(i=0; iaMem[i].flags & MEM_Null ){
*pRes = -1;
@@ -106798,7 +109167,9 @@ SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
pSrc = p->pSrc;
if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+ if( pItem->fg.isSubquery
+ && sqlite3WalkSelect(pWalker, pItem->u4.pSubq->pSelect)
+ ){
return WRC_Abort;
}
if( pItem->fg.isTabFunc
@@ -107104,7 +109475,7 @@ static void extendFJMatch(
if( pNew ){
pNew->iTable = pMatch->iCursor;
pNew->iColumn = iColumn;
- pNew->y.pTab = pMatch->pTab;
+ pNew->y.pTab = pMatch->pSTab;
assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 );
ExprSetProperty(pNew, EP_CanBeNull);
*ppList = sqlite3ExprListAppend(pParse, *ppList, pNew);
@@ -107117,7 +109488,7 @@ static void extendFJMatch(
static SQLITE_NOINLINE int isValidSchemaTableName(
const char *zTab, /* Name as it appears in the SQL */
Table *pTab, /* The schema table we are trying to match */
- Schema *pSchema /* non-NULL if a database qualifier is present */
+ const char *zDb /* non-NULL if a database qualifier is present */
){
const char *zLegacy;
assert( pTab!=0 );
@@ -107128,7 +109499,7 @@ static SQLITE_NOINLINE int isValidSchemaTableName(
if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
return 1;
}
- if( pSchema==0 ) return 0;
+ if( zDb==0 ) return 0;
if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
}else{
@@ -107183,7 +109554,6 @@ static int lookupName(
Schema *pSchema = 0; /* Schema of the expression */
int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
Table *pTab = 0; /* Table holding the row */
- Column *pCol; /* A column of pTab */
ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */
const char *zCol = pRight->u.zToken;
@@ -107234,11 +109604,10 @@ static int lookupName(
if( pSrcList ){
for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){
- u8 hCol;
- pTab = pItem->pTab;
+ pTab = pItem->pSTab;
assert( pTab!=0 && pTab->zName!=0 );
assert( pTab->nCol>0 || pParse->nErr );
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem));
if( pItem->fg.isNestedFrom ){
/* In this case, pItem is a subquery that has been formed from a
** parenthesized subset of the FROM clause terms. Example:
@@ -107247,8 +109616,12 @@ static int lookupName(
** This pItem -------------^
*/
int hit = 0;
- assert( pItem->pSelect!=0 );
- pEList = pItem->pSelect->pEList;
+ Select *pSel;
+ assert( pItem->fg.isSubquery );
+ assert( pItem->u4.pSubq!=0 );
+ pSel = pItem->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ pEList = pSel->pEList;
assert( pEList!=0 );
assert( pEList->nExpr==pTab->nCol );
for(j=0; jnExpr; j++){
@@ -107260,10 +109633,13 @@ static int lookupName(
if( cnt>0 ){
if( pItem->fg.isUsing==0
|| sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
+ || pMatch==pItem
){
/* Two or more tables have the same column name which is
- ** not joined by USING. This is an error. Signal as much
- ** by clearing pFJMatch and letting cnt go above 1. */
+ ** not joined by USING. Or, a single table has two columns
+ ** that match a USING term (if pMatch==pItem). These are both
+ ** "ambiguous column name" errors. Signal as much by clearing
+ ** pFJMatch and letting cnt go above 1. */
sqlite3ExprListDelete(db, pFJMatch);
pFJMatch = 0;
}else
@@ -107311,50 +109687,45 @@ static int lookupName(
}
}else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){
if( pTab->tnum!=1 ) continue;
- if( !isValidSchemaTableName(zTab, pTab, pSchema) ) continue;
+ if( !isValidSchemaTableName(zTab, pTab, zDb) ) continue;
}
assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT && pItem->zAlias ){
sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
- hCol = sqlite3StrIHash(zCol);
- for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){
- if( pCol->hName==hCol
- && sqlite3StrICmp(pCol->zCnName, zCol)==0
- ){
- if( cnt>0 ){
- if( pItem->fg.isUsing==0
- || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
- ){
- /* Two or more tables have the same column name which is
- ** not joined by USING. This is an error. Signal as much
- ** by clearing pFJMatch and letting cnt go above 1. */
- sqlite3ExprListDelete(db, pFJMatch);
- pFJMatch = 0;
- }else
- if( (pItem->fg.jointype & JT_RIGHT)==0 ){
- /* An INNER or LEFT JOIN. Use the left-most table */
- continue;
- }else
- if( (pItem->fg.jointype & JT_LEFT)==0 ){
- /* A RIGHT JOIN. Use the right-most table */
- cnt = 0;
- sqlite3ExprListDelete(db, pFJMatch);
- pFJMatch = 0;
- }else{
- /* For a FULL JOIN, we must construct a coalesce() func */
- extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
- }
+ j = sqlite3ColumnIndex(pTab, zCol);
+ if( j>=0 ){
+ if( cnt>0 ){
+ if( pItem->fg.isUsing==0
+ || sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
+ ){
+ /* Two or more tables have the same column name which is
+ ** not joined by USING. This is an error. Signal as much
+ ** by clearing pFJMatch and letting cnt go above 1. */
+ sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else
+ if( (pItem->fg.jointype & JT_RIGHT)==0 ){
+ /* An INNER or LEFT JOIN. Use the left-most table */
+ continue;
+ }else
+ if( (pItem->fg.jointype & JT_LEFT)==0 ){
+ /* A RIGHT JOIN. Use the right-most table */
+ cnt = 0;
+ sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else{
+ /* For a FULL JOIN, we must construct a coalesce() func */
+ extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
}
- cnt++;
- pMatch = pItem;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
- if( pItem->fg.isNestedFrom ){
- sqlite3SrcItemColumnUsed(pItem, j);
- }
- break;
+ }
+ cnt++;
+ pMatch = pItem;
+ /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
+ if( pItem->fg.isNestedFrom ){
+ sqlite3SrcItemColumnUsed(pItem, j);
}
}
if( 0==cnt && VisibleRowid(pTab) ){
@@ -107371,9 +109742,9 @@ static int lookupName(
*/
if( cntTab==0
|| (cntTab==1
- && ALWAYS(pMatch!=0)
- && ALWAYS(pMatch->pTab!=0)
- && (pMatch->pTab->tabFlags & TF_Ephemeral)!=0
+ && pMatch!=0
+ && ALWAYS(pMatch->pSTab!=0)
+ && (pMatch->pSTab->tabFlags & TF_Ephemeral)!=0
&& (pTab->tabFlags & TF_Ephemeral)==0)
){
cntTab = 1;
@@ -107394,7 +109765,7 @@ static int lookupName(
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
assert( ExprUseYTab(pExpr) );
- pExpr->y.pTab = pMatch->pTab;
+ pExpr->y.pTab = pMatch->pSTab;
if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
@@ -107436,7 +109807,7 @@ static int lookupName(
if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
Upsert *pUpsert = pNC->uNC.pUpsert;
if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
- pTab = pUpsert->pUpsertSrc->a[0].pTab;
+ pTab = pUpsert->pUpsertSrc->a[0].pSTab;
pExpr->iTable = EXCLUDED_TABLE_NUMBER;
}
}
@@ -107444,23 +109815,18 @@ static int lookupName(
if( pTab ){
int iCol;
- u8 hCol = sqlite3StrIHash(zCol);
pSchema = pTab->pSchema;
cntTab++;
- for(iCol=0, pCol=pTab->aCol; iColnCol; iCol++, pCol++){
- if( pCol->hName==hCol
- && sqlite3StrICmp(pCol->zCnName, zCol)==0
- ){
- if( iCol==pTab->iPKey ){
- iCol = -1;
- }
- break;
+ iCol = sqlite3ColumnIndex(pTab, zCol);
+ if( iCol>=0 ){
+ if( pTab->iPKey==iCol ) iCol = -1;
+ }else{
+ if( sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
+ iCol = -1;
+ }else{
+ iCol = pTab->nCol;
}
}
- if( iCol>=pTab->nCol && sqlite3IsRowid(zCol) && VisibleRowid(pTab) ){
- /* IMP: R-51414-32910 */
- iCol = -1;
- }
if( iColnCol ){
cnt++;
pMatch = 0;
@@ -107519,11 +109885,11 @@ static int lookupName(
&& pMatch
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& sqlite3IsRowid(zCol)
- && ALWAYS(VisibleRowid(pMatch->pTab) || pMatch->fg.isNestedFrom)
+ && ALWAYS(VisibleRowid(pMatch->pSTab) || pMatch->fg.isNestedFrom)
){
cnt = cntTab;
#if SQLITE_ALLOW_ROWID_IN_VIEW+0==2
- if( pMatch->pTab!=0 && IsView(pMatch->pTab) ){
+ if( pMatch->pSTab!=0 && IsView(pMatch->pSTab) ){
eNewExprOp = TK_NULL;
}
#endif
@@ -107760,7 +110126,7 @@ SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *db, SrcList *pSrc, int iSr
SrcItem *pItem = &pSrc->a[iSrc];
Table *pTab;
assert( ExprUseYTab(p) );
- pTab = p->y.pTab = pItem->pTab;
+ pTab = p->y.pTab = pItem->pSTab;
p->iTable = pItem->iCursor;
if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
@@ -107823,8 +110189,8 @@ static void notValidImpl(
/*
** 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.
+** Return 134,217,728 (2^27) 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;
@@ -107879,7 +110245,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
assert( ExprUseYTab(pExpr) );
- pExpr->y.pTab = pItem->pTab;
+ pExpr->y.pTab = pItem->pSTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn--;
pExpr->affExpr = SQLITE_AFF_INTEGER;
@@ -108004,8 +110370,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
/* Resolve function names
*/
case TK_FUNCTION: {
- ExprList *pList = pExpr->x.pList; /* The argument list */
- int n = pList ? pList->nExpr : 0; /* Number of arguments */
+ ExprList *pList; /* The argument list */
+ int n; /* Number of arguments */
int no_such_func = 0; /* True if no such function exists */
int wrong_num_args = 0; /* True if wrong number of arguments */
int is_agg = 0; /* True if is an aggregate function */
@@ -108018,6 +110384,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
assert( pExpr->pLeft==0 || pExpr->pLeft->op==TK_ORDER );
+ pList = pExpr->x.pList;
+ n = pList ? pList->nExpr : 0;
zId = pExpr->u.zToken;
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
if( pDef==0 ){
@@ -108066,6 +110434,24 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}
}
#endif
+
+ /* If the function may call sqlite3_value_subtype(), then set the
+ ** EP_SubtArg flag on all of its argument expressions. This prevents
+ ** where.c from replacing the expression with a value read from an
+ ** index on the same expression, which will not have the correct
+ ** subtype. Also set the flag if the function expression itself is
+ ** an EP_SubtArg expression. In this case subtypes are required as
+ ** the function may return a value with a subtype back to its
+ ** caller using sqlite3_result_value(). */
+ if( (pDef->funcFlags & SQLITE_SUBTYPE)
+ || ExprHasProperty(pExpr, EP_SubtArg)
+ ){
+ int ii;
+ for(ii=0; iia[ii].pExpr, EP_SubtArg);
+ }
+ }
+
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
/* For the purposes of the EP_ConstFunc flag, date and time
** functions and other functions that change slowly are considered
@@ -108079,13 +110465,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** sqlite_version() that might change over time cannot be used
** in an index or generated column. Curiously, they can be used
** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
- ** all this. */
+ ** allow this. */
sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
}else{
assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
pExpr->op2 = pNC->ncFlags & NC_SelfRef;
- if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
}
if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
&& pParse->nested==0
@@ -108101,6 +110486,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
&& !IN_RENAME_OBJECT
){
+ if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
}
}
@@ -108185,9 +110571,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3WalkExprList(pWalker, pExpr->pLeft->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( pWin ){
+ if( pWin && pParse->nErr==0 ){
Select *pSel = pNC->pWinSelect;
- assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) );
+ assert( ExprUseYWin(pExpr) && pWin==pExpr->y.pWin );
if( IN_RENAME_OBJECT==0 ){
sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
if( pParse->db->mallocFailed ) break;
@@ -108235,11 +110621,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
return WRC_Prune;
}
#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_EXISTS:
case TK_SELECT:
- case TK_EXISTS: testcase( pExpr->op==TK_EXISTS );
#endif
case TK_IN: {
testcase( pExpr->op==TK_IN );
+ testcase( pExpr->op==TK_EXISTS );
+ testcase( pExpr->op==TK_SELECT );
if( ExprUseXSelect(pExpr) ){
int nRef = pNC->nRef;
testcase( pNC->ncFlags & NC_IsCheck );
@@ -108247,6 +110635,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
assert( pExpr->x.pSelect );
+ if( pExpr->op==TK_EXISTS ) pParse->bHasExists = 1;
if( pNC->ncFlags & NC_SelfRef ){
notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
}else{
@@ -108394,7 +110783,7 @@ static int resolveOrderByTermToExprList(
int rc; /* Return code from subprocedures */
u8 savedSuppErr; /* Saved value of db->suppressErr */
- assert( sqlite3ExprIsInteger(pE, &i)==0 );
+ assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
pEList = pSelect->pEList;
/* Resolve all names in the ORDER BY term expression
@@ -108493,7 +110882,7 @@ static int resolveCompoundOrderBy(
if( pItem->fg.done ) continue;
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
if( NEVER(pE==0) ) continue;
- if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
return 1;
@@ -108678,7 +111067,7 @@ static int resolveOrderGroupBy(
continue;
}
}
- if( sqlite3ExprIsInteger(pE2, &iCol) ){
+ if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
/* The ORDER BY term is an integer constant. Again, set the column
** number so that sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
@@ -108769,7 +111158,11 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** moves the pOrderBy down to the sub-query. It will be moved back
** after the names have been resolved. */
if( p->selFlags & SF_Converted ){
- Select *pSub = p->pSrc->a[0].pSelect;
+ Select *pSub;
+ assert( p->pSrc->a[0].fg.isSubquery );
+ assert( p->pSrc->a[0].u4.pSubq!=0 );
+ pSub = p->pSrc->a[0].u4.pSubq->pSelect;
+ assert( pSub!=0 );
assert( p->pSrc->nSrc==1 && p->pOrderBy );
assert( pSub->pPrior && pSub->pOrderBy==0 );
pSub->pOrderBy = p->pOrderBy;
@@ -108781,13 +111174,16 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
if( pOuterNC ) pOuterNC->nNestedSelect++;
for(i=0; ipSrc->nSrc; i++){
SrcItem *pItem = &p->pSrc->a[i];
- assert( pItem->zName!=0 || pItem->pSelect!=0 );/* Test of tag-20240424-1*/
- if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
+ assert( pItem->zName!=0
+ || pItem->fg.isSubquery ); /* Test of tag-20240424-1*/
+ if( pItem->fg.isSubquery
+ && (pItem->u4.pSubq->pSelect->selFlags & SF_Resolved)==0
+ ){
int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
- sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
+ sqlite3ResolveSelectNames(pParse, pItem->u4.pSubq->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
if( pParse->nErr ) return WRC_Abort;
assert( db->mallocFailed==0 );
@@ -108889,7 +111285,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** These integers will be replaced by copies of the corresponding result
** set expressions by the call to resolveOrderGroupBy() below. */
if( p->selFlags & SF_Converted ){
- Select *pSub = p->pSrc->a[0].pSelect;
+ Select *pSub;
+ assert( p->pSrc->a[0].fg.isSubquery );
+ pSub = p->pSrc->a[0].u4.pSubq->pSelect;
+ assert( pSub!=0 );
p->pOrderBy = pSub->pOrderBy;
pSub->pOrderBy = 0;
}
@@ -109043,6 +111442,9 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames(
** Resolve all names for all expression in an expression list. This is
** just like sqlite3ResolveExprNames() except that it works for an expression
** list rather than a single expression.
+**
+** The return value is SQLITE_OK (0) for success or SQLITE_ERROR (1) for a
+** failure.
*/
SQLITE_PRIVATE int sqlite3ResolveExprListNames(
NameContext *pNC, /* Namespace to resolve expressions in. */
@@ -109051,7 +111453,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
int i;
int savedHasAgg = 0;
Walker w;
- if( pList==0 ) return WRC_Continue;
+ if( pList==0 ) return SQLITE_OK;
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
w.xSelectCallback = resolveSelectStep;
@@ -109065,7 +111467,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
#if SQLITE_MAX_EXPR_DEPTH>0
w.pParse->nHeight += pExpr->nHeight;
if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
- return WRC_Abort;
+ return SQLITE_ERROR;
}
#endif
sqlite3WalkExprNN(&w, pExpr);
@@ -109082,10 +111484,10 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
}
- if( w.pParse->nErr>0 ) return WRC_Abort;
+ if( w.pParse->nErr>0 ) return SQLITE_ERROR;
}
pNC->ncFlags |= savedHasAgg;
- return WRC_Continue;
+ return SQLITE_OK;
}
/*
@@ -109141,20 +111543,25 @@ SQLITE_PRIVATE int sqlite3ResolveSelfReference(
Expr *pExpr, /* Expression to resolve. May be NULL. */
ExprList *pList /* Expression list to resolve. May be NULL. */
){
- SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
+ SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */
NameContext sNC; /* Name context for pParse->pNewTable */
int rc;
+ union {
+ SrcList sSrc;
+ u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */
+ } uSrc;
assert( type==0 || pTab!=0 );
assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
|| type==NC_GenCol || pTab==0 );
memset(&sNC, 0, sizeof(sNC));
- memset(&sSrc, 0, sizeof(sSrc));
+ memset(&uSrc, 0, sizeof(uSrc));
+ pSrc = &uSrc.sSrc;
if( pTab ){
- sSrc.nSrc = 1;
- sSrc.a[0].zName = pTab->zName;
- sSrc.a[0].pTab = pTab;
- sSrc.a[0].iCursor = -1;
+ pSrc->nSrc = 1;
+ pSrc->a[0].zName = pTab->zName;
+ pSrc->a[0].pSTab = pTab;
+ pSrc->a[0].iCursor = -1;
if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
/* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
** schema elements */
@@ -109162,7 +111569,7 @@ SQLITE_PRIVATE int sqlite3ResolveSelfReference(
}
}
sNC.pParse = pParse;
- sNC.pSrcList = &sSrc;
+ sNC.pSrcList = pSrc;
sNC.ncFlags = type | NC_IsDDL;
if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
@@ -109246,7 +111653,9 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
- if( op==TK_VECTOR ){
+ if( op==TK_VECTOR
+ || (op==TK_FUNCTION && pExpr->affExpr==SQLITE_AFF_DEFER)
+ ){
assert( ExprUseXList(pExpr) );
return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
}
@@ -109258,7 +111667,9 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
op = pExpr->op;
continue;
}
- if( op!=TK_REGISTER || (op = pExpr->op2)==TK_REGISTER ) break;
+ if( op!=TK_REGISTER ) break;
+ op = pExpr->op2;
+ if( NEVER( op==TK_REGISTER ) ) break;
}
return pExpr->affExpr;
}
@@ -109437,7 +111848,9 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
p = p->pLeft;
continue;
}
- if( op==TK_VECTOR ){
+ if( op==TK_VECTOR
+ || (op==TK_FUNCTION && p->affExpr==SQLITE_AFF_DEFER)
+ ){
assert( ExprUseXList(p) );
p = p->x.pList->a[0].pExpr;
continue;
@@ -109650,7 +112063,7 @@ static int codeCompare(
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
- sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
+ sqlite3VdbeChangeP5(pParse->pVdbe, (u16)p5);
return addr;
}
@@ -110311,7 +112724,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){
return pLeft;
}else{
u32 f = pLeft->flags | pRight->flags;
- if( (f&(EP_OuterON|EP_InnerON|EP_IsFalse))==EP_IsFalse
+ if( (f&(EP_OuterON|EP_InnerON|EP_IsFalse|EP_HasFunc))==EP_IsFalse
&& !IN_RENAME_OBJECT
){
sqlite3ExprDeferredDelete(pParse, pLeft);
@@ -110406,6 +112819,11 @@ SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy(
sqlite3ExprListDelete(db, pOrderBy);
return;
}
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
+ sqlite3ExprListDelete(db, pOrderBy);
+ return;
+ }
pOB = sqlite3ExprAlloc(db, TK_ORDER, 0, 0);
if( pOB==0 ){
@@ -110909,7 +113327,7 @@ static Expr *exprDup(
SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p){
With *pRet = 0;
if( p ){
- sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
+ sqlite3_int64 nByte = SZ_WITH(p->nCte);
pRet = sqlite3DbMallocZero(db, nByte);
if( pRet ){
int i;
@@ -111020,7 +113438,6 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int
}
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
pItem->fg = pOldItem->fg;
- pItem->fg.done = 0;
pItem->u = pOldItem->u;
}
return pNew;
@@ -111037,26 +113454,39 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
SrcList *pNew;
int i;
- int nByte;
assert( db!=0 );
if( p==0 ) return 0;
- nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
- pNew = sqlite3DbMallocRawNN(db, nByte );
+ pNew = sqlite3DbMallocRawNN(db, SZ_SRCLIST(p->nSrc) );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; inSrc; i++){
SrcItem *pNewItem = &pNew->a[i];
const SrcItem *pOldItem = &p->a[i];
Table *pTab;
- pNewItem->pSchema = pOldItem->pSchema;
- pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
+ pNewItem->fg = pOldItem->fg;
+ if( pOldItem->fg.isSubquery ){
+ Subquery *pNewSubq = sqlite3DbMallocRaw(db, sizeof(Subquery));
+ if( pNewSubq==0 ){
+ assert( db->mallocFailed );
+ pNewItem->fg.isSubquery = 0;
+ }else{
+ memcpy(pNewSubq, pOldItem->u4.pSubq, sizeof(*pNewSubq));
+ pNewSubq->pSelect = sqlite3SelectDup(db, pNewSubq->pSelect, flags);
+ if( pNewSubq->pSelect==0 ){
+ sqlite3DbFree(db, pNewSubq);
+ pNewSubq = 0;
+ pNewItem->fg.isSubquery = 0;
+ }
+ }
+ pNewItem->u4.pSubq = pNewSubq;
+ }else if( pOldItem->fg.fixedSchema ){
+ pNewItem->u4.pSchema = pOldItem->u4.pSchema;
+ }else{
+ pNewItem->u4.zDatabase = sqlite3DbStrDup(db, pOldItem->u4.zDatabase);
+ }
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
- pNewItem->fg = pOldItem->fg;
pNewItem->iCursor = pOldItem->iCursor;
- pNewItem->addrFillSub = pOldItem->addrFillSub;
- pNewItem->regReturn = pOldItem->regReturn;
- pNewItem->regResult = pOldItem->regResult;
if( pNewItem->fg.isIndexedBy ){
pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
}else if( pNewItem->fg.isTabFunc ){
@@ -111069,11 +113499,10 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int fla
if( pNewItem->fg.isCte ){
pNewItem->u2.pCteUse->nUse++;
}
- pTab = pNewItem->pTab = pOldItem->pTab;
+ pTab = pNewItem->pSTab = pOldItem->pSTab;
if( pTab ){
pTab->nTabRef++;
}
- pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
if( pOldItem->fg.isUsing ){
assert( pNewItem->fg.isUsing );
pNewItem->u3.pUsing = sqlite3IdListDup(db, pOldItem->u3.pUsing);
@@ -111089,16 +113518,13 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
int i;
assert( db!=0 );
if( p==0 ) return 0;
- assert( p->eU4!=EU4_EXPR );
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
+ pNew = sqlite3DbMallocRawNN(db, SZ_IDLIST(p->nId));
if( pNew==0 ) return 0;
pNew->nId = p->nId;
- pNew->eU4 = p->eU4;
for(i=0; inId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
const struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
- pNewItem->u4 = pOldItem->u4;
}
return pNew;
}
@@ -111124,7 +113550,7 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int fla
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
pNew->iLimit = 0;
pNew->iOffset = 0;
- pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
+ pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
@@ -111147,7 +113573,6 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int fla
pp = &pNew->pPrior;
pNext = pNew;
}
-
return pRet;
}
#else
@@ -111177,7 +113602,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew(
struct ExprList_item *pItem;
ExprList *pList;
- pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
+ pList = sqlite3DbMallocRawNN(db, SZ_EXPRLIST(4));
if( pList==0 ){
sqlite3ExprDelete(db, pExpr);
return 0;
@@ -111197,8 +113622,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow(
struct ExprList_item *pItem;
ExprList *pNew;
pList->nAlloc *= 2;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
+ pNew = sqlite3DbRealloc(db, pList, SZ_EXPRLIST(pList->nAlloc));
if( pNew==0 ){
sqlite3ExprListDelete(db, pList);
sqlite3ExprDelete(db, pExpr);
@@ -111534,6 +113958,85 @@ SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
return pExpr;
}
+/*
+** Return true if it might be advantageous to compute the right operand
+** of expression pExpr first, before the left operand.
+**
+** Normally the left operand is computed before the right operand. But if
+** the left operand contains a subquery and the right does not, then it
+** might be more efficient to compute the right operand first.
+*/
+static int exprEvalRhsFirst(Expr *pExpr){
+ if( ExprHasProperty(pExpr->pLeft, EP_Subquery)
+ && !ExprHasProperty(pExpr->pRight, EP_Subquery)
+ ){
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
+/*
+** Compute the two operands of a binary operator.
+**
+** If either operand contains a subquery, then the code strives to
+** compute the operand containing the subquery second. If the other
+** operand evalutes to NULL, then a jump is made. The address of the
+** IsNull operand that does this jump is returned. The caller can use
+** this to optimize the computation so as to avoid doing the potentially
+** expensive subquery.
+**
+** If no optimization opportunities exist, return 0.
+*/
+static int exprComputeOperands(
+ Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* The comparison expression */
+ int *pR1, /* OUT: Register holding the left operand */
+ int *pR2, /* OUT: Register holding the right operand */
+ int *pFree1, /* OUT: Temp register to free if not zero */
+ int *pFree2 /* OUT: Another temp register to free if not zero */
+){
+ int addrIsNull;
+ int r1, r2;
+ Vdbe *v = pParse->pVdbe;
+
+ assert( v!=0 );
+ /*
+ ** If the left operand contains a (possibly expensive) subquery and the
+ ** right operand does not and the right operation might be NULL,
+ ** then compute the right operand first and do an IsNull jump if the
+ ** right operand evalutes to NULL.
+ */
+ if( exprEvalRhsFirst(pExpr) && sqlite3ExprCanBeNull(pExpr->pRight) ){
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pFree2);
+ addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r2);
+ VdbeComment((v, "skip left operand"));
+ VdbeCoverage(v);
+ }else{
+ r2 = 0; /* Silence a false-positive uninit-var warning in MSVC */
+ addrIsNull = 0;
+ }
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pFree1);
+ if( addrIsNull==0 ){
+ /*
+ ** If the right operand contains a subquery and the left operand does not
+ ** and the left operand might be NULL, then do an IsNull check
+ ** check on the left operand before computing the right operand.
+ */
+ if( ExprHasProperty(pExpr->pRight, EP_Subquery)
+ && sqlite3ExprCanBeNull(pExpr->pLeft)
+ ){
+ addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, r1);
+ VdbeComment((v, "skip right operand"));
+ VdbeCoverage(v);
+ }
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pFree2);
+ }
+ *pR1 = r1;
+ *pR2 = r2;
+ return addrIsNull;
+}
+
/*
** pExpr is a TK_FUNCTION node. Try to determine whether or not the
** function is a constant function. A function is constant if all of
@@ -111804,7 +114307,7 @@ static int sqlite3ExprIsTableConstant(Expr *p, int iCur, int bAllowSubq){
** (4a) pExpr must come from an ON clause..
** (4b) and specifically the ON clause associated with the LEFT JOIN.
**
-** (5) If pSrc is not the right operand of a LEFT JOIN or the left
+** (5) If pSrc is the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
**
@@ -111962,8 +114465,12 @@ SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr *p){
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue. If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
+**
+** If the pParse pointer is provided, then allow the expression p to be
+** a parameter (TK_VARIABLE) that is bound to an integer.
+** But if pParse is NULL, then p must be a pure integer literal.
*/
-SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
+SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
int rc = 0;
if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
@@ -111978,18 +114485,38 @@ SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr *p, int *pValue){
}
switch( p->op ){
case TK_UPLUS: {
- rc = sqlite3ExprIsInteger(p->pLeft, pValue);
+ rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
break;
}
case TK_UMINUS: {
int v = 0;
- if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+ if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
assert( ((unsigned int)v)!=0x80000000 );
*pValue = -v;
rc = 1;
}
break;
}
+ case TK_VARIABLE: {
+ sqlite3_value *pVal;
+ if( pParse==0 ) break;
+ if( NEVER(pParse->pVdbe==0) ) break;
+ if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
+ sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
+ pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
+ SQLITE_AFF_BLOB);
+ if( pVal ){
+ if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
+ sqlite3_int64 vv = sqlite3_value_int64(pVal);
+ if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
+ *pValue = (int)vv;
+ rc = 1;
+ }
+ }
+ sqlite3ValueFree(pVal);
+ }
+ break;
+ }
default: break;
}
return rc;
@@ -112103,13 +114630,7 @@ SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab){
int ii;
assert( VisibleRowid(pTab) );
for(ii=0; iinCol; iCol++){
- if( sqlite3_stricmp(azOpt[ii], pTab->aCol[iCol].zCnName)==0 ) break;
- }
- if( iCol==pTab->nCol ){
- return azOpt[ii];
- }
+ if( sqlite3ColumnIndex(pTab, azOpt[ii])<0 ) return azOpt[ii];
}
return 0;
}
@@ -112143,8 +114664,8 @@ static Select *isCandidateForInOpt(const Expr *pX){
pSrc = p->pSrc;
assert( pSrc!=0 );
if( pSrc->nSrc!=1 ) return 0; /* Single term in FROM clause */
- if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
- pTab = pSrc->a[0].pTab;
+ if( pSrc->a[0].fg.isSubquery) return 0;/* FROM is not a subquery or view */
+ pTab = pSrc->a[0].pSTab;
assert( pTab!=0 );
assert( !IsView(pTab) ); /* FROM clause is not a view */
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
@@ -112327,7 +114848,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */
- pTab = p->pSrc->a[0].pTab;
+ pTab = p->pSrc->a[0].pSTab;
/* Code an OP_Transaction and OP_TableLock for . */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -112419,6 +114940,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(
if( aiMap ) aiMap[i] = j;
}
+ assert( nExpr>0 && nExprop==TK_IN );
- zRet = sqlite3DbMallocRaw(pParse->db, nVal+1);
+ zRet = sqlite3DbMallocRaw(pParse->db, 1+(i64)nVal);
if( zRet ){
int i;
for(i=0; imSubrtnSig & (1<<(pNewSig->selId&7)))==0 ) return 0;
+ assert( pExpr->op==TK_IN );
+ assert( !ExprUseYSub(pExpr) );
+ assert( ExprUseXSelect(pExpr) );
+ assert( pExpr->x.pSelect!=0 );
+ assert( (pExpr->x.pSelect->selFlags & SF_All)==0 );
+ v = pParse->pVdbe;
+ assert( v!=0 );
+ pOp = sqlite3VdbeGetOp(v, 1);
+ pEnd = sqlite3VdbeGetLastOp(v);
+ for(; pOpp4type!=P4_SUBRTNSIG ) continue;
+ assert( pOp->opcode==OP_BeginSubrtn );
+ pSig = pOp->p4.pSubrtnSig;
+ assert( pSig!=0 );
+ if( !pSig->bComplete ) continue;
+ if( pNewSig->selId!=pSig->selId ) continue;
+ if( strcmp(pNewSig->zAff,pSig->zAff)!=0 ) continue;
+ pExpr->y.sub.iAddr = pSig->iAddr;
+ pExpr->y.sub.regReturn = pSig->regReturn;
+ pExpr->iTable = pSig->iTable;
+ ExprSetProperty(pExpr, EP_Subrtn);
+ return 1;
+ }
+ return 0;
+}
+#endif /* SQLITE_OMIT_SUBQUERY */
+
#ifndef SQLITE_OMIT_SUBQUERY
/*
** Generate code that will construct an ephemeral table containing all terms
@@ -112601,6 +115167,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
KeyInfo *pKeyInfo = 0; /* Key information */
int nVal; /* Size of vector pLeft */
Vdbe *v; /* The prepared statement under construction */
+ SubrtnSig *pSig = 0; /* Signature for this subroutine */
v = pParse->pVdbe;
assert( v!=0 );
@@ -112616,11 +115183,27 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
** and reuse it many names.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) && pParse->iSelfTab==0 ){
- /* Reuse of the RHS is allowed */
- /* If this routine has already been coded, but the previous code
- ** might not have been invoked yet, so invoke it now as a subroutine.
+ /* Reuse of the RHS is allowed
+ **
+ ** Compute a signature for the RHS of the IN operator to facility
+ ** finding and reusing prior instances of the same IN operator.
*/
- if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ assert( !ExprUseXSelect(pExpr) || pExpr->x.pSelect!=0 );
+ if( ExprUseXSelect(pExpr) && (pExpr->x.pSelect->selFlags & SF_All)==0 ){
+ pSig = sqlite3DbMallocRawNN(pParse->db, sizeof(pSig[0]));
+ if( pSig ){
+ pSig->selId = pExpr->x.pSelect->selId;
+ pSig->zAff = exprINAffinity(pParse, pExpr);
+ }
+ }
+
+ /* Check to see if there is a prior materialization of the RHS of
+ ** this IN operator. If there is, then make use of that prior
+ ** materialization rather than recomputing it.
+ */
+ if( ExprHasProperty(pExpr, EP_Subrtn)
+ || findCompatibleInRhsSubrtn(pParse, pExpr, pSig)
+ ){
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
@@ -112632,6 +115215,10 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
assert( iTab!=pExpr->iTable );
sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlite3VdbeJumpHere(v, addrOnce);
+ if( pSig ){
+ sqlite3DbFree(pParse->db, pSig->zAff);
+ sqlite3DbFree(pParse->db, pSig);
+ }
return;
}
@@ -112642,7 +115229,14 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
-
+ if( pSig ){
+ pSig->bComplete = 0;
+ pSig->iAddr = pExpr->y.sub.iAddr;
+ pSig->regReturn = pExpr->y.sub.regReturn;
+ pSig->iTable = iTab;
+ pParse->mSubrtnSig = 1 << (pSig->selId&7);
+ sqlite3VdbeChangeP4(v, -1, (const char*)pSig, P4_SUBRTNSIG);
+ }
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
@@ -112683,15 +115277,31 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
SelectDest dest;
int i;
int rc;
+ int addrBloom = 0;
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
+ if( addrOnce && OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
+ int regBloom = ++pParse->nMem;
+ addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
+ VdbeComment((v, "Bloom filter"));
+ dest.iSDParm2 = regBloom;
+ }
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
sqlite3SelectDelete(pParse->db, pCopy);
sqlite3DbFree(pParse->db, dest.zAffSdst);
+ if( addrBloom ){
+ /* Remember that location of the Bloom filter in the P3 operand
+ ** of the OP_Once that began this subroutine. tag-202407032019 */
+ sqlite3VdbeGetOp(v, addrOnce)->p3 = dest.iSDParm2;
+ if( dest.iSDParm2==0 ){
+ /* If the Bloom filter won't actually be used, keep it small */
+ sqlite3VdbeGetOp(v, addrBloom)->p1 = 10;
+ }
+ }
if( rc ){
sqlite3KeyInfoUnref(pKeyInfo);
return;
@@ -112757,6 +115367,7 @@ SQLITE_PRIVATE void sqlite3CodeRhsOfIN(
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
+ if( pSig ) pSig->bComplete = 1;
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
}
@@ -112860,9 +115471,22 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
pParse->nMem += nReg;
if( pExpr->op==TK_SELECT ){
dest.eDest = SRT_Mem;
- dest.iSdst = dest.iSDParm;
+ if( (pSel->selFlags&SF_Distinct) && pSel->pLimit && pSel->pLimit->pRight ){
+ /* If there is both a DISTINCT and an OFFSET clause, then allocate
+ ** a separate dest.iSdst array for sqlite3Select() and other
+ ** routines to populate. In this case results will be copied over
+ ** into the dest.iSDParm array only after OFFSET processing. This
+ ** ensures that in the case where OFFSET excludes all rows, the
+ ** dest.iSDParm array is not left populated with the contents of the
+ ** last row visited - it should be all NULLs if all rows were
+ ** excluded by OFFSET. */
+ dest.iSdst = pParse->nMem+1;
+ pParse->nMem += nReg;
+ }else{
+ dest.iSdst = dest.iSDParm;
+ }
dest.nSdst = nReg;
- sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
+ sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, pParse->nMem);
VdbeComment((v, "Init subquery result"));
}else{
dest.eDest = SRT_Exists;
@@ -112870,17 +115494,23 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
VdbeComment((v, "Init EXISTS result"));
}
if( pSel->pLimit ){
- /* The subquery already has a limit. If the pre-existing limit is X
- ** then make the new limit X<>0 so that the new limit is either 1 or 0 */
- sqlite3 *db = pParse->db;
- pLimit = sqlite3Expr(db, TK_INTEGER, "0");
- if( pLimit ){
- pLimit->affExpr = SQLITE_AFF_NUMERIC;
- pLimit = sqlite3PExpr(pParse, TK_NE,
- sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit);
+ /* The subquery already has a limit. If the pre-existing limit X is
+ ** not already integer value 1 or 0, then make the new limit X<>0 so that
+ ** the new limit is either 1 or 0 */
+ Expr *pLeft = pSel->pLimit->pLeft;
+ if( ExprHasProperty(pLeft, EP_IntValue)==0
+ || (pLeft->u.iValue!=1 && pLeft->u.iValue!=0)
+ ){
+ sqlite3 *db = pParse->db;
+ pLimit = sqlite3Expr(db, TK_INTEGER, "0");
+ if( pLimit ){
+ pLimit->affExpr = SQLITE_AFF_NUMERIC;
+ pLimit = sqlite3PExpr(pParse, TK_NE,
+ sqlite3ExprDup(db, pLeft, 0), pLimit);
+ }
+ sqlite3ExprDeferredDelete(pParse, pLeft);
+ pSel->pLimit->pLeft = pLimit;
}
- sqlite3ExprDeferredDelete(pParse, pSel->pLimit->pLeft);
- pSel->pLimit->pLeft = pLimit;
}else{
/* If there is no pre-existing limit add a limit of 1 */
pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1");
@@ -112968,7 +115598,6 @@ static void sqlite3ExprCodeIN(
int rRhsHasNull = 0; /* Register that is true if RHS contains NULL values */
int eType; /* Type of the RHS */
int rLhs; /* Register(s) holding the LHS values */
- int rLhsOrig; /* LHS values prior to reordering by aiMap[] */
Vdbe *v; /* Statement under construction */
int *aiMap = 0; /* Map from vector field to index column */
char *zAff = 0; /* Affinity string for comparisons */
@@ -112989,9 +115618,7 @@ static void sqlite3ExprCodeIN(
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
zAff = exprINAffinity(pParse, pExpr);
nVector = sqlite3ExprVectorSize(pExpr->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(
- pParse->db, nVector*(sizeof(int) + sizeof(char)) + 1
- );
+ aiMap = (int*)sqlite3DbMallocZero(pParse->db, nVector*sizeof(int));
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
/* Attempt to compute the RHS. After this step, if anything other than
@@ -113033,19 +115660,8 @@ static void sqlite3ExprCodeIN(
** by code generated below. */
assert( pParse->okConstFactor==okConstFactor );
pParse->okConstFactor = 0;
- rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
+ rLhs = exprCodeVector(pParse, pLeft, &iDummy);
pParse->okConstFactor = okConstFactor;
- for(i=0; ix.pList;
pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
@@ -113101,6 +115718,26 @@ static void sqlite3ExprCodeIN(
goto sqlite3ExprCodeIN_finished;
}
+ if( eType!=IN_INDEX_ROWID ){
+ /* If this IN operator will use an index, then the order of columns in the
+ ** vector might be different from the order in the index. In that case,
+ ** we need to reorder the LHS values to be in index order. Run Affinity
+ ** before reordering the columns, so that the affinity is correct.
+ */
+ sqlite3VdbeAddOp4(v, OP_Affinity, rLhs, nVector, 0, zAff, nVector);
+ for(i=0; iy.sub.iAddr);
+ assert( pOp->opcode==OP_Once || pParse->nErr );
+ if( pOp->opcode==OP_Once && pOp->p3>0 ){ /* tag-202407032019 */
+ assert( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) );
+ sqlite3VdbeAddOp4Int(v, OP_Filter, pOp->p3, destIfFalse,
+ rLhs, nVector); VdbeCoverage(v);
+ }
+ }
sqlite3VdbeAddOp4Int(v, OP_NotFound, iTab, destIfFalse,
rLhs, nVector); VdbeCoverage(v);
goto sqlite3ExprCodeIN_finished;
@@ -113200,7 +115846,6 @@ static void sqlite3ExprCodeIN(
sqlite3VdbeJumpHere(v, addrTruthOp);
sqlite3ExprCodeIN_finished:
- if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs);
VdbeComment((v, "end IN expr"));
sqlite3ExprCodeIN_oom_error:
sqlite3DbFree(pParse->db, aiMap);
@@ -113315,7 +115960,12 @@ SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(
iAddr = 0;
}
sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut);
- if( pCol->affinity>=SQLITE_AFF_TEXT ){
+ if( (pCol->colFlags & COLFLAG_VIRTUAL)!=0
+ && (pTab->tabFlags & TF_Strict)!=0
+ ){
+ int p3 = 2+(int)(pCol - pTab->aCol);
+ sqlite3VdbeAddOp4(v, OP_TypeCheck, regOut, 1, p3, (char*)pTab, P4_TABLE);
+ }else if( pCol->affinity>=SQLITE_AFF_TEXT ){
sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
}
if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
@@ -113416,13 +116066,17 @@ SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int n
** register iReg. The caller must ensure that iReg already contains
** the correct value for the expression.
*/
-static void exprToRegister(Expr *pExpr, int iReg){
+SQLITE_PRIVATE void sqlite3ExprToRegister(Expr *pExpr, int iReg){
Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
if( NEVER(p==0) ) return;
- p->op2 = p->op;
- p->op = TK_REGISTER;
- p->iTable = iReg;
- ExprClearProperty(p, EP_Skip);
+ if( p->op==TK_REGISTER ){
+ assert( p->iTable==iReg );
+ }else{
+ p->op2 = p->op;
+ p->op = TK_REGISTER;
+ p->iTable = iReg;
+ ExprClearProperty(p, EP_Skip);
+ }
}
/*
@@ -113592,6 +116246,59 @@ static int exprCodeInlineFunction(
return target;
}
+/*
+** Expression Node callback for sqlite3ExprCanReturnSubtype().
+**
+** Only a function call is able to return a subtype. So if the node
+** is not a function call, return WRC_Prune immediately.
+**
+** A function call is able to return a subtype if it has the
+** SQLITE_RESULT_SUBTYPE property.
+**
+** Assume that every function is able to pass-through a subtype from
+** one of its argument (using sqlite3_result_value()). Most functions
+** are not this way, but we don't have a mechanism to distinguish those
+** that are from those that are not, so assume they all work this way.
+** That means that if one of its arguments is another function and that
+** other function is able to return a subtype, then this function is
+** able to return a subtype.
+*/
+static int exprNodeCanReturnSubtype(Walker *pWalker, Expr *pExpr){
+ int n;
+ FuncDef *pDef;
+ sqlite3 *db;
+ if( pExpr->op!=TK_FUNCTION ){
+ return WRC_Prune;
+ }
+ assert( ExprUseXList(pExpr) );
+ db = pWalker->pParse->db;
+ n = ALWAYS(pExpr->x.pList) ? pExpr->x.pList->nExpr : 0;
+ pDef = sqlite3FindFunction(db, pExpr->u.zToken, n, ENC(db), 0);
+ if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_RESULT_SUBTYPE)!=0 ){
+ pWalker->eCode = 1;
+ return WRC_Prune;
+ }
+ return WRC_Continue;
+}
+
+/*
+** Return TRUE if expression pExpr is able to return a subtype.
+**
+** A TRUE return does not guarantee that a subtype will be returned.
+** It only indicates that a subtype return is possible. False positives
+** are acceptable as they only disable an optimization. False negatives,
+** on the other hand, can lead to incorrect answers.
+*/
+static int sqlite3ExprCanReturnSubtype(Parse *pParse, Expr *pExpr){
+ Walker w;
+ memset(&w, 0, sizeof(w));
+ w.pParse = pParse;
+ w.xExprCallback = exprNodeCanReturnSubtype;
+ sqlite3WalkExpr(&w, pExpr);
+ return w.eCode;
+}
+
+
/*
** Check to see if pExpr is one of the indexed expressions on pParse->pIdxEpr.
** If it is, then resolve the expression by reading from the index and
@@ -113624,6 +116331,17 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
continue;
}
+
+ /* Functions that might set a subtype should not be replaced by the
+ ** value taken from an expression index if they are themselves an
+ ** argument to another scalar function or aggregate.
+ ** https://sqlite.org/forum/forumpost/68d284c86b082c3e */
+ if( ExprHasProperty(pExpr, EP_SubtArg)
+ && sqlite3ExprCanReturnSubtype(pParse, pExpr)
+ ){
+ continue;
+ }
+
v = pParse->pVdbe;
assert( v!=0 );
if( p->bMaybeNullRow ){
@@ -113652,7 +116370,7 @@ static SQLITE_NOINLINE int sqlite3IndexedExprLookup(
/*
-** Expresion pExpr is guaranteed to be a TK_COLUMN or equivalent. This
+** Expression pExpr is guaranteed to be a TK_COLUMN or equivalent. This
** function checks the Parse.pIdxPartExpr list to see if this column
** can be replaced with a constant value. If so, it generates code to
** put the constant value in a register (ideally, but not necessarily,
@@ -113685,6 +116403,80 @@ static int exprPartidxExprLookup(Parse *pParse, Expr *pExpr, int iTarget){
return 0;
}
+/*
+** Generate code that evaluates an AND or OR operator leaving a
+** boolean result in a register. pExpr is the AND/OR expression.
+** Store the result in the "target" register. Use short-circuit
+** evaluation to avoid computing both operands, if possible.
+**
+** The code generated might require the use of a temporary register.
+** If it does, then write the number of that temporary register
+** into *pTmpReg. If not, leave *pTmpReg unchanged.
+*/
+static SQLITE_NOINLINE int exprCodeTargetAndOr(
+ Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* AND or OR expression to be coded */
+ int target, /* Put result in this register, guaranteed */
+ int *pTmpReg /* Write a temporary register here */
+){
+ int op; /* The opcode. TK_AND or TK_OR */
+ int skipOp; /* Opcode for the branch that skips one operand */
+ int addrSkip; /* Branch instruction that skips one of the operands */
+ int regSS = 0; /* Register holding computed operand when other omitted */
+ int r1, r2; /* Registers for left and right operands, respectively */
+ Expr *pAlt; /* Alternative, simplified expression */
+ Vdbe *v; /* statement being coded */
+
+ assert( pExpr!=0 );
+ op = pExpr->op;
+ assert( op==TK_AND || op==TK_OR );
+ assert( TK_AND==OP_And ); testcase( op==TK_AND );
+ assert( TK_OR==OP_Or ); testcase( op==TK_OR );
+ assert( pParse->pVdbe!=0 );
+ v = pParse->pVdbe;
+ pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
+ if( pAlt!=pExpr ){
+ r1 = sqlite3ExprCodeTarget(pParse, pAlt, target);
+ sqlite3VdbeAddOp3(v, OP_And, r1, r1, target);
+ return target;
+ }
+ skipOp = op==TK_AND ? OP_IfNot : OP_If;
+ if( exprEvalRhsFirst(pExpr) ){
+ /* Compute the right operand first. Skip the computation of the left
+ ** operand if the right operand fully determines the result */
+ r2 = regSS = sqlite3ExprCodeTarget(pParse, pExpr->pRight, target);
+ addrSkip = sqlite3VdbeAddOp1(v, skipOp, r2);
+ VdbeComment((v, "skip left operand"));
+ VdbeCoverage(v);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, pTmpReg);
+ }else{
+ /* Compute the left operand first */
+ r1 = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ if( ExprHasProperty(pExpr->pRight, EP_Subquery) ){
+ /* Skip over the computation of the right operand if the right
+ ** operand is a subquery and the left operand completely determines
+ ** the result */
+ regSS = r1;
+ addrSkip = sqlite3VdbeAddOp1(v, skipOp, r1);
+ VdbeComment((v, "skip right operand"));
+ VdbeCoverage(v);
+ }else{
+ addrSkip = regSS = 0;
+ }
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, pTmpReg);
+ }
+ sqlite3VdbeAddOp3(v, op, r2, r1, target);
+ testcase( (*pTmpReg)==0 );
+ if( addrSkip ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
+ sqlite3VdbeJumpHere(v, addrSkip);
+ sqlite3VdbeAddOp3(v, OP_Or, regSS, regSS, target);
+ VdbeComment((v, "short-circut value"));
+ }
+ return target;
+}
+
+
/*
** Generate code into the current Vdbe to evaluate the given
@@ -113876,6 +116668,12 @@ expr_code_doover:
sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
return target;
}
+ case TK_NULLS: {
+ /* Set a range of registers to NULL. pExpr->y.nReg registers starting
+ ** with target */
+ sqlite3VdbeAddOp3(v, OP_Null, 0, target, target + pExpr->y.nReg - 1);
+ return target;
+ }
default: {
/* Make NULL the default case so that if a bug causes an illegal
** Expr node to be passed into this function, it will be handled
@@ -113934,11 +116732,17 @@ expr_code_doover:
case TK_NE:
case TK_EQ: {
Expr *pLeft = pExpr->pLeft;
+ int addrIsNull = 0;
if( sqlite3ExprIsVector(pLeft) ){
codeVectorCompare(pParse, pExpr, target, op, p5);
}else{
- r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ if( ExprHasProperty(pExpr, EP_Subquery) && p5!=SQLITE_NULLEQ ){
+ addrIsNull = exprComputeOperands(pParse, pExpr,
+ &r1, &r2, ®Free1, ®Free2);
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ }
sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg);
codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2,
sqlite3VdbeCurrentAddr(v)+2, p5,
@@ -113953,6 +116757,11 @@ expr_code_doover:
sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg);
}else{
sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2);
+ if( addrIsNull ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
+ sqlite3VdbeJumpHere(v, addrIsNull);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, inReg);
+ }
}
testcase( regFree1==0 );
testcase( regFree2==0 );
@@ -113960,7 +116769,10 @@ expr_code_doover:
break;
}
case TK_AND:
- case TK_OR:
+ case TK_OR: {
+ inReg = exprCodeTargetAndOr(pParse, pExpr, target, ®Free1);
+ break;
+ }
case TK_PLUS:
case TK_STAR:
case TK_MINUS:
@@ -113971,8 +116783,7 @@ expr_code_doover:
case TK_LSHIFT:
case TK_RSHIFT:
case TK_CONCAT: {
- assert( TK_AND==OP_And ); testcase( op==TK_AND );
- assert( TK_OR==OP_Or ); testcase( op==TK_OR );
+ int addrIsNull;
assert( TK_PLUS==OP_Add ); testcase( op==TK_PLUS );
assert( TK_MINUS==OP_Subtract ); testcase( op==TK_MINUS );
assert( TK_REM==OP_Remainder ); testcase( op==TK_REM );
@@ -113982,11 +116793,23 @@ expr_code_doover:
assert( TK_LSHIFT==OP_ShiftLeft ); testcase( op==TK_LSHIFT );
assert( TK_RSHIFT==OP_ShiftRight ); testcase( op==TK_RSHIFT );
assert( TK_CONCAT==OP_Concat ); testcase( op==TK_CONCAT );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ if( ExprHasProperty(pExpr, EP_Subquery) ){
+ addrIsNull = exprComputeOperands(pParse, pExpr,
+ &r1, &r2, ®Free1, ®Free2);
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ addrIsNull = 0;
+ }
sqlite3VdbeAddOp3(v, op, r2, r1, target);
testcase( regFree1==0 );
testcase( regFree2==0 );
+ if( addrIsNull ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
+ sqlite3VdbeJumpHere(v, addrIsNull);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, target);
+ VdbeComment((v, "short-circut value"));
+ }
break;
}
case TK_UMINUS: {
@@ -114425,7 +117248,7 @@ expr_code_doover:
break;
}
testcase( pX->op==TK_COLUMN );
- exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
testcase( regFree1==0 );
memset(&opCompare, 0, sizeof(opCompare));
opCompare.op = TK_EQ;
@@ -114479,15 +117302,14 @@ expr_code_doover:
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( pExpr->affExpr==OE_Ignore ){
- sqlite3VdbeAddOp4(
- v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
+ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, OE_Ignore);
VdbeCoverage(v);
}else{
- sqlite3HaltConstraint(pParse,
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ sqlite3VdbeAddOp3(v, OP_Halt,
pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
- pExpr->affExpr, pExpr->u.zToken, 0, 0);
+ pExpr->affExpr, r1);
}
-
break;
}
#endif
@@ -114561,6 +117383,25 @@ SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(
return regDest;
}
+/*
+** Make arrangements to invoke OP_Null on a range of registers
+** during initialization.
+*/
+SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3ExprNullRegisterRange(
+ Parse *pParse, /* Parsing context */
+ int iReg, /* First register to set to NULL */
+ int nReg /* Number of sequential registers to NULL out */
+){
+ u8 okConstFactor = pParse->okConstFactor;
+ Expr t;
+ memset(&t, 0, sizeof(t));
+ t.op = TK_NULLS;
+ t.y.nReg = nReg;
+ pParse->okConstFactor = 1;
+ sqlite3ExprCodeRunJustOnce(pParse, &t, iReg);
+ pParse->okConstFactor = okConstFactor;
+}
+
/*
** Generate code to evaluate an expression and store the results
** into a register. Return the register number where the results
@@ -114776,7 +117617,7 @@ static void exprCodeBetween(
compRight.op = TK_LE;
compRight.pLeft = pDel;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
- exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
+ sqlite3ExprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
@@ -114836,17 +117677,27 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
if( pAlt!=pExpr ){
sqlite3ExprIfTrue(pParse, pAlt, dest, jumpIfNull);
- }else if( op==TK_AND ){
- int d2 = sqlite3VdbeMakeLabel(pParse);
- testcase( jumpIfNull==0 );
- sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,
- jumpIfNull^SQLITE_JUMPIFNULL);
- sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3VdbeResolveLabel(v, d2);
}else{
- testcase( jumpIfNull==0 );
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
+ Expr *pFirst, *pSecond;
+ if( exprEvalRhsFirst(pExpr) ){
+ pFirst = pExpr->pRight;
+ pSecond = pExpr->pLeft;
+ }else{
+ pFirst = pExpr->pLeft;
+ pSecond = pExpr->pRight;
+ }
+ if( op==TK_AND ){
+ int d2 = sqlite3VdbeMakeLabel(pParse);
+ testcase( jumpIfNull==0 );
+ sqlite3ExprIfFalse(pParse, pFirst, d2,
+ jumpIfNull^SQLITE_JUMPIFNULL);
+ sqlite3ExprIfTrue(pParse, pSecond, dest, jumpIfNull);
+ sqlite3VdbeResolveLabel(v, d2);
+ }else{
+ testcase( jumpIfNull==0 );
+ sqlite3ExprIfTrue(pParse, pFirst, dest, jumpIfNull);
+ sqlite3ExprIfTrue(pParse, pSecond, dest, jumpIfNull);
+ }
}
break;
}
@@ -114885,10 +117736,16 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
case TK_GE:
case TK_NE:
case TK_EQ: {
+ int addrIsNull;
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
- testcase( jumpIfNull==0 );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){
+ addrIsNull = exprComputeOperands(pParse, pExpr,
+ &r1, &r2, ®Free1, ®Free2);
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ addrIsNull = 0;
+ }
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
@@ -114903,6 +117760,13 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
VdbeCoverageIf(v, op==OP_Ne && jumpIfNull!=SQLITE_NULLEQ);
testcase( regFree1==0 );
testcase( regFree2==0 );
+ if( addrIsNull ){
+ if( jumpIfNull ){
+ sqlite3VdbeChangeP2(v, addrIsNull, dest);
+ }else{
+ sqlite3VdbeJumpHere(v, addrIsNull);
+ }
+ }
break;
}
case TK_ISNULL:
@@ -114910,11 +117774,11 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- sqlite3VdbeTypeofColumn(v, r1);
+ assert( regFree1==0 || regFree1==r1 );
+ if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1);
sqlite3VdbeAddOp2(v, op, r1, dest);
VdbeCoverageIf(v, op==TK_ISNULL);
VdbeCoverageIf(v, op==TK_NOTNULL);
- testcase( regFree1==0 );
break;
}
case TK_BETWEEN: {
@@ -115010,17 +117874,27 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
if( pAlt!=pExpr ){
sqlite3ExprIfFalse(pParse, pAlt, dest, jumpIfNull);
- }else if( pExpr->op==TK_AND ){
- testcase( jumpIfNull==0 );
- sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
- sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
}else{
- int d2 = sqlite3VdbeMakeLabel(pParse);
- testcase( jumpIfNull==0 );
- sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2,
- jumpIfNull^SQLITE_JUMPIFNULL);
- sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
- sqlite3VdbeResolveLabel(v, d2);
+ Expr *pFirst, *pSecond;
+ if( exprEvalRhsFirst(pExpr) ){
+ pFirst = pExpr->pRight;
+ pSecond = pExpr->pLeft;
+ }else{
+ pFirst = pExpr->pLeft;
+ pSecond = pExpr->pRight;
+ }
+ if( pExpr->op==TK_AND ){
+ testcase( jumpIfNull==0 );
+ sqlite3ExprIfFalse(pParse, pFirst, dest, jumpIfNull);
+ sqlite3ExprIfFalse(pParse, pSecond, dest, jumpIfNull);
+ }else{
+ int d2 = sqlite3VdbeMakeLabel(pParse);
+ testcase( jumpIfNull==0 );
+ sqlite3ExprIfTrue(pParse, pFirst, d2,
+ jumpIfNull^SQLITE_JUMPIFNULL);
+ sqlite3ExprIfFalse(pParse, pSecond, dest, jumpIfNull);
+ sqlite3VdbeResolveLabel(v, d2);
+ }
}
break;
}
@@ -115062,10 +117936,16 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
case TK_GE:
case TK_NE:
case TK_EQ: {
+ int addrIsNull;
if( sqlite3ExprIsVector(pExpr->pLeft) ) goto default_expr;
- testcase( jumpIfNull==0 );
- r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ if( ExprHasProperty(pExpr, EP_Subquery) && jumpIfNull!=SQLITE_NULLEQ ){
+ addrIsNull = exprComputeOperands(pParse, pExpr,
+ &r1, &r2, ®Free1, ®Free2);
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
+ addrIsNull = 0;
+ }
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull,ExprHasProperty(pExpr,EP_Commuted));
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
@@ -115080,16 +117960,23 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
VdbeCoverageIf(v, op==OP_Ne && jumpIfNull==SQLITE_NULLEQ);
testcase( regFree1==0 );
testcase( regFree2==0 );
+ if( addrIsNull ){
+ if( jumpIfNull ){
+ sqlite3VdbeChangeP2(v, addrIsNull, dest);
+ }else{
+ sqlite3VdbeJumpHere(v, addrIsNull);
+ }
+ }
break;
}
case TK_ISNULL:
case TK_NOTNULL: {
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
- sqlite3VdbeTypeofColumn(v, r1);
+ assert( regFree1==0 || regFree1==r1 );
+ if( regFree1 ) sqlite3VdbeTypeofColumn(v, r1);
sqlite3VdbeAddOp2(v, op, r1, dest);
testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);
- testcase( regFree1==0 );
break;
}
case TK_BETWEEN: {
@@ -115155,16 +118042,23 @@ SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,i
** same as that currently bound to variable pVar, non-zero is returned.
** Otherwise, if the values are not the same or if pExpr is not a simple
** SQL value, zero is returned.
+**
+** If the SQLITE_EnableQPSG flag is set on the database connection, then
+** this routine always returns false.
*/
-static int exprCompareVariable(
+static SQLITE_NOINLINE int exprCompareVariable(
const Parse *pParse,
const Expr *pVar,
const Expr *pExpr
){
- int res = 0;
+ int res = 2;
int iVar;
sqlite3_value *pL, *pR = 0;
+ if( pExpr->op==TK_VARIABLE && pVar->iColumn==pExpr->iColumn ){
+ return 0;
+ }
+ if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) return 2;
sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
if( pR ){
iVar = pVar->iColumn;
@@ -115174,12 +118068,11 @@ static int exprCompareVariable(
if( sqlite3_value_type(pL)==SQLITE_TEXT ){
sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
}
- res = 0==sqlite3MemCompare(pL, pR, 0);
+ res = sqlite3MemCompare(pL, pR, 0) ? 2 : 0;
}
sqlite3ValueFree(pR);
sqlite3ValueFree(pL);
}
-
return res;
}
@@ -115205,12 +118098,10 @@ static int exprCompareVariable(
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
**
-** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
-** pParse->pReprepare can be matched against literals in pB. The
-** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
-** If pParse is NULL (the normal case) then any TK_VARIABLE term in
-** Argument pParse should normally be NULL. If it is not NULL and pA or
-** pB causes a return value of 2.
+** If pParse is not NULL and SQLITE_EnableQPSG is off then TK_VARIABLE
+** terms in pA with bindings in pParse->pReprepare can be matched against
+** literals in pB. The pParse->pVdbe->expmask bitmask is updated for
+** each variable referenced.
*/
SQLITE_PRIVATE int sqlite3ExprCompare(
const Parse *pParse,
@@ -115222,8 +118113,8 @@ SQLITE_PRIVATE int sqlite3ExprCompare(
if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
}
- if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
- return 0;
+ if( pParse && pA->op==TK_VARIABLE ){
+ return exprCompareVariable(pParse, pA, pB);
}
combinedFlags = pA->flags | pB->flags;
if( combinedFlags & EP_IntValue ){
@@ -115418,18 +118309,70 @@ static int exprImpliesNotNull(
return 0;
}
+/*
+** Return true if the boolean value of the expression is always either
+** FALSE or NULL.
+*/
+static int sqlite3ExprIsNotTrue(Expr *pExpr){
+ int v;
+ if( pExpr->op==TK_NULL ) return 1;
+ if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1;
+ v = 1;
+ if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1;
+ return 0;
+}
+
+/*
+** Return true if the expression is one of the following:
+**
+** CASE WHEN x THEN y END
+** CASE WHEN x THEN y ELSE NULL END
+** CASE WHEN x THEN y ELSE false END
+** iif(x,y)
+** iif(x,y,NULL)
+** iif(x,y,false)
+*/
+static int sqlite3ExprIsIIF(sqlite3 *db, const Expr *pExpr){
+ ExprList *pList;
+ if( pExpr->op==TK_FUNCTION ){
+ const char *z = pExpr->u.zToken;
+ FuncDef *pDef;
+ if( (z[0]!='i' && z[0]!='I') ) return 0;
+ if( pExpr->x.pList==0 ) return 0;
+ pDef = sqlite3FindFunction(db, z, pExpr->x.pList->nExpr, ENC(db), 0);
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ if( pDef==0 ) return 0;
+#else
+ if( NEVER(pDef==0) ) return 0;
+#endif
+ if( (pDef->funcFlags & SQLITE_FUNC_INLINE)==0 ) return 0;
+ if( SQLITE_PTR_TO_INT(pDef->pUserData)!=INLINEFUNC_iif ) return 0;
+ }else if( pExpr->op==TK_CASE ){
+ if( pExpr->pLeft!=0 ) return 0;
+ }else{
+ return 0;
+ }
+ pList = pExpr->x.pList;
+ assert( pList!=0 );
+ if( pList->nExpr==2 ) return 1;
+ if( pList->nExpr==3 && sqlite3ExprIsNotTrue(pList->a[2].pExpr) ) return 1;
+ return 0;
+}
+
/*
** Return true if we can prove the pE2 will always be true if pE1 is
** true. Return false if we cannot complete the proof or if pE2 might
** be false. Examples:
**
-** pE1: x==5 pE2: x==5 Result: true
-** pE1: x>0 pE2: x==5 Result: false
-** pE1: x=21 pE2: x=21 OR y=43 Result: true
-** pE1: x!=123 pE2: x IS NOT NULL Result: true
-** pE1: x!=?1 pE2: x IS NOT NULL Result: true
-** pE1: x IS NULL pE2: x IS NOT NULL Result: false
-** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
+** pE1: x==5 pE2: x==5 Result: true
+** pE1: x>0 pE2: x==5 Result: false
+** pE1: x=21 pE2: x=21 OR y=43 Result: true
+** pE1: x!=123 pE2: x IS NOT NULL Result: true
+** pE1: x!=?1 pE2: x IS NOT NULL Result: true
+** pE1: x IS NULL pE2: x IS NOT NULL Result: false
+** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
+** pE1: iif(x,y) pE2: x Result: true
+** PE1: iif(x,y,0) pE2: x Result: true
**
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
** Expr.iTable<0 then assume a table number given by iTab.
@@ -115463,6 +118406,9 @@ SQLITE_PRIVATE int sqlite3ExprImpliesExpr(
){
return 1;
}
+ if( sqlite3ExprIsIIF(pParse->db, pE1) ){
+ return sqlite3ExprImpliesExpr(pParse,pE1->x.pList->a[0].pExpr,pE2,iTab);
+ }
return 0;
}
@@ -115930,7 +118876,9 @@ static void findOrCreateAggInfoColumn(
){
struct AggInfo_col *pCol;
int k;
+ int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+ assert( mxTerm <= SMXV(i16) );
assert( pAggInfo->iFirstReg==0 );
pCol = pAggInfo->aCol;
for(k=0; knColumn; k++, pCol++){
@@ -115948,6 +118896,10 @@ static void findOrCreateAggInfoColumn(
assert( pParse->db->mallocFailed );
return;
}
+ if( k>mxTerm ){
+ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm);
+ k = mxTerm;
+ }
pCol = &pAggInfo->aCol[k];
assert( ExprUseYTab(pExpr) );
pCol->pTab = pExpr->y.pTab;
@@ -115981,6 +118933,7 @@ fix_up_expr:
if( pExpr->op==TK_COLUMN ){
pExpr->op = TK_AGG_COLUMN;
}
+ assert( k <= SMXV(pExpr->iAgg) );
pExpr->iAgg = (i16)k;
}
@@ -116065,13 +119018,19 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
** function that is already in the pAggInfo structure
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
+ int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+ assert( mxTerm <= SMXV(i16) );
for(i=0; inFunc; i++, pItem++){
if( NEVER(pItem->pFExpr==pExpr) ) break;
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
}
- if( i>=pAggInfo->nFunc ){
+ if( i>mxTerm ){
+ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm);
+ i = mxTerm;
+ assert( inFunc );
+ }else if( i>=pAggInfo->nFunc ){
/* pExpr is original. Make a new entry in pAggInfo->aFunc[]
*/
u8 enc = ENC(pParse->db);
@@ -116125,6 +119084,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(pExpr, EP_NoReduce);
+ assert( i <= SMXV(pExpr->iAgg) );
pExpr->iAgg = (i16)i;
pExpr->pAggInfo = pAggInfo;
return WRC_Prune;
@@ -116835,13 +119795,13 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
- pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
+ pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*(u32)nAlloc);
pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
if( !pNew->aCol || !pNew->zName ){
assert( db->mallocFailed );
goto exit_begin_add_column;
}
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
+ memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*(size_t)pNew->nCol);
for(i=0; inCol; i++){
Column *pCol = &pNew->aCol[i];
pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
@@ -116936,10 +119896,8 @@ SQLITE_PRIVATE void sqlite3AlterRenameColumn(
** altered. Set iCol to be the index of the column being renamed */
zOld = sqlite3NameFromToken(db, pOld);
if( !zOld ) goto exit_rename_column;
- for(iCol=0; iColnCol; iCol++){
- if( 0==sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
- }
- if( iCol==pTab->nCol ){
+ iCol = sqlite3ColumnIndex(pTab, zOld);
+ if( iCol<0 ){
sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld);
goto exit_rename_column;
}
@@ -117442,6 +120400,7 @@ static int renameParseSql(
int bTemp /* True if SQL is from temp schema */
){
int rc;
+ u64 flags;
sqlite3ParseObjectInit(p, db);
if( zSql==0 ){
@@ -117450,11 +120409,21 @@ static int renameParseSql(
if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
return SQLITE_CORRUPT_BKPT;
}
- db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
+ if( bTemp ){
+ db->init.iDb = 1;
+ }else{
+ int iDb = sqlite3FindDbName(db, zDb);
+ assert( iDb>=0 && iDb<=0xff );
+ db->init.iDb = (u8)iDb;
+ }
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
+ flags = db->flags;
+ testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 );
+ db->flags |= SQLITE_Comments;
rc = sqlite3RunParser(p, zSql);
+ db->flags = flags;
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
&& NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
@@ -117517,10 +120486,11 @@ static int renameEditSql(
nQuot = sqlite3Strlen30(zQuot)-1;
}
- assert( nQuot>=nNew );
- zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
+ assert( nQuot>=nNew && nSql>=0 && nNew>=0 );
+ zOut = sqlite3DbMallocZero(db, (u64)nSql + pRename->nList*(u64)nQuot + 1);
}else{
- zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
+ assert( nSql>0 );
+ zOut = (char*)sqlite3DbMallocZero(db, (2*(u64)nSql + 1) * 3);
if( zOut ){
zBuf1 = &zOut[nSql*2+1];
zBuf2 = &zOut[nSql*4+2];
@@ -117532,16 +120502,17 @@ static int renameEditSql(
** with the new column name, or with single-quoted versions of themselves.
** All that remains is to construct and return the edited SQL string. */
if( zOut ){
- int nOut = nSql;
- memcpy(zOut, zSql, nSql);
+ i64 nOut = nSql;
+ assert( nSql>0 );
+ memcpy(zOut, zSql, (size_t)nSql);
while( pRename->pList ){
int iOff; /* Offset of token to replace in zOut */
- u32 nReplace;
+ i64 nReplace;
const char *zReplace;
RenameToken *pBest = renameColumnTokenNext(pRename);
if( zNew ){
- if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){
+ if( bQuote==0 && sqlite3IsIdChar(*(u8*)pBest->t.z) ){
nReplace = nNew;
zReplace = zNew;
}else{
@@ -117559,14 +120530,15 @@ static int renameEditSql(
memcpy(zBuf1, pBest->t.z, pBest->t.n);
zBuf1[pBest->t.n] = 0;
sqlite3Dequote(zBuf1);
- sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
+ assert( nSql < 0x15555554 /* otherwise malloc would have failed */ );
+ sqlite3_snprintf((int)(nSql*2), zBuf2, "%Q%s", zBuf1,
pBest->t.z[pBest->t.n]=='\'' ? " " : ""
);
zReplace = zBuf2;
nReplace = sqlite3Strlen30(zReplace);
}
- iOff = pBest->t.z - zSql;
+ iOff = (int)(pBest->t.z - zSql);
if( pBest->t.n!=nReplace ){
memmove(&zOut[iOff + nReplace], &zOut[iOff + pBest->t.n],
nOut - (iOff + pBest->t.n)
@@ -117592,11 +120564,12 @@ static int renameEditSql(
** Set all pEList->a[].fg.eEName fields in the expression-list to val.
*/
static void renameSetENames(ExprList *pEList, int val){
+ assert( val==ENAME_NAME || val==ENAME_TAB || val==ENAME_SPAN );
if( pEList ){
int i;
for(i=0; inExpr; i++){
assert( val==ENAME_NAME || pEList->a[i].fg.eEName==ENAME_NAME );
- pEList->a[i].fg.eEName = val;
+ pEList->a[i].fg.eEName = val&0x3;
}
}
}
@@ -117624,7 +120597,7 @@ static int renameResolveTrigger(Parse *pParse){
/* ALWAYS() because if the table of the trigger does not exist, the
** error would have been hit before this point */
if( ALWAYS(pParse->pTriggerTab) ){
- rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
+ rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab)!=0;
}
/* Resolve symbols in WHEN clause */
@@ -117670,8 +120643,9 @@ static int renameResolveTrigger(Parse *pParse){
int i;
for(i=0; ipFrom->nSrc && rc==SQLITE_OK; i++){
SrcItem *p = &pStep->pFrom->a[i];
- if( p->pSelect ){
- sqlite3SelectPrep(pParse, p->pSelect, 0);
+ if( p->fg.isSubquery ){
+ assert( p->u4.pSubq!=0 );
+ sqlite3SelectPrep(pParse, p->u4.pSubq->pSelect, 0);
}
}
}
@@ -117739,8 +120713,12 @@ static void renameWalkTrigger(Walker *pWalker, Trigger *pTrigger){
}
if( pStep->pFrom ){
int i;
- for(i=0; ipFrom->nSrc; i++){
- sqlite3WalkSelect(pWalker, pStep->pFrom->a[i].pSelect);
+ SrcList *pFrom = pStep->pFrom;
+ for(i=0; inSrc; i++){
+ if( pFrom->a[i].fg.isSubquery ){
+ assert( pFrom->a[i].u4.pSubq!=0 );
+ sqlite3WalkSelect(pWalker, pFrom->a[i].u4.pSubq->pSelect);
+ }
}
}
}
@@ -117848,7 +120826,7 @@ static void renameColumnFunc(
if( sParse.pNewTable ){
if( IsView(sParse.pNewTable) ){
Select *pSelect = sParse.pNewTable->u.view.pSelect;
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
@@ -117987,7 +120965,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
}
for(i=0; inSrc; i++){
SrcItem *pItem = &pSrc->a[i];
- if( pItem->pTab==p->pTab ){
+ if( pItem->pSTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
}
@@ -118066,7 +121044,7 @@ static void renameTableFunc(
sNC.pParse = &sParse;
assert( pSelect->selFlags & SF_View );
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
if( sParse.nErr ){
rc = sParse.rc;
@@ -118239,7 +121217,7 @@ static void renameQuotefixFunc(
if( sParse.pNewTable ){
if( IsView(sParse.pNewTable) ){
Select *pSelect = sParse.pNewTable->u.view.pSelect;
- pSelect->selFlags &= ~SF_View;
+ pSelect->selFlags &= ~(u32)SF_View;
sParse.rc = SQLITE_OK;
sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
@@ -118338,10 +121316,10 @@ static void renameTableTest(
if( zDb && zInput ){
int rc;
Parse sParse;
- int flags = db->flags;
+ u64 flags = db->flags;
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
- db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
+ db->flags = flags;
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
NameContext sNC;
@@ -118833,7 +121811,8 @@ static void openStatTable(
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
);
- aRoot[i] = (u32)pParse->regRoot;
+ assert( pParse->isCreate || pParse->nErr );
+ aRoot[i] = (u32)pParse->u1.cr.regRoot;
aCreateTbl[i] = OPFLAG_P2ISREG;
}
}else{
@@ -119024,7 +122003,7 @@ static void statInit(
int nCol; /* Number of columns in index being sampled */
int nKeyCol; /* Number of key columns */
int nColUp; /* nCol rounded up for alignment */
- int n; /* Bytes of space to allocate */
+ i64 n; /* Bytes of space to allocate */
sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */
#ifdef SQLITE_ENABLE_STAT4
/* Maximum number of samples. 0 if STAT4 data is not collected */
@@ -119060,7 +122039,7 @@ static void statInit(
p->db = db;
p->nEst = sqlite3_value_int64(argv[2]);
p->nRow = 0;
- p->nLimit = sqlite3_value_int64(argv[3]);
+ p->nLimit = sqlite3_value_int(argv[3]);
p->nCol = nCol;
p->nKeyCol = nKeyCol;
p->nSkipAhead = 0;
@@ -120193,16 +123172,6 @@ static void decodeIntArray(
while( z[0]!=0 && z[0]!=' ' ) z++;
while( z[0]==' ' ) z++;
}
-
- /* Set the bLowQual flag if the peak number of rows obtained
- ** from a full equality match is so large that a full table scan
- ** seems likely to be faster than using the index.
- */
- if( aLog[0] > 66 /* Index has more than 100 rows */
- && aLog[0] <= aLog[nOut-1] /* And only a single value seen */
- ){
- pIndex->bLowQual = 1;
- }
}
}
@@ -120415,12 +123384,13 @@ static int loadStatTbl(
while( sqlite3_step(pStmt)==SQLITE_ROW ){
int nIdxCol = 1; /* Number of columns in stat4 records */
- char *zIndex; /* Index name */
- Index *pIdx; /* Pointer to the index object */
- int nSample; /* Number of samples */
- int nByte; /* Bytes of space required */
- int i; /* Bytes of space required */
- tRowcnt *pSpace;
+ char *zIndex; /* Index name */
+ Index *pIdx; /* Pointer to the index object */
+ int nSample; /* Number of samples */
+ i64 nByte; /* Bytes of space required */
+ i64 i; /* Bytes of space required */
+ tRowcnt *pSpace; /* Available allocated memory space */
+ u8 *pPtr; /* Available memory as a u8 for easier manipulation */
zIndex = (char *)sqlite3_column_text(pStmt, 0);
if( zIndex==0 ) continue;
@@ -120440,7 +123410,7 @@ static int loadStatTbl(
}
pIdx->nSampleCol = nIdxCol;
pIdx->mxSample = nSample;
- nByte = sizeof(IndexSample) * nSample;
+ nByte = ROUND8(sizeof(IndexSample) * nSample);
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
@@ -120449,7 +123419,10 @@ static int loadStatTbl(
sqlite3_finalize(pStmt);
return SQLITE_NOMEM_BKPT;
}
- pSpace = (tRowcnt*)&pIdx->aSample[nSample];
+ pPtr = (u8*)pIdx->aSample;
+ pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
+ pSpace = (tRowcnt*)pPtr;
+ assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
pIdx->pTable->tabFlags |= TF_HasStat4;
for(i=0; iaDb, sizeof(db->aDb[0])*2);
}else{
- aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
+ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(1+(i64)db->nDb));
if( aNew==0 ) return;
}
db->aDb = aNew;
@@ -120813,6 +123786,12 @@ static void attachFunc(
sqlite3_free(zErr);
return;
}
+ if( (db->flags & SQLITE_AttachWrite)==0 ){
+ flags &= ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE);
+ flags |= SQLITE_OPEN_READONLY;
+ }else if( (db->flags & SQLITE_AttachCreate)==0 ){
+ flags &= ~SQLITE_OPEN_CREATE;
+ }
assert( pVfs );
flags |= SQLITE_OPEN_MAIN_DB;
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
@@ -120864,21 +123843,19 @@ static void attachFunc(
sqlite3BtreeEnterAll(db);
db->init.iDb = 0;
db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( db->setlkFlags & SQLITE_SETLK_BLOCK_ON_CONNECT ){
+ int val = 1;
+ sqlite3_file *fd = sqlite3PagerFile(sqlite3BtreePager(pNew->pBt));
+ sqlite3OsFileControlHint(fd, SQLITE_FCNTL_BLOCK_ON_CONNECT, &val);
+ }
+#endif
if( !REOPEN_AS_MEMDB(db) ){
rc = sqlite3Init(db, &zErrDyn);
}
sqlite3BtreeLeaveAll(db);
assert( zErrDyn==0 || rc!=SQLITE_OK );
}
-#ifdef SQLITE_USER_AUTHENTICATION
- if( rc==SQLITE_OK && !REOPEN_AS_MEMDB(db) ){
- u8 newAuth = 0;
- rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
- if( newAuthauth.authLevel ){
- rc = SQLITE_AUTH_USER;
- }
- }
-#endif
if( rc ){
if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){
int iDb = db->nDb - 1;
@@ -121122,20 +124099,21 @@ static int fixSelectCb(Walker *p, Select *pSelect){
if( NEVER(pList==0) ) return WRC_Continue;
for(i=0, pItem=pList->a; inSrc; i++, pItem++){
- if( pFix->bTemp==0 ){
- if( pItem->zDatabase ){
- if( iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
+ if( pFix->bTemp==0 && pItem->fg.isSubquery==0 ){
+ if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){
+ if( iDb!=sqlite3FindDbName(db, pItem->u4.zDatabase) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
- pFix->zType, pFix->pName, pItem->zDatabase);
+ pFix->zType, pFix->pName, pItem->u4.zDatabase);
return WRC_Abort;
}
- sqlite3DbFree(db, pItem->zDatabase);
- pItem->zDatabase = 0;
+ sqlite3DbFree(db, pItem->u4.zDatabase);
pItem->fg.notCte = 1;
+ pItem->fg.hadSchema = 1;
}
- pItem->pSchema = pFix->pSchema;
+ pItem->u4.pSchema = pFix->pSchema;
pItem->fg.fromDDL = 1;
+ pItem->fg.fixedSchema = 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( pList->a[i].fg.isUsing==0
@@ -121375,11 +124353,7 @@ SQLITE_PRIVATE int sqlite3AuthReadCol(
int rc; /* Auth callback return code */
if( db->init.busy ) return SQLITE_OK;
- rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
-#ifdef SQLITE_USER_AUTHENTICATION
- ,db->auth.zAuthUser
-#endif
- );
+ rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
if( rc==SQLITE_DENY ){
char *z = sqlite3_mprintf("%s.%s", zTab, zCol);
if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z);
@@ -121428,7 +124402,7 @@ SQLITE_PRIVATE void sqlite3AuthRead(
assert( pTabList );
for(iSrc=0; iSrcnSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
- pTab = pTabList->a[iSrc].pTab;
+ pTab = pTabList->a[iSrc].pSTab;
break;
}
}
@@ -121486,11 +124460,7 @@ SQLITE_PRIVATE int sqlite3AuthCheck(
testcase( zArg3==0 );
testcase( pParse->zAuthContext==0 );
- rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
-#ifdef SQLITE_USER_AUTHENTICATION
- ,db->auth.zAuthUser
-#endif
- );
+ rc = db->xAuth(db->pAuthArg,code,zArg1,zArg2,zArg3,pParse->zAuthContext);
if( rc==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;
@@ -121602,6 +124572,7 @@ static SQLITE_NOINLINE void lockTable(
}
}
+ assert( pToplevel->nTableLock < 0x7fff0000 );
nBytes = sizeof(TableLock) * (pToplevel->nTableLock+1);
pToplevel->aTableLock =
sqlite3DbReallocOrFree(pToplevel->db, pToplevel->aTableLock, nBytes);
@@ -121702,10 +124673,12 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
if( v ){
if( pParse->bReturning ){
- Returning *pReturning = pParse->u1.pReturning;
+ Returning *pReturning;
int addrRewind;
int reg;
+ assert( !pParse->isCreate );
+ pReturning = pParse->u1.d.pReturning;
if( pReturning->nRetCol ){
sqlite3VdbeAddOp0(v, OP_FkCheck);
addrRewind =
@@ -121723,17 +124696,6 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
}
sqlite3VdbeAddOp0(v, OP_Halt);
-#if SQLITE_USER_AUTHENTICATION && !defined(SQLITE_OMIT_SHARED_CACHE)
- if( pParse->nTableLock>0 && db->init.busy==0 ){
- sqlite3UserAuthInit(db);
- if( db->auth.authLevelrc = SQLITE_AUTH_USER;
- return;
- }
- }
-#endif
-
/* The cookie mask contains one bit for each database file open.
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
** set for each database that is used. Generate code to start a
@@ -121792,7 +124754,9 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
}
if( pParse->bReturning ){
- Returning *pRet = pParse->u1.pReturning;
+ Returning *pRet;
+ assert( !pParse->isCreate );
+ pRet = pParse->u1.d.pReturning;
if( pRet->nRetCol ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
}
@@ -121862,16 +124826,6 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
pParse->nested--;
}
-#if SQLITE_USER_AUTHENTICATION
-/*
-** Return TRUE if zTable is the name of the system table that stores the
-** list of users and their access credentials.
-*/
-SQLITE_PRIVATE int sqlite3UserAuthTable(const char *zTable){
- return sqlite3_stricmp(zTable, "sqlite_user")==0;
-}
-#endif
-
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
@@ -121890,13 +124844,6 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha
/* All mutexes are required for schema access. Make sure we hold them. */
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
-#if SQLITE_USER_AUTHENTICATION
- /* Only the admin user is allowed to know that the sqlite_user table
- ** exists */
- if( db->auth.authLevelnDb; i++){
if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
@@ -121990,6 +124937,16 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlite3PragmaVtabRegister(db, zName);
}
+#ifndef SQLITE_OMIT_JSON
+ if( pMod==0 && sqlite3_strnicmp(zName, "json", 4)==0 ){
+ pMod = sqlite3JsonVtabRegister(db, zName);
+ }
+#endif
+#ifdef SQLITE_ENABLE_CARRAY
+ if( pMod==0 && sqlite3_stricmp(zName, "carray")==0 ){
+ pMod = sqlite3CarrayRegister(db);
+ }
+#endif
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
testcase( pMod->pEpoTab==0 );
return pMod->pEpoTab;
@@ -122031,12 +124988,12 @@ SQLITE_PRIVATE Table *sqlite3LocateTableItem(
SrcItem *p
){
const char *zDb;
- assert( p->pSchema==0 || p->zDatabase==0 );
- if( p->pSchema ){
- int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+ if( p->fg.fixedSchema ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
- zDb = p->zDatabase;
+ assert( !p->fg.isSubquery );
+ zDb = p->u4.zDatabase;
}
return sqlite3LocateTable(pParse, flags, p->zName, zDb);
}
@@ -122624,10 +125581,16 @@ SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table *pTab){
** find the (first) offset of that column in index pIdx. Or return -1
** if column iCol is not used in index pIdx.
*/
-SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
+SQLITE_PRIVATE int sqlite3TableColumnToIndex(Index *pIdx, int iCol){
int i;
+ i16 iCol16;
+ assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
+ assert( pIdx->nColumn<=SQLITE_MAX_COLUMN*2 );
+ iCol16 = iCol;
for(i=0; inColumn; i++){
- if( iCol==pIdx->aiColumn[i] ) return i;
+ if( iCol16==pIdx->aiColumn[i] ){
+ return i;
+ }
}
return -1;
}
@@ -122881,8 +125844,9 @@ SQLITE_PRIVATE void sqlite3StartTable(
/* If the file format and encoding in the database have not been set,
** set them now.
*/
- reg1 = pParse->regRowid = ++pParse->nMem;
- reg2 = pParse->regRoot = ++pParse->nMem;
+ assert( pParse->isCreate );
+ reg1 = pParse->u1.cr.regRowid = ++pParse->nMem;
+ reg2 = pParse->u1.cr.regRoot = ++pParse->nMem;
reg3 = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, BTREE_FILE_FORMAT);
sqlite3VdbeUsesBtree(v, iDb);
@@ -122897,8 +125861,8 @@ SQLITE_PRIVATE void sqlite3StartTable(
** The record created does not contain anything yet. It will be replaced
** by the real entry in code generated at sqlite3EndTable().
**
- ** The rowid for the new entry is left in register pParse->regRowid.
- ** The root page number of the new table is left in reg pParse->regRoot.
+ ** The rowid for the new entry is left in register pParse->u1.cr.regRowid.
+ ** The root page of the new table is left in reg pParse->u1.cr.regRoot.
** The rowid and root page number values are needed by the code that
** sqlite3EndTable will generate.
*/
@@ -122909,7 +125873,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
#endif
{
assert( !pParse->bReturning );
- pParse->u1.addrCrTab =
+ pParse->u1.cr.addrCrTab =
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
sqlite3OpenSchemaTable(pParse, iDb);
@@ -122918,6 +125882,9 @@ SQLITE_PRIVATE void sqlite3StartTable(
sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3VdbeAddOp0(v, OP_Close);
+ }else if( db->init.imposterTable ){
+ pTable->tabFlags |= TF_Imposter;
+ if( db->init.imposterTable>=2 ) pTable->tabFlags |= TF_Readonly;
}
/* Normal (non-error) return. */
@@ -122987,7 +125954,8 @@ SQLITE_PRIVATE void sqlite3AddReturning(Parse *pParse, ExprList *pList){
sqlite3ExprListDelete(db, pList);
return;
}
- pParse->u1.pReturning = pRet;
+ assert( !pParse->isCreate );
+ pParse->u1.d.pReturning = pRet;
pRet->pParse = pParse;
pRet->pReturnEL = pList;
sqlite3ParserAddCleanup(pParse, sqlite3DeleteReturning, pRet);
@@ -123029,7 +125997,6 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
char *zType;
Column *pCol;
sqlite3 *db = pParse->db;
- u8 hName;
Column *aNew;
u8 eType = COLTYPE_CUSTOM;
u8 szEst = 1;
@@ -123083,13 +126050,10 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
memcpy(z, sName.z, sName.n);
z[sName.n] = 0;
sqlite3Dequote(z);
- hName = sqlite3StrIHash(z);
- for(i=0; inCol; i++){
- if( p->aCol[i].hName==hName && sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){
- sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
- sqlite3DbFree(db, z);
- return;
- }
+ if( p->nCol && sqlite3ColumnIndex(p, z)>=0 ){
+ sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
+ sqlite3DbFree(db, z);
+ return;
}
aNew = sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0]));
if( aNew==0 ){
@@ -123100,7 +126064,7 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
pCol->zCnName = z;
- pCol->hName = hName;
+ pCol->hName = sqlite3StrIHash(z);
sqlite3ColumnPropertiesFromName(p, pCol);
if( sType.n==0 ){
@@ -123124,9 +126088,14 @@ SQLITE_PRIVATE void sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
pCol->affinity = sqlite3AffinityType(zType, pCol);
pCol->colFlags |= COLFLAG_HASTYPE;
}
+ if( p->nCol<=0xff ){
+ u8 h = pCol->hName % sizeof(p->aHx);
+ p->aHx[h] = p->nCol;
+ }
p->nCol++;
p->nNVCol++;
- pParse->constraintName.n = 0;
+ assert( pParse->isCreate );
+ pParse->u1.cr.constraintName.n = 0;
}
/*
@@ -123390,15 +126359,11 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
assert( pCExpr!=0 );
sqlite3StringToId(pCExpr);
if( pCExpr->op==TK_ID ){
- const char *zCName;
assert( !ExprHasProperty(pCExpr, EP_IntValue) );
- zCName = pCExpr->u.zToken;
- for(iCol=0; iColnCol; iCol++){
- if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){
- pCol = &pTab->aCol[iCol];
- makeColumnPartOfPrimaryKey(pParse, pCol);
- break;
- }
+ iCol = sqlite3ColumnIndex(pTab, pCExpr->u.zToken);
+ if( iCol>=0 ){
+ pCol = &pTab->aCol[iCol];
+ makeColumnPartOfPrimaryKey(pParse, pCol);
}
}
}
@@ -123450,8 +126415,10 @@ SQLITE_PRIVATE void sqlite3AddCheckConstraint(
&& !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
){
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
- if( pParse->constraintName.n ){
- sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
+ assert( pParse->isCreate );
+ if( pParse->u1.cr.constraintName.n ){
+ sqlite3ExprListSetName(pParse, pTab->pCheck,
+ &pParse->u1.cr.constraintName, 1);
}else{
Token t;
for(zStart++; sqlite3Isspace(zStart[0]); zStart++){}
@@ -123646,7 +126613,8 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent){
** from sqliteMalloc() and must be freed by the calling function.
*/
static char *createTableStmt(sqlite3 *db, Table *p){
- int i, k, n;
+ int i, k, len;
+ i64 n;
char *zStmt;
char *zSep, *zSep2, *zEnd;
Column *pCol;
@@ -123670,8 +126638,9 @@ static char *createTableStmt(sqlite3 *db, Table *p){
sqlite3OomFault(db);
return 0;
}
- sqlite3_snprintf(n, zStmt, "CREATE TABLE ");
- k = sqlite3Strlen30(zStmt);
+ assert( n>14 && n<=0x7fffffff );
+ memcpy(zStmt, "CREATE TABLE ", 13);
+ k = 13;
identPut(zStmt, &k, p->zName);
zStmt[k++] = '(';
for(pCol=p->aCol, i=0; inCol; i++, pCol++){
@@ -123683,13 +126652,15 @@ static char *createTableStmt(sqlite3 *db, Table *p){
/* SQLITE_AFF_REAL */ " REAL",
/* SQLITE_AFF_FLEXNUM */ " NUM",
};
- int len;
const char *zType;
- sqlite3_snprintf(n-k, &zStmt[k], zSep);
- k += sqlite3Strlen30(&zStmt[k]);
+ len = sqlite3Strlen30(zSep);
+ assert( k+lenzCnName);
+ assert( kaffinity-SQLITE_AFF_BLOB >= 0 );
assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_BLOB );
@@ -123704,11 +126675,14 @@ static char *createTableStmt(sqlite3 *db, Table *p){
assert( pCol->affinity==SQLITE_AFF_BLOB
|| pCol->affinity==SQLITE_AFF_FLEXNUM
|| pCol->affinity==sqlite3AffinityType(zType, 0) );
+ assert( k+lennColumn>=N ) return SQLITE_OK;
+ db = pParse->db;
+ assert( N>0 );
+ assert( N <= SQLITE_MAX_COLUMN*2 /* tag-20250221-1 */ );
+ testcase( N==2*pParse->db->aLimit[SQLITE_LIMIT_COLUMN] );
assert( pIdx->isResized==0 );
- nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
+ nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*(u64)N;
zExtra = sqlite3DbMallocZero(db, nByte);
if( zExtra==0 ) return SQLITE_NOMEM_BKPT;
memcpy(zExtra, pIdx->azColl, sizeof(char*)*pIdx->nColumn);
@@ -123735,7 +126714,7 @@ static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
zExtra += sizeof(i16)*N;
memcpy(zExtra, pIdx->aSortOrder, pIdx->nColumn);
pIdx->aSortOrder = (u8*)zExtra;
- pIdx->nColumn = N;
+ pIdx->nColumn = (u16)N; /* See tag-20250221-1 above for proof of safety */
pIdx->isResized = 1;
return SQLITE_OK;
}
@@ -123901,9 +126880,9 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
** into BTREE_BLOBKEY.
*/
assert( !pParse->bReturning );
- if( pParse->u1.addrCrTab ){
+ if( pParse->u1.cr.addrCrTab ){
assert( v );
- sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY);
+ sqlite3VdbeChangeP3(v, pParse->u1.cr.addrCrTab, BTREE_BLOBKEY);
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
@@ -123989,14 +126968,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pIdx->nColumn = pIdx->nKeyCol;
continue;
}
- if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
+ if( resizeIndexObject(pParse, pIdx, pIdx->nKeyCol+n) ) return;
for(i=0, j=pIdx->nKeyCol; inKeyCol, pPk, i) ){
testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
pIdx->aiColumn[j] = pPk->aiColumn[i];
pIdx->azColl[j] = pPk->azColl[i];
if( pPk->aSortOrder[i] ){
- /* See ticket https://www.sqlite.org/src/info/bba7b69f9849b5bf */
+ /* See ticket https://sqlite.org/src/info/bba7b69f9849b5bf */
pIdx->bAscKeyBug = 1;
}
j++;
@@ -124013,7 +126992,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( !hasColumn(pPk->aiColumn, nPk, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
}
- if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
+ if( resizeIndexObject(pParse, pPk, nPk+nExtra) ) return;
for(i=0, j=nPk; inCol; i++){
if( !hasColumn(pPk->aiColumn, j, i)
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
@@ -124343,7 +127322,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
/* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
** statement to populate the new table. The root-page number for the
- ** new table is in register pParse->regRoot.
+ ** new table is in register pParse->u1.cr.regRoot.
**
** Once the SELECT has been coded by sqlite3Select(), it is in a
** suitable state to query for the column names and types to be used
@@ -124374,7 +127353,8 @@ SQLITE_PRIVATE void sqlite3EndTable(
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
sqlite3MayAbort(pParse);
- sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->regRoot, iDb);
+ assert( pParse->isCreate );
+ sqlite3VdbeAddOp3(v, OP_OpenWrite, iCsr, pParse->u1.cr.regRoot, iDb);
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
@@ -124419,6 +127399,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
** schema table. We just need to update that slot with all
** the information we've collected.
*/
+ assert( pParse->isCreate );
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE
" SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q"
@@ -124427,9 +127408,9 @@ SQLITE_PRIVATE void sqlite3EndTable(
zType,
p->zName,
p->zName,
- pParse->regRoot,
+ pParse->u1.cr.regRoot,
zStmt,
- pParse->regRowid
+ pParse->u1.cr.regRowid
);
sqlite3DbFree(db, zStmt);
sqlite3ChangeCookie(pParse, iDb);
@@ -124598,8 +127579,9 @@ create_view_fail:
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
** The Table structure pTable is really a VIEW. Fill in the names of
-** the columns of the view in the pTable structure. Return the number
-** of errors. If an error is seen leave an error message in pParse->zErrMsg.
+** the columns of the view in the pTable structure. Return non-zero if
+** there are errors. If an error is seen an error message is left
+** in pParse->zErrMsg.
*/
static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
Table *pSelTab; /* A fake table from which we get the result set */
@@ -124722,7 +127704,7 @@ static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
sqlite3DeleteColumnNames(db, pTable);
}
#endif /* SQLITE_OMIT_VIEW */
- return nErr;
+ return nErr + pParse->nErr;
}
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable!=0 );
@@ -125020,6 +128002,8 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
+ assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.isSubquery==0 );
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
assert( isView==0 || isView==LOCATE_VIEW );
@@ -125028,7 +128012,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
if( pTab==0 ){
if( noErr ){
- sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase);
sqlite3ForceNotReadOnly(pParse);
}
goto exit_drop_table;
@@ -125166,7 +128150,7 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
}else{
nCol = pFromCol->nExpr;
}
- nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
+ nByte = SZ_FKEY(nCol) + pTo->n + 1;
if( pToCol ){
for(i=0; inExpr; i++){
nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
@@ -125368,7 +128352,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
** not work for UNIQUE constraint indexes on WITHOUT ROWID tables
** with DESC primary keys, since those indexes have there keys in
** a different order from the main table.
- ** See ticket: https://www.sqlite.org/src/info/bba7b69f9849b5bf
+ ** See ticket: https://sqlite.org/src/info/bba7b69f9849b5bf
*/
sqlite3VdbeAddOp1(v, OP_SeekEnd, iIdx);
}
@@ -125392,13 +128376,14 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
*/
SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(
sqlite3 *db, /* Database connection */
- i16 nCol, /* Total number of columns in the index */
+ int nCol, /* Total number of columns in the index */
int nExtra, /* Number of bytes of extra space to alloc */
char **ppExtra /* Pointer to the "extra" space */
){
Index *p; /* Allocated index object */
- int nByte; /* Bytes of space for Index object + arrays */
+ i64 nByte; /* Bytes of space for Index object + arrays */
+ assert( nCol <= 2*db->aLimit[SQLITE_LIMIT_COLUMN] );
nByte = ROUND8(sizeof(Index)) + /* Index structure */
ROUND8(sizeof(char*)*nCol) + /* Index.azColl */
ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */
@@ -125411,8 +128396,9 @@ SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(
p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
p->aSortOrder = (u8*)pExtra;
- p->nColumn = nCol;
- p->nKeyCol = nCol - 1;
+ assert( nCol>0 );
+ p->nColumn = (u16)nCol;
+ p->nKeyCol = (u16)(nCol - 1);
*ppExtra = ((char*)p) + nByte;
}
return p;
@@ -125552,9 +128538,6 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
&& pTblName!=0
-#if SQLITE_USER_AUTHENTICATION
- && sqlite3UserAuthTable(pTab->zName)==0
-#endif
){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
@@ -126119,15 +129102,17 @@ SQLITE_PRIVATE void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists
}
assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
assert( pName->nSrc==1 );
+ assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.isSubquery==0 );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
}
- pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
+ pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].u4.zDatabase);
if( pIndex==0 ){
if( !ifExists ){
sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
- sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].u4.zDatabase);
sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
@@ -126224,12 +129209,11 @@ SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *
sqlite3 *db = pParse->db;
int i;
if( pList==0 ){
- pList = sqlite3DbMallocZero(db, sizeof(IdList) );
+ pList = sqlite3DbMallocZero(db, SZ_IDLIST(1));
if( pList==0 ) return 0;
}else{
IdList *pNew;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(IdList) + pList->nId*sizeof(pList->a));
+ pNew = sqlite3DbRealloc(db, pList, SZ_IDLIST(pList->nId+1));
if( pNew==0 ){
sqlite3IdListDelete(db, pList);
return 0;
@@ -126251,7 +129235,6 @@ SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
int i;
assert( db!=0 );
if( pList==0 ) return;
- assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */
for(i=0; inId; i++){
sqlite3DbFree(db, pList->a[i].zName);
}
@@ -126329,8 +129312,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
return 0;
}
if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
- pNew = sqlite3DbRealloc(db, pSrc,
- sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
+ pNew = sqlite3DbRealloc(db, pSrc, SZ_SRCLIST(nAlloc));
if( pNew==0 ){
assert( db->mallocFailed );
return 0;
@@ -126405,7 +129387,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
assert( pParse->db!=0 );
db = pParse->db;
if( pList==0 ){
- pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
+ pList = sqlite3DbMallocRawNN(pParse->db, SZ_SRCLIST(1));
if( pList==0 ) return 0;
pList->nAlloc = 1;
pList->nSrc = 1;
@@ -126424,12 +129406,14 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
if( pDatabase && pDatabase->z==0 ){
pDatabase = 0;
}
+ assert( pItem->fg.fixedSchema==0 );
+ assert( pItem->fg.isSubquery==0 );
if( pDatabase ){
pItem->zName = sqlite3NameFromToken(db, pDatabase);
- pItem->zDatabase = sqlite3NameFromToken(db, pTable);
+ pItem->u4.zDatabase = sqlite3NameFromToken(db, pTable);
}else{
pItem->zName = sqlite3NameFromToken(db, pTable);
- pItem->zDatabase = 0;
+ pItem->u4.zDatabase = 0;
}
return pList;
}
@@ -126445,13 +129429,40 @@ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
for(i=0, pItem=pList->a; inSrc; i++, pItem++){
if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
- if( pItem->pSelect ){
- sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
+ if( pItem->fg.isSubquery ){
+ assert( pItem->u4.pSubq!=0 );
+ assert( pItem->u4.pSubq->pSelect!=0 );
+ assert( pItem->u4.pSubq->pSelect->pSrc!=0 );
+ sqlite3SrcListAssignCursors(pParse, pItem->u4.pSubq->pSelect->pSrc);
}
}
}
}
+/*
+** Delete a Subquery object and its substructure.
+*/
+SQLITE_PRIVATE void sqlite3SubqueryDelete(sqlite3 *db, Subquery *pSubq){
+ assert( pSubq!=0 && pSubq->pSelect!=0 );
+ sqlite3SelectDelete(db, pSubq->pSelect);
+ sqlite3DbFree(db, pSubq);
+}
+
+/*
+** Remove a Subquery from a SrcItem. Return the associated Select object.
+** The returned Select becomes the responsibility of the caller.
+*/
+SQLITE_PRIVATE Select *sqlite3SubqueryDetach(sqlite3 *db, SrcItem *pItem){
+ Select *pSel;
+ assert( pItem!=0 );
+ assert( pItem->fg.isSubquery );
+ pSel = pItem->u4.pSubq->pSelect;
+ sqlite3DbFree(db, pItem->u4.pSubq);
+ pItem->u4.pSubq = 0;
+ pItem->fg.isSubquery = 0;
+ return pSel;
+}
+
/*
** Delete an entire SrcList including all its substructure.
*/
@@ -126461,13 +129472,24 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
assert( db!=0 );
if( pList==0 ) return;
for(pItem=pList->a, i=0; inSrc; i++, pItem++){
- if( pItem->zDatabase ) sqlite3DbNNFreeNN(db, pItem->zDatabase);
+
+ /* Check invariants on SrcItem */
+ assert( !pItem->fg.isIndexedBy || !pItem->fg.isTabFunc );
+ assert( !pItem->fg.isCte || !pItem->fg.isIndexedBy );
+ assert( !pItem->fg.fixedSchema || !pItem->fg.isSubquery );
+ assert( !pItem->fg.isSubquery || (pItem->u4.pSubq!=0 &&
+ pItem->u4.pSubq->pSelect!=0) );
+
if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName);
if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias);
+ if( pItem->fg.isSubquery ){
+ sqlite3SubqueryDelete(db, pItem->u4.pSubq);
+ }else if( pItem->fg.fixedSchema==0 && pItem->u4.zDatabase!=0 ){
+ sqlite3DbNNFreeNN(db, pItem->u4.zDatabase);
+ }
if( pItem->fg.isIndexedBy ) sqlite3DbFree(db, pItem->u1.zIndexedBy);
if( pItem->fg.isTabFunc ) sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
- sqlite3DeleteTable(db, pItem->pTab);
- if( pItem->pSelect ) sqlite3SelectDelete(db, pItem->pSelect);
+ sqlite3DeleteTable(db, pItem->pSTab);
if( pItem->fg.isUsing ){
sqlite3IdListDelete(db, pItem->u3.pUsing);
}else if( pItem->u3.pOn ){
@@ -126477,6 +129499,54 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3DbNNFreeNN(db, pList);
}
+/*
+** Attach a Subquery object to pItem->uv.pSubq. Set the
+** pSelect value but leave all the other values initialized
+** to zero.
+**
+** A copy of the Select object is made if dupSelect is true, and the
+** SrcItem takes responsibility for deleting the copy. If dupSelect is
+** false, ownership of the Select passes to the SrcItem. Either way,
+** the SrcItem will take responsibility for deleting the Select.
+**
+** When dupSelect is zero, that means the Select might get deleted right
+** away if there is an OOM error. Beware.
+**
+** Return non-zero on success. Return zero on an OOM error.
+*/
+SQLITE_PRIVATE int sqlite3SrcItemAttachSubquery(
+ Parse *pParse, /* Parsing context */
+ SrcItem *pItem, /* Item to which the subquery is to be attached */
+ Select *pSelect, /* The subquery SELECT. Must be non-NULL */
+ int dupSelect /* If true, attach a copy of pSelect, not pSelect itself.*/
+){
+ Subquery *p;
+ assert( pSelect!=0 );
+ assert( pItem->fg.isSubquery==0 );
+ if( pItem->fg.fixedSchema ){
+ pItem->u4.pSchema = 0;
+ pItem->fg.fixedSchema = 0;
+ }else if( pItem->u4.zDatabase!=0 ){
+ sqlite3DbFree(pParse->db, pItem->u4.zDatabase);
+ pItem->u4.zDatabase = 0;
+ }
+ if( dupSelect ){
+ pSelect = sqlite3SelectDup(pParse->db, pSelect, 0);
+ if( pSelect==0 ) return 0;
+ }
+ p = pItem->u4.pSubq = sqlite3DbMallocRawNN(pParse->db, sizeof(Subquery));
+ if( p==0 ){
+ sqlite3SelectDelete(pParse->db, pSelect);
+ return 0;
+ }
+ pItem->fg.isSubquery = 1;
+ p->pSelect = pSelect;
+ assert( offsetof(Subquery, pSelect)==0 );
+ memset(((char*)p)+sizeof(p->pSelect), 0, sizeof(*p)-sizeof(p->pSelect));
+ return 1;
+}
+
+
/*
** This routine is called by the parser to add a new term to the
** end of a growing FROM clause. The "p" parameter is the part of
@@ -126526,10 +129596,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
if( pAlias->n ){
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
}
+ assert( pSubquery==0 || pDatabase==0 );
if( pSubquery ){
- pItem->pSelect = pSubquery;
- if( pSubquery->selFlags & SF_NestedFrom ){
- pItem->fg.isNestedFrom = 1;
+ if( sqlite3SrcItemAttachSubquery(pParse, pItem, pSubquery, 0) ){
+ if( pSubquery->selFlags & SF_NestedFrom ){
+ pItem->fg.isNestedFrom = 1;
+ }
}
}
assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
@@ -126582,16 +129654,22 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI
** are deleted by this function.
*/
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){
- assert( p1 && p1->nSrc==1 );
+ assert( p1 );
+ assert( p2 || pParse->nErr );
+ assert( p2==0 || p2->nSrc>=1 );
+ testcase( p1->nSrc==0 );
if( p2 ){
- SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1);
+ int nOld = p1->nSrc;
+ SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, nOld);
if( pNew==0 ){
sqlite3SrcListDelete(pParse->db, p2);
}else{
p1 = pNew;
- memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
+ memcpy(&p1->a[nOld], p2->a, p2->nSrc*sizeof(SrcItem));
+ assert( nOld==1 || (p2->a[0].fg.jointype & JT_LTORJ)==0 );
+ assert( p1->nSrc>=1 );
+ p1->a[0].fg.jointype |= (JT_LTORJ & p2->a[0].fg.jointype);
sqlite3DbFree(pParse->db, p2);
- p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype);
}
}
return p1;
@@ -127102,14 +130180,19 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
}
if( pParse->nErr ){
assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
- if( pIdx->bNoQuery==0 ){
+ if( pIdx->bNoQuery==0
+ && sqlite3HashFind(&pIdx->pSchema->idxHash, pIdx->zName)
+ ){
/* Deactivate the index because it contains an unknown collating
** sequence. The only way to reactive the index is to reload the
** schema. Adding the missing collating sequence later does not
** reactive the index. The application had the chance to register
** the missing index using the collation-needed callback. For
** simplicity, SQLite will not give the application a second chance.
- */
+ **
+ ** Except, do not do this if the index is not in the schema hash
+ ** table. In this case the index is currently being constructed
+ ** by a CREATE INDEX statement, and retrying will not help. */
pIdx->bNoQuery = 1;
pParse->rc = SQLITE_ERROR_RETRY;
}
@@ -127201,10 +130284,9 @@ SQLITE_PRIVATE With *sqlite3WithAdd(
}
if( pWith ){
- sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
- pNew = sqlite3DbRealloc(db, pWith, nByte);
+ pNew = sqlite3DbRealloc(db, pWith, SZ_WITH(pWith->nCte+1));
}else{
- pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
+ pNew = sqlite3DbMallocZero(db, SZ_WITH(1));
}
assert( (pNew!=0 && zName!=0) || db->mallocFailed );
@@ -127542,12 +130624,18 @@ static int matchQuality(
u8 enc /* Desired text encoding */
){
int match;
- assert( p->nArg>=-1 );
+ assert( p->nArg>=(-4) && p->nArg!=(-2) );
+ assert( nArg>=(-2) );
/* Wrong number of arguments means "no match" */
if( p->nArg!=nArg ){
- if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
+ if( nArg==(-2) ) return p->xSFunc==0 ? 0 : FUNC_PERFECT_MATCH;
if( p->nArg>=0 ) return 0;
+ /* Special p->nArg values available to built-in functions only:
+ ** -3 1 or more arguments required
+ ** -4 2 or more arguments required
+ */
+ if( p->nArg<(-2) && nArg<(-2-p->nArg) ) return 0;
}
/* Give a better score to a function with a specific number of arguments
@@ -127741,6 +130829,7 @@ SQLITE_PRIVATE void sqlite3SchemaClear(void *p){
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
sqlite3DeleteTrigger(&xdb, (Trigger*)sqliteHashData(pElem));
}
+
sqlite3HashClear(&temp2);
sqlite3HashInit(&pSchema->tblHash);
for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
@@ -127807,8 +130896,8 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
**
** The following fields are initialized appropriate in pSrc:
**
-** pSrc->a[0].pTab Pointer to the Table object
-** pSrc->a[0].pIndex Pointer to the INDEXED BY index, if there is one
+** pSrc->a[0].spTab Pointer to the Table object
+** pSrc->a[0].u2.pIBIndex Pointer to the INDEXED BY index, if there is one
**
*/
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
@@ -127816,8 +130905,8 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
Table *pTab;
assert( pItem && pSrc->nSrc>=1 );
pTab = sqlite3LocateTableItem(pParse, 0, pItem);
- if( pItem->pTab ) sqlite3DeleteTable(pParse->db, pItem->pTab);
- pItem->pTab = pTab;
+ if( pItem->pSTab ) sqlite3DeleteTable(pParse->db, pItem->pSTab);
+ pItem->pSTab = pTab;
pItem->fg.notCte = 1;
if( pTab ){
pTab->nTabRef++;
@@ -127858,6 +130947,7 @@ SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *
** is for a top-level SQL statement.
*/
static int vtabIsReadOnly(Parse *pParse, Table *pTab){
+ assert( IsVirtual(pTab) );
if( sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 ){
return 1;
}
@@ -127939,7 +131029,8 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
- pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+ assert( pFrom->a[0].fg.fixedSchema==0 && pFrom->a[0].fg.isSubquery==0 );
+ pFrom->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
assert( pFrom->a[0].fg.isUsing==0 );
assert( pFrom->a[0].u3.pOn==0 );
}
@@ -128001,7 +131092,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
** );
*/
- pTab = pSrc->a[0].pTab;
+ pTab = pSrc->a[0].pSTab;
if( HasRowid(pTab) ){
pLhs = sqlite3PExpr(pParse, TK_ROW, 0, 0);
pEList = sqlite3ExprListAppend(
@@ -128034,9 +131125,9 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
- pSrc->a[0].pTab = 0;
+ pSrc->a[0].pSTab = 0;
pSelectSrc = sqlite3SrcListDup(db, pSrc, 0);
- pSrc->a[0].pTab = pTab;
+ pSrc->a[0].pSTab = pTab;
if( pSrc->a[0].fg.isIndexedBy ){
assert( pSrc->a[0].fg.isCte==0 );
pSrc->a[0].u2.pIBIndex = 0;
@@ -129168,16 +132259,10 @@ static void substrFunc(
int len;
int p0type;
i64 p1, p2;
- int negP2 = 0;
assert( argc==3 || argc==2 );
- if( sqlite3_value_type(argv[1])==SQLITE_NULL
- || (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL)
- ){
- return;
- }
p0type = sqlite3_value_type(argv[0]);
- p1 = sqlite3_value_int(argv[1]);
+ p1 = sqlite3_value_int64(argv[1]);
if( p0type==SQLITE_BLOB ){
len = sqlite3_value_bytes(argv[0]);
z = sqlite3_value_blob(argv[0]);
@@ -129193,28 +132278,31 @@ static void substrFunc(
}
}
}
-#ifdef SQLITE_SUBSTR_COMPATIBILITY
- /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as
- ** as substr(X,1,N) - it returns the first N characters of X. This
- ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8]
- ** from 2009-02-02 for compatibility of applications that exploited the
- ** old buggy behavior. */
- if( p1==0 ) p1 = 1; /* */
-#endif
if( argc==3 ){
- p2 = sqlite3_value_int(argv[2]);
- if( p2<0 ){
- p2 = -p2;
- negP2 = 1;
- }
+ p2 = sqlite3_value_int64(argv[2]);
+ if( p2==0 && sqlite3_value_type(argv[2])==SQLITE_NULL ) return;
}else{
p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
}
+ if( p1==0 ){
+#ifdef SQLITE_SUBSTR_COMPATIBILITY
+ /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as
+ ** as substr(X,1,N) - it returns the first N characters of X. This
+ ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8]
+ ** from 2009-02-02 for compatibility of applications that exploited the
+ ** old buggy behavior. */
+ p1 = 1; /* */
+#endif
+ if( sqlite3_value_type(argv[1])==SQLITE_NULL ) return;
+ }
if( p1<0 ){
p1 += len;
if( p1<0 ){
- p2 += p1;
- if( p2<0 ) p2 = 0;
+ if( p2<0 ){
+ p2 = 0;
+ }else{
+ p2 += p1;
+ }
p1 = 0;
}
}else if( p1>0 ){
@@ -129222,12 +132310,13 @@ static void substrFunc(
}else if( p2>0 ){
p2--;
}
- if( negP2 ){
- p1 -= p2;
- if( p1<0 ){
- p2 += p1;
- p1 = 0;
+ if( p2<0 ){
+ if( p2<-p1 ){
+ p2 = p1;
+ }else{
+ p2 = -p2;
}
+ p1 -= p2;
}
assert( p1>=0 && p2>=0 );
if( p0type!=SQLITE_BLOB ){
@@ -129241,9 +132330,11 @@ static void substrFunc(
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
SQLITE_UTF8);
}else{
- if( p1+p2>len ){
+ if( p1>=len ){
+ p1 = p2 = 0;
+ }else if( p2>len-p1 ){
p2 = len-p1;
- if( p2<0 ) p2 = 0;
+ assert( p2>0 );
}
sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
}
@@ -129254,13 +132345,13 @@ static void substrFunc(
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- int n = 0;
+ i64 n = 0;
double r;
char *zBuf;
assert( argc==1 || argc==2 );
if( argc==2 ){
if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
- n = sqlite3_value_int(argv[1]);
+ n = sqlite3_value_int64(argv[1]);
if( n>30 ) n = 30;
if( n<0 ) n = 0;
}
@@ -129275,7 +132366,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}else if( n==0 ){
r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5)));
}else{
- zBuf = sqlite3_mprintf("%!.*f",n,r);
+ zBuf = sqlite3_mprintf("%!.*f",(int)n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
return;
@@ -129299,7 +132390,7 @@ static void *contextMalloc(sqlite3_context *context, i64 nByte){
sqlite3 *db = sqlite3_context_db_handle(context);
assert( nByte>0 );
testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH] );
- testcase( nByte==db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
+ testcase( nByte==(i64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
z = 0;
@@ -129904,7 +132995,7 @@ static const char hexdigits[] = {
** Append to pStr text that is the SQL literal representation of the
** value contained in pValue.
*/
-SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
+SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue, int bEscape){
/* As currently implemented, the string must be initially empty.
** we might relax this requirement in the future, but that will
** require enhancements to the implementation. */
@@ -129952,7 +133043,7 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
}
case SQLITE_TEXT: {
const unsigned char *zArg = sqlite3_value_text(pValue);
- sqlite3_str_appendf(pStr, "%Q", zArg);
+ sqlite3_str_appendf(pStr, bEscape ? "%#Q" : "%Q", zArg);
break;
}
default: {
@@ -129963,6 +133054,105 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
}
}
+/*
+** Return true if z[] begins with N hexadecimal digits, and write
+** a decoding of those digits into *pVal. Or return false if any
+** one of the first N characters in z[] is not a hexadecimal digit.
+*/
+static int isNHex(const char *z, int N, u32 *pVal){
+ int i;
+ u32 v = 0;
+ for(i=0; i0 ){
+ memmove(&zOut[j], &zIn[i], n);
+ j += n;
+ i += n;
+ }
+ if( zIn[i+1]=='\\' ){
+ i += 2;
+ zOut[j++] = '\\';
+ }else if( sqlite3Isxdigit(zIn[i+1]) ){
+ if( !isNHex(&zIn[i+1], 4, &v) ) goto unistr_error;
+ i += 5;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='+' ){
+ if( !isNHex(&zIn[i+2], 6, &v) ) goto unistr_error;
+ i += 8;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='u' ){
+ if( !isNHex(&zIn[i+2], 4, &v) ) goto unistr_error;
+ i += 6;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else if( zIn[i+1]=='U' ){
+ if( !isNHex(&zIn[i+2], 8, &v) ) goto unistr_error;
+ i += 10;
+ j += sqlite3AppendOneUtf8Character(&zOut[j], v);
+ }else{
+ goto unistr_error;
+ }
+ }
+ zOut[j] = 0;
+ sqlite3_result_text64(context, zOut, j, sqlite3_free, SQLITE_UTF8);
+ return;
+
+unistr_error:
+ sqlite3_free(zOut);
+ sqlite3_result_error(context, "invalid Unicode escape", -1);
+ return;
+}
+
+
/*
** Implementation of the QUOTE() function.
**
@@ -129972,6 +133162,10 @@ SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum *pStr, sqlite3_value *pValue){
** as needed. BLOBs are encoded as hexadecimal literals. Strings with
** embedded NUL characters cannot be represented as string literals in SQL
** and hence the returned string literal is truncated prior to the first NUL.
+**
+** If sqlite3_user_data() is non-zero, then the UNISTR_QUOTE() function is
+** implemented instead. The difference is that UNISTR_QUOTE() uses the
+** UNISTR() function to escape control characters.
*/
static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3_str str;
@@ -129979,7 +133173,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
UNUSED_PARAMETER(argc);
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
- sqlite3QuoteValue(&str,argv[0]);
+ sqlite3QuoteValue(&str,argv[0],SQLITE_PTR_TO_INT(sqlite3_user_data(context)));
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
SQLITE_DYNAMIC);
if( str.accError!=SQLITE_OK ){
@@ -130234,7 +133428,7 @@ static void replaceFunc(
assert( zRep==sqlite3_value_text(argv[2]) );
nOut = nStr + 1;
assert( nOut0 ){
+ if( sqlite3_value_type(argv[i])!=SQLITE_NULL ){
+ int k = sqlite3_value_bytes(argv[i]);
const char *v = (const char*)sqlite3_value_text(argv[i]);
if( v!=0 ){
- if( j>0 && nSep>0 ){
+ if( bNotNull && nSep>0 ){
memcpy(&z[j], zSep, nSep);
j += nSep;
}
memcpy(&z[j], v, k);
j += k;
+ bNotNull = 1;
}
}
}
@@ -130630,7 +133826,7 @@ static void kahanBabuskaNeumaierInit(
** that it returns NULL if it sums over no inputs. TOTAL returns
** 0.0 in that case. In addition, TOTAL always returns a float where
** SUM might return an integer if it never encounters a floating point
-** value. TOTAL never fails, but SUM might through an exception if
+** value. TOTAL never fails, but SUM might throw an exception if
** it overflows an integer.
*/
static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
@@ -130682,7 +133878,10 @@ static void sumInverse(sqlite3_context *context, int argc, sqlite3_value**argv){
assert( p->cnt>0 );
p->cnt--;
if( !p->approx ){
- p->iSum -= sqlite3_value_int64(argv[0]);
+ if( sqlite3SubInt64(&p->iSum, sqlite3_value_int64(argv[0])) ){
+ p->ovrfl = 1;
+ p->approx = 1;
+ }
}else if( type==SQLITE_INTEGER ){
i64 iVal = sqlite3_value_int64(argv[0]);
if( iVal!=SMALLEST_INT64 ){
@@ -130863,7 +134062,11 @@ static void minMaxFinalize(sqlite3_context *context){
** group_concat(EXPR, ?SEPARATOR?)
** string_agg(EXPR, SEPARATOR)
**
-** The SEPARATOR goes before the EXPR string. This is tragic. The
+** Content is accumulated in GroupConcatCtx.str with the SEPARATOR
+** coming before the EXPR value, except for the first entry which
+** omits the SEPARATOR.
+**
+** It is tragic that the SEPARATOR goes before the EXPR string. The
** groupConcatInverse() implementation would have been easier if the
** SEPARATOR were appended after EXPR. And the order is undocumented,
** so we could change it, in theory. But the old behavior has been
@@ -130967,7 +134170,7 @@ static void groupConcatInverse(
/* pGCC is always non-NULL since groupConcatStep() will have always
** run first to initialize it */
if( ALWAYS(pGCC) ){
- int nVS;
+ int nVS; /* Number of characters to remove */
/* Must call sqlite3_value_text() to convert the argument into text prior
** to invoking sqlite3_value_bytes(), in case the text encoding is UTF16 */
(void)sqlite3_value_text(argv[0]);
@@ -131020,6 +134223,8 @@ static void groupConcatValue(sqlite3_context *context){
sqlite3_result_error_toobig(context);
}else if( pAccum->accError==SQLITE_NOMEM ){
sqlite3_result_error_nomem(context);
+ }else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
+ sqlite3_result_text(context, "", 1, SQLITE_STATIC);
}else{
const char *zText = sqlite3_str_value(pAccum);
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
@@ -131338,12 +134543,514 @@ static void signFunc(
sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
}
+#if defined(SQLITE_ENABLE_PERCENTILE)
+/***********************************************************************
+** This section implements the percentile(Y,P) SQL function and similar.
+** Requirements:
+**
+** (1) The percentile(Y,P) function is an aggregate function taking
+** exactly two arguments.
+**
+** (2) If the P argument to percentile(Y,P) is not the same for every
+** row in the aggregate then an error is thrown. The word "same"
+** in the previous sentence means that the value differ by less
+** than 0.001.
+**
+** (3) If the P argument to percentile(Y,P) evaluates to anything other
+** than a number in the range of 0.0 to 100.0 inclusive then an
+** error is thrown.
+**
+** (4) If any Y argument to percentile(Y,P) evaluates to a value that
+** is not NULL and is not numeric then an error is thrown.
+**
+** (5) If any Y argument to percentile(Y,P) evaluates to plus or minus
+** infinity then an error is thrown. (SQLite always interprets NaN
+** values as NULL.)
+**
+** (6) Both Y and P in percentile(Y,P) can be arbitrary expressions,
+** including CASE WHEN expressions.
+**
+** (7) The percentile(Y,P) aggregate is able to handle inputs of at least
+** one million (1,000,000) rows.
+**
+** (8) If there are no non-NULL values for Y, then percentile(Y,P)
+** returns NULL.
+**
+** (9) If there is exactly one non-NULL value for Y, the percentile(Y,P)
+** returns the one Y value.
+**
+** (10) If there N non-NULL values of Y where N is two or more and
+** the Y values are ordered from least to greatest and a graph is
+** drawn from 0 to N-1 such that the height of the graph at J is
+** the J-th Y value and such that straight lines are drawn between
+** adjacent Y values, then the percentile(Y,P) function returns
+** the height of the graph at P*(N-1)/100.
+**
+** (11) The percentile(Y,P) function always returns either a floating
+** point number or NULL.
+**
+** (12) The percentile(Y,P) is implemented as a single C99 source-code
+** file that compiles into a shared-library or DLL that can be loaded
+** into SQLite using the sqlite3_load_extension() interface.
+**
+** (13) A separate median(Y) function is the equivalent percentile(Y,50).
+**
+** (14) A separate percentile_cont(Y,P) function is equivalent to
+** percentile(Y,P/100.0). In other words, the fraction value in
+** the second argument is in the range of 0 to 1 instead of 0 to 100.
+**
+** (15) A separate percentile_disc(Y,P) function is like
+** percentile_cont(Y,P) except that instead of returning the weighted
+** average of the nearest two input values, it returns the next lower
+** value. So the percentile_disc(Y,P) will always return a value
+** that was one of the inputs.
+**
+** (16) All of median(), percentile(Y,P), percentile_cont(Y,P) and
+** percentile_disc(Y,P) can be used as window functions.
+**
+** Differences from standard SQL:
+**
+** * The percentile_cont(X,P) function is equivalent to the following in
+** standard SQL:
+**
+** (percentile_cont(P) WITHIN GROUP (ORDER BY X))
+**
+** The SQLite syntax is much more compact. The standard SQL syntax
+** is also supported if SQLite is compiled with the
+** -DSQLITE_ENABLE_ORDERED_SET_AGGREGATES option.
+**
+** * No median(X) function exists in the SQL standard. App developers
+** are expected to write "percentile_cont(0.5)WITHIN GROUP(ORDER BY X)".
+**
+** * No percentile(Y,P) function exists in the SQL standard. Instead of
+** percential(Y,P), developers must write this:
+** "percentile_cont(P/100.0) WITHIN GROUP (ORDER BY Y)". Note that
+** the fraction parameter to percentile() goes from 0 to 100 whereas
+** the fraction parameter in SQL standard percentile_cont() goes from
+** 0 to 1.
+**
+** Implementation notes as of 2024-08-31:
+**
+** * The regular aggregate-function versions of these routines work
+** by accumulating all values in an array of doubles, then sorting
+** that array using quicksort before computing the answer. Thus
+** the runtime is O(NlogN) where N is the number of rows of input.
+**
+** * For the window-function versions of these routines, the array of
+** inputs is sorted as soon as the first value is computed. Thereafter,
+** the array is kept in sorted order using an insert-sort. This
+** results in O(N*K) performance where K is the size of the window.
+** One can imagine alternative implementations that give O(N*logN*logK)
+** performance, but they require more complex logic and data structures.
+** The developers have elected to keep the asymptotically slower
+** algorithm for now, for simplicity, under the theory that window
+** functions are seldom used and when they are, the window size K is
+** often small. The developers might revisit that decision later,
+** should the need arise.
+*/
+
+/* The following object is the group context for a single percentile()
+** aggregate. Remember all input Y values until the very end.
+** Those values are accumulated in the Percentile.a[] array.
+*/
+typedef struct Percentile Percentile;
+struct Percentile {
+ u64 nAlloc; /* Number of slots allocated for a[] */
+ u64 nUsed; /* Number of slots actually used in a[] */
+ char bSorted; /* True if a[] is already in sorted order */
+ char bKeepSorted; /* True if advantageous to keep a[] sorted */
+ char bPctValid; /* True if rPct is valid */
+ double rPct; /* Fraction. 0.0 to 1.0 */
+ double *a; /* Array of Y values */
+};
+
+/*
+** Return TRUE if the input floating-point number is an infinity.
+*/
+static int percentIsInfinity(double r){
+ sqlite3_uint64 u;
+ assert( sizeof(u)==sizeof(r) );
+ memcpy(&u, &r, sizeof(u));
+ return ((u>>52)&0x7ff)==0x7ff;
+}
+
+/*
+** Return TRUE if two doubles differ by 0.001 or less.
+*/
+static int percentSameValue(double a, double b){
+ a -= b;
+ return a>=-0.001 && a<=0.001;
+}
+
+/*
+** Search p (which must have p->bSorted) looking for an entry with
+** value y. Return the index of that entry.
+**
+** If bExact is true, return -1 if the entry is not found.
+**
+** If bExact is false, return the index at which a new entry with
+** value y should be insert in order to keep the values in sorted
+** order. The smallest return value in this case will be 0, and
+** the largest return value will be p->nUsed.
+*/
+static i64 percentBinarySearch(Percentile *p, double y, int bExact){
+ i64 iFirst = 0; /* First element of search range */
+ i64 iLast = (i64)p->nUsed - 1; /* Last element of search range */
+ while( iLast>=iFirst ){
+ i64 iMid = (iFirst+iLast)/2;
+ double x = p->a[iMid];
+ if( xy ){
+ iLast = iMid - 1;
+ }else{
+ return iMid;
+ }
+ }
+ if( bExact ) return -1;
+ return iFirst;
+}
+
+/*
+** Generate an error for a percentile function.
+**
+** The error format string must have exactly one occurrence of "%%s()"
+** (with two '%' characters). That substring will be replaced by the name
+** of the function.
+*/
+static void percentError(sqlite3_context *pCtx, const char *zFormat, ...){
+ char *zMsg1;
+ char *zMsg2;
+ va_list ap;
+
+ va_start(ap, zFormat);
+ zMsg1 = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+ zMsg2 = zMsg1 ? sqlite3_mprintf(zMsg1, sqlite3VdbeFuncName(pCtx)) : 0;
+ sqlite3_result_error(pCtx, zMsg2, -1);
+ sqlite3_free(zMsg1);
+ sqlite3_free(zMsg2);
+}
+
+/*
+** The "step" function for percentile(Y,P) is called once for each
+** input row.
+*/
+static void percentStep(sqlite3_context *pCtx, int argc, sqlite3_value **argv){
+ Percentile *p;
+ double rPct;
+ int eType;
+ double y;
+ assert( argc==2 || argc==1 );
+
+ if( argc==1 ){
+ /* Requirement 13: median(Y) is the same as percentile(Y,50). */
+ rPct = 0.5;
+ }else{
+ /* P must be a number between 0 and 100 for percentile() or between
+ ** 0.0 and 1.0 for percentile_cont() and percentile_disc().
+ **
+ ** The user-data is an integer which is 10 times the upper bound.
+ */
+ double mxFrac = (SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx))&2)? 100.0 : 1.0;
+ eType = sqlite3_value_numeric_type(argv[1]);
+ rPct = sqlite3_value_double(argv[1])/mxFrac;
+ if( (eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT)
+ || rPct<0.0 || rPct>1.0
+ ){
+ percentError(pCtx, "the fraction argument to %%s()"
+ " is not between 0.0 and %.1f",
+ (double)mxFrac);
+ return;
+ }
+ }
+
+ /* Allocate the session context. */
+ p = (Percentile*)sqlite3_aggregate_context(pCtx, sizeof(*p));
+ if( p==0 ) return;
+
+ /* Remember the P value. Throw an error if the P value is different
+ ** from any prior row, per Requirement (2). */
+ if( !p->bPctValid ){
+ p->rPct = rPct;
+ p->bPctValid = 1;
+ }else if( !percentSameValue(p->rPct,rPct) ){
+ percentError(pCtx, "the fraction argument to %%s()"
+ " is not the same for all input rows");
+ return;
+ }
+
+ /* Ignore rows for which Y is NULL */
+ eType = sqlite3_value_type(argv[0]);
+ if( eType==SQLITE_NULL ) return;
+
+ /* If not NULL, then Y must be numeric. Otherwise throw an error.
+ ** Requirement 4 */
+ if( eType!=SQLITE_INTEGER && eType!=SQLITE_FLOAT ){
+ percentError(pCtx, "input to %%s() is not numeric");
+ return;
+ }
+
+ /* Throw an error if the Y value is infinity or NaN */
+ y = sqlite3_value_double(argv[0]);
+ if( percentIsInfinity(y) ){
+ percentError(pCtx, "Inf input to %%s()");
+ return;
+ }
+
+ /* Allocate and store the Y */
+ if( p->nUsed>=p->nAlloc ){
+ u64 n = p->nAlloc*2 + 250;
+ double *a = sqlite3_realloc64(p->a, sizeof(double)*n);
+ if( a==0 ){
+ sqlite3_free(p->a);
+ memset(p, 0, sizeof(*p));
+ sqlite3_result_error_nomem(pCtx);
+ return;
+ }
+ p->nAlloc = n;
+ p->a = a;
+ }
+ if( p->nUsed==0 ){
+ p->a[p->nUsed++] = y;
+ p->bSorted = 1;
+ }else if( !p->bSorted || y>=p->a[p->nUsed-1] ){
+ p->a[p->nUsed++] = y;
+ }else if( p->bKeepSorted ){
+ i64 i;
+ i = percentBinarySearch(p, y, 0);
+ if( i<(int)p->nUsed ){
+ memmove(&p->a[i+1], &p->a[i], (p->nUsed-i)*sizeof(p->a[0]));
+ }
+ p->a[i] = y;
+ p->nUsed++;
+ }else{
+ p->a[p->nUsed++] = y;
+ p->bSorted = 0;
+ }
+}
+
+/*
+** Interchange two doubles.
+*/
+#define SWAP_DOUBLE(X,Y) {double ttt=(X);(X)=(Y);(Y)=ttt;}
+
+/*
+** Sort an array of doubles.
+**
+** Algorithm: quicksort
+**
+** This is implemented separately rather than using the qsort() routine
+** from the standard library because:
+**
+** (1) To avoid a dependency on qsort()
+** (2) To avoid the function call to the comparison routine for each
+** comparison.
+*/
+static void percentSort(double *a, unsigned int n){
+ int iLt; /* Entries before a[iLt] are less than rPivot */
+ int iGt; /* Entries at or after a[iGt] are greater than rPivot */
+ int i; /* Loop counter */
+ double rPivot; /* The pivot value */
+
+ assert( n>=2 );
+ if( a[0]>a[n-1] ){
+ SWAP_DOUBLE(a[0],a[n-1])
+ }
+ if( n==2 ) return;
+ iGt = n-1;
+ i = n/2;
+ if( a[0]>a[i] ){
+ SWAP_DOUBLE(a[0],a[i])
+ }else if( a[i]>a[iGt] ){
+ SWAP_DOUBLE(a[i],a[iGt])
+ }
+ if( n==3 ) return;
+ rPivot = a[i];
+ iLt = i = 1;
+ do{
+ if( a[i]iLt ) SWAP_DOUBLE(a[i],a[iLt])
+ iLt++;
+ i++;
+ }else if( a[i]>rPivot ){
+ do{
+ iGt--;
+ }while( iGt>i && a[iGt]>rPivot );
+ SWAP_DOUBLE(a[i],a[iGt])
+ }else{
+ i++;
+ }
+ }while( i=2 ) percentSort(a, iLt);
+ if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
+
+/* Uncomment for testing */
+#if 0
+ for(i=0; ibSorted==0 ){
+ assert( p->nUsed>1 );
+ percentSort(p->a, p->nUsed);
+ p->bSorted = 1;
+ }
+ p->bKeepSorted = 1;
+
+ /* Find and remove the row */
+ i = percentBinarySearch(p, y, 1);
+ if( i>=0 ){
+ p->nUsed--;
+ if( i<(int)p->nUsed ){
+ memmove(&p->a[i], &p->a[i+1], (p->nUsed - i)*sizeof(p->a[0]));
+ }
+ }
+}
+
+/*
+** Compute the final output of percentile(). Clean up all allocated
+** memory if and only if bIsFinal is true.
+*/
+static void percentCompute(sqlite3_context *pCtx, int bIsFinal){
+ Percentile *p;
+ int settings = SQLITE_PTR_TO_INT(sqlite3_user_data(pCtx))&1; /* Discrete? */
+ unsigned i1, i2;
+ double v1, v2;
+ double ix, vx;
+ p = (Percentile*)sqlite3_aggregate_context(pCtx, 0);
+ if( p==0 ) return;
+ if( p->a==0 ) return;
+ if( p->nUsed ){
+ if( p->bSorted==0 ){
+ assert( p->nUsed>1 );
+ percentSort(p->a, p->nUsed);
+ p->bSorted = 1;
+ }
+ ix = p->rPct*(p->nUsed-1);
+ i1 = (unsigned)ix;
+ if( settings & 1 ){
+ vx = p->a[i1];
+ }else{
+ i2 = ix==(double)i1 || i1==p->nUsed-1 ? i1 : i1+1;
+ v1 = p->a[i1];
+ v2 = p->a[i2];
+ vx = v1 + (v2-v1)*(ix-i1);
+ }
+ sqlite3_result_double(pCtx, vx);
+ }
+ if( bIsFinal ){
+ sqlite3_free(p->a);
+ memset(p, 0, sizeof(*p));
+ }else{
+ p->bKeepSorted = 1;
+ }
+}
+static void percentFinal(sqlite3_context *pCtx){
+ percentCompute(pCtx, 1);
+}
+static void percentValue(sqlite3_context *pCtx){
+ percentCompute(pCtx, 0);
+}
+/****** End of percentile family of functions ******/
+#endif /* SQLITE_ENABLE_PERCENTILE */
+
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_FILESTAT)
+/*
+** Implementation of sqlite_filestat(SCHEMA).
+**
+** Return JSON text that describes low-level debug/diagnostic information
+** about the sqlite3_file object associated with SCHEMA.
+*/
+static void filestatFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3 *db = sqlite3_context_db_handle(context);
+ const char *zDbName;
+ sqlite3_str *pStr;
+ Btree *pBtree;
+
+ zDbName = (const char*)sqlite3_value_text(argv[0]);
+ pBtree = sqlite3DbNameToBtree(db, zDbName);
+ if( pBtree ){
+ Pager *pPager;
+ sqlite3_file *fd;
+ int rc;
+ sqlite3BtreeEnter(pBtree);
+ pPager = sqlite3BtreePager(pBtree);
+ assert( pPager!=0 );
+ fd = sqlite3PagerFile(pPager);
+ pStr = sqlite3_str_new(db);
+ if( pStr==0 ){
+ sqlite3_result_error_nomem(context);
+ }else{
+ sqlite3_str_append(pStr, "{\"db\":", 6);
+ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr);
+ if( rc ) sqlite3_str_append(pStr, "null", 4);
+ fd = sqlite3PagerJrnlFile(pPager);
+ if( fd && fd->pMethods!=0 ){
+ sqlite3_str_appendall(pStr, ",\"journal\":");
+ rc = sqlite3OsFileControl(fd, SQLITE_FCNTL_FILESTAT, pStr);
+ if( rc ) sqlite3_str_append(pStr, "null", 4);
+ }
+ sqlite3_str_append(pStr, "}", 1);
+ sqlite3_result_text(context, sqlite3_str_finish(pStr), -1,
+ sqlite3_free);
+ }
+ sqlite3BtreeLeave(pBtree);
+ }else{
+ sqlite3_result_text(context, "{}", 2, SQLITE_STATIC);
+ }
+}
+#endif /* SQLITE_DEBUG || SQLITE_ENABLE_FILESTAT */
+
#ifdef SQLITE_DEBUG
/*
** Implementation of fpdecode(x,y,z) function.
**
** x is a real number that is to be decoded. y is the precision.
-** z is the maximum real precision.
+** z is the maximum real precision. Return a string that shows the
+** results of the sqlite3FpDecode() function.
+**
+** Used for testing and debugging only, specifically testing and debugging
+** of the sqlite3FpDecode() function. This SQL function does not appear
+** in production builds. This function is not an API and is subject to
+** modification or removal in future versions of SQLite.
*/
static void fpdecodeFunc(
sqlite3_context *context,
@@ -131359,6 +135066,7 @@ static void fpdecodeFunc(
x = sqlite3_value_double(argv[0]);
y = sqlite3_value_int(argv[1]);
z = sqlite3_value_int(argv[2]);
+ if( z<=0 ) z = 1;
sqlite3FpDecode(&s, x, y, z);
if( s.isSpecial==2 ){
sqlite3_snprintf(sizeof(zBuf), zBuf, "NaN");
@@ -131369,6 +135077,82 @@ static void fpdecodeFunc(
}
#endif /* SQLITE_DEBUG */
+#ifdef SQLITE_DEBUG
+/*
+** Implementation of parseuri(uri,flags) function.
+**
+** Required Arguments:
+** "uri" The URI to parse.
+** "flags" Bitmask of flags, as if to sqlite3_open_v2().
+**
+** Additional arguments beyond the first two make calls to
+** sqlite3_uri_key() for integers and sqlite3_uri_parameter for
+** anything else.
+**
+** The result is a string showing the results of calling sqlite3ParseUri().
+**
+** Used for testing and debugging only, specifically testing and debugging
+** of the sqlite3ParseUri() function. This SQL function does not appear
+** in production builds. This function is not an API and is subject to
+** modification or removal in future versions of SQLite.
+*/
+static void parseuriFunc(
+ sqlite3_context *ctx,
+ int argc,
+ sqlite3_value **argv
+){
+ sqlite3_str *pResult;
+ const char *zVfs;
+ const char *zUri;
+ unsigned int flgs;
+ int rc;
+ sqlite3_vfs *pVfs = 0;
+ char *zFile = 0;
+ char *zErr = 0;
+
+ if( argc<2 ) return;
+ pVfs = sqlite3_vfs_find(0);
+ assert( pVfs );
+ zVfs = pVfs->zName;
+ zUri = (const char*)sqlite3_value_text(argv[0]);
+ if( zUri==0 ) return;
+ flgs = (unsigned int)sqlite3_value_int(argv[1]);
+ rc = sqlite3ParseUri(zVfs, zUri, &flgs, &pVfs, &zFile, &zErr);
+ pResult = sqlite3_str_new(0);
+ if( pResult ){
+ int i;
+ sqlite3_str_appendf(pResult, "rc=%d", rc);
+ sqlite3_str_appendf(pResult, ", flags=0x%x", flgs);
+ sqlite3_str_appendf(pResult, ", vfs=%Q", pVfs ? pVfs->zName: 0);
+ sqlite3_str_appendf(pResult, ", err=%Q", zErr);
+ sqlite3_str_appendf(pResult, ", file=%Q", zFile);
+ if( zFile ){
+ const char *z = zFile;
+ z += sqlite3Strlen30(z)+1;
+ while( z[0] ){
+ sqlite3_str_appendf(pResult, ", %Q", z);
+ z += sqlite3Strlen30(z)+1;
+ }
+ for(i=2; ia;
- pItem->pTab = pFKey->pFrom;
+ pItem->pSTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
- pItem->pTab->nTabRef++;
+ pItem->pSTab->nTabRef++;
pItem->iCursor = pParse->nTab++;
if( regNew!=0 ){
@@ -132900,7 +136697,8 @@ static Trigger *fkActionTrigger(
SrcList *pSrc;
Expr *pRaise;
- pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
+ pRaise = sqlite3Expr(db, TK_STRING, "FOREIGN KEY constraint failed"),
+ pRaise = sqlite3PExpr(pParse, TK_RAISE, pRaise, 0);
if( pRaise ){
pRaise->affExpr = OE_Abort;
}
@@ -132908,7 +136706,8 @@ static Trigger *fkActionTrigger(
if( pSrc ){
assert( pSrc->nSrc==1 );
pSrc->a[0].zName = sqlite3DbStrDup(db, zFrom);
- pSrc->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
+ assert( pSrc->a[0].fg.fixedSchema==0 && pSrc->a[0].fg.isSubquery==0 );
+ pSrc->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
}
pSelect = sqlite3SelectNew(pParse,
sqlite3ExprListAppend(pParse, 0, pRaise),
@@ -133242,12 +137041,15 @@ SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
** by one slot and insert a new OP_TypeCheck where the current
** OP_MakeRecord is found */
VdbeOp *pPrev;
+ int p3;
sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
pPrev = sqlite3VdbeGetLastOp(v);
assert( pPrev!=0 );
assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed );
pPrev->opcode = OP_TypeCheck;
- sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3);
+ p3 = pPrev->p3;
+ pPrev->p3 = 0;
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, p3);
}else{
/* Insert an isolated OP_Typecheck */
sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol);
@@ -133642,8 +137444,11 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
SQLITE_PRIVATE void sqlite3MultiValuesEnd(Parse *pParse, Select *pVal){
if( ALWAYS(pVal) && pVal->pSrc->nSrc>0 ){
SrcItem *pItem = &pVal->pSrc->a[0];
- sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->regReturn);
- sqlite3VdbeJumpHere(pParse->pVdbe, pItem->addrFillSub - 1);
+ assert( (pItem->fg.isSubquery && pItem->u4.pSubq!=0) || pParse->nErr );
+ if( pItem->fg.isSubquery ){
+ sqlite3VdbeEndCoroutine(pParse->pVdbe, pItem->u4.pSubq->regReturn);
+ sqlite3VdbeJumpHere(pParse->pVdbe, pItem->u4.pSubq->addrFillSub - 1);
+ }
}
}
@@ -133747,7 +137552,7 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
f = (f & pLeft->selFlags);
}
pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0);
- pLeft->selFlags &= ~SF_MultiValue;
+ pLeft->selFlags &= ~(u32)SF_MultiValue;
if( pSelect ){
pSelect->op = TK_ALL;
pSelect->pPrior = pLeft;
@@ -133771,36 +137576,42 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
if( pRet ){
SelectDest dest;
+ Subquery *pSubq;
pRet->pSrc->nSrc = 1;
pRet->pPrior = pLeft->pPrior;
pRet->op = pLeft->op;
+ if( pRet->pPrior ) pRet->selFlags |= SF_Values;
pLeft->pPrior = 0;
pLeft->op = TK_SELECT;
assert( pLeft->pNext==0 );
assert( pRet->pNext==0 );
p = &pRet->pSrc->a[0];
- p->pSelect = pLeft;
p->fg.viaCoroutine = 1;
- p->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
- p->regReturn = ++pParse->nMem;
p->iCursor = -1;
+ assert( !p->fg.isIndexedBy && !p->fg.isTabFunc );
p->u1.nRow = 2;
- sqlite3VdbeAddOp3(v,OP_InitCoroutine,p->regReturn,0,p->addrFillSub);
- sqlite3SelectDestInit(&dest, SRT_Coroutine, p->regReturn);
+ if( sqlite3SrcItemAttachSubquery(pParse, p, pLeft, 0) ){
+ pSubq = p->u4.pSubq;
+ pSubq->addrFillSub = sqlite3VdbeCurrentAddr(v) + 1;
+ pSubq->regReturn = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine,
+ pSubq->regReturn, 0, pSubq->addrFillSub);
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn);
- /* Allocate registers for the output of the co-routine. Do so so
- ** that there are two unused registers immediately before those
- ** used by the co-routine. This allows the code in sqlite3Insert()
- ** to use these registers directly, instead of copying the output
- ** of the co-routine to a separate array for processing. */
- dest.iSdst = pParse->nMem + 3;
- dest.nSdst = pLeft->pEList->nExpr;
- pParse->nMem += 2 + dest.nSdst;
+ /* Allocate registers for the output of the co-routine. Do so so
+ ** that there are two unused registers immediately before those
+ ** used by the co-routine. This allows the code in sqlite3Insert()
+ ** to use these registers directly, instead of copying the output
+ ** of the co-routine to a separate array for processing. */
+ dest.iSdst = pParse->nMem + 3;
+ dest.nSdst = pLeft->pEList->nExpr;
+ pParse->nMem += 2 + dest.nSdst;
- pLeft->selFlags |= SF_MultiValue;
- sqlite3Select(pParse, pLeft, &dest);
- p->regResult = dest.iSdst;
- assert( pParse->nErr || dest.iSdst>0 );
+ pLeft->selFlags |= SF_MultiValue;
+ sqlite3Select(pParse, pLeft, &dest);
+ pSubq->regResult = dest.iSdst;
+ assert( pParse->nErr || dest.iSdst>0 );
+ }
pLeft = pRet;
}
}else{
@@ -133810,12 +137621,18 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
}
if( pParse->nErr==0 ){
+ Subquery *pSubq;
assert( p!=0 );
- if( p->pSelect->pEList->nExpr!=pRow->nExpr ){
- sqlite3SelectWrongNumTermsError(pParse, p->pSelect);
+ assert( p->fg.isSubquery );
+ pSubq = p->u4.pSubq;
+ assert( pSubq!=0 );
+ assert( pSubq->pSelect!=0 );
+ assert( pSubq->pSelect->pEList!=0 );
+ if( pSubq->pSelect->pEList->nExpr!=pRow->nExpr ){
+ sqlite3SelectWrongNumTermsError(pParse, pSubq->pSelect);
}else{
- sqlite3ExprCodeExprList(pParse, pRow, p->regResult, 0, 0);
- sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, p->regReturn);
+ sqlite3ExprCodeExprList(pParse, pRow, pSubq->regResult, 0, 0);
+ sqlite3VdbeAddOp1(pParse->pVdbe, OP_Yield, pSubq->regReturn);
}
}
sqlite3ExprListDelete(pParse->db, pRow);
@@ -133969,6 +137786,7 @@ SQLITE_PRIVATE void sqlite3Insert(
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int *aRegIdx = 0; /* One register allocated to each index */
+ int *aTabColMap = 0; /* Mapping from pTab columns to pCol entries */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to insert into a view */
@@ -134113,31 +137931,25 @@ SQLITE_PRIVATE void sqlite3Insert(
*/
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
if( pColumn ){
- assert( pColumn->eU4!=EU4_EXPR );
- pColumn->eU4 = EU4_IDX;
+ aTabColMap = sqlite3DbMallocZero(db, pTab->nCol*sizeof(int));
+ if( aTabColMap==0 ) goto insert_cleanup;
for(i=0; inId; i++){
- pColumn->a[i].u4.idx = -1;
- }
- for(i=0; inId; i++){
- for(j=0; jnCol; j++){
- if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
- pColumn->a[i].u4.idx = j;
- if( i!=j ) bIdListInOrder = 0;
- if( j==pTab->iPKey ){
- ipkColumn = i; assert( !withoutRowid );
- }
-#ifndef SQLITE_OMIT_GENERATED_COLUMNS
- if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
- sqlite3ErrorMsg(pParse,
- "cannot INSERT into generated column \"%s\"",
- pTab->aCol[j].zCnName);
- goto insert_cleanup;
- }
-#endif
- break;
+ j = sqlite3ColumnIndex(pTab, pColumn->a[i].zName);
+ if( j>=0 ){
+ if( aTabColMap[j]==0 ) aTabColMap[j] = i+1;
+ if( i!=j ) bIdListInOrder = 0;
+ if( j==pTab->iPKey ){
+ ipkColumn = i; assert( !withoutRowid );
}
- }
- if( j>=pTab->nCol ){
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
+ sqlite3ErrorMsg(pParse,
+ "cannot INSERT into generated column \"%s\"",
+ pTab->aCol[j].zCnName);
+ goto insert_cleanup;
+ }
+#endif
+ }else{
if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
ipkColumn = i;
bIdListInOrder = 0;
@@ -134166,9 +137978,14 @@ SQLITE_PRIVATE void sqlite3Insert(
&& pSelect->pPrior==0
){
SrcItem *pItem = &pSelect->pSrc->a[0];
- dest.iSDParm = pItem->regReturn;
- regFromSelect = pItem->regResult;
- nColumn = pItem->pSelect->pEList->nExpr;
+ Subquery *pSubq;
+ assert( pItem->fg.isSubquery );
+ pSubq = pItem->u4.pSubq;
+ dest.iSDParm = pSubq->regReturn;
+ regFromSelect = pSubq->regResult;
+ assert( pSubq->pSelect!=0 );
+ assert( pSubq->pSelect->pEList!=0 );
+ nColumn = pSubq->pSelect->pEList->nExpr;
ExplainQueryPlan((pParse, 0, "SCAN %S", pItem));
if( bIdListInOrder && nColumn==pTab->nCol ){
regData = regFromSelect;
@@ -134430,7 +138247,7 @@ SQLITE_PRIVATE void sqlite3Insert(
continue;
}else if( pColumn==0 ){
/* Hidden columns that are not explicitly named in the INSERT
- ** get there default value */
+ ** get their default value */
sqlite3ExprCodeFactorable(pParse,
sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
iRegStore);
@@ -134438,9 +138255,9 @@ SQLITE_PRIVATE void sqlite3Insert(
}
}
if( pColumn ){
- assert( pColumn->eU4==EU4_IDX );
- for(j=0; jnId && pColumn->a[j].u4.idx!=i; j++){}
- if( j>=pColumn->nId ){
+ j = aTabColMap[i];
+ assert( j>=0 && j<=pColumn->nId );
+ if( j==0 ){
/* A column not named in the insert column list gets its
** default value */
sqlite3ExprCodeFactorable(pParse,
@@ -134448,7 +138265,7 @@ SQLITE_PRIVATE void sqlite3Insert(
iRegStore);
continue;
}
- k = j;
+ k = j - 1;
}else if( nColumn==0 ){
/* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
sqlite3ExprCodeFactorable(pParse,
@@ -134693,7 +138510,10 @@ insert_cleanup:
sqlite3ExprListDelete(db, pList);
sqlite3UpsertDelete(db, pUpsert);
sqlite3SelectDelete(db, pSelect);
- sqlite3IdListDelete(db, pColumn);
+ if( pColumn ){
+ sqlite3IdListDelete(db, pColumn);
+ sqlite3DbFree(db, aTabColMap);
+ }
if( aRegIdx ) sqlite3DbNNFreeNN(db, aRegIdx);
}
@@ -135152,7 +138972,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
** could happen in any order, but they are grouped up front for
** convenience.
**
- ** 2018-08-14: Ticket https://www.sqlite.org/src/info/908f001483982c43
+ ** 2018-08-14: Ticket https://sqlite.org/src/info/908f001483982c43
** The order of constraints used to have OE_Update as (2) and OE_Abort
** and so forth as (1). But apparently PostgreSQL checks the OE_Update
** constraint before any others, so it had to be moved.
@@ -136088,7 +139908,7 @@ static int xferOptimization(
if( pSelect->pSrc->nSrc!=1 ){
return 0; /* FROM clause must have exactly one term */
}
- if( pSelect->pSrc->a[0].pSelect ){
+ if( pSelect->pSrc->a[0].fg.isSubquery ){
return 0; /* FROM clause cannot contain a subquery */
}
if( pSelect->pWhere ){
@@ -136962,6 +140782,12 @@ struct sqlite3_api_routines {
/* Version 3.44.0 and later */
void *(*get_clientdata)(sqlite3*,const char*);
int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*));
+ /* Version 3.50.0 and later */
+ int (*setlk_timeout)(sqlite3*,int,int);
+ /* Version 3.51.0 and later */
+ int (*set_errmsg)(sqlite3*,int,const char*);
+ int (*db_status64)(sqlite3*,int,sqlite3_int64*,sqlite3_int64*,int);
+
};
/*
@@ -137295,6 +141121,11 @@ typedef int (*sqlite3_loadext_entry)(
/* Version 3.44.0 and later */
#define sqlite3_get_clientdata sqlite3_api->get_clientdata
#define sqlite3_set_clientdata sqlite3_api->set_clientdata
+/* Version 3.50.0 and later */
+#define sqlite3_setlk_timeout sqlite3_api->setlk_timeout
+/* Version 3.51.0 and later */
+#define sqlite3_set_errmsg sqlite3_api->set_errmsg
+#define sqlite3_db_status64 sqlite3_api->db_status64
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -137816,7 +141647,12 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_stmt_explain,
/* Version 3.44.0 and later */
sqlite3_get_clientdata,
- sqlite3_set_clientdata
+ sqlite3_set_clientdata,
+ /* Version 3.50.0 and later */
+ sqlite3_setlk_timeout,
+ /* Version 3.51.0 and later */
+ sqlite3_set_errmsg,
+ sqlite3_db_status64
};
/* True if x is the directory separator character
@@ -138338,48 +142174,48 @@ static const char *const pragCName[] = {
/* 13 */ "pk",
/* 14 */ "hidden",
/* table_info reuses 8 */
- /* 15 */ "schema", /* Used by: table_list */
- /* 16 */ "name",
+ /* 15 */ "name", /* Used by: function_list */
+ /* 16 */ "builtin",
/* 17 */ "type",
- /* 18 */ "ncol",
- /* 19 */ "wr",
- /* 20 */ "strict",
- /* 21 */ "seqno", /* Used by: index_xinfo */
- /* 22 */ "cid",
- /* 23 */ "name",
- /* 24 */ "desc",
- /* 25 */ "coll",
- /* 26 */ "key",
- /* 27 */ "name", /* Used by: function_list */
- /* 28 */ "builtin",
- /* 29 */ "type",
- /* 30 */ "enc",
- /* 31 */ "narg",
- /* 32 */ "flags",
- /* 33 */ "tbl", /* Used by: stats */
- /* 34 */ "idx",
- /* 35 */ "wdth",
- /* 36 */ "hght",
- /* 37 */ "flgs",
- /* 38 */ "seq", /* Used by: index_list */
- /* 39 */ "name",
- /* 40 */ "unique",
- /* 41 */ "origin",
- /* 42 */ "partial",
+ /* 18 */ "enc",
+ /* 19 */ "narg",
+ /* 20 */ "flags",
+ /* 21 */ "schema", /* Used by: table_list */
+ /* 22 */ "name",
+ /* 23 */ "type",
+ /* 24 */ "ncol",
+ /* 25 */ "wr",
+ /* 26 */ "strict",
+ /* 27 */ "seqno", /* Used by: index_xinfo */
+ /* 28 */ "cid",
+ /* 29 */ "name",
+ /* 30 */ "desc",
+ /* 31 */ "coll",
+ /* 32 */ "key",
+ /* 33 */ "seq", /* Used by: index_list */
+ /* 34 */ "name",
+ /* 35 */ "unique",
+ /* 36 */ "origin",
+ /* 37 */ "partial",
+ /* 38 */ "tbl", /* Used by: stats */
+ /* 39 */ "idx",
+ /* 40 */ "wdth",
+ /* 41 */ "hght",
+ /* 42 */ "flgs",
/* 43 */ "table", /* Used by: foreign_key_check */
/* 44 */ "rowid",
/* 45 */ "parent",
/* 46 */ "fkid",
- /* index_info reuses 21 */
- /* 47 */ "seq", /* Used by: database_list */
- /* 48 */ "name",
- /* 49 */ "file",
- /* 50 */ "busy", /* Used by: wal_checkpoint */
- /* 51 */ "log",
- /* 52 */ "checkpointed",
- /* collation_list reuses 38 */
+ /* 47 */ "busy", /* Used by: wal_checkpoint */
+ /* 48 */ "log",
+ /* 49 */ "checkpointed",
+ /* 50 */ "seq", /* Used by: database_list */
+ /* 51 */ "name",
+ /* 52 */ "file",
+ /* index_info reuses 27 */
/* 53 */ "database", /* Used by: lock_status */
/* 54 */ "status",
+ /* collation_list reuses 33 */
/* 55 */ "cache_size", /* Used by: default_cache_size */
/* module_list pragma_list reuses 9 */
/* 56 */ "timeout", /* Used by: busy_timeout */
@@ -138472,7 +142308,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "collation_list",
/* ePragTyp: */ PragTyp_COLLATION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 38, 2,
+ /* ColNames: */ 33, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
@@ -138507,7 +142343,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "database_list",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 47, 3,
+ /* ColNames: */ 50, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
@@ -138587,7 +142423,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "function_list",
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 27, 6,
+ /* ColNames: */ 15, 6,
/* iArg: */ 0 },
#endif
#endif
@@ -138616,17 +142452,17 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "index_info",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 21, 3,
+ /* ColNames: */ 27, 3,
/* iArg: */ 0 },
{/* zName: */ "index_list",
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 38, 5,
+ /* ColNames: */ 33, 5,
/* iArg: */ 0 },
{/* zName: */ "index_xinfo",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 21, 6,
+ /* ColNames: */ 27, 6,
/* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
@@ -138805,7 +142641,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 33, 5,
+ /* ColNames: */ 38, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -138824,7 +142660,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "table_list",
/* ePragTyp: */ PragTyp_TABLE_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
- /* ColNames: */ 15, 6,
+ /* ColNames: */ 21, 6,
/* iArg: */ 0 },
{/* zName: */ "table_xinfo",
/* ePragTyp: */ PragTyp_TABLE_INFO,
@@ -138901,7 +142737,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
- /* ColNames: */ 50, 3,
+ /* ColNames: */ 47, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -138923,7 +142759,7 @@ static const PragmaName aPragmaName[] = {
** the following macro or to the actual analysis_limit if it is non-zero,
** in order to prevent PRAGMA optimize from running for too long.
**
-** The value of 2000 is chosen emperically so that the worst-case run-time
+** The value of 2000 is chosen empirically so that the worst-case run-time
** for PRAGMA optimize does not exceed 100 milliseconds against a variety
** of test databases on a RaspberryPI-4 compiled using -Os and without
** -DSQLITE_DEBUG. Of course, your mileage may vary. For the purpose of
@@ -139278,6 +143114,22 @@ static int integrityCheckResultRow(Vdbe *v){
return addr;
}
+/*
+** Should table pTab be skipped when doing an integrity_check?
+** Return true or false.
+**
+** If pObjTab is not null, the return true if pTab matches pObjTab.
+**
+** If pObjTab is null, then return true only if pTab is an imposter table.
+*/
+static int tableSkipIntegrityCheck(const Table *pTab, const Table *pObjTab){
+ if( pObjTab ){
+ return pTab!=pObjTab;
+ }else{
+ return (pTab->tabFlags & TF_Imposter)!=0;
+ }
+}
+
/*
** Process a pragma statement.
**
@@ -140031,12 +143883,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
** in auto-commit mode. */
mask &= ~(SQLITE_ForeignKeys);
}
-#if SQLITE_USER_AUTHENTICATION
- if( db->auth.authLevel==UAUTH_User ){
- /* Do not allow non-admin users to modify the schema arbitrarily */
- mask &= ~(SQLITE_WriteSchema);
- }
-#endif
if( sqlite3GetBoolean(zRight, 0) ){
if( (mask & SQLITE_WriteSchema)==0
@@ -140046,7 +143892,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}else{
db->flags &= ~mask;
- if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
+ if( mask==SQLITE_DeferFKs ){
+ db->nDeferredImmCons = 0;
+ db->nDeferredCons = 0;
+ }
if( (mask & SQLITE_WriteSchema)!=0
&& sqlite3_stricmp(zRight, "reset")==0
){
@@ -140172,7 +144021,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
if( zSql ){
sqlite3_stmt *pDummy = 0;
- (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
+ (void)sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_DONT_LOG,
+ &pDummy, 0);
(void)sqlite3_finalize(pDummy);
sqlite3DbFree(db, zSql);
}
@@ -140625,7 +144475,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
Table *pTab = sqliteHashData(x); /* Current table */
Index *pIdx; /* An index on pTab */
int nIdx; /* Number of indexes on pTab */
- if( pObjTab && pObjTab!=pTab ) continue;
+ if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
if( HasRowid(pTab) ) cnt++;
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
}
@@ -140638,7 +144488,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx;
- if( pObjTab && pObjTab!=pTab ) continue;
+ if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
aRoot[++cnt] = pIdx->tnum;
@@ -140648,11 +144498,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Make sure sufficient number of registers have been allocated */
sqlite3TouchRegister(pParse, 8+cnt);
+ sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt);
sqlite3ClearTempRegCache(pParse);
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY);
- sqlite3VdbeChangeP5(v, (u8)i);
+ sqlite3VdbeChangeP5(v, (u16)i);
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
@@ -140668,7 +144519,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
int iTab = 0;
Table *pTab = sqliteHashData(x);
Index *pIdx;
- if( pObjTab && pObjTab!=pTab ) continue;
+ if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
if( HasRowid(pTab) ){
iTab = cnt++;
}else{
@@ -140704,7 +144555,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
int r2; /* Previous key for WITHOUT ROWID tables */
int mxCol; /* Maximum non-virtual column number */
- if( pObjTab && pObjTab!=pTab ) continue;
+ if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
if( !IsOrdinaryTable(pTab) ) continue;
if( isQuick || HasRowid(pTab) ){
pPk = 0;
@@ -141028,7 +144879,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
Table *pTab = sqliteHashData(x);
sqlite3_vtab *pVTab;
int a1;
- if( pObjTab && pObjTab!=pTab ) continue;
+ if( tableSkipIntegrityCheck(pTab,pObjTab) ) continue;
if( IsOrdinaryTable(pTab) ) continue;
if( !IsVirtual(pTab) ) continue;
if( pTab->nCol<=0 ){
@@ -141260,6 +145111,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
eMode = SQLITE_CHECKPOINT_RESTART;
}else if( sqlite3StrICmp(zRight, "truncate")==0 ){
eMode = SQLITE_CHECKPOINT_TRUNCATE;
+ }else if( sqlite3StrICmp(zRight, "noop")==0 ){
+ eMode = SQLITE_CHECKPOINT_NOOP;
}
}
pParse->nMem = 3;
@@ -142272,14 +146125,7 @@ SQLITE_PRIVATE int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFl
#else
encoding = SQLITE_UTF8;
#endif
- if( db->nVdbeActive>0 && encoding!=ENC(db)
- && (db->mDbFlags & DBFLAG_Vacuum)==0
- ){
- rc = SQLITE_LOCKED;
- goto initone_error_out;
- }else{
- sqlite3SetTextEncoding(db, encoding);
- }
+ sqlite3SetTextEncoding(db, encoding);
}else{
/* If opening an attached database, the encoding much match ENC(db) */
if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){
@@ -142833,9 +146679,11 @@ static int sqlite3LockAndPrepare(
rc = sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
assert( rc==SQLITE_OK || *ppStmt==0 );
if( rc==SQLITE_OK || db->mallocFailed ) break;
- }while( (rc==SQLITE_ERROR_RETRY && (cnt++)errMask)==rc );
db->busyHandler.nBusy = 0;
@@ -142973,12 +146821,24 @@ static int sqlite3Prepare16(
if( !sqlite3SafetyCheckOk(db)||zSql==0 ){
return SQLITE_MISUSE_BKPT;
}
+
+ /* Make sure nBytes is non-negative and correct. It should be the
+ ** number of bytes until the end of the input buffer or until the first
+ ** U+0000 character. If the input nBytes is odd, convert it into
+ ** an even number. If the input nBytes is negative, then the input
+ ** must be terminated by at least one U+0000 character */
if( nBytes>=0 ){
int sz;
const char *z = (const char*)zSql;
for(sz=0; szmutex);
zSql8 = sqlite3Utf16to8(db, zSql, nBytes, SQLITE_UTF16NATIVE);
if( zSql8 ){
@@ -142992,7 +146852,7 @@ static int sqlite3Prepare16(
** the same number of characters into the UTF-16 string.
*/
int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
- *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
+ *pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, nBytes, chars_parsed);
}
sqlite3DbFree(db, zSql8);
rc = sqlite3ApiExit(db, rc);
@@ -143208,7 +147068,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
- if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
+ if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
@@ -143373,10 +147233,33 @@ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *p
*/
SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
int i;
- u8 h = sqlite3StrIHash(zCol);
- Column *pCol;
- for(pCol=pTab->aCol, i=0; inCol; pCol++, i++){
- if( pCol->hName==h && sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i;
+ u8 h;
+ const Column *aCol;
+ int nCol;
+
+ h = sqlite3StrIHash(zCol);
+ aCol = pTab->aCol;
+ nCol = pTab->nCol;
+
+ /* See if the aHx gives us a lucky match */
+ i = pTab->aHx[h % sizeof(pTab->aHx)];
+ assert( i=nCol ) break;
}
return -1;
}
@@ -143386,11 +147269,13 @@ SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol){
*/
SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){
assert( pItem!=0 );
- assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem) );
if( pItem->fg.isNestedFrom ){
ExprList *pResults;
- assert( pItem->pSelect!=0 );
- pResults = pItem->pSelect->pEList;
+ assert( pItem->fg.isSubquery );
+ assert( pItem->u4.pSubq!=0 );
+ assert( pItem->u4.pSubq->pSelect!=0 );
+ pResults = pItem->u4.pSubq->pSelect->pEList;
assert( pResults!=0 );
assert( iCol>=0 && iColnExpr );
pResults->a[iCol].fg.bUsed = 1;
@@ -143413,7 +147298,7 @@ static int tableAndColumnIndex(
int iEnd, /* Last member of pSrc->a[] to check */
const char *zCol, /* Name of the column we are looking for */
int *piTab, /* Write index of pSrc->a[] here */
- int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+ int *piCol, /* Write index of pSrc->a[*piTab].pSTab->aCol[] here */
int bIgnoreHidden /* Ignore hidden columns */
){
int i; /* For looping over tables in pSrc */
@@ -143424,9 +147309,9 @@ static int tableAndColumnIndex(
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
for(i=iStart; i<=iEnd; i++){
- iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
+ iCol = sqlite3ColumnIndex(pSrc->a[i].pSTab, zCol);
if( iCol>=0
- && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
+ && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pSTab->aCol[iCol])==0)
){
if( piTab ){
sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
@@ -143472,8 +147357,7 @@ SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
p->w.iJoin = iTable;
- if( p->op==TK_FUNCTION ){
- assert( ExprUseXList(p) );
+ if( ExprUseXList(p) ){
if( p->x.pList ){
int i;
for(i=0; ix.pList->nExpr; i++){
@@ -143555,10 +147439,10 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for(i=0; inSrc-1; i++, pRight++, pLeft++){
- Table *pRightTab = pRight->pTab;
+ Table *pRightTab = pRight->pSTab;
u32 joinType;
- if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
+ if( NEVER(pLeft->pSTab==0 || pRightTab==0) ) continue;
joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON;
/* If this is a NATURAL join, synthesize an appropriate USING clause
@@ -143625,7 +147509,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
}
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
- if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
+ if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 && pParse->nErr==0 ){
/* This branch runs if the query contains one or more RIGHT or FULL
** JOINs. If only a single table on the left side of this join
** contains the zName column, then this branch is a no-op.
@@ -143641,6 +147525,8 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
*/
ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */
static const Token tkCoalesce = { "coalesce", 8 };
+ assert( pE1!=0 );
+ ExprSetProperty(pE1, EP_CanBeNull);
while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol,
pRight->fg.isSynthUsing)!=0 ){
if( pSrc->a[iLeft].fg.isUsing==0
@@ -143657,7 +147543,13 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
if( pFuncArgs ){
pFuncArgs = sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
pE1 = sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0);
+ if( pE1 ){
+ pE1->affExpr = SQLITE_AFF_DEFER;
+ }
}
+ }else if( (pSrc->a[i+1].fg.jointype & JT_LEFT)!=0 && pParse->nErr==0 ){
+ assert( pE1!=0 );
+ ExprSetProperty(pE1, EP_CanBeNull);
}
pE2 = sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
sqlite3SrcItemColumnUsed(pRight, iRightCol);
@@ -143681,6 +147573,7 @@ static int sqlite3ProcessJoin(Parse *pParse, Select *p){
p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn);
pRight->u3.pOn = 0;
pRight->fg.isOn = 1;
+ p->selFlags |= SF_OnToWhere;
}
}
return 0;
@@ -144431,12 +148324,18 @@ static void selectInnerLoop(
** case the order does matter */
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
+ pDest->iSDParm2 = 0; /* Signal that any Bloom filter is unpopulated */
}else{
int r1 = sqlite3GetTempReg(pParse);
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
+ if( pDest->iSDParm2 ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+ regResult, nResultCol);
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+ }
sqlite3ReleaseTempReg(pParse, r1);
}
break;
@@ -144460,9 +148359,14 @@ static void selectInnerLoop(
assert( nResultCol<=pDest->nSdst );
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
+ pDest->iSDParm = regResult;
}else{
assert( nResultCol==pDest->nSdst );
- assert( regResult==iParm );
+ if( regResult!=iParm ){
+ /* This occurs in cases where the SELECT had both a DISTINCT and
+ ** an OFFSET clause. */
+ sqlite3VdbeAddOp3(v, OP_Copy, regResult, iParm, nResultCol-1);
+ }
/* The LIMIT clause will jump out of the loop for us */
}
break;
@@ -144560,8 +148464,11 @@ static void selectInnerLoop(
** X extra columns.
*/
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
- int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
- KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
+ int nExtra = (N+X)*(sizeof(CollSeq*)+1);
+ KeyInfo *p;
+ assert( X>=0 );
+ if( NEVER(N+X>0xffff) ) return (KeyInfo*)sqlite3OomFault(db);
+ p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra);
if( p ){
p->aSortFlags = (u8*)&p->aColl[N+X];
p->nKeyField = (u16)N;
@@ -144569,7 +148476,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
p->enc = ENC(db);
p->db = db;
p->nRef = 1;
- memset(&p[1], 0, nExtra);
+ memset(p->aColl, 0, nExtra);
}else{
return (KeyInfo*)sqlite3OomFault(db);
}
@@ -144978,8 +148885,12 @@ static const char *columnTypeImpl(
SrcList *pTabList = pNC->pSrcList;
for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
if( jnSrc ){
- pTab = pTabList->a[j].pTab;
- pS = pTabList->a[j].pSelect;
+ pTab = pTabList->a[j].pSTab;
+ if( pTabList->a[j].fg.isSubquery ){
+ pS = pTabList->a[j].u4.pSubq->pSelect;
+ }else{
+ pS = 0;
+ }
}else{
pNC = pNC->pNext;
}
@@ -145124,6 +149035,10 @@ static void generateColumnTypes(
#endif
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
}
+#else
+ UNUSED_PARAMETER(pParse);
+ UNUSED_PARAMETER(pTabList);
+ UNUSED_PARAMETER(pEList);
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
}
@@ -145546,7 +149461,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
p->iLimit = iLimit = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
assert( v!=0 );
- if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
+ if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
@@ -146026,7 +149941,7 @@ static int multiSelect(
p->pPrior = pPrior;
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
if( p->pLimit
- && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
+ && sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){
p->nSelectRow = sqlite3LogEst((u64)nLimit);
@@ -146043,8 +149958,10 @@ static int multiSelect(
int priorOp; /* The SRT_ operation to apply to prior selects */
Expr *pLimit; /* Saved values of p->nLimit */
int addr;
+ int emptyBypass = 0; /* IfEmpty opcode to bypass RHS */
SelectDest uniondest;
+
testcase( p->op==TK_EXCEPT );
testcase( p->op==TK_UNION );
priorOp = SRT_Union;
@@ -146082,6 +149999,8 @@ static int multiSelect(
*/
if( p->op==TK_EXCEPT ){
op = SRT_Except;
+ emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, unionTab);
+ VdbeCoverage(v);
}else{
assert( p->op==TK_UNION );
op = SRT_Union;
@@ -146102,6 +150021,7 @@ static int multiSelect(
if( p->op==TK_UNION ){
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
}
+ if( emptyBypass ) sqlite3VdbeJumpHere(v, emptyBypass);
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->iLimit = 0;
@@ -146132,9 +150052,10 @@ static int multiSelect(
int tab1, tab2;
int iCont, iBreak, iStart;
Expr *pLimit;
- int addr;
+ int addr, iLimit, iOffset;
SelectDest intersectdest;
int r1;
+ int emptyBypass;
/* INTERSECT is different from the others since it requires
** two temporary tables. Hence it has its own case. Begin
@@ -146159,14 +150080,28 @@ static int multiSelect(
goto multi_select_end;
}
+ /* Initialize LIMIT counters before checking to see if the LHS
+ ** is empty, in case the jump is taken */
+ iBreak = sqlite3VdbeMakeLabel(pParse);
+ computeLimitRegisters(pParse, p, iBreak);
+ emptyBypass = sqlite3VdbeAddOp1(v, OP_IfEmpty, tab1); VdbeCoverage(v);
+
/* Code the current SELECT into temporary table "tab2"
*/
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
assert( p->addrOpenEphm[1] == -1 );
p->addrOpenEphm[1] = addr;
- p->pPrior = 0;
+
+ /* Disable prior SELECTs and the LIMIT counters during the computation
+ ** of the RHS select */
pLimit = p->pLimit;
+ iLimit = p->iLimit;
+ iOffset = p->iOffset;
+ p->pPrior = 0;
p->pLimit = 0;
+ p->iLimit = 0;
+ p->iOffset = 0;
+
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
sqlite3SelectOpName(p->op)));
@@ -146179,19 +150114,21 @@ static int multiSelect(
p->nSelectRow = pPrior->nSelectRow;
}
sqlite3ExprDelete(db, p->pLimit);
+
+ /* Reinstate the LIMIT counters prior to running the final intersect */
p->pLimit = pLimit;
+ p->iLimit = iLimit;
+ p->iOffset = iOffset;
/* Generate code to take the intersection of the two temporary
** tables.
*/
if( rc ) break;
assert( p->pEList );
- iBreak = sqlite3VdbeMakeLabel(pParse);
- iCont = sqlite3VdbeMakeLabel(pParse);
- computeLimitRegisters(pParse, p, iBreak);
- sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
+ sqlite3VdbeAddOp1(v, OP_Rewind, tab1);
r1 = sqlite3GetTempReg(pParse);
iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
+ iCont = sqlite3VdbeMakeLabel(pParse);
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r1);
@@ -146201,6 +150138,7 @@ static int multiSelect(
sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); VdbeCoverage(v);
sqlite3VdbeResolveLabel(v, iBreak);
sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
+ sqlite3VdbeJumpHere(v, emptyBypass);
sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
break;
}
@@ -146266,6 +150204,7 @@ static int multiSelect(
multi_select_end:
pDest->iSdst = dest.iSdst;
pDest->nSdst = dest.nSdst;
+ pDest->iSDParm2 = dest.iSDParm2;
if( pDelete ){
sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pDelete);
}
@@ -146370,6 +150309,11 @@ static int generateOutputSubroutine(
r1, pDest->zAffSdst, pIn->nSdst);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
+ if( pDest->iSDParm2>0 ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
+ pIn->iSdst, pIn->nSdst);
+ ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
+ }
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -146843,7 +150787,7 @@ static int multiSelectOrderBy(
** ## About "isOuterJoin":
**
** The isOuterJoin column indicates that the replacement will occur into a
-** position in the parent that NULL-able due to an OUTER JOIN. Either the
+** position in the parent that is NULL-able due to an OUTER JOIN. Either the
** target slot in the parent is the right operand of a LEFT JOIN, or one of
** the left operands of a RIGHT JOIN. In either case, we need to potentially
** bypass the substituted expression with OP_IfNullRow.
@@ -146873,6 +150817,7 @@ typedef struct SubstContext {
int iTable; /* Replace references to this table */
int iNewTable; /* New table number */
int isOuterJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */
+ int nSelDepth; /* Depth of sub-query recursion. Top==1 */
ExprList *pEList; /* Replacement expressions */
ExprList *pCList; /* Collation sequences for replacement expr */
} SubstContext;
@@ -146948,38 +150893,41 @@ static Expr *substExpr(
if( pSubst->isOuterJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
+ if( pNew->op==TK_TRUEFALSE ){
+ pNew->u.iValue = sqlite3ExprTruthValue(pNew);
+ pNew->op = TK_INTEGER;
+ ExprSetProperty(pNew, EP_IntValue);
+ }
+
+ /* Ensure that the expression now has an implicit collation sequence,
+ ** just as it did when it was a column of a view or sub-query. */
+ {
+ CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pNew);
+ CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
+ pSubst->pCList->a[iColumn].pExpr
+ );
+ if( pNat!=pColl || (pNew->op!=TK_COLUMN && pNew->op!=TK_COLLATE) ){
+ pNew = sqlite3ExprAddCollateString(pSubst->pParse, pNew,
+ (pColl ? pColl->zName : "BINARY")
+ );
+ }
+ }
+ ExprClearProperty(pNew, EP_Collate);
if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
pExpr->flags & (EP_OuterON|EP_InnerON));
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
- if( pExpr->op==TK_TRUEFALSE ){
- pExpr->u.iValue = sqlite3ExprTruthValue(pExpr);
- pExpr->op = TK_INTEGER;
- ExprSetProperty(pExpr, EP_IntValue);
- }
-
- /* Ensure that the expression now has an implicit collation sequence,
- ** just as it did when it was a column of a view or sub-query. */
- {
- CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
- CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
- pSubst->pCList->a[iColumn].pExpr
- );
- if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){
- pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
- (pColl ? pColl->zName : "BINARY")
- );
- }
- }
- ExprClearProperty(pExpr, EP_Collate);
}
}
}else{
if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
pExpr->iTable = pSubst->iNewTable;
}
+ if( pExpr->op==TK_AGG_FUNCTION && pExpr->op2>=pSubst->nSelDepth ){
+ pExpr->op2--;
+ }
pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
pExpr->pRight = substExpr(pSubst, pExpr->pRight);
if( ExprUseXSelect(pExpr) ){
@@ -147017,6 +150965,7 @@ static void substSelect(
SrcItem *pItem;
int i;
if( !p ) return;
+ pSubst->nSelDepth++;
do{
substExprList(pSubst, p->pEList);
substExprList(pSubst, p->pGroupBy);
@@ -147026,12 +150975,15 @@ static void substSelect(
pSrc = p->pSrc;
assert( pSrc!=0 );
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- substSelect(pSubst, pItem->pSelect, 1);
+ if( pItem->fg.isSubquery ){
+ substSelect(pSubst, pItem->u4.pSubq->pSelect, 1);
+ }
if( pItem->fg.isTabFunc ){
substExprList(pSubst, pItem->u1.pFuncArg);
}
}
}while( doPrior && (p = p->pPrior)!=0 );
+ pSubst->nSelDepth--;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
@@ -147057,7 +151009,7 @@ static void recomputeColumnsUsed(
SrcItem *pSrcItem /* Which FROM clause item to recompute */
){
Walker w;
- if( NEVER(pSrcItem->pTab==0) ) return;
+ if( NEVER(pSrcItem->pSTab==0) ) return;
memset(&w, 0, sizeof(w));
w.xExprCallback = recomputeColumnsUsedExpr;
w.xSelectCallback = sqlite3SelectWalkNoop;
@@ -147097,8 +151049,10 @@ static void srclistRenumberCursors(
aCsrMap[pItem->iCursor+1] = pParse->nTab++;
}
pItem->iCursor = aCsrMap[pItem->iCursor+1];
- for(p=pItem->pSelect; p; p=p->pPrior){
- srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ if( pItem->fg.isSubquery ){
+ for(p=pItem->u4.pSubq->pSelect; p; p=p->pPrior){
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ }
}
}
}
@@ -147245,9 +151199,9 @@ static int compoundHasDifferentAffinities(Select *p){
** from 2015-02-09.)
**
** (3) If the subquery is the right operand of a LEFT JOIN then
-** (3a) the subquery may not be a join and
-** (3b) the FROM clause of the subquery may not contain a virtual
-** table and
+** (3a) the subquery may not be a join
+** (**) Was (3b): "the FROM clause of the subquery may not contain
+** a virtual table"
** (**) Was: "The outer query may not have a GROUP BY." This case
** is now managed correctly
** (3d) the outer query may not be DISTINCT.
@@ -147409,7 +151363,8 @@ static int flattenSubquery(
assert( pSrc && iFrom>=0 && iFromnSrc );
pSubitem = &pSrc->a[iFrom];
iParent = pSubitem->iCursor;
- pSub = pSubitem->pSelect;
+ assert( pSubitem->fg.isSubquery );
+ pSub = pSubitem->u4.pSubq->pSelect;
assert( pSub!=0 );
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -147462,7 +151417,7 @@ static int flattenSubquery(
*/
if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
if( pSubSrc->nSrc>1 /* (3a) */
- || IsVirtual(pSubSrc->a[0].pTab) /* (3b) */
+ /**** || IsVirtual(pSubSrc->a[0].pSTab) (3b)-omitted */
|| (p->selFlags & SF_Distinct)!=0 /* (3d) */
|| (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){
@@ -147548,14 +151503,18 @@ static int flattenSubquery(
pParse->zAuthContext = zSavedAuthContext;
/* Delete the transient structures associated with the subquery */
- pSub1 = pSubitem->pSelect;
- sqlite3DbFree(db, pSubitem->zDatabase);
+
+ if( ALWAYS(pSubitem->fg.isSubquery) ){
+ pSub1 = sqlite3SubqueryDetach(db, pSubitem);
+ }else{
+ pSub1 = 0;
+ }
+ assert( pSubitem->fg.isSubquery==0 );
+ assert( pSubitem->fg.fixedSchema==0 );
sqlite3DbFree(db, pSubitem->zName);
sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
pSubitem->zName = 0;
pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 );
/* If the sub-query is a compound SELECT statement, then (by restrictions
@@ -147596,8 +151555,8 @@ static int flattenSubquery(
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
Select *pPrior = p->pPrior;
- Table *pItemTab = pSubitem->pTab;
- pSubitem->pTab = 0;
+ Table *pItemTab = pSubitem->pSTab;
+ pSubitem->pSTab = 0;
p->pOrderBy = 0;
p->pPrior = 0;
p->pLimit = 0;
@@ -147605,7 +151564,7 @@ static int flattenSubquery(
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->op = TK_ALL;
- pSubitem->pTab = pItemTab;
+ pSubitem->pSTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
@@ -147620,11 +151579,14 @@ static int flattenSubquery(
TREETRACE(0x4,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
- assert( pSubitem->pSelect==0 );
+ assert( pSubitem->fg.isSubquery==0 );
}
sqlite3DbFree(db, aCsrMap);
if( db->mallocFailed ){
- pSubitem->pSelect = pSub1;
+ assert( pSubitem->fg.fixedSchema==0 );
+ assert( pSubitem->fg.isSubquery==0 );
+ assert( pSubitem->u4.zDatabase==0 );
+ sqlite3SrcItemAttachSubquery(pParse, pSubitem, pSub1, 0);
return 1;
}
@@ -147633,10 +151595,10 @@ static int flattenSubquery(
** complete, since there may still exist Expr.pTab entries that
** refer to the subquery even after flattening. Ticket #3346.
**
- ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
+ ** pSubitem->pSTab is always non-NULL by test restrictions and tests above.
*/
- if( ALWAYS(pSubitem->pTab!=0) ){
- Table *pTabToDel = pSubitem->pTab;
+ if( ALWAYS(pSubitem->pSTab!=0) ){
+ Table *pTabToDel = pSubitem->pSTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
sqlite3ParserAddCleanup(pToplevel, sqlite3DeleteTableGeneric, pTabToDel);
@@ -147644,7 +151606,7 @@ static int flattenSubquery(
}else{
pTabToDel->nTabRef--;
}
- pSubitem->pTab = 0;
+ pSubitem->pSTab = 0;
}
/* The following loop runs once for each term in a compound-subquery
@@ -147663,17 +151625,12 @@ static int flattenSubquery(
pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
- u8 jointype = 0;
- u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ;
+ u8 jointype = pSubitem->fg.jointype;
assert( pSub!=0 );
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
- if( pParent==p ){
- jointype = pSubitem->fg.jointype; /* First time through the loop */
- }
-
/* The subquery uses a single slot of the FROM clause of the outer
** query. If the subquery has more than one element in its FROM clause,
** then expand the outer query to make space for it to hold all elements
@@ -147693,22 +151650,25 @@ static int flattenSubquery(
pSrc = sqlite3SrcListEnlarge(pParse, pSrc, nSubSrc-1,iFrom+1);
if( pSrc==0 ) break;
pParent->pSrc = pSrc;
+ pSubitem = &pSrc->a[iFrom];
}
/* Transfer the FROM clause terms from the subquery into the
** outer query.
*/
+ iNewParent = pSubSrc->a[0].iCursor;
for(i=0; ia[i+iFrom];
- if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
assert( pItem->fg.isTabFunc==0 );
+ assert( pItem->fg.isSubquery
+ || pItem->fg.fixedSchema
+ || pItem->u4.zDatabase==0 );
+ if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
*pItem = pSubSrc->a[i];
- pItem->fg.jointype |= ltorj;
- iNewParent = pSubSrc->a[i].iCursor;
+ pItem->fg.jointype |= (jointype & JT_LTORJ);
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
- pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
- pSrc->a[iFrom].fg.jointype |= jointype | ltorj;
+ pSubitem->fg.jointype |= jointype;
/* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
@@ -147744,6 +151704,7 @@ static int flattenSubquery(
pWhere = pSub->pWhere;
pSub->pWhere = 0;
if( isOuterJoin>0 ){
+ assert( pSubSrc->nSrc==1 );
sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
}
if( pWhere ){
@@ -147759,6 +151720,7 @@ static int flattenSubquery(
x.iTable = iParent;
x.iNewTable = iNewParent;
x.isOuterJoin = isOuterJoin;
+ x.nSelDepth = 0;
x.pEList = pSub->pEList;
x.pCList = findLeftmostExprlist(pSub);
substSelect(&x, pParent, 0);
@@ -147855,7 +151817,8 @@ static void constInsert(
return; /* Already present. Return without doing anything. */
}
}
- if( sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
+ assert( SQLITE_AFF_NONEbHasAffBlob = 1;
}
@@ -147930,7 +151893,8 @@ static int propagateConstantExprRewriteOne(
if( pColumn==pExpr ) continue;
if( pColumn->iTable!=pExpr->iTable ) continue;
if( pColumn->iColumn!=pExpr->iColumn ) continue;
- if( bIgnoreAffBlob && sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
+ assert( SQLITE_AFF_NONEiCursor;
x.iNewTable = pSrc->iCursor;
x.isOuterJoin = 0;
+ x.nSelDepth = 0;
x.pEList = pSubq->pEList;
x.pCList = findLeftmostExprlist(pSubq);
pNew = substExpr(&x, pNew);
@@ -148384,10 +152350,10 @@ static int disableUnusedSubqueryResultColumns(SrcItem *pItem){
if( pItem->fg.isCorrelated || pItem->fg.isCte ){
return 0;
}
- assert( pItem->pTab!=0 );
- pTab = pItem->pTab;
- assert( pItem->pSelect!=0 );
- pSub = pItem->pSelect;
+ assert( pItem->pSTab!=0 );
+ pTab = pItem->pSTab;
+ assert( pItem->fg.isSubquery );
+ pSub = pItem->u4.pSubq->pSelect;
assert( pSub->pEList->nExpr==pTab->nCol );
for(pX=pSub; pX; pX=pX->pPrior){
if( (pX->selFlags & (SF_Distinct|SF_Aggregate))!=0 ){
@@ -148516,13 +152482,13 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
if( p->pWhere
|| p->pEList->nExpr!=1
|| p->pSrc->nSrc!=1
- || p->pSrc->a[0].pSelect
+ || p->pSrc->a[0].fg.isSubquery
|| pAggInfo->nFunc!=1
|| p->pHaving
){
return 0;
}
- pTab = p->pSrc->a[0].pTab;
+ pTab = p->pSrc->a[0].pSTab;
assert( pTab!=0 );
assert( !IsView(pTab) );
if( !IsOrdinaryTable(pTab) ) return 0;
@@ -148547,7 +152513,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** pFrom->pIndex and return SQLITE_OK.
*/
SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
- Table *pTab = pFrom->pTab;
+ Table *pTab = pFrom->pSTab;
char *zIndexedBy = pFrom->u1.zIndexedBy;
Index *pIdx;
assert( pTab!=0 );
@@ -148582,7 +152548,7 @@ SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
** above that generates the code for a compound SELECT with an ORDER BY clause
** uses a merge algorithm that requires the same collating sequence on the
** result columns as on the ORDER BY clause. See ticket
-** http://www.sqlite.org/src/info/6709574d2a
+** http://sqlite.org/src/info/6709574d2a
**
** This transformation is only needed for EXCEPT, INTERSECT, and UNION.
** The UNION ALL operator works fine with multiSelectOrderBy() even when
@@ -148624,7 +152590,11 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
if( pNew==0 ) return WRC_Abort;
memset(&dummy, 0, sizeof(dummy));
pNewSrc = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0);
- if( pNewSrc==0 ) return WRC_Abort;
+ assert( pNewSrc!=0 || pParse->nErr );
+ if( pParse->nErr ){
+ sqlite3SrcListDelete(db, pNewSrc);
+ return WRC_Abort;
+ }
*pNew = *p;
p->pSrc = pNewSrc;
p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0));
@@ -148639,7 +152609,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
#ifndef SQLITE_OMIT_WINDOWFUNC
p->pWinDefn = 0;
#endif
- p->selFlags &= ~SF_Compound;
+ p->selFlags &= ~(u32)SF_Compound;
assert( (p->selFlags & SF_Converted)==0 );
p->selFlags |= SF_Converted;
assert( pNew->pPrior!=0 );
@@ -148679,7 +152649,7 @@ static struct Cte *searchWith(
){
const char *zName = pItem->zName;
With *p;
- assert( pItem->zDatabase==0 );
+ assert( pItem->fg.fixedSchema || pItem->u4.zDatabase==0 );
assert( zName!=0 );
for(p=pWith; p; p=p->pOuter){
int i;
@@ -148734,7 +152704,7 @@ SQLITE_PRIVATE With *sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
** CTE expression, through routine checks to see if the reference is
** a recursive reference to the CTE.
**
-** If pFrom matches a CTE according to either of these two above, pFrom->pTab
+** If pFrom matches a CTE according to either of these two above, pFrom->pSTab
** and other fields are populated accordingly.
**
** Return 0 if no match is found.
@@ -148749,7 +152719,7 @@ static int resolveFromTermToCte(
Cte *pCte; /* Matched CTE (or NULL if no match) */
With *pWith; /* The matching WITH */
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
if( pParse->pWith==0 ){
/* There are no WITH clauses in the stack. No match is possible */
return 0;
@@ -148759,7 +152729,8 @@ static int resolveFromTermToCte(
** go no further. */
return 0;
}
- if( pFrom->zDatabase!=0 ){
+ assert( pFrom->fg.hadSchema==0 || pFrom->fg.notCte!=0 );
+ if( pFrom->fg.fixedSchema==0 && pFrom->u4.zDatabase!=0 ){
/* The FROM term contains a schema qualifier (ex: main.t1) and so
** it cannot possibly be a CTE reference. */
return 0;
@@ -148795,7 +152766,7 @@ static int resolveFromTermToCte(
}
if( cannotBeFunction(pParse, pFrom) ) return 2;
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return 2;
pCteUse = pCte->pUse;
@@ -148809,26 +152780,29 @@ static int resolveFromTermToCte(
}
pCteUse->eM10d = pCte->eM10d;
}
- pFrom->pTab = pTab;
+ pFrom->pSTab = pTab;
pTab->nTabRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
- pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
+ sqlite3SrcItemAttachSubquery(pParse, pFrom, pCte->pSelect, 1);
if( db->mallocFailed ) return 2;
- pFrom->pSelect->selFlags |= SF_CopyCte;
- assert( pFrom->pSelect );
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq );
+ pSel = pFrom->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ pSel->selFlags |= SF_CopyCte;
if( pFrom->fg.isIndexedBy ){
sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy);
return 2;
}
+ assert( !pFrom->fg.isIndexedBy );
pFrom->fg.isCte = 1;
pFrom->u2.pCteUse = pCteUse;
pCteUse->nUse++;
/* Check if this is a recursive CTE. */
- pRecTerm = pSel = pFrom->pSelect;
+ pRecTerm = pSel;
bMayRecursive = ( pSel->op==TK_ALL || pSel->op==TK_UNION );
while( bMayRecursive && pRecTerm->op==pSel->op ){
int i;
@@ -148836,11 +152810,13 @@ static int resolveFromTermToCte(
assert( pRecTerm->pPrior!=0 );
for(i=0; inSrc; i++){
SrcItem *pItem = &pSrc->a[i];
- if( pItem->zDatabase==0
- && pItem->zName!=0
+ if( pItem->zName!=0
+ && !pItem->fg.hadSchema
+ && ALWAYS( !pItem->fg.isSubquery )
+ && (pItem->fg.fixedSchema || pItem->u4.zDatabase==0)
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName)
){
- pItem->pTab = pTab;
+ pItem->pSTab = pTab;
pTab->nTabRef++;
pItem->fg.isRecursive = 1;
if( pRecTerm->selFlags & SF_Recursive ){
@@ -148942,11 +152918,14 @@ SQLITE_PRIVATE void sqlite3SelectPopWith(Walker *pWalker, Select *p){
** SQLITE_NOMEM.
*/
SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
- Select *pSel = pFrom->pSelect;
+ Select *pSel;
Table *pTab;
+ assert( pFrom->fg.isSubquery );
+ assert( pFrom->u4.pSubq!=0 );
+ pSel = pFrom->u4.pSubq->pSelect;
assert( pSel );
- pFrom->pTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
+ pFrom->pSTab = pTab = sqlite3DbMallocZero(pParse->db, sizeof(Table));
if( pTab==0 ) return SQLITE_NOMEM;
pTab->nTabRef = 1;
if( pFrom->zAlias ){
@@ -149046,7 +153025,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pEList = p->pEList;
if( pParse->pWith && (p->selFlags & SF_View) ){
if( p->pWith==0 ){
- p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
+ p->pWith = (With*)sqlite3DbMallocZero(db, SZ_WITH(1) );
if( p->pWith==0 ){
return WRC_Abort;
}
@@ -149066,33 +153045,35 @@ static int selectExpander(Walker *pWalker, Select *p){
*/
for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){
Table *pTab;
- assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
- if( pFrom->pTab ) continue;
+ assert( pFrom->fg.isRecursive==0 || pFrom->pSTab!=0 );
+ if( pFrom->pSTab ) continue;
assert( pFrom->fg.isRecursive==0 );
if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
- Select *pSel = pFrom->pSelect;
+ Select *pSel;
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq!=0 );
+ pSel = pFrom->u4.pSubq->pSelect;
/* A sub-query in the FROM clause of a SELECT */
assert( pSel!=0 );
- assert( pFrom->pTab==0 );
+ assert( pFrom->pSTab==0 );
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
if( sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
#ifndef SQLITE_OMIT_CTE
}else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
if( rc>1 ) return WRC_Abort;
- pTab = pFrom->pTab;
+ pTab = pFrom->pSTab;
assert( pTab!=0 );
#endif
}else{
/* An ordinary table or view name in the FROM clause */
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
+ assert( pFrom->pSTab==0 );
+ pFrom->pSTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
if( pTab->nTabRef>=0xffff ){
sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
pTab->zName);
- pFrom->pTab = 0;
+ pFrom->pSTab = 0;
return WRC_Abort;
}
pTab->nTabRef++;
@@ -149104,7 +153085,7 @@ static int selectExpander(Walker *pWalker, Select *p){
i16 nCol;
u8 eCodeOrig = pWalker->eCode;
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
- assert( pFrom->pSelect==0 );
+ assert( pFrom->fg.isSubquery==0 );
if( IsView(pTab) ){
if( (db->flags & SQLITE_EnableView)==0
&& pTab->pSchema!=db->aDb[1].pSchema
@@ -149112,7 +153093,7 @@ static int selectExpander(Walker *pWalker, Select *p){
sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
pTab->zName);
}
- pFrom->pSelect = sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
+ sqlite3SrcItemAttachSubquery(pParse, pFrom, pTab->u.view.pSelect, 1);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( ALWAYS(IsVirtual(pTab))
@@ -149128,7 +153109,9 @@ static int selectExpander(Walker *pWalker, Select *p){
nCol = pTab->nCol;
pTab->nCol = -1;
pWalker->eCode = 1; /* Turn on Select.selId renumbering */
- sqlite3WalkSelect(pWalker, pFrom->pSelect);
+ if( pFrom->fg.isSubquery ){
+ sqlite3WalkSelect(pWalker, pFrom->u4.pSubq->pSelect);
+ }
pWalker->eCode = eCodeOrig;
pTab->nCol = nCol;
}
@@ -149215,7 +153198,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){
int nAdd; /* Number of cols including rowid */
- Table *pTab = pFrom->pTab; /* Table for this data source */
+ Table *pTab = pFrom->pSTab; /* Table for this data source */
ExprList *pNestedFrom; /* Result-set of a nested FROM clause */
char *zTabName; /* AS name for this data source */
const char *zSchemaName = 0; /* Schema name for this data source */
@@ -149226,10 +153209,11 @@ static int selectExpander(Walker *pWalker, Select *p){
zTabName = pTab->zName;
}
if( db->mallocFailed ) break;
- assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) );
+ assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom) );
if( pFrom->fg.isNestedFrom ){
- assert( pFrom->pSelect!=0 );
- pNestedFrom = pFrom->pSelect->pEList;
+ assert( pFrom->fg.isSubquery && pFrom->u4.pSubq );
+ assert( pFrom->u4.pSubq->pSelect!=0 );
+ pNestedFrom = pFrom->u4.pSubq->pSelect->pEList;
assert( pNestedFrom!=0 );
assert( pNestedFrom->nExpr==pTab->nCol );
assert( VisibleRowid(pTab)==0 || ViewCanHaveRowid );
@@ -149468,14 +153452,12 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
assert( (p->selFlags & SF_Resolved) );
pTabList = p->pSrc;
for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
+ Table *pTab = pFrom->pSTab;
assert( pTab!=0 );
- if( (pTab->tabFlags & TF_Ephemeral)!=0 ){
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 && pFrom->fg.isSubquery ){
/* A sub-query in the FROM clause of a SELECT */
- Select *pSel = pFrom->pSelect;
- if( pSel ){
- sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
- }
+ Select *pSel = pFrom->u4.pSubq->pSelect;
+ sqlite3SubqueryColumnTypes(pParse, pTab, pSel, SQLITE_AFF_NONE);
}
}
}
@@ -149760,6 +153742,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( pFunc->bOBPayload ){
/* extra columns for the function arguments */
assert( ExprUseXList(pFunc->pFExpr) );
+ assert( pFunc->pFExpr->x.pList!=0 );
nExtra += pFunc->pFExpr->x.pList->nExpr;
}
if( pFunc->bUseSubtype ){
@@ -149789,6 +153772,7 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){
ExprList *pList;
assert( ExprUseXList(pF->pFExpr) );
+ if( pParse->nErr ) return;
pList = pF->pFExpr->x.pList;
if( pF->iOBTab>=0 ){
/* For an ORDER BY aggregate, calls to OP_AggStep were deferred. Inputs
@@ -149829,7 +153813,7 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nArg);
+ sqlite3VdbeChangeP5(v, (u16)nArg);
sqlite3VdbeAddOp2(v, OP_Next, pF->iOBTab, iTop+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, iTop);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
@@ -149992,12 +153976,13 @@ static void updateAccumulator(
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u8)nArg);
+ sqlite3VdbeChangeP5(v, (u16)nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
}
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
}
+ if( pParse->nErr ) return;
}
if( regHit==0 && pAggInfo->nAccumulator ){
regHit = regAcc;
@@ -150007,6 +153992,7 @@ static void updateAccumulator(
}
for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pCExpr, AggInfoColumnReg(pAggInfo,i));
+ if( pParse->nErr ) return;
}
pAggInfo->directMode = 0;
@@ -150122,25 +154108,28 @@ static SrcItem *isSelfJoinView(
int iFirst, int iEnd /* Range of FROM-clause entries to search. */
){
SrcItem *pItem;
- assert( pThis->pSelect!=0 );
- if( pThis->pSelect->selFlags & SF_PushDown ) return 0;
+ Select *pSel;
+ assert( pThis->fg.isSubquery );
+ pSel = pThis->u4.pSubq->pSelect;
+ assert( pSel!=0 );
+ if( pSel->selFlags & SF_PushDown ) return 0;
while( iFirsta[iFirst++];
- if( pItem->pSelect==0 ) continue;
+ if( !pItem->fg.isSubquery ) continue;
if( pItem->fg.viaCoroutine ) continue;
if( pItem->zName==0 ) continue;
- assert( pItem->pTab!=0 );
- assert( pThis->pTab!=0 );
- if( pItem->pTab->pSchema!=pThis->pTab->pSchema ) continue;
+ assert( pItem->pSTab!=0 );
+ assert( pThis->pSTab!=0 );
+ if( pItem->pSTab->pSchema!=pThis->pSTab->pSchema ) continue;
if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue;
- pS1 = pItem->pSelect;
- if( pItem->pTab->pSchema==0 && pThis->pSelect->selId!=pS1->selId ){
+ pS1 = pItem->u4.pSubq->pSelect;
+ if( pItem->pSTab->pSchema==0 && pSel->selId!=pS1->selId ){
/* The query flattener left two different CTE tables with identical
** names in the same FROM clause. */
continue;
}
- if( pItem->pSelect->selFlags & SF_PushDown ){
+ if( pS1->selFlags & SF_PushDown ){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
@@ -150176,6 +154165,7 @@ static void agginfoFree(sqlite3 *db, void *pArg){
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
** * The outer query is a simple count(*) with no WHERE clause or other
** extraneous syntax.
+** * None of the subqueries are DISTINCT (forumpost/a860f5fb2e 2025-03-10)
**
** Return TRUE if the optimization is undertaken.
*/
@@ -150184,6 +154174,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
Expr *pExpr;
Expr *pCount;
sqlite3 *db;
+ SrcItem *pFrom;
if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */
if( p->pEList->nExpr!=1 ) return 0; /* Single result column */
if( p->pWhere ) return 0;
@@ -150198,17 +154189,22 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
if( ExprHasProperty(pExpr, EP_WinFunc) ) return 0;/* Not a window function */
- pSub = p->pSrc->a[0].pSelect;
- if( pSub==0 ) return 0; /* The FROM is a subquery */
+ pFrom = p->pSrc->a;
+ if( pFrom->fg.isSubquery==0 ) return 0; /* FROM is a subquery */
+ pSub = pFrom->u4.pSubq->pSelect;
if( pSub->pPrior==0 ) return 0; /* Must be a compound */
if( pSub->selFlags & SF_CopyCte ) return 0; /* Not a CTE */
do{
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
if( pSub->pWhere ) return 0; /* No WHERE clause */
if( pSub->pLimit ) return 0; /* No LIMIT clause */
- if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
+ if( pSub->selFlags & (SF_Aggregate|SF_Distinct) ){
+ testcase( pSub->selFlags & SF_Aggregate );
+ testcase( pSub->selFlags & SF_Distinct );
+ return 0; /* Not an aggregate nor DISTINCT */
+ }
assert( pSub->pHaving==0 ); /* Due to the previous */
- pSub = pSub->pPrior; /* Repeat over compound */
+ pSub = pSub->pPrior; /* Repeat over compound */
}while( pSub );
/* If we reach this point then it is OK to perform the transformation */
@@ -150216,17 +154212,16 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
db = pParse->db;
pCount = pExpr;
pExpr = 0;
- pSub = p->pSrc->a[0].pSelect;
- p->pSrc->a[0].pSelect = 0;
+ pSub = sqlite3SubqueryDetach(db, pFrom);
sqlite3SrcListDelete(db, p->pSrc);
- p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
+ p->pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
while( pSub ){
Expr *pTerm;
pPrior = pSub->pPrior;
pSub->pPrior = 0;
pSub->pNext = 0;
pSub->selFlags |= SF_Aggregate;
- pSub->selFlags &= ~SF_Compound;
+ pSub->selFlags &= ~(u32)SF_Compound;
pSub->nSelectRow = 0;
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList);
pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount;
@@ -150241,7 +154236,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
pSub = pPrior;
}
p->pEList->a[0].pExpr = pExpr;
- p->selFlags &= ~SF_Aggregate;
+ p->selFlags &= ~(u32)SF_Aggregate;
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x200 ){
@@ -150262,12 +154257,12 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
for(i=0; inSrc; i++){
SrcItem *p1 = &pSrc->a[i];
if( p1==p0 ) continue;
- if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
+ if( p0->pSTab==p1->pSTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
return 1;
}
- if( p1->pSelect
- && (p1->pSelect->selFlags & SF_NestedFrom)!=0
- && sameSrcAlias(p0, p1->pSelect->pSrc)
+ if( p1->fg.isSubquery
+ && (p1->u4.pSubq->pSelect->selFlags & SF_NestedFrom)!=0
+ && sameSrcAlias(p0, p1->u4.pSubq->pSelect->pSrc)
){
return 1;
}
@@ -150332,13 +154327,212 @@ static int fromClauseTermCanBeCoroutine(
if( i==0 ) break;
i--;
pItem--;
- if( pItem->pSelect!=0 ) return 0; /* (1c-i) */
+ if( pItem->fg.isSubquery ) return 0; /* (1c-i) */
}
return 1;
}
/*
-** Generate code for the SELECT statement given in the p argument.
+** Argument pWhere is the WHERE clause belonging to SELECT statement p. This
+** function attempts to transform expressions of the form:
+**
+** EXISTS (SELECT ...)
+**
+** into joins. For example, given
+**
+** CREATE TABLE sailors(sid INTEGER PRIMARY KEY, name TEXT);
+** CREATE TABLE reserves(sid INT, day DATE, PRIMARY KEY(sid, day));
+**
+** SELECT name FROM sailors AS S WHERE EXISTS (
+** SELECT * FROM reserves AS R WHERE S.sid = R.sid AND R.day = '2022-10-25'
+** );
+**
+** the SELECT statement may be transformed as follows:
+**
+** SELECT name FROM sailors AS S, reserves AS R
+** WHERE S.sid = R.sid AND R.day = '2022-10-25';
+**
+** **Approximately**. Really, we have to ensure that the FROM-clause term
+** that was formerly inside the EXISTS is only executed once. This is handled
+** by setting the SrcItem.fg.fromExists flag, which then causes code in
+** the where.c file to exit the corresponding loop after the first successful
+** match (if any).
+*/
+static SQLITE_NOINLINE void existsToJoin(
+ Parse *pParse, /* Parsing context */
+ Select *p, /* The SELECT statement being optimized */
+ Expr *pWhere /* part of the WHERE clause currently being examined */
+){
+ if( pParse->nErr==0
+ && pWhere!=0
+ && !ExprHasProperty(pWhere, EP_OuterON|EP_InnerON)
+ && ALWAYS(p->pSrc!=0)
+ && p->pSrc->nSrcop==TK_AND ){
+ Expr *pRight = pWhere->pRight;
+ existsToJoin(pParse, p, pWhere->pLeft);
+ existsToJoin(pParse, p, pRight);
+ }
+ else if( pWhere->op==TK_EXISTS ){
+ Select *pSub = pWhere->x.pSelect;
+ Expr *pSubWhere = pSub->pWhere;
+ if( pSub->pSrc->nSrc==1
+ && (pSub->selFlags & SF_Aggregate)==0
+ && !pSub->pSrc->a[0].fg.isSubquery
+ && pSub->pLimit==0
+ && pSub->pPrior==0
+ ){
+ /* Before combining the sub-select with the parent, renumber the
+ ** cursor used by the subselect. This is because the EXISTS expression
+ ** might be a copy of another EXISTS expression from somewhere
+ ** else in the tree, and in this case it is important that it use
+ ** a unique cursor number. */
+ sqlite3 *db = pParse->db;
+ int *aCsrMap = sqlite3DbMallocZero(db, (pParse->nTab+2)*sizeof(int));
+ if( aCsrMap==0 ) return;
+ aCsrMap[0] = (pParse->nTab+1);
+ renumberCursors(pParse, pSub, -1, aCsrMap);
+ sqlite3DbFree(db, aCsrMap);
+
+ memset(pWhere, 0, sizeof(*pWhere));
+ pWhere->op = TK_INTEGER;
+ pWhere->u.iValue = 1;
+ ExprSetProperty(pWhere, EP_IntValue);
+ assert( p->pWhere!=0 );
+ pSub->pSrc->a[0].fg.fromExists = 1;
+ pSub->pSrc->a[0].fg.jointype |= JT_CROSS;
+ p->pSrc = sqlite3SrcListAppendList(pParse, p->pSrc, pSub->pSrc);
+ if( pSubWhere ){
+ p->pWhere = sqlite3PExpr(pParse, TK_AND, p->pWhere, pSubWhere);
+ pSub->pWhere = 0;
+ }
+ pSub->pSrc = 0;
+ sqlite3ParserAddCleanup(pParse, sqlite3SelectDeleteGeneric, pSub);
+#if TREETRACE_ENABLED
+ if( sqlite3TreeTrace & 0x100000 ){
+ TREETRACE(0x100000,pParse,p,
+ ("After EXISTS-to-JOIN optimization:\n"));
+ sqlite3TreeViewSelect(0, p, 0);
+ }
+#endif
+ existsToJoin(pParse, p, pSubWhere);
+ }
+ }
+ }
+}
+
+/*
+** Type used for Walker callbacks by selectCheckOnClauses().
+*/
+typedef struct CheckOnCtx CheckOnCtx;
+struct CheckOnCtx {
+ SrcList *pSrc; /* SrcList for this context */
+ int iJoin; /* Cursor numbers must be =< than this */
+ CheckOnCtx *pParent; /* Parent context */
+};
+
+/*
+** True if the SrcList passed as the only argument contains at least
+** one RIGHT or FULL JOIN. False otherwise.
+*/
+#define hasRightJoin(pSrc) (((pSrc)->a[0].fg.jointype & JT_LTORJ)!=0)
+
+/*
+** The xExpr callback for the search of invalid ON clause terms.
+*/
+static int selectCheckOnClausesExpr(Walker *pWalker, Expr *pExpr){
+ CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx;
+
+ /* Check if pExpr is root or near-root of an ON clause constraint that needs
+ ** to be checked to ensure that it does not refer to tables in its FROM
+ ** clause to the right of itself. i.e. it is either:
+ **
+ ** + an ON clause on an OUTER join, or
+ ** + an ON clause on an INNER join within a FROM that features at
+ ** least one RIGHT or FULL join.
+ */
+ if( (ExprHasProperty(pExpr, EP_OuterON))
+ || (ExprHasProperty(pExpr, EP_InnerON) && hasRightJoin(pCtx->pSrc))
+ ){
+ /* If CheckOnCtx.iJoin is already set, then fall through and process
+ ** this expression node as normal. Or, if CheckOnCtx.iJoin is still 0,
+ ** set it to the cursor number of the RHS of the join to which this
+ ** ON expression was attached and then iterate through the entire
+ ** expression. */
+ assert( pCtx->iJoin==0 || pCtx->iJoin==pExpr->w.iJoin );
+ if( pCtx->iJoin==0 ){
+ pCtx->iJoin = pExpr->w.iJoin;
+ sqlite3WalkExprNN(pWalker, pExpr);
+ pCtx->iJoin = 0;
+ return WRC_Prune;
+ }
+ }
+
+ if( pExpr->op==TK_COLUMN ){
+ /* A column expression. Find the SrcList (if any) to which it refers.
+ ** Then, if CheckOnCtx.iJoin indicates that this expression is part of an
+ ** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it
+ ** does not refer to a table to the right of CheckOnCtx.iJoin. */
+ do {
+ SrcList *pSrc = pCtx->pSrc;
+ int iTab = pExpr->iTable;
+ if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){
+ if( pCtx->iJoin && iTab>pCtx->iJoin ){
+ sqlite3ErrorMsg(pWalker->pParse,
+ "ON clause references tables to its right");
+ return WRC_Abort;
+ }
+ break;
+ }
+ pCtx = pCtx->pParent;
+ }while( pCtx );
+ }
+ return WRC_Continue;
+}
+
+/*
+** The xSelect callback for the search of invalid ON clause terms.
+*/
+static int selectCheckOnClausesSelect(Walker *pWalker, Select *pSelect){
+ CheckOnCtx *pCtx = pWalker->u.pCheckOnCtx;
+ if( pSelect->pSrc==pCtx->pSrc || pSelect->pSrc->nSrc==0 ){
+ return WRC_Continue;
+ }else{
+ CheckOnCtx sCtx;
+ memset(&sCtx, 0, sizeof(sCtx));
+ sCtx.pSrc = pSelect->pSrc;
+ sCtx.pParent = pCtx;
+ pWalker->u.pCheckOnCtx = &sCtx;
+ sqlite3WalkSelect(pWalker, pSelect);
+ pWalker->u.pCheckOnCtx = pCtx;
+ pSelect->selFlags &= ~SF_OnToWhere;
+ return WRC_Prune;
+ }
+}
+
+/*
+** Check all ON clauses in pSelect to verify that they do not reference
+** columns to the right.
+*/
+static void selectCheckOnClauses(Parse *pParse, Select *pSelect){
+ Walker w;
+ CheckOnCtx sCtx;
+ assert( pSelect->selFlags & SF_OnToWhere );
+ assert( pSelect->pSrc!=0 && pSelect->pSrc->nSrc>=2 );
+ memset(&w, 0, sizeof(w));
+ w.pParse = pParse;
+ w.xExprCallback = selectCheckOnClausesExpr;
+ w.xSelectCallback = selectCheckOnClausesSelect;
+ w.u.pCheckOnCtx = &sCtx;
+ memset(&sCtx, 0, sizeof(sCtx));
+ sCtx.pSrc = pSelect->pSrc;
+ sqlite3WalkExprNN(&w, pSelect->pWhere);
+ pSelect->selFlags &= ~SF_OnToWhere;
+}
+
+/*
+** Generate byte-code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
** See comments in sqliteInt.h for further information.
@@ -150349,6 +154543,40 @@ static int fromClauseTermCanBeCoroutine(
**
** This routine does NOT free the Select structure passed in. The
** calling function needs to do that.
+**
+** This is a long function. The following is an outline of the processing
+** steps, with tags referencing various milestones:
+**
+** * Resolve names and similar preparation tag-select-0100
+** * Scan of the FROM clause tag-select-0200
+** + OUTER JOIN strength reduction tag-select-0220
+** + Sub-query ORDER BY removal tag-select-0230
+** + Query flattening tag-select-0240
+** * Separate subroutine for compound-SELECT tag-select-0300
+** * WHERE-clause constant propagation tag-select-0330
+** * Count()-of-VIEW optimization tag-select-0350
+** * Scan of the FROM clause again tag-select-0400
+** + Authorize unreferenced tables tag-select-0410
+** + Predicate push-down optimization tag-select-0420
+** + Omit unused subquery columns optimization tag-select-0440
+** + Generate code to implement subqueries tag-select-0480
+** - Co-routines tag-select-0482
+** - Reuse previously computed CTE tag-select-0484
+** - REuse previously computed VIEW tag-select-0486
+** - Materialize a VIEW or CTE tag-select-0488
+** * DISTINCT ORDER BY -> GROUP BY optimization tag-select-0500
+** * Set up for ORDER BY tag-select-0600
+** * Create output table tag-select-0630
+** * Prepare registers for LIMIT tag-select-0650
+** * Setup for DISTINCT tag-select-0680
+** * Generate code for non-aggregate and non-GROUP BY tag-select-0700
+** * Generate code for aggregate and/or GROUP BY tag-select-0800
+** + GROUP BY queries tag-select-0810
+** + non-GROUP BY queries tag-select-0820
+** - Special case of count() w/o GROUP BY tag-select-0821
+** - General case of non-GROUP BY aggregates tag-select-0822
+** * Sort results, as needed tag-select-0900
+** * Internal self-checks tag-select-1000
*/
SQLITE_PRIVATE int sqlite3Select(
Parse *pParse, /* The parser context */
@@ -150392,6 +154620,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
+ /* tag-select-0100 */
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistQueue );
@@ -150413,7 +154642,7 @@ SQLITE_PRIVATE int sqlite3Select(
testcase( pParse->earlyCleanup );
p->pOrderBy = 0;
}
- p->selFlags &= ~SF_Distinct;
+ p->selFlags &= ~(u32)SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
@@ -150429,6 +154658,18 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
+ /* If the SELECT statement contains ON clauses that were moved into
+ ** the WHERE clause, go through and verify that none of the terms
+ ** in the ON clauses reference tables to the right of the ON clause.
+ ** Do this now, after name resolution, but before query flattening
+ */
+ if( p->selFlags & SF_OnToWhere ){
+ selectCheckOnClauses(pParse, p);
+ if( pParse->nErr ){
+ goto select_end;
+ }
+ }
+
/* If the SF_UFSrcCheck flag is set, then this function is being called
** as part of populating the temp table for an UPDATE...FROM statement.
** In this case, it is an error if the target object (pSrc->a[0]) name
@@ -150443,7 +154684,7 @@ SQLITE_PRIVATE int sqlite3Select(
if( sameSrcAlias(p0, p->pSrc) ){
sqlite3ErrorMsg(pParse,
"target object/alias may not appear in FROM clause: %s",
- p0->zAlias ? p0->zAlias : p0->pTab->zName
+ p0->zAlias ? p0->zAlias : p0->pSTab->zName
);
goto select_end;
}
@@ -150452,7 +154693,7 @@ SQLITE_PRIVATE int sqlite3Select(
** and leaving this flag set can cause errors if a compound sub-query
** in p->pSrc is flattened into this query and this function called
** again as part of compound SELECT processing. */
- p->selFlags &= ~SF_UFSrcCheck;
+ p->selFlags &= ~(u32)SF_UFSrcCheck;
}
if( pDest->eDest==SRT_Output ){
@@ -150478,12 +154719,13 @@ SQLITE_PRIVATE int sqlite3Select(
/* Try to do various optimizations (flattening subqueries, and strength
** reduction of join operators) in the FROM clause up into the main query
+ ** tag-select-0200
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && inSrc; i++){
SrcItem *pItem = &pTabList->a[i];
- Select *pSub = pItem->pSelect;
- Table *pTab = pItem->pTab;
+ Select *pSub = pItem->fg.isSubquery ? pItem->u4.pSubq->pSelect : 0;
+ Table *pTab = pItem->pSTab;
/* The expander should have already created transient Table objects
** even for FROM clause elements such as subqueries that do not correspond
@@ -150500,6 +154742,7 @@ SQLITE_PRIVATE int sqlite3Select(
** way that the i-th table cannot be the NULL row of a join, then
** perform the appropriate simplification. This is called
** "OUTER JOIN strength reduction" in the SQLite documentation.
+ ** tag-select-0220
*/
if( (pItem->fg.jointype & (JT_LEFT|JT_LTORJ))!=0
&& sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor,
@@ -150570,7 +154813,8 @@ SQLITE_PRIVATE int sqlite3Select(
if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
assert( pSub->pGroupBy==0 );
- /* If a FROM-clause subquery has an ORDER BY clause that is not
+ /* tag-select-0230:
+ ** If a FROM-clause subquery has an ORDER BY clause that is not
** really doing anything, then delete it now so that it does not
** interfere with query flattening. See the discussion at
** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a
@@ -150589,13 +154833,16 @@ SQLITE_PRIVATE int sqlite3Select(
** (a) The outer query has a different ORDER BY clause
** (b) The subquery is part of a join
** See forum post 062d576715d277c8
+ ** (6) The subquery is not a recursive CTE. ORDER BY has a different
+ ** meaning for recursive CTEs and this optimization does not
+ ** apply.
**
** Also retain the ORDER BY if the OmitOrderBy optimization is disabled.
*/
if( pSub->pOrderBy!=0
&& (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */
&& pSub->pLimit==0 /* Condition (1) */
- && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
+ && (pSub->selFlags & (SF_OrderByReqd|SF_Recursive))==0 /* (2) and (6) */
&& (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
&& OptimizationEnabled(db, SQLITE_OmitOrderBy)
){
@@ -150633,6 +154880,7 @@ SQLITE_PRIVATE int sqlite3Select(
continue;
}
+ /* tag-select-0240 */
if( flattenSubquery(pParse, p, i, isAgg) ){
if( pParse->nErr ) goto select_end;
/* This subquery can be absorbed into its parent. */
@@ -150648,7 +154896,7 @@ SQLITE_PRIVATE int sqlite3Select(
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Handle compound SELECT statements using the separate multiSelect()
- ** procedure.
+ ** procedure. tag-select-0300
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
@@ -150663,10 +154911,17 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
+ /* If there may be an "EXISTS (SELECT ...)" in the WHERE clause, attempt
+ ** to change it into a join. */
+ if( pParse->bHasExists && OptimizationEnabled(db,SQLITE_ExistsToJoin) ){
+ existsToJoin(pParse, p, p->pWhere);
+ pTabList = p->pSrc;
+ }
+
/* Do the WHERE-clause constant propagation optimization if this is
- ** a join. No need to speed time on this operation for non-join queries
+ ** a join. No need to spend time on this operation for non-join queries
** as the equivalent optimization will be handled by query planner in
- ** sqlite3WhereBegin().
+ ** sqlite3WhereBegin(). tag-select-0330
*/
if( p->pWhere!=0
&& p->pWhere->op==TK_AND
@@ -150683,6 +154938,7 @@ SQLITE_PRIVATE int sqlite3Select(
TREETRACE(0x2000,pParse,p,("Constant propagation not helpful\n"));
}
+ /* tag-select-0350 */
if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView)
&& countOfViewOptimization(pParse, p)
){
@@ -150690,20 +154946,26 @@ SQLITE_PRIVATE int sqlite3Select(
pTabList = p->pSrc;
}
- /* For each term in the FROM clause, do two things:
- ** (1) Authorized unreferenced tables
- ** (2) Generate code for all sub-queries
+ /* Loop over all terms in the FROM clause and do two things for each term:
+ **
+ ** (1) Authorize unreferenced tables
+ ** (2) Generate code for all sub-queries
+ **
+ ** tag-select-0400
*/
for(i=0; inSrc; i++){
SrcItem *pItem = &pTabList->a[i];
SrcItem *pPrior;
SelectDest dest;
+ Subquery *pSubq;
Select *pSub;
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
const char *zSavedAuthContext;
#endif
- /* Issue SQLITE_READ authorizations with a fake column name for any
+ /* Authorized unreferenced tables. tag-select-0410
+ **
+ ** Issue SQLITE_READ authorizations with a fake column name for any
** tables that are referenced but from which no values are extracted.
** Examples of where these kinds of null SQLITE_READ authorizations
** would occur:
@@ -150720,17 +154982,28 @@ SQLITE_PRIVATE int sqlite3Select(
** string for the fake column name seems safer.
*/
if( pItem->colUsed==0 && pItem->zName!=0 ){
- sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
+ const char *zDb;
+ if( pItem->fg.fixedSchema ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, pItem->u4.pSchema);
+ zDb = db->aDb[iDb].zDbSName;
+ }else if( pItem->fg.isSubquery ){
+ zDb = 0;
+ }else{
+ zDb = pItem->u4.zDatabase;
+ }
+ sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", zDb);
}
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* Generate code for all sub-queries in the FROM clause
*/
- pSub = pItem->pSelect;
- if( pSub==0 || pItem->addrFillSub!=0 ) continue;
+ if( pItem->fg.isSubquery==0 ) continue;
+ pSubq = pItem->u4.pSubq;
+ assert( pSubq!=0 );
+ pSub = pSubq->pSelect;
/* The code for a subquery should only be generated once. */
- assert( pItem->addrFillSub==0 );
+ if( pSubq->addrFillSub!=0 ) continue;
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
@@ -150743,6 +155016,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Make copies of constant WHERE-clause terms in the outer query down
** inside the subquery. This can help the subquery to run more efficiently.
+ ** This is the "predicate push-down optimization". tag-select-0420
*/
if( OptimizationEnabled(db, SQLITE_PushDown)
&& (pItem->fg.isCte==0
@@ -150756,13 +155030,14 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3TreeViewSelect(0, p, 0);
}
#endif
- assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
+ assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 );
}else{
- TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
+ TREETRACE(0x4000,pParse,p,("WHERE-clause push-down not possible\n"));
}
/* Convert unused result columns of the subquery into simple NULL
** expressions, to avoid unneeded searching and computation.
+ ** tag-select-0440
*/
if( OptimizationEnabled(db, SQLITE_NullUnusedCols)
&& disableUnusedSubqueryResultColumns(pItem)
@@ -150780,32 +155055,33 @@ SQLITE_PRIVATE int sqlite3Select(
zSavedAuthContext = pParse->zAuthContext;
pParse->zAuthContext = pItem->zName;
- /* Generate code to implement the subquery
+ /* Generate byte-code to implement the subquery tag-select-0480
*/
if( fromClauseTermCanBeCoroutine(pParse, pTabList, i, p->selFlags) ){
/* Implement a co-routine that will return a single row of the result
- ** set on each invocation.
+ ** set on each invocation. tag-select-0482
*/
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
- pItem->regReturn = ++pParse->nMem;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
+ pSubq->regReturn = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, pSubq->regReturn, 0, addrTop);
VdbeComment((v, "%!S", pItem));
- pItem->addrFillSub = addrTop;
- sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
+ pSubq->addrFillSub = addrTop;
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, pSubq->regReturn);
ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->nRowLogEst = pSub->nSelectRow;
+ pItem->pSTab->nRowLogEst = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
- pItem->regResult = dest.iSdst;
- sqlite3VdbeEndCoroutine(v, pItem->regReturn);
+ pSubq->regResult = dest.iSdst;
+ sqlite3VdbeEndCoroutine(v, pSubq->regReturn);
+ VdbeComment((v, "end %!S", pItem));
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
}else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){
/* This is a CTE for which materialization code has already been
** generated. Invoke the subroutine to compute the materialization,
- ** the make the pItem->iCursor be a copy of the ephemeral table that
- ** holds the result of the materialization. */
+ ** then make the pItem->iCursor be a copy of the ephemeral table that
+ ** holds the result of the materialization. tag-select-0484 */
CteUse *pCteUse = pItem->u2.pCteUse;
sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e);
if( pItem->iCursor!=pCteUse->iCur ){
@@ -150815,25 +155091,30 @@ SQLITE_PRIVATE int sqlite3Select(
pSub->nSelectRow = pCteUse->nRowEst;
}else if( (pPrior = isSelfJoinView(pTabList, pItem, 0, i))!=0 ){
/* This view has already been materialized by a prior entry in
- ** this same FROM clause. Reuse it. */
- if( pPrior->addrFillSub ){
- sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
+ ** this same FROM clause. Reuse it. tag-select-0486 */
+ Subquery *pPriorSubq;
+ assert( pPrior->fg.isSubquery );
+ pPriorSubq = pPrior->u4.pSubq;
+ assert( pPriorSubq!=0 );
+ if( pPriorSubq->addrFillSub ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pPriorSubq->regReturn,
+ pPriorSubq->addrFillSub);
}
sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
- pSub->nSelectRow = pPrior->pSelect->nSelectRow;
+ pSub->nSelectRow = pPriorSubq->pSelect->nSelectRow;
}else{
/* Materialize the view. If the view is not correlated, generate a
** subroutine to do the materialization so that subsequent uses of
- ** the same view can reuse the materialization. */
+ ** the same view can reuse the materialization. tag-select-0488 */
int topAddr;
int onceAddr = 0;
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
int addrExplain;
#endif
- pItem->regReturn = ++pParse->nMem;
+ pSubq->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp0(v, OP_Goto);
- pItem->addrFillSub = topAddr+1;
+ pSubq->addrFillSub = topAddr+1;
pItem->fg.isMaterialized = 1;
if( pItem->fg.isCorrelated==0 ){
/* If the subquery is not correlated and if we are not inside of
@@ -150848,17 +155129,17 @@ SQLITE_PRIVATE int sqlite3Select(
ExplainQueryPlan2(addrExplain, (pParse, 1, "MATERIALIZE %!S", pItem));
sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->nRowLogEst = pSub->nSelectRow;
+ pItem->pSTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
- sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1);
+ sqlite3VdbeAddOp2(v, OP_Return, pSubq->regReturn, topAddr+1);
VdbeComment((v, "end %!S", pItem));
sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1);
sqlite3VdbeJumpHere(v, topAddr);
sqlite3ClearTempRegCache(pParse);
if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
CteUse *pCteUse = pItem->u2.pCteUse;
- pCteUse->addrM9e = pItem->addrFillSub;
- pCteUse->regRtn = pItem->regReturn;
+ pCteUse->addrM9e = pSubq->addrFillSub;
+ pCteUse->regRtn = pSubq->regReturn;
pCteUse->iCur = pItem->iCursor;
pCteUse->nRowEst = pSub->nSelectRow;
}
@@ -150884,7 +155165,9 @@ SQLITE_PRIVATE int sqlite3Select(
}
#endif
- /* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
+ /* tag-select-0500
+ **
+ ** If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
**
@@ -150901,12 +155184,18 @@ SQLITE_PRIVATE int sqlite3Select(
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
+ && OptimizationEnabled(db, SQLITE_GroupByOrder)
#ifndef SQLITE_OMIT_WINDOWFUNC
&& p->pWin==0
#endif
){
- p->selFlags &= ~SF_Distinct;
+ p->selFlags &= ~(u32)SF_Distinct;
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
+ if( pGroupBy ){
+ for(i=0; inExpr; i++){
+ pGroupBy->a[i].u.x.iOrderByCol = i+1;
+ }
+ }
p->selFlags |= SF_Aggregate;
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
@@ -150928,7 +155217,7 @@ SQLITE_PRIVATE int sqlite3Select(
** If that is the case, then the OP_OpenEphemeral instruction will be
** changed to an OP_Noop once we figure out that the sorting index is
** not needed. The sSort.addrSortIndex variable is used to facilitate
- ** that change.
+ ** that change. tag-select-0600
*/
if( sSort.pOrderBy ){
KeyInfo *pKeyInfo;
@@ -150945,6 +155234,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
/* If the output is destined for a temporary table, open that table.
+ ** tag-select-0630
*/
if( pDest->eDest==SRT_EphemTab ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
@@ -150962,7 +155252,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
}
- /* Set the limiter.
+ /* Set the limiter. tag-select-0650
*/
iEnd = sqlite3VdbeMakeLabel(pParse);
if( (p->selFlags & SF_FixedLimit)==0 ){
@@ -150974,7 +155264,7 @@ SQLITE_PRIVATE int sqlite3Select(
sSort.sortFlags |= SORTFLAG_UseSorter;
}
- /* Open an ephemeral index to use for the distinct set.
+ /* Open an ephemeral index to use for the distinct set. tag-select-0680
*/
if( p->selFlags & SF_Distinct ){
sDistinct.tabTnct = pParse->nTab++;
@@ -150989,7 +155279,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
if( !isAgg && pGroupBy==0 ){
- /* No aggregate functions and no GROUP BY clause */
+ /* No aggregate functions and no GROUP BY clause. tag-select-0700 */
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0)
| (p->selFlags & SF_FixedLimit);
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -151008,6 +155298,12 @@ SQLITE_PRIVATE int sqlite3Select(
if( pWInfo==0 ) goto select_end;
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
+ if( pDest->eDest<=SRT_DistQueue && pDest->eDest>=SRT_DistFifo ){
+ /* TUNING: For a UNION CTE, because UNION is implies DISTINCT,
+ ** reduce the estimated output row count by 8 (LogEst 30).
+ ** Search for tag-20250414a to see other cases */
+ p->nSelectRow -= 30;
+ }
}
if( sDistinct.isTnct && sqlite3WhereIsDistinct(pWInfo) ){
sDistinct.eTnctType = sqlite3WhereIsDistinct(pWInfo);
@@ -151062,8 +155358,8 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3WhereEnd(pWInfo);
}
}else{
- /* This case when there exist aggregate functions or a GROUP BY clause
- ** or both */
+ /* This case is for when there exist aggregate functions or a GROUP BY
+ ** clause or both. tag-select-0800 */
NameContext sNC; /* Name context for processing aggregate information */
int iAMem; /* First Mem address for storing current GROUP BY */
int iBMem; /* First Mem address for previous GROUP BY */
@@ -151182,7 +155478,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Processing for aggregates with GROUP BY is very different and
- ** much more complex than aggregates without a GROUP BY.
+ ** much more complex than aggregates without a GROUP BY. tag-select-0810
*/
if( pGroupBy ){
KeyInfo *pKeyInfo; /* Keying information for the group by clause */
@@ -151238,6 +155534,7 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
VdbeComment((v, "clear abort flag"));
sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
+ sqlite3ExprNullRegisterRange(pParse, iAMem, pGroupBy->nExpr);
/* Begin a loop that will extract all source rows in GROUP BY order.
** This might involve two separate loops with an OP_Sort in between, or
@@ -151369,12 +155666,29 @@ SQLITE_PRIVATE int sqlite3Select(
sortOut, sortPTab);
}
for(j=0; jnExpr; j++){
+ int iOrderByCol = pGroupBy->a[j].u.x.iOrderByCol;
+
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j);
}else{
pAggInfo->directMode = 1;
sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
}
+
+ if( iOrderByCol ){
+ Expr *pX = p->pEList->a[iOrderByCol-1].pExpr;
+ Expr *pBase = sqlite3ExprSkipCollateAndLikely(pX);
+ while( ALWAYS(pBase!=0) && pBase->op==TK_IF_NULL_ROW ){
+ pX = pBase->pLeft;
+ pBase = sqlite3ExprSkipCollateAndLikely(pX);
+ }
+ if( ALWAYS(pBase!=0)
+ && pBase->op!=TK_AGG_COLUMN
+ && pBase->op!=TK_REGISTER
+ ){
+ sqlite3ExprToRegister(pX, iAMem+j);
+ }
+ }
}
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO);
@@ -151390,13 +155704,13 @@ SQLITE_PRIVATE int sqlite3Select(
** and resets the aggregate accumulator registers in preparation
** for the next GROUP BY batch.
*/
- sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
- VdbeComment((v, "output one row"));
+ VdbeComment((v, "output one row of %d", p->selId));
+ sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); VdbeCoverage(v);
VdbeComment((v, "check abort flag"));
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
- VdbeComment((v, "reset accumulator"));
+ VdbeComment((v, "reset accumulator %d", p->selId));
/* Update the aggregate accumulators based on the content of
** the current row
@@ -151404,7 +155718,7 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeJumpHere(v, addr1);
updateAccumulator(pParse, iUseFlag, pAggInfo, eDist);
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
- VdbeComment((v, "indicate data in accumulator"));
+ VdbeComment((v, "indicate data in accumulator %d", p->selId));
/* End of the loop
*/
@@ -151421,7 +155735,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Output the final row of result
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
- VdbeComment((v, "output final row"));
+ VdbeComment((v, "output final row of %d", p->selId));
/* Jump over the subroutines
*/
@@ -151442,7 +155756,7 @@ SQLITE_PRIVATE int sqlite3Select(
addrOutputRow = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
VdbeCoverage(v);
- VdbeComment((v, "Groupby result generator entry point"));
+ VdbeComment((v, "Groupby result generator entry point %d", p->selId));
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
finalizeAggFunctions(pParse, pAggInfo);
sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
@@ -151450,14 +155764,14 @@ SQLITE_PRIVATE int sqlite3Select(
&sDistinct, pDest,
addrOutputRow+1, addrSetAbort);
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- VdbeComment((v, "end groupby result generator"));
+ VdbeComment((v, "end groupby result generator %d", p->selId));
/* Generate a subroutine that will reset the group-by accumulator
*/
sqlite3VdbeResolveLabel(v, addrReset);
resetAccumulator(pParse, pAggInfo);
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
- VdbeComment((v, "indicate accumulator empty"));
+ VdbeComment((v, "indicate accumulator %d empty", p->selId));
sqlite3VdbeAddOp1(v, OP_Return, regReset);
if( distFlag!=0 && eDist!=WHERE_DISTINCT_NOOP ){
@@ -151466,9 +155780,12 @@ SQLITE_PRIVATE int sqlite3Select(
}
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
+ /* Aggregate functions without GROUP BY. tag-select-0820 */
Table *pTab;
if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){
- /* If isSimpleCount() returns a pointer to a Table structure, then
+ /* tag-select-0821
+ **
+ ** If isSimpleCount() returns a pointer to a Table structure, then
** the SQL statement is of the form:
**
** SELECT count(*) FROM
@@ -151527,6 +155844,8 @@ SQLITE_PRIVATE int sqlite3Select(
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
explainSimpleCount(pParse, pTab, pBest);
}else{
+ /* The general case of an aggregate query without GROUP BY
+ ** tag-select-0822 */
int regAcc = 0; /* "populate accumulators" flag */
ExprList *pDistinct = 0;
u16 distFlag = 0;
@@ -151615,7 +155934,7 @@ SQLITE_PRIVATE int sqlite3Select(
}
/* If there is an ORDER BY clause, then we need to sort the results
- ** and send them to the callback one by one.
+ ** and send them to the callback one by one. tag-select-0900
*/
if( sSort.pOrderBy ){
assert( p->pEList==pEList );
@@ -151638,6 +155957,7 @@ select_end:
assert( db->mallocFailed==0 || pParse->nErr!=0 );
sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
+ /* Internal self-checks. tag-select-1000 */
if( pAggInfo && !db->mallocFailed ){
#if TREETRACE_ENABLED
if( sqlite3TreeTrace & 0x20 ){
@@ -151945,7 +156265,8 @@ SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *pParse, Table *pTab){
assert( pParse->db->pVtabCtx==0 );
#endif
assert( pParse->bReturning );
- assert( &(pParse->u1.pReturning->retTrig) == pTrig );
+ assert( !pParse->isCreate );
+ assert( &(pParse->u1.d.pReturning->retTrig) == pTrig );
pTrig->table = pTab->zName;
pTrig->pTabSchema = pTab->pSchema;
pTrig->pNext = pList;
@@ -152027,8 +156348,10 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
** name on pTableName if we are reparsing out of the schema table
*/
if( db->init.busy && iDb!=1 ){
- sqlite3DbFree(db, pTableName->a[0].zDatabase);
- pTableName->a[0].zDatabase = 0;
+ assert( pTableName->a[0].fg.fixedSchema==0 );
+ assert( pTableName->a[0].fg.isSubquery==0 );
+ sqlite3DbFree(db, pTableName->a[0].u4.zDatabase);
+ pTableName->a[0].u4.zDatabase = 0;
}
/* If the trigger name was unqualified, and the table is a temp table,
@@ -152506,7 +156829,8 @@ SQLITE_PRIVATE void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr)
}
assert( pName->nSrc==1 );
- zDb = pName->a[0].zDatabase;
+ assert( pName->a[0].fg.fixedSchema==0 && pName->a[0].fg.isSubquery==0 );
+ zDb = pName->a[0].u4.zDatabase;
zName = pName->a[0].zName;
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
for(i=OMIT_TEMPDB; inDb; i++){
@@ -152743,7 +157067,9 @@ SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(
Schema *pSchema = pStep->pTrig->pSchema;
pSrc->a[0].zName = zName;
if( pSchema!=db->aDb[1].pSchema ){
- pSrc->a[0].pSchema = pSchema;
+ assert( pSrc->a[0].fg.fixedSchema || pSrc->a[0].u4.zDatabase==0 );
+ pSrc->a[0].u4.pSchema = pSchema;
+ pSrc->a[0].fg.fixedSchema = 1;
}
if( pStep->pFrom ){
SrcList *pDup = sqlite3SrcListDup(db, pStep->pFrom, 0);
@@ -152856,7 +157182,7 @@ static int sqlite3ReturningSubqueryCorrelated(Walker *pWalker, Select *pSelect){
pSrc = pSelect->pSrc;
assert( pSrc!=0 );
for(i=0; inSrc; i++){
- if( pSrc->a[i].pTab==pWalker->u.pTab ){
+ if( pSrc->a[i].pSTab==pWalker->u.pTab ){
testcase( pSelect->selFlags & SF_Correlated );
pSelect->selFlags |= SF_Correlated;
pWalker->eCode = 1;
@@ -152908,7 +157234,11 @@ static void codeReturningTrigger(
ExprList *pNew;
Returning *pReturning;
Select sSelect;
- SrcList sFrom;
+ SrcList *pFrom;
+ union {
+ SrcList sSrc;
+ u8 fromSpace[SZ_SRCLIST_1];
+ } uSrc;
assert( v!=0 );
if( !pParse->bReturning ){
@@ -152917,19 +157247,21 @@ static void codeReturningTrigger(
return;
}
assert( db->pParse==pParse );
- pReturning = pParse->u1.pReturning;
+ assert( !pParse->isCreate );
+ pReturning = pParse->u1.d.pReturning;
if( pTrigger != &(pReturning->retTrig) ){
/* This RETURNING trigger is for a different statement */
return;
}
memset(&sSelect, 0, sizeof(sSelect));
- memset(&sFrom, 0, sizeof(sFrom));
+ memset(&uSrc, 0, sizeof(uSrc));
+ pFrom = &uSrc.sSrc;
sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
- sSelect.pSrc = &sFrom;
- sFrom.nSrc = 1;
- sFrom.a[0].pTab = pTab;
- sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
- sFrom.a[0].iCursor = -1;
+ sSelect.pSrc = pFrom;
+ pFrom->nSrc = 1;
+ pFrom->a[0].pSTab = pTab;
+ pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */
+ pFrom->a[0].iCursor = -1;
sqlite3SelectPrep(pParse, &sSelect, 0);
if( pParse->nErr==0 ){
assert( db->mallocFailed==0 );
@@ -153147,6 +157479,8 @@ static TriggerPrg *codeRowTrigger(
sSubParse.eTriggerOp = pTrigger->op;
sSubParse.nQueryLoop = pParse->nQueryLoop;
sSubParse.prepFlags = pParse->prepFlags;
+ sSubParse.oldmask = 0;
+ sSubParse.newmask = 0;
v = sqlite3GetVdbe(&sSubParse);
if( v ){
@@ -153279,7 +157613,7 @@ SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(
** invocation is disallowed if (a) the sub-program is really a trigger,
** not a foreign key action, and (b) the flag to enable recursive triggers
** is clear. */
- sqlite3VdbeChangeP5(v, (u8)bRecursive);
+ sqlite3VdbeChangeP5(v, (u16)bRecursive);
}
}
@@ -153638,7 +157972,7 @@ static void updateFromSelect(
Expr *pLimit2 = 0;
ExprList *pOrderBy2 = 0;
sqlite3 *db = pParse->db;
- Table *pTab = pTabList->a[0].pTab;
+ Table *pTab = pTabList->a[0].pSTab;
SrcList *pSrc;
Expr *pWhere2;
int eDest;
@@ -153662,8 +157996,8 @@ static void updateFromSelect(
if( pSrc ){
assert( pSrc->a[0].fg.notCte );
pSrc->a[0].iCursor = -1;
- pSrc->a[0].pTab->nTabRef--;
- pSrc->a[0].pTab = 0;
+ pSrc->a[0].pSTab->nTabRef--;
+ pSrc->a[0].pSTab = 0;
}
if( pPk ){
for(i=0; inKeyCol; i++){
@@ -153901,38 +158235,32 @@ SQLITE_PRIVATE void sqlite3Update(
*/
chngRowid = chngPk = 0;
for(i=0; inExpr; i++){
- u8 hCol = sqlite3StrIHash(pChanges->a[i].zEName);
/* If this is an UPDATE with a FROM clause, do not resolve expressions
** here. The call to sqlite3Select() below will do that. */
if( nChangeFrom==0 && sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
- for(j=0; jnCol; j++){
- if( pTab->aCol[j].hName==hCol
- && sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0
- ){
- if( j==pTab->iPKey ){
- chngRowid = 1;
- pRowidExpr = pChanges->a[i].pExpr;
- iRowidExpr = i;
- }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
- chngPk = 1;
- }
-#ifndef SQLITE_OMIT_GENERATED_COLUMNS
- else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
- testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
- testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
- sqlite3ErrorMsg(pParse,
- "cannot UPDATE generated column \"%s\"",
- pTab->aCol[j].zCnName);
- goto update_cleanup;
- }
-#endif
- aXRef[j] = i;
- break;
+ j = sqlite3ColumnIndex(pTab, pChanges->a[i].zEName);
+ if( j>=0 ){
+ if( j==pTab->iPKey ){
+ chngRowid = 1;
+ pRowidExpr = pChanges->a[i].pExpr;
+ iRowidExpr = i;
+ }else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
+ chngPk = 1;
}
- }
- if( j>=pTab->nCol ){
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
+ testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
+ testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
+ sqlite3ErrorMsg(pParse,
+ "cannot UPDATE generated column \"%s\"",
+ pTab->aCol[j].zCnName);
+ goto update_cleanup;
+ }
+#endif
+ aXRef[j] = i;
+ }else{
if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){
j = -1;
chngRowid = 1;
@@ -154911,7 +159239,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
int nClause = 0; /* Counter of ON CONFLICT clauses */
assert( pTabList->nSrc==1 );
- assert( pTabList->a[0].pTab!=0 );
+ assert( pTabList->a[0].pSTab!=0 );
assert( pUpsert!=0 );
assert( pUpsert->pUpsertTarget!=0 );
@@ -154930,7 +159258,7 @@ SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(
if( rc ) return rc;
/* Check to see if the conflict target matches the rowid. */
- pTab = pTabList->a[0].pTab;
+ pTab = pTabList->a[0].pSTab;
pTarget = pUpsert->pUpsertTarget;
iCursor = pTabList->a[0].iCursor;
if( HasRowid(pTab)
@@ -155255,7 +159583,7 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){
#else
/* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
** to VACUUM are silently ignored. This is a back-out of a bug fix that
- ** occurred on 2016-08-19 (https://www.sqlite.org/src/info/083f9e6270).
+ ** occurred on 2016-08-19 (https://sqlite.org/src/info/083f9e6270).
** The buggy behavior is required for binary compatibility with some
** legacy applications. */
iDb = sqlite3FindDb(pParse->db, pNm);
@@ -155301,6 +159629,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
const char *zDbMain; /* Schema name of database to vacuum */
const char *zOut; /* Name of output file */
u32 pgflags = PAGER_SYNCHRONOUS_OFF; /* sync flags for output db */
+ u64 iRandom; /* Random value used for zDbVacuum[] */
+ char zDbVacuum[42]; /* Name of the ATTACH-ed database used for vacuum */
+
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
@@ -155331,7 +159662,8 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_mTrace = db->mTrace;
- db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments
+ | SQLITE_AttachCreate | SQLITE_AttachWrite;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);
@@ -155341,27 +159673,29 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
pMain = db->aDb[iDb].pBt;
isMemDb = sqlite3PagerIsMemdb(sqlite3BtreePager(pMain));
- /* Attach the temporary database as 'vacuum_db'. The synchronous pragma
+ /* Attach the temporary database as 'vacuum_XXXXXX'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
** occurs anyway. The integrity of the database is maintained by a
** (possibly synchronous) transaction opened on the main database before
** sqlite3BtreeCopyFile() is called.
**
** An optimization would be to use a non-journaled pager.
- ** (Later:) I tried setting "PRAGMA vacuum_db.journal_mode=OFF" but
+ ** (Later:) I tried setting "PRAGMA vacuum_XXXXXX.journal_mode=OFF" but
** that actually made the VACUUM run slower. Very little journalling
** actually occurs when doing a vacuum since the vacuum_db is initially
** empty. Only the journal header is written. Apparently it takes more
** time to parse and run the PRAGMA to turn journalling off than it does
** to write the journal header file.
*/
+ sqlite3_randomness(sizeof(iRandom),&iRandom);
+ sqlite3_snprintf(sizeof(zDbVacuum), zDbVacuum, "vacuum_%016llx", iRandom);
nDb = db->nDb;
- rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
+ rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS %s", zOut, zDbVacuum);
db->openFlags = saved_openFlags;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
assert( (db->nDb-1)==nDb );
pDb = &db->aDb[nDb];
- assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
+ assert( strcmp(pDb->zDbSName,zDbVacuum)==0 );
pTemp = pDb->pBt;
if( pOut ){
sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
@@ -155380,6 +159714,15 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
}
nRes = sqlite3BtreeGetRequestedReserve(pMain);
+ /* A VACUUM cannot change the pagesize of an encrypted database. */
+ if( db->nextPagesize ){
+ extern void sqlite3mcCodecGetKey(sqlite3*, int, void**, int*);
+ int nKey;
+ char *zKey;
+ sqlite3mcCodecGetKey(db, iDb, (void**)&zKey, &nKey);
+ if( nKey ) db->nextPagesize = 0;
+ }
+
sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
sqlite3BtreeSetPagerFlags(pTemp, pgflags|PAGER_CACHESPILL);
@@ -155438,11 +159781,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
** the contents to the temporary database.
*/
rc = execSqlF(db, pzErrMsg,
- "SELECT'INSERT INTO vacuum_db.'||quote(name)"
+ "SELECT'INSERT INTO %s.'||quote(name)"
"||' SELECT*FROM\"%w\".'||quote(name)"
- "FROM vacuum_db.sqlite_schema "
+ "FROM %s.sqlite_schema "
"WHERE type='table'AND coalesce(rootpage,1)>0",
- zDbMain
+ zDbVacuum, zDbMain, zDbVacuum
);
assert( (db->mDbFlags & DBFLAG_Vacuum)!=0 );
db->mDbFlags &= ~DBFLAG_Vacuum;
@@ -155454,11 +159797,11 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3RunVacuum(
** from the schema table.
*/
rc = execSqlF(db, pzErrMsg,
- "INSERT INTO vacuum_db.sqlite_schema"
+ "INSERT INTO %s.sqlite_schema"
" SELECT*FROM \"%w\".sqlite_schema"
" WHERE type IN('view','trigger')"
" OR(type='table'AND rootpage=0)",
- zDbMain
+ zDbVacuum, zDbMain
);
if( rc ) goto end_of_vacuum;
@@ -156034,11 +160377,12 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
** schema table. We just need to update that slot with all
** the information we've collected.
**
- ** The VM register number pParse->regRowid holds the rowid of an
+ ** The VM register number pParse->u1.cr.regRowid holds the rowid of an
** entry in the sqlite_schema table that was created for this vtab
** by sqlite3StartTable().
*/
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( pParse->isCreate );
sqlite3NestedParse(pParse,
"UPDATE %Q." LEGACY_SCHEMA_TABLE " "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
@@ -156047,7 +160391,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
pTab->zName,
pTab->zName,
zStmt,
- pParse->regRowid
+ pParse->u1.cr.regRowid
);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(pParse, iDb);
@@ -156385,7 +160729,9 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
z = (const unsigned char*)zCreateTable;
for(i=0; aKeyword[i]; i++){
int tokenType = 0;
- do{ z += sqlite3GetToken(z, &tokenType); }while( tokenType==TK_SPACE );
+ do{
+ z += sqlite3GetToken(z, &tokenType);
+ }while( tokenType==TK_SPACE || tokenType==TK_COMMENT );
if( tokenType!=aKeyword[i] ){
sqlite3ErrorWithMsg(db, SQLITE_ERROR, "syntax error");
return SQLITE_ERROR;
@@ -156422,6 +160768,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
Table *pNew = sParse.pNewTable;
Index *pIdx;
pTab->aCol = pNew->aCol;
+ assert( IsOrdinaryTable(pNew) );
sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
pTab->nNVCol = pTab->nCol = pNew->nCol;
pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
@@ -156830,9 +161177,12 @@ SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
addModuleArgument(pParse, pTab, 0);
addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName));
+ db->nSchemaLock++;
rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
+ db->nSchemaLock--;
if( rc ){
sqlite3ErrorMsg(pParse, "%s", zErr);
+ pParse->rc = rc;
sqlite3DbFree(db, zErr);
sqlite3VtabEponymousTableClear(db, pMod);
}
@@ -157028,6 +161378,7 @@ struct WhereLevel {
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 addrHalt; /* Abort the query due to empty table or similar */
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 */
@@ -157096,11 +161447,13 @@ struct WhereLoop {
u16 nTop; /* Size of TOP vector */
u16 nDistinctCol; /* Index columns used to sort for DISTINCT */
Index *pIndex; /* Index used, or NULL */
+ ExprList *pOrderBy; /* ORDER BY clause if this is really a subquery */
} btree;
struct { /* Information for virtual tables */
int idxNum; /* Index number */
u32 needFree : 1; /* True if sqlite3_free(idxStr) is needed */
u32 bOmitOffset : 1; /* True to let virtual table handle offset */
+ u32 bIdxNumHex : 1; /* Show idxNum as hex in EXPLAIN QUERY PLAN */
i8 isOrdered; /* True if satisfies ORDER BY */
u16 omitMask; /* Terms that may be omitted */
char *idxStr; /* Index identifier string */
@@ -157113,6 +161466,10 @@ struct WhereLoop {
/**** whereLoopXfer() copies fields above ***********************/
# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
u16 nLSlot; /* Number of slots allocated for aLTerm[] */
+#ifdef WHERETRACE_ENABLED
+ LogEst rStarDelta; /* Cost delta due to star-schema heuristic. Not
+ ** initialized unless pWInfo->bStarUsed */
+#endif
WhereTerm **aLTerm; /* WhereTerms used */
WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
WhereTerm *aLTermSpace[3]; /* Initial aLTerm[] space */
@@ -157161,7 +161518,7 @@ struct WherePath {
Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */
LogEst nRow; /* Estimated number of rows generated by this path */
LogEst rCost; /* Total cost of this path */
- LogEst rUnsorted; /* Total cost of this path ignoring sorting costs */
+ LogEst rUnsort; /* Total cost of this path ignoring sorting costs */
i8 isOrdered; /* No. of ORDER BY terms satisfied. -1 for unknown */
WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */
};
@@ -157227,6 +161584,9 @@ struct WhereTerm {
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
int iParent; /* Disable pWC->a[iParent] when this term disabled */
int leftCursor; /* Cursor number of X in "X " */
+#ifdef SQLITE_DEBUG
+ int iTerm; /* Which WhereTerm is this, for debug purposes */
+#endif
union {
struct {
int leftColumn; /* Column number of X in "X " */
@@ -157434,8 +161794,13 @@ struct WhereInfo {
unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */
unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
- unsigned sorted :1; /* True if really sorted (not just grouped) */
+ unsigned sorted :1; /* True if really sorted (not just grouped) */
+ unsigned bStarDone :1; /* True if check for star-query is complete */
+ unsigned bStarUsed :1; /* True if star-query heuristic is used */
LogEst nRowOut; /* Estimated number of output rows */
+#ifdef WHERETRACE_ENABLED
+ LogEst rTotalCost; /* Total cost of the solution */
+#endif
int iTop; /* The very beginning of the WHERE loop */
int iEndWhere; /* End of the WHERE clause itself */
WhereLoop *pLoops; /* List of all WhereLoop objects */
@@ -157443,9 +161808,14 @@ struct WhereInfo {
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
WhereClause sWC; /* Decomposition of the WHERE clause */
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
+ WhereLevel a[FLEXARRAY]; /* Information about each nest loop in WHERE */
};
+/*
+** The size (in bytes) of a WhereInfo object that holds N WhereLevels.
+*/
+#define SZ_WHEREINFO(N) ROUND8(offsetof(WhereInfo,a)+(N)*sizeof(WhereLevel))
+
/*
** Private interfaces - callable only by other where.c routines.
**
@@ -157481,9 +161851,17 @@ SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter(
const WhereInfo *pWInfo, /* WHERE clause */
const WhereLevel *pLevel /* Bloom filter on this level */
);
+SQLITE_PRIVATE void sqlite3WhereAddExplainText(
+ Parse *pParse, /* Parse context */
+ int addr,
+ SrcList *pTabList, /* Table list this loop refers to */
+ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
+ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
+);
#else
# define sqlite3WhereExplainOneScan(u,v,w,x) 0
# define sqlite3WhereExplainBloomFilter(u,v,w) 0
+# define sqlite3WhereAddExplainText(u,v,w,x,y)
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
SQLITE_PRIVATE void sqlite3WhereAddScanStatus(
@@ -157586,7 +161964,8 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
#define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */
#define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */
#define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */
- /* 0x02000000 -- available for reuse */
+#define WHERE_COROUTINE 0x02000000 /* Implemented by co-routine.
+ ** NB: False-negatives are possible */
#define WHERE_EXPRIDX 0x04000000 /* Uses an index-on-expressions */
#endif /* !defined(SQLITE_WHEREINT_H) */
@@ -157684,38 +162063,37 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
}
/*
-** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
-** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
-** was defined at compile-time. If it is not a no-op, a single OP_Explain
-** opcode is added to the output to describe the table scan strategy in pLevel.
-**
-** If an OP_Explain opcode is added to the VM, its address is returned.
-** Otherwise, if no OP_Explain is coded, zero is returned.
+** This function sets the P4 value of an existing OP_Explain opcode to
+** text describing the loop in pLevel. If the OP_Explain opcode already has
+** a P4 value, it is freed before it is overwritten.
*/
-SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
+SQLITE_PRIVATE void sqlite3WhereAddExplainText(
Parse *pParse, /* Parse context */
+ int addr, /* Address of OP_Explain opcode */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
- int ret = 0;
#if !defined(SQLITE_DEBUG)
if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
#endif
{
+ VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe, addr);
SrcItem *pItem = &pTabList->a[pLevel->iFrom];
- Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
u32 flags; /* Flags that describe this loop */
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
char *zMsg; /* Text to add to EQP output */
+#endif
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
+ if( db->mallocFailed ) return;
+
pLoop = pLevel->pWLoop;
flags = pLoop->wsFlags;
- if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
@@ -157723,7 +162101,10 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
str.printfFlags = SQLITE_PRINTF_INTERNAL;
- sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem);
+ sqlite3_str_appendf(&str, "%s %S%s",
+ isSearch ? "SEARCH" : "SCAN",
+ pItem,
+ pItem->fg.fromExists ? " EXISTS" : "");
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
const char *zFmt = 0;
Index *pIdx;
@@ -157731,7 +162112,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
assert( pLoop->u.btree.pIndex!=0 );
pIdx = pLoop->u.btree.pIndex;
assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
- if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
+ if( !HasRowid(pItem->pSTab) && IsPrimaryKeyIndex(pIdx) ){
if( isSearch ){
zFmt = "PRIMARY KEY";
}
@@ -157739,7 +162120,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
zFmt = "AUTOMATIC PARTIAL COVERING INDEX";
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "AUTOMATIC COVERING INDEX";
- }else if( flags & WHERE_IDX_ONLY ){
+ }else if( flags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
zFmt = "COVERING INDEX %s";
}else{
zFmt = "INDEX %s";
@@ -157774,7 +162155,9 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
- sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
+ sqlite3_str_appendall(&str, " VIRTUAL TABLE INDEX ");
+ sqlite3_str_appendf(&str,
+ pLoop->u.vtab.bIdxNumHex ? "0x%x:%s" : "%d:%s",
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
@@ -157789,10 +162172,50 @@ SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
sqlite3_str_append(&str, " (~1 row)", 9);
}
#endif
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
zMsg = sqlite3StrAccumFinish(&str);
sqlite3ExplainBreakpoint("",zMsg);
- ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
- pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
+#endif
+
+ assert( pOp->opcode==OP_Explain );
+ assert( pOp->p4type==P4_DYNAMIC || pOp->p4.z==0 );
+ sqlite3DbFree(db, pOp->p4.z);
+ pOp->p4type = P4_DYNAMIC;
+ pOp->p4.z = sqlite3StrAccumFinish(&str);
+ }
+}
+
+
+/*
+** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
+** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
+** was defined at compile-time. If it is not a no-op, a single OP_Explain
+** opcode is added to the output to describe the table scan strategy in pLevel.
+**
+** If an OP_Explain opcode is added to the VM, its address is returned.
+** Otherwise, if no OP_Explain is coded, zero is returned.
+*/
+SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
+ Parse *pParse, /* Parse context */
+ SrcList *pTabList, /* Table list this loop refers to */
+ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
+ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
+){
+ int ret = 0;
+#if !defined(SQLITE_DEBUG)
+ if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
+#endif
+ {
+ if( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0
+ && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
+ ){
+ Vdbe *v = pParse->pVdbe;
+ int addr = sqlite3VdbeCurrentAddr(v);
+ ret = sqlite3VdbeAddOp3(
+ v, OP_Explain, addr, pParse->addrExplain, pLevel->pWLoop->rRun
+ );
+ sqlite3WhereAddExplainText(pParse, addr, pTabList, pLevel, wctrlFlags);
+ }
}
return ret;
}
@@ -157827,7 +162250,7 @@ SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter(
sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem);
pLoop = pLevel->pWLoop;
if( pLoop->wsFlags & WHERE_IPK ){
- const Table *pTab = pItem->pTab;
+ const Table *pTab = pItem->pSTab;
if( pTab->iPKey>=0 ){
sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName);
}else{
@@ -157890,8 +162313,11 @@ SQLITE_PRIVATE void sqlite3WhereAddScanStatus(
sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
}
}else{
- int addr = pSrclist->a[pLvl->iFrom].addrFillSub;
- VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-1);
+ int addr;
+ VdbeOp *pOp;
+ assert( pSrclist->a[pLvl->iFrom].fg.isSubquery );
+ addr = pSrclist->a[pLvl->iFrom].u4.pSubq->addrFillSub;
+ pOp = sqlite3VdbeGetOp(v, addr-1);
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine );
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr );
sqlite3VdbeScanStatusRange(v, addrExplain, addr, pOp->p2-1);
@@ -158034,11 +162460,44 @@ static void updateRangeAffinityStr(
}
}
+/*
+** The pOrderBy->a[].u.x.iOrderByCol values might be incorrect because
+** columns might have been rearranged in the result set. This routine
+** fixes them up.
+**
+** pEList is the new result set. The pEList->a[].u.x.iOrderByCol values
+** contain the *old* locations of each expression. This is a temporary
+** use of u.x.iOrderByCol, not its intended use. The caller must reset
+** u.x.iOrderByCol back to zero for all entries in pEList before the
+** caller returns.
+**
+** This routine changes pOrderBy->a[].u.x.iOrderByCol values from
+** pEList->a[N].u.x.iOrderByCol into N+1. (The "+1" is because of the 1-based
+** indexing used by iOrderByCol.) Or if no match, iOrderByCol is set to zero.
+*/
+static void adjustOrderByCol(ExprList *pOrderBy, ExprList *pEList){
+ int i, j;
+ if( pOrderBy==0 ) return;
+ for(i=0; inExpr; i++){
+ int t = pOrderBy->a[i].u.x.iOrderByCol;
+ if( t==0 ) continue;
+ for(j=0; jnExpr; j++){
+ if( pEList->a[j].u.x.iOrderByCol==t ){
+ pOrderBy->a[i].u.x.iOrderByCol = j+1;
+ break;
+ }
+ }
+ if( j>=pEList->nExpr ){
+ pOrderBy->a[i].u.x.iOrderByCol = 0;
+ }
+ }
+}
+
/*
** pX is an expression of the form: (vector) IN (SELECT ...)
** In other words, it is a vector IN operator with a SELECT clause on the
-** LHS. But not all terms in the vector are indexable and the terms might
+** RHS. But not all terms in the vector are indexable and the terms might
** not be in the correct order for indexing.
**
** This routine makes a copy of the input pX expression and then adjusts
@@ -158094,9 +162553,12 @@ static Expr *removeUnindexableInClauseTerms(
int iField;
assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
iField = pLoop->aLTerm[i]->u.x.iField - 1;
- if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
+ if( NEVER(pOrigRhs->a[iField].pExpr==0) ){
+ continue; /* Duplicate PK column */
+ }
pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
+ if( pRhs ) pRhs->a[pRhs->nExpr-1].u.x.iOrderByCol = iField+1;
if( pOrigLhs ){
assert( pOrigLhs->a[iField].pExpr!=0 );
pLhs = sqlite3ExprListAppend(pParse,pLhs,pOrigLhs->a[iField].pExpr);
@@ -158110,6 +162572,7 @@ static Expr *removeUnindexableInClauseTerms(
pNew->pLeft->x.pList = pLhs;
}
pSelect->pEList = pRhs;
+ pSelect->selId = ++pParse->nSelect; /* Req'd for SubrtnSig validity */
if( pLhs && pLhs->nExpr==1 ){
/* Take care here not to generate a TK_VECTOR containing only a
** single value. Since the parser never creates such a vector, some
@@ -158119,18 +162582,16 @@ static Expr *removeUnindexableInClauseTerms(
sqlite3ExprDelete(db, pNew->pLeft);
pNew->pLeft = p;
}
- if( pSelect->pOrderBy ){
- /* If the SELECT statement has an ORDER BY clause, zero the
- ** iOrderByCol variables. These are set to non-zero when an
- ** ORDER BY term exactly matches one of the terms of the
- ** result-set. Since the result-set of the SELECT statement may
- ** have been modified or reordered, these variables are no longer
- ** set correctly. Since setting them is just an optimization,
- ** it's easiest just to zero them here. */
- ExprList *pOrderBy = pSelect->pOrderBy;
- for(i=0; inExpr; i++){
- pOrderBy->a[i].u.x.iOrderByCol = 0;
- }
+
+ /* If either the ORDER BY clause or the GROUP BY clause contains
+ ** references to result-set columns, those references might now be
+ ** obsolete. So fix them up.
+ */
+ assert( pRhs!=0 || db->mallocFailed );
+ if( pRhs ){
+ adjustOrderByCol(pSelect->pOrderBy, pRhs);
+ adjustOrderByCol(pSelect->pGroupBy, pRhs);
+ for(i=0; inExpr; i++) pRhs->a[i].u.x.iOrderByCol = 0;
}
#if 0
@@ -158145,6 +162606,138 @@ static Expr *removeUnindexableInClauseTerms(
}
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** Generate code for a single X IN (....) term of the WHERE clause.
+**
+** This is a special-case of codeEqualityTerm() that works for IN operators
+** only. It is broken out into a subroutine because this case is
+** uncommon and by splitting it off into a subroutine, the common case
+** runs faster.
+**
+** The current value for the constraint is left in register iTarget.
+** This routine sets up a loop that will iterate over all values of X.
+*/
+static SQLITE_NOINLINE void codeINTerm(
+ Parse *pParse, /* The parsing context */
+ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
+ WhereLevel *pLevel, /* The level of the FROM clause we are working on */
+ int iEq, /* Index of the equality term within this level */
+ int bRev, /* True for reverse-order IN operations */
+ int iTarget /* Attempt to leave results in this register */
+){
+ Expr *pX = pTerm->pExpr;
+ int eType = IN_INDEX_NOOP;
+ int iTab;
+ struct InLoop *pIn;
+ WhereLoop *pLoop = pLevel->pWLoop;
+ Vdbe *v = pParse->pVdbe;
+ int i;
+ int nEq = 0;
+ int *aiMap = 0;
+
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
+ && pLoop->u.btree.pIndex!=0
+ && pLoop->u.btree.pIndex->aSortOrder[iEq]
+ ){
+ testcase( iEq==0 );
+ testcase( bRev );
+ bRev = !bRev;
+ }
+ assert( pX->op==TK_IN );
+
+ for(i=0; iaLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
+ disableTerm(pLevel, pTerm);
+ return;
+ }
+ }
+ for(i=iEq; inLTerm; i++){
+ assert( pLoop->aLTerm[i]!=0 );
+ if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
+ }
+
+ iTab = 0;
+ if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
+ eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
+ }else{
+ sqlite3 *db = pParse->db;
+ Expr *pXMod = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
+ if( !db->mallocFailed ){
+ aiMap = (int*)sqlite3DbMallocZero(db, sizeof(int)*nEq);
+ eType = sqlite3FindInIndex(pParse, pXMod, IN_INDEX_LOOP, 0, aiMap, &iTab);
+ }
+ sqlite3ExprDelete(db, pXMod);
+ }
+
+ if( eType==IN_INDEX_INDEX_DESC ){
+ testcase( bRev );
+ bRev = !bRev;
+ }
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
+ VdbeCoverageIf(v, bRev);
+ VdbeCoverageIf(v, !bRev);
+
+ assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
+ pLoop->wsFlags |= WHERE_IN_ABLE;
+ if( pLevel->u.in.nIn==0 ){
+ pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
+ }
+ if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
+ pLoop->wsFlags |= WHERE_IN_EARLYOUT;
+ }
+
+ i = pLevel->u.in.nIn;
+ pLevel->u.in.nIn += nEq;
+ pLevel->u.in.aInLoop =
+ sqlite3WhereRealloc(pTerm->pWC->pWInfo,
+ pLevel->u.in.aInLoop,
+ sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
+ pIn = pLevel->u.in.aInLoop;
+ if( pIn ){
+ int iMap = 0; /* Index in aiMap[] */
+ pIn += i;
+ for(i=iEq; inLTerm; i++){
+ if( pLoop->aLTerm[i]->pExpr==pX ){
+ int iOut = iTarget + i - iEq;
+ if( eType==IN_INDEX_ROWID ){
+ pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
+ }else{
+ int iCol = aiMap ? aiMap[iMap++] : 0;
+ pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
+ }
+ sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
+ if( i==iEq ){
+ pIn->iCur = iTab;
+ pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
+ if( iEq>0 ){
+ pIn->iBase = iTarget - i;
+ pIn->nPrefix = i;
+ }else{
+ pIn->nPrefix = 0;
+ }
+ }else{
+ pIn->eEndLoopOp = OP_Noop;
+ }
+ pIn++;
+ }
+ }
+ testcase( iEq>0
+ && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
+ && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
+ if( iEq>0
+ && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
+ ){
+ sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
+ }
+ }else{
+ pLevel->u.in.nIn = 0;
+ }
+ sqlite3DbFree(pParse->db, aiMap);
+}
+#endif
+
+
/*
** Generate code for a single equality term of the WHERE clause. An equality
** term can be either X=expr or X IN (...). pTerm is the term to be
@@ -158169,7 +162762,6 @@ static int codeEqualityTerm(
int iTarget /* Attempt to leave results in this register */
){
Expr *pX = pTerm->pExpr;
- Vdbe *v = pParse->pVdbe;
int iReg; /* Register holding results */
assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
@@ -158178,125 +162770,12 @@ static int codeEqualityTerm(
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
}else if( pX->op==TK_ISNULL ){
iReg = iTarget;
- sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg);
#ifndef SQLITE_OMIT_SUBQUERY
}else{
- int eType = IN_INDEX_NOOP;
- int iTab;
- struct InLoop *pIn;
- WhereLoop *pLoop = pLevel->pWLoop;
- int i;
- int nEq = 0;
- int *aiMap = 0;
-
- if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
- && pLoop->u.btree.pIndex!=0
- && pLoop->u.btree.pIndex->aSortOrder[iEq]
- ){
- testcase( iEq==0 );
- testcase( bRev );
- bRev = !bRev;
- }
assert( pX->op==TK_IN );
iReg = iTarget;
-
- for(i=0; iaLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
- disableTerm(pLevel, pTerm);
- return iTarget;
- }
- }
- for(i=iEq;inLTerm; i++){
- assert( pLoop->aLTerm[i]!=0 );
- if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
- }
-
- iTab = 0;
- if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
- }else{
- Expr *pExpr = pTerm->pExpr;
- if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
- sqlite3 *db = pParse->db;
- pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
- if( !db->mallocFailed ){
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
- pExpr->iTable = iTab;
- }
- sqlite3ExprDelete(db, pX);
- }else{
- int n = sqlite3ExprVectorSize(pX->pLeft);
- aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
- eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
- }
- pX = pExpr;
- }
-
- if( eType==IN_INDEX_INDEX_DESC ){
- testcase( bRev );
- bRev = !bRev;
- }
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
- VdbeCoverageIf(v, bRev);
- VdbeCoverageIf(v, !bRev);
-
- assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
- pLoop->wsFlags |= WHERE_IN_ABLE;
- if( pLevel->u.in.nIn==0 ){
- pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
- }
- if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
- pLoop->wsFlags |= WHERE_IN_EARLYOUT;
- }
-
- i = pLevel->u.in.nIn;
- pLevel->u.in.nIn += nEq;
- pLevel->u.in.aInLoop =
- sqlite3WhereRealloc(pTerm->pWC->pWInfo,
- pLevel->u.in.aInLoop,
- sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
- pIn = pLevel->u.in.aInLoop;
- if( pIn ){
- int iMap = 0; /* Index in aiMap[] */
- pIn += i;
- for(i=iEq;inLTerm; i++){
- if( pLoop->aLTerm[i]->pExpr==pX ){
- int iOut = iReg + i - iEq;
- if( eType==IN_INDEX_ROWID ){
- pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
- }else{
- int iCol = aiMap ? aiMap[iMap++] : 0;
- pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
- }
- sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
- if( i==iEq ){
- pIn->iCur = iTab;
- pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
- if( iEq>0 ){
- pIn->iBase = iReg - i;
- pIn->nPrefix = i;
- }else{
- pIn->nPrefix = 0;
- }
- }else{
- pIn->eEndLoopOp = OP_Noop;
- }
- pIn++;
- }
- }
- testcase( iEq>0
- && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
- && (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
- if( iEq>0
- && (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
- ){
- sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
- }
- }else{
- pLevel->u.in.nIn = 0;
- }
- sqlite3DbFree(pParse->db, aiMap);
+ codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget);
#endif
}
@@ -158869,6 +163348,7 @@ static SQLITE_NOINLINE void filterPullDown(
int addrNxt, /* Jump here to bypass inner loops */
Bitmask notReady /* Loops that are not ready */
){
+ int saved_addrBrk;
while( ++iLevel < pWInfo->nLevel ){
WhereLevel *pLevel = &pWInfo->a[iLevel];
WhereLoop *pLoop = pLevel->pWLoop;
@@ -158877,7 +163357,7 @@ static SQLITE_NOINLINE void filterPullDown(
/* ,--- Because sqlite3ConstructBloomFilter() has will not have set
** vvvvv--' pLevel->regFilter if this were true. */
if( NEVER(pLoop->prereq & notReady) ) continue;
- assert( pLevel->addrBrk==0 );
+ saved_addrBrk = pLevel->addrBrk;
pLevel->addrBrk = addrNxt;
if( pLoop->wsFlags & WHERE_IPK ){
WhereTerm *pTerm = pLoop->aLTerm[0];
@@ -158907,7 +163387,7 @@ static SQLITE_NOINLINE void filterPullDown(
VdbeCoverage(pParse->pVdbe);
}
pLevel->regFilter = 0;
- pLevel->addrBrk = 0;
+ pLevel->addrBrk = saved_addrBrk;
}
}
@@ -158954,7 +163434,6 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3 *db; /* Database connection */
SrcItem *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
- int addrHalt; /* addrBrk for the outermost loop */
int addrCont; /* Jump here to continue with next cycle */
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
int iReleaseReg = 0; /* Temp register to free before returning */
@@ -158968,7 +163447,8 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
iCur = pTabItem->iCursor;
pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
bRev = (pWInfo->revMask>>iLevel)&1;
- VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
+ VdbeModuleComment((v, "Begin WHERE-loop%d: %s",
+ iLevel, pTabItem->pSTab->zName));
#if WHERETRACE_ENABLED /* 0x4001 */
if( sqlite3WhereTrace & 0x1 ){
sqlite3DebugPrintf("Coding level %d of %d: notReady=%llx iFrom=%d\n",
@@ -158997,7 +163477,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** there are no IN operators in the constraints, the "addrNxt" label
** is the same as "addrBrk".
*/
- addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
+ addrBrk = pLevel->addrNxt = pLevel->addrBrk;
addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);
/* If this is the right table of a LEFT OUTER JOIN, allocate and
@@ -159013,21 +163493,17 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
VdbeComment((v, "init LEFT JOIN match flag"));
}
- /* Compute a safe address to jump to if we discover that the table for
- ** this loop is empty and can never contribute content. */
- for(j=iLevel; j>0; j--){
- if( pWInfo->a[j].iLeftJoin ) break;
- if( pWInfo->a[j].pRJ ) break;
- }
- addrHalt = pWInfo->a[j].addrBrk;
-
/* Special case of a FROM clause subquery implemented as a co-routine */
if( pTabItem->fg.viaCoroutine ){
- int regYield = pTabItem->regReturn;
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
+ int regYield;
+ Subquery *pSubq;
+ assert( pTabItem->fg.isSubquery && pTabItem->u4.pSubq!=0 );
+ pSubq = pTabItem->u4.pSubq;
+ regYield = pSubq->regReturn;
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub);
pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
VdbeCoverage(v);
- VdbeComment((v, "next row of %s", pTabItem->pTab->zName));
+ VdbeComment((v, "next row of %s", pTabItem->pSTab->zName));
pLevel->op = OP_Goto;
}else
@@ -159072,6 +163548,9 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
}
sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
sqlite3VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
+ /* The instruction immediately prior to OP_VFilter must be an OP_Integer
+ ** that sets the "argc" value for xVFilter. This is necessary for
+ ** resolveP2() to work correctly. See tag-20250207a. */
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
pLoop->u.vtab.idxStr,
pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
@@ -159252,7 +163731,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
VdbeCoverageIf(v, pX->op==TK_GE);
sqlite3ReleaseTempReg(pParse, rTemp);
}else{
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, pLevel->addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
}
@@ -159292,36 +163771,36 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
}
}else if( pLoop->wsFlags & WHERE_INDEXED ){
- /* Case 4: A scan using an index.
+ /* Case 4: Search using an index.
**
- ** The WHERE clause may contain zero or more equality
- ** terms ("==" or "IN" operators) that refer to the N
- ** left-most columns of the index. It may also contain
- ** inequality constraints (>, <, >= or <=) on the indexed
- ** column that immediately follows the N equalities. Only
- ** the right-most column can be an inequality - the rest must
- ** use the "==" and "IN" operators. For example, if the
- ** index is on (x,y,z), then the following clauses are all
- ** optimized:
+ ** The WHERE clause may contain zero or more equality
+ ** terms ("==" or "IN" or "IS" operators) that refer to the N
+ ** left-most columns of the index. It may also contain
+ ** inequality constraints (>, <, >= or <=) on the indexed
+ ** column that immediately follows the N equalities. Only
+ ** the right-most column can be an inequality - the rest must
+ ** use the "==", "IN", or "IS" operators. For example, if the
+ ** index is on (x,y,z), then the following clauses are all
+ ** optimized:
**
- ** x=5
- ** x=5 AND y=10
- ** x=5 AND y<10
- ** x=5 AND y>5 AND y<10
- ** x=5 AND y=5 AND z<=10
+ ** x=5
+ ** x=5 AND y=10
+ ** x=5 AND y<10
+ ** x=5 AND y>5 AND y<10
+ ** x=5 AND y=5 AND z<=10
**
- ** The z<10 term of the following cannot be used, only
- ** the x=5 term:
+ ** The z<10 term of the following cannot be used, only
+ ** the x=5 term:
**
- ** x=5 AND z<10
+ ** x=5 AND z<10
**
- ** N may be zero if there are inequality constraints.
- ** If there are no inequality constraints, then N is at
- ** least one.
+ ** N may be zero if there are inequality constraints.
+ ** If there are no inequality constraints, then N is at
+ ** least one.
**
- ** This case is also used when there are no WHERE clause
- ** constraints but an index is selected anyway, in order
- ** to force the output order to conform to an ORDER BY.
+ ** This case is also used when there are no WHERE clause
+ ** constraints but an index is selected anyway, in order
+ ** to force the output order to conform to an ORDER BY.
*/
static const u8 aStartOp[] = {
0,
@@ -159662,12 +164141,13 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
if( pLevel->iLeftJoin==0 ){
/* If a partial index is driving the loop, try to eliminate WHERE clause
** terms from the query that must be true due to the WHERE clause of
- ** the partial index.
+ ** the partial index. This optimization does not work on an outer join,
+ ** as shown by:
**
- ** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
- ** for a LEFT JOIN.
+ ** 2019-11-02 ticket 623eff57e76d45f6 (LEFT JOIN)
+ ** 2025-05-29 forum post 7dee41d32506c4ae (RIGHT JOIN)
*/
- if( pIdx->pPartIdxWhere ){
+ if( pIdx->pPartIdxWhere && pLevel->pRJ==0 ){
whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
}
}else{
@@ -159756,7 +164236,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
- Table *pTab = pTabItem->pTab;
+ Table *pTab = pTabItem->pSTab;
pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
@@ -159774,8 +164254,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
int nNotReady; /* The number of notReady tables */
SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
- pOrTab = sqlite3DbMallocRawNN(db,
- sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
+ pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1));
if( pOrTab==0 ) return notReady;
pOrTab->nAlloc = (u8)(nNotReady + 1);
pOrTab->nSrc = pOrTab->nAlloc;
@@ -159826,7 +164305,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
**
** This optimization also only applies if the (x1 OR x2 OR ...) term
** is not contained in the ON clause of a LEFT JOIN.
- ** See ticket http://www.sqlite.org/src/info/f2369304e4
+ ** See ticket http://sqlite.org/src/info/f2369304e4
**
** 2022-02-04: Do not push down slices of a row-value comparison.
** In other words, "w" or "y" may not be a slice of a vector. Otherwise,
@@ -160047,7 +164526,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
codeCursorHint(pTabItem, pWInfo, pLevel, 0);
pLevel->op = aStep[bRev];
pLevel->p1 = iCur;
- pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrHalt);
+ pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev],iCur,pLevel->addrHalt);
VdbeCoverageIf(v, bRev==0);
VdbeCoverageIf(v, bRev!=0);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
@@ -160215,7 +164694,7 @@ SQLITE_PRIVATE Bitmask sqlite3WhereCodeOneLoopStart(
** least once. This is accomplished by storing the PK for the row in
** both the iMatch index and the regBloom Bloom filter.
*/
- pTab = pWInfo->pTabList->a[pLevel->iFrom].pTab;
+ pTab = pWInfo->pTabList->a[pLevel->iFrom].pSTab;
if( HasRowid(pTab) ){
r = sqlite3GetTempRange(pParse, 2);
sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1);
@@ -160318,11 +164797,15 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
WhereInfo *pSubWInfo;
WhereLoop *pLoop = pLevel->pWLoop;
SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
- SrcList sFrom;
+ SrcList *pFrom;
+ union {
+ SrcList sSrc;
+ u8 fromSpace[SZ_SRCLIST_1];
+ } uSrc;
Bitmask mAll = 0;
int k;
- ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
+ ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pSTab->zName));
sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
pRJ->regReturn);
for(k=0; kpTabList->a[pWInfo->a[k].iFrom];
mAll |= pWInfo->a[k].pWLoop->maskSelf;
if( pRight->fg.viaCoroutine ){
+ Subquery *pSubq;
+ assert( pRight->fg.isSubquery && pRight->u4.pSubq!=0 );
+ pSubq = pRight->u4.pSubq;
+ assert( pSubq->pSelect!=0 && pSubq->pSelect->pEList!=0 );
sqlite3VdbeAddOp3(
- v, OP_Null, 0, pRight->regResult,
- pRight->regResult + pRight->pSelect->pEList->nExpr-1
+ v, OP_Null, 0, pSubq->regResult,
+ pSubq->regResult + pSubq->pSelect->pEList->nExpr-1
);
}
sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
@@ -160358,13 +164845,14 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
}
}
- sFrom.nSrc = 1;
- sFrom.nAlloc = 1;
- memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem));
- sFrom.a[0].fg.jointype = 0;
+ pFrom = &uSrc.sSrc;
+ pFrom->nSrc = 1;
+ pFrom->nAlloc = 1;
+ memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem));
+ pFrom->a[0].fg.jointype = 0;
assert( pParse->withinRJSubrtn < 100 );
pParse->withinRJSubrtn++;
- pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0,
+ pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0,
WHERE_RIGHT_JOIN, 0);
if( pSubWInfo ){
int iCur = pLevel->iTabCur;
@@ -160372,7 +164860,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
int nPk;
int jmp;
int addrCont = sqlite3WhereContinueLabel(pSubWInfo);
- Table *pTab = pTabItem->pTab;
+ Table *pTab = pTabItem->pSTab;
if( HasRowid(pTab) ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r);
nPk = 1;
@@ -160505,7 +164993,12 @@ static int allowedOp(int op){
assert( TK_LT>TK_EQ && TK_LTTK_EQ && TK_LE=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
+ assert( TK_INTK_GE ) return 0;
+ if( op>=TK_EQ ) return 1;
+ return op==TK_IN || op==TK_ISNULL || op==TK_IS;
}
/*
@@ -160538,15 +165031,16 @@ static u16 exprCommute(Parse *pParse, Expr *pExpr){
static u16 operatorMask(int op){
u16 c;
assert( allowedOp(op) );
- if( op==TK_IN ){
+ if( op>=TK_EQ ){
+ assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
+ c = (u16)(WO_EQ<<(op-TK_EQ));
+ }else if( op==TK_IN ){
c = WO_IN;
}else if( op==TK_ISNULL ){
c = WO_ISNULL;
- }else if( op==TK_IS ){
- c = WO_IS;
}else{
- assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
- c = (u16)(WO_EQ<<(op-TK_EQ));
+ assert( op==TK_IS );
+ c = WO_IS;
}
assert( op!=TK_ISNULL || c==WO_ISNULL );
assert( op!=TK_IN || c==WO_IN );
@@ -160617,12 +165111,28 @@ static int isLikeOrGlob(
z = (u8*)pRight->u.zToken;
}
if( z ){
-
- /* Count the number of prefix characters prior to the first wildcard */
+ /* Count the number of prefix bytes prior to the first wildcard,
+ ** U+fffd character, or malformed utf-8. If the underlying database
+ ** has a UTF16LE encoding, then only consider ASCII characters. Note that
+ ** the encoding of z[] is UTF8 - we are dealing with only UTF8 here in this
+ ** code, but the database engine itself might be processing content using a
+ ** different encoding. */
cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
- if( c==wc[3] && z[cnt]!=0 ) cnt++;
+ if( c==wc[3] && z[cnt]>0 && z[cnt]<0x80 ){
+ cnt++;
+ }else if( c>=0x80 ){
+ const u8 *z2 = z+cnt-1;
+ if( c==0xff || sqlite3Utf8Read(&z2)==0xfffd /* bad utf-8 */
+ || ENC(db)==SQLITE_UTF16LE
+ ){
+ cnt--;
+ break;
+ }else{
+ cnt = (int)(z2-z);
+ }
+ }
}
/* The optimization is possible only if (1) the pattern does not begin
@@ -160633,11 +165143,11 @@ static int isLikeOrGlob(
** range search. The third is because the caller assumes that the pattern
** consists of at least one character after all escapes have been
** removed. */
- if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && 255!=(u8)z[cnt-1] ){
+ if( (cnt>1 || (cnt>0 && z[0]!=wc[3])) && ALWAYS(255!=(u8)z[cnt-1]) ){
Expr *pPrefix;
/* A "complete" match if the pattern ends with "*" or "%" */
- *pisComplete = c==wc[0] && z[cnt+1]==0;
+ *pisComplete = c==wc[0] && z[cnt+1]==0 && ENC(db)!=SQLITE_UTF16LE;
/* Get the pattern prefix. Remove all escapes from the prefix. */
pPrefix = sqlite3Expr(db, TK_STRING, (char*)z);
@@ -160833,6 +165343,13 @@ static int isAuxiliaryVtabOperator(
}
}
}
+ }else if( pExpr->op>=TK_EQ ){
+ /* Comparison operators are a common case. Save a few comparisons for
+ ** that common case by terminating early. */
+ assert( TK_NE < TK_EQ );
+ assert( TK_ISNOT < TK_EQ );
+ assert( TK_NOTNULL < TK_EQ );
+ return 0;
}else if( pExpr->op==TK_NE || pExpr->op==TK_ISNOT || pExpr->op==TK_NOTNULL ){
int res = 0;
Expr *pLeft = pExpr->pLeft;
@@ -161306,30 +165823,42 @@ static void exprAnalyzeOrTerm(
** 1. The SQLITE_Transitive optimization must be enabled
** 2. Must be either an == or an IS operator
** 3. Not originating in the ON clause of an OUTER JOIN
-** 4. The affinities of A and B must be compatible
-** 5a. Both operands use the same collating sequence OR
-** 5b. The overall collating sequence is BINARY
+** 4. The operator is not IS or else the query does not contain RIGHT JOIN
+** 5. The affinities of A and B must be compatible
+** 6a. Both operands use the same collating sequence OR
+** 6b. The overall collating sequence is BINARY
** If this routine returns TRUE, that means that the RHS can be substituted
** for the LHS anyplace else in the WHERE clause where the LHS column occurs.
** This is an optimization. No harm comes from returning 0. But if 1 is
** returned when it should not be, then incorrect answers might result.
*/
-static int termIsEquivalence(Parse *pParse, Expr *pExpr){
+static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){
char aff1, aff2;
CollSeq *pColl;
- if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
- if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
- if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
+ if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */
+ if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */
+ if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */
+ assert( pSrc!=0 );
+ if( pExpr->op==TK_IS
+ && pSrc->nSrc>=2
+ && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0
+ ){
+ return 0; /* (4) */
+ }
aff1 = sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlite3ExprAffinity(pExpr->pRight);
if( aff1!=aff2
&& (!sqlite3IsNumericAffinity(aff1) || !sqlite3IsNumericAffinity(aff2))
){
- return 0;
+ return 0; /* (5) */
}
pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
- if( sqlite3IsBinary(pColl) ) return 1;
- return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
+ if( !sqlite3IsBinary(pColl)
+ && !sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight)
+ ){
+ return 0; /* (6) */
+ }
+ return 1;
}
/*
@@ -161349,7 +165878,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
if( ALWAYS(pSrc!=0) ){
int i;
for(i=0; inSrc; i++){
- mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
+ if( pSrc->a[i].fg.isSubquery ){
+ mask |= exprSelectUsage(pMaskSet, pSrc->a[i].u4.pSubq->pSelect);
+ }
if( pSrc->a[i].fg.isUsing==0 ){
mask |= sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn);
}
@@ -161387,7 +165918,7 @@ static SQLITE_NOINLINE int exprMightBeIndexed2(
int iCur;
do{
iCur = pFrom->a[j].iCursor;
- for(pIdx=pFrom->a[j].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ for(pIdx=pFrom->a[j].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->aColExpr==0 ) continue;
for(i=0; inKeyCol; i++){
if( pIdx->aiColumn[i]!=XN_EXPR ) continue;
@@ -161431,7 +165962,7 @@ static int exprMightBeIndexed(
for(i=0; inSrc; i++){
Index *pIdx;
- for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ for(pIdx=pFrom->a[i].pSTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->aColExpr ){
return exprMightBeIndexed2(pFrom,aiCurCol,pExpr,i);
}
@@ -161485,6 +166016,9 @@ static void exprAnalyze(
}
assert( pWC->nTerm > idxTerm );
pTerm = &pWC->a[idxTerm];
+#ifdef SQLITE_DEBUG
+ pTerm->iTerm = idxTerm;
+#endif
pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr;
assert( pExpr!=0 ); /* Because malloc() has not failed */
@@ -161528,21 +166062,7 @@ static void exprAnalyze(
prereqAll |= x;
extraRight = x-1; /* ON clause terms may not be used with an index
** on left table of a LEFT JOIN. Ticket #3015 */
- if( (prereqAll>>1)>=x ){
- sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
- return;
- }
}else if( (prereqAll>>1)>=x ){
- /* The ON clause of an INNER JOIN references a table to its right.
- ** Most other SQL database engines raise an error. But SQLite versions
- ** 3.0 through 3.38 just put the ON clause constraint into the WHERE
- ** clause and carried on. Beginning with 3.39, raise an error only
- ** if there is a RIGHT or FULL JOIN in the query. This makes SQLite
- ** more like other systems, and also preserves legacy. */
- if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
- sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
- return;
- }
ExprClearProperty(pExpr, EP_InnerON);
}
}
@@ -161592,8 +166112,8 @@ static void exprAnalyze(
if( op==TK_IS ) pNew->wtFlags |= TERM_IS;
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_COPIED;
-
- if( termIsEquivalence(pParse, pDup) ){
+ assert( pWInfo->pTabList!=0 );
+ if( termIsEquivalence(pParse, pDup, pWInfo->pTabList) ){
pTerm->eOperator |= WO_EQUIV;
eExtraOp = WO_EQUIV;
}
@@ -161759,9 +166279,8 @@ static void exprAnalyze(
}
if( !db->mallocFailed ){
- u8 c, *pC; /* Last character before the first wildcard */
+ u8 *pC; /* Last character before the first wildcard */
pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
- c = *pC;
if( noCase ){
/* The point is to increment the last character before the first
** wildcard. But if we increment '@', that will push it into the
@@ -161769,10 +166288,17 @@ static void exprAnalyze(
** inequality. To avoid this, make sure to also run the full
** LIKE on all candidate expressions by clearing the isComplete flag
*/
- if( c=='A'-1 ) isComplete = 0;
- c = sqlite3UpperToLower[c];
+ if( *pC=='A'-1 ) isComplete = 0;
+ *pC = sqlite3UpperToLower[*pC];
}
- *pC = c + 1;
+
+ /* Increment the value of the last utf8 character in the prefix. */
+ while( *pC==0xBF && pC>(u8*)pStr2->u.zToken ){
+ *pC = 0x80;
+ pC--;
+ }
+ assert( *pC!=0xFF ); /* isLikeOrGlob() guarantees this */
+ (*pC)++;
}
zCollSeqName = noCase ? "NOCASE" : sqlite3StrBINARY;
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
@@ -161893,7 +166419,7 @@ static void exprAnalyze(
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = prereqExpr;
+ pNewTerm->prereqRight = prereqExpr | extraRight;
pNewTerm->leftCursor = pLeft->iTable;
pNewTerm->u.x.leftColumn = pLeft->iColumn;
pNewTerm->eOperator = WO_AUX;
@@ -161974,7 +166500,7 @@ static void whereAddLimitExpr(
Expr *pNew;
int iVal = 0;
- if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
+ if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){
Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
if( pVal==0 ) return;
ExprSetProperty(pVal, EP_IntValue);
@@ -162004,7 +166530,7 @@ static void whereAddLimitExpr(
**
** 1. The SELECT statement has a LIMIT clause, and
** 2. The SELECT statement is not an aggregate or DISTINCT query, and
-** 3. The SELECT statement has exactly one object in its from clause, and
+** 3. The SELECT statement has exactly one object in its FROM clause, and
** that object is a virtual table, and
** 4. There are no terms in the WHERE clause that will not be passed
** to the virtual table xBestIndex method.
@@ -162019,7 +166545,7 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Selec
assert( p!=0 && p->pLimit!=0 ); /* 1 -- checked by caller */
if( p->pGroupBy==0
&& (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */
- && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab)) /* 3 */
+ && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pSTab)) /* 3 */
){
ExprList *pOrderBy = p->pOrderBy;
int iCsr = p->pSrc->a[0].iCursor;
@@ -162041,8 +166567,22 @@ SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3WhereAddLimit(WhereClause *pWC, Selec
** (leftCursor==iCsr) test below. */
continue;
}
- if( pWC->a[ii].leftCursor!=iCsr ) return;
- if( pWC->a[ii].prereqRight!=0 ) return;
+ if( pWC->a[ii].leftCursor==iCsr && pWC->a[ii].prereqRight==0 ) continue;
+
+ /* If this term has a parent with exactly one child, and the parent will
+ ** be passed through to xBestIndex, then this term can be ignored. */
+ if( pWC->a[ii].iParent>=0 ){
+ WhereTerm *pParent = &pWC->a[ pWC->a[ii].iParent ];
+ if( pParent->leftCursor==iCsr
+ && pParent->prereqRight==0
+ && pParent->nChild==1
+ ){
+ continue;
+ }
+ }
+
+ /* This term will not be passed through. Do not add a LIMIT clause. */
+ return;
}
/* Check condition (5). Return early if it is not met. */
@@ -162240,7 +166780,7 @@ SQLITE_PRIVATE void sqlite3WhereTabFuncArgs(
Expr *pColRef;
Expr *pTerm;
if( pItem->fg.isTabFunc==0 ) return;
- pTab = pItem->pTab;
+ pTab = pItem->pSTab;
assert( pTab!=0 );
pArgs = pItem->u1.pFuncArg;
if( pArgs==0 ) return;
@@ -162315,11 +166855,16 @@ struct HiddenIndexInfo {
int eDistinct; /* Value to return from sqlite3_vtab_distinct() */
u32 mIn; /* Mask of terms that are IN (...) */
u32 mHandleIn; /* Terms that vtab will handle as IN (...) */
- sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST
- ** because extra space is allocated to hold up
- ** to nTerm such values */
+ sqlite3_value *aRhs[FLEXARRAY]; /* RHS values for constraints. MUST BE LAST
+ ** Extra space is allocated to hold up
+ ** to nTerm such values */
};
+/* Size (in bytes) of a HiddenIndeInfo object sufficient to hold as
+** many as N constraints */
+#define SZ_HIDDENINDEXINFO(N) \
+ (offsetof(HiddenIndexInfo,aRhs) + (N)*sizeof(sqlite3_value*))
+
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
@@ -162701,11 +167246,11 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
pScan->pWC = pWC;
pScan->k = k+1;
#ifdef WHERETRACE_ENABLED
- if( sqlite3WhereTrace & 0x20000 ){
+ if( (sqlite3WhereTrace & 0x20000)!=0 && pScan->nEquiv>1 ){
int ii;
- sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
- pTerm, pScan->nEquiv);
- for(ii=0; iinEquiv; ii++){
+ sqlite3DebugPrintf("EQUIVALENT TO {%d:%d} (due to TERM-%d):",
+ pScan->aiCur[0], pScan->aiColumn[0], pTerm->iTerm);
+ for(ii=1; iinEquiv; ii++){
sqlite3DebugPrintf(" {%d:%d}",
pScan->aiCur[ii], pScan->aiColumn[ii]);
}
@@ -162924,7 +167469,7 @@ static int isDistinctRedundant(
** clause is redundant. */
if( pTabList->nSrc!=1 ) return 0;
iBase = pTabList->a[0].iCursor;
- pTab = pTabList->a[0].pTab;
+ pTab = pTabList->a[0].pSTab;
/* If any of the expressions is an IPK column on table iBase, then return
** true. Note: The (p->iTable==iBase) part of this test may be false if the
@@ -162999,6 +167544,12 @@ static void translateColumnToCopy(
VdbeOp *pOp = sqlite3VdbeGetOp(v, iStart);
int iEnd = sqlite3VdbeCurrentAddr(v);
if( pParse->db->mallocFailed ) return;
+#ifdef SQLITE_DEBUG
+ if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
+ printf("CHECKING for column-to-copy on cursor %d for %d..%d\n",
+ iTabCur, iStart, iEnd);
+ }
+#endif
for(; iStartp1!=iTabCur ) continue;
if( pOp->opcode==OP_Column ){
@@ -163113,13 +167664,52 @@ static int constraintCompatibleWithOuterJoin(
return 0;
}
if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0
- && ExprHasProperty(pTerm->pExpr, EP_InnerON)
+ && NEVER(ExprHasProperty(pTerm->pExpr, EP_InnerON))
){
return 0;
}
return 1;
}
+#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
+/*
+** Return true if column iCol of table pTab seem like it might be a
+** good column to use as part of a query-time index.
+**
+** Current algorithm (subject to improvement!):
+**
+** 1. If iCol is already the left-most column of some other index,
+** then return false.
+**
+** 2. If iCol is part of an existing index that has an aiRowLogEst of
+** more than 20, then return false.
+**
+** 3. If no disqualifying conditions above are found, return true.
+**
+** 2025-01-03: I experimented with a new rule that returns false if the
+** the datatype of the column is "BOOLEAN". This did not improve
+** performance on any queries at hand, but it did burn CPU cycles, so the
+** idea was not committed.
+*/
+static SQLITE_NOINLINE int columnIsGoodIndexCandidate(
+ const Table *pTab,
+ int iCol
+){
+ const Index *pIdx;
+ for(pIdx = pTab->pIndex; pIdx!=0; pIdx=pIdx->pNext){
+ int j;
+ for(j=0; jnKeyCol; j++){
+ if( pIdx->aiColumn[j]==iCol ){
+ if( j==0 ) return 0;
+ if( pIdx->hasStat1 && pIdx->aiRowLogEst[j+1]>20 ) return 0;
+ break;
+ }
+ }
+ }
+ return 1;
+}
+#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -163134,6 +167724,8 @@ static int termCanDriveIndex(
const Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
+ int leftCol;
+
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
@@ -163144,11 +167736,12 @@ static int termCanDriveIndex(
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
- if( pTerm->u.x.leftColumn<0 ) return 0;
- aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
+ leftCol = pTerm->u.x.leftColumn;
+ if( leftCol<0 ) return 0;
+ aff = pSrc->pSTab->aCol[leftCol].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
testcase( pTerm->pExpr->op==TK_IS );
- return 1;
+ return columnIsGoodIndexCandidate(pSrc->pSTab, leftCol);
}
#endif
@@ -163181,7 +167774,7 @@ static void explainAutomaticIndex(
sqlite3_str *pStr = sqlite3_str_new(pParse->db);
sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName);
assert( pIdx->nColumn>1 );
- assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID );
+ assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID || !HasRowid(pTab) );
for(ii=0; ii<(pIdx->nColumn-1); ii++){
const char *zName = 0;
int iCol = pIdx->aiColumn[ii];
@@ -163256,7 +167849,7 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
nKeyCol = 0;
pTabList = pWC->pWInfo->pTabList;
pSrc = &pTabList->a[pLevel->iFrom];
- pTable = pSrc->pTab;
+ pTable = pSrc->pSTab;
pWCEnd = &pWC->a[pWC->nTerm];
pLoop = pLevel->pWLoop;
idxCols = 0;
@@ -163312,6 +167905,19 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
}else{
extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
}
+ if( !HasRowid(pTable) ){
+ /* For WITHOUT ROWID tables, ensure that all PRIMARY KEY columns are
+ ** either in the idxCols mask or in the extraCols mask */
+ for(i=0; inCol; i++){
+ if( (pTable->aCol[i].colFlags & COLFLAG_PRIMKEY)==0 ) continue;
+ if( i>=BMS-1 ){
+ extraCols |= MASKBIT(BMS-1);
+ break;
+ }
+ if( idxCols & MASKBIT(i) ) continue;
+ extraCols |= MASKBIT(i);
+ }
+ }
mxBitCol = MIN(BMS-1,pTable->nCol);
testcase( pTable->nCol==BMS-1 );
testcase( pTable->nCol==BMS-2 );
@@ -163323,7 +167929,10 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
}
/* Construct the Index object to describe this index */
- pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed);
+ assert( nKeyCol <= pTable->nCol + MAX(0, pTable->nCol - BMS + 1) );
+ /* ^-- This guarantees that the number of index columns will fit in the u16 */
+ pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+HasRowid(pTable),
+ 0, &zNotUsed);
if( pIdx==0 ) goto end_auto_index_create;
pLoop->u.btree.pIndex = pIdx;
pIdx->zName = "auto-index";
@@ -163379,8 +167988,10 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
}
}
assert( n==nKeyCol );
- pIdx->aiColumn[n] = XN_ROWID;
- pIdx->azColl[n] = sqlite3StrBINARY;
+ if( HasRowid(pTable) ){
+ pIdx->aiColumn[n] = XN_ROWID;
+ pIdx->azColl[n] = sqlite3StrBINARY;
+ }
/* Create the automatic index */
explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp);
@@ -163398,14 +168009,21 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
/* Fill the automatic index with content */
assert( pSrc == &pWC->pWInfo->pTabList->a[pLevel->iFrom] );
if( pSrc->fg.viaCoroutine ){
- int regYield = pSrc->regReturn;
+ int regYield;
+ Subquery *pSubq;
+ assert( pSrc->fg.isSubquery );
+ pSubq = pSrc->u4.pSubq;
+ assert( pSubq!=0 );
+ regYield = pSubq->regReturn;
addrCounter = sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
- sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSrc->addrFillSub);
+ sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pSubq->addrFillSub);
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
VdbeCoverage(v);
- VdbeComment((v, "next row of %s", pSrc->pTab->zName));
+ VdbeComment((v, "next row of %s", pSrc->pSTab->zName));
}else{
- addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); VdbeCoverage(v);
+ assert( pLevel->addrHalt );
+ addrTop = sqlite3VdbeAddOp2(v, OP_Rewind,pLevel->iTabCur,pLevel->addrHalt);
+ VdbeCoverage(v);
}
if( pPartial ){
iContinue = sqlite3VdbeMakeLabel(pParse);
@@ -163425,18 +168043,22 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
if( pPartial ) sqlite3VdbeResolveLabel(v, iContinue);
if( pSrc->fg.viaCoroutine ){
+ assert( pSrc->fg.isSubquery && pSrc->u4.pSubq!=0 );
sqlite3VdbeChangeP2(v, addrCounter, regBase+n);
testcase( pParse->db->mallocFailed );
assert( pLevel->iIdxCur>0 );
translateColumnToCopy(pParse, addrTop, pLevel->iTabCur,
- pSrc->regResult, pLevel->iIdxCur);
+ pSrc->u4.pSubq->regResult, pLevel->iIdxCur);
sqlite3VdbeGoto(v, addrTop);
pSrc->fg.viaCoroutine = 0;
+ sqlite3VdbeJumpHere(v, addrTop);
}else{
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
+ if( (pSrc->fg.jointype & JT_LEFT)!=0 ){
+ sqlite3VdbeJumpHere(v, addrTop);
+ }
}
- sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord);
/* Jump here when skipping the initialization */
@@ -163520,7 +168142,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
iSrc = pLevel->iFrom;
pItem = &pTabList->a[iSrc];
assert( pItem!=0 );
- pTab = pItem->pTab;
+ pTab = pItem->pSTab;
assert( pTab!=0 );
sz = sqlite3LogEstToInt(pTab->nRowLogEst);
if( sz<10000 ){
@@ -163551,7 +168173,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
int r1 = sqlite3GetTempRange(pParse, n);
int jj;
for(jj=0; jjpTable==pItem->pTab );
+ assert( pIdx->pTable==pItem->pSTab );
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj);
}
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n);
@@ -163589,6 +168211,20 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
+** Return term iTerm of the WhereClause passed as the first argument. Terms
+** are numbered from 0 upwards, starting with the terms in pWC->a[], then
+** those in pWC->pOuter->a[] (if any), and so on.
+*/
+static WhereTerm *termFromWhereClause(WhereClause *pWC, int iTerm){
+ WhereClause *p;
+ for(p=pWC; p; p=p->pOuter){
+ if( iTermnTerm ) return &p->a[iTerm];
+ iTerm -= p->nTerm;
+ }
+ return 0;
+}
+
/*
** Allocate and populate an sqlite3_index_info structure. It is the
** responsibility of the caller to eventually release the structure
@@ -163615,9 +168251,10 @@ static sqlite3_index_info *allocateIndexInfo(
const Table *pTab;
int eDistinct = 0;
ExprList *pOrderBy = pWInfo->pOrderBy;
+ WhereClause *p;
assert( pSrc!=0 );
- pTab = pSrc->pTab;
+ pTab = pSrc->pSTab;
assert( pTab!=0 );
assert( IsVirtual(pTab) );
@@ -163625,28 +168262,30 @@ static sqlite3_index_info *allocateIndexInfo(
** Mark each term with the TERM_OK flag. Set nTerm to the number of
** terms found.
*/
- for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){
- pTerm->wtFlags &= ~TERM_OK;
- if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( pTerm->prereqRight & mUnusable ) continue;
- assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
- testcase( pTerm->eOperator & WO_IN );
- testcase( pTerm->eOperator & WO_ISNULL );
- testcase( pTerm->eOperator & WO_IS );
- testcase( pTerm->eOperator & WO_ALL );
- if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
- if( pTerm->wtFlags & TERM_VNULL ) continue;
+ for(p=pWC, nTerm=0; p; p=p->pOuter){
+ for(i=0, pTerm=p->a; inTerm; i++, pTerm++){
+ pTerm->wtFlags &= ~TERM_OK;
+ if( pTerm->leftCursor != pSrc->iCursor ) continue;
+ if( pTerm->prereqRight & mUnusable ) continue;
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+ testcase( pTerm->eOperator & WO_IN );
+ testcase( pTerm->eOperator & WO_ISNULL );
+ testcase( pTerm->eOperator & WO_IS );
+ testcase( pTerm->eOperator & WO_ALL );
+ if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
+ if( pTerm->wtFlags & TERM_VNULL ) continue;
- assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
- assert( pTerm->u.x.leftColumn>=XN_ROWID );
- assert( pTerm->u.x.leftColumnnCol );
- if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
- && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
- ){
- continue;
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
+ assert( pTerm->u.x.leftColumn>=XN_ROWID );
+ assert( pTerm->u.x.leftColumnnCol );
+ if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0
+ && !constraintCompatibleWithOuterJoin(pTerm,pSrc)
+ ){
+ continue;
+ }
+ nTerm++;
+ pTerm->wtFlags |= TERM_OK;
}
- nTerm++;
- pTerm->wtFlags |= TERM_OK;
}
/* If the ORDER BY clause contains only columns in the current
@@ -163708,8 +168347,8 @@ static sqlite3_index_info *allocateIndexInfo(
*/
pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
+ (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
- + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden)
- + sizeof(sqlite3_value*)*nTerm );
+ + sizeof(*pIdxOrderBy)*nOrderBy
+ + SZ_HIDDENINDEXINFO(nTerm) );
if( pIdxInfo==0 ){
sqlite3ErrorMsg(pParse, "out of memory");
return 0;
@@ -163721,53 +168360,69 @@ static sqlite3_index_info *allocateIndexInfo(
pIdxInfo->aConstraint = pIdxCons;
pIdxInfo->aOrderBy = pIdxOrderBy;
pIdxInfo->aConstraintUsage = pUsage;
+ pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
+ if( HasRowid(pTab)==0 ){
+ /* Ensure that all bits associated with PK columns are set. This is to
+ ** ensure they are available for cases like RIGHT joins or OR loops. */
+ Index *pPk = sqlite3PrimaryKeyIndex((Table*)pTab);
+ assert( pPk!=0 );
+ for(i=0; inKeyCol; i++){
+ int iCol = pPk->aiColumn[i];
+ assert( iCol>=0 );
+ if( iCol>=BMS-1 ) iCol = BMS-1;
+ pIdxInfo->colUsed |= MASKBIT(iCol);
+ }
+ }
pHidden->pWC = pWC;
pHidden->pParse = pParse;
pHidden->eDistinct = eDistinct;
pHidden->mIn = 0;
- for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){
- u16 op;
- if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
- pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
- pIdxCons[j].iTermOffset = i;
- op = pTerm->eOperator & WO_ALL;
- if( op==WO_IN ){
- if( (pTerm->wtFlags & TERM_SLICE)==0 ){
- pHidden->mIn |= SMASKBIT32(j);
+ for(p=pWC, i=j=0; p; p=p->pOuter){
+ int nLast = i+p->nTerm;;
+ for(pTerm=p->a; iwtFlags & TERM_OK)==0 ) continue;
+ pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
+ pIdxCons[j].iTermOffset = i;
+ op = pTerm->eOperator & WO_ALL;
+ if( op==WO_IN ){
+ if( (pTerm->wtFlags & TERM_SLICE)==0 ){
+ pHidden->mIn |= SMASKBIT32(j);
+ }
+ op = WO_EQ;
}
- op = WO_EQ;
- }
- if( op==WO_AUX ){
- pIdxCons[j].op = pTerm->eMatchOp;
- }else if( op & (WO_ISNULL|WO_IS) ){
- if( op==WO_ISNULL ){
- pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
+ if( op==WO_AUX ){
+ pIdxCons[j].op = pTerm->eMatchOp;
+ }else if( op & (WO_ISNULL|WO_IS) ){
+ if( op==WO_ISNULL ){
+ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_ISNULL;
+ }else{
+ pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
+ }
}else{
- pIdxCons[j].op = SQLITE_INDEX_CONSTRAINT_IS;
- }
- }else{
- pIdxCons[j].op = (u8)op;
- /* The direct assignment in the previous line is possible only because
- ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
- ** following asserts verify this fact. */
- assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
- assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
- assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
- assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
- assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
- assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
+ pIdxCons[j].op = (u8)op;
+ /* The direct assignment in the previous line is possible only because
+ ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
+ ** following asserts verify this fact. */
+ assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
+ assert( WO_LT==SQLITE_INDEX_CONSTRAINT_LT );
+ assert( WO_LE==SQLITE_INDEX_CONSTRAINT_LE );
+ assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
+ assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
+ assert( pTerm->eOperator&(WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_AUX) );
- if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
- && sqlite3ExprIsVector(pTerm->pExpr->pRight)
- ){
- testcase( j!=i );
- if( j<16 ) mNoOmit |= (1 << j);
- if( op==WO_LT ) pIdxCons[j].op = WO_LE;
- if( op==WO_GT ) pIdxCons[j].op = WO_GE;
+ if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
+ && sqlite3ExprIsVector(pTerm->pExpr->pRight)
+ ){
+ testcase( j!=i );
+ if( j<16 ) mNoOmit |= (1 << j);
+ if( op==WO_LT ) pIdxCons[j].op = WO_LE;
+ if( op==WO_GT ) pIdxCons[j].op = WO_GE;
+ }
}
+
+ j++;
}
-
- j++;
}
assert( j==nTerm );
pIdxInfo->nConstraint = j;
@@ -163787,6 +168442,17 @@ static sqlite3_index_info *allocateIndexInfo(
return pIdxInfo;
}
+/*
+** Free and zero the sqlite3_index_info.idxStr value if needed.
+*/
+static void freeIdxStr(sqlite3_index_info *pIdxInfo){
+ if( pIdxInfo->needToFreeIdxStr ){
+ sqlite3_free(pIdxInfo->idxStr);
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ }
+}
+
/*
** Free an sqlite3_index_info structure allocated by allocateIndexInfo()
** and possibly modified by xBestIndex methods.
@@ -163802,6 +168468,7 @@ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
pHidden->aRhs[i] = 0;
}
+ freeIdxStr(pIdxInfo);
sqlite3DbFree(db, pIdxInfo);
}
@@ -163822,9 +168489,11 @@ static void freeIndexInfo(sqlite3 *db, sqlite3_index_info *pIdxInfo){
** that this is required.
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
- sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
int rc;
+ sqlite3_vtab *pVtab;
+ assert( IsVirtual(pTab) );
+ pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
whereTraceIndexInfoInputs(p, pTab);
pParse->db->nSchemaLock++;
rc = pVtab->pModule->xBestIndex(pVtab, p);
@@ -164516,7 +169185,7 @@ static int whereInScanEst(
#endif /* SQLITE_ENABLE_STAT4 */
-#ifdef WHERETRACE_ENABLED
+#if defined(WHERETRACE_ENABLED) || defined(SQLITE_DEBUG)
/*
** Print the content of a WhereTerm object
*/
@@ -164541,6 +169210,7 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
}else{
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
}
+ iTerm = pTerm->iTerm = MAX(iTerm,pTerm->iTerm);
sqlite3DebugPrintf(
"TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x",
iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags);
@@ -164560,6 +169230,9 @@ SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
}
}
+SQLITE_PRIVATE void sqlite3ShowWhereTerm(WhereTerm *pTerm){
+ sqlite3WhereTermPrint(pTerm, 0);
+}
#endif
#ifdef WHERETRACE_ENABLED
@@ -164591,17 +169264,19 @@ SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){
** 1.002.001 t2.t2xy 2 f 010241 N 2 cost 0,56,31
*/
SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause *pWC){
+ WhereInfo *pWInfo;
if( pWC ){
- WhereInfo *pWInfo = pWC->pWInfo;
+ pWInfo = pWC->pWInfo;
int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
SrcItem *pItem = pWInfo->pTabList->a + p->iTab;
- Table *pTab = pItem->pTab;
+ Table *pTab = pItem->pSTab;
Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
p->iTab, nb, p->maskSelf, nb, p->prereq & mAll);
sqlite3DebugPrintf(" %12s",
pItem->zAlias ? pItem->zAlias : pTab->zName);
}else{
+ pWInfo = 0;
sqlite3DebugPrintf("%c%2d.%03llx.%03llx %c%d",
p->cId, p->iTab, p->maskSelf, p->prereq & 0xfff, p->cId, p->iTab);
}
@@ -164633,7 +169308,12 @@ SQLITE_PRIVATE void sqlite3WhereLoopPrint(const WhereLoop *p, const WhereClause
}else{
sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm);
}
- sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
+ if( pWInfo && pWInfo->bStarUsed && p->rStarDelta!=0 ){
+ sqlite3DebugPrintf(" cost %d,%d,%d delta=%d\n",
+ p->rSetup, p->rRun, p->nOut, p->rStarDelta);
+ }else{
+ sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
+ }
if( p->nLTerm && (sqlite3WhereTrace & 0x4000)!=0 ){
int i;
for(i=0; inLTerm; i++){
@@ -164767,7 +169447,7 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
** and Y has additional constraints that might speed the search that X lacks
** but the cost of running X is not more than the cost of running Y.
**
-** In other words, return true if the cost relationwship between X and Y
+** In other words, return true if the cost relationship between X and Y
** is inverted and needs to be adjusted.
**
** Case 1:
@@ -165153,7 +169833,7 @@ static void whereLoopOutputAdjust(
Expr *pRight = pTerm->pExpr->pRight;
int k = 0;
testcase( pTerm->pExpr->op==TK_IS );
- if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
+ if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
k = 10;
}else{
k = 20;
@@ -165305,11 +169985,8 @@ static int whereLoopAddBtreeIndex(
assert( pNew->u.btree.nBtm==0 );
opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE|WO_ISNULL|WO_IS;
}
- if( pProbe->bUnordered || pProbe->bLowQual ){
- if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
- if( pProbe->bLowQual && pSrc->fg.isIndexedBy==0 ){
- opMask &= ~(WO_EQ|WO_IN|WO_IS);
- }
+ if( pProbe->bUnordered ){
+ opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
}
assert( pNew->u.btree.nEqnColumn );
@@ -165382,6 +170059,7 @@ static int whereLoopAddBtreeIndex(
if( ExprUseXSelect(pExpr) ){
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
int i;
+ int bRedundant = 0;
nIn = 46; assert( 46==sqlite3LogEst(25) );
/* The expression may actually be of the form (x, y) IN (SELECT...).
@@ -165390,7 +170068,20 @@ static int whereLoopAddBtreeIndex(
** for each such term. The following loop checks that pTerm is the
** first such term in use, and sets nIn back to 0 if it is not. */
for(i=0; inLTerm-1; i++){
- if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
+ if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ){
+ nIn = 0;
+ if( pNew->aLTerm[i]->u.x.iField == pTerm->u.x.iField ){
+ /* Detect when two or more columns of an index match the same
+ ** column of a vector IN operater, and avoid adding the column
+ ** to the WhereLoop more than once. See tag-20250707-01
+ ** in test/rowvalue.test */
+ bRedundant = 1;
+ }
+ }
+ }
+ if( bRedundant ){
+ pNew->nLTerm--;
+ continue;
}
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
/* "x IN (value, value, ...)" */
@@ -165450,7 +170141,7 @@ static int whereLoopAddBtreeIndex(
|| (iCol>=0 && nInMul==0 && saved_nEq==pProbe->nKeyCol-1)
){
if( iCol==XN_ROWID || pProbe->uniqNotNull
- || (pProbe->nKeyCol==1 && pProbe->onError && eOp==WO_EQ)
+ || (pProbe->nKeyCol==1 && pProbe->onError && (eOp & WO_EQ))
){
pNew->wsFlags |= WHERE_ONEROW;
}else{
@@ -165583,7 +170274,7 @@ static int whereLoopAddBtreeIndex(
** 2. Stepping forward in the index pNew->nOut times to find all
** additional matching entries.
*/
- assert( pSrc->pTab->szTabRow>0 );
+ assert( pSrc->pSTab->szTabRow>0 );
if( pProbe->idxType==SQLITE_IDXTYPE_IPK ){
/* The pProbe->szIdxRow is low for an IPK table since the interior
** pages are small. Thus szIdxRow gives a good estimate of seek cost.
@@ -165591,7 +170282,7 @@ static int whereLoopAddBtreeIndex(
** under-estimate the scanning cost. */
rCostIdx = pNew->nOut + 16;
}else{
- rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
+ rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pSTab->szTabRow;
}
rCostIdx = sqlite3LogEstAdd(rLogSize, rCostIdx);
@@ -165622,7 +170313,7 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEqnColumn
&& (pNew->u.btree.nEqnKeyCol ||
- pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
+ pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
){
if( pNew->u.btree.nEq>3 ){
sqlite3ProgressCheck(pParse);
@@ -165661,6 +170352,7 @@ static int whereLoopAddBtreeIndex(
&& pProbe->hasStat1!=0
&& OptimizationEnabled(db, SQLITE_SkipScan)
&& pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
+ && pSrc->fg.fromExists==0
&& (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
){
LogEst nIter;
@@ -165745,13 +170437,13 @@ static int whereUsablePartialIndex(
if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
}
- if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){
Expr *pExpr;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
+ && !sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, -1)
&& (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
@@ -166056,9 +170748,9 @@ static int whereLoopAddBtree(
pWInfo = pBuilder->pWInfo;
pTabList = pWInfo->pTabList;
pSrc = pTabList->a + pNew->iTab;
- pTab = pSrc->pTab;
+ pTab = pSrc->pSTab;
pWC = pBuilder->pWC;
- assert( !IsVirtual(pSrc->pTab) );
+ assert( !IsVirtual(pSrc->pSTab) );
if( pSrc->fg.isIndexedBy ){
assert( pSrc->fg.isCte==0 );
@@ -166083,7 +170775,7 @@ static int whereLoopAddBtree(
sPk.idxType = SQLITE_IDXTYPE_IPK;
aiRowEstPk[0] = pTab->nRowLogEst;
aiRowEstPk[1] = 0;
- pFirst = pSrc->pTab->pIndex;
+ pFirst = pSrc->pSTab->pIndex;
if( pSrc->fg.notIndexed==0 ){
/* The real indices of the table are only considered if the
** NOT INDEXED qualifier is omitted from the FROM clause */
@@ -166100,7 +170792,6 @@ static int whereLoopAddBtree(
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
&& !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */
&& !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
- && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
&& !pSrc->fg.isRecursive /* Not a recursive common table expression. */
&& (pSrc->fg.jointype & JT_RIGHT)==0 /* Not the right tab of a RIGHT JOIN */
@@ -166166,6 +170857,7 @@ static int whereLoopAddBtree(
pNew->u.btree.nEq = 0;
pNew->u.btree.nBtm = 0;
pNew->u.btree.nTop = 0;
+ pNew->u.btree.nDistinctCol = 0;
pNew->nSkip = 0;
pNew->nLTerm = 0;
pNew->iSortIdx = 0;
@@ -166173,6 +170865,7 @@ static int whereLoopAddBtree(
pNew->prereq = mPrereq;
pNew->nOut = rSize;
pNew->u.btree.pIndex = pProbe;
+ pNew->u.btree.pOrderBy = 0;
b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
/* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
@@ -166202,6 +170895,10 @@ static int whereLoopAddBtree(
#endif
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
+ if( pSrc->fg.isSubquery ){
+ if( pSrc->fg.viaCoroutine ) pNew->wsFlags |= WHERE_COROUTINE;
+ pNew->u.btree.pOrderBy = pSrc->u4.pSubq->pSelect->pOrderBy;
+ }
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
if( rc ) break;
@@ -166239,9 +170936,11 @@ static int whereLoopAddBtree(
" according to whereIsCoveringIndex()\n", pProbe->zName));
}
}
- }else if( m==0 ){
+ }else if( m==0
+ && (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700))
+ ){
WHERETRACE(0x200,
- ("-> %s a covering index according to bitmasks\n",
+ ("-> %s is a covering index according to bitmasks\n",
pProbe->zName, m==0 ? "is" : "is not"));
pNew->wsFlags = WHERE_IDX_ONLY | WHERE_INDEXED;
}
@@ -166402,7 +171101,7 @@ static int whereLoopAddVirtualOne(
** arguments mUsable and mExclude. */
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
for(i=0; ia[pIdxCons->iTermOffset];
+ WhereTerm *pTerm = termFromWhereClause(pWC, pIdxCons->iTermOffset);
pIdxCons->usable = 0;
if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
&& (pTerm->eOperator & mExclude)==0
@@ -166421,11 +171120,10 @@ static int whereLoopAddVirtualOne(
pIdxInfo->estimatedCost = SQLITE_BIG_DBL / (double)2;
pIdxInfo->estimatedRows = 25;
pIdxInfo->idxFlags = 0;
- pIdxInfo->colUsed = (sqlite3_int64)pSrc->colUsed;
pHidden->mHandleIn = 0;
/* Invoke the virtual table xBestIndex() method */
- rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
+ rc = vtabBestIndex(pParse, pSrc->pSTab, pIdxInfo);
if( rc ){
if( rc==SQLITE_CONSTRAINT ){
/* If the xBestIndex method returns SQLITE_CONSTRAINT, that means
@@ -166433,6 +171131,7 @@ static int whereLoopAddVirtualOne(
** Make no entries in the loop table.
*/
WHERETRACE(0xffffffff, (" ^^^^--- non-viable plan rejected!\n"));
+ freeIdxStr(pIdxInfo);
return SQLITE_OK;
}
return rc;
@@ -166450,18 +171149,17 @@ static int whereLoopAddVirtualOne(
int j = pIdxCons->iTermOffset;
if( iTerm>=nConstraint
|| j<0
- || j>=pWC->nTerm
+ || (pTerm = termFromWhereClause(pWC, j))==0
|| pNew->aLTerm[iTerm]!=0
|| pIdxCons->usable==0
){
- sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
- testcase( pIdxInfo->needToFreeIdxStr );
+ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName);
+ freeIdxStr(pIdxInfo);
return SQLITE_ERROR;
}
testcase( iTerm==nConstraint-1 );
testcase( j==0 );
testcase( j==pWC->nTerm-1 );
- pTerm = &pWC->a[j];
pNew->prereq |= pTerm->prereqRight;
assert( iTermnLSlot );
pNew->aLTerm[iTerm] = pTerm;
@@ -166506,11 +171204,7 @@ static int whereLoopAddVirtualOne(
** the plan cannot be used. In these cases set variable *pbRetryLimit
** to true to tell the caller to retry with LIMIT and OFFSET
** disabled. */
- if( pIdxInfo->needToFreeIdxStr ){
- sqlite3_free(pIdxInfo->idxStr);
- pIdxInfo->idxStr = 0;
- pIdxInfo->needToFreeIdxStr = 0;
- }
+ freeIdxStr(pIdxInfo);
*pbRetryLimit = 1;
return SQLITE_OK;
}
@@ -166522,8 +171216,8 @@ static int whereLoopAddVirtualOne(
if( pNew->aLTerm[i]==0 ){
/* The non-zero argvIdx values must be contiguous. Raise an
** error if they are not */
- sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pTab->zName);
- testcase( pIdxInfo->needToFreeIdxStr );
+ sqlite3ErrorMsg(pParse,"%s.xBestIndex malfunction",pSrc->pSTab->zName);
+ freeIdxStr(pIdxInfo);
return SQLITE_ERROR;
}
}
@@ -166534,6 +171228,7 @@ static int whereLoopAddVirtualOne(
pNew->u.vtab.idxStr = pIdxInfo->idxStr;
pNew->u.vtab.isOrdered = (i8)(pIdxInfo->orderByConsumed ?
pIdxInfo->nOrderBy : 0);
+ pNew->u.vtab.bIdxNumHex = (pIdxInfo->idxFlags&SQLITE_INDEX_SCAN_HEX)!=0;
pNew->rSetup = 0;
pNew->rRun = sqlite3LogEstFromDouble(pIdxInfo->estimatedCost);
pNew->nOut = sqlite3LogEst(pIdxInfo->estimatedRows);
@@ -166578,7 +171273,7 @@ SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info *pIdxInfo, int
if( iCons>=0 && iConsnConstraint ){
CollSeq *pC = 0;
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
- Expr *pX = pHidden->pWC->a[iTerm].pExpr;
+ Expr *pX = termFromWhereClause(pHidden->pWC, iTerm)->pExpr;
if( pX->pLeft ){
pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
}
@@ -166624,7 +171319,9 @@ SQLITE_API int sqlite3_vtab_rhs_value(
rc = SQLITE_MISUSE_BKPT; /* EV: R-30545-25046 */
}else{
if( pH->aRhs[iCons]==0 ){
- WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset];
+ WhereTerm *pTerm = termFromWhereClause(
+ pH->pWC, pIdxInfo->aConstraint[iCons].iTermOffset
+ );
rc = sqlite3ValueFromExpr(
pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
SQLITE_AFF_BLOB, &pH->aRhs[iCons]
@@ -166722,7 +171419,7 @@ static int whereLoopAddVirtual(
pWC = pBuilder->pWC;
pNew = pBuilder->pNew;
pSrc = &pWInfo->pTabList->a[pNew->iTab];
- assert( IsVirtual(pSrc->pTab) );
+ assert( IsVirtual(pSrc->pSTab) );
p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit);
if( p==0 ) return SQLITE_NOMEM_BKPT;
pNew->rSetup = 0;
@@ -166736,7 +171433,7 @@ static int whereLoopAddVirtual(
}
/* First call xBestIndex() with all constraints usable. */
- WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName));
+ WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pSTab->zName));
WHERETRACE(0x800, (" VirtualOne: all usable\n"));
rc = whereLoopAddVirtualOne(
pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry
@@ -166780,9 +171477,8 @@ static int whereLoopAddVirtual(
Bitmask mNext = ALLBITS;
assert( mNext>0 );
for(i=0; ia[p->aConstraint[i].iTermOffset].prereqRight & ~mPrereq
- );
+ int iTerm = p->aConstraint[i].iTermOffset;
+ Bitmask mThis = termFromWhereClause(pWC, iTerm)->prereqRight & ~mPrereq;
if( mThis>mPrev && mThisneedToFreeIdxStr ) sqlite3_free(p->idxStr);
freeIndexInfo(pParse->db, p);
- WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
+ WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pSTab->zName, rc));
return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -166892,7 +171587,7 @@ static int whereLoopAddOr(
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pItem->pTab) ){
+ if( IsVirtual(pItem->pSTab) ){
rc = whereLoopAddVirtual(&sSubBuild, mPrereq, mUnusable);
}else
#endif
@@ -167006,7 +171701,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
mPrereq = 0;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pItem->pTab) ){
+ if( IsVirtual(pItem->pSTab) ){
SrcItem *p;
for(p=&pItem[1]; pfg.jointype & (JT_OUTER|JT_CROSS)) ){
@@ -167038,6 +171733,97 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
return rc;
}
+/* Implementation of the order-by-subquery optimization:
+**
+** WhereLoop pLoop, which the iLoop-th term of the nested loop, is really
+** a subquery or CTE that has an ORDER BY clause. See if any of the terms
+** in the subquery ORDER BY clause will satisfy pOrderBy from the outer
+** query. Mark off all satisfied terms (by setting bits in *pOBSat) and
+** return TRUE if they do. If not, return false.
+**
+** Example:
+**
+** CREATE TABLE t1(a,b,c, PRIMARY KEY(a,b));
+** CREATE TABLE t2(x,y);
+** WITH t3(p,q) AS MATERIALIZED (SELECT x+y, x-y FROM t2 ORDER BY x+y)
+** SELECT * FROM t3 JOIN t1 ON a=q ORDER BY p, b;
+**
+** The CTE named "t3" comes out in the natural order of "p", so the first
+** first them of "ORDER BY p,b" is satisfied by a sequential scan of "t3"
+** and sorting only needs to occur on the second term "b".
+**
+** Limitations:
+**
+** (1) The optimization is not applied if the outer ORDER BY contains
+** a COLLATE clause. The optimization might be applied if the
+** outer ORDER BY uses NULLS FIRST, NULLS LAST, ASC, and/or DESC as
+** long as the subquery ORDER BY does the same. But if the
+** outer ORDER BY uses COLLATE, even a redundant COLLATE, the
+** optimization is bypassed.
+**
+** (2) The subquery ORDER BY terms must exactly match subquery result
+** columns, including any COLLATE annotations. This routine relies
+** on iOrderByCol to do matching between order by terms and result
+** columns, and iOrderByCol will not be set if the result column
+** and ORDER BY collations differ.
+**
+** (3) The subquery and outer ORDER BY can be in opposite directions as
+** long as the subquery is materialized. If the subquery is
+** implemented as a co-routine, the sort orders must be in the same
+** direction because there is no way to run a co-routine backwards.
+*/
+static SQLITE_NOINLINE int wherePathMatchSubqueryOB(
+ WhereInfo *pWInfo, /* The WHERE clause */
+ WhereLoop *pLoop, /* The nested loop term that is a subquery */
+ int iLoop, /* Which level of the nested loop. 0==outermost */
+ int iCur, /* Cursor used by the this loop */
+ ExprList *pOrderBy, /* The ORDER BY clause on the whole query */
+ Bitmask *pRevMask, /* When loops need to go in reverse order */
+ Bitmask *pOBSat /* Which terms of pOrderBy are satisfied so far */
+){
+ int iOB; /* Index into pOrderBy->a[] */
+ int jSub; /* Index into pSubOB->a[] */
+ u8 rev = 0; /* True if iOB and jSub sort in opposite directions */
+ u8 revIdx = 0; /* Sort direction for jSub */
+ Expr *pOBExpr; /* Current term of outer ORDER BY */
+ ExprList *pSubOB; /* Complete ORDER BY on the subquery */
+
+ pSubOB = pLoop->u.btree.pOrderBy;
+ assert( pSubOB!=0 );
+ for(iOB=0; (MASKBIT(iOB) & *pOBSat)!=0; iOB++){}
+ for(jSub=0; jSubnExpr && iOBnExpr; jSub++, iOB++){
+ if( pSubOB->a[jSub].u.x.iOrderByCol==0 ) break;
+ pOBExpr = pOrderBy->a[iOB].pExpr;
+ if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) break;
+ if( pOBExpr->iTable!=iCur ) break;
+ if( pOBExpr->iColumn!=pSubOB->a[jSub].u.x.iOrderByCol-1 ) break;
+ if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
+ u8 sfOB = pOrderBy->a[iOB].fg.sortFlags; /* sortFlags for iOB */
+ u8 sfSub = pSubOB->a[jSub].fg.sortFlags; /* sortFlags for jSub */
+ if( (sfSub & KEYINFO_ORDER_BIGNULL) != (sfOB & KEYINFO_ORDER_BIGNULL) ){
+ break;
+ }
+ revIdx = sfSub & KEYINFO_ORDER_DESC;
+ if( jSub>0 ){
+ if( (rev^revIdx)!=(sfOB & KEYINFO_ORDER_DESC) ){
+ break;
+ }
+ }else{
+ rev = revIdx ^ (sfOB & KEYINFO_ORDER_DESC);
+ if( rev ){
+ if( (pLoop->wsFlags & WHERE_COROUTINE)!=0 ){
+ /* Cannot run a co-routine in reverse order */
+ break;
+ }
+ *pRevMask |= MASKBIT(iLoop);
+ }
+ }
+ }
+ *pOBSat |= MASKBIT(iOB);
+ }
+ return jSub>0;
+}
+
/*
** Examine a WherePath (with the addition of the extra WhereLoop of the 6th
** parameters) to see if it outputs rows in the requested ORDER BY
@@ -167138,10 +171924,12 @@ static i8 wherePathSatisfiesOrderBy(
&& ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
){
obSat = obDone;
+ }else{
+ /* No further ORDER BY terms may be matched. So this call should
+ ** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */
+ isOrderDistinct = 0;
}
break;
- }else if( wctrlFlags & WHERE_DISTINCTBY ){
- pLoop->u.btree.nDistinctCol = 0;
}
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
@@ -167183,9 +171971,18 @@ static i8 wherePathSatisfiesOrderBy(
if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
if( pLoop->wsFlags & WHERE_IPK ){
+ if( pLoop->u.btree.pOrderBy
+ && OptimizationEnabled(db, SQLITE_OrderBySubq)
+ && wherePathMatchSubqueryOB(pWInfo,pLoop,iLoop,iCur,
+ pOrderBy,pRevMask, &obSat)
+ ){
+ nColumn = 0;
+ isOrderDistinct = 0;
+ }else{
+ nColumn = 1;
+ }
pIndex = 0;
nKeyCol = 0;
- nColumn = 1;
}else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
return 0;
}else{
@@ -167195,7 +171992,7 @@ static i8 wherePathSatisfiesOrderBy(
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|| !HasRowid(pIndex->pTable));
/* All relevant terms of the index must also be non-NULL in order
- ** for isOrderDistinct to be true. So the isOrderDistint value
+ ** for isOrderDistinct to be true. So the isOrderDistinct value
** computed here might be a false positive. Corrections will be
** made at tag-20210426-1 below */
isOrderDistinct = IsUniqueIndex(pIndex)
@@ -167280,7 +172077,7 @@ static i8 wherePathSatisfiesOrderBy(
}
/* Find the ORDER BY term that corresponds to the j-th column
- ** of the index and mark that ORDER BY term off
+ ** of the index and mark that ORDER BY term having been satisfied.
*/
isMatch = 0;
for(i=0; bOnce && inLevel; /* Number of terms in the join */
+ WhereLoop *pWLoop; /* For looping over WhereLoops */
+
+#ifdef SQLITE_DEBUG
+ /* The star-query detection code below makes use of the following
+ ** properties of the WhereLoop list, so verify them before
+ ** continuing:
+ ** (1) .maskSelf is the bitmask corresponding to .iTab
+ ** (2) The WhereLoop list is in ascending .iTab order
+ */
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+ assert( pWLoop->maskSelf==MASKBIT(pWLoop->iTab) );
+ assert( pWLoop->pNextLoop==0 || pWLoop->iTab<=pWLoop->pNextLoop->iTab );
+ }
+#endif /* SQLITE_DEBUG */
+
+ if( nLoop>=5
+ && !pWInfo->bStarDone
+ && OptimizationEnabled(pWInfo->pParse->db, SQLITE_StarQuery)
+ ){
+ SrcItem *aFromTabs; /* All terms of the FROM clause */
+ int iFromIdx; /* Term of FROM clause is the candidate fact-table */
+ Bitmask m; /* Bitmask for candidate fact-table */
+ Bitmask mSelfJoin = 0; /* Tables that cannot be dimension tables */
+ WhereLoop *pStart; /* Where to start searching for dimension-tables */
+
+ pWInfo->bStarDone = 1; /* Only do this computation once */
+
+ /* Look for fact tables with four or more dimensions where the
+ ** dimension tables are not separately from the fact tables by an outer
+ ** or cross join. Adjust cost weights if found.
+ */
+ assert( !pWInfo->bStarUsed );
+ aFromTabs = pWInfo->pTabList->a;
+ pStart = pWInfo->pLoops;
+ for(iFromIdx=0, m=1; iFromIdxfg.jointype & (JT_OUTER|JT_CROSS))!=0 ){
+ /* If the candidate fact-table is the right table of an outer join
+ ** restrict the search for dimension-tables to be tables to the right
+ ** of the fact-table. */
+ if( iFromIdx+4 > nLoop ) break; /* Impossible to reach nDep>=4 */
+ while( pStart && pStart->iTab<=iFromIdx ){
+ pStart = pStart->pNextLoop;
+ }
+ }
+ for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){
+ if( (aFromTabs[pWLoop->iTab].fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){
+ /* Fact-tables and dimension-tables cannot be separated by an
+ ** outer join (at least for the definition of fact- and dimension-
+ ** used by this heuristic). */
+ break;
+ }
+ if( (pWLoop->prereq & m)!=0 /* pWInfo depends on iFromIdx */
+ && (pWLoop->maskSelf & mSeen)==0 /* pWInfo not already a dependency */
+ && (pWLoop->maskSelf & mSelfJoin)==0 /* Not a self-join */
+ ){
+ if( aFromTabs[pWLoop->iTab].pSTab==pFactTab->pSTab ){
+ mSelfJoin |= m;
+ }else{
+ nDep++;
+ mSeen |= pWLoop->maskSelf;
+ }
+ }
+ }
+ if( nDep<=3 ) continue;
+
+ /* If we reach this point, it means that pFactTab is a fact table
+ ** with four or more dimensions connected by inner joins. Proceed
+ ** to make cost adjustments. */
+
+#ifdef WHERETRACE_ENABLED
+ /* Make sure rStarDelta values are initialized */
+ if( !pWInfo->bStarUsed ){
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+ pWLoop->rStarDelta = 0;
+ }
+ }
+#endif
+ pWInfo->bStarUsed = 1;
+
+ /* Compute the maximum cost of any WhereLoop for the
+ ** fact table plus one epsilon */
+ mxRun = LOGEST_MIN;
+ for(pWLoop=pStart; pWLoop; pWLoop=pWLoop->pNextLoop){
+ if( pWLoop->iTabiTab>iFromIdx ) break;
+ if( pWLoop->rRun>mxRun ) mxRun = pWLoop->rRun;
+ }
+ if( ALWAYS(mxRunpNextLoop){
+ if( (pWLoop->maskSelf & mSeen)==0 ) continue;
+ if( pWLoop->nLTerm ) continue;
+ if( pWLoop->rRuniTab;
+ sqlite3DebugPrintf(
+ "Increase SCAN cost of dimension %s(%d) of fact %s(%d) to %d\n",
+ pDim->zAlias ? pDim->zAlias: pDim->pSTab->zName, pWLoop->iTab,
+ pFactTab->zAlias ? pFactTab->zAlias : pFactTab->pSTab->zName,
+ iFromIdx, mxRun
+ );
+ }
+ pWLoop->rStarDelta = mxRun - pWLoop->rRun;
+#endif /* WHERETRACE_ENABLED */
+ pWLoop->rRun = mxRun;
+ }
+ }
+ }
+#ifdef WHERETRACE_ENABLED /* 0x80000 */
+ if( (sqlite3WhereTrace & 0x80000)!=0 && pWInfo->bStarUsed ){
+ sqlite3DebugPrintf("WhereLoops changed by star-query heuristic:\n");
+ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
+ if( pWLoop->rStarDelta ){
+ sqlite3WhereLoopPrint(pWLoop, &pWInfo->sWC);
+ }
+ }
+ }
+#endif
+ }
+ return pWInfo->bStarUsed ? 18 : 12;
+}
+
+/*
+** Two WhereLoop objects, pCandidate and pBaseline, are known to have the
+** same cost. Look deep into each to see if pCandidate is even slightly
+** better than pBaseline. Return false if it is, if pCandidate is is preferred.
+** Return true if pBaseline is preferred or if we cannot tell the difference.
+**
+** Result Meaning
+** -------- ----------------------------------------------------------
+** true We cannot tell the difference in pCandidate and pBaseline
+** false pCandidate seems like a better choice than pBaseline
+*/
+static SQLITE_NOINLINE int whereLoopIsNoBetter(
+ const WhereLoop *pCandidate,
+ const WhereLoop *pBaseline
+){
+ if( (pCandidate->wsFlags & WHERE_INDEXED)==0 ) return 1;
+ if( (pBaseline->wsFlags & WHERE_INDEXED)==0 ) return 1;
+ if( pCandidate->u.btree.pIndex->szIdxRow <
+ pBaseline->u.btree.pIndex->szIdxRow ) return 0;
+ return 1;
+}
+
/*
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
** attempts to find the lowest cost path that visits each WhereLoop
@@ -167508,7 +172515,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
int mxI = 0; /* Index of next entry to replace */
int nOrderBy; /* Number of ORDER BY clause terms */
LogEst mxCost = 0; /* Maximum cost of a set of paths */
- LogEst mxUnsorted = 0; /* Maximum unsorted cost of a set of path */
+ LogEst mxUnsort = 0; /* Maximum unsorted cost of a set of path */
int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */
WherePath *aFrom; /* All nFrom paths at the previous level */
WherePath *aTo; /* The nTo best paths at the current level */
@@ -167522,13 +172529,27 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pParse = pWInfo->pParse;
nLoop = pWInfo->nLevel;
- /* TUNING: For simple queries, only the best path is tracked.
- ** For 2-way joins, the 5 best paths are followed.
- ** For joins of 3 or more tables, track the 10 best paths */
- mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
- assert( nLoop<=pWInfo->pTabList->nSrc );
WHERETRACE(0x002, ("---- begin solver. (nRowEst=%d, nQueryLoop=%d)\n",
nRowEst, pParse->nQueryLoop));
+ /* TUNING: mxChoice is the maximum number of possible paths to preserve
+ ** at each step. Based on the number of loops in the FROM clause:
+ **
+ ** nLoop mxChoice
+ ** ----- --------
+ ** 1 1 // the most common case
+ ** 2 5
+ ** 3+ 12 or 18 // see computeMxChoice()
+ */
+ if( nLoop<=1 ){
+ mxChoice = 1;
+ }else if( nLoop==2 ){
+ mxChoice = 5;
+ }else if( pParse->nErr ){
+ mxChoice = 1;
+ }else{
+ mxChoice = computeMxChoice(pWInfo);
+ }
+ assert( nLoop<=pWInfo->pTabList->nSrc );
/* If nRowEst is zero and there is an ORDER BY clause, ignore it. In this
** case the purpose of this call is to estimate the number of rows returned
@@ -167593,7 +172614,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
LogEst nOut; /* Rows visited by (pFrom+pWLoop) */
LogEst rCost; /* Cost of path (pFrom+pWLoop) */
- LogEst rUnsorted; /* Unsorted cost of (pFrom+pWLoop) */
+ LogEst rUnsort; /* Unsorted cost of (pFrom+pWLoop) */
i8 isOrdered; /* isOrdered for (pFrom+pWLoop) */
Bitmask maskNew; /* Mask of src visited by (..) */
Bitmask revMask; /* Mask of rev-order loops for (..) */
@@ -167611,8 +172632,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
/* At this point, pWLoop is a candidate to be the next loop.
** Compute its cost */
- rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
- rUnsorted = sqlite3LogEstAdd(rUnsorted, pFrom->rUnsorted);
+ rUnsort = pWLoop->rRun + pFrom->nRow;
+ if( pWLoop->rSetup ){
+ rUnsort = sqlite3LogEstAdd(pWLoop->rSetup, rUnsort);
+ }
+ rUnsort = sqlite3LogEstAdd(rUnsort, pFrom->rUnsort);
nOut = pFrom->nRow + pWLoop->nOut;
maskNew = pFrom->maskLoop | pWLoop->maskSelf;
isOrdered = pFrom->isOrdered;
@@ -167634,31 +172658,39 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
** extra encouragement to the query planner to select a plan
** where the rows emerge in the correct order without any sorting
** required. */
- rCost = sqlite3LogEstAdd(rUnsorted, aSortCost[isOrdered]) + 3;
+ rCost = sqlite3LogEstAdd(rUnsort, aSortCost[isOrdered]) + 3;
WHERETRACE(0x002,
("---- sort cost=%-3d (%d/%d) increases cost %3d to %-3d\n",
aSortCost[isOrdered], (nOrderBy-isOrdered), nOrderBy,
- rUnsorted, rCost));
+ rUnsort, rCost));
}else{
- rCost = rUnsorted;
- rUnsorted -= 2; /* TUNING: Slight bias in favor of no-sort plans */
+ rCost = rUnsort;
+ rUnsort -= 2; /* TUNING: Slight bias in favor of no-sort plans */
}
/* Check to see if pWLoop should be added to the set of
** mxChoice best-so-far paths.
**
** First look for an existing path among best-so-far paths
- ** that covers the same set of loops and has the same isOrdered
- ** setting as the current path candidate.
+ ** that:
+ ** (1) covers the same set of loops, and
+ ** (2) has a compatible isOrdered value.
+ **
+ ** "Compatible isOrdered value" means either
+ ** (A) both have isOrdered==-1, or
+ ** (B) both have isOrder>=0, or
+ ** (C) ordering does not matter because this is the last round
+ ** of the solver.
**
** The term "((pTo->isOrdered^isOrdered)&0x80)==0" is equivalent
** to (pTo->isOrdered==(-1))==(isOrdered==(-1))" for the range
** of legal values for isOrdered, -1..64.
*/
+ testcase( nTo==0 );
for(jj=0, pTo=aTo; jjmaskLoop==maskNew
- && ((pTo->isOrdered^isOrdered)&0x80)==0
+ && ( ((pTo->isOrdered^isOrdered)&0x80)==0 || iLoop==nLoop-1 )
){
testcase( jj==nTo-1 );
break;
@@ -167667,7 +172699,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( jj>=nTo ){
/* None of the existing best-so-far paths match the candidate. */
if( nTo>=mxChoice
- && (rCost>mxCost || (rCost==mxCost && rUnsorted>=mxUnsorted))
+ && (rCost>mxCost || (rCost==mxCost && rUnsort>=mxUnsort))
){
/* The current candidate is no better than any of the mxChoice
** paths currently in the best-so-far buffer. So discard
@@ -167675,7 +172707,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort,
isOrdered>=0 ? isOrdered+'0' : '?');
}
#endif
@@ -167694,7 +172726,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf("New %s cost=%-3d,%3d,%3d order=%c\n",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort,
isOrdered>=0 ? isOrdered+'0' : '?');
}
#endif
@@ -167705,24 +172737,23 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
** pTo or if the candidate should be skipped.
**
** The conditional is an expanded vector comparison equivalent to:
- ** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted)
+ ** (pTo->rCost,pTo->nRow,pTo->rUnsort) <= (rCost,nOut,rUnsort)
*/
- if( pTo->rCostrCost==rCost
- && (pTo->nRownRow==nOut && pTo->rUnsorted<=rUnsorted)
- )
- )
+ if( (pTo->rCostrCost==rCost && pTo->nRowrCost==rCost && pTo->nRow==nOut && pTo->rUnsortrCost==rCost && pTo->nRow==nOut && pTo->rUnsort==rUnsort
+ && whereLoopIsNoBetter(pWLoop, pTo->aLoop[iLoop]) )
){
#ifdef WHERETRACE_ENABLED /* 0x4 */
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
"Skip %s cost=%-3d,%3d,%3d order=%c",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort,
isOrdered>=0 ? isOrdered+'0' : '?');
sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
+ pTo->rUnsort, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
/* Discard the candidate path from further consideration */
@@ -167736,11 +172767,11 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( sqlite3WhereTrace&0x4 ){
sqlite3DebugPrintf(
"Update %s cost=%-3d,%3d,%3d order=%c",
- wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
+ wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsort,
isOrdered>=0 ? isOrdered+'0' : '?');
sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n",
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
- pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
+ pTo->rUnsort, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
}
#endif
}
@@ -167749,20 +172780,20 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pTo->revLoop = revMask;
pTo->nRow = nOut;
pTo->rCost = rCost;
- pTo->rUnsorted = rUnsorted;
+ pTo->rUnsort = rUnsort;
pTo->isOrdered = isOrdered;
memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
pTo->aLoop[iLoop] = pWLoop;
if( nTo>=mxChoice ){
mxI = 0;
mxCost = aTo[0].rCost;
- mxUnsorted = aTo[0].nRow;
+ mxUnsort = aTo[0].nRow;
for(jj=1, pTo=&aTo[1]; jjrCost>mxCost
- || (pTo->rCost==mxCost && pTo->rUnsorted>mxUnsorted)
+ || (pTo->rCost==mxCost && pTo->rUnsort>mxUnsort)
){
mxCost = pTo->rCost;
- mxUnsorted = pTo->rUnsorted;
+ mxUnsort = pTo->rUnsort;
mxI = jj;
}
}
@@ -167772,17 +172803,32 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
#ifdef WHERETRACE_ENABLED /* >=2 */
if( sqlite3WhereTrace & 0x02 ){
+ LogEst rMin, rFloor = 0;
+ int nDone = 0;
+ int nProgress;
sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
- for(ii=0, pTo=aTo; iirCost, pTo->nRow,
- pTo->isOrdered>=0 ? (pTo->isOrdered+'0') : '?');
- if( pTo->isOrdered>0 ){
- sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
- }else{
- sqlite3DebugPrintf("\n");
+ do{
+ nProgress = 0;
+ rMin = 0x7fff;
+ for(ii=0, pTo=aTo; iirCost>rFloor && pTo->rCostrCost;
}
- }
+ for(ii=0, pTo=aTo; ii