summaryrefslogtreecommitdiff
path: root/ext/sqlite3/libsqlite/sqlite3.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite3/libsqlite/sqlite3.c')
-rw-r--r--ext/sqlite3/libsqlite/sqlite3.c20088
1 files changed, 8342 insertions, 11746 deletions
diff --git a/ext/sqlite3/libsqlite/sqlite3.c b/ext/sqlite3/libsqlite/sqlite3.c
index 6cedac9c30..6389f6177b 100644
--- a/ext/sqlite3/libsqlite/sqlite3.c
+++ b/ext/sqlite3/libsqlite/sqlite3.c
@@ -1,10 +1,6 @@
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma optimize("", off)
-#endif
-
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.6.2. By combining all the individual C code files into this
+** version 3.6.1. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a one translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -15,13 +11,13 @@
** programs, you need this file and the "sqlite3.h" header file that defines
** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy in the first
-** 6728 lines past this header comment.) Additional code files may be
+** 6279 lines past this header comment.) Additional code files may be
** needed if you want a wrapper to interface SQLite with your choice of
** programming language. The code for the "sqlite3" command-line shell
** is also in a separate file. This file contains only code for the core
** SQLite library.
**
-** This amalgamation was generated on 2008-11-26 17:54:40 UTC.
+** This amalgamation was generated on 2008-08-05 21:36:42 UTC.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@@ -379,16 +375,6 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
#endif
/*
-** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
-** It determines whether or not the features related to
-** SQLITE_CONFIG_MEMSTATUS are availabe by default or not. This value can
-** be overridden at runtime using the sqlite3_config() API.
-*/
-#if !defined(SQLITE_DEFAULT_MEMSTATUS)
-# define SQLITE_DEFAULT_MEMSTATUS 1
-#endif
-
-/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
@@ -401,12 +387,12 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+defined(SQLITE_POW2_MEMORY_SIZE)>1
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+ defined(SQLITE_POW2_MEMORY_SIZE)>1
# error "At most one of the following compile-time configuration options\
is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\
SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE"
#endif
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+defined(SQLITE_POW2_MEMORY_SIZE)==0
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+ defined(SQLITE_POW2_MEMORY_SIZE)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif
@@ -435,9 +421,6 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */
#endif
-/*
-** The TCL headers are only needed when compiling the TCL bindings.
-*/
#if defined(SQLITE_TCL) || defined(TCLSH)
# include <tcl.h>
#endif
@@ -509,22 +492,6 @@ extern "C" {
#endif
/*
-** These no-op macros are used in front of interfaces to mark those
-** interfaces as either deprecated or experimental. New applications
-** should not use deprecated intrfaces - they are support for backwards
-** compatibility only. Application writers should be aware that
-** experimental interfaces are subject to change in point releases.
-**
-** These macros used to resolve to various kinds of compiler magic that
-** would generate warning messages when they were used. But that
-** compiler magic ended up generating such a flurry of bug reports
-** that we have taken it all out and gone back to using simple
-** noop macros.
-*/
-#define SQLITE_DEPRECATED
-#define SQLITE_EXPERIMENTAL
-
-/*
** Ensure these symbols were not defined by some previous header file.
*/
#ifdef SQLITE_VERSION
@@ -564,8 +531,8 @@ extern "C" {
** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z
** are the major version, minor version, and release number.
*/
-#define SQLITE_VERSION "3.6.6.2"
-#define SQLITE_VERSION_NUMBER 3006006
+#define SQLITE_VERSION "3.6.1"
+#define SQLITE_VERSION_NUMBER 3006001
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@@ -602,9 +569,8 @@ SQLITE_API int sqlite3_libversion_number(void);
** CAPI3REF: Test To See If The Library Is Threadsafe {H10100} <S60100>
**
** SQLite can be compiled with or without mutexes. When
-** the [SQLITE_THREADSAFE] C preprocessor macro 1 or 2, mutexes
-** are enabled and SQLite is threadsafe. When the
-** [SQLITE_THREADSAFE] macro is 0,
+** the [SQLITE_THREADSAFE] C preprocessor macro is true, mutexes
+** are enabled and SQLite is threadsafe. When that macro is false,
** the mutexes are omitted. Without the mutexes, it is not safe
** to use SQLite concurrently from more than one thread.
**
@@ -626,15 +592,19 @@ SQLITE_API int sqlite3_libversion_number(void);
** only the default compile-time setting, not any run-time changes
** to that setting.
**
-** See the [threading mode] documentation for additional information.
-**
** INVARIANTS:
**
-** {H10101} The [sqlite3_threadsafe()] function shall return zero if
-** and only if SQLite was compiled with mutexing code omitted.
+** {H10101} The [sqlite3_threadsafe()] function shall return nonzero if
+** SQLite was compiled with the its mutexes enabled by default
+** or zero if SQLite was compiled such that mutexes are
+** permanently disabled.
**
** {H10102} The value returned by the [sqlite3_threadsafe()] function
-** shall remain the same across calls to [sqlite3_config()].
+** shall not change when mutex setting are modified at
+** runtime using the [sqlite3_config()] interface and
+** especially the [SQLITE_CONFIG_SINGLETHREAD],
+** [SQLITE_CONFIG_MULTITHREAD], [SQLITE_CONFIG_SERIALIZED],
+** and [SQLITE_CONFIG_MUTEX] verbs.
*/
SQLITE_API int sqlite3_threadsafe(void);
@@ -731,7 +701,7 @@ typedef sqlite_uint64 sqlite3_uint64;
** an [SQLITE_BUSY] error code.
**
** {H12015} A call to [sqlite3_close(C)] where C is a NULL pointer shall
-** be a harmless no-op returning SQLITE_OK.
+** return SQLITE_OK.
**
** {H12019} When [sqlite3_close(C)] is invoked on a [database connection] C
** that has a pending transaction, the transaction shall be
@@ -835,14 +805,12 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** *E to NULL if E is not NULL and there are no errors.
**
** {H12137} The [sqlite3_exec(D,S,C,A,E)] function shall set the [error code]
-** and message accessible via [sqlite3_errcode()],
-** [sqlite3_extended_errcode()],
+** and message accessible via [sqlite3_errcode()],
** [sqlite3_errmsg()], and [sqlite3_errmsg16()].
**
** {H12138} If the S parameter to [sqlite3_exec(D,S,C,A,E)] is NULL or an
** empty string or contains nothing other than whitespace, comments,
** and/or semicolons, then results of [sqlite3_errcode()],
-** [sqlite3_extended_errcode()],
** [sqlite3_errmsg()], and [sqlite3_errmsg16()]
** shall reset to indicate no errors.
**
@@ -963,7 +931,6 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8))
#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8))
#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
-#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
/*
** CAPI3REF: Flags For File Open Operations {H10230} <H11120> <H12700>
@@ -986,7 +953,6 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_SUBJOURNAL 0x00002000
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000
#define SQLITE_OPEN_NOMUTEX 0x00008000
-#define SQLITE_OPEN_FULLMUTEX 0x00010000
/*
** CAPI3REF: Device Characteristics {H10240} <H11120>
@@ -1044,7 +1010,7 @@ SQLITE_API int sqlite3_exec(
** sync operation only needs to flush data to mass storage. Inode
** information need not be flushed. The SQLITE_SYNC_NORMAL flag means
** to use normal fsync() semantics. The SQLITE_SYNC_FULL flag means
-** to use Mac OS X style fullsync instead of fsync().
+** to use Mac OS-X style fullsync instead of fsync().
*/
#define SQLITE_SYNC_NORMAL 0x00002
#define SQLITE_SYNC_FULL 0x00003
@@ -1076,7 +1042,7 @@ struct sqlite3_file {
**
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
-** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
+** The second choice is a Mac OS-X style fullsync. The [SQLITE_SYNC_DATAONLY]
** flag may be ORed in to indicate that only the data of the file
** and not its inode needs to be synced.
**
@@ -1139,12 +1105,6 @@ struct sqlite3_file {
** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
** information is written to disk in the same order as calls
** to xWrite().
-**
-** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill
-** in the unread portions of the buffer with zeros. A VFS that
-** fails to zero-fill short reads might seem to work. However,
-** failure to zero-fill short reads will eventually lead to
-** database corruption.
*/
typedef struct sqlite3_io_methods sqlite3_io_methods;
struct sqlite3_io_methods {
@@ -1371,24 +1331,24 @@ struct sqlite3_vfs {
** sqlite3_os_init(). Similarly, sqlite3_shutdown()
** shall invoke sqlite3_os_end().
**
-** The sqlite3_initialize() routine returns [SQLITE_OK] on success.
+** The sqlite3_initialize() routine returns SQLITE_OK on success.
** If for some reason, sqlite3_initialize() is unable to initialize
** the library (perhaps it is unable to allocate a needed resource such
-** as a mutex) it returns an [error code] other than [SQLITE_OK].
+** as a mutex) it returns an [error code] other than SQLITE_OK.
**
** The sqlite3_initialize() routine is called internally by many other
** 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
-** already. However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT]
+** 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
** prior to using any other SQLite interface. For maximum portability,
** it is recommended that applications always invoke sqlite3_initialize()
** directly prior to using any other SQLite interface. Future releases
** of SQLite may require this. In other words, the behavior exhibited
-** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the
+** when SQLite is compiled with SQLITE_OMIT_AUTOINIT might become the
** default behavior in some future release of SQLite.
**
** The sqlite3_os_init() routine does operating-system specific
@@ -1406,11 +1366,11 @@ struct sqlite3_vfs {
** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate
** implementations for sqlite3_os_init() and sqlite3_os_end()
** are built into SQLite when it is compiled for unix, windows, or os/2.
-** When built for other platforms (using the [SQLITE_OS_OTHER=1] compile-time
+** When built for other platforms (using the SQLITE_OS_OTHER=1 compile-time
** option) the application must supply a suitable implementation for
** sqlite3_os_init() and sqlite3_os_end(). An application-supplied
** implementation of sqlite3_os_init() or sqlite3_os_end()
-** must return [SQLITE_OK] on success and some other [error code] upon
+** must return SQLITE_OK on success and some other [error code] upon
** failure.
*/
SQLITE_API int sqlite3_initialize(void);
@@ -1419,7 +1379,7 @@ SQLITE_API int sqlite3_os_init(void);
SQLITE_API int sqlite3_os_end(void);
/*
-** CAPI3REF: Configuring The SQLite Library {H14100} <S20000><S30200>
+** CAPI3REF: Configuring The SQLite Library {H10145} <S20000><S30200>
** EXPERIMENTAL
**
** The sqlite3_config() interface is used to make global configuration
@@ -1442,103 +1402,14 @@ SQLITE_API int sqlite3_os_end(void);
** vary depending on the [SQLITE_CONFIG_SINGLETHREAD | configuration option]
** in the first argument.
**
-** When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
+** When a configuration option is set, sqlite3_config() returns SQLITE_OK.
** If the option is unknown or SQLite is unable to set the option
** then this routine returns a non-zero [error code].
-**
-** INVARIANTS:
-**
-** {H14103} A successful invocation of [sqlite3_config()] shall return
-** [SQLITE_OK].
-**
-** {H14106} The [sqlite3_config()] interface shall return [SQLITE_MISUSE]
-** if it is invoked in between calls to [sqlite3_initialize()] and
-** [sqlite3_shutdown()].
-**
-** {H14120} A successful call to [sqlite3_config]([SQLITE_CONFIG_SINGLETHREAD])
-** shall set the default [threading mode] to Single-thread.
-**
-** {H14123} A successful call to [sqlite3_config]([SQLITE_CONFIG_MULTITHREAD])
-** shall set the default [threading mode] to Multi-thread.
-**
-** {H14126} A successful call to [sqlite3_config]([SQLITE_CONFIG_SERIALIZED])
-** shall set the default [threading mode] to Serialized.
-**
-** {H14129} A successful call to [sqlite3_config]([SQLITE_CONFIG_MUTEX],X)
-** where X is a pointer to an initialized [sqlite3_mutex_methods]
-** object shall cause all subsequent mutex operations performed
-** by SQLite to use the mutex methods that were present in X
-** during the call to [sqlite3_config()].
-**
-** {H14132} A successful call to [sqlite3_config]([SQLITE_CONFIG_GETMUTEX],X)
-** where X is a pointer to an [sqlite3_mutex_methods] object
-** shall overwrite the content of [sqlite3_mutex_methods] object
-** with the mutex methods currently in use by SQLite.
-**
-** {H14135} A successful call to [sqlite3_config]([SQLITE_CONFIG_MALLOC],M)
-** where M is a pointer to an initialized [sqlite3_mem_methods]
-** object shall cause all subsequent memory allocation operations
-** performed by SQLite to use the methods that were present in
-** M during the call to [sqlite3_config()].
-**
-** {H14138} A successful call to [sqlite3_config]([SQLITE_CONFIG_GETMALLOC],M)
-** where M is a pointer to an [sqlite3_mem_methods] object shall
-** overwrite the content of [sqlite3_mem_methods] object with
-** the memory allocation methods currently in use by
-** SQLite.
-**
-** {H14141} A successful call to [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],1)
-** shall enable the memory allocation status collection logic.
-**
-** {H14144} A successful call to [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],0)
-** shall disable the memory allocation status collection logic.
-**
-** {H14147} The memory allocation status collection logic shall be
-** enabled by default.
-**
-** {H14150} A successful call to [sqlite3_config]([SQLITE_CONFIG_SCRATCH],S,Z,N)
-** where Z and N are non-negative integers and
-** S is a pointer to an aligned memory buffer not less than
-** Z*N bytes in size shall cause S to be used by the
-** [scratch memory allocator] for as many as N simulataneous
-** allocations each of size Z.
-**
-** {H14153} A successful call to [sqlite3_config]([SQLITE_CONFIG_SCRATCH],S,Z,N)
-** where S is a NULL pointer shall disable the
-** [scratch memory allocator].
-**
-** {H14156} A successful call to
-** [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],S,Z,N)
-** where Z and N are non-negative integers and
-** S is a pointer to an aligned memory buffer not less than
-** Z*N bytes in size shall cause S to be used by the
-** [pagecache memory allocator] for as many as N simulataneous
-** allocations each of size Z.
-**
-** {H14159} A successful call to
-** [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],S,Z,N)
-** where S is a NULL pointer shall disable the
-** [pagecache memory allocator].
-**
-** {H14162} A successful call to [sqlite3_config]([SQLITE_CONFIG_HEAP],H,Z,N)
-** where Z and N are non-negative integers and
-** H is a pointer to an aligned memory buffer not less than
-** Z bytes in size shall enable the [memsys5] memory allocator
-** and cause it to use buffer S as its memory source and to use
-** a minimum allocation size of N.
-**
-** {H14165} A successful call to [sqlite3_config]([SQLITE_CONFIG_HEAP],H,Z,N)
-** where H is a NULL pointer shall disable the
-** [memsys5] memory allocator.
-**
-** {H14168} A successful call to [sqlite3_config]([SQLITE_CONFIG_LOOKASIDE],Z,N)
-** shall cause the default [lookaside memory allocator] configuration
-** for new [database connections] to be N slots of Z bytes each.
-*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
-
-/*
-** CAPI3REF: Configure database connections {H14200} <S20000>
+*/
+SQLITE_API int sqlite3_config(int, ...);
+
+/*
+** CAPI3REF: Configure database connections {H10180} <S20000>
** EXPERIMENTAL
**
** The sqlite3_db_config() interface is used to make configuration
@@ -1555,40 +1426,8 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
** The only choice for this value is [SQLITE_DBCONFIG_LOOKASIDE].
** New verbs are likely to be added in future releases of SQLite.
** Additional arguments depend on the verb.
-**
-** INVARIANTS:
-**
-** {H14203} A call to [sqlite3_db_config(D,V,...)] shall return [SQLITE_OK]
-** if and only if the call is successful.
-**
-** {H14206} If one or more slots of the [lookaside memory allocator] for
-** [database connection] D are in use, then a call to
-** [sqlite3_db_config](D,[SQLITE_DBCONFIG_LOOKASIDE],...) shall
-** fail with an [SQLITE_BUSY] return code.
-**
-** {H14209} A successful call to
-** [sqlite3_db_config](D,[SQLITE_DBCONFIG_LOOKASIDE],B,Z,N) where
-** D is an open [database connection] and Z and N are positive
-** integers and B is an aligned buffer at least Z*N bytes in size
-** shall cause the [lookaside memory allocator] for D to use buffer B
-** with N slots of Z bytes each.
-**
-** {H14212} A successful call to
-** [sqlite3_db_config](D,[SQLITE_DBCONFIG_LOOKASIDE],B,Z,N) where
-** D is an open [database connection] and Z and N are positive
-** integers and B is NULL pointer shall cause the
-** [lookaside memory allocator] for D to a obtain Z*N byte buffer
-** from the primary memory allocator and use that buffer
-** with N lookaside slots of Z bytes each.
-**
-** {H14215} A successful call to
-** [sqlite3_db_config](D,[SQLITE_DBCONFIG_LOOKASIDE],B,Z,N) where
-** D is an open [database connection] and Z and N are zero shall
-** disable the [lookaside memory allocator] for D.
-**
-**
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Memory Allocation Routines {H10155} <S20120>
@@ -1671,9 +1510,7 @@ struct sqlite3_mem_methods {
** The application is responsible for serializing access to
** [database connections] and [prepared statements]. But other mutexes
** are enabled so that SQLite will be safe to use in a multi-threaded
-** environment as long as no two threads attempt to use the same
-** [database connection] at the same time. See the [threading mode]
-** documentation for additional information.</dd>
+** environment.</dd>
**
** <dt>SQLITE_CONFIG_SERIALIZED</dt>
** <dd>There are no arguments to this option. This option enables
@@ -1684,7 +1521,11 @@ struct sqlite3_mem_methods {
** to [database connections] and [prepared statements] so that the
** application is free to use the same [database connection] or the
** same [prepared statement] in different threads at the same time.
-** See the [threading mode] documentation for additional information.</dd>
+**
+** <p>This configuration option merely sets the default mutex
+** behavior to serialize access to [database connections]. Individual
+** [database connections] can override this setting
+** using the [SQLITE_OPEN_NOMUTEX] flag to [sqlite3_open_v2()].</p></dd>
**
** <dt>SQLITE_CONFIG_MALLOC</dt>
** <dd>This option takes a single argument which is a pointer to an
@@ -1731,10 +1572,7 @@ struct sqlite3_mem_methods {
**
** <dt>SQLITE_CONFIG_PAGECACHE</dt>
** <dd>This option specifies a static memory buffer that SQLite can use for
-** the database page cache with the default page cache implemenation.
-** This configuration should not be used if an application-define page
-** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
-** There are three arguments to this option: A pointer to the
+** the database page cache. There are three arguments: A pointer to the
** memory, the size of each page buffer (sz), and the number of pages (N).
** The sz argument must be a power of two between 512 and 32768. The first
** argument should point to an allocation of at least sz*N bytes of memory.
@@ -1779,17 +1617,6 @@ struct sqlite3_mem_methods {
** size of each lookaside buffer slot and the second is the number of
** slots allocated to each database connection.</dd>
**
-** <dt>SQLITE_CONFIG_PCACHE</dt>
-** <dd>This option takes a single argument which is a pointer to
-** an [sqlite3_pcache_methods] object. This object specifies the interface
-** to a custom page cache implementation. SQLite makes a copy of the
-** object and uses it for page cache memory allocations.</dd>
-**
-** <dt>SQLITE_CONFIG_GETPCACHE</dt>
-** <dd>This option takes a single argument which is a pointer to an
-** [sqlite3_pcache_methods] object. SQLite copies of the current
-** page cache implementation into that object.</dd>
-**
** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
@@ -1803,10 +1630,8 @@ struct sqlite3_mem_methods {
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
-/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
+#define SQLITE_CONFIG_CHUNKALLOC 12 /* int threshold */
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
-#define SQLITE_CONFIG_PCACHE 14 /* sqlite3_pcache_methods* */
-#define SQLITE_CONFIG_GETPCACHE 15 /* sqlite3_pcache_methods* */
/*
** CAPI3REF: Configuration Options {H10170} <S20000>
@@ -1868,17 +1693,17 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
** is another alias for the rowid.
**
** This routine returns the rowid of the most recent
-** successful [INSERT] into the database from the [database connection]
-** in the first argument. If no successful [INSERT]s
+** successful INSERT into the database from the [database connection]
+** in the first argument. If no successful INSERTs
** have ever occurred on that database connection, zero is returned.
**
-** If an [INSERT] occurs within a trigger, then the rowid of the inserted
+** If an INSERT occurs within a trigger, then the rowid of the inserted
** row is returned by this routine as long as the trigger is running.
** But once the trigger terminates, the value returned by this routine
** reverts to the last value inserted before the trigger fired.
**
-** An [INSERT] that fails due to a constraint violation is not a
-** successful [INSERT] and does not change the value returned by this
+** An INSERT that fails due to a constraint violation is not a
+** successful INSERT and does not change the value returned by this
** routine. Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
** and INSERT OR ABORT make no changes to the return value of this
** routine when their insertion fails. When INSERT OR REPLACE
@@ -1887,24 +1712,23 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
** the constraint problem so INSERT OR REPLACE will always change
** the return value of this interface.
**
-** For the purposes of this routine, an [INSERT] is considered to
+** For the purposes of this routine, an INSERT is considered to
** be successful even if it is subsequently rolled back.
**
** INVARIANTS:
**
-** {H12221} The [sqlite3_last_insert_rowid()] function shall return the rowid
-** of the most recent successful [INSERT] performed on the same
+** {H12221} The [sqlite3_last_insert_rowid()] function returns the rowid
+** of the most recent successful INSERT performed on the same
** [database connection] and within the same or higher level
-** trigger context, or zero if there have been no qualifying
-** [INSERT] statements.
+** trigger context, or zero if there have been no qualifying inserts.
**
-** {H12223} The [sqlite3_last_insert_rowid()] function shall return the
+** {H12223} The [sqlite3_last_insert_rowid()] function returns the
** same value when called from the same trigger context
-** immediately before and after a [ROLLBACK].
+** immediately before and after a ROLLBACK.
**
** ASSUMPTIONS:
**
-** {A12232} If a separate thread performs a new [INSERT] on the same
+** {A12232} If a separate thread performs a new INSERT on the same
** database connection while the [sqlite3_last_insert_rowid()]
** function is running and thus changes the last insert rowid,
** then the value returned by [sqlite3_last_insert_rowid()] is
@@ -1919,8 +1743,8 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** This function returns the number of database rows that were changed
** or inserted or deleted by the most recently completed SQL statement
** on the [database connection] specified by the first parameter.
-** Only changes that are directly specified by the [INSERT], [UPDATE],
-** or [DELETE] statement are counted. Auxiliary changes caused by
+** Only changes that are directly specified by the INSERT, UPDATE,
+** or DELETE statement are counted. Auxiliary changes caused by
** triggers are not counted. Use the [sqlite3_total_changes()] function
** to find the total number of changes including changes caused by triggers.
**
@@ -1954,15 +1778,13 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** caused by subtriggers since those have their own context.
**
** SQLite implements the command "DELETE FROM table" without a WHERE clause
-** by dropping and recreating the table. Doing so is much faster than going
-** through and deleting individual elements from the table. Because of this
+** by dropping and recreating the table. (This is much faster than going
+** through and deleting individual elements from the table.) Because of this
** optimization, the deletions in "DELETE FROM table" are not row changes and
** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()]
** functions, regardless of the number of elements that were originally
** in the table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead. Or recompile using the
-** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the
-** optimization on all queries.
+** "DELETE FROM table WHERE 1" instead.
**
** INVARIANTS:
**
@@ -2004,9 +1826,7 @@ SQLITE_API int sqlite3_changes(sqlite3*);
** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()]
** functions, regardless of the number of elements that were originally
** in the table. To get an accurate count of the number of rows deleted, use
-** "DELETE FROM table WHERE 1" instead. Or recompile using the
-** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the
-** optimization on all queries.
+** "DELETE FROM table WHERE 1" instead.
**
** See also the [sqlite3_changes()] interface.
**
@@ -2168,10 +1988,6 @@ SQLITE_API int sqlite3_complete16(const void *sql);
** previously set handler. Note that calling [sqlite3_busy_timeout()]
** will also set or clear the busy handler.
**
-** The busy callback should not take any actions which modify the
-** database connection that invoked the busy handler. Any such actions
-** result in undefined behavior.
-**
** INVARIANTS:
**
** {H12311} The [sqlite3_busy_handler(D,C,A)] function shall replace
@@ -2485,7 +2301,7 @@ SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
** memory might result in a segmentation fault or other severe error.
** Memory corruption, a segmentation fault, or other severe error
** might result if sqlite3_free() is called with a non-NULL pointer that
-** was not obtained from sqlite3_malloc() or sqlite3_realloc().
+** was not obtained from sqlite3_malloc() or sqlite3_free().
**
** The sqlite3_realloc() interface attempts to resize a
** prior memory allocation to be at least N bytes, where N is the
@@ -2700,16 +2516,6 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** previous call. Disable the authorizer by installing a NULL callback.
** The authorizer is disabled by default.
**
-** The authorizer callback must not do anything that will modify
-** the database connection that invoked the authorizer callback.
-** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
-** database connections for the meaning of "modify" in this paragraph.
-**
-** When [sqlite3_prepare_v2()] is used to prepare a statement, the
-** statement might be reprepared during [sqlite3_step()] due to a
-** schema change. Hence, the application should ensure that the
-** correct authorizer callback remains in place during the [sqlite3_step()].
-**
** Note that the authorizer callback is invoked only during
** [sqlite3_prepare()] or its variants. Authorization is not
** performed during statement evaluation in [sqlite3_step()].
@@ -2720,11 +2526,11 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** authorizer callback with database connection D.
**
** {H12502} The authorizer callback is invoked as SQL statements are
-** being parseed and compiled.
+** being compiled.
**
** {H12503} If the authorizer callback returns any value other than
** [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY], then
-** the application interface call that caused
+** the [sqlite3_prepare_v2()] or equivalent call that caused
** the authorizer callback to run shall fail with an
** [SQLITE_ERROR] error code and an appropriate error message.
**
@@ -2732,7 +2538,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** described is processed normally.
**
** {H12505} When the authorizer callback returns [SQLITE_DENY], the
-** application interface call that caused the
+** [sqlite3_prepare_v2()] or equivalent call that caused the
** authorizer callback to run shall fail
** with an [SQLITE_ERROR] error code and an error message
** explaining that access is denied.
@@ -2806,21 +2612,21 @@ SQLITE_API int sqlite3_set_authorizer(
** INVARIANTS:
**
** {H12551} The second parameter to an
-** [sqlite3_set_authorizer | authorizer callback] shall be an integer
+** [sqlite3_set_authorizer | authorizer callback] is always an integer
** [SQLITE_COPY | authorizer code] that specifies what action
** is being authorized.
**
** {H12552} The 3rd and 4th parameters to the
** [sqlite3_set_authorizer | authorization callback]
-** shall be parameters or NULL depending on which
+** will be parameters or NULL depending on which
** [SQLITE_COPY | authorizer code] is used as the second parameter.
**
** {H12553} The 5th parameter to the
-** [sqlite3_set_authorizer | authorizer callback] shall be the name
+** [sqlite3_set_authorizer | authorizer callback] is the name
** of the database (example: "main", "temp", etc.) if applicable.
**
** {H12554} The 6th parameter to the
-** [sqlite3_set_authorizer | authorizer callback] shall be the name
+** [sqlite3_set_authorizer | authorizer callback] is the name
** of the inner-most trigger or view that is responsible for
** the access attempt or NULL if this access attempt is directly from
** top-level SQL code.
@@ -2856,7 +2662,7 @@ SQLITE_API int sqlite3_set_authorizer(
#define SQLITE_ANALYZE 28 /* Table Name NULL */
#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */
#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
-#define SQLITE_FUNCTION 31 /* NULL Function Name */
+#define SQLITE_FUNCTION 31 /* Function Name NULL */
#define SQLITE_COPY 0 /* No longer used */
/*
@@ -2880,17 +2686,16 @@ SQLITE_API int sqlite3_set_authorizer(
**
** INVARIANTS:
**
-** {H12281} The callback function registered by [sqlite3_trace()]
-** shall be invoked
+** {H12281} The callback function registered by [sqlite3_trace()] is
** whenever an SQL statement first begins to execute and
** whenever a trigger subprogram first begins to run.
**
-** {H12282} Each call to [sqlite3_trace()] shall override the previously
+** {H12282} Each call to [sqlite3_trace()] overrides the previously
** registered trace callback.
**
-** {H12283} A NULL trace callback shall disable tracing.
+** {H12283} A NULL trace callback disables tracing.
**
-** {H12284} The first argument to the trace callback shall be a copy of
+** {H12284} The first argument to the trace callback is a copy of
** the pointer which was the 3rd argument to [sqlite3_trace()].
**
** {H12285} The second argument to the trace callback is a
@@ -2914,8 +2719,8 @@ SQLITE_API int sqlite3_set_authorizer(
** of the number of nanoseconds of wall-clock time required to
** run the SQL statement from start to finish.
*/
-SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
-SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
+SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_API void *sqlite3_profile(sqlite3*,
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
/*
@@ -2929,12 +2734,7 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
**
** If the progress callback returns non-zero, the operation is
** interrupted. This feature can be used to implement a
-** "Cancel" button on a GUI progress dialog box.
-**
-** The progress handler must not do anything that will modify
-** the database connection that invoked the progress handler.
-** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
-** database connections for the meaning of "modify" in this paragraph.
+** "Cancel" button on a GUI dialog box.
**
** INVARIANTS:
**
@@ -2997,7 +2797,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** except that it accepts two additional parameters for additional control
** over the new database connection. The flags parameter can take one of
** the following three values, optionally combined with the
-** [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags:
+** [SQLITE_OPEN_NOMUTEX] flag:
**
** <dl>
** <dt>[SQLITE_OPEN_READONLY]</dt>
@@ -3017,15 +2817,16 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
** combinations shown above or one of the combinations shown above combined
-** with the [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags,
-** then the behavior is undefined.
+** with the [SQLITE_OPEN_NOMUTEX] flag, then the behavior is undefined.
**
-** If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
-** opens in the multi-thread [threading mode] as long as the single-thread
-** mode has not been set at compile-time or start-time. If the
-** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
-** in the serialized [threading mode] unless single-thread was
-** previously selected at compile-time or start-time.
+** If the [SQLITE_OPEN_NOMUTEX] flag is set, then mutexes on the
+** opened [database connection] are disabled and the appliation must
+** insure that access to the [database connection] and its associated
+** [prepared statements] is serialized. The [SQLITE_OPEN_NOMUTEX] flag
+** is the default behavior is SQLite is configured using the
+** [SQLITE_CONFIG_MULTITHREAD] or [SQLITE_CONFIG_SINGLETHREAD] options
+** to [sqlite3_config()]. The [SQLITE_OPEN_NOMUTEX] flag only makes a
+** difference when SQLite is in its default [SQLITE_CONFIG_SERIALIZED] mode.
**
** If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection. This in-memory database will vanish when
@@ -3088,11 +2889,11 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** reading and writing if possible, or for reading only if the
** file is write protected by the operating system.
**
-** {H12713} If the G parameter to [sqlite3_open_v2(F,D,G,V)] omits the
+** {H12713} If the G parameter to [sqlite3_open(v2(F,D,G,V)] omits the
** bit value [SQLITE_OPEN_CREATE] and the database does not
** previously exist, an error is returned.
**
-** {H12714} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
+** {H12714} If the G parameter to [sqlite3_open(v2(F,D,G,V)] contains the
** bit value [SQLITE_OPEN_CREATE] and the database does not
** previously exist, then an attempt is made to create and
** initialize the database.
@@ -3139,10 +2940,7 @@ SQLITE_API int sqlite3_open_v2(
** [extended result code] for the most recent failed sqlite3_* API call
** associated with a [database connection]. If a prior API call failed
** but the most recent API call succeeded, the return value from
-** sqlite3_errcode() is undefined. The sqlite3_extended_errcode()
-** interface is the same except that it always returns the
-** [extended result code] even when extended result codes are
-** disabled.
+** sqlite3_errcode() is undefined.
**
** The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
** text that describes the error, as either UTF-8 or UTF-16 respectively.
@@ -3151,16 +2949,6 @@ SQLITE_API int sqlite3_open_v2(
** However, the error string might be overwritten or deallocated by
** subsequent calls to other SQLite interface functions.
**
-** When the serialized [threading mode] is in use, it might be the
-** case that a second error occurs on a separate thread in between
-** the time of the first error and the call to these interfaces.
-** When that happens, the second error will be reported since these
-** interfaces always report the most recent result. To avoid
-** this, each thread can obtain exclusive use of the [database connection] D
-** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning
-** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after
-** all calls to the interfaces listed here are completed.
-**
** If an interface fails with SQLITE_MISUSE, that means the interface
** was invoked incorrectly by the application. In that case, the
** error code and message may or may not be set.
@@ -3171,10 +2959,6 @@ SQLITE_API int sqlite3_open_v2(
** [result code] or [extended result code] for the most recently
** failed interface call associated with the [database connection] D.
**
-** {H12802} The [sqlite3_extended_errcode(D)] interface returns the numeric
-** [extended result code] for the most recently
-** failed interface call associated with the [database connection] D.
-**
** {H12803} The [sqlite3_errmsg(D)] and [sqlite3_errmsg16(D)]
** interfaces return English-language text that describes
** the error in the mostly recently failed interface call,
@@ -3186,18 +2970,15 @@ SQLITE_API int sqlite3_open_v2(
** {H12808} Calls to API routines that do not return an error code
** (example: [sqlite3_data_count()]) do not
** change the error code or message returned by
-** [sqlite3_errcode()], [sqlite3_extended_errcode()],
-** [sqlite3_errmsg()], or [sqlite3_errmsg16()].
+** [sqlite3_errcode()], [sqlite3_errmsg()], or [sqlite3_errmsg16()].
**
** {H12809} Interfaces that are not associated with a specific
** [database connection] (examples:
** [sqlite3_mprintf()] or [sqlite3_enable_shared_cache()]
** do not change the values returned by
-** [sqlite3_errcode()], [sqlite3_extended_errcode()],
-** [sqlite3_errmsg()], or [sqlite3_errmsg16()].
+** [sqlite3_errcode()], [sqlite3_errmsg()], or [sqlite3_errmsg16()].
*/
SQLITE_API int sqlite3_errcode(sqlite3 *db);
-SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
@@ -3466,7 +3247,7 @@ SQLITE_API int sqlite3_prepare16_v2(
);
/*
-** CAPI3REF: Retrieving Statement SQL {H13100} <H13000>
+** CAPIREF: Retrieving Statement SQL {H13100} <H13000>
**
** This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
@@ -4464,8 +4245,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** characters. Any attempt to create a function with a longer name
** will result in [SQLITE_ERROR] being returned.
**
-** The third parameter (nArg)
-** is the number of arguments that the SQL function or
+** The third parameter is the number of arguments that the SQL function or
** aggregate takes. If this parameter is negative, then the SQL function or
** aggregate may take any number of arguments.
**
@@ -4496,91 +4276,72 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** functions with the same name but with either differing numbers of
** arguments or differing preferred text encodings. SQLite will use
** the implementation most closely matches the way in which the
-** SQL function is used. A function implementation with a non-negative
-** nArg parameter is a better match than a function implementation with
-** a negative nArg. A function where the preferred text encoding
-** matches the database encoding is a better
-** match than a function where the encoding is different.
-** A function where the encoding difference is between UTF16le and UTF16be
-** is a closer match than a function where the encoding difference is
-** between UTF8 and UTF16.
-**
-** Built-in functions may be overloaded by new application-defined functions.
-** The first application-defined function with a given name overrides all
-** built-in functions in the same [database connection] with the same name.
-** Subsequent application-defined functions of the same name only override
-** prior application-defined functions that are an exact match for the
-** number of parameters and preferred encoding.
-**
-** An application-defined function is permitted to call other
-** SQLite interfaces. However, such calls must not
-** close the database connection nor finalize or reset the prepared
-** statement in which the function is running.
+** SQL function is used.
**
** INVARIANTS:
**
-** {H16103} The [sqlite3_create_function16(D,X,...)] interface shall behave
-** as [sqlite3_create_function(D,X,...)] in every way except that it
-** interprets the X argument as zero-terminated UTF-16
+** {H16103} The [sqlite3_create_function16()] interface behaves exactly
+** like [sqlite3_create_function()] in every way except that it
+** interprets the zFunctionName argument as zero-terminated UTF-16
** native byte order instead of as zero-terminated UTF-8.
**
-** {H16106} A successful invocation of the
-** [sqlite3_create_function(D,X,N,E,...)] interface shall register
+** {H16106} A successful invocation of
+** the [sqlite3_create_function(D,X,N,E,...)] interface registers
** or replaces callback functions in the [database connection] D
** used to implement the SQL function named X with N parameters
** and having a preferred text encoding of E.
**
** {H16109} A successful call to [sqlite3_create_function(D,X,N,E,P,F,S,L)]
-** shall replace the P, F, S, and L values from any prior calls with
+** replaces the P, F, S, and L values from any prior calls with
** the same D, X, N, and E values.
**
-** {H16112} The [sqlite3_create_function(D,X,...)] interface shall fail
-** if the SQL function name X is
+** {H16112} The [sqlite3_create_function(D,X,...)] interface fails with
+** a return code of [SQLITE_ERROR] if the SQL function name X is
** longer than 255 bytes exclusive of the zero terminator.
**
-** {H16118} The [sqlite3_create_function(D,X,N,E,P,F,S,L)] interface
-** shall fail unless either F is NULL and S and L are non-NULL or
-*** F is non-NULL and S and L are NULL.
+** {H16118} Either F must be NULL and S and L are non-NULL or else F
+** is non-NULL and S and L are NULL, otherwise
+** [sqlite3_create_function(D,X,N,E,P,F,S,L)] returns [SQLITE_ERROR].
**
-** {H16121} The [sqlite3_create_function(D,...)] interface shall fails with an
+** {H16121} The [sqlite3_create_function(D,...)] interface fails with an
** error code of [SQLITE_BUSY] if there exist [prepared statements]
** associated with the [database connection] D.
**
-** {H16124} The [sqlite3_create_function(D,X,N,...)] interface shall fail with
-** an error code of [SQLITE_ERROR] if parameter N is less
+** {H16124} The [sqlite3_create_function(D,X,N,...)] interface fails with an
+** error code of [SQLITE_ERROR] if parameter N (specifying the number
+** of arguments to the SQL function being registered) is less
** than -1 or greater than 127.
**
** {H16127} When N is non-negative, the [sqlite3_create_function(D,X,N,...)]
-** interface shall register callbacks to be invoked for the
-** SQL function
+** interface causes callbacks to be invoked for the SQL function
** named X when the number of arguments to the SQL function is
** exactly N.
**
** {H16130} When N is -1, the [sqlite3_create_function(D,X,N,...)]
-** interface shall register callbacks to be invoked for the SQL
-** function named X with any number of arguments.
+** interface causes callbacks to be invoked for the SQL function
+** named X with any number of arguments.
**
** {H16133} When calls to [sqlite3_create_function(D,X,N,...)]
** specify multiple implementations of the same function X
** and when one implementation has N>=0 and the other has N=(-1)
-** the implementation with a non-zero N shall be preferred.
+** the implementation with a non-zero N is preferred.
**
** {H16136} When calls to [sqlite3_create_function(D,X,N,E,...)]
** specify multiple implementations of the same function X with
** the same number of arguments N but with different
** encodings E, then the implementation where E matches the
-** database encoding shall preferred.
+** database encoding is preferred.
**
** {H16139} For an aggregate SQL function created using
** [sqlite3_create_function(D,X,N,E,P,0,S,L)] the finalizer
-** function L shall always be invoked exactly once if the
+** function L will always be invoked exactly once if the
** step function S is called one or more times.
**
** {H16142} When SQLite invokes either the xFunc or xStep function of
** an application-defined SQL function or aggregate created
** by [sqlite3_create_function()] or [sqlite3_create_function16()],
** then the array of [sqlite3_value] objects passed as the
-** third parameter shall be [protected sqlite3_value] objects.
+** third parameter are always [protected sqlite3_value] objects.
*/
SQLITE_API int sqlite3_create_function(
sqlite3 *db,
@@ -4624,16 +4385,14 @@ SQLITE_API int sqlite3_create_function16(
** backwards compatibility with older code, these functions continue
** to be supported. However, new applications should avoid
** the use of these functions. To help encourage people to avoid
-** using these functions, we are not going to tell you what they do.
+** using these functions, we are not going to tell you want they do.
*/
-#ifndef SQLITE_OMIT_DEPRECATED
-SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
-SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
-#endif
+SQLITE_API int sqlite3_aggregate_count(sqlite3_context*);
+SQLITE_API int sqlite3_expired(sqlite3_stmt*);
+SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_API int sqlite3_global_recover(void);
+SQLITE_API void sqlite3_thread_cleanup(void);
+SQLITE_API int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
/*
** CAPI3REF: Obtaining SQL Function Parameter Values {H15100} <S20200>
@@ -5494,14 +5253,6 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
** If another function was previously registered, its
** pArg value is returned. Otherwise NULL is returned.
**
-** The callback implementation must not do anything that will modify
-** the database connection that invoked the callback. Any actions
-** to modify the database connection must be deferred until after the
-** completion of the [sqlite3_step()] call that triggered the commit
-** or rollback hook in the first place.
-** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
-** database connections for the meaning of "modify" in this paragraph.
-**
** Registering a NULL function disables the callback.
**
** For the purposes of this API, a transaction is said to have been
@@ -5576,13 +5327,6 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).
**
-** The update hook implementation must not do anything that will modify
-** the database connection that invoked the update hook. Any actions
-** to modify the database connection must be deferred until after the
-** completion of the [sqlite3_step()] call that triggered the update hook.
-** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
-** database connections for the meaning of "modify" in this paragraph.
-**
** If another function was previously registered, its pArg value
** is returned. Otherwise NULL is returned.
**
@@ -6073,7 +5817,7 @@ struct sqlite3_index_info {
** This interface is experimental and is subject to change or
** removal in future releases of SQLite.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module(
+SQLITE_API int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *, /* Methods for the module */
@@ -6088,7 +5832,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module(
** except that it allows a destructor function to be specified. It is
** even more experimental than the rest of the virtual tables API.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
+SQLITE_API int sqlite3_create_module_v2(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *, /* Methods for the module */
@@ -6160,7 +5904,7 @@ struct sqlite3_vtab_cursor {
** This interface is experimental and is subject to change or
** removal in future releases of SQLite.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
+SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
/*
** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400>
@@ -6181,7 +5925,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zC
** This API should be considered part of the virtual table interface,
** which is experimental and subject to change.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
/*
** The interface to the virtual-table mechanism defined above (back up
@@ -6266,7 +6010,6 @@ typedef struct sqlite3_blob sqlite3_blob;
**
** {H17821} If an error occurs during evaluation of [sqlite3_blob_open(D,...)]
** then subsequent calls to [sqlite3_errcode(D)],
-** [sqlite3_extended_errcode()],
** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] shall return
** information appropriate for that error.
**
@@ -6380,7 +6123,6 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
**
** {H17868} If an error occurs during evaluation of [sqlite3_blob_read(P,...)]
** then subsequent calls to [sqlite3_errcode(D)],
-** [sqlite3_extended_errcode()],
** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] shall return
** information appropriate for that error, where D is the
** [database connection] that was used to open the [BLOB handle] P.
@@ -6450,7 +6192,6 @@ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
**
** {H17888} If an error occurs during evaluation of [sqlite3_blob_write(D,...)]
** then subsequent calls to [sqlite3_errcode(D)],
-** [sqlite3_extended_errcode()],
** [sqlite3_errmsg(D)], and [sqlite3_errmsg16(D)] shall return
** information appropriate for that error.
*/
@@ -6749,17 +6490,6 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */
/*
-** CAPI3REF: Retrieve the mutex for a database connection {H17002} <H17000>
-**
-** This interface returns a pointer 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
-** routine returns a NULL pointer.
-*/
-SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
-
-/*
** CAPI3REF: Low-Level Control Of Database Files {H11300} <S30800>
**
** {H11301} The [sqlite3_file_control()] interface makes a direct call to the
@@ -6852,8 +6582,27 @@ SQLITE_API int sqlite3_test_control(int op, ...);
**
** See also: [sqlite3_db_status()]
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+/*
+** CAPI3REF: Database Connection Status {H17201} <S60200>
+** EXPERIMENTAL
+**
+** This interface is used to retrieve runtime status information
+** about a single [database connection]. The first argument is the
+** database connection object to be interrogated. The second argument
+** is the parameter to interrogate. Currently, the only allowed value
+** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
+** Additional options will likely appear in future releases of SQLite.
+**
+** The current value of the request parameter is written into *pCur
+** and the highest instantaneous value is written into *pHiwtr. If
+** the resetFlg is true, then the highest instantaneous value is
+** reset back down to the current value.
+**
+** See also: [sqlite3_status()].
+*/
+SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters {H17250} <H17200>
@@ -6943,27 +6692,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pH
#define SQLITE_STATUS_SCRATCH_SIZE 8
/*
-** CAPI3REF: Database Connection Status {H17500} <S60200>
-** EXPERIMENTAL
-**
-** This interface is used to retrieve runtime status information
-** about a single [database connection]. The first argument is the
-** database connection object to be interrogated. The second argument
-** is the parameter to interrogate. Currently, the only allowed value
-** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
-** Additional options will likely appear in future releases of SQLite.
-**
-** The current value of the requested parameter is written into *pCur
-** and the highest instantaneous value is written into *pHiwtr. If
-** the resetFlg is true, then the highest instantaneous value is
-** reset back down to the current value.
-**
-** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
-*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
-
-/*
-** CAPI3REF: Status Parameters for database connections {H17520} <H17500>
+** CAPI3REF: Status Parameters for database connections {H17275} <H17200>
** EXPERIMENTAL
**
** Status verbs for [sqlite3_db_status()].
@@ -6976,201 +6705,6 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
-
-/*
-** CAPI3REF: Prepared Statement Status {H17550} <S60200>
-** EXPERIMENTAL
-**
-** Each prepared statement maintains various
-** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
-** of times it has performed specific operations. These counters can
-** be used to monitor the performance characteristics of the prepared
-** statements. For example, if the number of table steps greatly exceeds
-** the number of table searches or result rows, that would tend to indicate
-** that the prepared statement is using a full table scan rather than
-** an index.
-**
-** This interface is used to retrieve and reset counter values from
-** a [prepared statement]. The first argument is the prepared statement
-** object to be interrogated. The second argument
-** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
-** to be interrogated.
-** The current value of the requested counter is returned.
-** If the resetFlg is true, then the counter is reset to zero after this
-** interface call returns.
-**
-** See also: [sqlite3_status()] and [sqlite3_db_status()].
-*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
-
-/*
-** CAPI3REF: Status Parameters for prepared statements {H17570} <H17550>
-** EXPERIMENTAL
-**
-** These preprocessor macros define integer codes that name counter
-** values associated with the [sqlite3_stmt_status()] interface.
-** The meanings of the various counters are as follows:
-**
-** <dl>
-** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
-** <dd>This is the number of times that SQLite has stepped forward in
-** a table as part of a full table scan. Large numbers for this counter
-** may indicate opportunities for performance improvement through
-** careful use of indices.</dd>
-**
-** <dt>SQLITE_STMTSTATUS_SORT</dt>
-** <dd>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.</dd>
-**
-** </dl>
-*/
-#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
-#define SQLITE_STMTSTATUS_SORT 2
-
-/*
-** CAPI3REF: Custom Page Cache Object
-** EXPERIMENTAL
-**
-** The sqlite3_pcache type is opaque. It is implemented by
-** the pluggable module. The SQLite core has no knowledge of
-** its size or internal structure and never deals with the
-** sqlite3_pcache object except by holding and passing pointers
-** to the object.
-**
-** See [sqlite3_pcache_methods] for additional information.
-*/
-typedef struct sqlite3_pcache sqlite3_pcache;
-
-/*
-** CAPI3REF: Application Defined Page Cache.
-** EXPERIMENTAL
-**
-** The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can
-** register an alternative page cache implementation by passing in an
-** instance of the sqlite3_pcache_methods structure. The majority of the
-** heap memory used by sqlite is used by the page cache to cache data read
-** from, or ready to be written to, the database file. By implementing a
-** custom page cache using this API, an application can control more
-** precisely the amount of memory consumed by sqlite, the way in which
-** said memory is allocated and released, and the policies used to
-** determine exactly which parts of a database file are cached and for
-** how long.
-**
-** The contents of the structure are copied to an internal buffer by sqlite
-** within the call to [sqlite3_config].
-**
-** The xInit() method is called once for each call to [sqlite3_initialize()]
-** (usually only once during the lifetime of the process). It is passed
-** a copy of the sqlite3_pcache_methods.pArg value. It can be used to set
-** up global structures and mutexes required by the custom page cache
-** implementation. The xShutdown() method is called from within
-** [sqlite3_shutdown()], if the application invokes this API. It can be used
-** to clean up any outstanding resources before process shutdown, if required.
-**
-** The xCreate() method is used to construct a new cache instance. The
-** first parameter, szPage, is the size in bytes of the pages that must
-** be allocated by the cache. szPage will not be a power of two. The
-** second argument, bPurgeable, is true if the cache being created will
-** be used to cache database pages read from 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 on the value of bPurgeable,
-** it is purely advisory.
-**
-** 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
-** 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 special with this
-** value, it is advisory only.
-**
-** The xPagecount() method should return the number of pages currently
-** stored in the cache supplied as an argument.
-**
-** The xFetch() method is used to fetch a page and return a pointer to it.
-** A 'page', in this context, is a buffer of szPage bytes aligned at an
-** 8-byte boundary. The page to be fetched is determined by the key. The
-** mimimum key value is 1. After it has been retrieved using xFetch, the page
-** is considered to be pinned.
-**
-** If the requested page is already in the page cache, then a pointer to
-** the cached buffer should be returned with its contents intact. If the
-** page is not already in the cache, then the expected behaviour of the
-** cache is determined by the value of the createFlag parameter passed
-** to xFetch, according to the following table:
-**
-** <table border=1 width=85% align=center>
-** <tr><th>createFlag<th>Expected Behaviour
-** <tr><td>0<td>NULL should be returned. No new cache entry is created.
-** <tr><td>1<td>If createFlag is set to 1, this indicates that
-** SQLite is holding pinned pages that can be unpinned
-** by writing their contents to the database file (a
-** relatively expensive operation). In this situation the
-** cache implementation has two choices: it can return NULL,
-** in which case SQLite will attempt to unpin one or more
-** pages before re-requesting the same page, or it can
-** allocate a new page and return a pointer to it. If a new
-** page is allocated, then it must be completely zeroed before
-** it is returned.
-** <tr><td>2<td>If createFlag is set to 2, then SQLite is not holding any
-** pinned pages associated with the specific cache passed
-** as the first argument to xFetch() that can be unpinned. The
-** cache implementation should attempt to allocate a new
-** cache entry and return a pointer to it. Again, the new
-** page should be zeroed before it is returned. If the xFetch()
-** method returns NULL when createFlag==2, SQLite assumes that
-** a memory allocation failed and returns SQLITE_NOMEM to the
-** user.
-** </table>
-**
-** xUnpin() is called by SQLite with a pointer to a currently pinned page
-** as its second argument. If the third parameter, discard, is non-zero,
-** then the page should be evicted from the cache. In this case SQLite
-** assumes that the next time the page is retrieved from the cache using
-** the xFetch() method, it will be zeroed. If the discard parameter is
-** zero, then the page is considered to be unpinned. The cache implementation
-** may choose to reclaim (free or recycle) unpinned pages at any time.
-** SQLite assumes that next time the page is retrieved from the cache
-** it will either be zeroed, or contain the same data that it did when it
-** was unpinned.
-**
-** The cache is not required to perform any reference counting. A single
-** call to xUnpin() unpins the page regardless of the number of prior calls
-** to xFetch().
-**
-** The xRekey() method is used to change the key value associated with the
-** page passed as the second argument from oldKey to newKey. If the cache
-** previously contains an entry associated with newKey, it should be
-** discarded. Any prior cache entry associated with newKey is guaranteed not
-** to be pinned.
-**
-** 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
-** they can be safely discarded.
-**
-** The xDestroy() method is used to delete a cache allocated by xCreate().
-** All resources associated with the specified cache should be freed. After
-** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
-** handle invalid, and will not use it with any other sqlite3_pcache_methods
-** functions.
-*/
-typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
-struct sqlite3_pcache_methods {
- void *pArg;
- int (*xInit)(void*);
- void (*xShutdown)(void*);
- sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
- void (*xCachesize)(sqlite3_pcache*, int nCachesize);
- int (*xPagecount)(sqlite3_pcache*);
- void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
- void (*xUnpin)(sqlite3_pcache*, void*, int discard);
- void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
- void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
- void (*xDestroy)(sqlite3_pcache*);
-};
-
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
@@ -7220,13 +6754,14 @@ typedef struct HashElem HashElem;
** this structure opaque.
*/
struct Hash {
- unsigned int copyKey: 1; /* True if copy of key made on insert */
- unsigned int htsize : 31; /* Number of buckets in the hash table */
- unsigned int count; /* Number of entries in this table */
- HashElem *first; /* The first element of the array */
- struct _ht { /* the hash table */
- int count; /* Number of entries with this hash */
- HashElem *chain; /* Pointer to first entry with this hash */
+ char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */
+ char copyKey; /* True if copy of key made on insert */
+ int count; /* Number of entries in this table */
+ int htsize; /* Number of buckets in the hash table */
+ HashElem *first; /* The first element of the array */
+ struct _ht { /* the hash table */
+ int count; /* Number of entries with this hash */
+ HashElem *chain; /* Pointer to first entry with this hash */
} *ht;
};
@@ -7243,9 +6778,31 @@ struct HashElem {
};
/*
+** There are 4 different modes of operation for a hash table:
+**
+** SQLITE_HASH_INT nKey is used as the key and pKey is ignored.
+**
+** SQLITE_HASH_POINTER pKey is used as the key and nKey is ignored.
+**
+** SQLITE_HASH_STRING pKey points to a string that is nKey bytes long
+** (including the null-terminator, if any). Case
+** is ignored in comparisons.
+**
+** SQLITE_HASH_BINARY pKey points to binary data nKey bytes long.
+** memcmp() is used to compare keys.
+**
+** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY
+** if the copyKey parameter to HashInit is 1.
+*/
+/* #define SQLITE_HASH_INT 1 // NOT USED */
+/* #define SQLITE_HASH_POINTER 2 // NOT USED */
+#define SQLITE_HASH_STRING 3
+#define SQLITE_HASH_BINARY 4
+
+/*
** Access routines. To delete, insert a NULL pointer.
*/
-SQLITE_PRIVATE void sqlite3HashInit(Hash*, int copyKey);
+SQLITE_PRIVATE void sqlite3HashInit(Hash*, int keytype, int copyKey);
SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData);
SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const void *pKey, int nKey);
SQLITE_PRIVATE HashElem *sqlite3HashFindElem(const Hash*, const void *pKey, int nKey);
@@ -7394,39 +6951,39 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_DOT 112
#define TK_FROM 113
#define TK_JOIN 114
-#define TK_INDEXED 115
-#define TK_BY 116
-#define TK_USING 117
-#define TK_ORDER 118
-#define TK_GROUP 119
-#define TK_HAVING 120
-#define TK_LIMIT 121
-#define TK_WHERE 122
-#define TK_INTO 123
-#define TK_VALUES 124
-#define TK_INTEGER 125
-#define TK_FLOAT 126
-#define TK_BLOB 127
-#define TK_REGISTER 128
-#define TK_VARIABLE 129
-#define TK_CASE 130
-#define TK_WHEN 131
-#define TK_THEN 132
-#define TK_ELSE 133
-#define TK_INDEX 134
-#define TK_ALTER 135
-#define TK_TO 136
-#define TK_ADD 137
-#define TK_COLUMNKW 138
-#define TK_TO_TEXT 139
-#define TK_TO_BLOB 140
-#define TK_TO_NUMERIC 141
-#define TK_TO_INT 142
-#define TK_TO_REAL 143
-#define TK_END_OF_FILE 144
-#define TK_ILLEGAL 145
-#define TK_SPACE 146
-#define TK_UNCLOSED_STRING 147
+#define TK_USING 115
+#define TK_ORDER 116
+#define TK_BY 117
+#define TK_GROUP 118
+#define TK_HAVING 119
+#define TK_LIMIT 120
+#define TK_WHERE 121
+#define TK_INTO 122
+#define TK_VALUES 123
+#define TK_INTEGER 124
+#define TK_FLOAT 125
+#define TK_BLOB 126
+#define TK_REGISTER 127
+#define TK_VARIABLE 128
+#define TK_CASE 129
+#define TK_WHEN 130
+#define TK_THEN 131
+#define TK_ELSE 132
+#define TK_INDEX 133
+#define TK_ALTER 134
+#define TK_TO 135
+#define TK_ADD 136
+#define TK_COLUMNKW 137
+#define TK_TO_TEXT 138
+#define TK_TO_BLOB 139
+#define TK_TO_NUMERIC 140
+#define TK_TO_INT 141
+#define TK_TO_REAL 142
+#define TK_END_OF_FILE 143
+#define TK_ILLEGAL 144
+#define TK_SPACE 145
+#define TK_UNCLOSED_STRING 146
+#define TK_COMMENT 147
#define TK_FUNCTION 148
#define TK_COLUMN 149
#define TK_AGG_FUNCTION 150
@@ -7572,7 +7129,7 @@ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
-typedef INT8_TYPE i8; /* 1-byte signed integer */
+typedef UINT8_TYPE i8; /* 1-byte signed integer */
/*
** Macros to determine whether the machine is big or little endian,
@@ -7583,8 +7140,7 @@ SQLITE_PRIVATE const int sqlite3one;
#else
SQLITE_PRIVATE const int sqlite3one;
#endif
-#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
- || defined(__x86_64) || defined(__x86_64__)
+#if defined(i386) || defined(__i386__) || defined(_M_IX86)
# define SQLITE_BIGENDIAN 0
# define SQLITE_LITTLEENDIAN 1
# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
@@ -7640,7 +7196,7 @@ struct BusyHandler {
** A convenience macro that returns the number of elements in
** an array.
*/
-#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
+#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
/*
** The following value as a destructor means to use sqlite3DbFree().
@@ -7649,51 +7205,6 @@ struct BusyHandler {
#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree)
/*
-** When SQLITE_OMIT_WSD is defined, it means that the target platform does
-** not support Writable Static Data (WSD) such as global and static variables.
-** All variables must either be on the stack or dynamically allocated from
-** the heap. When WSD is unsupported, the variable declarations scattered
-** throughout the SQLite code must become constants instead. The SQLITE_WSD
-** macro is used for this purpose. And instead of referencing the variable
-** directly, we use its constant as a key to lookup the run-time allocated
-** buffer that holds real variable. The constant is also the initializer
-** for the run-time allocated buffer.
-**
-** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL
-** macros become no-ops and have zero performance impact.
-*/
-#ifdef SQLITE_OMIT_WSD
- #define SQLITE_WSD const
- #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
- #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
-SQLITE_API int sqlite3_wsd_init(int N, int J);
-SQLITE_API void *sqlite3_wsd_find(void *K, int L);
-#else
- #define SQLITE_WSD
- #define GLOBAL(t,v) v
- #define sqlite3GlobalConfig sqlite3Config
-#endif
-
-/*
-** The following macros are used to suppress compiler warnings and to
-** make it clear to human readers when a function parameter is deliberately
-** left unused within the body of a function. This usually happens when
-** a function is called via a function pointer. For example the
-** implementation of an SQL aggregate step callback may not use the
-** parameter indicating the number of arguments passed to the aggregate,
-** if it knows that this is enforced elsewhere.
-**
-** When a function parameter is not used at all within the body of a function,
-** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
-** However, these macros may also be used to suppress warnings related to
-** parameters that may or may not be used depending on compilation options.
-** For example those parameters only used in assert() statements. In these
-** cases the parameters are named as per the usual conventions.
-*/
-#define UNUSED_PARAMETER(x) (void)(x)
-#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
-
-/*
** Forward references to structures
*/
typedef struct AggInfo AggInfo;
@@ -7707,7 +7218,6 @@ typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FKey FKey;
typedef struct FuncDef FuncDef;
-typedef struct FuncDefHash FuncDefHash;
typedef struct IdList IdList;
typedef struct Index Index;
typedef struct KeyClass KeyClass;
@@ -7726,8 +7236,6 @@ typedef struct Token Token;
typedef struct TriggerStack TriggerStack;
typedef struct TriggerStep TriggerStep;
typedef struct Trigger Trigger;
-typedef struct UnpackedRecord UnpackedRecord;
-typedef struct Walker Walker;
typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;
@@ -7857,11 +7365,13 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
-SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, int*);
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int);
SQLITE_PRIVATE int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
+struct UnpackedRecord; /* Forward declaration. Definition in vdbeaux.c. */
+
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
@@ -7875,17 +7385,11 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeMoveto(
BtCursor*,
const void *pKey,
+ struct UnpackedRecord *pUnKey,
i64 nKey,
int bias,
int *pRes
);
-SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
- BtCursor*,
- UnpackedRecord *pUnKey,
- i64 intKey,
- int bias,
- int *pRes
-);
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
@@ -7910,7 +7414,6 @@ SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *);
-SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
#ifdef SQLITE_TEST
SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
@@ -8002,6 +7505,7 @@ typedef struct Vdbe Vdbe;
*/
typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
+typedef struct UnpackedRecord UnpackedRecord;
/*
** A single instruction of the virtual machine has an opcode
@@ -8120,7 +7624,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Affinity 2
#define OP_Column 3
#define OP_SetCookie 4
-#define OP_Real 126 /* same as TK_FLOAT */
+#define OP_Real 125 /* same as TK_FLOAT */
#define OP_Sequence 5
#define OP_MoveGt 6
#define OP_Ge 72 /* same as TK_GE */
@@ -8130,7 +7634,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_OpenWrite 9
#define OP_NotNull 66 /* same as TK_NOTNULL */
#define OP_If 10
-#define OP_ToInt 142 /* same as TK_TO_INT */
+#define OP_ToInt 141 /* same as TK_TO_INT */
#define OP_String8 88 /* same as TK_STRING */
#define OP_VRowid 11
#define OP_CollSeq 12
@@ -8176,7 +7680,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Gosub 47
#define OP_Divide 81 /* same as TK_SLASH */
#define OP_Integer 48
-#define OP_ToNumeric 141 /* same as TK_TO_NUMERIC*/
+#define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/
#define OP_Prev 49
#define OP_Concat 83 /* same as TK_CONCAT */
#define OP_BitAnd 74 /* same as TK_BITAND */
@@ -8200,7 +7704,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_IfNot 85
#define OP_DropTable 86
#define OP_MakeRecord 89
-#define OP_ToBlob 140 /* same as TK_TO_BLOB */
+#define OP_ToBlob 139 /* same as TK_TO_BLOB */
#define OP_ResultRow 90
#define OP_Delete 91
#define OP_AggFinal 92
@@ -8214,9 +7718,9 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Le 70 /* same as TK_LE */
#define OP_VerifyCookie 99
#define OP_AggStep 100
-#define OP_ToText 139 /* same as TK_TO_TEXT */
+#define OP_ToText 138 /* same as TK_TO_TEXT */
#define OP_Not 16 /* same as TK_NOT */
-#define OP_ToReal 143 /* same as TK_TO_REAL */
+#define OP_ToReal 142 /* same as TK_TO_REAL */
#define OP_SetNumColumns 101
#define OP_Transaction 102
#define OP_VFilter 103
@@ -8246,7 +7750,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_IfZero 123
#define OP_BitNot 87 /* same as TK_BITNOT */
#define OP_VCreate 124
-#define OP_Found 125
+#define OP_Found 126
#define OP_IfPos 127
#define OP_NullRow 128
#define OP_Jump 129
@@ -8260,7 +7764,6 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_NotUsed_135 135
#define OP_NotUsed_136 136
#define OP_NotUsed_137 137
-#define OP_NotUsed_138 138
/* Properties such as "out2" or "jump" that are specified in
@@ -8289,10 +7792,9 @@ typedef struct VdbeOpList VdbeOpList;
/* 96 */ 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01,\
/* 104 */ 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x02, 0x05,\
/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01,\
-/* 120 */ 0x11, 0x00, 0x00, 0x05, 0x00, 0x11, 0x02, 0x05,\
+/* 120 */ 0x11, 0x00, 0x00, 0x05, 0x00, 0x02, 0x11, 0x05,\
/* 128 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 136 */ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,\
-}
+/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,}
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -8329,7 +7831,7 @@ SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*);
SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int);
-SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
+SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, int);
SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*);
SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
@@ -8338,8 +7840,7 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int);
#endif
-SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,
- UnpackedRecord*,int);
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int);
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
@@ -8427,16 +7928,15 @@ typedef struct PgHdr DbPage;
#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
-#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
-#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
/*
** See source code comments for a detailed description of the following
** routines:
*/
SQLITE_PRIVATE int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
-SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*));
+SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
+SQLITE_PRIVATE void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int));
+SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*);
SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
@@ -8445,7 +7945,6 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
-SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*);
SQLITE_PRIVATE int sqlite3PagerRef(DbPage*);
SQLITE_PRIVATE int sqlite3PagerUnref(DbPage*);
SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
@@ -8460,7 +7959,7 @@ SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager*);
SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager*);
SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager*);
SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage*);
-SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage*);
+SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*);
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int);
SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*);
@@ -8478,6 +7977,10 @@ SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
+#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
+SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int);
+#endif
+
#ifdef SQLITE_HAS_CODEC
SQLITE_PRIVATE void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
#endif
@@ -8505,168 +8008,6 @@ void enable_simulated_io_errors(void);
/************** End of pager.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
-/************** Include pcache.h in the middle of sqliteInt.h ****************/
-/************** Begin file pcache.h ******************************************/
-/*
-** 2008 August 05
-**
-** 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 header file defines the interface that the sqlite page cache
-** subsystem.
-**
-** @(#) $Id$
-*/
-
-#ifndef _PCACHE_H_
-
-typedef struct PgHdr PgHdr;
-typedef struct PCache PCache;
-
-/*
-** Every page in the cache is controlled by an instance of the following
-** structure.
-*/
-struct PgHdr {
- void *pData; /* Content of this page */
- void *pExtra; /* Extra content */
- PgHdr *pDirty; /* Transient list of dirty pages */
- Pgno pgno; /* Page number for this page */
- Pager *pPager; /* The pager this page is part of */
-#ifdef SQLITE_CHECK_PAGES
- u32 pageHash; /* Hash of page content */
-#endif
- u16 flags; /* PGHDR flags defined below */
-
- /**********************************************************************
- ** Elements above are public. All that follows is private to pcache.c
- ** and should not be accessed by other modules.
- */
- i16 nRef; /* Number of users of this page */
- PCache *pCache; /* Cache that owns this page */
-
- PgHdr *pDirtyNext; /* Next element in list of dirty pages */
- PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
-};
-
-/* Bit values for PgHdr.flags */
-#define PGHDR_DIRTY 0x002 /* Page has changed */
-#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before
- ** writing this page to the database */
-#define PGHDR_NEED_READ 0x008 /* Content is unread */
-#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */
-#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
-
-/* Initialize and shutdown the page cache subsystem */
-SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
-SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
-
-/* Page cache buffer management:
-** These routines implement SQLITE_CONFIG_PAGECACHE.
-*/
-SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n);
-
-/* Create a new pager cache.
-** Under memory stress, invoke xStress to try to make pages clean.
-** Only clean and unpinned pages can be reclaimed.
-*/
-SQLITE_PRIVATE void sqlite3PcacheOpen(
- int szPage, /* Size of every page */
- int szExtra, /* Extra space associated with each page */
- int bPurgeable, /* True if pages are on backing store */
- int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */
- void *pStress, /* Argument to xStress */
- PCache *pToInit /* Preallocated space for the PCache */
-);
-
-/* Modify the page-size after the cache has been created. */
-SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int);
-
-/* Return the size in bytes of a PCache object. Used to preallocate
-** storage space.
-*/
-SQLITE_PRIVATE int sqlite3PcacheSize(void);
-
-/* One release per successful fetch. Page is pinned until released.
-** Reference counted.
-*/
-SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**);
-SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*);
-
-SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
-SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
-SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
-SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
-
-/* Change a page number. Used by incr-vacuum. */
-SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno);
-
-/* Remove all pages with pgno>x. Reset the cache if x==0 */
-SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x);
-
-/* Get a list of all dirty pages in the cache, sorted by page number */
-SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*);
-
-/* Reset and close the cache object */
-SQLITE_PRIVATE void sqlite3PcacheClose(PCache*);
-
-/* Clear flags from pages of the page cache */
-SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *);
-
-/* Discard the contents of the cache */
-SQLITE_PRIVATE int sqlite3PcacheClear(PCache*);
-
-/* Return the total number of outstanding page references */
-SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*);
-
-/* Increment the reference count of an existing page */
-SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*);
-
-SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*);
-
-/* Return the total number of pages stored in the cache */
-SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*);
-
-#ifdef SQLITE_CHECK_PAGES
-/* Iterate through all dirty pages currently stored in the cache. This
-** interface is only available if SQLITE_CHECK_PAGES is defined when the
-** library is built.
-*/
-SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
-#endif
-
-/* Set and get the suggested cache-size for the specified pager-cache.
-**
-** If no global maximum is configured, then the system attempts to limit
-** the total number of pages cached by purgeable pager-caches to the sum
-** of the suggested cache-sizes.
-*/
-SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int);
-#ifdef SQLITE_TEST
-SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *);
-#endif
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-/* Try to return memory used by the pcache module to the main memory heap */
-SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int);
-#endif
-
-#ifdef SQLITE_TEST
-SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*);
-#endif
-
-SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
-
-#endif /* _PCACHE_H_ */
-
-/************** End of pcache.h **********************************************/
-/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include os.h in the middle of sqliteInt.h ********************/
/************** Begin file os.h **********************************************/
@@ -8975,17 +8316,24 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
*/
+#ifdef SQLITE_MUTEX_APPDEF
+/*
+** If SQLITE_MUTEX_APPDEF is defined, then this whole module is
+** omitted and equivalent functionality must be provided by the
+** application that links against the SQLite library.
+*/
+#else
/*
** Figure out what version of the code to use. The choices are
**
-** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The
-** mutexes implemention cannot be overridden
-** at start-time.
+** SQLITE_MUTEX_NOOP For single-threaded applications that
+** do not desire error checking.
**
-** SQLITE_MUTEX_NOOP For single-threaded applications. No
-** mutual exclusion is provided. But this
-** implementation can be overridden at
-** start-time.
+** SQLITE_MUTEX_NOOP_DEBUG For single-threaded applications with
+** error checking to help verify that mutexes
+** are being used correctly even though they
+** are not needed. Used when SQLITE_DEBUG is
+** defined on single-threaded builds.
**
** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix.
**
@@ -8993,22 +8341,25 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
**
** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2.
*/
-#if !SQLITE_THREADSAFE
-# define SQLITE_MUTEX_OMIT
-#endif
-#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP)
-# if SQLITE_OS_UNIX
-# define SQLITE_MUTEX_PTHREADS
-# elif SQLITE_OS_WIN
-# define SQLITE_MUTEX_W32
-# elif SQLITE_OS_OS2
-# define SQLITE_MUTEX_OS2
-# else
-# define SQLITE_MUTEX_NOOP
-# endif
+#define SQLITE_MUTEX_NOOP 1 /* The default */
+#if defined(SQLITE_DEBUG) && !SQLITE_THREADSAFE
+# undef SQLITE_MUTEX_NOOP
+# define SQLITE_MUTEX_NOOP_DEBUG
+#endif
+#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && SQLITE_OS_UNIX
+# undef SQLITE_MUTEX_NOOP
+# define SQLITE_MUTEX_PTHREADS
+#endif
+#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && SQLITE_OS_WIN
+# undef SQLITE_MUTEX_NOOP
+# define SQLITE_MUTEX_W32
+#endif
+#if defined(SQLITE_MUTEX_NOOP) && SQLITE_THREADSAFE && SQLITE_OS_OS2
+# undef SQLITE_MUTEX_NOOP
+# define SQLITE_MUTEX_OS2
#endif
-#ifdef SQLITE_MUTEX_OMIT
+#ifdef SQLITE_MUTEX_NOOP
/*
** If this is a no-op implementation, implement everything as macros.
*/
@@ -9022,7 +8373,9 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *);
#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8)
#define sqlite3MutexInit() SQLITE_OK
#define sqlite3MutexEnd()
-#endif /* defined(SQLITE_OMIT_MUTEX) */
+#endif
+
+#endif /* SQLITE_MUTEX_APPDEF */
/************** End of mutex.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -9120,7 +8473,7 @@ struct Lookaside {
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
int nOut; /* Number of buffers currently checked out */
int mxOut; /* Highwater mark for nOut */
- LookasideSlot *pFree; /* List of available buffers */
+ LookasideSlot *pFree; /* List if available buffers */
void *pStart; /* First byte of available memory space */
void *pEnd; /* First byte past end of available space */
};
@@ -9129,16 +8482,6 @@ struct LookasideSlot {
};
/*
-** A hash table for function definitions.
-**
-** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
-** Collisions are on the FuncDef.pHash chain.
-*/
-struct FuncDefHash {
- FuncDef *a[23]; /* Hash table for functions */
-};
-
-/*
** Each database is an instance of the following structure.
**
** The sqlite.lastRowid records the last insert rowid generated by an
@@ -9183,7 +8526,7 @@ struct sqlite3 {
CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
i64 lastRowid; /* ROWID of most recent insert (see above) */
i64 priorNewRowid; /* Last randomly generated ROWID */
- u32 magic; /* Magic number for detect library misuse */
+ int magic; /* Magic number for detect library misuse */
int nChange; /* Value returned by sqlite3_changes() */
int nTotalChange; /* Value returned by sqlite3_total_changes() */
sqlite3_mutex *mutex; /* Connection mutex */
@@ -9197,7 +8540,6 @@ struct sqlite3 {
void **aExtension; /* Array of shared libraray handles */
struct Vdbe *pVdbe; /* List of active virtual machines */
int activeVdbeCnt; /* Number of vdbes currently executing */
- int writeVdbeCnt; /* Number of active VDBEs that are writing */
void (*xTrace)(void*,const char*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
void (*xProfile)(void*,const char*,u64); /* Profiling function */
@@ -9215,7 +8557,7 @@ struct sqlite3 {
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
union {
- volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
+ int isInterrupted; /* True if sqlite3_interrupt has been called */
double notUsed1; /* Spacer */
} u1;
Lookaside lookaside; /* Lookaside malloc configuration */
@@ -9235,7 +8577,7 @@ struct sqlite3 {
sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */
int nVTrans; /* Allocated size of aVTrans */
#endif
- FuncDefHash aFunc; /* Hash table of connection functions */
+ Hash aFunc; /* All functions that can be in SQL exprs */
Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */
int busyTimeout; /* Busy handler timeout, in msec */
@@ -9302,60 +8644,17 @@ struct sqlite3 {
struct FuncDef {
i16 nArg; /* Number of arguments. -1 means unlimited */
u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
+ u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */
u8 flags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */
- char *zName; /* SQL name of the function. */
- FuncDef *pHash; /* Next with a different name but the same hash */
+ char zName[1]; /* SQL name of the function. MUST BE LAST */
};
/*
-** Possible values for FuncDef.flags
-*/
-#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
-#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
-#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
-#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
-
-/*
-** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
-** used to create the initializers for the FuncDef structures.
-**
-** FUNCTION(zName, nArg, iArg, bNC, xFunc)
-** Used to create a scalar function definition of a function zName
-** implemented by C function xFunc that accepts nArg arguments. The
-** value passed as iArg is cast to a (void*) and made available
-** as the user-data (sqlite3_user_data()) for the function. If
-** argument bNC is true, then the FuncDef.needCollate flag is set.
-**
-** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
-** Used to create an aggregate function definition implemented by
-** the C functions xStep and xFinal. The first four parameters
-** are interpreted in the same way as the first 4 parameters to
-** FUNCTION().
-**
-** LIKEFUNC(zName, nArg, pArg, flags)
-** Used to create a scalar function definition of a function zName
-** that accepts nArg arguments and is implemented by a call to C
-** function likeFunc. Argument pArg is cast to a (void *) and made
-** available as the function user-data (sqlite3_user_data()). The
-** FuncDef.flags variable is set to the value passed as the flags
-** parameter.
-*/
-#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_UTF8, bNC*8, SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0}
-#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
- {nArg, SQLITE_UTF8, bNC*8, pArg, 0, xFunc, 0, 0, #zName, 0}
-#define LIKEFUNC(zName, nArg, arg, flags) \
- {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0}
-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
- {nArg, SQLITE_UTF8, nc*8, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0}
-
-
-/*
** Each SQLite module (virtual table definition) is defined by an
** instance of the following structure, stored in the sqlite3.aModule
** hash table.
@@ -9368,6 +8667,13 @@ struct Module {
};
/*
+** Possible values for FuncDef.flags
+*/
+#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
+#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
+
+/*
** information about each column of an SQL table is held in an instance
** of this structure.
*/
@@ -9415,7 +8721,7 @@ struct CollSeq {
};
/*
-** Allowed values of CollSeq.type:
+** Allowed values of CollSeq flags:
*/
#define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */
#define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */
@@ -9433,7 +8739,7 @@ struct CollSeq {
**
** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
-** the speed a little by numbering the values consecutively.
+** the speed a little by number the values consecutively.
**
** But rather than start with 0 or 1, we begin with 'a'. That way,
** when multiple affinity types are concatenated into a string and
@@ -9479,14 +8785,14 @@ struct CollSeq {
** that the datatype of the PRIMARY KEY must be INTEGER for this field to
** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
-** is generated for each row of the table. TF_HasPrimaryKey is set if
+** is generated for each row of the table. Table.hasPrimKey is true if
** the table has any PRIMARY KEY, INTEGER or otherwise.
**
** Table.tnum is the page number for the root BTree page of the table in the
** database file. If Table.iDb is the index of the database table backend
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
-** holds temporary tables and indices. If TF_Ephemeral is set
-** then the table is stored in a file that is automatically deleted
+** holds temporary tables and indices. If Table.isEphem
+** is true, then the table is stored in a file that is automatically deleted
** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
** page number. Transient tables are used to hold the results of a
@@ -9494,55 +8800,47 @@ struct CollSeq {
** of a SELECT statement.
*/
struct Table {
- sqlite3 *db; /* Associated database connection. Might be NULL. */
- char *zName; /* Name of the table or view */
- int iPKey; /* If not negative, use aCol[iPKey] as the primary key */
- int nCol; /* Number of columns in this table */
- Column *aCol; /* Information about each column */
- Index *pIndex; /* List of SQL indexes on this table. */
- int tnum; /* Root BTree node for this table (see note above) */
- Select *pSelect; /* NULL for tables. Points to definition if a view. */
- u16 nRef; /* Number of pointers to this Table */
- u8 tabFlags; /* Mask of TF_* values */
- u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
- Trigger *pTrigger; /* List of SQL triggers on this table */
- FKey *pFKey; /* Linked list of all foreign keys in this table */
- char *zColAff; /* String defining the affinity of each column */
+ sqlite3 *db; /* Associated database connection. Might be NULL. */
+ char *zName; /* Name of the table */
+ int nCol; /* Number of columns in this table */
+ Column *aCol; /* Information about each column */
+ int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */
+ Index *pIndex; /* List of SQL indexes on this table. */
+ int tnum; /* Root BTree node for this table (see note above) */
+ Select *pSelect; /* NULL for tables. Points to definition if a view. */
+ int nRef; /* Number of pointers to this Table */
+ Trigger *pTrigger; /* List of SQL triggers on this table */
+ FKey *pFKey; /* Linked list of all foreign keys in this table */
+ char *zColAff; /* String defining the affinity of each column */
#ifndef SQLITE_OMIT_CHECK
- Expr *pCheck; /* The AND of all CHECK constraints */
+ Expr *pCheck; /* The AND of all CHECK constraints */
#endif
#ifndef SQLITE_OMIT_ALTERTABLE
- int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
+ int addColOffset; /* Offset in CREATE TABLE statement to add a new column */
#endif
+ u8 readOnly; /* True if this table should not be written by the user */
+ u8 isEphem; /* True if created using OP_OpenEphermeral */
+ u8 hasPrimKey; /* True if there exists a primary key */
+ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
+ u8 autoInc; /* True if the integer primary key is autoincrement */
#ifndef SQLITE_OMIT_VIRTUALTABLE
- Module *pMod; /* Pointer to the implementation of the module */
- sqlite3_vtab *pVtab; /* Pointer to the module instance */
- int nModuleArg; /* Number of arguments to the module */
- char **azModuleArg; /* Text of all module args. [0] is module name */
-#endif
- Schema *pSchema; /* Schema that contains this table */
- Table *pNextZombie; /* Next on the Parse.pZombieTab list */
+ u8 isVirtual; /* True if this is a virtual table */
+ u8 isCommit; /* True once the CREATE TABLE has been committed */
+ Module *pMod; /* Pointer to the implementation of the module */
+ sqlite3_vtab *pVtab; /* Pointer to the module instance */
+ int nModuleArg; /* Number of arguments to the module */
+ char **azModuleArg; /* Text of all module args. [0] is module name */
+#endif
+ Schema *pSchema; /* Schema that contains this table */
};
/*
-** Allowed values for Tabe.tabFlags.
-*/
-#define TF_Readonly 0x01 /* Read-only system table */
-#define TF_Ephemeral 0x02 /* An emphermal table */
-#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
-#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
-#define TF_Virtual 0x10 /* Is a virtual table */
-#define TF_NeedMetadata 0x20 /* aCol[].zType and aCol[].pColl missing */
-
-
-
-/*
** Test to see whether or not a table is a virtual table. This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
-# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
+# define IsVirtual(X) ((X)->isVirtual)
# define IsHiddenColumn(X) ((X)->isHidden)
#else
# define IsVirtual(X) 0
@@ -9634,46 +8932,22 @@ struct FKey {
** An instance of the following structure is passed as the first
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
+**
+** If the KeyInfo.incrKey value is true and the comparison would
+** otherwise be equal, then return a result as if the second key
+** were larger.
*/
struct KeyInfo {
sqlite3 *db; /* The database connection */
u8 enc; /* Text encoding - one of the TEXT_Utf* values */
- u16 nField; /* Number of entries in aColl[] */
+ u8 incrKey; /* Increase 2nd key by epsilon before comparison */
+ u8 prefixIsEqual; /* Treat a prefix as equal */
+ int nField; /* Number of entries in aColl[] */
u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
};
/*
-** An instance of the following structure holds information about a
-** single index record that has already been parsed out into individual
-** values.
-**
-** A record is an object that contains one or more fields of data.
-** Records are used to store the content of a table row and to store
-** the key of an index. A blob encoding of a record is created by
-** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
-** OP_Column opcode.
-**
-** This structure holds a record that has already been disassembled
-** into its constitutent fields.
-*/
-struct UnpackedRecord {
- KeyInfo *pKeyInfo; /* Collation and sort-order information */
- u16 nField; /* Number of entries in apMem[] */
- u16 flags; /* Boolean settings. UNPACKED_... below */
- Mem *aMem; /* Values */
-};
-
-/*
-** Allowed values of UnpackedRecord.flags
-*/
-#define UNPACKED_NEED_FREE 0x0001 /* Memory is from sqlite3Malloc() */
-#define UNPACKED_NEED_DESTROY 0x0002 /* apMem[]s should all be destroyed */
-#define UNPACKED_IGNORE_ROWID 0x0004 /* Ignore trailing rowid on key1 */
-#define UNPACKED_INCRKEY 0x0008 /* Make this key an epsilon larger */
-#define UNPACKED_PREFIX_MATCH 0x0010 /* A prefix match is considered OK */
-
-/*
** Each SQL index is represented in memory by an
** instance of the following structure.
**
@@ -9836,7 +9110,7 @@ struct Expr {
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
Select *pSelect; /* When the expression is a sub-select. Also the
** right side of "<expr> IN (<select>)" */
- Table *pTab; /* Table for TK_COLUMN expressions. */
+ Table *pTab; /* Table for OP_Column expressions. */
#if SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Height of the tree headed by this node */
#endif
@@ -9882,9 +9156,8 @@ struct ExprList {
Expr *pExpr; /* The list of expressions */
char *zName; /* Token associated with this expression */
u8 sortOrder; /* 1 for DESC or 0 for ASC */
+ u8 isAgg; /* True if this is an aggregate like count(*) */
u8 done; /* A flag to indicate when processing is finished */
- u16 iCol; /* For ORDER BY, column number in result set */
- u16 iAlias; /* Index into Parse.aAlias[] for zName */
} *a; /* One entry for each expression */
};
@@ -9922,11 +9195,6 @@ struct IdList {
typedef u64 Bitmask;
/*
-** The number of bits in a Bitmask. "BMS" means "BitMask Size".
-*/
-#define BMS ((int)(sizeof(Bitmask)*8))
-
-/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
@@ -9957,9 +9225,6 @@ struct SrcList {
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N or pTab is used */
- u8 notIndexed; /* True if there is a NOT INDEXED clause */
- char *zIndex; /* Identifier from "INDEXED BY <zIndex>" clause */
- Index *pIndex; /* Index structure corresponding to zIndex, if any */
} a[1]; /* One entry for each identifier on the list */
};
@@ -10005,7 +9270,7 @@ struct WhereLevel {
int nxt; /* Jump here to start the next IN combination */
int cont; /* Jump here to continue with the next loop cycle */
int top; /* First instruction of interior of the loop */
- int op, p1, p2, p5; /* Opcode used to terminate the loop */
+ int op, p1, p2; /* Opcode used to terminate the loop */
int nEq; /* Number of == or IN constraints on this loop */
int nIn; /* Number of IN operators constraining this loop */
struct InLoop {
@@ -10106,8 +9371,12 @@ struct NameContext {
struct Select {
ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
+ u8 isDistinct; /* True if the DISTINCT keyword is present */
+ u8 isResolved; /* True once sqlite3SelectResolve() has run. */
+ u8 isAgg; /* True if this is an aggregate query */
+ u8 usesEphm; /* True if uses an OpenEphemeral opcode */
+ u8 disallowOrderBy; /* Do not allow an ORDER BY to be attached if TRUE */
char affinity; /* MakeRecord with this affinity for SRT_Set */
- u16 selFlags; /* Various SF_* values */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
@@ -10123,20 +9392,7 @@ struct Select {
};
/*
-** Allowed values for Select.selFlags. The "SF" prefix stands for
-** "Select Flag".
-*/
-#define SF_Distinct 0x0001 /* Output should be DISTINCT */
-#define SF_Resolved 0x0002 /* Identifiers have been resolved */
-#define SF_Aggregate 0x0004 /* Contains aggregate functions */
-#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
-#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
-#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
-
-
-/*
-** The results of a select can be distributed in several ways. The
-** "SRT" prefix means "SELECT Result Type".
+** The results of a select can be distributed in several ways.
*/
#define SRT_Union 1 /* Store result as keys in an index */
#define SRT_Except 2 /* Remove result from a UNION index */
@@ -10146,7 +9402,7 @@ struct Select {
/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)
-#define SRT_Output 5 /* Output each row of result */
+#define SRT_Callback 5 /* Invoke a callback with each row of result */
#define SRT_Mem 6 /* Store result in a memory cell */
#define SRT_Set 7 /* Store results as keys in an index */
#define SRT_Table 8 /* Store result as data with an automatic rowid */
@@ -10229,8 +9485,6 @@ struct Parse {
int nVarExpr; /* Number of used slots in apVarExpr[] */
int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */
Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */
- int nAlias; /* Number of aliased result set columns */
- int *aAlias; /* Register used to hold aliased result */
u8 explain; /* True if the EXPLAIN flag is found on the query */
Token sErrToken; /* The token at which the error occurred */
Token sNameToken; /* Token with unqualified schema object name */
@@ -10248,7 +9502,6 @@ struct Parse {
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
int nHeight; /* Expression tree height of current sub-select */
- Table *pZombieTab; /* List of Table objects to delete after code gen */
};
#ifdef SQLITE_OMIT_VIRTUALTABLE
@@ -10461,7 +9714,6 @@ struct Sqlite3Config {
int nLookaside; /* Default lookaside buffer count */
sqlite3_mem_methods m; /* Low-level memory allocation interface */
sqlite3_mutex_methods mutex; /* Low-level mutex interface */
- sqlite3_pcache_methods pcache; /* Low-level page-cache interface */
void *pHeap; /* Heap storage space */
int nHeap; /* Size of pHeap[] */
int mnReq, mxReq; /* Min and max heap requests sizes */
@@ -10472,43 +9724,13 @@ struct Sqlite3Config {
int szPage; /* Size of each page in pPage[] */
int nPage; /* Number of pages in pPage[] */
int isInit; /* True after initialization has finished */
- int inProgress; /* True while initialization in progress */
int isMallocInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
- int nRefInitMutex; /* Number of users of pInitMutex */
+ int nSmall; /* alloc size threshold used by mem6.c */
int mxParserStack; /* maximum depth of the parser stack */
- int sharedCacheEnabled; /* true if shared-cache mode enabled */
};
/*
-** Context pointer passed down through the tree-walk.
-*/
-struct Walker {
- int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
- int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
- Parse *pParse; /* Parser context. */
- union { /* Extra data for callback */
- NameContext *pNC; /* Naming context */
- int i; /* Integer value */
- } u;
-};
-
-/* Forward declarations */
-SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
-SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
-SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
-SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
-SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
-
-/*
-** Return code from the parse-tree walking primitives and their
-** callbacks.
-*/
-#define WRC_Continue 0
-#define WRC_Prune 1
-#define WRC_Abort 2
-
-/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
@@ -10558,24 +9780,20 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void*);
SQLITE_PRIVATE void *sqlite3PageMalloc(int);
SQLITE_PRIVATE void sqlite3PageFree(void*);
SQLITE_PRIVATE void sqlite3MemSetDefault(void);
-SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
-SQLITE_PRIVATE int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64);
-
-#ifdef SQLITE_ENABLE_MEMSYS3
-SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
-#endif
-#ifdef SQLITE_ENABLE_MEMSYS5
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetDefault(void);
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
-#endif
-
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys6(void);
+SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
-#ifndef SQLITE_MUTEX_OMIT
+#ifndef SQLITE_MUTEX_NOOP
SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void);
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int);
SQLITE_PRIVATE int sqlite3MutexInit(void);
SQLITE_PRIVATE int sqlite3MutexEnd(void);
#endif
+SQLITE_PRIVATE void sqlite3StatusReset(void);
SQLITE_PRIVATE int sqlite3StatusValue(int);
SQLITE_PRIVATE void sqlite3StatusAdd(int, int);
SQLITE_PRIVATE void sqlite3StatusSet(int, int);
@@ -10611,7 +9829,6 @@ SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
SQLITE_PRIVATE void sqlite3ExprSpan(Expr*,Token*,Token*);
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*);
-SQLITE_PRIVATE void sqlite3ExprClear(sqlite3*, Expr*);
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*,Token*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
@@ -10621,7 +9838,7 @@ SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3*, int);
SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*);
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
@@ -10654,12 +9871,9 @@ SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*,
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int,int*,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
-SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int);
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
-SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
- Token*, Select*, Expr*, IdList*);
-SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
-SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
+SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, Token*,
+ Select*, Expr*, IdList*);
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList*);
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
@@ -10667,16 +9881,13 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Token*, int, int);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
-SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
+SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,int,Expr*,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
-#endif
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8);
@@ -10705,6 +9916,7 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse*);
SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*);
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*);
+SQLITE_PRIVATE int sqlite3ExprResolveNames(NameContext *, Expr *);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
@@ -10727,7 +9939,7 @@ SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
int*,int,int,int,int);
-SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
+SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*,int,int,int,int);
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*);
@@ -10736,11 +9948,9 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*);
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*);
-SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*);
-SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void);
-SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void);
+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(sqlite3*);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3*);
@@ -10751,10 +9961,7 @@ SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
-
-#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
-SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
-#endif
+SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Select*, Expr*, int);
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
@@ -10762,7 +9969,7 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,
SQLITE_PRIVATE void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
SQLITE_PRIVATE void sqlite3DropTrigger(Parse*, SrcList*, int);
SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse*, Trigger*);
-SQLITE_PRIVATE int sqlite3TriggersExist(Table*, int, ExprList*);
+SQLITE_PRIVATE int sqlite3TriggersExist(Parse*, Table*, int, ExprList*);
SQLITE_PRIVATE int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,
int, int, u32*, u32*);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
@@ -10775,7 +9982,7 @@ SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
#else
-# define sqlite3TriggersExist(B,C,D,E,F) 0
+# define sqlite3TriggersExist(A,B,C,D,E,F) 0
# define sqlite3DeleteTrigger(A,B)
# define sqlite3DropTriggerPtr(A,B)
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
@@ -10807,6 +10014,7 @@ SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*);
+SQLITE_API char *sqlite3_snprintf(int,char*,const char*,...);
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *, int);
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
@@ -10843,8 +10051,8 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
** x = putVarint32( A, B );
**
*/
-#define getVarint32(A,B) ((*(A)<(unsigned char)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), (u32 *)&(B)))
-#define putVarint32(A,B) (((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B)))
+#define getVarint32(A,B) ((*(A)<(unsigned char)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), &(B)))
+#define putVarint32(A,B) (((B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B)))
#define getVarint sqlite3GetVarint
#define putVarint sqlite3PutVarint
@@ -10879,8 +10087,7 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
-SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
-SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
+SQLITE_PRIVATE struct Sqlite3Config sqlite3Config;
#endif
SQLITE_PRIVATE void sqlite3RootPageMoved(Db*, int, int);
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
@@ -10889,11 +10096,8 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
-SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *, Expr *, int, int);
-SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
-SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
-SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
-SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
+SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *, Expr *, int);
+SQLITE_PRIVATE int sqlite3SelectResolve(Parse *, Select *, NameContext *);
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
@@ -10906,6 +10110,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*);
SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3*, int);
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
+SQLITE_PRIVATE void sqlite3AttachFunctions(sqlite3 *);
SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int);
SQLITE_PRIVATE void sqlite3SchemaFree(void *);
SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
@@ -10955,13 +10160,11 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
# define sqlite3VtabSync(X,Y) SQLITE_OK
# define sqlite3VtabRollback(X)
# define sqlite3VtabCommit(X)
-# define sqlite3VtabInSync(db) 0
#else
SQLITE_PRIVATE void sqlite3VtabClear(Table*);
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **);
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
-# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
SQLITE_PRIVATE void sqlite3VtabLock(sqlite3_vtab*);
@@ -10976,7 +10179,6 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
-SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
@@ -11014,18 +10216,12 @@ SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *);
#define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
#endif
-SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
-SQLITE_PRIVATE int sqlite3MemJournalSize();
-SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *);
-
#if SQLITE_MAX_EXPR_DEPTH>0
SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *);
-SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int);
#else
#define sqlite3ExprSetHeight(x,y)
#define sqlite3SelectExprHeight(x) 0
- #define sqlite3ExprCheckHeight(x,y)
#endif
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
@@ -11124,24 +10320,16 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
** The following singleton contains the global configuration for
** the SQLite library.
*/
-SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
- SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
- 1, /* bCoreMutex */
- SQLITE_THREADSAFE==1, /* bFullMutex */
- 0x7ffffffe, /* mxStrlen */
- 100, /* szLookaside */
- 500, /* nLookaside */
+SQLITE_PRIVATE struct Sqlite3Config sqlite3Config = {
+ 1, /* bMemstat */
+ 1, /* bCoreMutex */
+ 1, /* bFullMutex */
+ 0x7ffffffe, /* mxStrlen */
+ 100, /* szLookaside */
+ 500, /* nLookaside */
/* Other fields all default to zero */
};
-
-/*
-** Hash table for global functions - functions common to all
-** database connections. After initialization, this table is
-** read-only.
-*/
-SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
-
/************** End of global.c **********************************************/
/************** Begin file status.c ******************************************/
/*
@@ -11165,34 +10353,26 @@ SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
/*
** Variables in which to record status information.
*/
-typedef struct sqlite3StatType sqlite3StatType;
-static SQLITE_WSD struct sqlite3StatType {
+static struct {
int nowValue[9]; /* Current value */
int mxValue[9]; /* Maximum value */
-} sqlite3Stat = { {0,}, {0,} };
+} sqlite3Stat;
-/* The "wsdStat" macro will resolve to the status information
-** state vector. If writable static data is unsupported on the target,
-** we have to locate the state vector at run-time. In the more common
-** case where writable static data is supported, wsdStat can refer directly
-** to the "sqlite3Stat" state vector declared above.
+/*
+** Reset the status records. This routine is called by
+** sqlite3_initialize().
*/
-#ifdef SQLITE_OMIT_WSD
-# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
-# define wsdStat x[0]
-#else
-# define wsdStatInit
-# define wsdStat sqlite3Stat
-#endif
+SQLITE_PRIVATE void sqlite3StatusReset(void){
+ memset(&sqlite3Stat, 0, sizeof(sqlite3Stat));
+}
/*
** Return the current value of a status parameter.
*/
SQLITE_PRIVATE int sqlite3StatusValue(int op){
- wsdStatInit;
- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
- return wsdStat.nowValue[op];
+ assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
+ return sqlite3Stat.nowValue[op];
}
/*
@@ -11200,11 +10380,10 @@ SQLITE_PRIVATE int sqlite3StatusValue(int op){
** caller holds appropriate locks.
*/
SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
- wsdStatInit;
- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
- wsdStat.nowValue[op] += N;
- if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
- wsdStat.mxValue[op] = wsdStat.nowValue[op];
+ assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
+ sqlite3Stat.nowValue[op] += N;
+ if( sqlite3Stat.nowValue[op]>sqlite3Stat.mxValue[op] ){
+ sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
}
}
@@ -11212,11 +10391,10 @@ SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
** Set the value of a status to X.
*/
SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
- wsdStatInit;
- assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
- wsdStat.nowValue[op] = X;
- if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
- wsdStat.mxValue[op] = wsdStat.nowValue[op];
+ assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
+ sqlite3Stat.nowValue[op] = X;
+ if( sqlite3Stat.nowValue[op]>sqlite3Stat.mxValue[op] ){
+ sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
}
}
@@ -11228,14 +10406,13 @@ SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
** then this routine is not threadsafe.
*/
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
- wsdStatInit;
- if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
+ if( op<0 || op>=ArraySize(sqlite3Stat.nowValue) ){
return SQLITE_MISUSE;
}
- *pCurrent = wsdStat.nowValue[op];
- *pHighwater = wsdStat.mxValue[op];
+ *pCurrent = sqlite3Stat.nowValue[op];
+ *pHighwater = sqlite3Stat.mxValue[op];
if( resetFlag ){
- wsdStat.mxValue[op] = wsdStat.nowValue[op];
+ sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
}
return SQLITE_OK;
}
@@ -11788,7 +10965,7 @@ static int parseModifier(const char *zMod, DateTime *p){
double r;
char *z, zBuf[30];
z = zBuf;
- for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
+ for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){
z[n] = tolower(zMod[n]);
}
z[n] = 0;
@@ -11823,7 +11000,7 @@ static int parseModifier(const char *zMod, DateTime *p){
}
#ifndef SQLITE_OMIT_LOCALTIME
else if( strcmp(z, "utc")==0 ){
- int c1;
+ double c1;
computeJD(p);
c1 = localtimeOffset(p);
p->iJD -= c1;
@@ -12156,7 +11333,7 @@ static void strftimeFunc(
}
if( n<sizeof(zBuf) ){
z = zBuf;
- }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ }else if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
return;
}else{
@@ -12235,10 +11412,9 @@ static void strftimeFunc(
*/
static void ctimeFunc(
sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
+ int argc,
+ sqlite3_value **argv
){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
timeFunc(context, 0, 0);
}
@@ -12249,10 +11425,9 @@ static void ctimeFunc(
*/
static void cdateFunc(
sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
+ int argc,
+ sqlite3_value **argv
){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
dateFunc(context, 0, 0);
}
@@ -12263,10 +11438,9 @@ static void cdateFunc(
*/
static void ctimestampFunc(
sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
+ int argc,
+ sqlite3_value **argv
){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
datetimeFunc(context, 0, 0);
}
#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
@@ -12322,30 +11496,44 @@ static void currentTimeFunc(
** functions. This should be the only routine in this file with
** external linkage.
*/
-SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
- static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
#ifndef SQLITE_OMIT_DATETIME_FUNCS
- FUNCTION(julianday, -1, 0, 0, juliandayFunc ),
- FUNCTION(date, -1, 0, 0, dateFunc ),
- FUNCTION(time, -1, 0, 0, timeFunc ),
- FUNCTION(datetime, -1, 0, 0, datetimeFunc ),
- FUNCTION(strftime, -1, 0, 0, strftimeFunc ),
- FUNCTION(current_time, 0, 0, 0, ctimeFunc ),
- FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
- FUNCTION(current_date, 0, 0, 0, cdateFunc ),
+ static const struct {
+ char *zName;
+ int nArg;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
+ } aFuncs[] = {
+ { "julianday", -1, juliandayFunc },
+ { "date", -1, dateFunc },
+ { "time", -1, timeFunc },
+ { "datetime", -1, datetimeFunc },
+ { "strftime", -1, strftimeFunc },
+ { "current_time", 0, ctimeFunc },
+ { "current_timestamp", 0, ctimestampFunc },
+ { "current_date", 0, cdateFunc },
+ };
+ int i;
+
+ for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+ sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
+ SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
+ }
#else
- STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
- STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc),
- STR_FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
-#endif
+ static const struct {
+ char *zName;
+ char *zFormat;
+ } aFuncs[] = {
+ { "current_time", "%H:%M:%S" },
+ { "current_date", "%Y-%m-%d" },
+ { "current_timestamp", "%Y-%m-%d %H:%M:%S" }
};
int i;
- FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
- FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
- for(i=0; i<ArraySize(aDateTimeFuncs); i++){
- sqlite3FuncDefInsert(pHash, &aFunc[i]);
+ for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+ sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8,
+ aFuncs[i].zFormat, currentTimeFunc, 0, 0);
}
+#endif
}
/************** End of date.c ************************************************/
@@ -12387,7 +11575,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
** sqlite3OsLock()
**
*/
-#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0)
+#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) && 0
#define DO_OS_MALLOC_TEST if (1) { \
void *pTstAlloc = sqlite3Malloc(10); \
if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \
@@ -12541,8 +11729,7 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *pFile){
/*
** The list of all registered VFS implementations.
*/
-static sqlite3_vfs * SQLITE_WSD vfsList = 0;
-#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
+static sqlite3_vfs *vfsList = 0;
/*
** Locate a VFS by name. If no name is given, simply return the
@@ -12550,14 +11737,14 @@ static sqlite3_vfs * SQLITE_WSD vfsList = 0;
*/
SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
sqlite3_vfs *pVfs = 0;
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex;
#endif
#ifndef SQLITE_OMIT_AUTOINIT
int rc = sqlite3_initialize();
if( rc ) return 0;
#endif
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
sqlite3_mutex_enter(mutex);
@@ -12619,7 +11806,7 @@ SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
** Unregister a VFS so that it is no longer accessible.
*/
SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
sqlite3_mutex_enter(mutex);
@@ -12666,27 +11853,10 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
/*
** Global variables.
*/
-typedef struct BenignMallocHooks BenignMallocHooks;
-static SQLITE_WSD struct BenignMallocHooks {
+static struct BenignMallocHooks {
void (*xBenignBegin)(void);
void (*xBenignEnd)(void);
-} sqlite3Hooks = { 0, 0 };
-
-/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
-** structure. If writable static data is unsupported on the target,
-** we have to locate the state vector at run-time. In the more common
-** case where writable static data is supported, wsdHooks can refer directly
-** to the "sqlite3Hooks" state vector declared above.
-*/
-#ifdef SQLITE_OMIT_WSD
-# define wsdHooksInit \
- BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
-# define wsdHooks x[0]
-#else
-# define wsdHooksInit
-# define wsdHooks sqlite3Hooks
-#endif
-
+} hooks;
/*
** Register hooks to call when sqlite3BeginBenignMalloc() and
@@ -12696,9 +11866,8 @@ SQLITE_PRIVATE void sqlite3BenignMallocHooks(
void (*xBenignBegin)(void),
void (*xBenignEnd)(void)
){
- wsdHooksInit;
- wsdHooks.xBenignBegin = xBenignBegin;
- wsdHooks.xBenignEnd = xBenignEnd;
+ hooks.xBenignBegin = xBenignBegin;
+ hooks.xBenignEnd = xBenignEnd;
}
/*
@@ -12707,84 +11876,19 @@ SQLITE_PRIVATE void sqlite3BenignMallocHooks(
** indicates that subsequent malloc failures are non-benign.
*/
SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
- wsdHooksInit;
- if( wsdHooks.xBenignBegin ){
- wsdHooks.xBenignBegin();
+ if( hooks.xBenignBegin ){
+ hooks.xBenignBegin();
}
}
SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
- wsdHooksInit;
- if( wsdHooks.xBenignEnd ){
- wsdHooks.xBenignEnd();
+ if( hooks.xBenignEnd ){
+ hooks.xBenignEnd();
}
}
#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
/************** End of fault.c ***********************************************/
-/************** Begin file mem0.c ********************************************/
-/*
-** 2008 October 28
-**
-** 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 a no-op memory allocation drivers for use when
-** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented
-** here always fail. SQLite will not operate with these drivers. These
-** are merely placeholders. Real drivers must be substituted using
-** sqlite3_config() before SQLite will operate.
-**
-** $Id$
-*/
-
-/*
-** This version of the memory allocator is the default. It is
-** used when no other memory allocator is specified using compile-time
-** macros.
-*/
-#ifdef SQLITE_ZERO_MALLOC
-
-/*
-** No-op versions of all memory allocation routines
-*/
-static void *sqlite3MemMalloc(int nByte){ return 0; }
-static void sqlite3MemFree(void *pPrior){ return; }
-static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
-static int sqlite3MemSize(void *pPrior){ return 0; }
-static int sqlite3MemRoundup(int n){ return n; }
-static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
-static void sqlite3MemShutdown(void *NotUsed){ return; }
-
-/*
-** This routine is the only routine in this file with external linkage.
-**
-** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file.
-*/
-SQLITE_PRIVATE void sqlite3MemSetDefault(void){
- static const sqlite3_mem_methods defaultMethods = {
- sqlite3MemMalloc,
- sqlite3MemFree,
- sqlite3MemRealloc,
- sqlite3MemSize,
- sqlite3MemRoundup,
- sqlite3MemInit,
- sqlite3MemShutdown,
- 0
- };
- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
-}
-
-#endif /* SQLITE_ZERO_MALLOC */
-
-/************** End of mem0.c ************************************************/
/************** Begin file mem1.c ********************************************/
/*
** 2007 August 14
@@ -12897,7 +12001,6 @@ static int sqlite3MemRoundup(int n){
** Initialize this module.
*/
static int sqlite3MemInit(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
return SQLITE_OK;
}
@@ -12905,17 +12008,10 @@ static int sqlite3MemInit(void *NotUsed){
** Deinitialize this module.
*/
static void sqlite3MemShutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
return;
}
-/*
-** This routine is the only routine in this file with external linkage.
-**
-** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file.
-*/
-SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetDefault(void){
static const sqlite3_mem_methods defaultMethods = {
sqlite3MemMalloc,
sqlite3MemFree,
@@ -12926,7 +12022,17 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
sqlite3MemShutdown,
0
};
- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+ return &defaultMethods;
+}
+
+/*
+** This routine is the only routine in this file with external linkage.
+**
+** Populate the low-level memory allocation function pointers in
+** sqlite3Config.m with pointers to the routines in this file.
+*/
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+ sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault());
}
#endif /* SQLITE_SYSTEM_MALLOC */
@@ -12970,7 +12076,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
extern int backtrace(void**,int);
extern void backtrace_symbols_fd(void*const*,int,int);
#else
-# define backtrace(A,B) 1
+# define backtrace(A,B) 0
# define backtrace_symbols_fd(A,B,C)
#endif
@@ -13118,7 +12224,7 @@ static int sqlite3MemSize(void *p){
** Initialize the memory allocation subsystem.
*/
static int sqlite3MemInit(void *NotUsed){
- if( !sqlite3GlobalConfig.bMemstat ){
+ if( !sqlite3Config.bMemstat ){
/* If memory status is enabled, then the malloc.c wrapper will already
** hold the STATIC_MEM mutex when the routines here are invoked. */
mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
@@ -13203,7 +12309,7 @@ static void sqlite3MemFree(void *pPrior){
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
- assert( sqlite3GlobalConfig.bMemstat || mem.mutex!=0 );
+ assert( sqlite3Config.bMemstat || mem.mutex!=0 );
pHdr = sqlite3MemsysGetHeader(pPrior);
pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
@@ -13256,11 +12362,8 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){
return pNew;
}
-/*
-** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file.
-*/
-SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetDefault(void){
static const sqlite3_mem_methods defaultMethods = {
sqlite3MemMalloc,
sqlite3MemFree,
@@ -13271,7 +12374,15 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
sqlite3MemShutdown,
0
};
- sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+ return &defaultMethods;
+}
+
+/*
+** Populate the low-level memory allocation function pointers in
+** sqlite3Config.m with pointers to the routines in this file.
+*/
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+ sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault());
}
/*
@@ -13472,14 +12583,7 @@ struct Mem3Block {
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
-static SQLITE_WSD struct Mem3Global {
- /*
- ** Memory available for allocation. nPool is the size of the array
- ** (in Mem3Blocks) pointed to by aPool less 2.
- */
- u32 nPool;
- Mem3Block *aPool;
-
+static struct {
/*
** True if we are evaluating an out-of-memory callback.
*/
@@ -13511,9 +12615,14 @@ static SQLITE_WSD struct Mem3Global {
*/
u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
-} mem3 = { 97535575 };
-#define mem3 GLOBAL(struct Mem3Global, mem3)
+ /*
+ ** Memory available for allocation. nPool is the size of the array
+ ** (in Mem3Blocks) pointed to by aPool less 2.
+ */
+ u32 nPool;
+ Mem3Block *aPool;
+} mem3;
/*
** Unlink the chunk at mem3.aPool[i] from list it is currently
@@ -13592,10 +12701,10 @@ static void memsys3Link(u32 i){
/*
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
** will already be held (obtained by code in malloc.c) if
-** sqlite3GlobalConfig.bMemStat is true.
+** sqlite3Config.bMemStat is true.
*/
static void memsys3Enter(void){
- if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
+ if( sqlite3Config.bMemstat==0 && mem3.mutex==0 ){
mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
sqlite3_mutex_enter(mem3.mutex);
@@ -13624,7 +12733,7 @@ static void memsys3OutOfMemory(int nByte){
** size parameters for check-out and return a pointer to the
** user portion of the chunk.
*/
-static void *memsys3Checkout(u32 i, u32 nBlock){
+static void *memsys3Checkout(u32 i, int nBlock){
u32 x;
assert( sqlite3_mutex_held(mem3.mutex) );
assert( i>=1 );
@@ -13642,7 +12751,7 @@ static void *memsys3Checkout(u32 i, u32 nBlock){
** Return a pointer to the new allocation. Or, if the master chunk
** is not large enough, return 0.
*/
-static void *memsys3FromMaster(u32 nBlock){
+static void *memsys3FromMaster(int nBlock){
assert( sqlite3_mutex_held(mem3.mutex) );
assert( mem3.szMaster>=nBlock );
if( nBlock>=mem3.szMaster-1 ){
@@ -13728,8 +12837,8 @@ static void memsys3Merge(u32 *pRoot){
*/
static void *memsys3MallocUnsafe(int nByte){
u32 i;
- u32 nBlock;
- u32 toFree;
+ int nBlock;
+ int toFree;
assert( sqlite3_mutex_held(mem3.mutex) );
assert( sizeof(Mem3Block)==8 );
@@ -13925,15 +13034,14 @@ void *memsys3Realloc(void *pPrior, int nBytes){
** Initialize this module.
*/
static int memsys3Init(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- if( !sqlite3GlobalConfig.pHeap ){
+ if( !sqlite3Config.pHeap ){
return SQLITE_ERROR;
}
/* Store a pointer to the memory block in global structure mem3. */
assert( sizeof(Mem3Block)==8 );
- mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
- mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
+ mem3.aPool = (Mem3Block *)sqlite3Config.pHeap;
+ mem3.nPool = (sqlite3Config.nHeap / sizeof(Mem3Block)) - 2;
/* Initialize the master block. */
mem3.szMaster = mem3.nPool;
@@ -13950,7 +13058,6 @@ static int memsys3Init(void *NotUsed){
** Deinitialize this module.
*/
static void memsys3Shutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
return;
}
@@ -13960,10 +13067,10 @@ static void memsys3Shutdown(void *NotUsed){
** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
-SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
FILE *out;
- u32 i, j;
+ int i, j;
u32 size;
if( zFilename==0 || zFilename[0]==0 ){
out = stdout;
@@ -14028,17 +13135,15 @@ SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
}else{
fclose(out);
}
-#else
- UNUSED_PARAMETER(zFilename);
-#endif
}
+#endif
/*
** This routine is the only routine in this file with external
** linkage.
**
** Populate the low-level memory allocation function pointers in
-** sqlite3GlobalConfig.m with pointers to the routines in this file. The
+** sqlite3Config.m with pointers to the routines in this file. The
** arguments specify the block of memory to manage.
**
** This routine is only called by sqlite3_config(), and therefore
@@ -14092,11 +13197,33 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
/*
** This version of the memory allocator is used only when
-** SQLITE_ENABLE_MEMSYS5 is defined.
+** SQLITE_POW2_MEMORY_SIZE is defined.
*/
#ifdef SQLITE_ENABLE_MEMSYS5
/*
+** Log2 of the minimum size of an allocation. For example, if
+** 4 then all allocations will be rounded up to at least 16 bytes.
+** If 5 then all allocations will be rounded up to at least 32 bytes.
+*/
+#ifndef SQLITE_POW2_LOGMIN
+# define SQLITE_POW2_LOGMIN 6
+#endif
+
+/*
+** Log2 of the maximum size of an allocation.
+*/
+#ifndef SQLITE_POW2_LOGMAX
+# define SQLITE_POW2_LOGMAX 20
+#endif
+#define POW2_MAX (((unsigned int)1)<<SQLITE_POW2_LOGMAX)
+
+/*
+** Number of distinct allocation sizes.
+*/
+#define NSIZE (SQLITE_POW2_LOGMAX - SQLITE_POW2_LOGMIN + 1)
+
+/*
** A minimum allocation is an instance of the following structure.
** Larger allocations are an array of these structures where the
** size of the array is a power of 2.
@@ -14126,13 +13253,18 @@ struct Mem5Link {
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
-static SQLITE_WSD struct Mem5Global {
+static struct {
/*
- ** Memory available for allocation
+ ** The alarm callback and its arguments. The mem5.mutex lock will
+ ** be held while the callback is running. Recursive calls into
+ ** the memory subsystem are allowed, but no new callbacks will be
+ ** issued. The alarmBusy variable is set to prevent recursive
+ ** callbacks.
*/
- int nAtom; /* Smallest possible allocation in bytes */
- int nBlock; /* Number of nAtom sized blocks in zPool */
- u8 *zPool;
+ sqlite3_int64 alarmThreshold;
+ void (*alarmCallback)(void*, sqlite3_int64,int);
+ void *alarmArg;
+ int alarmBusy;
/*
** Mutex to control access to the memory allocation subsystem.
@@ -14162,9 +13294,13 @@ static SQLITE_WSD struct Mem5Global {
*/
u8 *aCtrl;
-} mem5 = { 19804167 };
-
-#define mem5 GLOBAL(struct Mem5Global, mem5)
+ /*
+ ** Memory available for allocation
+ */
+ int nAtom; /* Smallest possible allocation in bytes */
+ int nBlock; /* Number of nAtom sized blocks in zPool */
+ u8 *zPool;
+} mem5;
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.nAtom]))
@@ -14213,10 +13349,10 @@ static void memsys5Link(int i, int iLogsize){
/*
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
** will already be held (obtained by code in malloc.c) if
-** sqlite3GlobalConfig.bMemStat is true.
+** sqlite3Config.bMemStat is true.
*/
static void memsys5Enter(void){
- if( sqlite3GlobalConfig.bMemstat==0 && mem5.mutex==0 ){
+ if( sqlite3Config.bMemstat==0 && mem5.mutex==0 ){
mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
sqlite3_mutex_enter(mem5.mutex);
@@ -14271,11 +13407,12 @@ static void *memsys5MallocUnsafe(int nByte){
/* Keep track of the maximum allocation request. Even unfulfilled
** requests are counted */
- if( (u32)nByte>mem5.maxRequest ){
+ if( nByte>mem5.maxRequest ){
mem5.maxRequest = nByte;
}
/* Round nByte up to the next valid power of two */
+ if( nByte>POW2_MAX ) return 0;
for(iFullSz=mem5.nAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}
/* Make sure mem5.aiFreelist[iLogsize] contains at least one free
@@ -14327,12 +13464,12 @@ static void memsys5FreeUnsafe(void *pOld){
iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
size = 1<<iLogsize;
- assert( iBlock+size-1<(u32)mem5.nBlock );
+ assert( iBlock+size-1<mem5.nBlock );
mem5.aCtrl[iBlock] |= CTRL_FREE;
mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
assert( mem5.currentCount>0 );
- assert( mem5.currentOut>=(size*mem5.nAtom) );
+ assert( mem5.currentOut>=0 );
mem5.currentCount--;
mem5.currentOut -= size*mem5.nAtom;
assert( mem5.currentOut>0 || mem5.currentCount==0 );
@@ -14437,20 +13574,18 @@ static int memsys5Log(int iValue){
*/
static int memsys5Init(void *NotUsed){
int ii;
- int nByte = sqlite3GlobalConfig.nHeap;
- u8 *zByte = (u8 *)sqlite3GlobalConfig.pHeap;
+ int nByte = sqlite3Config.nHeap;
+ u8 *zByte = (u8 *)sqlite3Config.pHeap;
int nMinLog; /* Log of minimum allocation size in bytes*/
int iOffset;
- UNUSED_PARAMETER(NotUsed);
-
if( !zByte ){
return SQLITE_ERROR;
}
- nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
+ nMinLog = memsys5Log(sqlite3Config.mnReq);
mem5.nAtom = (1<<nMinLog);
- while( (int)sizeof(Mem5Link)>mem5.nAtom ){
+ while( sizeof(Mem5Link)>mem5.nAtom ){
mem5.nAtom = mem5.nAtom << 1;
}
@@ -14480,7 +13615,6 @@ static int memsys5Init(void *NotUsed){
** Deinitialize this module.
*/
static void memsys5Shutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
return;
}
@@ -14524,8 +13658,6 @@ SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
}else{
fclose(out);
}
-#else
- UNUSED_PARAMETER(zFilename);
#endif
}
@@ -14551,6 +13683,504 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
#endif /* SQLITE_ENABLE_MEMSYS5 */
/************** End of mem5.c ************************************************/
+/************** Begin file mem6.c ********************************************/
+/*
+** 2008 July 24
+**
+** 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 an alternative memory allocation system for SQLite.
+** This system is implemented as a wrapper around the system provided
+** by the operating system - vanilla malloc(), realloc() and free().
+**
+** This system differentiates between requests for "small" allocations
+** (by default those of 128 bytes or less) and "large" allocations (all
+** others). The 256 byte threshhold is configurable at runtime.
+**
+** All requests for large allocations are passed through to the
+** default system.
+**
+** Requests for small allocations are met by allocating space within
+** one or more larger "chunks" of memory obtained from the default
+** memory allocation system. Chunks of memory are usually 64KB or
+** larger. The algorithm used to manage space within each chunk is
+** the same as that used by mem5.c.
+**
+** This strategy is designed to prevent the default memory allocation
+** system (usually the system malloc) from suffering from heap
+** fragmentation. On some systems, heap fragmentation can cause a
+** significant real-time slowdown.
+**
+** $Id$
+*/
+
+#ifdef SQLITE_ENABLE_MEMSYS6
+
+
+/*
+** Maximum size of any "small" allocation is ((1<<LOGMAX)*Mem6Chunk.nAtom).
+** Mem6Chunk.nAtom is always at least 8, so this is not a practical
+** limitation
+*/
+#define LOGMAX 30
+
+/*
+** Default value for the "small" allocation size threshold.
+*/
+#define SMALL_MALLOC_DEFAULT_THRESHOLD 256
+
+/*
+** Minimum size for a memory chunk.
+*/
+#define MIN_CHUNKSIZE (1<<16)
+
+#define LOG2_MINALLOC 4
+
+
+typedef struct Mem6Chunk Mem6Chunk;
+typedef struct Mem6Link Mem6Link;
+
+/*
+** A minimum allocation is an instance of the following structure.
+** Larger allocations are an array of these structures where the
+** size of the array is a power of 2.
+*/
+struct Mem6Link {
+ int next; /* Index of next free chunk */
+ int prev; /* Index of previous free chunk */
+};
+
+/*
+** Masks used for mem5.aCtrl[] elements.
+*/
+#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block relative to POW2_MIN */
+#define CTRL_FREE 0x20 /* True if not checked out */
+
+struct Mem6Chunk {
+ Mem6Chunk *pNext;
+
+ /*
+ ** Lists of free blocks of various sizes.
+ */
+ int aiFreelist[LOGMAX+1];
+
+ int nCheckedOut; /* Number of currently outstanding allocations */
+
+ /*
+ ** Space for tracking which blocks are checked out and the size
+ ** of each block. One byte per block.
+ */
+ u8 *aCtrl;
+
+ /*
+ ** Memory available for allocation
+ */
+ int nAtom; /* Smallest possible allocation in bytes */
+ int nBlock; /* Number of nAtom sized blocks in zPool */
+ u8 *zPool; /* Pointer to memory chunk from which allocations are made */
+};
+
+#define MEM6LINK(idx) ((Mem6Link *)(&pChunk->zPool[(idx)*pChunk->nAtom]))
+
+struct Mem6Global {
+ int nMinAlloc; /* Minimum allowed allocation size */
+ int nThreshold; /* Allocs larger than this go to malloc() */
+ int nLogThreshold; /* log2 of (nThreshold/nMinAlloc) */
+ sqlite3_mutex *mutex;
+ Mem6Chunk *pChunk; /* Singly linked list of all memory chunks */
+} mem6;
+
+/*
+** Unlink the chunk at pChunk->aPool[i] from list it is currently
+** on. It should be found on pChunk->aiFreelist[iLogsize].
+*/
+static void memsys6Unlink(Mem6Chunk *pChunk, int i, int iLogsize){
+ int next, prev;
+ assert( i>=0 && i<pChunk->nBlock );
+ assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold );
+ assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+
+ next = MEM6LINK(i)->next;
+ prev = MEM6LINK(i)->prev;
+ if( prev<0 ){
+ pChunk->aiFreelist[iLogsize] = next;
+ }else{
+ MEM6LINK(prev)->next = next;
+ }
+ if( next>=0 ){
+ MEM6LINK(next)->prev = prev;
+ }
+}
+
+/*
+** Link the chunk at mem5.aPool[i] so that is on the iLogsize
+** free list.
+*/
+static void memsys6Link(Mem6Chunk *pChunk, int i, int iLogsize){
+ int x;
+ assert( i>=0 && i<pChunk->nBlock );
+ assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold );
+ assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
+
+ x = MEM6LINK(i)->next = pChunk->aiFreelist[iLogsize];
+ MEM6LINK(i)->prev = -1;
+ if( x>=0 ){
+ assert( x<pChunk->nBlock );
+ MEM6LINK(x)->prev = i;
+ }
+ pChunk->aiFreelist[iLogsize] = i;
+}
+
+
+/*
+** Find the first entry on the freelist iLogsize. Unlink that
+** entry and return its index.
+*/
+static int memsys6UnlinkFirst(Mem6Chunk *pChunk, int iLogsize){
+ int i;
+ int iFirst;
+
+ assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold );
+ i = iFirst = pChunk->aiFreelist[iLogsize];
+ assert( iFirst>=0 );
+ memsys6Unlink(pChunk, iFirst, iLogsize);
+ return iFirst;
+}
+
+static int roundupLog2(int n){
+ static const char LogTable256[256] = {
+ 0, /* 1 */
+ 1, /* 2 */
+ 2, 2, /* 3..4 */
+ 3, 3, 3, 3, /* 5..8 */
+ 4, 4, 4, 4, 4, 4, 4, 4, /* 9..16 */
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* 17..32 */
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, /* 33..64 */
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* 65..128 */
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* 129..256 */
+ };
+
+ assert(n<=(1<<16) && n>0);
+ if( n<=256 ) return LogTable256[n-1];
+ return LogTable256[(n>>8) - ((n&0xFF)?0:1)] + 8;
+}
+
+/*
+** Allocate and return a block of (pChunk->nAtom << iLogsize) bytes from chunk
+** pChunk. If the allocation request cannot be satisfied, return 0.
+*/
+static void *chunkMalloc(Mem6Chunk *pChunk, int iLogsize){
+ int i; /* Index of a mem5.aPool[] slot */
+ int iBin; /* Index into mem5.aiFreelist[] */
+
+ /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
+ ** block. If not, then split a block of the next larger power of
+ ** two in order to create a new free block of size iLogsize.
+ */
+ for(iBin=iLogsize; pChunk->aiFreelist[iBin]<0 && iBin<=mem6.nLogThreshold; iBin++){}
+ if( iBin>mem6.nLogThreshold ) return 0;
+ i = memsys6UnlinkFirst(pChunk, iBin);
+ while( iBin>iLogsize ){
+ int newSize;
+ iBin--;
+ newSize = 1 << iBin;
+ pChunk->aCtrl[i+newSize] = CTRL_FREE | iBin;
+ memsys6Link(pChunk, i+newSize, iBin);
+ }
+ pChunk->aCtrl[i] = iLogsize;
+
+ /* Return a pointer to the allocated memory. */
+ pChunk->nCheckedOut++;
+ return (void*)&pChunk->zPool[i*pChunk->nAtom];
+}
+
+/*
+** Free the allocation pointed to by p, which is guaranteed to be non-zero
+** and a part of chunk object pChunk.
+*/
+static void chunkFree(Mem6Chunk *pChunk, void *pOld){
+ u32 size, iLogsize;
+ int iBlock;
+
+ /* Set iBlock to the index of the block pointed to by pOld in
+ ** the array of pChunk->nAtom byte blocks pointed to by pChunk->zPool.
+ */
+ iBlock = ((u8 *)pOld-pChunk->zPool)/pChunk->nAtom;
+
+ /* Check that the pointer pOld points to a valid, non-free block. */
+ assert( iBlock>=0 && iBlock<pChunk->nBlock );
+ assert( ((u8 *)pOld-pChunk->zPool)%pChunk->nAtom==0 );
+ assert( (pChunk->aCtrl[iBlock] & CTRL_FREE)==0 );
+
+ iLogsize = pChunk->aCtrl[iBlock] & CTRL_LOGSIZE;
+ size = 1<<iLogsize;
+ assert( iBlock+size-1<pChunk->nBlock );
+
+ pChunk->aCtrl[iBlock] |= CTRL_FREE;
+ pChunk->aCtrl[iBlock+size-1] |= CTRL_FREE;
+
+ pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize;
+ while( iLogsize<mem6.nLogThreshold ){
+ int iBuddy;
+ if( (iBlock>>iLogsize) & 1 ){
+ iBuddy = iBlock - size;
+ }else{
+ iBuddy = iBlock + size;
+ }
+ assert( iBuddy>=0 );
+ if( (iBuddy+(1<<iLogsize))>pChunk->nBlock ) break;
+ if( pChunk->aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
+ memsys6Unlink(pChunk, iBuddy, iLogsize);
+ iLogsize++;
+ if( iBuddy<iBlock ){
+ pChunk->aCtrl[iBuddy] = CTRL_FREE | iLogsize;
+ pChunk->aCtrl[iBlock] = 0;
+ iBlock = iBuddy;
+ }else{
+ pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize;
+ pChunk->aCtrl[iBuddy] = 0;
+ }
+ size *= 2;
+ }
+ pChunk->nCheckedOut--;
+ memsys6Link(pChunk, iBlock, iLogsize);
+}
+
+/*
+** Return the actual size of the block pointed to by p, which is guaranteed
+** to have been allocated from chunk pChunk.
+*/
+static int chunkSize(Mem6Chunk *pChunk, void *p){
+ int iSize = 0;
+ if( p ){
+ int i = ((u8 *)p-pChunk->zPool)/pChunk->nAtom;
+ assert( i>=0 && i<pChunk->nBlock );
+ iSize = pChunk->nAtom * (1 << (pChunk->aCtrl[i]&CTRL_LOGSIZE));
+ }
+ return iSize;
+}
+
+/*
+** Return true if there are currently no outstanding allocations.
+*/
+static int chunkIsEmpty(Mem6Chunk *pChunk){
+ return (pChunk->nCheckedOut==0);
+}
+
+/*
+** Initialize the buffer zChunk, which is nChunk bytes in size, as
+** an Mem6Chunk object. Return a copy of the zChunk pointer.
+*/
+static Mem6Chunk *chunkInit(u8 *zChunk, int nChunk, int nMinAlloc){
+ int ii;
+ int iOffset;
+ Mem6Chunk *pChunk = (Mem6Chunk *)zChunk;
+
+ assert( nChunk>sizeof(Mem6Chunk) );
+ assert( nMinAlloc>sizeof(Mem6Link) );
+
+ memset(pChunk, 0, sizeof(Mem6Chunk));
+ pChunk->nAtom = nMinAlloc;
+ pChunk->nBlock = ((nChunk-sizeof(Mem6Chunk)) / (pChunk->nAtom+sizeof(u8)));
+
+ pChunk->zPool = (u8 *)&pChunk[1];
+ pChunk->aCtrl = &pChunk->zPool[pChunk->nBlock*pChunk->nAtom];
+
+ for(ii=0; ii<=mem6.nLogThreshold; ii++){
+ pChunk->aiFreelist[ii] = -1;
+ }
+
+ iOffset = 0;
+ for(ii=mem6.nLogThreshold; ii>=0; ii--){
+ int nAlloc = (1<<ii);
+ while( (iOffset+nAlloc)<=pChunk->nBlock ){
+ pChunk->aCtrl[iOffset] = ii | CTRL_FREE;
+ memsys6Link(pChunk, iOffset, ii);
+ iOffset += nAlloc;
+ }
+ }
+
+ return pChunk;
+}
+
+
+static void mem6Enter(void){
+ sqlite3_mutex_enter(mem6.mutex);
+}
+
+static void mem6Leave(void){
+ sqlite3_mutex_leave(mem6.mutex);
+}
+
+/*
+** Based on the number and size of the currently allocated chunks, return
+** the size of the next chunk to allocate, in bytes.
+*/
+static int nextChunkSize(void){
+ int iTotal = MIN_CHUNKSIZE;
+ Mem6Chunk *p;
+ for(p=mem6.pChunk; p; p=p->pNext){
+ iTotal = iTotal*2;
+ }
+ return iTotal;
+}
+
+static void freeChunk(Mem6Chunk *pChunk){
+ Mem6Chunk **pp = &mem6.pChunk;
+ for( pp=&mem6.pChunk; *pp!=pChunk; pp = &(*pp)->pNext );
+ *pp = (*pp)->pNext;
+ free(pChunk);
+}
+
+static void *memsys6Malloc(int nByte){
+ Mem6Chunk *pChunk;
+ void *p = 0;
+ int nTotal = nByte+8;
+ int iOffset = 0;
+
+ if( nTotal>mem6.nThreshold ){
+ p = malloc(nTotal);
+ }else{
+ int iLogsize = 0;
+ if( nTotal>(1<<LOG2_MINALLOC) ){
+ iLogsize = roundupLog2(nTotal) - LOG2_MINALLOC;
+ }
+ mem6Enter();
+ for(pChunk=mem6.pChunk; pChunk; pChunk=pChunk->pNext){
+ p = chunkMalloc(pChunk, iLogsize);
+ if( p ){
+ break;
+ }
+ }
+ if( !p ){
+ int iSize = nextChunkSize();
+ p = malloc(iSize);
+ if( p ){
+ pChunk = chunkInit((u8 *)p, iSize, mem6.nMinAlloc);
+ pChunk->pNext = mem6.pChunk;
+ mem6.pChunk = pChunk;
+ p = chunkMalloc(pChunk, iLogsize);
+ assert(p);
+ }
+ }
+ iOffset = ((u8*)p - (u8*)pChunk);
+ mem6Leave();
+ }
+
+ if( !p ){
+ return 0;
+ }
+ ((u32 *)p)[0] = iOffset;
+ ((u32 *)p)[1] = nByte;
+ return &((u32 *)p)[2];
+}
+
+static int memsys6Size(void *pPrior){
+ if( pPrior==0 ) return 0;
+ return ((u32*)pPrior)[-1];
+}
+
+static void memsys6Free(void *pPrior){
+ int iSlot;
+ void *p = &((u32 *)pPrior)[-2];
+ iSlot = ((u32 *)p)[0];
+ if( iSlot ){
+ Mem6Chunk *pChunk;
+ mem6Enter();
+ pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]);
+ chunkFree(pChunk, p);
+ if( chunkIsEmpty(pChunk) ){
+ freeChunk(pChunk);
+ }
+ mem6Leave();
+ }else{
+ free(p);
+ }
+}
+
+static void *memsys6Realloc(void *p, int nByte){
+ void *p2;
+
+ if( p && nByte<=memsys6Size(p) ){
+ p2 = p;
+ }else{
+ p2 = memsys6Malloc(nByte);
+ if( p && p2 ){
+ memcpy(p2, p, memsys6Size(p));
+ memsys6Free(p);
+ }
+ }
+
+ return p2;
+}
+
+static int memsys6Roundup(int n){
+ if( n>mem6.nThreshold ){
+ return n;
+ }else{
+ return (1<<roundupLog2(n));
+ }
+}
+
+static int memsys6Init(void *pCtx){
+ u8 bMemstat = sqlite3Config.bMemstat;
+ mem6.nMinAlloc = (1 << LOG2_MINALLOC);
+ mem6.pChunk = 0;
+ mem6.nThreshold = sqlite3Config.nSmall;
+ if( mem6.nThreshold<=0 ){
+ mem6.nThreshold = SMALL_MALLOC_DEFAULT_THRESHOLD;
+ }
+ mem6.nLogThreshold = roundupLog2(mem6.nThreshold) - LOG2_MINALLOC;
+ if( !bMemstat ){
+ mem6.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
+ }
+ return SQLITE_OK;
+}
+
+static void memsys6Shutdown(void *pCtx){
+ memset(&mem6, 0, sizeof(mem6));
+}
+
+/*
+** This routine is the only routine in this file with external
+** linkage. It returns a pointer to a static sqlite3_mem_methods
+** struct populated with the memsys6 methods.
+*/
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys6(void){
+ static const sqlite3_mem_methods memsys6Methods = {
+ memsys6Malloc,
+ memsys6Free,
+ memsys6Realloc,
+ memsys6Size,
+ memsys6Roundup,
+ memsys6Init,
+ memsys6Shutdown,
+ 0
+ };
+ return &memsys6Methods;
+}
+
+#endif
+
+/************** End of mem6.c ************************************************/
/************** Begin file mutex.c *******************************************/
/*
** 2007 August 14
@@ -14565,29 +14195,34 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
*************************************************************************
** This file contains the C functions that implement mutexes.
**
-** This file contains code that is common across all mutex implementations.
-
+** The implementation in this file does not provide any mutual
+** exclusion and is thus suitable for use only in applications
+** that use SQLite in a single thread. But this implementation
+** does do a lot of error checking on mutexes to make sure they
+** are called correctly and at appropriate times. Hence, this
+** implementation is suitable for testing.
+** debugging purposes
**
** $Id$
*/
-#ifndef SQLITE_MUTEX_OMIT
+#ifndef SQLITE_MUTEX_NOOP
/*
** Initialize the mutex system.
*/
SQLITE_PRIVATE int sqlite3MutexInit(void){
int rc = SQLITE_OK;
- if( sqlite3GlobalConfig.bCoreMutex ){
- if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
+ if( sqlite3Config.bCoreMutex ){
+ if( !sqlite3Config.mutex.xMutexAlloc ){
/* If the xMutexAlloc method has not been set, then the user did not
** install a mutex implementation via sqlite3_config() prior to
** sqlite3_initialize() being called. This block copies pointers to
- ** the default implementation into the sqlite3GlobalConfig structure.
+ ** the default implementation into the sqlite3Config structure.
**
** The danger is that although sqlite3_config() is not a threadsafe
** API, sqlite3_initialize() is, and so multiple threads may be
** attempting to run this function simultaneously. To guard write
- ** access to the sqlite3GlobalConfig structure, the 'MASTER' static mutex
+ ** access to the sqlite3Config structure, the 'MASTER' static mutex
** is obtained before modifying it.
*/
sqlite3_mutex_methods *p = sqlite3DefaultMutex();
@@ -14598,16 +14233,16 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){
pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
assert(pMaster);
p->xMutexEnter(pMaster);
- assert( sqlite3GlobalConfig.mutex.xMutexAlloc==0
- || sqlite3GlobalConfig.mutex.xMutexAlloc==p->xMutexAlloc
+ assert( sqlite3Config.mutex.xMutexAlloc==0
+ || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc
);
- if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
- sqlite3GlobalConfig.mutex = *p;
+ if( !sqlite3Config.mutex.xMutexAlloc ){
+ sqlite3Config.mutex = *p;
}
p->xMutexLeave(pMaster);
}
}else{
- rc = sqlite3GlobalConfig.mutex.xMutexInit();
+ rc = sqlite3Config.mutex.xMutexInit();
}
}
@@ -14620,7 +14255,7 @@ SQLITE_PRIVATE int sqlite3MutexInit(void){
*/
SQLITE_PRIVATE int sqlite3MutexEnd(void){
int rc = SQLITE_OK;
- rc = sqlite3GlobalConfig.mutex.xMutexEnd();
+ rc = sqlite3Config.mutex.xMutexEnd();
return rc;
}
@@ -14631,14 +14266,14 @@ SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
- return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
+ return sqlite3Config.mutex.xMutexAlloc(id);
}
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
- if( !sqlite3GlobalConfig.bCoreMutex ){
+ if( !sqlite3Config.bCoreMutex ){
return 0;
}
- return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
+ return sqlite3Config.mutex.xMutexAlloc(id);
}
/*
@@ -14646,7 +14281,7 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
*/
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
if( p ){
- sqlite3GlobalConfig.mutex.xMutexFree(p);
+ sqlite3Config.mutex.xMutexFree(p);
}
}
@@ -14656,7 +14291,7 @@ SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
*/
SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
if( p ){
- sqlite3GlobalConfig.mutex.xMutexEnter(p);
+ sqlite3Config.mutex.xMutexEnter(p);
}
}
@@ -14667,7 +14302,7 @@ SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
int rc = SQLITE_OK;
if( p ){
- return sqlite3GlobalConfig.mutex.xMutexTry(p);
+ return sqlite3Config.mutex.xMutexTry(p);
}
return rc;
}
@@ -14680,7 +14315,7 @@ SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
*/
SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
if( p ){
- sqlite3GlobalConfig.mutex.xMutexLeave(p);
+ sqlite3Config.mutex.xMutexLeave(p);
}
}
@@ -14690,87 +14325,20 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
** intended for use inside assert() statements.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
- return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
+ return p==0 || sqlite3Config.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
- return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
+ return p==0 || sqlite3Config.mutex.xMutexNotheld(p);
}
#endif
-#endif /* SQLITE_OMIT_MUTEX */
-
-/************** End of mutex.c ***********************************************/
-/************** Begin file mutex_noop.c **************************************/
-/*
-** 2008 October 07
-**
-** 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 the C functions that implement mutexes.
-**
-** This implementation in this file does not provide any mutual
-** exclusion and is thus suitable for use only in applications
-** that use SQLite in a single thread. The routines defined
-** here are place-holders. Applications can substitute working
-** mutex routines at start-time using the
-**
-** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
-**
-** interface.
-**
-** If compiled with SQLITE_DEBUG, then additional logic is inserted
-** that does error checking on mutexes to make sure they are being
-** called correctly.
-**
-** $Id$
-*/
-
-
-#if defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG)
-/*
-** Stub routines for all mutex methods.
-**
-** This routines provide no mutual exclusion or error checking.
-*/
-static int noopMutexHeld(sqlite3_mutex *p){ return 1; }
-static int noopMutexNotheld(sqlite3_mutex *p){ return 1; }
-static int noopMutexInit(void){ return SQLITE_OK; }
-static int noopMutexEnd(void){ return SQLITE_OK; }
-static sqlite3_mutex *noopMutexAlloc(int id){ return (sqlite3_mutex*)8; }
-static void noopMutexFree(sqlite3_mutex *p){ return; }
-static void noopMutexEnter(sqlite3_mutex *p){ return; }
-static int noopMutexTry(sqlite3_mutex *p){ return SQLITE_OK; }
-static void noopMutexLeave(sqlite3_mutex *p){ return; }
-
-SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
- static sqlite3_mutex_methods sMutex = {
- noopMutexInit,
- noopMutexEnd,
- noopMutexAlloc,
- noopMutexFree,
- noopMutexEnter,
- noopMutexTry,
- noopMutexLeave,
-
- noopMutexHeld,
- noopMutexNotheld
- };
-
- return &sMutex;
-}
-#endif /* defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG) */
+#endif
-#if defined(SQLITE_MUTEX_NOOP) && defined(SQLITE_DEBUG)
+#ifdef SQLITE_MUTEX_NOOP_DEBUG
/*
-** In this implementation, error checking is provided for testing
-** and debugging purposes. The mutexes still do not provide any
-** mutual exclusion.
+** In this implementation, mutexes do not provide any mutual exclusion.
+** But the error checking is provided. This implementation is useful
+** for test purposes.
*/
/*
@@ -14785,25 +14353,25 @@ struct sqlite3_mutex {
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
*/
-static int debugMutexHeld(sqlite3_mutex *p){
+static int noopMutexHeld(sqlite3_mutex *p){
return p==0 || p->cnt>0;
}
-static int debugMutexNotheld(sqlite3_mutex *p){
+static int noopMutexNotheld(sqlite3_mutex *p){
return p==0 || p->cnt==0;
}
/*
** Initialize and deinitialize the mutex subsystem.
*/
-static int debugMutexInit(void){ return SQLITE_OK; }
-static int debugMutexEnd(void){ return SQLITE_OK; }
+static int noopMutexInit(void){ return SQLITE_OK; }
+static int noopMutexEnd(void){ return SQLITE_OK; }
/*
** The sqlite3_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. If it returns NULL
** that means that a mutex could not be allocated.
*/
-static sqlite3_mutex *debugMutexAlloc(int id){
+static sqlite3_mutex *noopMutexAlloc(int id){
static sqlite3_mutex aStatic[6];
sqlite3_mutex *pNew = 0;
switch( id ){
@@ -14830,7 +14398,7 @@ static sqlite3_mutex *debugMutexAlloc(int id){
/*
** This routine deallocates a previously allocated mutex.
*/
-static void debugMutexFree(sqlite3_mutex *p){
+static void noopMutexFree(sqlite3_mutex *p){
assert( p->cnt==0 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
sqlite3_free(p);
@@ -14847,12 +14415,12 @@ static void debugMutexFree(sqlite3_mutex *p){
** can enter. If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
-static void debugMutexEnter(sqlite3_mutex *p){
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) );
+static void noopMutexEnter(sqlite3_mutex *p){
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) );
p->cnt++;
}
-static int debugMutexTry(sqlite3_mutex *p){
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) );
+static int noopMutexTry(sqlite3_mutex *p){
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) );
p->cnt++;
return SQLITE_OK;
}
@@ -14863,31 +14431,31 @@ static int debugMutexTry(sqlite3_mutex *p){
** is undefined if the mutex is not currently entered or
** is not currently allocated. SQLite will never do either.
*/
-static void debugMutexLeave(sqlite3_mutex *p){
- assert( debugMutexHeld(p) );
+static void noopMutexLeave(sqlite3_mutex *p){
+ assert( noopMutexHeld(p) );
p->cnt--;
- assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) );
+ assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) );
}
SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
static sqlite3_mutex_methods sMutex = {
- debugMutexInit,
- debugMutexEnd,
- debugMutexAlloc,
- debugMutexFree,
- debugMutexEnter,
- debugMutexTry,
- debugMutexLeave,
-
- debugMutexHeld,
- debugMutexNotheld
+ noopMutexInit,
+ noopMutexEnd,
+ noopMutexAlloc,
+ noopMutexFree,
+ noopMutexEnter,
+ noopMutexTry,
+ noopMutexLeave,
+
+ noopMutexHeld,
+ noopMutexNotheld
};
return &sMutex;
}
-#endif /* defined(SQLITE_MUTEX_NOOP) && defined(SQLITE_DEBUG) */
+#endif /* SQLITE_MUTEX_NOOP_DEBUG */
-/************** End of mutex_noop.c ******************************************/
+/************** End of mutex.c ***********************************************/
/************** Begin file mutex_os2.c ***************************************/
/*
** 2007 August 28
@@ -15226,7 +14794,7 @@ struct sqlite3_mutex {
** make sure no assert() statements are evaluated and hence these
** routines are never called.
*/
-#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
+#ifndef NDEBUG
static int pthreadMutexHeld(sqlite3_mutex *p){
return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
}
@@ -15322,7 +14890,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
}
default: {
assert( iType-2 >= 0 );
- assert( iType-2 < ArraySize(staticMutexes) );
+ assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
p = &staticMutexes[iType-2];
p->id = iType;
break;
@@ -15533,14 +15101,7 @@ struct sqlite3_mutex {
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
-**
-** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
-** which is only available if your application was compiled with
-** _WIN32_WINNT defined to a value >= 0x0400. Currently, the only
-** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef
-** this out as well.
*/
-#if 0
#if SQLITE_OS_WINCE
# define mutexIsNT() (1)
#else
@@ -15555,7 +15116,7 @@ struct sqlite3_mutex {
return osType==2;
}
#endif /* SQLITE_OS_WINCE */
-#endif
+
#ifdef SQLITE_DEBUG
/*
@@ -15768,10 +15329,9 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
*/
static void softHeapLimitEnforcer(
void *NotUsed,
- sqlite3_int64 NotUsed2,
+ sqlite3_int64 inUse,
int allocSize
){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_release_memory(allocSize);
}
@@ -15789,9 +15349,9 @@ SQLITE_API void sqlite3_soft_heap_limit(int n){
}
sqlite3_initialize();
if( iLimit>0 ){
- sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, iLimit);
+ sqlite3_memory_alarm(softHeapLimitEnforcer, 0, iLimit);
}else{
- sqlite3MemoryAlarm(0, 0, 0);
+ sqlite3_memory_alarm(0, 0, 0);
}
overage = sqlite3_memory_used() - n;
if( overage>0 ){
@@ -15806,14 +15366,10 @@ SQLITE_API void sqlite3_soft_heap_limit(int n){
*/
SQLITE_API int sqlite3_release_memory(int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- int nRet = 0;
-#if 0
- nRet += sqlite3VdbeReleaseMemory(n);
-#endif
- nRet += sqlite3PcacheReleaseMemory(n-nRet);
+ int nRet = sqlite3VdbeReleaseMemory(n);
+ nRet += sqlite3PagerReleaseMemory(n-nRet);
return nRet;
#else
- UNUSED_PARAMETER(n);
return SQLITE_OK;
#endif
}
@@ -15821,11 +15377,7 @@ SQLITE_API int sqlite3_release_memory(int n){
/*
** State information local to the memory allocation subsystem.
*/
-static SQLITE_WSD struct Mem0Global {
- /* Number of free pages for scratch and page-cache memory */
- u32 nScratchFree;
- u32 nPageFree;
-
+static struct {
sqlite3_mutex *mutex; /* Mutex to serialize access */
/*
@@ -15841,63 +15393,65 @@ static SQLITE_WSD struct Mem0Global {
int alarmBusy;
/*
- ** Pointers to the end of sqlite3GlobalConfig.pScratch and
- ** sqlite3GlobalConfig.pPage to a block of memory that records
+ ** Pointers to the end of sqlite3Config.pScratch and
+ ** sqlite3Config.pPage to a block of memory that records
** which pages are available.
*/
u32 *aScratchFree;
u32 *aPageFree;
-} mem0 = { 62560955, 0, 0, 0, 0, 0, 0, 0, 0 };
-#define mem0 GLOBAL(struct Mem0Global, mem0)
+ /* Number of free pages for scratch and page-cache memory */
+ u32 nScratchFree;
+ u32 nPageFree;
+} mem0;
/*
** Initialize the memory allocation subsystem.
*/
SQLITE_PRIVATE int sqlite3MallocInit(void){
- if( sqlite3GlobalConfig.m.xMalloc==0 ){
+ if( sqlite3Config.m.xMalloc==0 ){
sqlite3MemSetDefault();
}
memset(&mem0, 0, sizeof(mem0));
- if( sqlite3GlobalConfig.bCoreMutex ){
+ if( sqlite3Config.bCoreMutex ){
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
- if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
- && sqlite3GlobalConfig.nScratch>=0 ){
+ if( sqlite3Config.pScratch && sqlite3Config.szScratch>=100
+ && sqlite3Config.nScratch>=0 ){
int i;
- sqlite3GlobalConfig.szScratch -= 4;
- mem0.aScratchFree = (u32*)&((char*)sqlite3GlobalConfig.pScratch)
- [sqlite3GlobalConfig.szScratch*sqlite3GlobalConfig.nScratch];
- for(i=0; i<sqlite3GlobalConfig.nScratch; i++){ mem0.aScratchFree[i] = i; }
- mem0.nScratchFree = sqlite3GlobalConfig.nScratch;
+ sqlite3Config.szScratch -= 4;
+ mem0.aScratchFree = (u32*)&((char*)sqlite3Config.pScratch)
+ [sqlite3Config.szScratch*sqlite3Config.nScratch];
+ for(i=0; i<sqlite3Config.nScratch; i++){ mem0.aScratchFree[i] = i; }
+ mem0.nScratchFree = sqlite3Config.nScratch;
}else{
- sqlite3GlobalConfig.pScratch = 0;
- sqlite3GlobalConfig.szScratch = 0;
+ sqlite3Config.pScratch = 0;
+ sqlite3Config.szScratch = 0;
}
- if( sqlite3GlobalConfig.pPage && sqlite3GlobalConfig.szPage>=512
- && sqlite3GlobalConfig.nPage>=1 ){
+ if( sqlite3Config.pPage && sqlite3Config.szPage>=512
+ && sqlite3Config.nPage>=1 ){
int i;
int overhead;
- int sz = sqlite3GlobalConfig.szPage;
- int n = sqlite3GlobalConfig.nPage;
+ int sz = sqlite3Config.szPage;
+ int n = sqlite3Config.nPage;
overhead = (4*n + sz - 1)/sz;
- sqlite3GlobalConfig.nPage -= overhead;
- mem0.aPageFree = (u32*)&((char*)sqlite3GlobalConfig.pPage)
- [sqlite3GlobalConfig.szPage*sqlite3GlobalConfig.nPage];
- for(i=0; i<sqlite3GlobalConfig.nPage; i++){ mem0.aPageFree[i] = i; }
- mem0.nPageFree = sqlite3GlobalConfig.nPage;
+ sqlite3Config.nPage -= overhead;
+ mem0.aPageFree = (u32*)&((char*)sqlite3Config.pPage)
+ [sqlite3Config.szPage*sqlite3Config.nPage];
+ for(i=0; i<sqlite3Config.nPage; i++){ mem0.aPageFree[i] = i; }
+ mem0.nPageFree = sqlite3Config.nPage;
}else{
- sqlite3GlobalConfig.pPage = 0;
- sqlite3GlobalConfig.szPage = 0;
+ sqlite3Config.pPage = 0;
+ sqlite3Config.szPage = 0;
}
- return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
+ return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
}
/*
** Deinitialize the memory allocation subsystem.
*/
SQLITE_PRIVATE void sqlite3MallocEnd(void){
- sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
+ sqlite3Config.m.xShutdown(sqlite3Config.m.pAppData);
memset(&mem0, 0, sizeof(mem0));
}
@@ -15928,7 +15482,7 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
/*
** Change the alarm callback
*/
-SQLITE_PRIVATE int sqlite3MemoryAlarm(
+SQLITE_API int sqlite3_memory_alarm(
void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
void *pArg,
sqlite3_int64 iThreshold
@@ -15941,20 +15495,6 @@ SQLITE_PRIVATE int sqlite3MemoryAlarm(
return SQLITE_OK;
}
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** Deprecated external interface. Internal/core SQLite code
-** should call sqlite3MemoryAlarm.
-*/
-SQLITE_API int sqlite3_memory_alarm(
- void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
- void *pArg,
- sqlite3_int64 iThreshold
-){
- return sqlite3MemoryAlarm(xCallback, pArg, iThreshold);
-}
-#endif
-
/*
** Trigger the alarm
*/
@@ -15981,7 +15521,7 @@ static int mallocWithAlarm(int n, void **pp){
int nFull;
void *p;
assert( sqlite3_mutex_held(mem0.mutex) );
- nFull = sqlite3GlobalConfig.m.xRoundup(n);
+ nFull = sqlite3Config.m.xRoundup(n);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmCallback!=0 ){
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
@@ -15989,10 +15529,10 @@ static int mallocWithAlarm(int n, void **pp){
sqlite3MallocAlarm(nFull);
}
}
- p = sqlite3GlobalConfig.m.xMalloc(nFull);
+ p = sqlite3Config.m.xMalloc(nFull);
if( p==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nFull);
- p = sqlite3GlobalConfig.m.xMalloc(nFull);
+ p = sqlite3Config.m.xMalloc(nFull);
}
if( p ){
nFull = sqlite3MallocSize(p);
@@ -16010,12 +15550,12 @@ SQLITE_PRIVATE void *sqlite3Malloc(int n){
void *p;
if( n<=0 ){
p = 0;
- }else if( sqlite3GlobalConfig.bMemstat ){
+ }else if( sqlite3Config.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
mallocWithAlarm(n, &p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3GlobalConfig.m.xMalloc(n);
+ p = sqlite3Config.m.xMalloc(n);
}
return p;
}
@@ -16063,7 +15603,7 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
assert( scratchAllocOut==0 );
#endif
- if( sqlite3GlobalConfig.szScratch<n ){
+ if( sqlite3Config.szScratch<n ){
goto scratch_overflow;
}else{
sqlite3_mutex_enter(mem0.mutex);
@@ -16073,11 +15613,11 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
}else{
int i;
i = mem0.aScratchFree[--mem0.nScratchFree];
- i *= sqlite3GlobalConfig.szScratch;
+ sqlite3_mutex_leave(mem0.mutex);
+ i *= sqlite3Config.szScratch;
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
- sqlite3_mutex_leave(mem0.mutex);
- p = (void*)&((char*)sqlite3GlobalConfig.pScratch)[i];
+ p = (void*)&((char*)sqlite3Config.pScratch)[i];
}
}
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
@@ -16087,14 +15627,14 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
return p;
scratch_overflow:
- if( sqlite3GlobalConfig.bMemstat ){
+ if( sqlite3Config.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
n = mallocWithAlarm(n, &p);
if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3GlobalConfig.m.xMalloc(n);
+ p = sqlite3Config.m.xMalloc(n);
}
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
scratchAllocOut = p!=0;
@@ -16113,26 +15653,26 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
scratchAllocOut = 0;
#endif
- if( sqlite3GlobalConfig.pScratch==0
- || p<sqlite3GlobalConfig.pScratch
+ if( sqlite3Config.pScratch==0
+ || p<sqlite3Config.pScratch
|| p>=(void*)mem0.aScratchFree ){
- if( sqlite3GlobalConfig.bMemstat ){
+ if( sqlite3Config.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
- sqlite3GlobalConfig.m.xFree(p);
+ sqlite3Config.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3GlobalConfig.m.xFree(p);
+ sqlite3Config.m.xFree(p);
}
}else{
int i;
- i = (u8 *)p - (u8 *)sqlite3GlobalConfig.pScratch;
- i /= sqlite3GlobalConfig.szScratch;
- assert( i>=0 && i<sqlite3GlobalConfig.nScratch );
+ i = (u8 *)p - (u8 *)sqlite3Config.pScratch;
+ i /= sqlite3Config.szScratch;
+ assert( i>=0 && i<sqlite3Config.nScratch );
sqlite3_mutex_enter(mem0.mutex);
- assert( mem0.nScratchFree<(u32)sqlite3GlobalConfig.nScratch );
+ assert( mem0.nScratchFree<sqlite3Config.nScratch );
mem0.aScratchFree[mem0.nScratchFree++] = i;
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
sqlite3_mutex_leave(mem0.mutex);
@@ -16146,14 +15686,13 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
** and that memory is of the right size and is not completely
** consumed. Otherwise, failover to sqlite3Malloc().
*/
-#if 0
SQLITE_PRIVATE void *sqlite3PageMalloc(int n){
void *p;
assert( n>0 );
assert( (n & (n-1))==0 );
assert( n>=512 && n<=32768 );
- if( sqlite3GlobalConfig.szPage<n ){
+ if( sqlite3Config.szPage<n ){
goto page_overflow;
}else{
sqlite3_mutex_enter(mem0.mutex);
@@ -16164,57 +15703,57 @@ SQLITE_PRIVATE void *sqlite3PageMalloc(int n){
int i;
i = mem0.aPageFree[--mem0.nPageFree];
sqlite3_mutex_leave(mem0.mutex);
- i *= sqlite3GlobalConfig.szPage;
+ i *= sqlite3Config.szPage;
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, n);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
- p = (void*)&((char*)sqlite3GlobalConfig.pPage)[i];
+ p = (void*)&((char*)sqlite3Config.pPage)[i];
}
}
return p;
page_overflow:
- if( sqlite3GlobalConfig.bMemstat ){
+ if( sqlite3Config.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, n);
n = mallocWithAlarm(n, &p);
if( p ) sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, n);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3GlobalConfig.m.xMalloc(n);
+ p = sqlite3Config.m.xMalloc(n);
}
return p;
}
SQLITE_PRIVATE void sqlite3PageFree(void *p){
if( p ){
- if( sqlite3GlobalConfig.pPage==0
- || p<sqlite3GlobalConfig.pPage
+ if( sqlite3Config.pPage==0
+ || p<sqlite3Config.pPage
|| p>=(void*)mem0.aPageFree ){
/* In this case, the page allocation was obtained from a regular
** call to sqlite3_mem_methods.xMalloc() (a page-cache-memory
** "overflow"). Free the block with sqlite3_mem_methods.xFree().
*/
- if( sqlite3GlobalConfig.bMemstat ){
+ if( sqlite3Config.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
- sqlite3GlobalConfig.m.xFree(p);
+ sqlite3Config.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3GlobalConfig.m.xFree(p);
+ sqlite3Config.m.xFree(p);
}
}else{
- /* The page allocation was allocated from the sqlite3GlobalConfig.pPage
+ /* The page allocation was allocated from the sqlite3Config.pPage
** buffer. In this case all that is add the index of the page in
- ** the sqlite3GlobalConfig.pPage array to the set of free indexes stored
+ ** the sqlite3Config.pPage array to the set of free indexes stored
** in the mem0.aPageFree[] array.
*/
int i;
- i = (u8 *)p - (u8 *)sqlite3GlobalConfig.pPage;
- i /= sqlite3GlobalConfig.szPage;
- assert( i>=0 && i<sqlite3GlobalConfig.nPage );
+ i = (u8 *)p - (u8 *)sqlite3Config.pPage;
+ i /= sqlite3Config.szPage;
+ assert( i>=0 && i<sqlite3Config.nPage );
sqlite3_mutex_enter(mem0.mutex);
- assert( mem0.nPageFree<sqlite3GlobalConfig.nPage );
+ assert( mem0.nPageFree<sqlite3Config.nPage );
mem0.aPageFree[mem0.nPageFree++] = i;
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
sqlite3_mutex_leave(mem0.mutex);
@@ -16227,31 +15766,26 @@ SQLITE_PRIVATE void sqlite3PageFree(void *p){
}
}
}
-#endif
/*
** TRUE if p is a lookaside memory allocation from db
*/
-#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, void *p){
return db && p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
}
-#else
-#define isLookaside(A,B) 0
-#endif
/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
SQLITE_PRIVATE int sqlite3MallocSize(void *p){
- return sqlite3GlobalConfig.m.xSize(p);
+ return sqlite3Config.m.xSize(p);
}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
- return sqlite3GlobalConfig.m.xSize(p);
+ return sqlite3Config.m.xSize(p);
}
}
@@ -16260,13 +15794,13 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
*/
SQLITE_API void sqlite3_free(void *p){
if( p==0 ) return;
- if( sqlite3GlobalConfig.bMemstat ){
+ if( sqlite3Config.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
- sqlite3GlobalConfig.m.xFree(p);
+ sqlite3Config.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3GlobalConfig.m.xFree(p);
+ sqlite3Config.m.xFree(p);
}
}
@@ -16299,10 +15833,10 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
return 0;
}
nOld = sqlite3MallocSize(pOld);
- if( sqlite3GlobalConfig.bMemstat ){
+ if( sqlite3Config.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
- nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
+ nNew = sqlite3Config.m.xRoundup(nBytes);
if( nOld==nNew ){
pNew = pOld;
}else{
@@ -16310,10 +15844,10 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
mem0.alarmThreshold ){
sqlite3MallocAlarm(nNew-nOld);
}
- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
+ pNew = sqlite3Config.m.xRealloc(pOld, nNew);
if( pNew==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nBytes);
- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
+ pNew = sqlite3Config.m.xRealloc(pOld, nNew);
}
if( pNew ){
nNew = sqlite3MallocSize(pNew);
@@ -16322,7 +15856,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, int nBytes){
}
sqlite3_mutex_leave(mem0.mutex);
}else{
- pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nBytes);
+ pNew = sqlite3Config.m.xRealloc(pOld, nBytes);
}
return pNew;
}
@@ -16365,24 +15899,9 @@ SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, int n){
/*
** Allocate and zero memory. If the allocation fails, make
** the mallocFailed flag in the connection pointer.
-**
-** If db!=0 and db->mallocFailed is true (indicating a prior malloc
-** failure on the same database connection) then always return 0.
-** Hence for a particular database connection, once malloc starts
-** failing, it fails consistently until mallocFailed is reset.
-** This is an important assumption. There are many places in the
-** code that do things like this:
-**
-** int *a = (int*)sqlite3DbMallocRaw(db, 100);
-** int *b = (int*)sqlite3DbMallocRaw(db, 200);
-** if( b ) a[10] = 9;
-**
-** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
-** that all prior mallocs (ex: "a") worked too.
*/
SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){
void *p;
-#ifndef SQLITE_OMIT_LOOKASIDE
if( db ){
LookasideSlot *pBuf;
if( db->mallocFailed ){
@@ -16398,11 +15917,6 @@ SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, int n){
return (void*)pBuf;
}
}
-#else
- if( db && db->mallocFailed ){
- return 0;
- }
-#endif
p = sqlite3Malloc(n);
if( !p && db ){
db->mallocFailed = 1;
@@ -16523,7 +16037,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
** is unsafe, as is the call to sqlite3Error().
*/
assert( !db || sqlite3_mutex_held(db->mutex) );
- if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){
+ if( db && db->mallocFailed ){
sqlite3Error(db, SQLITE_NOMEM, 0);
db->mallocFailed = 0;
rc = SQLITE_NOMEM;
@@ -16671,6 +16185,7 @@ static const et_info fmtinfo[] = {
{ 'S', 0, 2, etSRCLIST, 0, 0 },
{ 'r', 10, 3, etORDINAL, 0, 0 },
};
+#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
/*
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
@@ -16707,7 +16222,7 @@ static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
*/
static void appendSpace(StrAccum *pAccum, int N){
static const char zSpaces[] = " ";
- while( N>=(int)sizeof(zSpaces)-1 ){
+ while( N>=sizeof(zSpaces)-1 ){
sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
N -= sizeof(zSpaces)-1;
}
@@ -16779,6 +16294,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
+ etByte errorflag = 0; /* True if an error is encountered */
etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -16802,6 +16318,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( c==0 ) break;
}
if( (c=(*++fmt))==0 ){
+ errorflag = 1;
sqlite3StrAccumAppend(pAccum, "%", 1);
break;
}
@@ -16870,7 +16387,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}
/* Fetch the info entry for the field */
infop = 0;
- for(idx=0; idx<ArraySize(fmtinfo); idx++){
+ for(idx=0; idx<etNINFO; idx++){
if( c==fmtinfo[idx].fmttype ){
infop = &fmtinfo[idx];
if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
@@ -17179,10 +16696,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = sqlite3Malloc( n );
- if( bufpt==0 ){
- pAccum->mallocFailed = 1;
- return;
- }
+ if( bufpt==0 ) return;
}else{
bufpt = buf;
}
@@ -17493,11 +17007,11 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
/* All threads share a single random number generator.
** This structure is the current state of the generator.
*/
-static SQLITE_WSD struct sqlite3PrngType {
+static struct sqlite3PrngType {
unsigned char isInit; /* True if initialized */
unsigned char i, j; /* State variables */
unsigned char s[256]; /* State variables */
-} sqlite3Prng = { 0, };
+} sqlite3Prng;
/*
** Get a single 8-bit random value from the RC4 PRNG. The Mutex
@@ -17519,20 +17033,6 @@ static int randomByte(void){
unsigned char t;
- /* The "wsdPrng" macro will resolve to the pseudo-random number generator
- ** state vector. If writable static data is unsupported on the target,
- ** we have to locate the state vector at run-time. In the more common
- ** case where writable static data is supported, wsdPrng can refer directly
- ** to the "sqlite3Prng" state vector declared above.
- */
-#ifdef SQLITE_OMIT_WSD
- struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
-# define wsdPrng p[0]
-#else
-# define wsdPrng sqlite3Prng
-#endif
-
-
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
@@ -17542,33 +17042,33 @@ static int randomByte(void){
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device.
*/
- if( !wsdPrng.isInit ){
+ if( !sqlite3Prng.isInit ){
int i;
char k[256];
- wsdPrng.j = 0;
- wsdPrng.i = 0;
+ sqlite3Prng.j = 0;
+ sqlite3Prng.i = 0;
sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
for(i=0; i<256; i++){
- wsdPrng.s[i] = i;
+ sqlite3Prng.s[i] = i;
}
for(i=0; i<256; i++){
- wsdPrng.j += wsdPrng.s[i] + k[i];
- t = wsdPrng.s[wsdPrng.j];
- wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
- wsdPrng.s[i] = t;
+ sqlite3Prng.j += sqlite3Prng.s[i] + k[i];
+ t = sqlite3Prng.s[sqlite3Prng.j];
+ sqlite3Prng.s[sqlite3Prng.j] = sqlite3Prng.s[i];
+ sqlite3Prng.s[i] = t;
}
- wsdPrng.isInit = 1;
+ sqlite3Prng.isInit = 1;
}
/* Generate and return single random byte
*/
- wsdPrng.i++;
- t = wsdPrng.s[wsdPrng.i];
- wsdPrng.j += t;
- wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
- wsdPrng.s[wsdPrng.j] = t;
- t += wsdPrng.s[wsdPrng.i];
- return wsdPrng.s[t];
+ sqlite3Prng.i++;
+ t = sqlite3Prng.s[sqlite3Prng.i];
+ sqlite3Prng.j += t;
+ sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j];
+ sqlite3Prng.s[sqlite3Prng.j] = t;
+ t += sqlite3Prng.s[sqlite3Prng.i];
+ return sqlite3Prng.s[t];
}
/*
@@ -17576,7 +17076,7 @@ static int randomByte(void){
*/
SQLITE_API void sqlite3_randomness(int N, void *pBuf){
unsigned char *zBuf = pBuf;
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
#endif
sqlite3_mutex_enter(mutex);
@@ -17589,30 +17089,19 @@ SQLITE_API void sqlite3_randomness(int N, void *pBuf){
#ifndef SQLITE_OMIT_BUILTIN_TEST
/*
** For testing purposes, we sometimes want to preserve the state of
-** PRNG and restore the PRNG to its saved state at a later time, or
-** to reset the PRNG to its initial state. These routines accomplish
-** those tasks.
-**
+** PRNG and restore the PRNG to its saved state at a later time.
** The sqlite3_test_control() interface calls these routines to
** control the PRNG.
*/
-static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng = { 0, };
+static struct sqlite3PrngType sqlite3SavedPrng;
SQLITE_PRIVATE void sqlite3PrngSaveState(void){
- memcpy(
- &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
- &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
- sizeof(sqlite3Prng)
- );
+ memcpy(&sqlite3SavedPrng, &sqlite3Prng, sizeof(sqlite3Prng));
}
SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
- memcpy(
- &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
- &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
- sizeof(sqlite3Prng)
- );
+ memcpy(&sqlite3Prng, &sqlite3SavedPrng, sizeof(sqlite3Prng));
}
SQLITE_PRIVATE void sqlite3PrngResetState(void){
- GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
+ sqlite3Prng.isInit = 0;
}
#endif /* SQLITE_OMIT_BUILTIN_TEST */
@@ -17709,12 +17198,12 @@ typedef unsigned char Bool;
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
**
-** If the VdbeCursor.isTriggerRow flag is set it means that this cursor is
+** If the Cursor.isTriggerRow flag is set it means that this cursor is
** really a single row that represents the NEW or OLD pseudo-table of
-** a row trigger. The data for the row is stored in VdbeCursor.pData and
-** the rowid is in VdbeCursor.iKey.
+** a row trigger. The data for the row is stored in Cursor.pData and
+** the rowid is in Cursor.iKey.
*/
-struct VdbeCursor {
+struct Cursor {
BtCursor *pCursor; /* The cursor structure of the backend */
int iDb; /* Index of cursor database in db->aDb[] (or -1) */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
@@ -17730,11 +17219,13 @@ struct VdbeCursor {
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
+ u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
Btree *pBt; /* Separate file holding temporary table */
int nData; /* Number of bytes in pData */
char *pData; /* Data for a NEW or OLD pseudo-table */
i64 iKey; /* Key for the NEW or OLD pseudo-table row */
+ u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int nField; /* Number of fields in the header */
i64 seqCount; /* Sequence counter */
@@ -17752,10 +17243,10 @@ struct VdbeCursor {
u32 *aOffset; /* Cached offsets to the start of each columns data */
u8 *aRow; /* Data for the current row, if all on one page */
};
-typedef struct VdbeCursor VdbeCursor;
+typedef struct Cursor Cursor;
/*
-** A value for VdbeCursor.cacheValid that means the cache is always invalid.
+** A value for Cursor.cacheValid that means the cache is always invalid.
*/
#define CACHE_STALE 0
@@ -17950,16 +17441,16 @@ struct Vdbe {
Mem **apArg; /* Arguments to currently executing user function */
Mem *aColName; /* Column names to return */
int nCursor; /* Number of slots in apCsr[] */
- VdbeCursor **apCsr; /* One element of this array for each open cursor */
+ Cursor **apCsr; /* One element of this array for each open cursor */
int nVar; /* Number of entries in aVar[] */
Mem *aVar; /* Values for the OP_Variable opcode. */
char **azVar; /* Name of variables */
int okVar; /* True if azVar[] has been initialized */
- u32 magic; /* Magic number for sanity checking */
+ int magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
int nCallback; /* Number of callbacks invoked so far */
- int cacheCtr; /* VdbeCursor row cache generation counter */
+ int cacheCtr; /* Cursor row cache generation counter */
Fifo sFifo; /* A list of ROWIDs */
int contextStackTop; /* Index of top element in the context stack */
int contextStackDepth; /* The size of the "context" stack */
@@ -17978,17 +17469,14 @@ struct Vdbe {
u8 expired; /* True if the VM needs to be recompiled */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 inVtabMethod; /* See comments above */
- u8 usesStmtJournal; /* True if uses a statement journal */
- u8 readOnly; /* True for read-only statements */
int nChange; /* Number of db changes made since last reset */
i64 startTime; /* Time when query started - used for profiling */
int btreeMask; /* Bitmask of db->aDb[] entries referenced */
BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
- int aCounter[2]; /* Counters used by sqlite3_stmt_status() */
int nSql; /* Number of bytes in zSql */
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_DEBUG
- FILE *trace; /* Write an execution trace here, if not NULL */
+ FILE *trace; /* Write an execution trace here, if not NULL */
#endif
int openedStatement; /* True if this VM has opened a statement journal */
#ifdef SQLITE_SSE
@@ -18002,6 +17490,28 @@ struct Vdbe {
};
/*
+** An instance of the following structure holds information about a
+** single index record that has already been parsed out into individual
+** values.
+**
+** A record is an object that contains one or more fields of data.
+** Records are used to store the content of a table row and to store
+** the key of an index. A blob encoding of a record is created by
+** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
+** OP_Column opcode.
+**
+** This structure holds a record that has already been disassembled
+** into its constitutent fields.
+*/
+struct UnpackedRecord {
+ KeyInfo *pKeyInfo; /* Collation and sort-order information */
+ u16 nField; /* Number of entries in apMem[] */
+ u8 needFree; /* True if memory obtained from sqlite3_malloc() */
+ u8 needDestroy; /* True if apMem[]s should be destroyed on close */
+ Mem *aMem; /* Values */
+};
+
+/*
** The following are allowed values for Vdbe.magic
*/
#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
@@ -18012,9 +17522,9 @@ struct Vdbe {
/*
** Function prototypes
*/
-SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
+SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, Cursor*);
void sqliteVdbePopStack(Vdbe*,int);
-SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*);
+SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(Cursor*);
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
@@ -18025,9 +17535,10 @@ SQLITE_PRIVATE int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
-SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
+SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8*, int, int*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -18273,7 +17784,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
return SQLITE_NOMEM;
}
zIn = (u8*)pMem->z;
- zTerm = &zIn[pMem->n&~1];
+ zTerm = &zIn[pMem->n];
while( zIn<zTerm ){
temp = *zIn;
*zIn = *(zIn+1);
@@ -18291,7 +17802,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
** A single byte is required for the output string
** nul-terminator.
*/
- pMem->n &= ~1;
len = pMem->n * 2 + 1;
}else{
/* When converting from UTF-8 to UTF-16 the maximum growth is caused
@@ -18452,7 +17962,7 @@ SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
unsigned char *zOut = zIn;
unsigned char *zStart = zIn;
- unsigned char *zTerm = &zIn[strlen((char *)zIn)];
+ unsigned char *zTerm;
u32 c;
while( zIn[0] ){
@@ -18529,7 +18039,7 @@ SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
** It checks that the primitives for serializing and deserializing
** characters in each encoding are inverses of each other.
*/
-SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
+SQLITE_PRIVATE void sqlite3UtfSelfTest(){
unsigned int i, t;
unsigned char zBuf[20];
unsigned char *z;
@@ -18635,7 +18145,7 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){
SQLITE_PRIVATE int sqlite3Strlen(sqlite3 *db, const char *z){
const char *z2 = z;
int len;
- int x;
+ size_t x;
while( *z2 ){ z2++; }
x = z2 - z;
len = 0x7fffffff & x;
@@ -19512,7 +19022,7 @@ SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3 *db){
** used as an argument to sqlite3_errmsg() or sqlite3_close().
*/
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
- u32 magic;
+ int magic;
if( db==0 ) return 0;
magic = db->magic;
if( magic!=SQLITE_MAGIC_OPEN &&
@@ -19520,7 +19030,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
return 1;
}
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
- u32 magic;
+ int magic;
if( db==0 ) return 0;
magic = db->magic;
if( magic!=SQLITE_MAGIC_SICK &&
@@ -19552,12 +19062,22 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
-** "copyKey" is true if the hash table should make its own private
-** copy of keys and false if it should just use the supplied pointer.
+** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
+** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass
+** determines what kind of key the hash table will use. "copyKey" is
+** true if the hash table should make its own private copy of keys and
+** false if it should just use the supplied pointer. CopyKey only makes
+** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
+** for other key classes.
*/
-SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew, int copyKey){
+SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
assert( pNew!=0 );
- pNew->copyKey = copyKey!=0;
+ assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY );
+ pNew->keyClass = keyClass;
+#if 0
+ if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0;
+#endif
+ pNew->copyKey = copyKey;
pNew->first = 0;
pNew->count = 0;
pNew->htsize = 0;
@@ -19588,6 +19108,33 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
pH->count = 0;
}
+#if 0 /* NOT USED */
+/*
+** Hash and comparison functions when the mode is SQLITE_HASH_INT
+*/
+static int intHash(const void *pKey, int nKey){
+ return nKey ^ (nKey<<8) ^ (nKey>>8);
+}
+static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
+ return n2 - n1;
+}
+#endif
+
+#if 0 /* NOT USED */
+/*
+** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
+*/
+static int ptrHash(const void *pKey, int nKey){
+ uptr x = Addr(pKey);
+ return x ^ (x<<8) ^ (x>>8);
+}
+static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
+ if( pKey1==pKey2 ) return 0;
+ if( pKey1<pKey2 ) return -1;
+ return 1;
+}
+#endif
+
/*
** Hash and comparison functions when the mode is SQLITE_HASH_STRING
*/
@@ -19606,6 +19153,79 @@ static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
}
+/*
+** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
+*/
+static int binHash(const void *pKey, int nKey){
+ int h = 0;
+ const char *z = (const char *)pKey;
+ while( nKey-- > 0 ){
+ h = (h<<3) ^ h ^ *(z++);
+ }
+ return h & 0x7fffffff;
+}
+static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
+ if( n1!=n2 ) return 1;
+ return memcmp(pKey1,pKey2,n1);
+}
+
+/*
+** Return a pointer to the appropriate hash function given the key class.
+**
+** The C syntax in this function definition may be unfamilar to some
+** programmers, so we provide the following additional explanation:
+**
+** The name of the function is "hashFunction". The function takes a
+** single parameter "keyClass". The return value of hashFunction()
+** is a pointer to another function. Specifically, the return value
+** of hashFunction() is a pointer to a function that takes two parameters
+** with types "const void*" and "int" and returns an "int".
+*/
+static int (*hashFunction(int keyClass))(const void*,int){
+#if 0 /* HASH_INT and HASH_POINTER are never used */
+ switch( keyClass ){
+ case SQLITE_HASH_INT: return &intHash;
+ case SQLITE_HASH_POINTER: return &ptrHash;
+ case SQLITE_HASH_STRING: return &strHash;
+ case SQLITE_HASH_BINARY: return &binHash;;
+ default: break;
+ }
+ return 0;
+#else
+ if( keyClass==SQLITE_HASH_STRING ){
+ return &strHash;
+ }else{
+ assert( keyClass==SQLITE_HASH_BINARY );
+ return &binHash;
+ }
+#endif
+}
+
+/*
+** Return a pointer to the appropriate hash function given the key class.
+**
+** For help in interpreted the obscure C code in the function definition,
+** see the header comment on the previous function.
+*/
+static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
+#if 0 /* HASH_INT and HASH_POINTER are never used */
+ switch( keyClass ){
+ case SQLITE_HASH_INT: return &intCompare;
+ case SQLITE_HASH_POINTER: return &ptrCompare;
+ case SQLITE_HASH_STRING: return &strCompare;
+ case SQLITE_HASH_BINARY: return &binCompare;
+ default: break;
+ }
+ return 0;
+#else
+ if( keyClass==SQLITE_HASH_STRING ){
+ return &strCompare;
+ }else{
+ assert( keyClass==SQLITE_HASH_BINARY );
+ return &binCompare;
+ }
+#endif
+}
/* Link an element into the hash table
*/
@@ -19640,6 +19260,7 @@ static void insertElement(
static void rehash(Hash *pH, int new_size){
struct _ht *new_ht; /* The new hash table */
HashElem *elem, *next_elem; /* For looping over existing elements */
+ int (*xHash)(const void*,int); /* The hash function */
#ifdef SQLITE_MALLOC_SOFT_LIMIT
if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
@@ -19661,8 +19282,9 @@ static void rehash(Hash *pH, int new_size){
sqlite3_free(pH->ht);
pH->ht = new_ht;
pH->htsize = new_size;
+ xHash = hashFunction(pH->keyClass);
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
- int h = strHash(elem->pKey, elem->nKey) & (new_size-1);
+ int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
next_elem = elem->next;
insertElement(pH, &new_ht[h], elem);
}
@@ -19680,13 +19302,15 @@ static HashElem *findElementGivenHash(
){
HashElem *elem; /* Used to loop thru the element list */
int count; /* Number of elements left to test */
+ int (*xCompare)(const void*,int,const void*,int); /* comparison function */
if( pH->ht ){
struct _ht *pEntry = &pH->ht[h];
elem = pEntry->chain;
count = pEntry->count;
+ xCompare = compareFunction(pH->keyClass);
while( count-- && elem ){
- if( strCompare(elem->pKey,elem->nKey,pKey,nKey)==0 ){
+ if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
@@ -19740,9 +19364,12 @@ static void removeElementGivenHash(
SQLITE_PRIVATE HashElem *sqlite3HashFindElem(const Hash *pH, const void *pKey, int nKey){
int h; /* A hash on key */
HashElem *elem; /* The element that matches key */
+ int (*xHash)(const void*,int); /* The hash function */
if( pH==0 || pH->ht==0 ) return 0;
- h = strHash(pKey,nKey);
+ xHash = hashFunction(pH->keyClass);
+ assert( xHash!=0 );
+ h = (*xHash)(pKey,nKey);
elem = findElementGivenHash(pH,pKey,nKey, h % pH->htsize);
return elem;
}
@@ -19777,9 +19404,12 @@ SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, voi
int h; /* the hash of the key modulo hash table size */
HashElem *elem; /* Used to loop thru the element list */
HashElem *new_elem; /* New element added to the pH */
+ int (*xHash)(const void*,int); /* The hash function */
assert( pH!=0 );
- hraw = strHash(pKey, nKey);
+ xHash = hashFunction(pH->keyClass);
+ assert( xHash!=0 );
+ hraw = (*xHash)(pKey, nKey);
if( pH->htsize ){
h = hraw % pH->htsize;
elem = findElementGivenHash(pH,pKey,nKey,h);
@@ -19964,8 +19594,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 122 */ "VUpdate",
/* 123 */ "IfZero",
/* 124 */ "VCreate",
- /* 125 */ "Found",
- /* 126 */ "Real",
+ /* 125 */ "Real",
+ /* 126 */ "Found",
/* 127 */ "IfPos",
/* 128 */ "NullRow",
/* 129 */ "Jump",
@@ -19977,12 +19607,11 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 135 */ "NotUsed_135",
/* 136 */ "NotUsed_136",
/* 137 */ "NotUsed_137",
- /* 138 */ "NotUsed_138",
- /* 139 */ "ToText",
- /* 140 */ "ToBlob",
- /* 141 */ "ToNumeric",
- /* 142 */ "ToInt",
- /* 143 */ "ToReal",
+ /* 138 */ "ToText",
+ /* 139 */ "ToBlob",
+ /* 140 */ "ToNumeric",
+ /* 141 */ "ToInt",
+ /* 142 */ "ToReal",
};
return azName[i];
}
@@ -20347,7 +19976,6 @@ static int os2Read(
if( got == (ULONG)amt )
return SQLITE_OK;
else {
- /* Unread portions of the input buffer must be zero-filled */
memset(&((char*)pBuf)[got], 0, amt-got);
return SQLITE_IOERR_SHORT_READ;
}
@@ -20395,7 +20023,7 @@ static int os2Truncate( sqlite3_file *id, i64 nByte ){
OSTRACE3( "TRUNCATE %d %lld\n", pFile->h, nByte );
SimulateIOError( return SQLITE_IOERR_TRUNCATE );
rc = DosSetFileSize( pFile->h, nByte );
- return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_TRUNCATE;
+ return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
}
#ifdef SQLITE_TEST
@@ -20419,14 +20047,7 @@ static int os2Sync( sqlite3_file *id, int flags ){
}
sqlite3_sync_count++;
#endif
- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
- ** no-op
- */
-#ifdef SQLITE_NO_SYNC
- return SQLITE_OK;
-#else
return DosResetBuffer( pFile->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
-#endif
}
/*
@@ -20437,13 +20058,13 @@ static int os2FileSize( sqlite3_file *id, sqlite3_int64 *pSize ){
FILESTATUS3 fsts3FileInfo;
memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo));
assert( id!=0 );
- SimulateIOError( return SQLITE_IOERR_FSTAT );
+ SimulateIOError( return SQLITE_IOERR );
rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) );
if( rc == NO_ERROR ){
*pSize = fsts3FileInfo.cbFile;
return SQLITE_OK;
}else{
- return SQLITE_IOERR_FSTAT;
+ return SQLITE_IOERR;
}
}
@@ -20977,7 +20598,7 @@ static int os2Open(
int *pOutFlags /* Status return flags */
){
HFILE h;
- ULONG ulFileAttribute = FILE_NORMAL;
+ ULONG ulFileAttribute = 0;
ULONG ulOpenFlags = 0;
ULONG ulOpenMode = 0;
os2File *pFile = (os2File*)id;
@@ -21002,6 +20623,7 @@ static int os2Open(
OSTRACE2( "OPEN want %d\n", flags );
+ /*ulOpenMode = flags & SQLITE_OPEN_READWRITE ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY;*/
if( flags & SQLITE_OPEN_READWRITE ){
ulOpenMode |= OPEN_ACCESS_READWRITE;
OSTRACE1( "OPEN read/write\n" );
@@ -21010,6 +20632,7 @@ static int os2Open(
OSTRACE1( "OPEN read only\n" );
}
+ /*ulOpenFlags = flags & SQLITE_OPEN_CREATE ? OPEN_ACTION_CREATE_IF_NEW : OPEN_ACTION_FAIL_IF_NEW;*/
if( flags & SQLITE_OPEN_CREATE ){
ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
OSTRACE1( "OPEN open new/create\n" );
@@ -21018,6 +20641,7 @@ static int os2Open(
OSTRACE1( "OPEN open existing\n" );
}
+ /*ulOpenMode |= flags & SQLITE_OPEN_MAIN_DB ? OPEN_SHARE_DENYNONE : OPEN_SHARE_DENYWRITE;*/
if( flags & SQLITE_OPEN_MAIN_DB ){
ulOpenMode |= OPEN_SHARE_DENYNONE;
OSTRACE1( "OPEN share read/write\n" );
@@ -21026,15 +20650,18 @@ static int os2Open(
OSTRACE1( "OPEN share read only\n" );
}
- if( flags & SQLITE_OPEN_DELETEONCLOSE ){
+ if( flags & (SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TEMP_JOURNAL
+ | SQLITE_OPEN_SUBJOURNAL) ){
char pathUtf8[CCHMAXPATH];
#ifdef NDEBUG /* when debugging we want to make sure it is deleted */
ulFileAttribute = FILE_HIDDEN;
#endif
+ ulFileAttribute = FILE_NORMAL;
os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
OSTRACE1( "OPEN hidden/delete on close file attributes\n" );
}else{
+ ulFileAttribute = FILE_ARCHIVED | FILE_NORMAL;
pFile->pathToDel = NULL;
OSTRACE1( "OPEN normal file attribute\n" );
}
@@ -21095,7 +20722,7 @@ static int os2Delete(
rc = DosDelete( (PSZ)zFilenameCp );
free( zFilenameCp );
OSTRACE2( "DELETE \"%s\"\n", zFilename );
- return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_DELETE;
+ return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
}
/*
@@ -21364,36 +20991,16 @@ SQLITE_API int sqlite3_os_end(void){
#if SQLITE_OS_UNIX /* This file is used on unix only */
/*
-** If SQLITE_ENABLE_LOCKING_STYLE is defined and is non-zero, then several
-** alternative locking implementations are provided:
+** If SQLITE_ENABLE_LOCKING_STYLE is defined, then several different
+** locking implementations are provided:
**
** * POSIX locking (the default),
** * No locking,
** * Dot-file locking,
** * flock() locking,
-** * AFP locking (OSX only),
-** * Named POSIX semaphores (VXWorks only).
-**
-** SQLITE_ENABLE_LOCKING_STYLE only works on a Mac. It is turned on by
-** default on a Mac and disabled on all other posix platforms.
-*/
-#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
-# if defined(__DARWIN__)
-# define SQLITE_ENABLE_LOCKING_STYLE 1
-# else
-# define SQLITE_ENABLE_LOCKING_STYLE 0
-# endif
-#endif
-
-/*
-** Define the IS_VXWORKS pre-processor macro to 1 if building on
-** vxworks, or 0 otherwise.
+** * AFP locking (OSX only).
*/
-#if defined(__RTP__) || defined(_WRS_KERNEL)
-# define IS_VXWORKS 1
-#else
-# define IS_VXWORKS 0
-#endif
+/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */
/*
** These #defines should enable >2GB file support on Posix if the
@@ -21426,16 +21033,10 @@ SQLITE_API int sqlite3_os_end(void){
#include <sys/time.h>
#include <errno.h>
-#if SQLITE_ENABLE_LOCKING_STYLE
-# include <sys/ioctl.h>
-# if IS_VXWORKS
-# define lstat stat
-# include <semaphore.h>
-# include <limits.h>
-# else
-# include <sys/param.h>
-# include <sys/mount.h>
-# endif
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/mount.h>
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
/*
@@ -21474,7 +21075,7 @@ struct unixFile {
#endif
struct openCnt *pOpen; /* Info about all open fd's on this inode */
struct lockInfo *pLock; /* Info about locks on this inode */
-#if SQLITE_ENABLE_LOCKING_STYLE
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
void *lockingContext; /* Locking style specific state */
#endif
int h; /* The file descriptor */
@@ -21483,11 +21084,6 @@ struct unixFile {
#if SQLITE_THREADSAFE
pthread_t tid; /* The thread that "owns" this unixFile */
#endif
- int lastErrno; /* The unix errno from the last I/O error */
-#if IS_VXWORKS
- int isDelete; /* Delete on close if true */
- char *zRealpath;
-#endif
};
/*
@@ -21898,11 +21494,7 @@ SQLITE_API int sqlite3_open_file_count = 0;
*/
struct lockKey {
dev_t dev; /* Device number */
-#if IS_VXWORKS
- void *rnam; /* Realname since inode unusable */
-#else
ino_t ino; /* Inode number */
-#endif
#if SQLITE_THREADSAFE
pthread_t tid; /* Thread ID or zero if threads can override each other */
#endif
@@ -21932,11 +21524,7 @@ struct lockInfo {
*/
struct openKey {
dev_t dev; /* Device number */
-#if IS_VXWORKS
- void *rnam; /* Realname since inode unusable */
-#else
ino_t ino; /* Inode number */
-#endif
};
/*
@@ -21952,10 +21540,6 @@ struct openCnt {
int nLock; /* Number of outstanding locks */
int nPending; /* Number of pending close() operations */
int *aPending; /* Malloced space holding fd's awaiting a close() */
-#if IS_VXWORKS
- sem_t *pSem; /* Named POSIX semaphore */
- char aSemName[MAX_PATHNAME+1]; /* Name of that semaphore */
-#endif
struct openCnt *pNext, *pPrev; /* List of all openCnt objects */
};
@@ -21968,18 +21552,6 @@ struct openCnt {
static struct lockInfo *lockList = 0;
static struct openCnt *openList = 0;
-#if IS_VXWORKS
-/*
-** This hash table is used to bind the canonical file name to a
-** unixFile structure and use the hash key (= canonical name)
-** instead of the Inode number of the file to find the matching
-** lockInfo and openCnt structures. It also helps to make the
-** name of the semaphore when LOCKING_STYLE_NAMEDSEM is used
-** for the file.
-*/
-static Hash nameHash;
-#endif
-
/*
** The locking styles are associated with the different file locking
** capabilities supported by different file systems.
@@ -21992,8 +21564,6 @@ static Hash nameHash;
** can be used on file systems that do not offer any reliable file locking
** NO locking means that no locking will be attempted, this is only used for
** read-only file systems currently
-** NAMEDSEM is similar to DOTLOCK but uses a named semaphore instead of an
-** indicator file.
** UNSUPPORTED means that no locking will be attempted, this is only used for
** file systems that are known to be unsupported
*/
@@ -22002,21 +21572,14 @@ static Hash nameHash;
#define LOCKING_STYLE_DOTFILE 3
#define LOCKING_STYLE_FLOCK 4
#define LOCKING_STYLE_AFP 5
-#define LOCKING_STYLE_NAMEDSEM 6
-
-/*
-** Only set the lastErrno if the error code is a real error and not
-** a normal expected return code of SQLITE_BUSY or SQLITE_OK
-*/
-#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
/*
** Helper functions to obtain and relinquish the global mutex.
*/
-static void enterMutex(void){
+static void enterMutex(){
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
-static void leaveMutex(void){
+static void leaveMutex(){
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
@@ -22117,19 +21680,16 @@ static int lockTrace(int fd, int op, struct flock *p){
#define fcntl lockTrace
#endif /* SQLITE_LOCK_TRACE */
-#ifdef __linux__
/*
-** This function is used as the main routine for a thread launched by
-** testThreadLockingBehavior(). It tests whether the shared-lock obtained
-** by the main thread in testThreadLockingBehavior() conflicts with a
-** hypothetical write-lock obtained by this thread on the same file.
-**
-** The write-lock is not actually acquired, as this is not possible if
-** the file is open in read-only mode (see ticket #3472).
-*/
+** The testThreadLockingBehavior() routine launches two separate
+** threads on this routine. This routine attempts to lock a file
+** descriptor then returns. The success or failure of that attempt
+** allows the testThreadLockingBehavior() procedure to determine
+** whether or not threads can override each others locks.
+*/
static void *threadLockingTest(void *pArg){
struct threadTestData *pData = (struct threadTestData*)pArg;
- pData->result = fcntl(pData->fd, F_GETLK, &pData->lock);
+ pData->result = fcntl(pData->fd, F_SETLK, &pData->lock);
return pArg;
}
@@ -22140,39 +21700,26 @@ static void *threadLockingTest(void *pArg){
*/
static void testThreadLockingBehavior(int fd_orig){
int fd;
- int rc;
- struct threadTestData d;
- struct flock l;
- pthread_t t;
+ struct threadTestData d[2];
+ pthread_t t[2];
fd = dup(fd_orig);
if( fd<0 ) return;
- memset(&l, 0, sizeof(l));
- l.l_type = F_RDLCK;
- l.l_len = 1;
- l.l_start = 0;
- l.l_whence = SEEK_SET;
- rc = fcntl(fd_orig, F_SETLK, &l);
- if( rc!=0 ) return;
- memset(&d, 0, sizeof(d));
- d.fd = fd;
- d.lock = l;
- d.lock.l_type = F_WRLCK;
- pthread_create(&t, 0, threadLockingTest, &d);
- pthread_join(t, 0);
+ memset(d, 0, sizeof(d));
+ d[0].fd = fd;
+ d[0].lock.l_type = F_RDLCK;
+ d[0].lock.l_len = 1;
+ d[0].lock.l_start = 0;
+ d[0].lock.l_whence = SEEK_SET;
+ d[1] = d[0];
+ d[1].lock.l_type = F_WRLCK;
+ pthread_create(&t[0], 0, threadLockingTest, &d[0]);
+ pthread_create(&t[1], 0, threadLockingTest, &d[1]);
+ pthread_join(t[0], 0);
+ pthread_join(t[1], 0);
close(fd);
- if( d.result!=0 ) return;
- threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK);
+ threadsOverrideEachOthersLocks = d[0].result==0 && d[1].result==0;
}
-#else
-/*
-** On anything other than linux, assume threads override each others locks.
-*/
-static void testThreadLockingBehavior(int fd_orig){
- threadsOverrideEachOthersLocks = 1;
-}
-#endif /* __linux__ */
-
#endif /* SQLITE_THREADSAFE */
/*
@@ -22222,103 +21769,10 @@ static void releaseOpenCnt(struct openCnt *pOpen){
}
}
-#if IS_VXWORKS
-/*
-** Implementation of a realpath() like function for vxWorks
-** to determine canonical path name from given name. It does
-** not support symlinks. Neither does it handle volume prefixes.
-*/
-char *
-vxrealpath(const char *pathname, int dostat)
-{
- struct stat sbuf;
- int len;
- char *where, *ptr, *last;
- char *result, *curpath, *workpath, *namebuf;
-
- len = pathconf(pathname, _PC_PATH_MAX);
- if( len<0 ){
- len = PATH_MAX;
- }
- result = sqlite3_malloc(len * 4);
- if( !result ){
- return 0;
- }
- curpath = result + len;
- workpath = curpath + len;
- namebuf = workpath + len;
- strcpy(curpath, pathname);
- if( *pathname!='/' ){
- if( !getcwd(workpath, len) ){
- sqlite3_free(result);
- return 0;
- }
- }else{
- *workpath = '\0';
- }
- where = curpath;
- while( *where ){
- if( !strcmp(where, ".") ){
- where++;
- continue;
- }
- if( !strncmp(where, "./", 2) ){
- where += 2;
- continue;
- }
- if( !strncmp(where, "../", 3) ){
- where += 3;
- ptr = last = workpath;
- while( *ptr ){
- if( *ptr=='/' ){
- last = ptr;
- }
- ptr++;
- }
- *last = '\0';
- continue;
- }
- ptr = strchr(where, '/');
- if( !ptr ){
- ptr = where + strlen(where) - 1;
- }else{
- *ptr = '\0';
- }
- strcpy(namebuf, workpath);
- for( last = namebuf; *last; last++ ){
- continue;
- }
- if( *--last!='/' ){
- strcat(namebuf, "/");
- }
- strcat(namebuf, where);
- where = ++ptr;
- if( dostat ){
- if( stat(namebuf, &sbuf)==-1 ){
- sqlite3_free(result);
- return 0;
- }
- if( (sbuf.st_mode & S_IFDIR)==S_IFDIR ){
- strcpy(workpath, namebuf);
- continue;
- }
- if( *where ){
- sqlite3_free(result);
- return 0;
- }
- }
- strcpy(workpath, namebuf);
- }
- strcpy(result, workpath);
- return result;
-}
-#endif
-
-#if SQLITE_ENABLE_LOCKING_STYLE
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
/*
** Tests a byte-range locking query to see if byte range locks are
** supported, if not we fall back to dotlockLockingStyle.
-** On vxWorks we fall back to namedsemLockingStyle.
*/
static int testLockingStyle(int fd){
struct flock lockInfo;
@@ -22335,10 +21789,9 @@ static int testLockingStyle(int fd){
}
/* Testing for flock() can give false positives. So if if the above
- ** test fails, then we fall back to using dot-file style locking (or
- ** named-semaphore locking on vxworks).
- */
- return (IS_VXWORKS ? LOCKING_STYLE_NAMEDSEM : LOCKING_STYLE_DOTFILE);
+ ** test fails, then we fall back to using dot-file style locking.
+ */
+ return LOCKING_STYLE_DOTFILE;
}
#endif
@@ -22353,23 +21806,12 @@ static int testLockingStyle(int fd){
** If SQLITE_ENABLE_LOCKING_STYLE is not defined, this function always
** returns LOCKING_STYLE_POSIX.
*/
-#if SQLITE_ENABLE_LOCKING_STYLE
static int detectLockingStyle(
sqlite3_vfs *pVfs,
const char *filePath,
int fd
){
-#if IS_VXWORKS
- if( !filePath ){
- return LOCKING_STYLE_NONE;
- }
- if( pVfs->pAppData ){
- return SQLITE_PTR_TO_INT(pVfs->pAppData);
- }
- if (access(filePath, 0) != -1){
- return testLockingStyle(fd);
- }
-#else
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
struct Mapping {
const char *zFilesystem;
int eLockingStyle;
@@ -22377,11 +21819,7 @@ static int detectLockingStyle(
{ "hfs", LOCKING_STYLE_POSIX },
{ "ufs", LOCKING_STYLE_POSIX },
{ "afpfs", LOCKING_STYLE_AFP },
-#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
- { "smbfs", LOCKING_STYLE_AFP },
-#else
{ "smbfs", LOCKING_STYLE_FLOCK },
-#endif
{ "msdos", LOCKING_STYLE_DOTFILE },
{ "webdav", LOCKING_STYLE_NONE },
{ 0, 0 }
@@ -22393,7 +21831,7 @@ static int detectLockingStyle(
return LOCKING_STYLE_NONE;
}
if( pVfs->pAppData ){
- return SQLITE_PTR_TO_INT(pVfs->pAppData);
+ return (int)pVfs->pAppData;
}
if( statfs(filePath, &fsInfo) != -1 ){
@@ -22409,12 +21847,9 @@ static int detectLockingStyle(
/* Default case. Handles, amongst others, "nfs". */
return testLockingStyle(fd);
-#endif /* if IS_VXWORKS */
+#endif
return LOCKING_STYLE_POSIX;
}
-#else
- #define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX
-#endif /* ifdef SQLITE_ENABLE_LOCKING_STYLE */
/*
** Given a file descriptor, locate lockInfo and openCnt structures that
@@ -22425,9 +21860,6 @@ static int detectLockingStyle(
*/
static int findLockInfo(
int fd, /* The file descriptor used in the key */
-#if IS_VXWORKS
- void *rnam, /* vxWorks realname */
-#endif
struct lockInfo **ppLock, /* Return the lockInfo structure here */
struct openCnt **ppOpen /* Return the openCnt structure here */
){
@@ -22465,11 +21897,7 @@ static int findLockInfo(
memset(&key1, 0, sizeof(key1));
key1.dev = statbuf.st_dev;
-#if IS_VXWORKS
- key1.rnam = rnam;
-#else
key1.ino = statbuf.st_ino;
-#endif
#if SQLITE_THREADSAFE
if( threadsOverrideEachOthersLocks<0 ){
testThreadLockingBehavior(fd);
@@ -22478,11 +21906,7 @@ static int findLockInfo(
#endif
memset(&key2, 0, sizeof(key2));
key2.dev = statbuf.st_dev;
-#if IS_VXWORKS
- key2.rnam = rnam;
-#else
key2.ino = statbuf.st_ino;
-#endif
pLock = lockList;
while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){
pLock = pLock->pNext;
@@ -22526,10 +21950,6 @@ static int findLockInfo(
pOpen->pPrev = 0;
if( openList ) openList->pPrev = pOpen;
openList = pOpen;
-#if IS_VXWORKS
- pOpen->pSem = NULL;
- pOpen->aSemName[0] = '\0';
-#endif
}else{
pOpen->nRef++;
}
@@ -22594,11 +22014,7 @@ static int transferOwnership(unixFile *pFile){
pFile->tid = hSelf;
if (pFile->pLock != NULL) {
releaseLockInfo(pFile->pLock);
-#if IS_VXWORKS
- rc = findLockInfo(pFile->h, pFile->zRealpath, &pFile->pLock, 0);
-#else
rc = findLockInfo(pFile->h, &pFile->pLock, 0);
-#endif
OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
locktypeName(pFile->locktype),
locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
@@ -22664,7 +22080,6 @@ static int unixRead(
}else if( got<0 ){
return SQLITE_IOERR_READ;
}else{
- /* Unread parts of the buffer must be zero-filled */
memset(&((char*)pBuf)[got], 0, amt-got);
return SQLITE_IOERR_SHORT_READ;
}
@@ -22768,20 +22183,6 @@ SQLITE_API int sqlite3_fullsync_count = 0;
static int full_fsync(int fd, int fullSync, int dataOnly){
int rc;
- /* The following "ifdef/elif/else/" block has the same structure as
- ** the one below. It is replicated here solely to avoid cluttering
- ** up the real code with the UNUSED_PARAMETER() macros.
- */
-#ifdef SQLITE_NO_SYNC
- UNUSED_PARAMETER(fd);
- UNUSED_PARAMETER(fullSync);
- UNUSED_PARAMETER(dataOnly);
-#elif HAVE_FULLFSYNC
- UNUSED_PARAMETER(dataOnly);
-#else
- UNUSED_PARAMETER(fullSync);
-#endif
-
/* Record the number of times that we do a normal fsync() and
** FULLSYNC. This is used during testing to verify that this procedure
** gets called with the correct arguments.
@@ -22796,7 +22197,9 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
*/
#ifdef SQLITE_NO_SYNC
rc = SQLITE_OK;
-#elif HAVE_FULLFSYNC
+#else
+
+#if HAVE_FULLFSYNC
if( fullSync ){
rc = fcntl(fd, F_FULLFSYNC, 0);
}else{
@@ -22815,17 +22218,12 @@ static int full_fsync(int fd, int fullSync, int dataOnly){
#else
if( dataOnly ){
rc = fdatasync(fd);
- if( IS_VXWORKS && rc==-1 && errno==ENOTSUP ){
- rc = fsync(fd);
- }
}else{
rc = fsync(fd);
}
-#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
+#endif /* HAVE_FULLFSYNC */
+#endif /* defined(SQLITE_NO_SYNC) */
- if( IS_VXWORKS && rc!= -1 ){
- rc = 0;
- }
return rc;
}
@@ -22856,11 +22254,6 @@ static int unixSync(sqlite3_file *id, int flags){
|| (flags&0x0F)==SQLITE_SYNC_FULL
);
- /* Unix cannot, but some systems may return SQLITE_FULL from here. This
- ** line is to test that doing so does not cause any problems.
- */
- SimulateDiskfullError( return SQLITE_FULL );
-
assert( pFile );
OSTRACE2("SYNC %-3d\n", pFile->h);
rc = full_fsync(pFile->h, isFullsync, isDataOnly);
@@ -22934,79 +22327,13 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){
}
/*
-** This routine translates a standard POSIX errno code into something
-** useful to the clients of the sqlite3 functions. Specifically, it is
-** intended to translate a variety of "try again" errors into SQLITE_BUSY
-** and a variety of "please close the file descriptor NOW" errors into
-** SQLITE_IOERR
-**
-** Errors during initialization of locks, or file system support for locks,
-** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
-*/
-static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
- switch (posixError) {
- case 0:
- return SQLITE_OK;
-
- case EAGAIN:
- case ETIMEDOUT:
- case EBUSY:
- case EINTR:
- case ENOLCK:
- /* random NFS retry error, unless during file system support
- * introspection, in which it actually means what it says */
- return SQLITE_BUSY;
-
- case EACCES:
- /* EACCES is like EAGAIN during locking operations, but not any other time*/
- if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
- return SQLITE_BUSY;
- }
- /* else fall through */
- case EPERM:
- return SQLITE_PERM;
-
- case EDEADLK:
- return SQLITE_IOERR_BLOCKED;
-
-#if EOPNOTSUPP!=ENOTSUP
- case EOPNOTSUPP:
- /* something went terribly awry, unless during file system support
- * introspection, in which it actually means what it says */
-#endif
-#ifdef ENOTSUP
- case ENOTSUP:
- /* invalid fd, unless during file system support introspection, in which
- * it actually means what it says */
-#endif
- case EIO:
- case EBADF:
- case EINVAL:
- case ENOTCONN:
- case ENODEV:
- case ENXIO:
- case ENOENT:
- case ESTALE:
- case ENOSYS:
- /* these should force the client to close the file and reconnect */
-
- default:
- return sqliteIOErr;
- }
-}
-
-/*
** 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.
+** file by this or any other process. If such a lock is held, return
+** non-zero. If the file is unlocked or holds only SHARED locks, then
+** return zero.
*/
static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
+ int r = 0;
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -23016,31 +22343,28 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
/* Check if a thread in this process holds such a lock */
if( pFile->pLock->locktype>SHARED_LOCK ){
- reserved = 1;
+ r = 1;
}
/* Otherwise see if some other process holds it.
*/
- if( !reserved ){
+ if( !r ){
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = RESERVED_BYTE;
lock.l_len = 1;
lock.l_type = F_WRLCK;
- if (-1 == fcntl(pFile->h, F_GETLK, &lock)) {
- int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
- pFile->lastErrno = tErrno;
- } else if( lock.l_type!=F_UNLCK ){
- reserved = 1;
+ fcntl(pFile->h, F_GETLK, &lock);
+ if( lock.l_type!=F_UNLCK ){
+ r = 1;
}
}
leaveMutex();
- OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
+ OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
- *pResOut = reserved;
- return rc;
+ *pResOut = r;
+ return SQLITE_OK;
}
/*
@@ -23186,11 +22510,7 @@ static int unixLock(sqlite3_file *id, int locktype){
lock.l_start = PENDING_BYTE;
s = fcntl(pFile->h, F_SETLK, &lock);
if( s==(-1) ){
- int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
+ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
goto end_lock;
}
}
@@ -23200,36 +22520,24 @@ static int unixLock(sqlite3_file *id, int locktype){
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
- int tErrno = 0;
assert( pLock->cnt==0 );
assert( pLock->locktype==0 );
/* Now get the read-lock */
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
- if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
- tErrno = errno;
- }
+ s = fcntl(pFile->h, F_SETLK, &lock);
+
/* Drop the temporary PENDING lock */
lock.l_start = PENDING_BYTE;
lock.l_len = 1L;
lock.l_type = F_UNLCK;
if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
- if( s != -1 ){
- /* This could happen with a network mount */
- tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- goto end_lock;
- }
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ goto end_lock;
}
if( s==(-1) ){
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
+ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
pFile->locktype = SHARED_LOCK;
pFile->pOpen->nLock++;
@@ -23259,11 +22567,7 @@ static int unixLock(sqlite3_file *id, int locktype){
}
s = fcntl(pFile->h, F_SETLK, &lock);
if( s==(-1) ){
- int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
+ rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}
}
@@ -23322,12 +22626,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
if( fcntl(h, F_SETLK, &lock)==(-1) ){
- int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- goto end_unlock;
+ rc = SQLITE_IOERR_RDLOCK;
}
}
lock.l_type = F_UNLCK;
@@ -23337,12 +22636,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){
if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = SHARED_LOCK;
}else{
- int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- goto end_unlock;
+ rc = SQLITE_IOERR_UNLOCK;
}
}
if( locktype==NO_LOCK ){
@@ -23363,13 +22657,8 @@ static int unixUnlock(sqlite3_file *id, int locktype){
if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = NO_LOCK;
}else{
- int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
+ rc = SQLITE_IOERR_UNLOCK;
pLock->cnt = 1;
- goto end_unlock;
}
}
@@ -23392,8 +22681,6 @@ static int unixUnlock(sqlite3_file *id, int locktype){
}
}
}
-
-end_unlock:
leaveMutex();
if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
@@ -23414,25 +22701,6 @@ static int closeUnixFile(sqlite3_file *id){
if( pFile->h>=0 ){
close(pFile->h);
}
-#if IS_VXWORKS
- if( pFile->isDelete && pFile->zRealpath ){
- unlink(pFile->zRealpath);
- }
- if( pFile->zRealpath ){
- HashElem *pElem;
- int n = strlen(pFile->zRealpath) + 1;
- pElem = sqlite3HashFindElem(&nameHash, pFile->zRealpath, n);
- if( pElem ){
- long cnt = (long)pElem->data;
- cnt--;
- if( cnt==0 ){
- sqlite3HashInsert(&nameHash, pFile->zRealpath, n, 0);
- }else{
- pElem->data = (void*)cnt;
- }
- }
- }
-#endif
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
@@ -23475,9 +22743,7 @@ static int unixClose(sqlite3_file *id){
}
-#if SQLITE_ENABLE_LOCKING_STYLE
-
-#if !IS_VXWORKS
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
#pragma mark AFP Support
/*
@@ -23502,11 +22768,14 @@ struct ByteRangeLockPB2
#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
/*
- ** Return SQLITE_OK on success, SQLITE_BUSY on failure.
- */
+** Return 0 on success, 1 on failure. To match the behavior of the
+** normal posix file locking (used in unixLock for example), we should
+** provide 'richer' return codes - specifically to differentiate between
+** 'file busy' and 'file system error' results.
+*/
static int _AFPFSSetLock(
const char *path,
- unixFile *pFile,
+ int fd,
unsigned long long offset,
unsigned long long length,
int setLockFlag
@@ -23518,63 +22787,55 @@ static int _AFPFSSetLock(
pb.startEndFlag = 0;
pb.offset = offset;
pb.length = length;
- pb.fd = pFile->h;
+ pb.fd = fd;
OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n",
- (setLockFlag?"ON":"OFF"), pFile->h, offset, length);
+ (setLockFlag?"ON":"OFF"), fd, offset, length);
err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
if ( err==-1 ) {
- int rc;
- int tErrno = errno;
- OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, tErrno, strerror(tErrno));
- rc = sqliteErrorFromPosixError(tErrno, setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); /* error */
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- return rc;
+ OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno,
+ strerror(errno));
+ return 1; /* error */
} else {
- return SQLITE_OK;
+ return 0;
}
}
-/* AFP-style reserved lock checking following the behavior of
-** unixCheckReservedLock, see the unixCheckReservedLock function comments */
+/*
+ ** 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, return
+ ** non-zero. If the file is unlocked or holds only SHARED locks, then
+ ** return zero.
+ */
static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
+ int r = 0;
unixFile *pFile = (unixFile*)id;
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
+ assert( pFile );
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
/* Check if a thread in this process holds such a lock */
if( pFile->locktype>SHARED_LOCK ){
- reserved = 1;
+ r = 1;
}
/* Otherwise see if some other process holds it.
*/
- if( !reserved ){
- /* lock the RESERVED byte */
- int lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);
- if( SQLITE_OK==lrc ){
+ if ( !r ) {
+ /* lock the byte */
+ int failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
+ if (failed) {
+ /* if we failed to get the lock then someone else must have it */
+ r = 1;
+ } else {
/* if we succeeded in taking the reserved lock, unlock it to restore
** the original state */
- lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1, 0);
- } else {
- /* if we failed to get the lock then someone else must have it */
- reserved = 1;
- }
- if( IS_LOCK_ERROR(lrc) ){
- rc=lrc;
+ _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0);
}
}
+ OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
- OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
-
- *pResOut = reserved;
- return rc;
+ *pResOut = r;
+ return SQLITE_OK;
}
/* AFP-style locking following the behavior of unixLock, see the unixLock
@@ -23624,9 +22885,9 @@ static int afpLock(sqlite3_file *id, int locktype){
|| (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
){
int failed;
- failed = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 1);
+ failed = _AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 1);
if (failed) {
- rc = failed;
+ rc = SQLITE_BUSY;
goto afp_end_lock;
}
}
@@ -23635,29 +22896,23 @@ static int afpLock(sqlite3_file *id, int locktype){
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
- int lk, lrc1, lrc2, lrc1Errno;
+ int lk, failed;
- /* Now get the read-lock SHARED_LOCK */
+ /* Now get the read-lock */
/* note that the quality of the randomness doesn't matter that much */
lk = random();
context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
- lrc1 = _AFPFSSetLock(context->filePath, pFile,
- SHARED_FIRST+context->sharedLockByte, 1, 1);
- if( IS_LOCK_ERROR(lrc1) ){
- lrc1Errno = pFile->lastErrno;
- }
- /* Drop the temporary PENDING lock */
- lrc2 = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 0);
+ failed = _AFPFSSetLock(context->filePath, pFile->h,
+ SHARED_FIRST+context->sharedLockByte, 1, 1);
- if( IS_LOCK_ERROR(lrc1) ) {
- pFile->lastErrno = lrc1Errno;
- rc = lrc1;
- goto afp_end_lock;
- } else if( IS_LOCK_ERROR(lrc2) ){
- rc = lrc2;
+ /* Drop the temporary PENDING lock */
+ if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)) {
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
goto afp_end_lock;
- } else if( lrc1 != SQLITE_OK ) {
- rc = lrc1;
+ }
+
+ if( failed ){
+ rc = SQLITE_BUSY;
} else {
pFile->locktype = SHARED_LOCK;
}
@@ -23670,7 +22925,7 @@ static int afpLock(sqlite3_file *id, int locktype){
assert( 0!=pFile->locktype );
if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
/* Acquire a RESERVED lock */
- failed = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);
+ failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
}
if (!failed && locktype == EXCLUSIVE_LOCK) {
/* Acquire an EXCLUSIVE lock */
@@ -23678,21 +22933,22 @@ static int afpLock(sqlite3_file *id, int locktype){
/* Remove the shared lock before trying the range. we'll need to
** reestablish the shared lock if we can't get the afpUnlock
*/
- if (!(failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST +
- context->sharedLockByte, 1, 0))) {
+ if (!_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST +
+ context->sharedLockByte, 1, 0)) {
/* now attemmpt to get the exclusive lock range */
- failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST,
+ failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST,
SHARED_SIZE, 1);
- if (failed && (failed = _AFPFSSetLock(context->filePath, pFile,
- SHARED_FIRST + context->sharedLockByte, 1, 1))) {
- rc = failed;
+ if (failed && _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST +
+ context->sharedLockByte, 1, 1)) {
+ rc = SQLITE_IOERR_RDLOCK; /* this should never happen */
}
} else {
- rc = failed;
+ /* */
+ rc = SQLITE_IOERR_UNLOCK; /* this should never happen */
}
}
- if( failed ){
- rc = failed;
+ if( failed && rc == SQLITE_OK){
+ rc = SQLITE_BUSY;
}
}
@@ -23724,7 +22980,7 @@ static int afpUnlock(sqlite3_file *id, int locktype) {
assert( pFile );
OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
pFile->locktype, getpid());
-
+
assert( locktype<=SHARED_LOCK );
if( pFile->locktype<=locktype ){
return SQLITE_OK;
@@ -23733,46 +22989,45 @@ static int afpUnlock(sqlite3_file *id, int locktype) {
return SQLITE_MISUSE;
}
enterMutex();
- int failed = SQLITE_OK;
if( pFile->locktype>SHARED_LOCK ){
if( locktype==SHARED_LOCK ){
+ int failed = 0;
/* unlock the exclusive range - then re-establish the shared lock */
if (pFile->locktype==EXCLUSIVE_LOCK) {
- failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST,
+ failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST,
SHARED_SIZE, 0);
if (!failed) {
/* successfully removed the exclusive lock */
- if ((failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST+
- context->sharedLockByte, 1, 1))) {
+ if (_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST+
+ context->sharedLockByte, 1, 1)) {
/* failed to re-establish our shared lock */
- rc = failed;
+ rc = SQLITE_IOERR_RDLOCK; /* This should never happen */
}
} else {
- rc = failed;
+ /* This should never happen - failed to unlock the exclusive range */
+ rc = SQLITE_IOERR_UNLOCK;
}
}
}
if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) {
- if ((failed = _AFPFSSetLock(context->filePath, pFile,
- PENDING_BYTE, 1, 0))){
+ if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)){
/* failed to release the pending lock */
- rc = failed;
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
}
}
if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) {
- if ((failed = _AFPFSSetLock(context->filePath, pFile,
- RESERVED_BYTE, 1, 0))) {
+ if (_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0)) {
/* failed to release the reserved lock */
- rc = failed;
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
}
}
}
if( locktype==NO_LOCK ){
- int failed = _AFPFSSetLock(context->filePath, pFile,
+ int failed = _AFPFSSetLock(context->filePath, pFile->h,
SHARED_FIRST + context->sharedLockByte, 1, 0);
if (failed) {
- rc = failed;
+ rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
}
}
if (rc == SQLITE_OK)
@@ -23801,61 +23056,27 @@ static int afpClose(sqlite3_file *id) {
*/
typedef void flockLockingContext;
-/* flock-style reserved lock checking following the behavior of
- ** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int rc = SQLITE_OK;
- int reserved = 0;
+ int r = 1;
unixFile *pFile = (unixFile*)id;
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->locktype>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
+ if (pFile->locktype != RESERVED_LOCK) {
/* attempt to get the lock */
- int lrc = flock(pFile->h, LOCK_EX | LOCK_NB);
- if( !lrc ){
+ int rc = flock(pFile->h, LOCK_EX | LOCK_NB);
+ if (!rc) {
/* got the lock, unlock it */
- lrc = flock(pFile->h, LOCK_UN);
- if ( lrc ) {
- int tErrno = errno;
- /* unlock failed with an error */
- lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if( IS_LOCK_ERROR(lrc) ){
- pFile->lastErrno = 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) ){
- pFile->lastErrno = tErrno;
- rc = lrc;
- }
+ flock(pFile->h, LOCK_UN);
+ r = 0; /* no one has it reserved */
}
}
- OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
- *pResOut = reserved;
- return rc;
+ *pResOut = r;
+ return SQLITE_OK;
}
static int flockLock(sqlite3_file *id, int locktype) {
- int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
-
- assert( pFile );
-
+
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (pFile->locktype > NO_LOCK) {
@@ -23864,29 +23085,20 @@ static int flockLock(sqlite3_file *id, int locktype) {
}
/* grab an exclusive lock */
-
- if (flock(pFile->h, LOCK_EX | LOCK_NB)) {
- int tErrno = errno;
+ int rc = flock(pFile->h, LOCK_EX | LOCK_NB);
+ if (rc) {
/* didn't get, must be busy */
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
+ return SQLITE_BUSY;
} else {
/* got it, set the type and return ok */
pFile->locktype = locktype;
+ return SQLITE_OK;
}
- OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
- rc==SQLITE_OK ? "ok" : "failed");
- return rc;
}
static int flockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
- assert( pFile );
- OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
- pFile->locktype, getpid());
assert( locktype<=SHARED_LOCK );
/* no-op if possible */
@@ -23902,14 +23114,9 @@ static int flockUnlock(sqlite3_file *id, int locktype) {
/* no, really, unlock. */
int rc = flock(pFile->h, LOCK_UN);
- if (rc) {
- int r, tErrno = errno;
- r = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if( IS_LOCK_ERROR(r) ){
- pFile->lastErrno = tErrno;
- }
- return r;
- } else {
+ if (rc)
+ return SQLITE_IOERR_UNLOCK;
+ else {
pFile->locktype = NO_LOCK;
return SQLITE_OK;
}
@@ -23925,105 +23132,63 @@ static int flockClose(sqlite3_file *id) {
return closeUnixFile(id);
}
-#endif /* !IS_VXWORKS */
-
#pragma mark Old-School .lock file based locking
-/* Dotlock-style reserved lock checking following the behavior of
-** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
+ int r = 1;
unixFile *pFile = (unixFile*)id;
+ char *zLockFile = (char *)pFile->lockingContext;
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->locktype>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- char *zLockFile = (char *)pFile->lockingContext;
+ if (pFile->locktype != RESERVED_LOCK) {
struct stat statBuf;
-
- if( lstat(zLockFile, &statBuf)==0 ){
- /* file exists, someone else has the lock */
- reserved = 1;
- }else{
+ if (lstat(zLockFile, &statBuf) != 0){
/* file does not exist, we could have it if we want it */
- int tErrno = errno;
- if( ENOENT != tErrno ){
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
- pFile->lastErrno = tErrno;
- }
+ r = 0;
}
}
- OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
- *pResOut = reserved;
- return rc;
+ *pResOut = r;
+ return SQLITE_OK;
}
static int dotlockLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int fd;
char *zLockFile = (char *)pFile->lockingContext;
- int rc=SQLITE_OK;
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (pFile->locktype > NO_LOCK) {
pFile->locktype = locktype;
-#if !IS_VXWORKS
+
/* Always update the timestamp on the old file */
utimes(zLockFile, NULL);
-#endif
- rc = SQLITE_OK;
- goto dotlock_end_lock;
+ return SQLITE_OK;
}
/* check to see if lock file already exists */
struct stat statBuf;
if (lstat(zLockFile,&statBuf) == 0){
- rc = SQLITE_BUSY; /* it does, busy */
- goto dotlock_end_lock;
+ return SQLITE_BUSY; /* it does, busy */
}
/* grab an exclusive lock */
fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
if( fd<0 ){
/* failed to open/create the file, someone else may have stolen the lock */
- int tErrno = errno;
- if( EEXIST == tErrno ){
- rc = SQLITE_BUSY;
- } else {
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- }
- goto dotlock_end_lock;
- }
+ return SQLITE_BUSY;
+ }
close(fd);
/* got it, set the type and return ok */
pFile->locktype = locktype;
-
- dotlock_end_lock:
- return rc;
+ return SQLITE_OK;
}
static int dotlockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
char *zLockFile = (char *)pFile->lockingContext;
- assert( pFile );
- OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
- pFile->locktype, getpid());
assert( locktype<=SHARED_LOCK );
/* no-op if possible */
@@ -24038,16 +23203,7 @@ static int dotlockUnlock(sqlite3_file *id, int locktype) {
}
/* no, really, unlock. */
- if (unlink(zLockFile) ) {
- int rc, tErrno = errno;
- if( ENOENT != tErrno ){
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- }
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- return rc;
- }
+ unlink(zLockFile);
pFile->locktype = NO_LOCK;
return SQLITE_OK;
}
@@ -24056,142 +23212,14 @@ static int dotlockUnlock(sqlite3_file *id, int locktype) {
** Close a file.
*/
static int dotlockClose(sqlite3_file *id) {
- int rc;
if( id ){
unixFile *pFile = (unixFile*)id;
dotlockUnlock(id, NO_LOCK);
sqlite3_free(pFile->lockingContext);
}
- if( IS_VXWORKS ) enterMutex();
- rc = closeUnixFile(id);
- if( IS_VXWORKS ) leaveMutex();
- return rc;
-}
-
-#if IS_VXWORKS
-
-#pragma mark POSIX/vxWorks named semaphore based locking
-
-/* Namedsem-style reserved lock checking following the behavior of
-** unixCheckReservedLock, see the unixCheckReservedLock function comments */
-static int namedsemCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
- unixFile *pFile = (unixFile*)id;
-
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->locktype>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- sem_t *pSem = pFile->pOpen->pSem;
- struct stat statBuf;
-
- if( sem_trywait(pSem)==-1 ){
- int tErrno = errno;
- if( EAGAIN != tErrno ){
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
- pFile->lastErrno = tErrno;
- } else {
- /* someone else has the lock when we are in NO_LOCK */
- reserved = (pFile->locktype < SHARED_LOCK);
- }
- }else{
- /* we could have it if we want it */
- sem_post(pSem);
- }
- }
- OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
-
- *pResOut = reserved;
- return rc;
-}
-
-static int namedsemLock(sqlite3_file *id, int locktype) {
- unixFile *pFile = (unixFile*)id;
- int fd;
- sem_t *pSem = pFile->pOpen->pSem;
- int rc = SQLITE_OK;
-
- /* if we already have a lock, it is exclusive.
- ** Just adjust level and punt on outta here. */
- if (pFile->locktype > NO_LOCK) {
- pFile->locktype = locktype;
- rc = SQLITE_OK;
- goto namedsem_end_lock;
- }
-
- /* lock semaphore now but bail out when already locked. */
- if( sem_trywait(pSem)==-1 ){
- rc = SQLITE_BUSY;
- goto namedsem_end_lock;
- }
-
- /* got it, set the type and return ok */
- pFile->locktype = locktype;
-
- namedsem_end_lock:
- return rc;
-}
-
-static int namedsemUnlock(sqlite3_file *id, int locktype) {
- unixFile *pFile = (unixFile*)id;
- sem_t *pSem = pFile->pOpen->pSem;
-
- assert( pFile );
- assert( pSem );
- OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
- pFile->locktype, getpid());
- assert( locktype<=SHARED_LOCK );
-
- /* no-op if possible */
- if( pFile->locktype==locktype ){
- return SQLITE_OK;
- }
-
- /* shared can just be set because we always have an exclusive */
- if (locktype==SHARED_LOCK) {
- pFile->locktype = locktype;
- return SQLITE_OK;
- }
-
- /* no, really unlock. */
- if ( sem_post(pSem)==-1 ) {
- int rc, tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- return rc;
- }
- pFile->locktype = NO_LOCK;
- return SQLITE_OK;
-}
-
-/*
- ** Close a file.
- */
-static int namedsemClose(sqlite3_file *id) {
- if( id ){
- unixFile *pFile = (unixFile*)id;
- namedsemUnlock(id, NO_LOCK);
- assert( pFile );
- enterMutex();
- releaseLockInfo(pFile->pLock);
- releaseOpenCnt(pFile->pOpen);
- closeUnixFile(id);
- leaveMutex();
- }
- return SQLITE_OK;
+ return closeUnixFile(id);
}
-#endif /* IS_VXWORKS */
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
@@ -24200,19 +23228,16 @@ static int namedsemClose(sqlite3_file *id) {
*/
typedef void nolockLockingContext;
-static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
- UNUSED_PARAMETER(NotUsed);
+static int nolockCheckReservedLock(sqlite3_file *id, int *pResOut) {
*pResOut = 0;
return SQLITE_OK;
}
-static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
+static int nolockLock(sqlite3_file *id, int locktype) {
return SQLITE_OK;
}
-static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
+static int nolockUnlock(sqlite3_file *id, int locktype) {
return SQLITE_OK;
}
@@ -24220,11 +23245,7 @@ static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
** Close a file.
*/
static int nolockClose(sqlite3_file *id) {
- int rc;
- if( IS_VXWORKS ) enterMutex();
- rc = closeUnixFile(id);
- if( IS_VXWORKS ) leaveMutex();
- return rc;
+ return closeUnixFile(id);
}
@@ -24251,16 +23272,14 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
** a database and its journal file) that the sector size will be the
** same for both.
*/
-static int unixSectorSize(sqlite3_file *NotUsed){
- UNUSED_PARAMETER(NotUsed);
+static int unixSectorSize(sqlite3_file *id){
return SQLITE_DEFAULT_SECTOR_SIZE;
}
/*
-** Return the device characteristics for the file. This is always 0 for unix.
+** Return the device characteristics for the file. This is always 0.
*/
-static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
- UNUSED_PARAMETER(NotUsed);
+static int unixDeviceCharacteristics(sqlite3_file *id){
return 0;
}
@@ -24278,8 +23297,7 @@ static int fillInUnixFile(
int dirfd, /* Directory file descriptor */
sqlite3_file *pId, /* Write to the unixFile structure here */
const char *zFilename, /* Name of the file being opened */
- int noLock, /* Omit locking if true */
- int isDelete /* Delete on close if true */
+ int noLock /* Omit locking if true */
){
int eLockingStyle;
unixFile *pNew = (unixFile *)pId;
@@ -24308,17 +23326,10 @@ static int fillInUnixFile(
static sqlite3_io_methods aIoMethod[] = {
IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock)
,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
-#if SQLITE_ENABLE_LOCKING_STYLE
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock)
-#if IS_VXWORKS
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
- ,IOMETHODS(namedsemClose, namedsemLock, namedsemUnlock, namedsemCheckReservedLock)
-#else
,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
-#endif
#endif
};
/* The order of the IOMETHODS macros above is important. It must be the
@@ -24329,60 +23340,15 @@ static int fillInUnixFile(
assert(LOCKING_STYLE_DOTFILE==3);
assert(LOCKING_STYLE_FLOCK==4);
assert(LOCKING_STYLE_AFP==5);
- assert(LOCKING_STYLE_NAMEDSEM==6);
assert( pNew->pLock==NULL );
assert( pNew->pOpen==NULL );
- /* Parameter isDelete is only used on vxworks. Parameter pVfs is only
- ** used if ENABLE_LOCKING_STYLE is defined. Express this explicitly
- ** here to prevent compiler warnings about unused parameters.
- */
- if( !IS_VXWORKS ) UNUSED_PARAMETER(isDelete);
- if( !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(pVfs);
- if( !IS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename);
-
OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->h = h;
pNew->dirfd = dirfd;
SET_THREADID(pNew);
-#if IS_VXWORKS
- {
- HashElem *pElem;
- char *zRealname = vxrealpath(zFilename, 1);
- int n;
- pNew->zRealpath = 0;
- if( !zRealname ){
- rc = SQLITE_NOMEM;
- eLockingStyle = LOCKING_STYLE_NONE;
- }else{
- n = strlen(zRealname) + 1;
- enterMutex();
- pElem = sqlite3HashFindElem(&nameHash, zRealname, n);
- if( pElem ){
- long cnt = (long)pElem->data;
- cnt++;
- pNew->zRealpath = pElem->pKey;
- pElem->data = (void*)cnt;
- }else{
- if( sqlite3HashInsert(&nameHash, zRealname, n, (void*)1)==0 ){
- pElem = sqlite3HashFindElem(&nameHash, zRealname, n);
- if( pElem ){
- pNew->zRealpath = pElem->pKey;
- }else{
- sqlite3HashInsert(&nameHash, zRealname, n, 0);
- rc = SQLITE_NOMEM;
- eLockingStyle = LOCKING_STYLE_NONE;
- }
- }
- }
- leaveMutex();
- sqlite3_free(zRealname);
- }
- }
-#endif
-
if( noLock ){
eLockingStyle = LOCKING_STYLE_NONE;
}else{
@@ -24393,18 +23359,12 @@ static int fillInUnixFile(
case LOCKING_STYLE_POSIX: {
enterMutex();
-#if IS_VXWORKS
- rc = findLockInfo(h, pNew->zRealpath, &pNew->pLock, &pNew->pOpen);
-#else
rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen);
-#endif
leaveMutex();
break;
}
-#if SQLITE_ENABLE_LOCKING_STYLE
-
-#if !IS_VXWORKS
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
case LOCKING_STYLE_AFP: {
/* AFP locking uses the file path so it needs to be included in
** the afpLockingContext.
@@ -24422,7 +23382,6 @@ static int fillInUnixFile(
}
break;
}
-#endif
case LOCKING_STYLE_DOTFILE: {
/* Dotfile locking uses the file path so it needs to be included in
@@ -24441,44 +23400,12 @@ static int fillInUnixFile(
break;
}
-#if IS_VXWORKS
- case LOCKING_STYLE_NAMEDSEM: {
- /* Named semaphore locking uses the file path so it needs to be
- ** included in the namedsemLockingContext
- */
- enterMutex();
- rc = findLockInfo(h, pNew->zRealpath, &pNew->pLock, &pNew->pOpen);
- if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
- char *zSemName = pNew->pOpen->aSemName;
- int n;
- sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", pNew->zRealpath);
- for( n=0; zSemName[n]; n++ )
- if( zSemName[n]=='/' ) zSemName[n] = '_';
- pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
- if( pNew->pOpen->pSem == SEM_FAILED ){
- rc = SQLITE_NOMEM;
- pNew->pOpen->aSemName[0] = '\0';
- }
- }
- leaveMutex();
- break;
- }
-#endif
-
case LOCKING_STYLE_FLOCK:
case LOCKING_STYLE_NONE:
break;
#endif
}
-
- pNew->lastErrno = 0;
-#if IS_VXWORKS
- if( rc!=SQLITE_OK ){
- unlink(zFilename);
- isDelete = 0;
- }
- pNew->isDelete = isDelete;
-#endif
+
if( rc!=SQLITE_OK ){
if( dirfd>=0 ) close(dirfd);
close(h);
@@ -24548,7 +23475,7 @@ static int getTempname(int nBuf, char *zBuf){
SimulateIOError( return SQLITE_IOERR );
azDirs[0] = sqlite3_temp_directory;
- for(i=0; i<ArraySize(azDirs); i++){
+ for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
if( azDirs[i]==0 ) continue;
if( stat(azDirs[i], &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
@@ -24560,7 +23487,7 @@ static int getTempname(int nBuf, char *zBuf){
/* Check that the output buffer is large enough for the temporary file
** name. If it is not, return SQLITE_ERROR.
*/
- if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= (size_t)nBuf ){
+ if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){
return SQLITE_ERROR;
}
@@ -24677,7 +23604,6 @@ static int unixOpen(
oflags |= (O_LARGEFILE|O_BINARY);
fd = open(zName, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS);
- OSTRACE4("OPENX %-3d %s 0%o\n", fd, zName, oflags);
if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
/* Failed to open the file for read/write access. Try read-only. */
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
@@ -24688,11 +23614,7 @@ static int unixOpen(
return SQLITE_CANTOPEN;
}
if( isDelete ){
-#if IS_VXWORKS
- zPath = zName;
-#else
unlink(zName);
-#endif
}
if( pOutFlags ){
*pOutFlags = flags;
@@ -24712,35 +23634,27 @@ static int unixOpen(
#endif
noLock = eType!=SQLITE_OPEN_MAIN_DB;
- return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
+ return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock);
}
/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file.
*/
-static int unixDelete(sqlite3_vfs *NotUsed, const char *zPath, int dirSync){
+static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
int rc = SQLITE_OK;
- UNUSED_PARAMETER(NotUsed);
SimulateIOError(return SQLITE_IOERR_DELETE);
unlink(zPath);
-#ifndef SQLITE_DISABLE_DIRSYNC
if( dirSync ){
int fd;
rc = openDirectory(zPath, &fd);
if( rc==SQLITE_OK ){
-#if IS_VXWORKS
- if( fsync(fd)==-1 )
-#else
- if( fsync(fd) )
-#endif
- {
+ if( fsync(fd) ){
rc = SQLITE_IOERR_DIR_FSYNC;
}
close(fd);
}
}
-#endif
return rc;
}
@@ -24755,13 +23669,12 @@ static int unixDelete(sqlite3_vfs *NotUsed, const char *zPath, int dirSync){
** Otherwise return 0.
*/
static int unixAccess(
- sqlite3_vfs *NotUsed,
+ sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
int amode = 0;
- UNUSED_PARAMETER(NotUsed);
SimulateIOError( return SQLITE_IOERR_ACCESS; );
switch( flags ){
case SQLITE_ACCESS_EXISTS:
@@ -24806,20 +23719,6 @@ static int unixFullPathname(
SimulateIOError( return SQLITE_ERROR );
assert( pVfs->mxPathname==MAX_PATHNAME );
- UNUSED_PARAMETER(pVfs);
-
-#if IS_VXWORKS
- {
- char *zRealname = vxrealpath(zPath, 0);
- zOut[0] = '\0';
- if( !zRealname ){
- return SQLITE_CANTOPEN;
- }
- sqlite3_snprintf(nOut, zOut, "%s", zRealname);
- sqlite3_free(zRealname);
- return SQLITE_OK;
- }
-#else
zOut[nOut-1] = '\0';
if( zPath[0]=='/' ){
sqlite3_snprintf(nOut, zOut, "%s", zPath);
@@ -24858,7 +23757,6 @@ static int unixFullPathname(
zFull[j] = 0;
}
#endif
-#endif
}
@@ -24868,8 +23766,7 @@ static int unixFullPathname(
** within the shared library, and closing the shared library.
*/
#include <dlfcn.h>
-static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
- UNUSED_PARAMETER(NotUsed);
+static void *unixDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
}
@@ -24880,9 +23777,8 @@ static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
** is available, zBufOut is left unmodified and SQLite uses a default
** error message.
*/
-static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
+static void unixDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
char *zErr;
- UNUSED_PARAMETER(NotUsed);
enterMutex();
zErr = dlerror();
if( zErr ){
@@ -24890,12 +23786,10 @@ static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
}
leaveMutex();
}
-static void *unixDlSym(sqlite3_vfs *NotUsed, void *pHandle, const char*zSymbol){
- UNUSED_PARAMETER(NotUsed);
+static void *unixDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
return dlsym(pHandle, zSymbol);
}
-static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
- UNUSED_PARAMETER(NotUsed);
+static void unixDlClose(sqlite3_vfs *pVfs, void *pHandle){
dlclose(pHandle);
}
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
@@ -24908,9 +23802,9 @@ static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
/*
** Write nBuf bytes of random data to the supplied buffer zBuf.
*/
-static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
- UNUSED_PARAMETER(NotUsed);
- assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
+static int unixRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+
+ assert(nBuf>=(sizeof(time_t)+sizeof(int)));
/* We have to initialize zBuf to prevent valgrind from reporting
** errors. The reports issued by valgrind are incorrect - we would
@@ -24935,15 +23829,13 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
memcpy(zBuf, &t, sizeof(t));
pid = getpid();
memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
- assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
- nBuf = sizeof(t) + sizeof(pid);
}else{
- nBuf = read(fd, zBuf, nBuf);
+ read(fd, zBuf, nBuf);
close(fd);
}
}
#endif
- return nBuf;
+ return SQLITE_OK;
}
@@ -24955,15 +23847,8 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
** might be greater than or equal to the argument, but not less
** than the argument.
*/
-static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
-#if IS_VXWORKS
- struct timespec sp;
-
- sp.tv_sec = microseconds / 1000000;
- sp.tv_nsec = (microseconds % 1000000) * 1000;
- nanosleep(&sp, NULL);
- return microseconds;
-#elif defined(HAVE_USLEEP) && HAVE_USLEEP
+static int unixSleep(sqlite3_vfs *pVfs, int microseconds){
+#if defined(HAVE_USLEEP) && HAVE_USLEEP
usleep(microseconds);
return microseconds;
#else
@@ -24971,7 +23856,6 @@ static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
sleep(seconds);
return seconds*1000000;
#endif
- UNUSED_PARAMETER(NotUsed);
}
/*
@@ -24987,12 +23871,8 @@ SQLITE_API int sqlite3_current_time = 0;
** current time and date as a Julian Day number into *prNow and
** return 0. Return 1 if the time and date cannot be found.
*/
-static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
-#if IS_VXWORKS
- struct timespec sNow;
- clock_gettime(CLOCK_REALTIME, &sNow);
- *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_nsec/86400000000000.0;
-#elif defined(NO_GETTOD)
+static int unixCurrentTime(sqlite3_vfs *pVfs, double *prNow){
+#ifdef NO_GETTOD
time_t t;
time(&t);
*prNow = t/86400.0 + 2440587.5;
@@ -25001,20 +23881,15 @@ static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
gettimeofday(&sNow, 0);
*prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0;
#endif
-
#ifdef SQLITE_TEST
if( sqlite3_current_time ){
*prNow = sqlite3_current_time/86400.0 + 2440587.5;
}
#endif
- UNUSED_PARAMETER(NotUsed);
return 0;
}
-static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
- UNUSED_PARAMETER(NotUsed);
- UNUSED_PARAMETER(NotUsed2);
- UNUSED_PARAMETER(NotUsed3);
+static int unixGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
return 0;
}
@@ -25049,22 +23924,20 @@ SQLITE_API int sqlite3_os_init(void){
}
static sqlite3_vfs unixVfs = UNIXVFS("unix", 0);
-#if SQLITE_ENABLE_LOCKING_STYLE
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#if 0
int i;
static sqlite3_vfs aVfs[] = {
UNIXVFS("unix-posix", LOCKING_STYLE_POSIX),
UNIXVFS("unix-afp", LOCKING_STYLE_AFP),
UNIXVFS("unix-flock", LOCKING_STYLE_FLOCK),
UNIXVFS("unix-dotfile", LOCKING_STYLE_DOTFILE),
- UNIXVFS("unix-none", LOCKING_STYLE_NONE),
- UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
+ UNIXVFS("unix-none", LOCKING_STYLE_NONE)
};
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
sqlite3_vfs_register(&aVfs[i], 0);
}
#endif
-#if IS_VXWORKS
- sqlite3HashInit(&nameHash, 1);
#endif
sqlite3_vfs_register(&unixVfs, 1);
return SQLITE_OK;
@@ -25377,17 +24250,10 @@ SQLITE_API int sqlite3_open_file_count = 0;
/************** Continuing where we left off in os_win.c *********************/
/*
-** Some microsoft compilers lack this definition.
-*/
-#ifndef INVALID_FILE_ATTRIBUTES
-# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
-#endif
-
-/*
** Determine if we are dealing with WindowsCE - which has a much
** reduced API.
*/
-#if SQLITE_OS_WINCE
+#if defined(SQLITE_OS_WINCE)
# define AreFileApisANSI() 1
#endif
@@ -25566,7 +24432,7 @@ static char *unicodeToMbcs(const WCHAR *zWideFilename){
** Convert multibyte character string to UTF-8. Space to hold the
** returned string is obtained from malloc().
*/
-SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
+static char *mbcsToUtf8(const char *zFilename){
char *zFilenameUtf8;
WCHAR *zTmpWide;
@@ -25923,7 +24789,7 @@ static int winClose(sqlite3_file *id){
OSTRACE2("CLOSE %d\n", pFile->h);
do{
rc = CloseHandle(pFile->h);
- }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
+ }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
#if SQLITE_OS_WINCE
#define WINCE_DELETION_ATTEMPTS 3
winceDestroyLock(pFile);
@@ -25979,7 +24845,6 @@ static int winRead(
if( got==(DWORD)amt ){
return SQLITE_OK;
}else{
- /* Unread parts of the buffer must be zero-filled */
memset(&((char*)pBuf)[got], 0, amt-got);
return SQLITE_IOERR_SHORT_READ;
}
@@ -26027,20 +24892,14 @@ static int winWrite(
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
- DWORD rc;
LONG upperBits = (nByte>>32) & 0x7fffffff;
LONG lowerBits = nByte & 0xffffffff;
winFile *pFile = (winFile*)id;
OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte);
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
- rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
- if( INVALID_SET_FILE_POINTER != rc ){
- /* SetEndOfFile will fail if nByte is negative */
- if( SetEndOfFile(pFile->h) ){
- return SQLITE_OK;
- }
- }
- return SQLITE_IOERR_TRUNCATE;
+ SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
+ SetEndOfFile(pFile->h);
+ return SQLITE_OK;
}
#ifdef SQLITE_TEST
@@ -26064,18 +24923,11 @@ static int winSync(sqlite3_file *id, int flags){
}
sqlite3_sync_count++;
#endif
- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
- ** no-op
- */
-#ifdef SQLITE_NO_SYNC
- return SQLITE_OK;
-#else
if( FlushFileBuffers(pFile->h) ){
return SQLITE_OK;
}else{
return SQLITE_IOERR;
}
-#endif
}
/*
@@ -26111,15 +24963,11 @@ static int getReadLock(winFile *pFile){
ovlp.hEvent = 0;
res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY,
0, SHARED_SIZE, 0, &ovlp);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-*/
-#if SQLITE_OS_WINCE==0
}else{
int lk;
sqlite3_randomness(sizeof(lk), &lk);
pFile->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
-#endif
}
return res;
}
@@ -26131,12 +24979,8 @@ static int unlockReadLock(winFile *pFile){
int res;
if( isNT() ){
res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-*/
-#if SQLITE_OS_WINCE==0
}else{
res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
-#endif
}
return res;
}
@@ -26409,12 +25253,8 @@ static void *convertUtf8Filename(const char *zFilename){
void *zConverted = 0;
if( isNT() ){
zConverted = utf8ToUnicode(zFilename);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-*/
-#if SQLITE_OS_WINCE==0
}else{
zConverted = utf8ToMbcs(zFilename);
-#endif
}
/* caller will handle out of memory */
return zConverted;
@@ -26444,23 +25284,17 @@ static int getTempname(int nBuf, char *zBuf){
}else{
return SQLITE_NOMEM;
}
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-** Since the ASCII version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
}else{
char *zUtf8;
char zMbcsPath[MAX_PATH];
GetTempPathA(MAX_PATH-30, zMbcsPath);
- zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
+ zUtf8 = mbcsToUtf8(zMbcsPath);
if( zUtf8 ){
sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
free(zUtf8);
}else{
return SQLITE_NOMEM;
}
-#endif
}
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
zTempPath[i] = 0;
@@ -26522,9 +25356,7 @@ static int winOpen(
DWORD dwShareMode;
DWORD dwCreationDisposition;
DWORD dwFlagsAndAttributes = 0;
-#if SQLITE_OS_WINCE
- int isTemp = 0;
-#endif
+ int isTemp;
winFile *pFile = (winFile*)id;
void *zConverted; /* Filename in OS encoding */
const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
@@ -26565,20 +25397,19 @@ static int winOpen(
if( flags & SQLITE_OPEN_DELETEONCLOSE ){
#if SQLITE_OS_WINCE
dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
- isTemp = 1;
#else
dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
| FILE_ATTRIBUTE_HIDDEN
| FILE_FLAG_DELETE_ON_CLOSE;
#endif
+ isTemp = 1;
}else{
dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
+ isTemp = 0;
}
/* Reports from the internet are that performance is always
** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
-#if SQLITE_OS_WINCE
dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
-#endif
if( isNT() ){
h = CreateFileW((WCHAR*)zConverted,
dwDesiredAccess,
@@ -26588,11 +25419,6 @@ static int winOpen(
dwFlagsAndAttributes,
NULL
);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-** Since the ASCII version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
}else{
h = CreateFileA((char*)zConverted,
dwDesiredAccess,
@@ -26602,7 +25428,6 @@ static int winOpen(
dwFlagsAndAttributes,
NULL
);
-#endif
}
if( h==INVALID_HANDLE_VALUE ){
free(zConverted);
@@ -26662,7 +25487,7 @@ static int winDelete(
int syncDir /* Not used on win32 */
){
int cnt = 0;
- DWORD rc;
+ int rc;
DWORD error;
void *zConverted = convertUtf8Filename(zFilename);
if( zConverted==0 ){
@@ -26674,25 +25499,19 @@ static int winDelete(
DeleteFileW(zConverted);
}while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
|| ((error = GetLastError()) == ERROR_ACCESS_DENIED))
- && (++cnt < MX_DELETION_ATTEMPTS)
+ && (cnt++ < MX_DELETION_ATTEMPTS)
&& (Sleep(100), 1) );
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-** Since the ASCII version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
}else{
do{
DeleteFileA(zConverted);
}while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
|| ((error = GetLastError()) == ERROR_ACCESS_DENIED))
- && (++cnt < MX_DELETION_ATTEMPTS)
+ && (cnt++ < MX_DELETION_ATTEMPTS)
&& (Sleep(100), 1) );
-#endif
}
free(zConverted);
OSTRACE2("DELETE \"%s\"\n", zFilename);
- return ( (rc == INVALID_FILE_ATTRIBUTES)
+ return ( (rc==INVALID_FILE_ATTRIBUTES)
&& (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
}
@@ -26713,14 +25532,8 @@ static int winAccess(
}
if( isNT() ){
attr = GetFileAttributesW((WCHAR*)zConverted);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-** Since the ASCII version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
}else{
attr = GetFileAttributesA((char*)zConverted);
-#endif
}
free(zConverted);
switch( flags ){
@@ -26779,11 +25592,6 @@ static int winFullPathname(
free(zConverted);
zOut = unicodeToUtf8(zTemp);
free(zTemp);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-** Since the ASCII version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
}else{
char *zTemp;
nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
@@ -26794,9 +25602,8 @@ static int winFullPathname(
}
GetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
free(zConverted);
- zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
+ zOut = mbcsToUtf8(zTemp);
free(zTemp);
-#endif
}
if( zOut ){
sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut);
@@ -26825,14 +25632,8 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
}
if( isNT() ){
h = LoadLibraryW((WCHAR*)zConverted);
-/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
-** Since the ASCII version of these Windows API do not exist for WINCE,
-** it's important to not reference them for WINCE builds.
-*/
-#if SQLITE_OS_WINCE==0
}else{
h = LoadLibraryA((char*)zConverted);
-#endif
}
free(zConverted);
return (void*)h;
@@ -26866,11 +25667,6 @@ void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
*/
static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
int n = 0;
- UNUSED_PARAMETER(pVfs);
-#if defined(SQLITE_TEST)
- n = nBuf;
- memset(zBuf, 0, nBuf);
-#else
if( sizeof(SYSTEMTIME)<=nBuf-n ){
SYSTEMTIME x;
GetSystemTime(&x);
@@ -26893,7 +25689,6 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
memcpy(&zBuf[n], &i, sizeof(i));
n += sizeof(i);
}
-#endif
return n;
}
@@ -27029,14 +25824,12 @@ SQLITE_API int sqlite3_os_end(void){
** This file implements an object that represents a fixed-length
** bitmap. Bits are numbered starting with 1.
**
-** A bitmap is used to record which pages of a database file have been
-** journalled during a transaction, or which pages have the "dont-write"
-** property. Usually only a few pages are meet either condition.
-** So the bitmap is usually sparse and has low cardinality.
+** A bitmap is used to record what pages a database file have been
+** journalled during a transaction. Usually only a few pages are
+** journalled. So the bitmap is usually sparse and has low cardinality.
** But sometimes (for example when during a DROP of a large table) most
-** or all of the pages in a database can get journalled. In those cases,
-** the bitmap becomes dense with high cardinality. The algorithm needs
-** to handle both cases well.
+** or all of the pages get journalled. In those cases, the bitmap becomes
+** dense. The algorithm needs to handle both cases well.
**
** The size of the bitmap is fixed when the object is created.
**
@@ -27054,38 +25847,17 @@ SQLITE_API int sqlite3_os_end(void){
** @(#) $Id$
*/
-/* Size of the Bitvec structure in bytes. */
#define BITVEC_SZ 512
-
/* Round the union size down to the nearest pointer boundary, since that's how
** it will be aligned within the Bitvec struct. */
-#define BITVEC_USIZE (((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
-
-/* Type of the array "element" for the bitmap representation.
-** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE.
-** Setting this to the "natural word" size of your CPU may improve
-** performance. */
-#define BITVEC_TELEM u8
-/* Size, in bits, of the bitmap element. */
-#define BITVEC_SZELEM 8
-/* Number of elements in a bitmap array. */
-#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM))
-/* Number of bits in the bitmap array. */
-#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM)
-
-/* Number of u32 values in hash table. */
-#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
-/* Maximum number of entries in hash table before
-** sub-dividing and re-hashing. */
+#define BITVEC_USIZE (((BITVEC_SZ-12)/sizeof(Bitvec*))*sizeof(Bitvec*))
+#define BITVEC_NCHAR BITVEC_USIZE
+#define BITVEC_NBIT (BITVEC_NCHAR*8)
+#define BITVEC_NINT (BITVEC_USIZE/4)
#define BITVEC_MXHASH (BITVEC_NINT/2)
-/* Hashing function for the aHash representation.
-** Empirical testing showed that the *37 multiplier
-** (an arbitrary prime)in the hash function provided
-** 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_HASH(X) (((X)*37)%BITVEC_NINT)
/*
** A bitmap is an instance of the following structure.
@@ -27109,15 +25881,11 @@ SQLITE_API int sqlite3_os_end(void){
** to hold deal with values between 1 and iDivisor.
*/
struct Bitvec {
- u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */
- u32 nSet; /* Number of bits that are set - only valid for aHash element */
- /* Max nSet is BITVEC_NINT. For BITVEC_SZ of 512, this would be 125. */
- u32 iDivisor; /* Number of bits handled by each apSub[] entry. */
- /* Should >=0 for apSub element. */
- /* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */
- /* For a BITVEC_SZ of 512, this would be 34,359,739. */
+ u32 iSize; /* Maximum bit index */
+ u32 nSet; /* Number of bits that are set */
+ u32 iDivisor; /* Number of bits handled by each apSub[] entry */
union {
- BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */
+ u8 aBitmap[BITVEC_NCHAR]; /* Bitmap representation */
u32 aHash[BITVEC_NINT]; /* Hash table representation */
Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
} u;
@@ -27146,19 +25914,16 @@ SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
if( p==0 ) return 0;
if( i>p->iSize || i==0 ) return 0;
- i--;
- while( p->iDivisor ){
- u32 bin = i/p->iDivisor;
- i = i%p->iDivisor;
- p = p->u.apSub[bin];
- if (!p) {
- return 0;
- }
- }
if( p->iSize<=BITVEC_NBIT ){
- return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
- } else{
- u32 h = BITVEC_HASH(i++);
+ i--;
+ return (p->u.aBitmap[i/8] & (1<<(i&7)))!=0;
+ }
+ if( p->iDivisor>0 ){
+ u32 bin = (i-1)/p->iDivisor;
+ i = (i-1)%p->iDivisor + 1;
+ return sqlite3BitvecTest(p->u.apSub[bin], i);
+ }else{
+ u32 h = BITVEC_HASH(i);
while( p->u.aHash[h] ){
if( p->u.aHash[h]==i ) return 1;
h++;
@@ -27171,64 +25936,40 @@ SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
/*
** Set the i-th bit. Return 0 on success and an error code if
** anything goes wrong.
-**
-** This routine might cause sub-bitmaps to be allocated. Failing
-** to get the memory needed to hold the sub-bitmap is the only
-** that can go wrong with an insert, assuming p and i are valid.
-**
-** The calling function must ensure that p is a valid Bitvec object
-** and that the value for "i" is within range of the Bitvec object.
-** Otherwise the behavior is undefined.
*/
SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
u32 h;
assert( p!=0 );
assert( i>0 );
assert( i<=p->iSize );
- i--;
- while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
- u32 bin = i/p->iDivisor;
- i = i%p->iDivisor;
+ if( p->iSize<=BITVEC_NBIT ){
+ i--;
+ p->u.aBitmap[i/8] |= 1 << (i&7);
+ return SQLITE_OK;
+ }
+ if( p->iDivisor ){
+ u32 bin = (i-1)/p->iDivisor;
+ i = (i-1)%p->iDivisor + 1;
if( p->u.apSub[bin]==0 ){
sqlite3BeginBenignMalloc();
p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
sqlite3EndBenignMalloc();
if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
}
- p = p->u.apSub[bin];
+ return sqlite3BitvecSet(p->u.apSub[bin], i);
}
- if( p->iSize<=BITVEC_NBIT ){
- p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
- return SQLITE_OK;
- }
- h = BITVEC_HASH(i++);
- /* if there wasn't a hash collision, and this doesn't */
- /* completely fill the hash, then just add it without */
- /* worring about sub-dividing and re-hashing. */
- if( !p->u.aHash[h] ){
- if (p->nSet<(BITVEC_NINT-1)) {
- goto bitvec_set_end;
- } else {
- goto bitvec_set_rehash;
- }
- }
- /* there was a collision, check to see if it's already */
- /* in hash, if not, try to find a spot for it */
- do {
+ h = BITVEC_HASH(i);
+ while( p->u.aHash[h] ){
if( p->u.aHash[h]==i ) return SQLITE_OK;
h++;
- if( h>=BITVEC_NINT ) h = 0;
- } while( p->u.aHash[h] );
- /* we didn't find it in the hash. h points to the first */
- /* available free spot. check to see if this is going to */
- /* make our hash too "full". */
-bitvec_set_rehash:
+ if( h==BITVEC_NINT ) h = 0;
+ }
+ p->nSet++;
if( p->nSet>=BITVEC_MXHASH ){
- unsigned int j;
- int rc;
+ int j, rc;
u32 aiValues[BITVEC_NINT];
memcpy(aiValues, p->u.aHash, sizeof(aiValues));
- memset(p->u.apSub, 0, sizeof(aiValues));
+ memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR);
p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
rc = sqlite3BitvecSet(p, i);
for(j=0; j<BITVEC_NINT; j++){
@@ -27236,44 +25977,35 @@ bitvec_set_rehash:
}
return rc;
}
-bitvec_set_end:
- p->nSet++;
p->u.aHash[h] = i;
return SQLITE_OK;
}
/*
-** Clear the i-th bit.
+** Clear the i-th bit. Return 0 on success and an error code if
+** anything goes wrong.
*/
SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i){
assert( p!=0 );
assert( i>0 );
- i--;
- while( p->iDivisor ){
- u32 bin = i/p->iDivisor;
- i = i%p->iDivisor;
- p = p->u.apSub[bin];
- if (!p) {
- return;
- }
- }
if( p->iSize<=BITVEC_NBIT ){
- p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
+ i--;
+ p->u.aBitmap[i/8] &= ~(1 << (i&7));
+ }else if( p->iDivisor ){
+ u32 bin = (i-1)/p->iDivisor;
+ i = (i-1)%p->iDivisor + 1;
+ if( p->u.apSub[bin] ){
+ sqlite3BitvecClear(p->u.apSub[bin], i);
+ }
}else{
- unsigned int j;
+ int j;
u32 aiValues[BITVEC_NINT];
memcpy(aiValues, p->u.aHash, sizeof(aiValues));
- memset(p->u.aHash, 0, sizeof(aiValues));
+ memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT);
p->nSet = 0;
for(j=0; j<BITVEC_NINT; j++){
- if( aiValues[j] && aiValues[j]!=(i+1) ){
- u32 h = BITVEC_HASH(aiValues[j]-1);
- p->nSet++;
- while( p->u.aHash[h] ){
- h++;
- if( h>=BITVEC_NINT ) h = 0;
- }
- p->u.aHash[h] = aiValues[j];
+ if( aiValues[j] && aiValues[j]!=i ){
+ sqlite3BitvecSet(p, aiValues[j]);
}
}
}
@@ -27285,7 +26017,7 @@ SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i){
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
if( p==0 ) return;
if( p->iDivisor ){
- unsigned int i;
+ int i;
for(i=0; i<BITVEC_NPTR; i++){
sqlite3BitvecDestroy(p->u.apSub[i]);
}
@@ -27404,1328 +26136,6 @@ bitvec_end:
#endif /* SQLITE_OMIT_BUILTIN_TEST */
/************** End of bitvec.c **********************************************/
-/************** Begin file pcache.c ******************************************/
-/*
-** 2008 August 05
-**
-** 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 implements that page cache.
-**
-** @(#) $Id$
-*/
-
-/*
-** A complete page cache is an instance of this structure.
-*/
-struct PCache {
- PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
- PgHdr *pSynced; /* Last synced page in dirty page list */
- int nRef; /* Number of referenced pages */
- int nMax; /* Configured cache size */
- int nMin; /* Configured minimum cache size */
- int szPage; /* Size of every page in this cache */
- int szExtra; /* Size of extra space for each page */
- int bPurgeable; /* True if pages are on backing store */
- int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
- void *pStress; /* Argument to xStress */
- sqlite3_pcache *pCache; /* Pluggable cache module */
- PgHdr *pPage1;
-};
-
-/*
-** Some of the assert() macros in this code are too expensive to run
-** even during normal debugging. Use them only rarely on long-running
-** tests. Enable the expensive asserts using the
-** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
-*/
-#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
-# define expensive_assert(X) assert(X)
-#else
-# define expensive_assert(X)
-#endif
-
-/********************************** Linked List Management ********************/
-
-#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
-/*
-** Check that the pCache->pSynced variable is set correctly. If it
-** is not, either fail an assert or return zero. Otherwise, return
-** non-zero. This is only used in debugging builds, as follows:
-**
-** expensive_assert( pcacheCheckSynced(pCache) );
-*/
-static int pcacheCheckSynced(PCache *pCache){
- PgHdr *p;
- for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pDirtyPrev){
- assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
- }
- return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
-}
-#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
-
-/*
-** Remove page pPage from the list of dirty pages.
-*/
-static void pcacheRemoveFromDirtyList(PgHdr *pPage){
- PCache *p = pPage->pCache;
-
- assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
- assert( pPage->pDirtyPrev || pPage==p->pDirty );
-
- /* Update the PCache1.pSynced variable if necessary. */
- if( p->pSynced==pPage ){
- PgHdr *pSynced = pPage->pDirtyPrev;
- while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
- pSynced = pSynced->pDirtyPrev;
- }
- p->pSynced = pSynced;
- }
-
- if( pPage->pDirtyNext ){
- pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
- }else{
- assert( pPage==p->pDirtyTail );
- p->pDirtyTail = pPage->pDirtyPrev;
- }
- if( pPage->pDirtyPrev ){
- pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
- }else{
- assert( pPage==p->pDirty );
- p->pDirty = pPage->pDirtyNext;
- }
- pPage->pDirtyNext = 0;
- pPage->pDirtyPrev = 0;
-
- expensive_assert( pcacheCheckSynced(p) );
-}
-
-/*
-** Add page pPage to the head of the dirty list (PCache1.pDirty is set to
-** pPage).
-*/
-static void pcacheAddToDirtyList(PgHdr *pPage){
- PCache *p = pPage->pCache;
-
- assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage );
-
- pPage->pDirtyNext = p->pDirty;
- if( pPage->pDirtyNext ){
- assert( pPage->pDirtyNext->pDirtyPrev==0 );
- pPage->pDirtyNext->pDirtyPrev = pPage;
- }
- p->pDirty = pPage;
- if( !p->pDirtyTail ){
- p->pDirtyTail = pPage;
- }
- if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
- p->pSynced = pPage;
- }
- expensive_assert( pcacheCheckSynced(p) );
-}
-
-/*
-** Wrapper around the pluggable caches xUnpin method. If the cache is
-** being used for an in-memory database, this function is a no-op.
-*/
-static void pcacheUnpin(PgHdr *p){
- PCache *pCache = p->pCache;
- if( pCache->bPurgeable ){
- if( p->pgno==1 ){
- pCache->pPage1 = 0;
- }
- sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 0);
- }
-}
-
-/*************************************************** General Interfaces ******
-**
-** Initialize and shutdown the page cache subsystem. Neither of these
-** functions are threadsafe.
-*/
-SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
- if( sqlite3GlobalConfig.pcache.xInit==0 ){
- sqlite3PCacheSetDefault();
- }
- return sqlite3GlobalConfig.pcache.xInit(sqlite3GlobalConfig.pcache.pArg);
-}
-SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
- if( sqlite3GlobalConfig.pcache.xShutdown ){
- sqlite3GlobalConfig.pcache.xShutdown(sqlite3GlobalConfig.pcache.pArg);
- }
-}
-
-/*
-** Return the size in bytes of a PCache object.
-*/
-SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
-
-/*
-** Create a new PCache object. Storage space to hold the object
-** has already been allocated and is passed in as the p pointer.
-** The caller discovers how much space needs to be allocated by
-** calling sqlite3PcacheSize().
-*/
-SQLITE_PRIVATE void sqlite3PcacheOpen(
- int szPage, /* Size of every page */
- int szExtra, /* Extra space associated with each page */
- int bPurgeable, /* True if pages are on backing store */
- int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
- void *pStress, /* Argument to xStress */
- PCache *p /* Preallocated space for the PCache */
-){
- memset(p, 0, sizeof(PCache));
- p->szPage = szPage;
- p->szExtra = szExtra;
- p->bPurgeable = bPurgeable;
- p->xStress = xStress;
- p->pStress = pStress;
- p->nMax = 100;
- p->nMin = 10;
-}
-
-/*
-** Change the page size for PCache object. The caller must ensure that there
-** are no outstanding page references when this function is called.
-*/
-SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
- assert( pCache->nRef==0 && pCache->pDirty==0 );
- if( pCache->pCache ){
- sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
- pCache->pCache = 0;
- }
- pCache->szPage = szPage;
-}
-
-/*
-** Try to obtain a page from the cache.
-*/
-SQLITE_PRIVATE int sqlite3PcacheFetch(
- PCache *pCache, /* Obtain the page from this cache */
- Pgno pgno, /* Page number to obtain */
- int createFlag, /* If true, create page if it does not exist already */
- PgHdr **ppPage /* Write the page here */
-){
- PgHdr *pPage = 0;
- int eCreate;
-
- assert( pCache!=0 );
- assert( pgno>0 );
-
- /* If the pluggable cache (sqlite3_pcache*) has not been allocated,
- ** allocate it now.
- */
- if( !pCache->pCache && createFlag ){
- sqlite3_pcache *p;
- int nByte;
- nByte = pCache->szPage + pCache->szExtra + sizeof(PgHdr);
- p = sqlite3GlobalConfig.pcache.xCreate(nByte, pCache->bPurgeable);
- if( !p ){
- return SQLITE_NOMEM;
- }
- sqlite3GlobalConfig.pcache.xCachesize(p, pCache->nMax);
- pCache->pCache = p;
- }
-
- eCreate = createFlag ? 1 : 0;
- if( eCreate && (!pCache->bPurgeable || !pCache->pDirty) ){
- eCreate = 2;
- }
- if( pCache->pCache ){
- pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, eCreate);
- }
-
- if( !pPage && eCreate==1 ){
- PgHdr *pPg;
-
- /* Find a dirty page to write-out and recycle. First try to find a
- ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
- ** cleared), but if that is not possible settle for any other
- ** unreferenced dirty page.
- */
- expensive_assert( pcacheCheckSynced(pCache) );
- for(pPg=pCache->pSynced;
- pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
- pPg=pPg->pDirtyPrev
- );
- if( !pPg ){
- for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
- }
- if( pPg ){
- int rc;
- rc = pCache->xStress(pCache->pStress, pPg);
- if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
- return rc;
- }
- }
-
- pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2);
- }
-
- if( pPage ){
- if( 0==pPage->nRef ){
- pCache->nRef++;
- }
- pPage->nRef++;
- pPage->pData = (void*)&pPage[1];
- pPage->pExtra = (void*)&((char*)pPage->pData)[pCache->szPage];
- pPage->pCache = pCache;
- pPage->pgno = pgno;
- if( pgno==1 ){
- pCache->pPage1 = pPage;
- }
- }
- *ppPage = pPage;
- return (pPage==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK;
-}
-
-/*
-** Decrement the reference count on a page. If the page is clean and the
-** reference count drops to 0, then it is made elible for recycling.
-*/
-SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){
- assert( p->nRef>0 );
- p->nRef--;
- if( p->nRef==0 ){
- PCache *pCache = p->pCache;
- pCache->nRef--;
- if( (p->flags&PGHDR_DIRTY)==0 ){
- pcacheUnpin(p);
- }else{
- /* Move the page to the head of the dirty list. */
- pcacheRemoveFromDirtyList(p);
- pcacheAddToDirtyList(p);
- }
- }
-}
-
-/*
-** Increase the reference count of a supplied page by 1.
-*/
-SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
- assert(p->nRef>0);
- p->nRef++;
-}
-
-/*
-** Drop a page from the cache. There must be exactly one reference to the
-** page. This function deletes that reference, so after it returns the
-** page pointed to by p is invalid.
-*/
-SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
- PCache *pCache;
- assert( p->nRef==1 );
- if( p->flags&PGHDR_DIRTY ){
- pcacheRemoveFromDirtyList(p);
- }
- pCache = p->pCache;
- pCache->nRef--;
- if( p->pgno==1 ){
- pCache->pPage1 = 0;
- }
- sqlite3GlobalConfig.pcache.xUnpin(pCache->pCache, p, 1);
-}
-
-/*
-** Make sure the page is marked as dirty. If it isn't dirty already,
-** make it so.
-*/
-SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
- PCache *pCache;
- p->flags &= ~PGHDR_DONT_WRITE;
- assert( p->nRef>0 );
- if( 0==(p->flags & PGHDR_DIRTY) ){
- pCache = p->pCache;
- p->flags |= PGHDR_DIRTY;
- pcacheAddToDirtyList( p);
- }
-}
-
-/*
-** Make sure the page is marked as clean. If it isn't clean already,
-** make it so.
-*/
-SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
- if( (p->flags & PGHDR_DIRTY) ){
- pcacheRemoveFromDirtyList(p);
- p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC);
- if( p->nRef==0 ){
- pcacheUnpin(p);
- }
- }
-}
-
-/*
-** Make every page in the cache clean.
-*/
-SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
- PgHdr *p;
- while( (p = pCache->pDirty)!=0 ){
- sqlite3PcacheMakeClean(p);
- }
-}
-
-/*
-** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
-*/
-SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
- PgHdr *p;
- for(p=pCache->pDirty; p; p=p->pDirtyNext){
- p->flags &= ~PGHDR_NEED_SYNC;
- }
- pCache->pSynced = pCache->pDirtyTail;
-}
-
-/*
-** Change the page number of page p to newPgno.
-*/
-SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
- PCache *pCache = p->pCache;
- assert( p->nRef>0 );
- assert( newPgno>0 );
- sqlite3GlobalConfig.pcache.xRekey(pCache->pCache, p, p->pgno, newPgno);
- p->pgno = newPgno;
- if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
- pcacheRemoveFromDirtyList(p);
- pcacheAddToDirtyList(p);
- }
-}
-
-/*
-** Drop every cache entry whose page number is greater than "pgno". The
-** caller must ensure that there are no outstanding references to any pages
-** other than page 1 with a page number greater than pgno.
-**
-** If there is a reference to page 1 and the pgno parameter passed to this
-** function is 0, then the data area associated with page 1 is zeroed, but
-** the page object is not dropped.
-*/
-SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
- if( pCache->pCache ){
- PgHdr *p;
- PgHdr *pNext;
- for(p=pCache->pDirty; p; p=pNext){
- pNext = p->pDirtyNext;
- if( p->pgno>pgno ){
- assert( p->flags&PGHDR_DIRTY );
- sqlite3PcacheMakeClean(p);
- }
- }
- if( pgno==0 && pCache->pPage1 ){
- memset(pCache->pPage1->pData, 0, pCache->szPage);
- pgno = 1;
- }
- sqlite3GlobalConfig.pcache.xTruncate(pCache->pCache, pgno+1);
- }
-}
-
-/*
-** Close a cache.
-*/
-SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
- if( pCache->pCache ){
- sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache);
- }
-}
-
-/*
-** Discard the contents of the cache.
-*/
-SQLITE_PRIVATE int sqlite3PcacheClear(PCache *pCache){
- sqlite3PcacheTruncate(pCache, 0);
- return SQLITE_OK;
-}
-
-/*
-** Merge two lists of pages connected by pDirty and in pgno order.
-** Do not both fixing the pDirtyPrev pointers.
-*/
-static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
- PgHdr result, *pTail;
- pTail = &result;
- while( pA && pB ){
- if( pA->pgno<pB->pgno ){
- pTail->pDirty = pA;
- pTail = pA;
- pA = pA->pDirty;
- }else{
- pTail->pDirty = pB;
- pTail = pB;
- pB = pB->pDirty;
- }
- }
- if( pA ){
- pTail->pDirty = pA;
- }else if( pB ){
- pTail->pDirty = pB;
- }else{
- pTail->pDirty = 0;
- }
- return result.pDirty;
-}
-
-/*
-** Sort the list of pages in accending order by pgno. Pages are
-** connected by pDirty pointers. The pDirtyPrev pointers are
-** corrupted by this sort.
-*/
-#define N_SORT_BUCKET_ALLOC 25
-#define N_SORT_BUCKET 25
-#ifdef SQLITE_TEST
- int sqlite3_pager_n_sort_bucket = 0;
- #undef N_SORT_BUCKET
- #define N_SORT_BUCKET \
- (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
-#endif
-static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
- PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
- int i;
- memset(a, 0, sizeof(a));
- while( pIn ){
- p = pIn;
- pIn = p->pDirty;
- p->pDirty = 0;
- for(i=0; i<N_SORT_BUCKET-1; i++){
- if( a[i]==0 ){
- a[i] = p;
- break;
- }else{
- p = pcacheMergeDirtyList(a[i], p);
- a[i] = 0;
- }
- }
- if( i==N_SORT_BUCKET-1 ){
- /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET)
- ** elements in the input list. This is possible, but impractical.
- ** Testing this line is the point of global variable
- ** sqlite3_pager_n_sort_bucket.
- */
- a[i] = pcacheMergeDirtyList(a[i], p);
- }
- }
- p = a[0];
- for(i=1; i<N_SORT_BUCKET; i++){
- p = pcacheMergeDirtyList(p, a[i]);
- }
- return p;
-}
-
-/*
-** Return a list of all dirty pages in the cache, sorted by page number.
-*/
-SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
- PgHdr *p;
- for(p=pCache->pDirty; p; p=p->pDirtyNext){
- p->pDirty = p->pDirtyNext;
- }
- return pcacheSortDirtyList(pCache->pDirty);
-}
-
-/*
-** Return the total number of referenced pages held by the cache.
-*/
-SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
- return pCache->nRef;
-}
-
-/*
-** Return the number of references to the page supplied as an argument.
-*/
-SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
- return p->nRef;
-}
-
-/*
-** Return the total number of pages in the cache.
-*/
-SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
- int nPage = 0;
- if( pCache->pCache ){
- nPage = sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache);
- }
- return nPage;
-}
-
-#ifdef SQLITE_TEST
-/*
-** Get the suggested cache-size value.
-*/
-SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
- return pCache->nMax;
-}
-#endif
-
-/*
-** Set the suggested cache-size value.
-*/
-SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
- pCache->nMax = mxPage;
- if( pCache->pCache ){
- sqlite3GlobalConfig.pcache.xCachesize(pCache->pCache, mxPage);
- }
-}
-
-#ifdef SQLITE_CHECK_PAGES
-/*
-** For all dirty pages currently in the cache, invoke the specified
-** callback. This is only used if the SQLITE_CHECK_PAGES macro is
-** defined.
-*/
-SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
- PgHdr *pDirty;
- for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
- xIter(pDirty);
- }
-}
-#endif
-
-
-/************** End of pcache.c **********************************************/
-/************** Begin file pcache1.c *****************************************/
-/*
-** 2008 November 05
-**
-** 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 implements the default page cache implementation (the
-** sqlite3_pcache interface). It also contains part of the implementation
-** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
-** If the default page cache implementation is overriden, then neither of
-** these two features are available.
-**
-** @(#) $Id$
-*/
-
-
-typedef struct PCache1 PCache1;
-typedef struct PgHdr1 PgHdr1;
-typedef struct PgFreeslot PgFreeslot;
-
-/* Pointers to structures of this type are cast and returned as
-** opaque sqlite3_pcache* handles
-*/
-struct PCache1 {
- /* Cache configuration parameters. Page size (szPage) and the purgeable
- ** flag (bPurgeable) are set when the cache is created. nMax may be
- ** modified at any time by a call to the pcache1CacheSize() method.
- ** The global mutex must be held when accessing nMax.
- */
- int szPage; /* Size of allocated pages in bytes */
- int bPurgeable; /* True if cache is purgeable */
- unsigned int nMin; /* Minimum number of pages reserved */
- unsigned int nMax; /* Configured "cache_size" value */
-
- /* Hash table of all pages. The following variables may only be accessed
- ** when the accessor is holding the global mutex (see pcache1EnterMutex()
- ** and pcache1LeaveMutex()).
- */
- unsigned int nRecyclable; /* Number of pages in the LRU list */
- unsigned int nPage; /* Total number of pages in apHash */
- unsigned int nHash; /* Number of slots in apHash[] */
- PgHdr1 **apHash; /* Hash table for fast lookup by key */
-};
-
-/*
-** Each cache entry is represented by an instance of the following
-** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
-** directly after the structure in memory (see the PGHDR1_TO_PAGE()
-** macro below).
-*/
-struct PgHdr1 {
- unsigned int iKey; /* Key value (page number) */
- PgHdr1 *pNext; /* Next in hash table chain */
- PCache1 *pCache; /* Cache that currently owns this page */
- PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
- PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
-};
-
-/*
-** Free slots in the allocator used to divide up the buffer provided using
-** the SQLITE_CONFIG_PAGECACHE mechanism.
-*/
-struct PgFreeslot {
- PgFreeslot *pNext; /* Next free slot */
-};
-
-/*
-** Global data used by this cache.
-*/
-static SQLITE_WSD struct PCacheGlobal {
- sqlite3_mutex *mutex; /* static mutex MUTEX_STATIC_LRU */
-
- int nMaxPage; /* Sum of nMaxPage for purgeable caches */
- int nMinPage; /* Sum of nMinPage for purgeable caches */
- int nCurrentPage; /* Number of purgeable pages allocated */
- PgHdr1 *pLruHead, *pLruTail; /* LRU list of unpinned pages */
-
- /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
- int szSlot; /* Size of each free slot */
- void *pStart, *pEnd; /* Bounds of pagecache malloc range */
- PgFreeslot *pFree; /* Free page blocks */
-} pcache1_g;
-
-/*
-** All code in this file should access the global structure above via the
-** alias "pcache1". This ensures that the WSD emulation is used when
-** compiling for systems that do not support real WSD.
-*/
-#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
-
-/*
-** When a PgHdr1 structure is allocated, the associated PCache1.szPage
-** bytes of data are located directly after it in memory (i.e. the total
-** size of the allocation is sizeof(PgHdr1)+PCache1.szPage byte). The
-** PGHDR1_TO_PAGE() macro takes a pointer to a PgHdr1 structure as
-** an argument and returns a pointer to the associated block of szPage
-** bytes. The PAGE_TO_PGHDR1() macro does the opposite: its argument is
-** a pointer to a block of szPage bytes of data and the return value is
-** a pointer to the associated PgHdr1 structure.
-**
-** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(X))==X );
-*/
-#define PGHDR1_TO_PAGE(p) (void *)(&((unsigned char *)p)[sizeof(PgHdr1)])
-#define PAGE_TO_PGHDR1(p) (PgHdr1 *)(&((unsigned char *)p)[-1*sizeof(PgHdr1)])
-
-/*
-** Macros to enter and leave the global LRU mutex.
-*/
-#define pcache1EnterMutex() sqlite3_mutex_enter(pcache1.mutex)
-#define pcache1LeaveMutex() sqlite3_mutex_leave(pcache1.mutex)
-
-/******************************************************************************/
-/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
-
-/*
-** This function is called during initialization if a static buffer is
-** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
-** verb to sqlite3_config(). Parameter pBuf points to an allocation large
-** enough to contain 'n' buffers of 'sz' bytes each.
-*/
-SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
- PgFreeslot *p;
- sz &= ~7;
- pcache1.szSlot = sz;
- pcache1.pStart = pBuf;
- pcache1.pFree = 0;
- while( n-- ){
- p = (PgFreeslot*)pBuf;
- p->pNext = pcache1.pFree;
- pcache1.pFree = p;
- pBuf = (void*)&((char*)pBuf)[sz];
- }
- pcache1.pEnd = pBuf;
-}
-
-/*
-** Malloc function used within this file to allocate space from the buffer
-** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
-** such buffer exists or there is no space left in it, this function falls
-** back to sqlite3Malloc().
-*/
-static void *pcache1Alloc(int nByte){
- void *p;
- assert( sqlite3_mutex_held(pcache1.mutex) );
- if( nByte<=pcache1.szSlot && pcache1.pFree ){
- p = (PgHdr1 *)pcache1.pFree;
- pcache1.pFree = pcache1.pFree->pNext;
- sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
- }else{
-
- /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
- ** global pcache mutex and unlock the pager-cache object pCache. This is
- ** so that if the attempt to allocate a new buffer causes the the
- ** configured soft-heap-limit to be breached, it will be possible to
- ** reclaim memory from this pager-cache.
- */
- pcache1LeaveMutex();
- p = sqlite3Malloc(nByte);
- pcache1EnterMutex();
- if( p ){
- int sz = sqlite3MallocSize(p);
- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
- }
- }
- return p;
-}
-
-/*
-** Free an allocated buffer obtained from pcache1Alloc().
-*/
-static void pcache1Free(void *p){
- assert( sqlite3_mutex_held(pcache1.mutex) );
- if( p==0 ) return;
- if( p>=pcache1.pStart && p<pcache1.pEnd ){
- PgFreeslot *pSlot;
- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
- pSlot = (PgFreeslot*)p;
- pSlot->pNext = pcache1.pFree;
- pcache1.pFree = pSlot;
- }else{
- int iSize = sqlite3MallocSize(p);
- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
- sqlite3_free(p);
- }
-}
-
-/*
-** Allocate a new page object initially associated with cache pCache.
-*/
-static PgHdr1 *pcache1AllocPage(PCache1 *pCache){
- int nByte = sizeof(PgHdr1) + pCache->szPage;
- PgHdr1 *p = (PgHdr1 *)pcache1Alloc(nByte);
- if( p ){
- memset(p, 0, nByte);
- if( pCache->bPurgeable ){
- pcache1.nCurrentPage++;
- }
- }
- return p;
-}
-
-/*
-** Free a page object allocated by pcache1AllocPage().
-*/
-static void pcache1FreePage(PgHdr1 *p){
- if( p ){
- if( p->pCache->bPurgeable ){
- pcache1.nCurrentPage--;
- }
- pcache1Free(p);
- }
-}
-
-/*
-** Malloc function used by SQLite to obtain space from the buffer configured
-** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
-** exists, this function falls back to sqlite3Malloc().
-*/
-SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
- void *p;
- pcache1EnterMutex();
- p = pcache1Alloc(sz);
- pcache1LeaveMutex();
- return p;
-}
-
-/*
-** Free an allocated buffer obtained from sqlite3PageMalloc().
-*/
-SQLITE_PRIVATE void sqlite3PageFree(void *p){
- pcache1EnterMutex();
- pcache1Free(p);
- pcache1LeaveMutex();
-}
-
-/******************************************************************************/
-/******** General Implementation Functions ************************************/
-
-/*
-** This function is used to resize the hash table used by the cache passed
-** as the first argument.
-**
-** The global mutex must be held when this function is called.
-*/
-static int pcache1ResizeHash(PCache1 *p){
- PgHdr1 **apNew;
- unsigned int nNew;
- unsigned int i;
-
- assert( sqlite3_mutex_held(pcache1.mutex) );
-
- nNew = p->nHash*2;
- if( nNew<256 ){
- nNew = 256;
- }
-
- pcache1LeaveMutex();
- apNew = (PgHdr1 **)sqlite3_malloc(sizeof(PgHdr1 *)*nNew);
- pcache1EnterMutex();
- if( apNew ){
- memset(apNew, 0, sizeof(PgHdr1 *)*nNew);
- for(i=0; i<p->nHash; i++){
- PgHdr1 *pPage;
- PgHdr1 *pNext = p->apHash[i];
- while( (pPage = pNext) ){
- unsigned int h = pPage->iKey % nNew;
- pNext = pPage->pNext;
- pPage->pNext = apNew[h];
- apNew[h] = pPage;
- }
- }
- sqlite3_free(p->apHash);
- p->apHash = apNew;
- p->nHash = nNew;
- }
-
- return (p->apHash ? SQLITE_OK : SQLITE_NOMEM);
-}
-
-/*
-** This function is used internally to remove the page pPage from the
-** global LRU list, if is part of it. If pPage is not part of the global
-** LRU list, then this function is a no-op.
-**
-** The global mutex must be held when this function is called.
-*/
-static void pcache1PinPage(PgHdr1 *pPage){
- assert( sqlite3_mutex_held(pcache1.mutex) );
- if( pPage && (pPage->pLruNext || pPage==pcache1.pLruTail) ){
- if( pPage->pLruPrev ){
- pPage->pLruPrev->pLruNext = pPage->pLruNext;
- }
- if( pPage->pLruNext ){
- pPage->pLruNext->pLruPrev = pPage->pLruPrev;
- }
- if( pcache1.pLruHead==pPage ){
- pcache1.pLruHead = pPage->pLruNext;
- }
- if( pcache1.pLruTail==pPage ){
- pcache1.pLruTail = pPage->pLruPrev;
- }
- pPage->pLruNext = 0;
- pPage->pLruPrev = 0;
- pPage->pCache->nRecyclable--;
- }
-}
-
-
-/*
-** Remove the page supplied as an argument from the hash table
-** (PCache1.apHash structure) that it is currently stored in.
-**
-** The global mutex must be held when this function is called.
-*/
-static void pcache1RemoveFromHash(PgHdr1 *pPage){
- unsigned int h;
- PCache1 *pCache = pPage->pCache;
- PgHdr1 **pp;
-
- h = pPage->iKey % pCache->nHash;
- for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
- *pp = (*pp)->pNext;
-
- pCache->nPage--;
-}
-
-/*
-** If there are currently more than pcache.nMaxPage pages allocated, try
-** to recycle pages to reduce the number allocated to pcache.nMaxPage.
-*/
-static void pcache1EnforceMaxPage(void){
- assert( sqlite3_mutex_held(pcache1.mutex) );
- while( pcache1.nCurrentPage>pcache1.nMaxPage && pcache1.pLruTail ){
- PgHdr1 *p = pcache1.pLruTail;
- pcache1PinPage(p);
- pcache1RemoveFromHash(p);
- pcache1FreePage(p);
- }
-}
-
-/*
-** Discard all pages from cache pCache with a page number (key value)
-** greater than or equal to iLimit. Any pinned pages that meet this
-** criteria are unpinned before they are discarded.
-**
-** The global mutex must be held when this function is called.
-*/
-static void pcache1TruncateUnsafe(
- PCache1 *pCache,
- unsigned int iLimit
-){
- unsigned int h;
- assert( sqlite3_mutex_held(pcache1.mutex) );
- for(h=0; h<pCache->nHash; h++){
- PgHdr1 **pp = &pCache->apHash[h];
- PgHdr1 *pPage;
- while( (pPage = *pp) ){
- if( pPage->iKey>=iLimit ){
- pcache1PinPage(pPage);
- *pp = pPage->pNext;
- pcache1FreePage(pPage);
- }else{
- pp = &pPage->pNext;
- }
- }
- }
-}
-
-/******************************************************************************/
-/******** sqlite3_pcache Methods **********************************************/
-
-/*
-** Implementation of the sqlite3_pcache.xInit method.
-*/
-static int pcache1Init(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- memset(&pcache1, 0, sizeof(pcache1));
- if( sqlite3GlobalConfig.bCoreMutex ){
- pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
- }
- return SQLITE_OK;
-}
-
-/*
-** Implementation of the sqlite3_pcache.xShutdown method.
-*/
-static void pcache1Shutdown(void *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- /* no-op */
-}
-
-/*
-** Implementation of the sqlite3_pcache.xCreate method.
-**
-** Allocate a new cache.
-*/
-static sqlite3_pcache *pcache1Create(int szPage, int bPurgeable){
- PCache1 *pCache;
-
- pCache = (PCache1 *)sqlite3_malloc(sizeof(PCache1));
- if( pCache ){
- memset(pCache, 0, sizeof(PCache1));
- pCache->szPage = szPage;
- pCache->bPurgeable = (bPurgeable ? 1 : 0);
- if( bPurgeable ){
- pCache->nMin = 10;
- pcache1EnterMutex();
- pcache1.nMinPage += pCache->nMin;
- pcache1LeaveMutex();
- }
- }
- return (sqlite3_pcache *)pCache;
-}
-
-/*
-** Implementation of the sqlite3_pcache.xCachesize method.
-**
-** Configure the cache_size limit for a cache.
-*/
-static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
- PCache1 *pCache = (PCache1 *)p;
- if( pCache->bPurgeable ){
- pcache1EnterMutex();
- pcache1.nMaxPage += (nMax - pCache->nMax);
- pCache->nMax = nMax;
- pcache1EnforceMaxPage();
- pcache1LeaveMutex();
- }
-}
-
-/*
-** Implementation of the sqlite3_pcache.xPagecount method.
-*/
-static int pcache1Pagecount(sqlite3_pcache *p){
- int n;
- pcache1EnterMutex();
- n = ((PCache1 *)p)->nPage;
- pcache1LeaveMutex();
- return n;
-}
-
-/*
-** Implementation of the sqlite3_pcache.xFetch method.
-**
-** Fetch a page by key value.
-**
-** Whether or not a new page may be allocated by this function depends on
-** the value of the createFlag argument.
-**
-** There are three different approaches to obtaining space for a page,
-** depending on the value of parameter createFlag (which may be 0, 1 or 2).
-**
-** 1. Regardless of the value of createFlag, the cache is searched for a
-** copy of the requested page. If one is found, it is returned.
-**
-** 2. If createFlag==0 and the page is not already in the cache, NULL is
-** returned.
-**
-** 3. If createFlag is 1, the cache is marked as purgeable and the page is
-** not already in the cache, and if either of the following are true,
-** return NULL:
-**
-** (a) the number of pages pinned by the cache is greater than
-** PCache1.nMax, or
-** (b) the number of pages pinned by the cache is greater than
-** the sum of nMax for all purgeable caches, less the sum of
-** nMin for all other purgeable caches.
-**
-** 4. If none of the first three conditions apply and the cache is marked
-** as purgeable, and if one of the following is true:
-**
-** (a) The number of pages allocated for the cache is already
-** PCache1.nMax, or
-**
-** (b) The number of pages allocated for all purgeable caches is
-** already equal to or greater than the sum of nMax for all
-** purgeable caches,
-**
-** then attempt to recycle a page from the LRU list. If it is the right
-** size, return the recycled buffer. Otherwise, free the buffer and
-** proceed to step 5.
-**
-** 5. Otherwise, allocate and return a new page buffer.
-*/
-static void *pcache1Fetch(sqlite3_pcache *p, unsigned int iKey, int createFlag){
- unsigned int nPinned;
- PCache1 *pCache = (PCache1 *)p;
- PgHdr1 *pPage = 0;
-
- pcache1EnterMutex();
- if( createFlag==1 ) sqlite3BeginBenignMalloc();
-
- /* Search the hash table for an existing entry. */
- if( pCache->nHash>0 ){
- unsigned int h = iKey % pCache->nHash;
- for(pPage=pCache->apHash[h]; pPage&&pPage->iKey!=iKey; pPage=pPage->pNext);
- }
-
- if( pPage || createFlag==0 ){
- pcache1PinPage(pPage);
- goto fetch_out;
- }
-
- /* Step 3 of header comment. */
- nPinned = pCache->nPage - pCache->nRecyclable;
- if( createFlag==1 && pCache->bPurgeable && (
- nPinned>=(pcache1.nMaxPage+pCache->nMin-pcache1.nMinPage)
- || nPinned>=(pCache->nMax)
- )){
- goto fetch_out;
- }
-
- if( pCache->nPage>=pCache->nHash && pcache1ResizeHash(pCache) ){
- goto fetch_out;
- }
-
- /* Step 4. Try to recycle a page buffer if appropriate. */
- if( pCache->bPurgeable && pcache1.pLruTail && (
- pCache->nPage>=pCache->nMax-1 || pcache1.nCurrentPage>=pcache1.nMaxPage
- )){
- pPage = pcache1.pLruTail;
- pcache1RemoveFromHash(pPage);
- pcache1PinPage(pPage);
- if( pPage->pCache->szPage!=pCache->szPage ){
- pcache1FreePage(pPage);
- pPage = 0;
- }else{
- pcache1.nCurrentPage -= (pPage->pCache->bPurgeable - pCache->bPurgeable);
- }
- }
-
- /* Step 5. If a usable page buffer has still not been found,
- ** attempt to allocate a new one.
- */
- if( !pPage ){
- pPage = pcache1AllocPage(pCache);
- }
-
- if( pPage ){
- unsigned int h = iKey % pCache->nHash;
- memset(pPage, 0, pCache->szPage + sizeof(PgHdr1));
- pCache->nPage++;
- pPage->iKey = iKey;
- pPage->pNext = pCache->apHash[h];
- pPage->pCache = pCache;
- pCache->apHash[h] = pPage;
- }
-
-fetch_out:
- if( createFlag==1 ) sqlite3EndBenignMalloc();
- pcache1LeaveMutex();
- return (pPage ? PGHDR1_TO_PAGE(pPage) : 0);
-}
-
-
-/*
-** Implementation of the sqlite3_pcache.xUnpin method.
-**
-** Mark a page as unpinned (eligible for asynchronous recycling).
-*/
-static void pcache1Unpin(sqlite3_pcache *p, void *pPg, int reuseUnlikely){
- PCache1 *pCache = (PCache1 *)p;
- PgHdr1 *pPage = PAGE_TO_PGHDR1(pPg);
-
- pcache1EnterMutex();
-
- /* It is an error to call this function if the page is already
- ** part of the global LRU list.
- */
- assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
- assert( pcache1.pLruHead!=pPage && pcache1.pLruTail!=pPage );
-
- if( reuseUnlikely || pcache1.nCurrentPage>pcache1.nMaxPage ){
- pcache1RemoveFromHash(pPage);
- pcache1FreePage(pPage);
- }else{
- /* Add the page to the global LRU list. Normally, the page is added to
- ** the head of the list (last page to be recycled). However, if the
- ** reuseUnlikely flag passed to this function is true, the page is added
- ** to the tail of the list (first page to be recycled).
- */
- if( pcache1.pLruHead ){
- pcache1.pLruHead->pLruPrev = pPage;
- pPage->pLruNext = pcache1.pLruHead;
- pcache1.pLruHead = pPage;
- }else{
- pcache1.pLruTail = pPage;
- pcache1.pLruHead = pPage;
- }
- pCache->nRecyclable++;
- }
-
- pcache1LeaveMutex();
-}
-
-/*
-** Implementation of the sqlite3_pcache.xRekey method.
-*/
-static void pcache1Rekey(
- sqlite3_pcache *p,
- void *pPg,
- unsigned int iOld,
- unsigned int iNew
-){
- PCache1 *pCache = (PCache1 *)p;
- PgHdr1 *pPage = PAGE_TO_PGHDR1(pPg);
- PgHdr1 **pp;
- unsigned int h;
- assert( pPage->iKey==iOld );
-
- pcache1EnterMutex();
-
- h = iOld%pCache->nHash;
- pp = &pCache->apHash[h];
- while( (*pp)!=pPage ){
- pp = &(*pp)->pNext;
- }
- *pp = pPage->pNext;
-
- h = iNew%pCache->nHash;
- pPage->iKey = iNew;
- pPage->pNext = pCache->apHash[h];
- pCache->apHash[h] = pPage;
-
- pcache1LeaveMutex();
-}
-
-/*
-** Implementation of the sqlite3_pcache.xTruncate method.
-**
-** Discard all unpinned pages in the cache with a page number equal to
-** or greater than parameter iLimit. Any pinned pages with a page number
-** equal to or greater than iLimit are implicitly unpinned.
-*/
-static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
- PCache1 *pCache = (PCache1 *)p;
- pcache1EnterMutex();
- pcache1TruncateUnsafe(pCache, iLimit);
- pcache1LeaveMutex();
-}
-
-/*
-** Implementation of the sqlite3_pcache.xDestroy method.
-**
-** Destroy a cache allocated using pcache1Create().
-*/
-static void pcache1Destroy(sqlite3_pcache *p){
- PCache1 *pCache = (PCache1 *)p;
- pcache1EnterMutex();
- pcache1TruncateUnsafe(pCache, 0);
- pcache1.nMaxPage -= pCache->nMax;
- pcache1.nMinPage -= pCache->nMin;
- pcache1EnforceMaxPage();
- pcache1LeaveMutex();
- sqlite3_free(pCache->apHash);
- sqlite3_free(pCache);
-}
-
-/*
-** This function is called during initialization (sqlite3_initialize()) to
-** install the default pluggable cache module, assuming the user has not
-** already provided an alternative.
-*/
-SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
- static sqlite3_pcache_methods defaultMethods = {
- 0, /* pArg */
- pcache1Init, /* xInit */
- pcache1Shutdown, /* xShutdown */
- pcache1Create, /* xCreate */
- pcache1Cachesize, /* xCachesize */
- pcache1Pagecount, /* xPagecount */
- pcache1Fetch, /* xFetch */
- pcache1Unpin, /* xUnpin */
- pcache1Rekey, /* xRekey */
- pcache1Truncate, /* xTruncate */
- pcache1Destroy /* xDestroy */
- };
- sqlite3_config(SQLITE_CONFIG_PCACHE, &defaultMethods);
-}
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-/*
-** This function is called to free superfluous dynamically allocated memory
-** held by the pager system. Memory in use by any SQLite pager allocated
-** by the current thread may be sqlite3_free()ed.
-**
-** nReq is the number of bytes of memory required. Once this much has
-** been released, the function returns. The return value is the total number
-** of bytes of memory released.
-*/
-SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
- int nFree = 0;
- if( pcache1.pStart==0 ){
- PgHdr1 *p;
- pcache1EnterMutex();
- while( (nReq<0 || nFree<nReq) && (p=pcache1.pLruTail) ){
- nFree += sqlite3MallocSize(p);
- pcache1PinPage(p);
- pcache1RemoveFromHash(p);
- pcache1FreePage(p);
- }
- pcache1LeaveMutex();
- }
- return nFree;
-}
-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
-
-#ifdef SQLITE_TEST
-/*
-** This function is used by test procedures to inspect the internal state
-** of the global cache.
-*/
-SQLITE_PRIVATE void sqlite3PcacheStats(
- int *pnCurrent, /* OUT: Total number of pages cached */
- int *pnMax, /* OUT: Global maximum cache size */
- int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
- int *pnRecyclable /* OUT: Total number of pages available for recycling */
-){
- PgHdr1 *p;
- int nRecyclable = 0;
- for(p=pcache1.pLruHead; p; p=p->pLruNext){
- nRecyclable++;
- }
- *pnCurrent = pcache1.nCurrentPage;
- *pnMax = pcache1.nMaxPage;
- *pnMin = pcache1.nMinPage;
- *pnRecyclable = nRecyclable;
-}
-#endif
-
-/************** End of pcache1.c *********************************************/
/************** Begin file pager.c *******************************************/
/*
** 2001 September 15
@@ -28857,6 +26267,173 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
*/
#define FORCE_ALIGNMENT(X) (((X)+7)&~7)
+typedef struct PgHdr PgHdr;
+
+/*
+** Each pager stores all currently unreferenced pages in a list sorted
+** in least-recently-used (LRU) order (i.e. the first item on the list has
+** not been referenced in a long time, the last item has been recently
+** used). An instance of this structure is included as part of each
+** pager structure for this purpose (variable Pager.lru).
+**
+** Additionally, if memory-management is enabled, all unreferenced pages
+** are stored in a global LRU list (global variable sqlite3LruPageList).
+**
+** In both cases, the PagerLruList.pFirstSynced variable points to
+** the first page in the corresponding list that does not require an
+** fsync() operation before its memory can be reclaimed. If no such
+** page exists, PagerLruList.pFirstSynced is set to NULL.
+*/
+typedef struct PagerLruList PagerLruList;
+struct PagerLruList {
+ PgHdr *pFirst; /* First page in LRU list */
+ PgHdr *pLast; /* Last page in LRU list (the most recently used) */
+ PgHdr *pFirstSynced; /* First page in list with PgHdr.needSync==0 */
+};
+
+/*
+** The following structure contains the next and previous pointers used
+** to link a PgHdr structure into a PagerLruList linked list.
+*/
+typedef struct PagerLruLink PagerLruLink;
+struct PagerLruLink {
+ PgHdr *pNext;
+ PgHdr *pPrev;
+};
+
+/*
+** Each in-memory image of a page begins with the following header.
+** This header is only visible to this pager module. The client
+** code that calls pager sees only the data that follows the header.
+**
+** Client code should call sqlite3PagerWrite() on a page prior to making
+** any modifications to that page. The first time sqlite3PagerWrite()
+** is called, the original page contents are written into the rollback
+** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once
+** the journal page has made it onto the disk surface, PgHdr.needSync
+** is cleared. The modified page cannot be written back into the original
+** database file until the journal pages has been synced to disk and the
+** PgHdr.needSync has been cleared.
+**
+** The PgHdr.dirty flag is set when sqlite3PagerWrite() is called and
+** is cleared again when the page content is written back to the original
+** database file.
+**
+** Details of important structure elements:
+**
+** needSync
+**
+** If this is true, this means that it is not safe to write the page
+** content to the database because the original content needed
+** for rollback has not by synced to the main rollback journal.
+** The original content may have been written to the rollback journal
+** but it has not yet been synced. So we cannot write to the database
+** file because power failure might cause the page in the journal file
+** to never reach the disk. It is as if the write to the journal file
+** does not occur until the journal file is synced.
+**
+** This flag is false if the page content exactly matches what
+** currently exists in the database file. The needSync flag is also
+** false if the original content has been written to the main rollback
+** journal and synced. If the page represents a new page that has
+** been added onto the end of the database during the current
+** transaction, the needSync flag is true until the original database
+** size in the journal header has been synced to disk.
+**
+** inJournal
+**
+** This is true if the original page has been written into the main
+** rollback journal. This is always false for new pages added to
+** the end of the database file during the current transaction.
+** And this flag says nothing about whether or not the journal
+** has been synced to disk. For pages that are in the original
+** database file, the following expression should always be true:
+**
+** inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno)
+**
+** The pPager->pInJournal object is only valid for the original
+** pages of the database, not new pages that are added to the end
+** of the database, so obviously the above expression cannot be
+** valid for new pages. For new pages inJournal is always 0.
+**
+** dirty
+**
+** When true, this means that the content of the page has been
+** modified and needs to be written back to the database file.
+** If false, it means that either the content of the page is
+** unchanged or else the content is unimportant and we do not
+** care whether or not it is preserved.
+**
+** alwaysRollback
+**
+** This means that the sqlite3PagerDontRollback() API should be
+** ignored for this page. The DontRollback() API attempts to say
+** that the content of the page on disk is unimportant (it is an
+** unused page on the freelist) so that it is unnecessary to
+** rollback changes to this page because the content of the page
+** can change without changing the meaning of the database. This
+** flag overrides any DontRollback() attempt. This flag is set
+** when a page that originally contained valid data is added to
+** the freelist. Later in the same transaction, this page might
+** be pulled from the freelist and reused for something different
+** and at that point the DontRollback() API will be called because
+** pages taken from the freelist do not need to be protected by
+** the rollback journal. But this flag says that the page was
+** not originally part of the freelist so that it still needs to
+** be rolled back in spite of any subsequent DontRollback() calls.
+**
+** needRead
+**
+** This flag means (when true) that the content of the page has
+** not yet been loaded from disk. The in-memory content is just
+** garbage. (Actually, we zero the content, but you should not
+** make any assumptions about the content nevertheless.) If the
+** content is needed in the future, it should be read from the
+** original database file.
+*/
+struct PgHdr {
+ Pager *pPager; /* The pager to which this page belongs */
+ Pgno pgno; /* The page number for this page */
+ PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */
+ PagerLruLink free; /* Next and previous free pages */
+ PgHdr *pNextAll; /* A list of all pages */
+ u8 inJournal; /* TRUE if has been written to journal */
+ u8 dirty; /* TRUE if we need to write back changes */
+ u8 needSync; /* Sync journal before writing this page */
+ u8 alwaysRollback; /* Disable DontRollback() for this page */
+ u8 needRead; /* Read content if PagerWrite() is called */
+ short int nRef; /* Number of users of this page */
+ PgHdr *pDirty, *pPrevDirty; /* Dirty pages */
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ PgHdr *pPrevAll; /* A list of all pages */
+ PagerLruLink gfree; /* Global list of nRef==0 pages */
+#endif
+#ifdef SQLITE_CHECK_PAGES
+ u32 pageHash;
+#endif
+ void *pData; /* Page data */
+ /* Pager.nExtra bytes of local data appended to this header */
+};
+
+/*
+** For an in-memory only database, some extra information is recorded about
+** each page so that changes can be rolled back. (Journal files are not
+** used for in-memory databases.) The following information is added to
+** the end of every EXTRA block for in-memory databases.
+**
+** This information could have been added directly to the PgHdr structure.
+** But then it would take up an extra 8 bytes of storage on every PgHdr
+** even for disk-based databases. Splitting it out saves 8 bytes. This
+** is only a savings of 0.8% but those percentages add up.
+*/
+typedef struct PgHistory PgHistory;
+struct PgHistory {
+ u8 *pOrig; /* Original page text. Restore to this on a full rollback */
+ u8 *pStmt; /* Text as it was at the beginning of the current statement */
+ PgHdr *pNextStmt, *pPrevStmt; /* List of pages in the statement journal */
+ u8 inStmt; /* TRUE if in the statement subjournal */
+};
+
/*
** A macro used for invoking the codec if there is one
*/
@@ -28869,6 +26446,15 @@ SQLITE_PRIVATE void sqlite3PcacheStats(
#endif
/*
+** Convert a pointer to a PgHdr into a pointer to its data
+** and back again.
+*/
+#define PGHDR_TO_DATA(P) ((P)->pData)
+#define PGHDR_TO_EXTRA(G,P) ((void*)&((G)[1]))
+#define PGHDR_TO_HIST(P,PGR) \
+ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->nExtra])
+
+/*
** A open page cache is an instance of the following structure.
**
** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or
@@ -28904,49 +26490,59 @@ struct Pager {
u8 journalMode; /* On of the PAGER_JOURNALMODE_* values */
u8 dbModified; /* True if there are any changes to the Db */
u8 changeCountDone; /* Set after incrementing the change-counter */
- u8 dbSizeValid; /* Set when dbSize is correct */
u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
int errCode; /* One of several kinds of errors */
- Pgno dbSize; /* Number of pages in the file */
- Pgno origDbSize; /* dbSize before the current change */
- Pgno stmtSize; /* Size of database (in pages) at stmt_begin() */
+ int dbSize; /* Number of pages in the file */
+ int origDbSize; /* dbSize before the current change */
+ int stmtSize; /* Size of database (in pages) at stmt_begin() */
int nRec; /* Number of pages written to the journal */
u32 cksumInit; /* Quasi-random value added to every checksum */
int stmtNRec; /* Number of records in stmt subjournal */
int nExtra; /* Add this many bytes to each in-memory page */
int pageSize; /* Number of bytes in a page */
int nPage; /* Total number of in-memory pages */
+ int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
int mxPage; /* Maximum number of pages to hold in cache */
Pgno mxPgno; /* Maximum allowed size of the database */
Bitvec *pInJournal; /* One bit for each page in the database file */
Bitvec *pInStmt; /* One bit for each page in the database */
- Bitvec *pAlwaysRollback; /* One bit for each page marked always-rollback */
char *zFilename; /* Name of the database file */
char *zJournal; /* Name of the journal file */
char *zDirectory; /* Directory hold database and journal files */
sqlite3_file *fd, *jfd; /* File descriptors for database and journal */
sqlite3_file *stfd; /* File descriptor for the statement subjournal*/
- int (*xBusyHandler)(void*); /* Function to call when busy */
- void *pBusyHandlerArg; /* Context argument for xBusyHandler */
+ BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */
+ PagerLruList lru; /* LRU list of free pages */
+ PgHdr *pAll; /* List of all pages */
+ PgHdr *pStmt; /* List of pages in the statement subjournal */
+ PgHdr *pDirty; /* List of all dirty pages */
i64 journalOff; /* Current byte offset in the journal file */
i64 journalHdr; /* Byte offset to previous journal header */
i64 stmtHdrOff; /* First journal header written this statement */
i64 stmtCksum; /* cksumInit when statement was started */
i64 stmtJSize; /* Size of journal at stmt_begin() */
- u32 sectorSize; /* Assumed sector size during rollback */
+ int sectorSize; /* Assumed sector size during rollback */
#ifdef SQLITE_TEST
int nHit, nMiss; /* Cache hits and missing */
int nRead, nWrite; /* Database pages read/written */
#endif
- void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
+ void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */
+ void (*xReiniter)(DbPage*,int); /* Call this routine when reloading pages */
#ifdef SQLITE_HAS_CODEC
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
void *pCodecArg; /* First argument to xCodec() */
#endif
+ int nHash; /* Size of the pager hash table */
+ PgHdr **aHash; /* Hash table to map page number to PgHdr */
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ Pager *pNext; /* Doubly linked list of pagers on which */
+ Pager *pPrev; /* sqlite3_release_memory() will work */
+ volatile int iInUseMM; /* Non-zero if unavailable to MM */
+ volatile int iInUseDB; /* Non-zero if in sqlite3_release_memory() */
+#endif
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
char dbFileVers[16]; /* Changes whenever database file changes */
i64 journalSizeLimit; /* Size limit for persistent journal files */
- PCache *pPCache; /* Pointer to page cache object */
};
/*
@@ -28958,11 +26554,22 @@ struct Pager {
SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */
SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */
SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */
+SQLITE_API int sqlite3_pager_pgfree_count = 0; /* Number of cache pages freed */
# define PAGER_INCR(v) v++
#else
# define PAGER_INCR(v)
#endif
+/*
+** The following variable points to the head of a double-linked list
+** of all pagers that are eligible for page stealing by the
+** sqlite3_release_memory() interface. Access to this list is
+** protected by the SQLITE_MUTEX_STATIC_MEM2 mutex.
+*/
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+static Pager *sqlite3PagerList = 0;
+static PagerLruList sqlite3LruPageList = {0, 0, 0};
+#endif
/*
@@ -29025,7 +26632,7 @@ static const unsigned char aJournalMagic[] = {
** roll back. See comments for function writeMasterJournal() for details.
*/
/* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */
-#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
+#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1)
/*
** The maximum legal page number is (2^31 - 1).
@@ -29033,17 +26640,216 @@ static const unsigned char aJournalMagic[] = {
#define PAGER_MAX_PGNO 2147483647
/*
+** The pagerEnter() and pagerLeave() routines acquire and release
+** a mutex on each pager. The mutex is recursive.
+**
+** This is a special-purpose mutex. It only provides mutual exclusion
+** between the Btree and the Memory Management sqlite3_release_memory()
+** function. It does not prevent, for example, two Btrees from accessing
+** the same pager at the same time. Other general-purpose mutexes in
+** the btree layer handle that chore.
+*/
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ static void pagerEnter(Pager *p){
+ p->iInUseDB++;
+ if( p->iInUseMM && p->iInUseDB==1 ){
+#ifndef SQLITE_MUTEX_NOOP
+ sqlite3_mutex *mutex;
+ mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
+#endif
+ p->iInUseDB = 0;
+ sqlite3_mutex_enter(mutex);
+ p->iInUseDB = 1;
+ sqlite3_mutex_leave(mutex);
+ }
+ assert( p->iInUseMM==0 );
+ }
+ static void pagerLeave(Pager *p){
+ p->iInUseDB--;
+ assert( p->iInUseDB>=0 );
+ }
+#else
+# define pagerEnter(X)
+# define pagerLeave(X)
+#endif
+
+/*
+** Add page pPg to the end of the linked list managed by structure
+** pList (pPg becomes the last entry in the list - the most recently
+** used). Argument pLink should point to either pPg->free or pPg->gfree,
+** depending on whether pPg is being added to the pager-specific or
+** global LRU list.
+*/
+static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){
+ pLink->pNext = 0;
+ pLink->pPrev = pList->pLast;
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ assert(pLink==&pPg->free || pLink==&pPg->gfree);
+ assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
+#endif
+
+ if( pList->pLast ){
+ int iOff = (char *)pLink - (char *)pPg;
+ PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)[iOff]);
+ pLastLink->pNext = pPg;
+ }else{
+ assert(!pList->pFirst);
+ pList->pFirst = pPg;
+ }
+
+ pList->pLast = pPg;
+ if( !pList->pFirstSynced && pPg->needSync==0 ){
+ pList->pFirstSynced = pPg;
+ }
+}
+
+/*
+** Remove pPg from the list managed by the structure pointed to by pList.
+**
+** Argument pLink should point to either pPg->free or pPg->gfree, depending
+** on whether pPg is being added to the pager-specific or global LRU list.
+*/
+static void listRemove(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){
+ int iOff = (char *)pLink - (char *)pPg;
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ assert(pLink==&pPg->free || pLink==&pPg->gfree);
+ assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
+#endif
+
+ if( pPg==pList->pFirst ){
+ pList->pFirst = pLink->pNext;
+ }
+ if( pPg==pList->pLast ){
+ pList->pLast = pLink->pPrev;
+ }
+ if( pLink->pPrev ){
+ PagerLruLink *pPrevLink = (PagerLruLink *)(&((u8 *)pLink->pPrev)[iOff]);
+ pPrevLink->pNext = pLink->pNext;
+ }
+ if( pLink->pNext ){
+ PagerLruLink *pNextLink = (PagerLruLink *)(&((u8 *)pLink->pNext)[iOff]);
+ pNextLink->pPrev = pLink->pPrev;
+ }
+ if( pPg==pList->pFirstSynced ){
+ PgHdr *p = pLink->pNext;
+ while( p && p->needSync ){
+ PagerLruLink *pL = (PagerLruLink *)(&((u8 *)p)[iOff]);
+ p = pL->pNext;
+ }
+ pList->pFirstSynced = p;
+ }
+
+ pLink->pNext = pLink->pPrev = 0;
+}
+
+/*
+** Add page pPg to the list of free pages for the pager. If
+** memory-management is enabled, also add the page to the global
+** list of free pages.
+*/
+static void lruListAdd(PgHdr *pPg){
+ listAdd(&pPg->pPager->lru, &pPg->free, pPg);
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ if( !pPg->pPager->memDb ){
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+ listAdd(&sqlite3LruPageList, &pPg->gfree, pPg);
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+ }
+#endif
+}
+
+/*
+** Remove page pPg from the list of free pages for the associated pager.
+** If memory-management is enabled, also remove pPg from the global list
+** of free pages.
+*/
+static void lruListRemove(PgHdr *pPg){
+ listRemove(&pPg->pPager->lru, &pPg->free, pPg);
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ if( !pPg->pPager->memDb ){
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+ listRemove(&sqlite3LruPageList, &pPg->gfree, pPg);
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+ }
+#endif
+}
+
+/*
+** This function is called just after the needSync flag has been cleared
+** from all pages managed by pPager (usually because the journal file
+** has just been synced). It updates the pPager->lru.pFirstSynced variable
+** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced
+** variable also.
+*/
+static void lruListSetFirstSynced(Pager *pPager){
+ pPager->lru.pFirstSynced = pPager->lru.pFirst;
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ if( !pPager->memDb ){
+ PgHdr *p;
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+ for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext);
+ assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced);
+ sqlite3LruPageList.pFirstSynced = p;
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+ }
+#endif
+}
+
+/*
** Return true if page *pPg has already been written to the statement
** journal (or statement snapshot has been created, if *pPg is part
** of an in-memory database).
*/
static int pageInStatement(PgHdr *pPg){
Pager *pPager = pPg->pPager;
- return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
+ if( MEMDB ){
+ return PGHDR_TO_HIST(pPg, pPager)->inStmt;
+ }else{
+ return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
+ }
}
-static int pageInJournal(PgHdr *pPg){
- return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
+/*
+** Change the size of the pager hash table to N. N must be a power
+** of two.
+*/
+static void pager_resize_hash_table(Pager *pPager, int N){
+ PgHdr **aHash, *pPg;
+ assert( N>0 && (N&(N-1))==0 );
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+ if( N*sizeof(aHash[0])>SQLITE_MALLOC_SOFT_LIMIT ){
+ N = SQLITE_MALLOC_SOFT_LIMIT/sizeof(aHash[0]);
+ }
+ if( N==pPager->nHash ) return;
+#endif
+ pagerLeave(pPager);
+ if( pPager->aHash!=0 ) sqlite3BeginBenignMalloc();
+ aHash = sqlite3MallocZero( sizeof(aHash[0])*N );
+ if( pPager->aHash!=0 ) sqlite3EndBenignMalloc();
+ pagerEnter(pPager);
+ if( aHash==0 ){
+ /* Failure to rehash is not an error. It is only a performance hit. */
+ return;
+ }
+ sqlite3_free(pPager->aHash);
+ pPager->nHash = N;
+ pPager->aHash = aHash;
+ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+ int h;
+ if( pPg->pgno==0 ){
+ assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
+ continue;
+ }
+ h = pPg->pgno & (N-1);
+ pPg->pNextHash = aHash[h];
+ if( aHash[h] ){
+ aHash[h]->pPrevHash = pPg;
+ }
+ aHash[h] = pPg;
+ pPg->pPrevHash = 0;
+ }
}
/*
@@ -29155,9 +26961,7 @@ static int pager_error(Pager *pPager, int rc){
rc2==SQLITE_CORRUPT
){
pPager->errCode = rc;
- if( pPager->state==PAGER_UNLOCK
- && sqlite3PcacheRefCount(pPager->pPCache)==0
- ){
+ if( pPager->state==PAGER_UNLOCK && pPager->nRef==0 ){
/* If the pager is already unlocked, call pager_unlock() now to
** clear the error state and ensure that the pager-cache is
** completely empty.
@@ -29186,10 +26990,8 @@ static u32 pager_datahash(int nByte, unsigned char *pData){
return hash;
}
static u32 pager_pagehash(PgHdr *pPage){
- return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
-}
-static void pager_set_pagehash(PgHdr *pPage){
- pPage->pageHash = pager_pagehash(pPage);
+ return pager_datahash(pPage->pPager->pageSize,
+ (unsigned char *)PGHDR_TO_DATA(pPage));
}
/*
@@ -29200,15 +27002,15 @@ static void pager_set_pagehash(PgHdr *pPage){
#define CHECK_PAGE(x) checkPage(x)
static void checkPage(PgHdr *pPg){
Pager *pPager = pPg->pPager;
- assert( !pPg->pageHash || pPager->errCode
- || (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
+ assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty ||
+ pPg->pageHash==pager_pagehash(pPg) );
}
#else
#define pager_datahash(X,Y) 0
#define pager_pagehash(X) 0
#define CHECK_PAGE(x)
-#endif /* SQLITE_CHECK_PAGES */
+#endif
/*
** When this is called the journal file for pager pPager must be open.
@@ -29225,7 +27027,7 @@ static void checkPage(PgHdr *pPg){
** If no master journal file name is present zMaster[0] is set to 0 and
** SQLITE_OK returned.
*/
-static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
+static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, int nMaster){
int rc;
u32 len;
i64 szJ;
@@ -29307,7 +27109,7 @@ static void seekJournalHdr(Pager *pPager){
*/
static int zeroJournalHdr(Pager *pPager, int doTruncate){
int rc = SQLITE_OK;
- static const char zeroHdr[28] = {0};
+ static const char zeroHdr[28];
if( pPager->journalOff ){
i64 iLimit = pPager->journalSizeLimit;
@@ -29357,8 +27159,8 @@ static int zeroJournalHdr(Pager *pPager, int doTruncate){
static int writeJournalHdr(Pager *pPager){
int rc = SQLITE_OK;
char *zHeader = pPager->pTmpSpace;
- u32 nHeader = pPager->pageSize;
- u32 nWrite;
+ int nHeader = pPager->pageSize;
+ int nWrite;
if( nHeader>JOURNAL_HDR_SZ(pPager) ){
nHeader = JOURNAL_HDR_SZ(pPager);
@@ -29394,7 +27196,7 @@ static int writeJournalHdr(Pager *pPager){
** that garbage data is never appended to the journal file.
*/
assert(pPager->fd->pMethods||pPager->noSync);
- if( (pPager->noSync) || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
+ if( (pPager->noSync)
|| (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
){
put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
@@ -29490,12 +27292,8 @@ static int readJournalHdr(
** is being called from within pager_playback(). The local value
** of Pager.sectorSize is restored at the end of that routine.
*/
- rc = read32bits(pPager->jfd, jrnlOff+12, &pPager->sectorSize);
+ rc = read32bits(pPager->jfd, jrnlOff+12, (u32 *)&pPager->sectorSize);
if( rc ) return rc;
- if( (pPager->sectorSize & (pPager->sectorSize-1))!=0
- || pPager->sectorSize>0x1000000 ){
- return SQLITE_DONE;
- }
pPager->journalOff += JOURNAL_HDR_SZ(pPager);
return SQLITE_OK;
@@ -29530,8 +27328,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
u32 cksum = 0;
char zBuf[sizeof(aJournalMagic)+2*4];
- if( !zMaster || pPager->setMaster ) return SQLITE_OK;
- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ) return SQLITE_OK;
+ if( !zMaster || pPager->setMaster) return SQLITE_OK;
pPager->setMaster = 1;
len = strlen(zMaster);
@@ -29584,12 +27381,40 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
}
/*
+** Add or remove a page from the list of all pages that are in the
+** statement journal.
+**
+** The Pager keeps a separate list of pages that are currently in
+** the statement journal. This helps the sqlite3PagerStmtCommit()
+** routine run MUCH faster for the common case where there are many
+** pages in memory but only a few are in the statement journal.
+*/
+static void page_add_to_stmt_list(PgHdr *pPg){
+ Pager *pPager = pPg->pPager;
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ assert( MEMDB );
+ if( !pHist->inStmt ){
+ assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 );
+ if( pPager->pStmt ){
+ PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg;
+ }
+ pHist->pNextStmt = pPager->pStmt;
+ pPager->pStmt = pPg;
+ pHist->inStmt = 1;
+ }
+}
+
+/*
** Find a page in the hash table given its page number. Return
** a pointer to the page or NULL if not found.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
PgHdr *p;
- sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
+ if( pPager->aHash==0 ) return 0;
+ p = pPager->aHash[pgno & (pPager->nHash-1)];
+ while( p && p->pgno!=pgno ){
+ p = p->pNextHash;
+ }
return p;
}
@@ -29600,8 +27425,27 @@ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
** to access those pages will likely result in a coredump.
*/
static void pager_reset(Pager *pPager){
+ PgHdr *pPg, *pNext;
if( pPager->errCode ) return;
- sqlite3PcacheClear(pPager->pPCache);
+ for(pPg=pPager->pAll; pPg; pPg=pNext){
+ IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
+ PAGER_INCR(sqlite3_pager_pgfree_count);
+ pNext = pPg->pNextAll;
+ lruListRemove(pPg);
+ sqlite3PageFree(pPg->pData);
+ sqlite3_free(pPg);
+ }
+ assert(pPager->lru.pFirst==0);
+ assert(pPager->lru.pFirstSynced==0);
+ assert(pPager->lru.pLast==0);
+ pPager->pStmt = 0;
+ pPager->pAll = 0;
+ pPager->pDirty = 0;
+ pPager->nHash = 0;
+ sqlite3_free(pPager->aHash);
+ pPager->nPage = 0;
+ pPager->aHash = 0;
+ pPager->nRef = 0;
}
/*
@@ -29615,46 +27459,48 @@ static void pager_reset(Pager *pPager){
*/
static void pager_unlock(Pager *pPager){
if( !pPager->exclusiveMode ){
- int rc = osUnlock(pPager->fd, NO_LOCK);
- if( rc ) pPager->errCode = rc;
- pPager->dbSizeValid = 0;
- IOTRACE(("UNLOCK %p\n", pPager))
-
- /* Always close the journal file when dropping the database lock.
- ** Otherwise, another connection with journal_mode=delete might
- ** delete the file out from under us.
- */
- if( pPager->journalOpen ){
- sqlite3OsClose(pPager->jfd);
- pPager->journalOpen = 0;
- sqlite3BitvecDestroy(pPager->pInJournal);
- pPager->pInJournal = 0;
- sqlite3BitvecDestroy(pPager->pAlwaysRollback);
- pPager->pAlwaysRollback = 0;
- }
+ if( !MEMDB ){
+ int rc = osUnlock(pPager->fd, NO_LOCK);
+ if( rc ) pPager->errCode = rc;
+ pPager->dbSize = -1;
+ IOTRACE(("UNLOCK %p\n", pPager))
+
+ /* Always close the journal file when dropping the database lock.
+ ** Otherwise, another connection with journal_mode=delete might
+ ** delete the file out from under us.
+ */
+ if( pPager->journalOpen ){
+ sqlite3OsClose(pPager->jfd);
+ pPager->journalOpen = 0;
+ sqlite3BitvecDestroy(pPager->pInJournal);
+ pPager->pInJournal = 0;
+ }
- /* If Pager.errCode is set, the contents of the pager cache cannot be
- ** trusted. Now that the pager file is unlocked, the contents of the
- ** cache can be discarded and the error code safely cleared.
- */
- if( pPager->errCode ){
- if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
- pager_reset(pPager);
- if( pPager->stmtOpen ){
- sqlite3OsClose(pPager->stfd);
- sqlite3BitvecDestroy(pPager->pInStmt);
- pPager->pInStmt = 0;
+ /* If Pager.errCode is set, the contents of the pager cache cannot be
+ ** trusted. Now that the pager file is unlocked, the contents of the
+ ** cache can be discarded and the error code safely cleared.
+ */
+ if( pPager->errCode ){
+ if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
+ pager_reset(pPager);
+ if( pPager->stmtOpen ){
+ sqlite3OsClose(pPager->stfd);
+ sqlite3BitvecDestroy(pPager->pInStmt);
+ pPager->pInStmt = 0;
+ }
+ pPager->stmtOpen = 0;
+ pPager->stmtInUse = 0;
+ pPager->journalOff = 0;
+ pPager->journalStarted = 0;
+ pPager->stmtAutoopen = 0;
+ pPager->origDbSize = 0;
}
- pPager->stmtOpen = 0;
- pPager->stmtInUse = 0;
- pPager->journalOff = 0;
- pPager->journalStarted = 0;
- pPager->stmtAutoopen = 0;
- pPager->origDbSize = 0;
}
- pPager->state = PAGER_UNLOCK;
- pPager->changeCountDone = 0;
+ if( !MEMDB || pPager->errCode==SQLITE_OK ){
+ pPager->state = PAGER_UNLOCK;
+ pPager->changeCountDone = 0;
+ }
}
}
@@ -29664,12 +27510,17 @@ static void pager_unlock(Pager *pPager){
** do not attempt the rollback.
*/
static void pagerUnlockAndRollback(Pager *p){
+ /* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */
if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){
sqlite3BeginBenignMalloc();
sqlite3PagerRollback(p);
sqlite3EndBenignMalloc();
}
pager_unlock(p);
+#if 0
+ assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );
+ assert( p->errCode || !p->stmtOpen || p->exclusiveMode );
+#endif
}
/*
@@ -29690,8 +27541,10 @@ static void pagerUnlockAndRollback(Pager *p){
** a file is an expensive operation.
*/
static int pager_end_transaction(Pager *pPager, int hasMaster){
+ PgHdr *pPg;
int rc = SQLITE_OK;
int rc2 = SQLITE_OK;
+ assert( !MEMDB );
if( pPager->state<PAGER_RESERVED ){
return SQLITE_OK;
}
@@ -29701,18 +27554,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
pPager->stmtOpen = 0;
}
if( pPager->journalOpen ){
- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
- int isMemoryJournal = sqlite3IsMemJournal(pPager->jfd);
- sqlite3OsClose(pPager->jfd);
- pPager->journalOpen = 0;
- if( !isMemoryJournal ){
- rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
- }
- }else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE
- && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){
- pPager->journalOff = 0;
- pPager->journalStarted = 0;
- }else if( pPager->exclusiveMode
+ if( pPager->exclusiveMode
|| pPager->journalMode==PAGER_JOURNALMODE_PERSIST
){
rc = zeroJournalHdr(pPager, hasMaster);
@@ -29720,7 +27562,6 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
pPager->journalOff = 0;
pPager->journalStarted = 0;
}else{
- assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE || rc );
sqlite3OsClose(pPager->jfd);
pPager->journalOpen = 0;
if( rc==SQLITE_OK && !pPager->tempFile ){
@@ -29729,12 +27570,16 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
}
sqlite3BitvecDestroy(pPager->pInJournal);
pPager->pInJournal = 0;
- sqlite3BitvecDestroy(pPager->pAlwaysRollback);
- pPager->pAlwaysRollback = 0;
+ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+ pPg->inJournal = 0;
+ pPg->dirty = 0;
+ pPg->needSync = 0;
+ pPg->alwaysRollback = 0;
#ifdef SQLITE_CHECK_PAGES
- sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
+ pPg->pageHash = pager_pagehash(pPg);
#endif
- sqlite3PcacheCleanAll(pPager->pPCache);
+ }
+ pPager->pDirty = 0;
pPager->dirtyCache = 0;
pPager->nRec = 0;
}else{
@@ -29750,10 +27595,8 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
pPager->origDbSize = 0;
pPager->setMaster = 0;
pPager->needSync = 0;
- /* lruListSetFirstSynced(pPager); */
- if( !MEMDB ){
- pPager->dbSizeValid = 0;
- }
+ lruListSetFirstSynced(pPager);
+ pPager->dbSize = -1;
pPager->dbModified = 0;
return (rc==SQLITE_OK?rc2:rc);
@@ -29789,19 +27632,22 @@ static u32 pager_cksum(Pager *pPager, const u8 *aData){
return cksum;
}
+/* Forward declaration */
+static void makeClean(PgHdr*);
+
/*
** Read a single page from the journal file opened on file descriptor
** jfd. Playback this one page.
**
-** The isMainJrnl flag is true if this is the main rollback journal and
-** false for the statement journal. The main rollback journal uses
-** checksums - the statement journal does not.
+** If useCksum==0 it means this journal does not use checksums. Checksums
+** are not used in statement journals because statement journals do not
+** need to survive power failures.
*/
static int pager_playback_one_page(
- Pager *pPager, /* The pager being played back */
- sqlite3_file *jfd, /* The file that is the journal being rolled back */
- i64 offset, /* Offset of the page within the journal */
- int isMainJrnl /* True for main rollback journal. False for Stmt jrnl */
+ Pager *pPager,
+ sqlite3_file *jfd,
+ i64 offset,
+ int useCksum
){
int rc;
PgHdr *pPg; /* An existing page in the cache */
@@ -29809,10 +27655,10 @@ static int pager_playback_one_page(
u32 cksum; /* Checksum used for sanity checking */
u8 *aData = (u8 *)pPager->pTmpSpace; /* Temp storage for a page */
- /* isMainJrnl should be true for the main journal and false for
+ /* useCksum should be true for the main journal and false for
** statement journals. Verify that this is always the case
*/
- assert( jfd == (isMainJrnl ? pPager->jfd : pPager->stfd) );
+ assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) );
assert( aData );
rc = read32bits(jfd, offset, &pgno);
@@ -29832,7 +27678,7 @@ static int pager_playback_one_page(
if( pgno>(unsigned)pPager->dbSize ){
return SQLITE_OK;
}
- if( isMainJrnl ){
+ if( useCksum ){
rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum);
if( rc ) return rc;
pPager->journalOff += 4;
@@ -29878,12 +27724,13 @@ static int pager_playback_one_page(
pPg = pager_lookup(pPager, pgno);
PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));
- if( (pPager->state>=PAGER_EXCLUSIVE)
- && (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
- && (pPager->fd->pMethods)
- ){
- i64 ofst = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
+ if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0)
+ && pPager->fd->pMethods ){
+ i64 offset = (pgno-1)*(i64)pPager->pageSize;
+ rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset);
+ if( pPg ){
+ makeClean(pPg);
+ }
}
if( pPg ){
/* No page should ever be explicitly rolled back that is in use, except
@@ -29893,13 +27740,11 @@ static int pager_playback_one_page(
** sqlite3PagerRollback().
*/
void *pData;
- pData = pPg->pData;
+ /* assert( pPg->nRef==0 || pPg->pgno==1 ); */
+ pData = PGHDR_TO_DATA(pPg);
memcpy(pData, aData, pPager->pageSize);
if( pPager->xReiniter ){
- pPager->xReiniter(pPg);
- }
- if( isMainJrnl ){
- sqlite3PcacheMakeClean(pPg);
+ pPager->xReiniter(pPg, pPager->pageSize);
}
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
@@ -29912,7 +27757,6 @@ static int pager_playback_one_page(
/* Decode the page just read from disk */
CODEC1(pPager, pData, pPg->pgno, 3);
- sqlite3PcacheRelease(pPg);
}
return rc;
}
@@ -30039,7 +27883,7 @@ static void pager_truncate_cache(Pager *pPager);
** so detect this case and write a single zero byte to the end of the new
** file instead.
*/
-static int pager_truncate(Pager *pPager, Pgno nPage){
+static int pager_truncate(Pager *pPager, int nPage){
int rc = SQLITE_OK;
if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){
i64 currentSize, newSize;
@@ -30231,11 +28075,6 @@ static int pager_playback(Pager *pPager, int isHot){
pPager->journalOff = szJ;
break;
}else{
- /* If we are unable to rollback, then the database is probably
- ** going to end up being corrupt. It is corrupt to us, anyhow.
- ** Perhaps the next process to come along can fix it....
- */
- rc = SQLITE_CORRUPT_BKPT;
goto end_playback;
}
}
@@ -30252,7 +28091,7 @@ end_playback:
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zMaster[0]!='\0');
}
- if( rc==SQLITE_OK && zMaster[0] && res ){
+ if( rc==SQLITE_OK && zMaster[0] ){
/* If there was a master journal and this routine will return success,
** see if it is possible to delete the master journal.
*/
@@ -30371,7 +28210,11 @@ end_stmt_playback:
** Change the maximum number of in-memory pages that are allowed.
*/
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
- sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
+ if( mxPage>10 ){
+ pPager->mxPage = mxPage;
+ }else{
+ pPager->mxPage = 10;
+ }
}
/*
@@ -30401,10 +28244,10 @@ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){
+SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int full_fsync){
pPager->noSync = level==1 || pPager->tempFile;
pPager->fullSync = level==3 && !pPager->tempFile;
- pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
+ pPager->sync_flags = (full_fsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
if( pPager->noSync ) pPager->needSync = 0;
}
#endif
@@ -30443,8 +28286,6 @@ static int sqlite3PagerOpentemp(
return rc;
}
-static int pagerStress(void *,PgHdr *);
-
/*
** Create a new page cache and put a pointer to the page cache in *ppPager.
** The file to be cached need not exist. The file is not locked until
@@ -30476,18 +28317,11 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int readOnly = 0;
int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
- int journalFileSize;
- int pcacheSize = sqlite3PcacheSize();
+ int journalFileSize = sqlite3JournalSize(pVfs);
int szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;
char *zPathname = 0;
int nPathname = 0;
- if( sqlite3JournalSize(pVfs)>sqlite3MemJournalSize() ){
- journalFileSize = sqlite3JournalSize(pVfs);
- }else{
- journalFileSize = sqlite3MemJournalSize();
- }
-
/* The default return is a NULL pointer */
*ppPager = 0;
@@ -30520,23 +28354,20 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* Allocate memory for the pager structure */
pPager = sqlite3MallocZero(
sizeof(*pPager) + /* Pager structure */
- pcacheSize + /* PCache object */
journalFileSize + /* The journal file structure */
- pVfs->szOsFile + /* The main db file */
- journalFileSize * 2 + /* The two journal files */
+ pVfs->szOsFile * 3 + /* The main db and two journal files */
3*nPathname + 40 /* zFilename, zDirectory, zJournal */
);
if( !pPager ){
sqlite3_free(zPathname);
return SQLITE_NOMEM;
}
- pPager->pPCache = (PCache *)&pPager[1];
- pPtr = ((u8 *)&pPager[1]) + pcacheSize;
+ pPtr = (u8 *)&pPager[1];
pPager->vfsFlags = vfsFlags;
pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0];
- pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile];
- pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile+journalFileSize];
- pPager->zFilename = (char*)&pPtr[pVfs->szOsFile+2*journalFileSize];
+ pPager->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*1];
+ pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile*2];
+ pPager->zFilename = (char*)&pPtr[pVfs->szOsFile*2+journalFileSize];
pPager->zDirectory = &pPager->zFilename[nPathname+1];
pPager->zJournal = &pPager->zDirectory[nPathname+1];
pPager->pVfs = pVfs;
@@ -30548,7 +28379,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* Open the pager file.
*/
if( zFilename && zFilename[0] && !memDb ){
- if( nPathname>(pVfs->mxPathname - (int)sizeof("-journal")) ){
+ if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){
rc = SQLITE_CANTOPEN;
}else{
int fout = 0;
@@ -30586,14 +28417,10 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
}
}
}
- }else{
+ }else if( !memDb ){
/* If a temporary file is requested, it is not opened immediately.
** In this case we accept the default page size and delay actually
** opening the file until the first call to OsWrite().
- **
- ** This branch is also run for an in-memory database. An in-memory
- ** database is the same as a temp-file that is never written out to
- ** disk and uses an in-memory rollback journal.
*/
tempFile = 1;
pPager->state = PAGER_EXCLUSIVE;
@@ -30613,9 +28440,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
sqlite3_free(pPager);
return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
}
- nExtra = FORCE_ALIGNMENT(nExtra);
- sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
- !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename);
IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
@@ -30634,12 +28458,12 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
}
/* pPager->journalOpen = 0; */
- pPager->useJournal = useJournal;
+ pPager->useJournal = useJournal && !memDb;
pPager->noReadlock = noReadlock && readOnly;
/* pPager->stmtOpen = 0; */
/* pPager->stmtInUse = 0; */
/* pPager->nRef = 0; */
- pPager->dbSizeValid = memDb;
+ pPager->dbSize = memDb-1;
pPager->pageSize = szPageDflt;
/* pPager->stmtSize = 0; */
/* pPager->stmtJSize = 0; */
@@ -30663,30 +28487,53 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* pPager->pFirst = 0; */
/* pPager->pFirstSynced = 0; */
/* pPager->pLast = 0; */
- pPager->nExtra = nExtra;
+ pPager->nExtra = FORCE_ALIGNMENT(nExtra);
pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
- assert(pPager->fd->pMethods||tempFile);
- setSectorSize(pPager);
- if( memDb ){
- pPager->journalMode = PAGER_JOURNALMODE_MEMORY;
+ assert(pPager->fd->pMethods||memDb||tempFile);
+ if( !memDb ){
+ setSectorSize(pPager);
}
- /* pPager->xBusyHandler = 0; */
- /* pPager->pBusyHandlerArg = 0; */
+ /* pPager->pBusyHandler = 0; */
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
*ppPager = pPager;
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ pPager->iInUseMM = 0;
+ pPager->iInUseDB = 0;
+ if( !memDb ){
+#ifndef SQLITE_MUTEX_NOOP
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
+#endif
+ sqlite3_mutex_enter(mutex);
+ pPager->pNext = sqlite3PagerList;
+ if( sqlite3PagerList ){
+ assert( sqlite3PagerList->pPrev==0 );
+ sqlite3PagerList->pPrev = pPager;
+ }
+ pPager->pPrev = 0;
+ sqlite3PagerList = pPager;
+ sqlite3_mutex_leave(mutex);
+ }
+#endif
return SQLITE_OK;
}
/*
** Set the busy handler function.
*/
-SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
- Pager *pPager,
- int (*xBusyHandler)(void *),
- void *pBusyHandlerArg
-){
- pPager->xBusyHandler = xBusyHandler;
- pPager->pBusyHandlerArg = pBusyHandlerArg;
+SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){
+ pPager->pBusyHandler = pBusyHandler;
+}
+
+/*
+** Set the destructor for this pager. If not NULL, the destructor is called
+** when the reference count on each page reaches zero. The destructor can
+** be used to clean up information in the extra segment appended to each page.
+**
+** The destructor is not called as a result sqlite3PagerClose().
+** Destructors are only called by sqlite3PagerUnref().
+*/
+SQLITE_PRIVATE void sqlite3PagerSetDestructor(Pager *pPager, void (*xDesc)(DbPage*,int)){
+ pPager->xDestructor = xDesc;
}
/*
@@ -30696,7 +28543,7 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
** an opportunity to restore the EXTRA section to agree with the restored
** page data.
*/
-SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*)){
+SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){
pPager->xReiniter = xReinit;
}
@@ -30706,28 +28553,26 @@ SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPag
** value before returning.
*/
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){
- int rc = pPager->errCode;
- if( rc==SQLITE_OK ){
- u16 pageSize = *pPageSize;
- assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
- if( pageSize && pageSize!=pPager->pageSize
- && (pPager->memDb==0 || pPager->dbSize==0)
- && sqlite3PcacheRefCount(pPager->pPCache)==0
- ){
- char *pNew = (char *)sqlite3PageMalloc(pageSize);
- if( !pNew ){
- rc = SQLITE_NOMEM;
- }else{
- pager_reset(pPager);
- pPager->pageSize = pageSize;
- if( !pPager->memDb ) setSectorSize(pPager);
- sqlite3PageFree(pPager->pTmpSpace);
- pPager->pTmpSpace = pNew;
- sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
- }
+ int rc = SQLITE_OK;
+ u16 pageSize = *pPageSize;
+ assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
+ if( pageSize && pageSize!=pPager->pageSize
+ && !pPager->memDb && pPager->nRef==0
+ ){
+ char *pNew = (char *)sqlite3PageMalloc(pageSize);
+ if( !pNew ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pagerEnter(pPager);
+ pager_reset(pPager);
+ pPager->pageSize = pageSize;
+ setSectorSize(pPager);
+ sqlite3PageFree(pPager->pTmpSpace);
+ pPager->pTmpSpace = pNew;
+ pagerLeave(pPager);
}
- *pPageSize = pPager->pageSize;
}
+ *pPageSize = pPager->pageSize;
return rc;
}
@@ -30795,7 +28640,7 @@ void enable_simulated_io_errors(void){
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
int rc = SQLITE_OK;
memset(pDest, 0, N);
- assert(pPager->fd->pMethods||pPager->tempFile);
+ assert(MEMDB||pPager->fd->pMethods||pPager->tempFile);
if( pPager->fd->pMethods ){
IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
@@ -30820,16 +28665,17 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
int rc;
assert( pPager!=0 );
if( pPager->errCode ){
- rc = pPager->errCode;
- return rc;
+ return pPager->errCode;
}
- if( pPager->dbSizeValid ){
+ if( pPager->dbSize>=0 ){
n = pPager->dbSize;
} else {
assert(pPager->fd->pMethods||pPager->tempFile);
if( (pPager->fd->pMethods)
&& (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
+ pPager->nRef++;
pager_error(pPager, rc);
+ pPager->nRef--;
return rc;
}
if( n>0 && n<pPager->pageSize ){
@@ -30839,7 +28685,6 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
}
if( pPager->state!=PAGER_UNLOCK ){
pPager->dbSize = n;
- pPager->dbSizeValid = 1;
}
}
if( n==(PENDING_BYTE/pPager->pageSize) ){
@@ -30854,12 +28699,69 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
return SQLITE_OK;
}
+
+#ifndef SQLITE_OMIT_MEMORYDB
+/*
+** Clear a PgHistory block
+*/
+static void clearHistory(PgHistory *pHist){
+ sqlite3PageFree(pHist->pOrig);
+ sqlite3PageFree(pHist->pStmt);
+ pHist->pOrig = 0;
+ pHist->pStmt = 0;
+}
+#else
+#define clearHistory(x)
+#endif
+
/*
** Forward declaration
*/
static int syncJournal(Pager*);
/*
+** Unlink pPg from its hash chain. Also set the page number to 0 to indicate
+** that the page is not part of any hash chain. This is required because the
+** sqlite3PagerMovepage() routine can leave a page in the
+** pNextFree/pPrevFree list that is not a part of any hash-chain.
+*/
+static void unlinkHashChain(Pager *pPager, PgHdr *pPg){
+ if( pPg->pgno==0 ){
+ assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
+ return;
+ }
+ if( pPg->pNextHash ){
+ pPg->pNextHash->pPrevHash = pPg->pPrevHash;
+ }
+ if( pPg->pPrevHash ){
+ assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg );
+ pPg->pPrevHash->pNextHash = pPg->pNextHash;
+ }else{
+ int h = pPg->pgno & (pPager->nHash-1);
+ pPager->aHash[h] = pPg->pNextHash;
+ }
+ if( MEMDB ){
+ clearHistory(PGHDR_TO_HIST(pPg, pPager));
+ }
+ pPg->pgno = 0;
+ pPg->pNextHash = pPg->pPrevHash = 0;
+}
+
+/*
+** Unlink a page from the free list (the list of all pages where nRef==0)
+** and from its hash collision chain.
+*/
+static void unlinkPage(PgHdr *pPg){
+ Pager *pPager = pPg->pPager;
+
+ /* Unlink from free page list */
+ lruListRemove(pPg);
+
+ /* Unlink from the pgno hash table */
+ unlinkHashChain(pPager, pPg);
+}
+
+/*
** This routine is used to truncate the cache when a database
** is truncated. Drop from the cache all pages whose pgno is
** larger than pPager->dbSize and is unreferenced.
@@ -30872,7 +28774,33 @@ static int syncJournal(Pager*);
** to zero it and hope that we error out sanely.
*/
static void pager_truncate_cache(Pager *pPager){
- sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
+ PgHdr *pPg;
+ PgHdr **ppPg;
+ int dbSize = pPager->dbSize;
+
+ ppPg = &pPager->pAll;
+ while( (pPg = *ppPg)!=0 ){
+ if( pPg->pgno<=dbSize ){
+ ppPg = &pPg->pNextAll;
+ }else if( pPg->nRef>0 ){
+ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
+ ppPg = &pPg->pNextAll;
+ }else{
+ *ppPg = pPg->pNextAll;
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ if( *ppPg ){
+ (*ppPg)->pPrevAll = pPg->pPrevAll;
+ }
+#endif
+ IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
+ PAGER_INCR(sqlite3_pager_pgfree_count);
+ unlinkPage(pPg);
+ makeClean(pPg);
+ sqlite3PageFree(pPg->pData);
+ sqlite3_free(pPg);
+ pPager->nPage--;
+ }
+ }
}
/*
@@ -30892,14 +28820,15 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
/* If the file is currently unlocked then the size must be unknown */
- assert( pPager->state>=PAGER_SHARED || pPager->dbSizeValid==0 );
+ assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
if( pPager->state>=locktype ){
rc = SQLITE_OK;
}else{
+ if( pPager->pBusyHandler ) pPager->pBusyHandler->nBusy = 0;
do {
rc = sqlite3OsLock(pPager->fd, locktype);
- }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
+ }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
if( rc==SQLITE_OK ){
pPager->state = locktype;
IOTRACE(("LOCK %p %d\n", pPager, locktype))
@@ -30912,23 +28841,37 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
** Truncate the file to the number of pages specified.
*/
SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
- int rc = SQLITE_OK;
- assert( pPager->state>=PAGER_SHARED );
-
+ int rc;
+ assert( pPager->state>=PAGER_SHARED || MEMDB );
sqlite3PagerPagecount(pPager, 0);
if( pPager->errCode ){
rc = pPager->errCode;
- }else if( nPage<pPager->dbSize ){
- rc = syncJournal(pPager);
- if( rc==SQLITE_OK ){
- /* Get an exclusive lock on the database before truncating. */
- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
- }
- if( rc==SQLITE_OK ){
- rc = pager_truncate(pPager, nPage);
- }
+ return rc;
+ }
+ if( nPage>=(unsigned)pPager->dbSize ){
+ return SQLITE_OK;
+ }
+ if( MEMDB ){
+ pPager->dbSize = nPage;
+ pager_truncate_cache(pPager);
+ return SQLITE_OK;
+ }
+ pagerEnter(pPager);
+ rc = syncJournal(pPager);
+ pagerLeave(pPager);
+ if( rc!=SQLITE_OK ){
+ return rc;
}
+ /* Get an exclusive lock on the database before truncating. */
+ pagerEnter(pPager);
+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+ pagerLeave(pPager);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ rc = pager_truncate(pPager, nPage);
return rc;
}
@@ -30947,15 +28890,30 @@ SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
** to the caller.
*/
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ if( !MEMDB ){
+#ifndef SQLITE_MUTEX_NOOP
+ sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
+#endif
+ sqlite3_mutex_enter(mutex);
+ if( pPager->pPrev ){
+ pPager->pPrev->pNext = pPager->pNext;
+ }else{
+ sqlite3PagerList = pPager->pNext;
+ }
+ if( pPager->pNext ){
+ pPager->pNext->pPrev = pPager->pPrev;
+ }
+ sqlite3_mutex_leave(mutex);
+ }
+#endif
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
pPager->errCode = 0;
pPager->exclusiveMode = 0;
pager_reset(pPager);
- if( !MEMDB ){
- pagerUnlockAndRollback(pPager);
- }
+ pagerUnlockAndRollback(pPager);
enable_simulated_io_errors();
sqlite3EndBenignMalloc();
PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
@@ -30964,7 +28922,6 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
sqlite3OsClose(pPager->jfd);
}
sqlite3BitvecDestroy(pPager->pInJournal);
- sqlite3BitvecDestroy(pPager->pAlwaysRollback);
if( pPager->stmtOpen ){
sqlite3OsClose(pPager->stfd);
}
@@ -30975,8 +28932,8 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
** }
*/
+ sqlite3_free(pPager->aHash);
sqlite3PageFree(pPager->pTmpSpace);
- sqlite3PcacheClose(pPager->pPCache);
sqlite3_free(pPager);
return SQLITE_OK;
}
@@ -30991,11 +28948,42 @@ SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *p){
#endif
/*
+** The page_ref() function increments the reference count for a page.
+** If the page is currently on the freelist (the reference count is zero) then
+** remove it from the freelist.
+**
+** For non-test systems, page_ref() is a macro that calls _page_ref()
+** online of the reference count is zero. For test systems, page_ref()
+** is a real function so that we can set breakpoints and trace it.
+*/
+static void _page_ref(PgHdr *pPg){
+ if( pPg->nRef==0 ){
+ /* The page is currently on the freelist. Remove it. */
+ lruListRemove(pPg);
+ pPg->pPager->nRef++;
+ }
+ pPg->nRef++;
+}
+#ifdef SQLITE_DEBUG
+ static void page_ref(PgHdr *pPg){
+ if( pPg->nRef==0 ){
+ _page_ref(pPg);
+ }else{
+ pPg->nRef++;
+ }
+ }
+#else
+# define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++)
+#endif
+
+/*
** Increment the reference count for a page. The input pointer is
** a reference to the page data.
*/
SQLITE_PRIVATE int sqlite3PagerRef(DbPage *pPg){
- sqlite3PcacheRef(pPg);
+ pagerEnter(pPg->pPager);
+ page_ref(pPg);
+ pagerLeave(pPg->pPager);
return SQLITE_OK;
}
@@ -31025,14 +29013,14 @@ SQLITE_PRIVATE int sqlite3PagerRef(DbPage *pPg){
** memory.
*/
static int syncJournal(Pager *pPager){
+ PgHdr *pPg;
int rc = SQLITE_OK;
/* Sync the journal before modifying the main database
** (assuming there is a journal and it needs to be synced.)
*/
if( pPager->needSync ){
- assert( !pPager->tempFile );
- if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
+ if( !pPager->tempFile ){
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
assert( pPager->journalOpen );
@@ -31075,21 +29063,110 @@ static int syncJournal(Pager *pPager){
/* Erase the needSync flag from every page.
*/
- sqlite3PcacheClearSyncFlags(pPager->pPCache);
+ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+ pPg->needSync = 0;
+ }
+ lruListSetFirstSynced(pPager);
}
+#ifndef NDEBUG
+ /* If the Pager.needSync flag is clear then the PgHdr.needSync
+ ** flag must also be clear for all pages. Verify that this
+ ** invariant is true.
+ */
+ else{
+ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+ assert( pPg->needSync==0 );
+ }
+ assert( pPager->lru.pFirstSynced==pPager->lru.pFirst );
+ }
+#endif
+
return rc;
}
/*
+** Merge two lists of pages connected by pDirty and in pgno order.
+** Do not both fixing the pPrevDirty pointers.
+*/
+static PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB){
+ PgHdr result, *pTail;
+ pTail = &result;
+ while( pA && pB ){
+ if( pA->pgno<pB->pgno ){
+ pTail->pDirty = pA;
+ pTail = pA;
+ pA = pA->pDirty;
+ }else{
+ pTail->pDirty = pB;
+ pTail = pB;
+ pB = pB->pDirty;
+ }
+ }
+ if( pA ){
+ pTail->pDirty = pA;
+ }else if( pB ){
+ pTail->pDirty = pB;
+ }else{
+ pTail->pDirty = 0;
+ }
+ return result.pDirty;
+}
+
+/*
+** Sort the list of pages in accending order by pgno. Pages are
+** connected by pDirty pointers. The pPrevDirty pointers are
+** corrupted by this sort.
+*/
+#define N_SORT_BUCKET_ALLOC 25
+#define N_SORT_BUCKET 25
+#ifdef SQLITE_TEST
+ int sqlite3_pager_n_sort_bucket = 0;
+ #undef N_SORT_BUCKET
+ #define N_SORT_BUCKET \
+ (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
+#endif
+static PgHdr *sort_pagelist(PgHdr *pIn){
+ PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
+ int i;
+ memset(a, 0, sizeof(a));
+ while( pIn ){
+ p = pIn;
+ pIn = p->pDirty;
+ p->pDirty = 0;
+ for(i=0; i<N_SORT_BUCKET-1; i++){
+ if( a[i]==0 ){
+ a[i] = p;
+ break;
+ }else{
+ p = merge_pagelist(a[i], p);
+ a[i] = 0;
+ }
+ }
+ if( i==N_SORT_BUCKET-1 ){
+ /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET)
+ ** elements in the input list. This is possible, but impractical.
+ ** Testing this line is the point of global variable
+ ** sqlite3_pager_n_sort_bucket.
+ */
+ a[i] = merge_pagelist(a[i], p);
+ }
+ }
+ p = a[0];
+ for(i=1; i<N_SORT_BUCKET; i++){
+ p = merge_pagelist(p, a[i]);
+ }
+ return p;
+}
+
+/*
** Given a list of pages (connected by the PgHdr.pDirty pointer) write
-** every one of those pages out to the database file. No calls are made
-** to the page-cache to mark the pages as clean. It is the responsibility
-** of the caller to use PcacheCleanAll() or PcacheMakeClean() to mark
-** the pages as clean.
+** every one of those pages out to the database file and mark them all
+** as clean.
*/
static int pager_write_pagelist(PgHdr *pList){
Pager *pPager;
+ PgHdr *p;
int rc;
if( pList==0 ) return SQLITE_OK;
@@ -31116,6 +29193,11 @@ static int pager_write_pagelist(PgHdr *pList){
return rc;
}
+ pList = sort_pagelist(pList);
+ for(p=pList; p; p=p->pDirty){
+ assert( p->dirty );
+ p->dirty = 0;
+ }
while( pList ){
/* If the file has not yet been opened, open it now. */
@@ -31130,9 +29212,9 @@ static int pager_write_pagelist(PgHdr *pList){
** make the file smaller (presumably by auto-vacuum code). Do not write
** any such pages to the file.
*/
- if( pList->pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
+ if( pList->pgno<=pPager->dbSize ){
i64 offset = (pList->pgno-1)*(i64)pPager->pageSize;
- char *pData = CODEC2(pPager, pList->pData, pList->pgno, 6);
+ char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
PAGERTRACE4("STORE %d page %d hash(%08x)\n",
PAGERID(pPager), pList->pgno, pager_pagehash(pList));
IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
@@ -31154,53 +29236,31 @@ static int pager_write_pagelist(PgHdr *pList){
#endif
pList = pList->pDirty;
}
-
return SQLITE_OK;
}
/*
-** This function is called by the pcache layer when it has reached some
-** soft memory limit. The argument is a pointer to a purgeable Pager
-** object. This function attempts to make a single dirty page that has no
-** outstanding references (if one exists) clean so that it can be recycled
-** by the pcache layer.
+** Collect every dirty page into a dirty list and
+** return a pointer to the head of that list. All pages are
+** collected even if they are still in use.
*/
-static int pagerStress(void *p, PgHdr *pPg){
- Pager *pPager = (Pager *)p;
- int rc = SQLITE_OK;
+static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
- if( pPager->doNotSync ){
- return SQLITE_OK;
- }
-
- assert( pPg->flags&PGHDR_DIRTY );
- if( pPager->errCode==SQLITE_OK ){
- if( pPg->flags&PGHDR_NEED_SYNC ){
- rc = syncJournal(pPager);
- if( rc==SQLITE_OK && pPager->fullSync &&
- !(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) &&
- !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
- ){
- pPager->nRec = 0;
- rc = writeJournalHdr(pPager);
- }
- }
- if( rc==SQLITE_OK ){
- pPg->pDirty = 0;
- rc = pager_write_pagelist(pPg);
- }
- if( rc!=SQLITE_OK ){
- pager_error(pPager, rc);
- }
- }
+#ifndef NDEBUG
+ /* Verify the sanity of the dirty list when we are running
+ ** in debugging mode. This is expensive, so do not
+ ** do this on a normal build. */
+ int n1 = 0;
+ int n2 = 0;
+ PgHdr *p;
+ for(p=pPager->pAll; p; p=p->pNextAll){ if( p->dirty ) n1++; }
+ for(p=pPager->pDirty; p; p=p->pDirty){ n2++; }
+ assert( n1==n2 );
+#endif
- if( rc==SQLITE_OK ){
- sqlite3PcacheMakeClean(pPg);
- }
- return rc;
+ return pPager->pDirty;
}
-
/*
** Return 1 if there is a hot journal on the given pager.
** A hot journal is one that needs to be played back.
@@ -31223,29 +29283,256 @@ static int pagerStress(void *p, PgHdr *pPg){
static int hasHotJournal(Pager *pPager, int *pExists){
sqlite3_vfs *pVfs = pPager->pVfs;
int rc = SQLITE_OK;
- int exists;
- int locked;
- assert( pPager!=0 );
- assert( pPager->useJournal );
- assert( pPager->fd->pMethods );
*pExists = 0;
- rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
- if( rc==SQLITE_OK && exists ){
- rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
+ if( pPager->useJournal && pPager->fd->pMethods ){
+ int exists;
+ int locked;
+
+ rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
+ if( rc==SQLITE_OK && exists ){
+ rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
+ }
+
+ if( rc==SQLITE_OK && exists && !locked ){
+ int nPage;
+ rc = sqlite3PagerPagecount(pPager, &nPage);
+ if( rc==SQLITE_OK ){
+ if( nPage==0 ){
+ sqlite3OsDelete(pVfs, pPager->zJournal, 0);
+ }else{
+ *pExists = 1;
+ }
+ }
+ }
+ }
+
+ return rc;
+}
+
+/*
+** Try to find a page in the cache that can be recycled.
+**
+** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It
+** does not set the pPager->errCode variable.
+*/
+static int pager_recycle(Pager *pPager, PgHdr **ppPg){
+ PgHdr *pPg;
+ *ppPg = 0;
+
+ /* It is illegal to call this function unless the pager object
+ ** pointed to by pPager has at least one free page (page with nRef==0).
+ */
+ assert(!MEMDB);
+ assert(pPager->lru.pFirst);
+
+ /* Find a page to recycle. Try to locate a page that does not
+ ** require us to do an fsync() on the journal.
+ */
+ pPg = pPager->lru.pFirstSynced;
+
+ /* If we could not find a page that does not require an fsync()
+ ** on the journal file then fsync the journal file. This is a
+ ** very slow operation, so we work hard to avoid it. But sometimes
+ ** it can't be helped.
+ */
+ if( pPg==0 && pPager->lru.pFirst ){
+ if( !pPager->errCode ){
+ int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
+ int rc = syncJournal(pPager);
+ if( rc!=0 ){
+ return rc;
+ }
+ if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
+ /* If in full-sync mode, write a new journal header into the
+ ** journal file. This is done to avoid ever modifying a journal
+ ** header that is involved in the rollback of pages that have
+ ** already been written to the database (in case the header is
+ ** trashed when the nRec field is updated).
+ */
+ pPager->nRec = 0;
+ assert( pPager->journalOff > 0 );
+ assert( pPager->doNotSync==0 );
+ rc = writeJournalHdr(pPager);
+ if( rc!=0 ){
+ return rc;
+ }
+ }
+ }
+ pPg = pPager->lru.pFirst;
+ }
+
+ assert( pPg->nRef==0 );
+
+ /* Write the page to the database file if it is dirty.
+ */
+ if( pPg->dirty && !pPager->errCode ){
+ int rc;
+ assert( pPg->needSync==0 );
+ makeClean(pPg);
+ pPg->dirty = 1;
+ pPg->pDirty = 0;
+ rc = pager_write_pagelist( pPg );
+ pPg->dirty = 0;
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
}
- if( rc==SQLITE_OK && exists && !locked ){
- int nPage;
- rc = sqlite3PagerPagecount(pPager, &nPage);
+ assert( pPg->dirty==0 || pPager->errCode );
+
+ /* If the page we are recycling is marked as alwaysRollback, then
+ ** set the global alwaysRollback flag, thus disabling the
+ ** sqlite3PagerDontRollback() optimization for the rest of this transaction.
+ ** It is necessary to do this because the page marked alwaysRollback
+ ** might be reloaded at a later time but at that point we won't remember
+ ** that is was marked alwaysRollback. This means that all pages must
+ ** be marked as alwaysRollback from here on out.
+ */
+ if( pPg->alwaysRollback ){
+ IOTRACE(("ALWAYS_ROLLBACK %p\n", pPager))
+ pPager->alwaysRollback = 1;
+ }
+
+ /* Unlink the old page from the free list and the hash table
+ */
+ unlinkPage(pPg);
+ assert( pPg->pgno==0 );
+
+ *ppPg = pPg;
+ return SQLITE_OK;
+}
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+/*
+** This function is called to free superfluous dynamically allocated memory
+** held by the pager system. Memory in use by any SQLite pager allocated
+** by the current thread may be sqlite3_free()ed.
+**
+** nReq is the number of bytes of memory required. Once this much has
+** been released, the function returns. The return value is the total number
+** of bytes of memory released.
+*/
+SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int nReq){
+ int nReleased = 0; /* Bytes of memory released so far */
+ Pager *pPager; /* For looping over pagers */
+ BusyHandler *savedBusy; /* Saved copy of the busy handler */
+ int rc = SQLITE_OK;
+
+ /* Acquire the memory-management mutex
+ */
+#ifndef SQLITE_MUTEX_NOOP
+ sqlite3_mutex *mutex; /* The MEM2 mutex */
+ mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
+#endif
+ sqlite3_mutex_enter(mutex);
+
+ /* Signal all database connections that memory management wants
+ ** to have access to the pagers.
+ */
+ for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
+ pPager->iInUseMM = 1;
+ }
+
+ while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){
+ PgHdr *pPg;
+ PgHdr *pRecycled;
+
+ /* Try to find a page to recycle that does not require a sync(). If
+ ** this is not possible, find one that does require a sync().
+ */
+ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+ pPg = sqlite3LruPageList.pFirstSynced;
+ while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){
+ pPg = pPg->gfree.pNext;
+ }
+ if( !pPg ){
+ pPg = sqlite3LruPageList.pFirst;
+ while( pPg && pPg->pPager->iInUseDB ){
+ pPg = pPg->gfree.pNext;
+ }
+ }
+ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
+
+ /* If pPg==0, then the block above has failed to find a page to
+ ** recycle. In this case return early - no further memory will
+ ** be released.
+ */
+ if( !pPg ) break;
+
+ pPager = pPg->pPager;
+ assert(!pPg->needSync || pPg==pPager->lru.pFirst);
+ assert(pPg->needSync || pPg==pPager->lru.pFirstSynced);
+
+ savedBusy = pPager->pBusyHandler;
+ pPager->pBusyHandler = 0;
+ rc = pager_recycle(pPager, &pRecycled);
+ pPager->pBusyHandler = savedBusy;
+ assert(pRecycled==pPg || rc!=SQLITE_OK);
if( rc==SQLITE_OK ){
- if( nPage==0 ){
- sqlite3OsDelete(pVfs, pPager->zJournal, 0);
+ /* We've found a page to free. At this point the page has been
+ ** removed from the page hash-table, free-list and synced-list
+ ** (pFirstSynced). It is still in the all pages (pAll) list.
+ ** Remove it from this list before freeing.
+ **
+ ** Todo: Check the Pager.pStmt list to make sure this is Ok. It
+ ** probably is though.
+ */
+ PgHdr *pTmp;
+ assert( pPg );
+ if( pPg==pPager->pAll ){
+ assert(pPg->pPrevAll==0);
+ assert(pPg->pNextAll==0 || pPg->pNextAll->pPrevAll==pPg);
+ pPager->pAll = pPg->pNextAll;
+ if( pPager->pAll ){
+ pPager->pAll->pPrevAll = 0;
+ }
}else{
- *pExists = 1;
+ assert(pPg->pPrevAll);
+ assert(pPg->pPrevAll->pNextAll==pPg);
+ pTmp = pPg->pPrevAll;
+ pTmp->pNextAll = pPg->pNextAll;
+ if( pTmp->pNextAll ){
+ pTmp->pNextAll->pPrevAll = pTmp;
+ }
}
+ nReleased += (
+ sizeof(*pPg) + pPager->pageSize
+ + sizeof(u32) + pPager->nExtra
+ + MEMDB*sizeof(PgHistory)
+ );
+ IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno));
+ PAGER_INCR(sqlite3_pager_pgfree_count);
+ sqlite3PageFree(pPg->pData);
+ sqlite3_free(pPg);
+ pPager->nPage--;
+ }else{
+ /* An error occured whilst writing to the database file or
+ ** journal in pager_recycle(). The error is not returned to the
+ ** caller of this function. Instead, set the Pager.errCode variable.
+ ** The error will be returned to the user (or users, in the case
+ ** of a shared pager cache) of the pager for which the error occured.
+ */
+ assert(
+ (rc&0xff)==SQLITE_IOERR ||
+ rc==SQLITE_FULL ||
+ rc==SQLITE_BUSY
+ );
+ assert( pPager->state>=PAGER_RESERVED );
+ pager_error(pPager, rc);
}
}
- return rc;
+
+ /* Clear the memory management flags and release the mutex
+ */
+ for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
+ pPager->iInUseMM = 0;
+ }
+ sqlite3_mutex_leave(mutex);
+
+ /* Return the number of bytes released
+ */
+ return nReleased;
}
+#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
/*
** Read the content of page pPg out of the database file.
@@ -31259,15 +29546,15 @@ static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){
return SQLITE_IOERR_SHORT_READ;
}
offset = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, offset);
+ rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize, offset);
PAGER_INCR(sqlite3_pager_readdb_count);
PAGER_INCR(pPager->nRead);
IOTRACE(("PGIN %p %d\n", pPager, pgno));
if( pgno==1 ){
- memcpy(&pPager->dbFileVers, &((u8*)pPg->pData)[24],
+ memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24],
sizeof(pPager->dbFileVers));
}
- CODEC1(pPager, pPg->pData, pPg->pgno, 3);
+ CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
PAGERTRACE4("FETCH %d page %d hash(%08x)\n",
PAGERID(pPager), pPg->pgno, pager_pagehash(pPg));
return rc;
@@ -31292,9 +29579,7 @@ static int pagerSharedLock(Pager *pPager){
** the error. Discard the contents of the pager-cache and treat any
** open journal file as a hot-journal.
*/
- if( !MEMDB && pPager->exclusiveMode
- && sqlite3PcacheRefCount(pPager->pPCache)==0 && pPager->errCode
- ){
+ if( !MEMDB && pPager->exclusiveMode && pPager->nRef==0 && pPager->errCode ){
if( pPager->journalOpen ){
isErrorReset = 1;
}
@@ -31312,135 +29597,140 @@ static int pagerSharedLock(Pager *pPager){
if( pPager->state==PAGER_UNLOCK || isErrorReset ){
sqlite3_vfs *pVfs = pPager->pVfs;
- int isHotJournal;
- assert( !MEMDB );
- assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
- if( !pPager->noReadlock ){
- rc = pager_wait_on_lock(pPager, SHARED_LOCK);
- if( rc!=SQLITE_OK ){
- assert( pPager->state==PAGER_UNLOCK );
- return pager_error(pPager, rc);
+ if( !MEMDB ){
+ int isHotJournal;
+ assert( pPager->nRef==0 );
+ if( !pPager->noReadlock ){
+ rc = pager_wait_on_lock(pPager, SHARED_LOCK);
+ if( rc!=SQLITE_OK ){
+ assert( pPager->state==PAGER_UNLOCK );
+ return pager_error(pPager, rc);
+ }
+ assert( pPager->state>=SHARED_LOCK );
}
- assert( pPager->state>=SHARED_LOCK );
- }
-
- /* If a journal file exists, and there is no RESERVED lock on the
- ** database file, then it either needs to be played back or deleted.
- */
- if( !isErrorReset ){
- rc = hasHotJournal(pPager, &isHotJournal);
- if( rc!=SQLITE_OK ){
- goto failed;
- }
- }
- if( isErrorReset || isHotJournal ){
- /* Get an EXCLUSIVE lock on the database file. At this point it is
- ** important that a RESERVED lock is not obtained on the way to the
- ** EXCLUSIVE lock. If it were, another process might open the
- ** database file, detect the RESERVED lock, and conclude that the
- ** database is safe to read while this process is still rolling it
- ** back.
- **
- ** Because the intermediate RESERVED lock is not requested, the
- ** second process will get to this point in the code and fail to
- ** obtain its own EXCLUSIVE lock on the database file.
+
+ /* If a journal file exists, and there is no RESERVED lock on the
+ ** database file, then it either needs to be played back or deleted.
*/
- if( pPager->state<EXCLUSIVE_LOCK ){
- rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
+ if( !isErrorReset ){
+ rc = hasHotJournal(pPager, &isHotJournal);
if( rc!=SQLITE_OK ){
- rc = pager_error(pPager, rc);
goto failed;
}
- pPager->state = PAGER_EXCLUSIVE;
}
+ if( isErrorReset || isHotJournal ){
+ /* Get an EXCLUSIVE lock on the database file. At this point it is
+ ** important that a RESERVED lock is not obtained on the way to the
+ ** EXCLUSIVE lock. If it were, another process might open the
+ ** database file, detect the RESERVED lock, and conclude that the
+ ** database is safe to read while this process is still rolling it
+ ** back.
+ **
+ ** Because the intermediate RESERVED lock is not requested, the
+ ** second process will get to this point in the code and fail to
+ ** obtain its own EXCLUSIVE lock on the database file.
+ */
+ if( pPager->state<EXCLUSIVE_LOCK ){
+ rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
+ if( rc!=SQLITE_OK ){
+ rc = pager_error(pPager, rc);
+ goto failed;
+ }
+ pPager->state = PAGER_EXCLUSIVE;
+ }
- /* Open the journal for read/write access. This is because in
- ** exclusive-access mode the file descriptor will be kept open and
- ** possibly used for a transaction later on. On some systems, the
- ** OsTruncate() call used in exclusive-access mode also requires
- ** a read/write file handle.
- */
- if( !isErrorReset && pPager->journalOpen==0 ){
- int res;
- rc = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS,&res);
- if( rc==SQLITE_OK ){
- if( res ){
- int fout = 0;
- int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
- assert( !pPager->tempFile );
- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
- assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
- if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
- rc = SQLITE_CANTOPEN;
- sqlite3OsClose(pPager->jfd);
+ /* Open the journal for read/write access. This is because in
+ ** exclusive-access mode the file descriptor will be kept open and
+ ** possibly used for a transaction later on. On some systems, the
+ ** OsTruncate() call used in exclusive-access mode also requires
+ ** a read/write file handle.
+ */
+ if( !isErrorReset && pPager->journalOpen==0 ){
+ int res;
+ rc = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS,&res);
+ if( rc==SQLITE_OK ){
+ if( res ){
+ int fout = 0;
+ int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
+ assert( !pPager->tempFile );
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
+ assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
+ if( fout&SQLITE_OPEN_READONLY ){
+ rc = SQLITE_BUSY;
+ sqlite3OsClose(pPager->jfd);
+ }
+ }else{
+ /* If the journal does not exist, that means some other process
+ ** has already rolled it back */
+ rc = SQLITE_BUSY;
}
- }else{
- /* If the journal does not exist, that means some other process
- ** has already rolled it back */
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK
+ && rc!=SQLITE_IOERR_NOMEM
+ ){
rc = SQLITE_BUSY;
}
+ goto failed;
}
- }
- if( rc!=SQLITE_OK ){
- goto failed;
- }
- pPager->journalOpen = 1;
- pPager->journalStarted = 0;
- pPager->journalOff = 0;
- pPager->setMaster = 0;
- pPager->journalHdr = 0;
+ pPager->journalOpen = 1;
+ pPager->journalStarted = 0;
+ pPager->journalOff = 0;
+ pPager->setMaster = 0;
+ pPager->journalHdr = 0;
- /* Playback and delete the journal. Drop the database write
- ** lock and reacquire the read lock.
- */
- rc = pager_playback(pPager, 1);
- if( rc!=SQLITE_OK ){
- rc = pager_error(pPager, rc);
- goto failed;
+ /* Playback and delete the journal. Drop the database write
+ ** lock and reacquire the read lock.
+ */
+ rc = pager_playback(pPager, 1);
+ if( rc!=SQLITE_OK ){
+ rc = pager_error(pPager, rc);
+ goto failed;
+ }
+ assert(pPager->state==PAGER_SHARED ||
+ (pPager->exclusiveMode && pPager->state>PAGER_SHARED)
+ );
}
- assert(pPager->state==PAGER_SHARED ||
- (pPager->exclusiveMode && pPager->state>PAGER_SHARED)
- );
- }
- if( sqlite3PcachePagecount(pPager->pPCache)>0 ){
- /* The shared-lock has just been acquired on the database file
- ** and there are already pages in the cache (from a previous
- ** read or write transaction). Check to see if the database
- ** has been modified. If the database has changed, flush the
- ** cache.
- **
- ** Database changes is detected by looking at 15 bytes beginning
- ** at offset 24 into the file. The first 4 of these 16 bytes are
- ** a 32-bit counter that is incremented with each change. The
- ** other bytes change randomly with each file change when
- ** a codec is in use.
- **
- ** There is a vanishingly small chance that a change will not be
- ** detected. The chance of an undetected change is so small that
- ** it can be neglected.
- */
- char dbFileVers[sizeof(pPager->dbFileVers)];
- sqlite3PagerPagecount(pPager, 0);
-
- if( pPager->errCode ){
- rc = pPager->errCode;
- goto failed;
- }
+ if( pPager->pAll ){
+ /* The shared-lock has just been acquired on the database file
+ ** and there are already pages in the cache (from a previous
+ ** read or write transaction). Check to see if the database
+ ** has been modified. If the database has changed, flush the
+ ** cache.
+ **
+ ** Database changes is detected by looking at 15 bytes beginning
+ ** at offset 24 into the file. The first 4 of these 16 bytes are
+ ** a 32-bit counter that is incremented with each change. The
+ ** other bytes change randomly with each file change when
+ ** a codec is in use.
+ **
+ ** There is a vanishingly small chance that a change will not be
+ ** detected. The chance of an undetected change is so small that
+ ** it can be neglected.
+ */
+ char dbFileVers[sizeof(pPager->dbFileVers)];
+ sqlite3PagerPagecount(pPager, 0);
- assert( pPager->dbSizeValid );
- if( pPager->dbSize>0 ){
- IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
- rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
- if( rc!=SQLITE_OK ){
+ if( pPager->errCode ){
+ rc = pPager->errCode;
goto failed;
}
- }else{
- memset(dbFileVers, 0, sizeof(dbFileVers));
- }
- if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
- pager_reset(pPager);
+ if( pPager->dbSize>0 ){
+ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
+ rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
+ if( rc!=SQLITE_OK ){
+ goto failed;
+ }
+ }else{
+ memset(dbFileVers, 0, sizeof(dbFileVers));
+ }
+
+ if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
+ pager_reset(pPager);
+ }
}
}
assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED );
@@ -31458,6 +29748,104 @@ static int pagerSharedLock(Pager *pPager){
}
/*
+** Allocate a PgHdr object. Either create a new one or reuse
+** an existing one that is not otherwise in use.
+**
+** A new PgHdr structure is created if any of the following are
+** true:
+**
+** (1) We have not exceeded our maximum allocated cache size
+** as set by the "PRAGMA cache_size" command.
+**
+** (2) There are no unused PgHdr objects available at this time.
+**
+** (3) This is an in-memory database.
+**
+** (4) There are no PgHdr objects that do not require a journal
+** file sync and a sync of the journal file is currently
+** prohibited.
+**
+** Otherwise, reuse an existing PgHdr. In other words, reuse an
+** existing PgHdr if all of the following are true:
+**
+** (1) We have reached or exceeded the maximum cache size
+** allowed by "PRAGMA cache_size".
+**
+** (2) There is a PgHdr available with PgHdr->nRef==0
+**
+** (3) We are not in an in-memory database
+**
+** (4) Either there is an available PgHdr that does not need
+** to be synced to disk or else disk syncing is currently
+** allowed.
+*/
+static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
+ int rc = SQLITE_OK;
+ PgHdr *pPg;
+ int nByteHdr;
+
+ /* Create a new PgHdr if any of the four conditions defined
+ ** above are met: */
+ if( pPager->nPage<pPager->mxPage
+ || pPager->lru.pFirst==0
+ || MEMDB
+ || (pPager->lru.pFirstSynced==0 && pPager->doNotSync)
+ ){
+ void *pData;
+ if( pPager->nPage>=pPager->nHash ){
+ pager_resize_hash_table(pPager,
+ pPager->nHash<256 ? 256 : pPager->nHash*2);
+ if( pPager->nHash==0 ){
+ rc = SQLITE_NOMEM;
+ goto pager_allocate_out;
+ }
+ }
+ pagerLeave(pPager);
+ nByteHdr = sizeof(*pPg) + sizeof(u32) + pPager->nExtra
+ + MEMDB*sizeof(PgHistory);
+ pPg = sqlite3Malloc( nByteHdr );
+ if( pPg ){
+ pData = sqlite3PageMalloc( pPager->pageSize );
+ if( pData==0 ){
+ sqlite3_free(pPg);
+ pPg = 0;
+ }
+ }
+ pagerEnter(pPager);
+ if( pPg==0 ){
+ rc = SQLITE_NOMEM;
+ goto pager_allocate_out;
+ }
+ memset(pPg, 0, nByteHdr);
+ pPg->pData = pData;
+ pPg->pPager = pPager;
+ pPg->pNextAll = pPager->pAll;
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ if( pPg->pNextAll ){
+ pPg->pNextAll->pPrevAll = pPg;
+ }
+#endif
+ pPager->pAll = pPg;
+ pPager->nPage++;
+ }else{
+ /* Recycle an existing page with a zero ref-count. */
+ rc = pager_recycle(pPager, &pPg);
+ if( rc==SQLITE_BUSY ){
+ rc = SQLITE_IOERR_BLOCKED;
+ }
+ if( rc!=SQLITE_OK ){
+ goto pager_allocate_out;
+ }
+ assert( pPager->state>=SHARED_LOCK );
+ assert(pPg);
+ }
+ *ppPg = pPg;
+
+pager_allocate_out:
+ return rc;
+}
+
+/*
** Make sure we have the content for a page. If the page was
** previously acquired with noContent==1, then the content was
** just initialized to zeros instead of being read from disk.
@@ -31465,10 +29853,10 @@ static int pagerSharedLock(Pager *pPager){
** have it. Read it in if we do not have it already.
*/
static int pager_get_content(PgHdr *pPg){
- if( pPg->flags&PGHDR_NEED_READ ){
+ if( pPg->needRead ){
int rc = readDbPage(pPg->pPager, pPg, pPg->pgno);
if( rc==SQLITE_OK ){
- pPg->flags &= ~PGHDR_NEED_READ;
+ pPg->needRead = 0;
}else{
return rc;
}
@@ -31477,30 +29865,6 @@ static int pager_get_content(PgHdr *pPg){
}
/*
-** If the reference count has reached zero, and the pager is not in the
-** middle of a write transaction or opened in exclusive mode, unlock it.
-*/
-static void pagerUnlockIfUnused(Pager *pPager){
- if( (sqlite3PcacheRefCount(pPager->pPCache)==0)
- && (!pPager->exclusiveMode || pPager->journalOff>0)
- ){
- pagerUnlockAndRollback(pPager);
- }
-}
-
-/*
-** Drop a page from the cache using sqlite3PcacheDrop().
-**
-** If this means there are now no pages with references to them, a rollback
-** occurs and the lock on the database is removed.
-*/
-static void pagerDropPage(DbPage *pPg){
- Pager *pPager = pPg->pPager;
- sqlite3PcacheDrop(pPg);
- pagerUnlockIfUnused(pPager);
-}
-
-/*
** Acquire a page.
**
** A read lock on the disk file is obtained when the first page is acquired.
@@ -31532,19 +29896,16 @@ static void pagerDropPage(DbPage *pPg){
** called again with noContent==0, that means that the content is needed
** and the disk read should occur at that point.
*/
-SQLITE_PRIVATE int sqlite3PagerAcquire(
+static int pagerAcquire(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
DbPage **ppPage, /* Write a pointer to the page here */
int noContent /* Do not bother reading content from disk if true */
){
- PgHdr *pPg = 0;
+ PgHdr *pPg;
int rc;
- assert( pPager->state==PAGER_UNLOCK
- || sqlite3PcacheRefCount(pPager->pPCache)>0
- || pgno==1
- );
+ assert( pPager->state==PAGER_UNLOCK || pPager->nRef>0 || pgno==1 );
/* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
** number greater than this, or zero, is requested.
@@ -31568,62 +29929,97 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
}
assert( pPager->state!=PAGER_UNLOCK );
- rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, &pPg);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- if( pPg->pPager==0 ){
- /* The pager cache has created a new page. Its content needs to
- ** be initialized.
- */
+ pPg = pager_lookup(pPager, pgno);
+ if( pPg==0 ){
+ /* The requested page is not in the page cache. */
int nMax;
+ int h;
PAGER_INCR(pPager->nMiss);
- pPg->pPager = pPager;
- memset(pPg->pExtra, 0, pPager->nExtra);
+ rc = pagerAllocatePage(pPager, &pPg);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pPg->pgno = pgno;
+ assert( !MEMDB || pgno>pPager->stmtSize );
+ pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
+ pPg->needSync = 0;
+
+ makeClean(pPg);
+ pPg->nRef = 1;
+
+ pPager->nRef++;
+ if( pPager->nExtra>0 ){
+ memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
+ }
rc = sqlite3PagerPagecount(pPager, &nMax);
if( rc!=SQLITE_OK ){
sqlite3PagerUnref(pPg);
return rc;
}
- if( nMax<(int)pgno || MEMDB || noContent ){
+ /* Populate the page with data, either by reading from the database
+ ** file, or by setting the entire page to zero.
+ */
+ if( nMax<(int)pgno || MEMDB || (noContent && !pPager->alwaysRollback) ){
if( pgno>pPager->mxPgno ){
sqlite3PagerUnref(pPg);
return SQLITE_FULL;
}
- memset(pPg->pData, 0, pPager->pageSize);
- if( noContent ){
- pPg->flags |= PGHDR_NEED_READ;
- }
+ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
+ pPg->needRead = noContent && !pPager->alwaysRollback;
IOTRACE(("ZERO %p %d\n", pPager, pgno));
}else{
rc = readDbPage(pPager, pPg, pgno);
if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
- /* sqlite3PagerUnref(pPg); */
- pagerDropPage(pPg);
+ pPg->pgno = 0;
+ sqlite3PagerUnref(pPg);
return rc;
}
+ pPg->needRead = 0;
}
+
+ /* Link the page into the page hash table */
+ h = pgno & (pPager->nHash-1);
+ assert( pgno!=0 );
+ pPg->pNextHash = pPager->aHash[h];
+ pPager->aHash[h] = pPg;
+ if( pPg->pNextHash ){
+ assert( pPg->pNextHash->pPrevHash==0 );
+ pPg->pNextHash->pPrevHash = pPg;
+ }
+
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}else{
/* The requested page is in the page cache. */
- assert(sqlite3PcacheRefCount(pPager->pPCache)>0 || pgno==1);
+ assert(pPager->nRef>0 || pgno==1);
PAGER_INCR(pPager->nHit);
if( !noContent ){
rc = pager_get_content(pPg);
if( rc ){
- sqlite3PagerUnref(pPg);
return rc;
}
}
+ page_ref(pPg);
}
-
*ppPage = pPg;
return SQLITE_OK;
}
+SQLITE_PRIVATE int sqlite3PagerAcquire(
+ Pager *pPager, /* The pager open on the database file */
+ Pgno pgno, /* Page number to fetch */
+ DbPage **ppPage, /* Write a pointer to the page here */
+ int noContent /* Do not bother reading content from disk if true */
+){
+ int rc;
+ pagerEnter(pPager);
+ rc = pagerAcquire(pPager, pgno, ppPage, noContent);
+ pagerLeave(pPager);
+ return rc;
+}
+
/*
** Acquire a page if it is already in the in-memory cache. Do
@@ -31638,15 +30034,19 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
*/
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
PgHdr *pPg = 0;
+
assert( pPager!=0 );
assert( pgno!=0 );
- if( (pPager->state!=PAGER_UNLOCK)
- && (pPager->errCode==SQLITE_OK || pPager->errCode==SQLITE_FULL)
- ){
- sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
+ pagerEnter(pPager);
+ if( pPager->state==PAGER_UNLOCK ){
+ assert( !pPager->pAll || pPager->exclusiveMode );
+ }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
+ /* Do nothing */
+ }else if( (pPg = pager_lookup(pPager, pgno))!=0 ){
+ page_ref(pPg);
}
-
+ pagerLeave(pPager);
return pPg;
}
@@ -31659,11 +30059,39 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
** removed.
*/
SQLITE_PRIVATE int sqlite3PagerUnref(DbPage *pPg){
- if( pPg ){
- Pager *pPager = pPg->pPager;
- sqlite3PcacheRelease(pPg);
- pagerUnlockIfUnused(pPager);
+ Pager *pPager;
+
+ if( pPg==0 ) return SQLITE_OK;
+ pPager = pPg->pPager;
+
+ /* Decrement the reference count for this page
+ */
+ assert( pPg->nRef>0 );
+ pagerEnter(pPg->pPager);
+ pPg->nRef--;
+
+ CHECK_PAGE(pPg);
+
+ /* When the number of references to a page reach 0, call the
+ ** destructor and add the page to the freelist.
+ */
+ if( pPg->nRef==0 ){
+
+ lruListAdd(pPg);
+ if( pPager->xDestructor ){
+ pPager->xDestructor(pPg, pPager->pageSize);
+ }
+
+ /* When all pages reach the freelist, drop the read lock from
+ ** the database file.
+ */
+ pPager->nRef--;
+ assert( pPager->nRef>=0 );
+ if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){
+ pagerUnlockAndRollback(pPager);
+ }
}
+ pagerLeave(pPager);
return SQLITE_OK;
}
@@ -31679,11 +30107,14 @@ static int pager_open_journal(Pager *pPager){
int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE);
int rc;
+ assert( !MEMDB );
assert( pPager->state>=PAGER_RESERVED );
assert( pPager->useJournal );
assert( pPager->pInJournal==0 );
sqlite3PagerPagecount(pPager, 0);
+ pagerLeave(pPager);
pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
+ pagerEnter(pPager);
if( pPager->pInJournal==0 ){
rc = SQLITE_NOMEM;
goto failed_to_open_journal;
@@ -31695,18 +30126,13 @@ static int pager_open_journal(Pager *pPager){
}else{
flags |= (SQLITE_OPEN_MAIN_JOURNAL);
}
- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
- sqlite3MemJournalOpen(pPager->jfd);
- rc = SQLITE_OK;
- }else{
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
- rc = sqlite3JournalOpen(
- pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
- );
+ rc = sqlite3JournalOpen(
+ pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
+ );
#else
- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
#endif
- }
assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
pPager->journalOff = 0;
pPager->setMaster = 0;
@@ -31721,6 +30147,7 @@ static int pager_open_journal(Pager *pPager){
pPager->journalOpen = 1;
pPager->journalStarted = 0;
pPager->needSync = 0;
+ pPager->alwaysRollback = 0;
pPager->nRec = 0;
if( pPager->errCode ){
rc = pPager->errCode;
@@ -31777,26 +30204,32 @@ failed_to_open_journal:
SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
+ pagerEnter(pPager);
assert( pPg->nRef>0 );
assert( pPager->state!=PAGER_UNLOCK );
if( pPager->state==PAGER_SHARED ){
assert( pPager->pInJournal==0 );
- assert( !MEMDB );
- rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
- if( rc==SQLITE_OK ){
- pPager->state = PAGER_RESERVED;
- if( exFlag ){
- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+ if( MEMDB ){
+ pPager->state = PAGER_EXCLUSIVE;
+ pPager->origDbSize = pPager->dbSize;
+ }else{
+ rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
+ if( rc==SQLITE_OK ){
+ pPager->state = PAGER_RESERVED;
+ if( exFlag ){
+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ pagerLeave(pPager);
+ return rc;
+ }
+ pPager->dirtyCache = 0;
+ PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager));
+ if( pPager->useJournal && !pPager->tempFile
+ && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
+ rc = pager_open_journal(pPager);
}
- }
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pPager->dirtyCache = 0;
- PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager));
- if( pPager->useJournal && !pPager->tempFile
- && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
- rc = pager_open_journal(pPager);
}
}else if( pPager->journalOpen && pPager->journalOff==0 ){
/* This happens when the pager was in exclusive-access mode the last
@@ -31809,7 +30242,9 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
assert( pPager->origDbSize==0 );
assert( pPager->pInJournal==0 );
sqlite3PagerPagecount(pPager, 0);
+ pagerLeave(pPager);
pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
+ pagerEnter(pPager);
if( !pPager->pInJournal ){
rc = SQLITE_NOMEM;
}else{
@@ -31818,10 +30253,50 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
}
}
assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK );
+ pagerLeave(pPager);
return rc;
}
/*
+** Make a page dirty. Set its dirty flag and add it to the dirty
+** page list.
+*/
+static void makeDirty(PgHdr *pPg){
+ if( pPg->dirty==0 ){
+ Pager *pPager = pPg->pPager;
+ pPg->dirty = 1;
+ pPg->pDirty = pPager->pDirty;
+ if( pPager->pDirty ){
+ pPager->pDirty->pPrevDirty = pPg;
+ }
+ pPg->pPrevDirty = 0;
+ pPager->pDirty = pPg;
+ }
+}
+
+/*
+** Make a page clean. Clear its dirty bit and remove it from the
+** dirty page list.
+*/
+static void makeClean(PgHdr *pPg){
+ if( pPg->dirty ){
+ pPg->dirty = 0;
+ if( pPg->pDirty ){
+ assert( pPg->pDirty->pPrevDirty==pPg );
+ pPg->pDirty->pPrevDirty = pPg->pPrevDirty;
+ }
+ if( pPg->pPrevDirty ){
+ assert( pPg->pPrevDirty->pDirty==pPg );
+ pPg->pPrevDirty->pDirty = pPg->pDirty;
+ }else{
+ assert( pPg->pPager->pDirty==pPg );
+ pPg->pPager->pDirty = pPg->pDirty;
+ }
+ }
+}
+
+
+/*
** Mark a data page as writeable. The page is written into the journal
** if it is not there already. This routine must be called before making
** changes to a page.
@@ -31839,7 +30314,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
** reset.
*/
static int pager_write(PgHdr *pPg){
- void *pData = pPg->pData;
+ void *pData = PGHDR_TO_DATA(pPg);
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
@@ -31872,8 +30347,8 @@ static int pager_write(PgHdr *pPg){
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
- sqlite3PcacheMakeDirty(pPg);
- if( pageInJournal(pPg) && (pageInStatement(pPg) || pPager->stmtInUse==0) ){
+ makeDirty(pPg);
+ if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){
pPager->dirtyCache = 1;
pPager->dbModified = 1;
}else{
@@ -31903,61 +30378,67 @@ static int pager_write(PgHdr *pPg){
** EXCLUSIVE lock on the main database file. Write the current page to
** the transaction journal if it is not there already.
*/
- if( !pageInJournal(pPg) && pPager->journalOpen ){
- if( pPg->pgno<=pPager->origDbSize ){
- u32 cksum;
- char *pData2;
-
- /* We should never write to the journal file the page that
- ** contains the database locks. The following assert verifies
- ** that we do not. */
- assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
- pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
- cksum = pager_cksum(pPager, (u8*)pData2);
- rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize,
- pPager->journalOff + 4);
- pPager->journalOff += pPager->pageSize+4;
- }
- if( rc==SQLITE_OK ){
- rc = write32bits(pPager->jfd, pPager->journalOff, cksum);
- pPager->journalOff += 4;
- }
- IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
- pPager->journalOff, pPager->pageSize));
- PAGER_INCR(sqlite3_pager_writej_count);
- PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n",
- PAGERID(pPager), pPg->pgno,
- ((pPg->flags&PGHDR_NEED_SYNC)?1:0), pager_pagehash(pPg));
-
- /* An error has occured writing to the journal file. The
- ** transaction will be rolled back by the layer above.
- */
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ if( !pPg->inJournal && (pPager->journalOpen || MEMDB) ){
+ if( (int)pPg->pgno <= pPager->origDbSize ){
+ if( MEMDB ){
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
+ assert( pHist->pOrig==0 );
+ pHist->pOrig = sqlite3PageMalloc( pPager->pageSize );
+ if( !pHist->pOrig ){
+ return SQLITE_NOMEM;
+ }
+ memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
+ }else{
+ u32 cksum;
+ char *pData2;
+
+ /* We should never write to the journal file the page that
+ ** contains the database locks. The following assert verifies
+ ** that we do not. */
+ assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
+ pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
+ cksum = pager_cksum(pPager, (u8*)pData2);
+ rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize,
+ pPager->journalOff + 4);
+ pPager->journalOff += pPager->pageSize+4;
+ }
+ if( rc==SQLITE_OK ){
+ rc = write32bits(pPager->jfd, pPager->journalOff, cksum);
+ pPager->journalOff += 4;
+ }
+ IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
+ pPager->journalOff, pPager->pageSize));
+ PAGER_INCR(sqlite3_pager_writej_count);
+ PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n",
+ PAGERID(pPager), pPg->pgno, pPg->needSync, pager_pagehash(pPg));
+
+ /* An error has occured writing to the journal file. The
+ ** transaction will be rolled back by the layer above.
+ */
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
- pPager->nRec++;
- assert( pPager->pInJournal!=0 );
- sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
- if( !pPager->noSync ){
- pPg->flags |= PGHDR_NEED_SYNC;
- }
- if( pPager->stmtInUse ){
- sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
+ pPager->nRec++;
+ assert( pPager->pInJournal!=0 );
+ sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
+ pPg->needSync = !pPager->noSync;
+ if( pPager->stmtInUse ){
+ sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
+ }
}
}else{
- if( !pPager->journalStarted && !pPager->noSync ){
- pPg->flags |= PGHDR_NEED_SYNC;
- }
+ pPg->needSync = !pPager->journalStarted && !pPager->noSync;
PAGERTRACE4("APPEND %d page %d needSync=%d\n",
- PAGERID(pPager), pPg->pgno,
- ((pPg->flags&PGHDR_NEED_SYNC)?1:0));
+ PAGERID(pPager), pPg->pgno, pPg->needSync);
}
- if( pPg->flags&PGHDR_NEED_SYNC ){
+ if( pPg->needSync ){
pPager->needSync = 1;
}
+ pPg->inJournal = 1;
}
/* If the statement journal is open and the page is not in it,
@@ -31967,31 +30448,42 @@ static int pager_write(PgHdr *pPg){
*/
if( pPager->stmtInUse
&& !pageInStatement(pPg)
- && pPg->pgno<=pPager->stmtSize
+ && (int)pPg->pgno<=pPager->stmtSize
){
- i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
- char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
- assert( pageInJournal(pPg) || pPg->pgno>pPager->origDbSize );
- rc = write32bits(pPager->stfd, offset, pPg->pgno);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4);
- }
- PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
- if( rc!=SQLITE_OK ){
- return rc;
+ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
+ if( MEMDB ){
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ assert( pHist->pStmt==0 );
+ pHist->pStmt = sqlite3PageMalloc( pPager->pageSize );
+ if( pHist->pStmt ){
+ memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
+ }
+ PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
+ page_add_to_stmt_list(pPg);
+ }else{
+ i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
+ char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
+ rc = write32bits(pPager->stfd, offset, pPg->pgno);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4);
+ }
+ PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pPager->stmtNRec++;
+ assert( pPager->pInStmt!=0 );
+ sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
- pPager->stmtNRec++;
- assert( pPager->pInStmt!=0 );
- sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
}
/* Update the database size and return.
*/
assert( pPager->state>=PAGER_SHARED );
- if( pPager->dbSize<pPg->pgno ){
+ if( pPager->dbSize<(int)pPg->pgno ){
pPager->dbSize = pPg->pgno;
- if( pPager->dbSize==(PAGER_MJ_PGNO(pPager)-1) ){
+ if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
pPager->dbSize++;
}
}
@@ -32015,7 +30507,8 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
Pager *pPager = pPg->pPager;
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
- if( nPagePerSector>1 ){
+ pagerEnter(pPager);
+ if( !MEMDB && nPagePerSector>1 ){
Pgno nPageCount; /* Total number of pages in database file */
Pgno pg1; /* First page of the sector pPg is located on. */
int nPage; /* Number of pages starting at pg1 to journal */
@@ -32025,7 +30518,6 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
/* Set the doNotSync flag to 1. This is because we cannot allow a journal
** header to be written between the pages journaled by this function.
*/
- assert( !MEMDB );
assert( pPager->doNotSync==0 );
pPager->doNotSync = 1;
@@ -32055,17 +30547,16 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
rc = sqlite3PagerGet(pPager, pg, &pPage);
if( rc==SQLITE_OK ){
rc = pager_write(pPage);
- if( pPage->flags&PGHDR_NEED_SYNC ){
+ if( pPage->needSync ){
needSync = 1;
}
sqlite3PagerUnref(pPage);
}
}
}else if( (pPage = pager_lookup(pPager, pg))!=0 ){
- if( pPage->flags&PGHDR_NEED_SYNC ){
+ if( pPage->needSync ){
needSync = 1;
}
- sqlite3PagerUnref(pPage);
}
}
@@ -32076,11 +30567,9 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
** before any of them can be written out to the database file.
*/
if( needSync ){
- assert( !MEMDB && pPager->noSync==0 );
for(ii=0; ii<nPage && needSync; ii++){
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
- if( pPage ) pPage->flags |= PGHDR_NEED_SYNC;
- sqlite3PagerUnref(pPage);
+ if( pPage ) pPage->needSync = 1;
}
assert(pPager->needSync);
}
@@ -32090,6 +30579,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
}else{
rc = pager_write(pDbPage);
}
+ pagerLeave(pPager);
return rc;
}
@@ -32100,16 +30590,14 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
*/
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
- return pPg->flags&PGHDR_DIRTY;
+ return pPg->dirty;
}
#endif
/*
** A call to this routine tells the pager that it is not necessary to
** write the information on page pPg back to the disk, even though
-** that page might be marked as dirty. This happens, for example, when
-** the page has been added as a leaf of the freelist and so its
-** content no longer matters.
+** that page might be marked as dirty.
**
** The overlying software layer calls this routine when all of the data
** on the given page is unused. The pager marks the page as clean so
@@ -32130,26 +30618,16 @@ SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
** page contains critical data, we still need to be sure it gets
** rolled back in spite of the sqlite3PagerDontRollback() call.
*/
-SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage *pDbPage){
+SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage *pDbPage){
PgHdr *pPg = pDbPage;
Pager *pPager = pPg->pPager;
- int rc;
- if( pPg->pgno>pPager->origDbSize ){
- return SQLITE_OK;
- }
- if( pPager->pAlwaysRollback==0 ){
- assert( pPager->pInJournal );
- pPager->pAlwaysRollback = sqlite3BitvecCreate(pPager->origDbSize);
- if( !pPager->pAlwaysRollback ){
- return SQLITE_NOMEM;
- }
- }
- rc = sqlite3BitvecSet(pPager->pAlwaysRollback, pPg->pgno);
-
- if( rc==SQLITE_OK && (pPg->flags&PGHDR_DIRTY) && !pPager->stmtInUse ){
+ if( MEMDB ) return;
+ pagerEnter(pPager);
+ pPg->alwaysRollback = 1;
+ if( pPg->dirty && !pPager->stmtInUse ){
assert( pPager->state>=PAGER_SHARED );
- if( pPager->dbSize==pPg->pgno && pPager->origDbSize<pPager->dbSize ){
+ if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
/* If this pages is the last page in the file and the file has grown
** during the current transaction, then do NOT mark the page as clean.
** When the database file grows, we must make sure that the last page
@@ -32161,13 +30639,13 @@ SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage *pDbPage){
}else{
PAGERTRACE3("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager));
IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
- pPg->flags |= PGHDR_DONT_WRITE;
+ makeClean(pPg);
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}
}
- return rc;
+ pagerLeave(pPager);
}
/*
@@ -32184,22 +30662,21 @@ SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage *pDbPage){
SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){
Pager *pPager = pPg->pPager;
+ pagerEnter(pPager);
assert( pPager->state>=PAGER_RESERVED );
/* If the journal file is not open, or DontWrite() has been called on
** this page (DontWrite() sets the alwaysRollback flag), then this
** function is a no-op.
*/
- if( pPager->journalOpen==0
- || sqlite3BitvecTest(pPager->pAlwaysRollback, pPg->pgno)
- || pPg->pgno>pPager->origDbSize
- ){
+ if( pPager->journalOpen==0 || pPg->alwaysRollback || pPager->alwaysRollback ){
+ pagerLeave(pPager);
return;
}
+ assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */
#ifdef SQLITE_SECURE_DELETE
- if( sqlite3BitvecTest(pPager->pInJournal, pPg->pgno)!=0
- || pPg->pgno>pPager->origDbSize ){
+ if( pPg->inJournal || (int)pPg->pgno > pPager->origDbSize ){
return;
}
#endif
@@ -32218,13 +30695,15 @@ SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){
assert( pPager->pInJournal!=0 );
sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
- pPg->flags &= ~PGHDR_NEED_READ;
+ pPg->inJournal = 1;
+ pPg->needRead = 0;
if( pPager->stmtInUse ){
assert( pPager->stmtSize >= pPager->origDbSize );
sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
+ pagerLeave(pPager);
}
@@ -32256,11 +30735,11 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){
/* Increment the value just read and write it back to byte 24. */
change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
change_counter++;
- put32bits(((char*)pPgHdr->pData)+24, change_counter);
+ put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter);
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
if( isDirect && pPager->fd->pMethods ){
- const void *zBuf = pPgHdr->pData;
+ const void *zBuf = PGHDR_TO_DATA(pPgHdr);
rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
}
#endif
@@ -32277,11 +30756,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){
*/
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
int rc;
- if( MEMDB ){
- rc = SQLITE_OK;
- }else{
- rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
- }
+ pagerEnter(pPager);
+ rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
+ pagerLeave(pPager);
return rc;
}
@@ -32330,6 +30807,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n",
pPager->zFilename, zMaster, nTrunc);
+ pagerEnter(pPager);
/* If this is an in-memory db, or no pages have been written to, or this
** function has already been called, it is a no-op.
@@ -32349,14 +30827,12 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
** If the optimization can be used, then the journal file will never
** be created for this transaction.
*/
- int useAtomicWrite;
- pPg = sqlite3PcacheDirtyList(pPager->pPCache);
- useAtomicWrite = (
+ int useAtomicWrite = (
!zMaster &&
pPager->journalOpen &&
pPager->journalOff==jrnlBufferSize(pPager) &&
nTrunc==0 &&
- (pPg==0 || pPg->pDirty==0)
+ (0==pPager->pDirty || 0==pPager->pDirty->pDirty)
);
assert( pPager->journalOpen || pPager->journalMode==PAGER_JOURNALMODE_OFF );
if( useAtomicWrite ){
@@ -32398,7 +30874,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
** file.
*/
Pgno i;
- Pgno iSkip = PAGER_MJ_PGNO(pPager);
+ int iSkip = PAGER_MJ_PGNO(pPager);
for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){
if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
rc = sqlite3PagerGet(pPager, i, &pPg);
@@ -32425,7 +30901,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
#endif
/* Write all dirty pages to the database file */
- pPg = sqlite3PcacheDirtyList(pPager->pPCache);
+ pPg = pager_get_all_dirty_pages(pPager);
rc = pager_write_pagelist(pPg);
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED );
@@ -32438,7 +30914,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
*/
goto sync_exit;
}
- sqlite3PcacheCleanAll(pPager->pPCache);
+ pPager->pDirty = 0;
/* Sync the database file. */
if( !pPager->noSync && !noSync ){
@@ -32460,6 +30936,7 @@ sync_exit:
*/
rc = SQLITE_BUSY;
}
+ pagerLeave(pPager);
return rc;
}
@@ -32472,7 +30949,8 @@ sync_exit:
** is returned.
*/
SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
- int rc = SQLITE_OK;
+ int rc;
+ PgHdr *pPg;
if( pPager->errCode ){
return pPager->errCode;
@@ -32486,10 +30964,38 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
return SQLITE_OK;
}
+ pagerEnter(pPager);
PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
- assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dirtyCache );
+ if( MEMDB ){
+ pPg = pager_get_all_dirty_pages(pPager);
+ while( pPg ){
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ clearHistory(pHist);
+ pPg->dirty = 0;
+ pPg->inJournal = 0;
+ pHist->inStmt = 0;
+ pPg->needSync = 0;
+ pHist->pPrevStmt = pHist->pNextStmt = 0;
+ pPg = pPg->pDirty;
+ }
+ pPager->pDirty = 0;
+#ifndef NDEBUG
+ for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ assert( !pPg->alwaysRollback );
+ assert( !pHist->pOrig );
+ assert( !pHist->pStmt );
+ }
+#endif
+ pPager->pStmt = 0;
+ pPager->state = PAGER_SHARED;
+ pagerLeave(pPager);
+ return SQLITE_OK;
+ }
+ assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
rc = pager_end_transaction(pPager, pPager->setMaster);
rc = pager_error(pPager, rc);
+ pagerLeave(pPager);
return rc;
}
@@ -32506,37 +31012,77 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** SQLITE_OK is returned.
*/
SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
- int rc = SQLITE_OK;
+ int rc;
PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
+ if( MEMDB ){
+ PgHdr *p;
+ for(p=pPager->pAll; p; p=p->pNextAll){
+ PgHistory *pHist;
+ assert( !p->alwaysRollback );
+ if( !p->dirty ){
+ assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
+ assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
+ continue;
+ }
+
+ pHist = PGHDR_TO_HIST(p, pPager);
+ if( pHist->pOrig ){
+ memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
+ PAGERTRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager));
+ }else{
+ PAGERTRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager));
+ }
+ clearHistory(pHist);
+ p->dirty = 0;
+ p->inJournal = 0;
+ pHist->inStmt = 0;
+ pHist->pPrevStmt = pHist->pNextStmt = 0;
+ if( pPager->xReiniter ){
+ pPager->xReiniter(p, pPager->pageSize);
+ }
+ }
+ pPager->pDirty = 0;
+ pPager->pStmt = 0;
+ pPager->dbSize = pPager->origDbSize;
+ pager_truncate_cache(pPager);
+ pPager->stmtInUse = 0;
+ pPager->state = PAGER_SHARED;
+ return SQLITE_OK;
+ }
+
+ pagerEnter(pPager);
if( !pPager->dirtyCache || !pPager->journalOpen ){
rc = pager_end_transaction(pPager, pPager->setMaster);
- }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
+ pagerLeave(pPager);
+ return rc;
+ }
+
+ if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
if( pPager->state>=PAGER_EXCLUSIVE ){
pager_playback(pPager, 0);
}
- rc = pPager->errCode;
- }else{
- if( pPager->state==PAGER_RESERVED ){
- int rc2;
- rc = pager_playback(pPager, 0);
- rc2 = pager_end_transaction(pPager, pPager->setMaster);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }else{
- rc = pager_playback(pPager, 0);
- }
-
- if( !MEMDB ){
- pPager->dbSizeValid = 0;
+ pagerLeave(pPager);
+ return pPager->errCode;
+ }
+ if( pPager->state==PAGER_RESERVED ){
+ int rc2;
+ rc = pager_playback(pPager, 0);
+ rc2 = pager_end_transaction(pPager, pPager->setMaster);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
}
-
- /* If an error occurs during a ROLLBACK, we can no longer trust the pager
- ** cache. So call pager_error() on the way out to make any error
- ** persistent.
- */
- rc = pager_error(pPager, rc);
+ }else{
+ rc = pager_playback(pPager, 0);
}
+ /* pager_reset(pPager); */
+ pPager->dbSize = -1;
+
+ /* If an error occurs during a ROLLBACK, we can no longer trust the pager
+ ** cache. So call pager_error() on the way out to make any error
+ ** persistent.
+ */
+ rc = pager_error(pPager, rc);
+ pagerLeave(pPager);
return rc;
}
@@ -32552,14 +31098,7 @@ SQLITE_PRIVATE int sqlite3PagerIsreadonly(Pager *pPager){
** Return the number of references to the pager.
*/
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
- return sqlite3PcacheRefCount(pPager->pPCache);
-}
-
-/*
-** Return the number of references to the specified page.
-*/
-SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){
- return sqlite3PcachePageRefcount(pPage);
+ return pPager->nRef;
}
#ifdef SQLITE_TEST
@@ -32568,10 +31107,10 @@ SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage *pPage){
*/
SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
static int a[11];
- a[0] = sqlite3PcacheRefCount(pPager->pPCache);
- a[1] = sqlite3PcachePagecount(pPager->pPCache);
- a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
- a[3] = pPager->dbSizeValid ? (int) pPager->dbSize : -1;
+ a[0] = pPager->nRef;
+ a[1] = pPager->nPage;
+ a[2] = pPager->mxPage;
+ a[3] = pPager->dbSize;
a[4] = pPager->state;
a[5] = pPager->errCode;
a[6] = pPager->nHit;
@@ -32597,15 +31136,22 @@ static int pagerStmtBegin(Pager *pPager){
int rc;
assert( !pPager->stmtInUse );
assert( pPager->state>=PAGER_SHARED );
- assert( pPager->dbSizeValid );
+ assert( pPager->dbSize>=0 );
PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
+ if( MEMDB ){
+ pPager->stmtInUse = 1;
+ pPager->stmtSize = pPager->dbSize;
+ return SQLITE_OK;
+ }
if( !pPager->journalOpen ){
pPager->stmtAutoopen = 1;
return SQLITE_OK;
}
assert( pPager->journalOpen );
+ pagerLeave(pPager);
assert( pPager->pInStmt==0 );
pPager->pInStmt = sqlite3BitvecCreate(pPager->dbSize);
+ pagerEnter(pPager);
if( pPager->pInStmt==0 ){
/* sqlite3OsLock(pPager->fd, SHARED_LOCK); */
return SQLITE_NOMEM;
@@ -32615,13 +31161,9 @@ static int pagerStmtBegin(Pager *pPager){
pPager->stmtHdrOff = 0;
pPager->stmtCksum = pPager->cksumInit;
if( !pPager->stmtOpen ){
- if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){
- sqlite3MemJournalOpen(pPager->stfd);
- }else{
- rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL);
- if( rc ){
- goto stmt_begin_failed;
- }
+ rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL);
+ if( rc ){
+ goto stmt_begin_failed;
}
pPager->stmtOpen = 1;
pPager->stmtNRec = 0;
@@ -32638,7 +31180,9 @@ stmt_begin_failed:
}
SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager *pPager){
int rc;
+ pagerEnter(pPager);
rc = pagerStmtBegin(pPager);
+ pagerLeave(pPager);
return rc;
}
@@ -32646,17 +31190,31 @@ SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager *pPager){
** Commit a statement.
*/
SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager *pPager){
+ pagerEnter(pPager);
if( pPager->stmtInUse ){
+ PgHdr *pPg, *pNext;
PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
- sqlite3BitvecDestroy(pPager->pInStmt);
- pPager->pInStmt = 0;
+ if( !MEMDB ){
+ /* sqlite3OsTruncate(pPager->stfd, 0); */
+ sqlite3BitvecDestroy(pPager->pInStmt);
+ pPager->pInStmt = 0;
+ }else{
+ for(pPg=pPager->pStmt; pPg; pPg=pNext){
+ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
+ pNext = pHist->pNextStmt;
+ assert( pHist->inStmt );
+ pHist->inStmt = 0;
+ pHist->pPrevStmt = pHist->pNextStmt = 0;
+ sqlite3PageFree(pHist->pStmt);
+ pHist->pStmt = 0;
+ }
+ }
pPager->stmtNRec = 0;
pPager->stmtInUse = 0;
- if( sqlite3IsMemJournal(pPager->stfd) ){
- sqlite3OsTruncate(pPager->stfd, 0);
- }
+ pPager->pStmt = 0;
}
pPager->stmtAutoopen = 0;
+ pagerLeave(pPager);
return SQLITE_OK;
}
@@ -32665,14 +31223,32 @@ SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager *pPager){
*/
SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager *pPager){
int rc;
+ pagerEnter(pPager);
if( pPager->stmtInUse ){
PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
- rc = pager_stmt_playback(pPager);
+ if( MEMDB ){
+ PgHdr *pPg;
+ PgHistory *pHist;
+ for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){
+ pHist = PGHDR_TO_HIST(pPg, pPager);
+ if( pHist->pStmt ){
+ memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize);
+ sqlite3PageFree(pHist->pStmt);
+ pHist->pStmt = 0;
+ }
+ }
+ pPager->dbSize = pPager->stmtSize;
+ pager_truncate_cache(pPager);
+ rc = SQLITE_OK;
+ }else{
+ rc = pager_stmt_playback(pPager);
+ }
sqlite3PagerStmtCommit(pPager);
}else{
rc = SQLITE_OK;
}
pPager->stmtAutoopen = 0;
+ pagerLeave(pPager);
return rc;
}
@@ -32741,7 +31317,7 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
**
** There must be no references to the page previously located at
** pgno (which we call pPgOld) though that page is allowed to be
-** in cache. If the page previously located at pgno is not already
+** in cache. If the page previous located at pgno is not already
** in the rollback journal, it is not put there by by this routine.
**
** References to the page pPg remain valid. Updating any
@@ -32760,12 +31336,14 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
*/
SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
PgHdr *pPgOld; /* The page being overwritten. */
+ int h;
Pgno needSyncPgno = 0;
+ pagerEnter(pPager);
assert( pPg->nRef>0 );
PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n",
- PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno);
+ PAGERID(pPager), pPg->pgno, pPg->needSync, pgno);
IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
pager_get_content(pPg);
@@ -32777,31 +31355,46 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
** the journal needs to be sync()ed before database page pPg->pgno
** can be written to. The caller has already promised not to write to it.
*/
- if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
+ if( pPg->needSync && !isCommit ){
needSyncPgno = pPg->pgno;
- assert( pageInJournal(pPg) || pPg->pgno>pPager->origDbSize );
- assert( pPg->flags&PGHDR_DIRTY );
+ assert( pPg->inJournal || (int)pgno>pPager->origDbSize );
+ assert( pPg->dirty );
assert( pPager->needSync );
}
+ /* Unlink pPg from its hash-chain */
+ unlinkHashChain(pPager, pPg);
+
/* If the cache contains a page with page-number pgno, remove it
** from its hash chain. Also, if the PgHdr.needSync was set for
** page pgno before the 'move' operation, it needs to be retained
** for the page moved there.
*/
- pPg->flags &= ~PGHDR_NEED_SYNC;
+ pPg->needSync = 0;
pPgOld = pager_lookup(pPager, pgno);
- assert( !pPgOld || pPgOld->nRef==1 );
if( pPgOld ){
- pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
+ assert( pPgOld->nRef==0 );
+ unlinkHashChain(pPager, pPgOld);
+ makeClean(pPgOld);
+ pPg->needSync = pPgOld->needSync;
+ }else{
+ pPg->needSync = 0;
}
+ pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
- sqlite3PcacheMove(pPg, pgno);
- if( pPgOld ){
- sqlite3PcacheDrop(pPgOld);
+ /* Change the page number for pPg and insert it into the new hash-chain. */
+ assert( pgno!=0 );
+ pPg->pgno = pgno;
+ h = pgno & (pPager->nHash-1);
+ if( pPager->aHash[h] ){
+ assert( pPager->aHash[h]->pPrevHash==0 );
+ pPager->aHash[h]->pPrevHash = pPg;
}
+ pPg->pNextHash = pPager->aHash[h];
+ pPager->aHash[h] = pPg;
+ pPg->pPrevHash = 0;
- sqlite3PcacheMakeDirty(pPg);
+ makeDirty(pPg);
pPager->dirtyCache = 1;
pPager->dbModified = 1;
@@ -32828,18 +31421,20 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
assert( pPager->needSync );
rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr);
if( rc!=SQLITE_OK ){
- if( pPager->pInJournal && needSyncPgno<=pPager->origDbSize ){
+ if( pPager->pInJournal && (int)needSyncPgno<=pPager->origDbSize ){
sqlite3BitvecClear(pPager->pInJournal, needSyncPgno);
}
+ pagerLeave(pPager);
return rc;
}
pPager->needSync = 1;
- assert( pPager->noSync==0 && !MEMDB );
- pPgHdr->flags |= PGHDR_NEED_SYNC;
- sqlite3PcacheMakeDirty(pPgHdr);
+ pPgHdr->needSync = 1;
+ pPgHdr->inJournal = 1;
+ makeDirty(pPgHdr);
sqlite3PagerUnref(pPgHdr);
}
+ pagerLeave(pPager);
return SQLITE_OK;
}
#endif
@@ -32848,8 +31443,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
** Return a pointer to the data for the specified page.
*/
SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
- assert( pPg->nRef>0 || pPg->pPager->memDb );
- return pPg->pData;
+ return PGHDR_TO_DATA(pPg);
}
/*
@@ -32858,7 +31452,7 @@ SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
*/
SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
Pager *pPager = pPg->pPager;
- return (pPager?pPg->pExtra:0);
+ return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0);
}
/*
@@ -32884,34 +31478,24 @@ SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *pPager, int eMode){
}
/*
-** Get/set the journal-mode for this pager. Parameter eMode must be one of:
-**
-** PAGER_JOURNALMODE_QUERY
-** PAGER_JOURNALMODE_DELETE
-** PAGER_JOURNALMODE_TRUNCATE
-** PAGER_JOURNALMODE_PERSIST
-** PAGER_JOURNALMODE_OFF
-**
-** If the parameter is not _QUERY, then the journal-mode is set to the
-** value specified.
+** Get/set the journal-mode for this pager. Parameter eMode must be one
+** of PAGER_JOURNALMODE_QUERY, PAGER_JOURNALMODE_DELETE or
+** PAGER_JOURNALMODE_PERSIST. If the parameter is not _QUERY, then
+** the journal-mode is set to the value specified.
**
-** The returned indicate the current (possibly updated)
+** The returned value is either PAGER_JOURNALMODE_DELETE or
+** PAGER_JOURNALMODE_PERSIST, indicating the current (possibly updated)
** journal-mode.
*/
SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *pPager, int eMode){
- if( !MEMDB ){
- assert( eMode==PAGER_JOURNALMODE_QUERY
- || eMode==PAGER_JOURNALMODE_DELETE
- || eMode==PAGER_JOURNALMODE_TRUNCATE
- || eMode==PAGER_JOURNALMODE_PERSIST
- || eMode==PAGER_JOURNALMODE_OFF
- || eMode==PAGER_JOURNALMODE_MEMORY );
- assert( PAGER_JOURNALMODE_QUERY<0 );
- if( eMode>=0 ){
- pPager->journalMode = eMode;
- }else{
- assert( eMode==PAGER_JOURNALMODE_QUERY );
- }
+ assert( eMode==PAGER_JOURNALMODE_QUERY
+ || eMode==PAGER_JOURNALMODE_DELETE
+ || eMode==PAGER_JOURNALMODE_PERSIST
+ || eMode==PAGER_JOURNALMODE_OFF );
+ assert( PAGER_JOURNALMODE_QUERY<0 );
+ assert( PAGER_JOURNALMODE_DELETE>=0 && PAGER_JOURNALMODE_PERSIST>=0 );
+ if( eMode>=0 ){
+ pPager->journalMode = eMode;
}
return (int)pPager->journalMode;
}
@@ -33219,6 +31803,7 @@ typedef struct BtLock BtLock;
*/
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
+ u8 idxShift; /* True if Cell indices have changed */
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
u8 intKey; /* True if intkey flag is set */
u8 leaf; /* True if leaf flag is set */
@@ -33228,6 +31813,7 @@ struct MemPage {
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
+ u16 idxParent; /* Index in parent of this node */
u16 nFree; /* Number of free bytes on the page */
u16 nCell; /* Number of cells on this page, local and ovfl */
u16 maskPage; /* Mask for page offset */
@@ -33239,6 +31825,7 @@ struct MemPage {
u8 *aData; /* Pointer to disk image of the page data */
DbPage *pDbPage; /* Pager page handle */
Pgno pgno; /* Page number for this page */
+ MemPage *pParent; /* The parent of this page. NULL for root */
};
/*
@@ -33332,6 +31919,7 @@ struct BtShared {
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
+ BusyHandler busyHdr; /* The busy handler for this btree */
#ifndef SQLITE_OMIT_SHARED_CACHE
int nRef; /* Number of references to this structure */
BtShared *pNext; /* Next on a list of sharable BtShared structs */
@@ -33359,17 +31947,6 @@ struct CellInfo {
};
/*
-** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
-** this will be declared corrupt. This value is calculated based on a
-** maximum database size of 2^31 pages a minimum fanout of 2 for a
-** root-node and 3 for all other internal nodes.
-**
-** If a tree that appears to be taller than this is encountered, it is
-** assumed that the database is corrupt.
-*/
-#define BTCURSOR_MAX_DEPTH 20
-
-/*
** A cursor is a pointer to a particular entry within a particular
** b-tree within a database file.
**
@@ -33389,6 +31966,8 @@ struct BtCursor {
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
Pgno pgnoRoot; /* The root page of this tree */
+ MemPage *pPage; /* Page that contains the entry */
+ int idx; /* Index of the entry in pPage->aCell[] */
CellInfo info; /* A parse of the cell we are pointing at */
u8 wrFlag; /* True if writable */
u8 atLast; /* Cursor pointing to the last entry */
@@ -33401,12 +31980,6 @@ struct BtCursor {
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
Pgno *aOverflow; /* Cache of overflow page locations */
#endif
-#ifndef NDEBUG
- u8 pagesShuffled; /* True if Btree pages are rearranged by balance()*/
-#endif
- i16 iPage; /* Index of current page in apPage */
- MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
- u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
};
/*
@@ -33449,7 +32022,7 @@ struct BtCursor {
#ifdef SQLITE_OMIT_DISKIO
# define PENDING_BYTE_PAGE(pBt) 0x7fffffff
#else
-# define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/(pBt)->pageSize)+1))
+# define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1)
#endif
/*
@@ -33556,7 +32129,7 @@ typedef struct IntegrityCk IntegrityCk;
struct IntegrityCk {
BtShared *pBt; /* The tree being checked out */
Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
- Pgno nPage; /* Number of pages in the database */
+ int nPage; /* Number of pages in the database */
int *anRef; /* Number of times each page is referenced */
int mxErr; /* Stop accumulating errors when this reaches zero */
int nErr; /* Number of messages written to zErrMsg so far */
@@ -33576,12 +32149,13 @@ struct IntegrityCk {
** Internal routines that should be accessed by the btree layer only.
*/
SQLITE_PRIVATE int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int);
-SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage);
+SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage, MemPage *pParent);
SQLITE_PRIVATE void sqlite3BtreeParseCellPtr(MemPage*, u8*, CellInfo*);
SQLITE_PRIVATE void sqlite3BtreeParseCell(MemPage*, int, CellInfo*);
SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur);
SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur);
SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur);
+SQLITE_PRIVATE int sqlite3BtreeIsRootPage(MemPage *pPage);
SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur);
/************** End of btreeInt.h ********************************************/
@@ -33629,6 +32203,7 @@ SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){
p->wantToLock++;
if( p->locked ) return;
+#ifndef SQLITE_MUTEX_NOOP
/* In most cases, we should be able to acquire the lock we
** want without having to go throught the ascending lock
** procedure that follows. Just be sure not to block.
@@ -33660,6 +32235,7 @@ SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){
pLater->locked = 1;
}
}
+#endif /* SQLITE_MUTEX_NOOP */
}
/*
@@ -33816,7 +32392,7 @@ SQLITE_PRIVATE void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree
}
#endif
assert( pArray->nMutex>=0 );
- assert( pArray->nMutex<ArraySize(pArray->aBtree)-1 );
+ assert( pArray->nMutex<sizeof(pArray->aBtree)/sizeof(pArray->aBtree[0])-1 );
pBt = pBtree->pBt;
for(i=0; i<pArray->nMutex; i++){
assert( pArray->aBtree[i]!=pBtree );
@@ -33919,33 +32495,22 @@ int sqlite3BtreeTrace=0; /* True to enable tracing */
# define TRACE(X)
#endif
-/*
-** Sometimes we need a small amount of code such as a variable initialization
-** to setup for a later assert() statement. We do not want this code to
-** appear when assert() is disabled. The following macro is therefore
-** used to contain that setup code. The "VVA" acronym stands for
-** "Verification, Validation, and Accreditation". In other words, the
-** code within VVA_ONLY() will only run during verification processes.
-*/
-#ifndef NDEBUG
-# define VVA_ONLY(X) X
-#else
-# define VVA_ONLY(X)
-#endif
-
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
-** A list of BtShared objects that are eligible for participation
-** in shared cache. This variable has file scope during normal builds,
-** but the test harness needs to access it so we make it global for
-** test builds.
+** A flag to indicate whether or not shared cache is enabled. Also,
+** a list of BtShared objects that are eligible for participation
+** in shared cache. The variables have file scope during normal builds,
+** but the test harness needs to access these variables so we make them
+** global for test builds.
*/
#ifdef SQLITE_TEST
-SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
+SQLITE_PRIVATE BtShared *sqlite3SharedCacheList = 0;
+SQLITE_PRIVATE int sqlite3SharedCacheEnabled = 0;
#else
-static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
+static BtShared *sqlite3SharedCacheList = 0;
+static int sqlite3SharedCacheEnabled = 0;
#endif
#endif /* SQLITE_OMIT_SHARED_CACHE */
@@ -33958,7 +32523,7 @@ static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2().
*/
SQLITE_API int sqlite3_enable_shared_cache(int enable){
- sqlite3GlobalConfig.sharedCacheEnabled = enable;
+ sqlite3SharedCacheEnabled = enable;
return SQLITE_OK;
}
#endif
@@ -34200,7 +32765,7 @@ static int saveCursorPosition(BtCursor *pCur){
** table, then malloc space for and store the pCur->nKey bytes of key
** data.
*/
- if( rc==SQLITE_OK && 0==pCur->apPage[0]->intKey){
+ if( rc==SQLITE_OK && 0==pCur->pPage->intKey){
void *pKey = sqlite3Malloc(pCur->nKey);
if( pKey ){
rc = sqlite3BtreeKey(pCur, 0, pCur->nKey, pKey);
@@ -34213,15 +32778,11 @@ static int saveCursorPosition(BtCursor *pCur){
rc = SQLITE_NOMEM;
}
}
- assert( !pCur->apPage[0]->intKey || !pCur->pKey );
+ assert( !pCur->pPage->intKey || !pCur->pKey );
if( rc==SQLITE_OK ){
- int i;
- for(i=0; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- pCur->apPage[i] = 0;
- }
- pCur->iPage = -1;
+ releasePage(pCur->pPage);
+ pCur->pPage = 0;
pCur->eState = CURSOR_REQUIRESEEK;
}
@@ -34253,7 +32814,7 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
/*
** Clear the current cursor position.
*/
-SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *pCur){
+static void clearCursorPosition(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
@@ -34275,7 +32836,7 @@ SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur){
return pCur->skip;
}
pCur->eState = CURSOR_INVALID;
- rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip);
+ rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip);
if( rc==SQLITE_OK ){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
@@ -34291,7 +32852,7 @@ SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur){
/*
** Determine whether or not a cursor has moved from the position it
-** was last placed at. Cursors can move when the row they are pointing
+** was last placed at. Cursor can move when the row they are pointing
** at is deleted out from under them.
**
** This routine returns an error code if something goes wrong. The
@@ -34320,8 +32881,7 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
** input page number.
*/
static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
- int nPagesPerMapPage;
- Pgno iPtrMap, ret;
+ int nPagesPerMapPage, iPtrMap, ret;
assert( sqlite3_mutex_held(pBt->mutex) );
nPagesPerMapPage = (pBt->usableSize/5)+1;
iPtrMap = (pgno-2)/nPagesPerMapPage;
@@ -34588,7 +33148,7 @@ static int ptrmapPutOvfl(MemPage *pPage, int iCell){
** big FreeBlk that occurs in between the header and cell
** pointer array and the cell content area.
*/
-static int defragmentPage(MemPage *pPage){
+static void defragmentPage(MemPage *pPage){
int i; /* Loop counter */
int pc; /* Address of a i-th cell */
int addr; /* Offset of first byte after cell pointer array */
@@ -34596,7 +33156,7 @@ static int defragmentPage(MemPage *pPage){
int size; /* Size of a cell */
int usableSize; /* Number of usable bytes on a page */
int cellOffset; /* Offset to the cell pointer array */
- int cbrk; /* Offset to the cell content area */
+ int brk; /* Offset to the cell content area */
int nCell; /* Number of cells on the page */
unsigned char *data; /* The page data */
unsigned char *temp; /* Temp area for cell content */
@@ -34613,36 +33173,26 @@ static int defragmentPage(MemPage *pPage){
nCell = pPage->nCell;
assert( nCell==get2byte(&data[hdr+3]) );
usableSize = pPage->pBt->usableSize;
- cbrk = get2byte(&data[hdr+5]);
- memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk);
- cbrk = usableSize;
+ brk = get2byte(&data[hdr+5]);
+ memcpy(&temp[brk], &data[brk], usableSize - brk);
+ brk = usableSize;
for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */
pAddr = &data[cellOffset + i*2];
pc = get2byte(pAddr);
- if( pc>=usableSize ){
- return SQLITE_CORRUPT_BKPT;
- }
+ assert( pc<pPage->pBt->usableSize );
size = cellSizePtr(pPage, &temp[pc]);
- cbrk -= size;
- if( cbrk<cellOffset+2*nCell || pc+size>usableSize ){
- return SQLITE_CORRUPT_BKPT;
- }
- assert( cbrk+size<=usableSize && cbrk>=0 );
- memcpy(&data[cbrk], &temp[pc], size);
- put2byte(pAddr, cbrk);
+ brk -= size;
+ memcpy(&data[brk], &temp[pc], size);
+ put2byte(pAddr, brk);
}
- assert( cbrk>=cellOffset+2*nCell );
- put2byte(&data[hdr+5], cbrk);
+ assert( brk>=cellOffset+2*nCell );
+ put2byte(&data[hdr+5], brk);
data[hdr+1] = 0;
data[hdr+2] = 0;
data[hdr+7] = 0;
addr = cellOffset+2*nCell;
- memset(&data[addr], 0, cbrk-addr);
- if( cbrk-addr!=pPage->nFree ){
- return SQLITE_CORRUPT_BKPT;
- }
- return SQLITE_OK;
+ memset(&data[addr], 0, brk-addr);
}
/*
@@ -34721,7 +33271,7 @@ static int allocateSpace(MemPage *pPage, int nByte){
** Most of the effort here is involved in coalesing adjacent
** free blocks into a single big free block.
*/
-static int freeSpace(MemPage *pPage, int start, int size){
+static void freeSpace(MemPage *pPage, int start, int size){
int addr, pbegin, hdr;
unsigned char *data = pPage->aData;
@@ -34743,14 +33293,10 @@ static int freeSpace(MemPage *pPage, int start, int size){
addr = hdr + 1;
while( (pbegin = get2byte(&data[addr]))<start && pbegin>0 ){
assert( pbegin<=pPage->pBt->usableSize-4 );
- if( pbegin<=addr ) {
- return SQLITE_CORRUPT_BKPT;
- }
+ assert( pbegin>addr );
addr = pbegin;
}
- if ( pbegin>pPage->pBt->usableSize-4 ) {
- return SQLITE_CORRUPT_BKPT;
- }
+ assert( pbegin<=pPage->pBt->usableSize-4 );
assert( pbegin>addr || pbegin==0 );
put2byte(&data[addr], start);
put2byte(&data[start], pbegin);
@@ -34767,9 +33313,7 @@ static int freeSpace(MemPage *pPage, int start, int size){
psize = get2byte(&data[pbegin+2]);
if( pbegin + psize + 3 >= pnext && pnext>0 ){
int frag = pnext - (pbegin+psize);
- if( (frag<0) || (frag>data[pPage->hdrOffset+7]) ){
- return SQLITE_CORRUPT_BKPT;
- }
+ assert( frag<=data[pPage->hdrOffset+7] );
data[pPage->hdrOffset+7] -= frag;
put2byte(&data[pbegin], get2byte(&data[pnext]));
put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin);
@@ -34786,7 +33330,6 @@ static int freeSpace(MemPage *pPage, int start, int size){
top = get2byte(&data[hdr+5]);
put2byte(&data[hdr+5], top + get2byte(&data[pbegin+2]));
}
- return SQLITE_OK;
}
/*
@@ -34829,70 +33372,88 @@ static int decodeFlags(MemPage *pPage, int flagByte){
/*
** Initialize the auxiliary information for a disk block.
**
+** The pParent parameter must be a pointer to the MemPage which
+** is the parent of the page being initialized. The root of a
+** BTree has no parent and so for that page, pParent==NULL.
+**
** Return SQLITE_OK on success. If we see that the page does
** not contain a well-formed database page, then return
** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not
** guarantee that the page is well-formed. It only shows that
** we failed to detect any corruption.
*/
-SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage){
+SQLITE_PRIVATE int sqlite3BtreeInitPage(
+ MemPage *pPage, /* The page to be initialized */
+ MemPage *pParent /* The parent. Might be NULL */
+){
+ int pc; /* Address of a freeblock within pPage->aData[] */
+ int hdr; /* Offset to beginning of page header */
+ u8 *data; /* Equal to pPage->aData */
+ BtShared *pBt; /* The main btree structure */
+ int usableSize; /* Amount of usable space on each page */
+ int cellOffset; /* Offset from start of page to first cell pointer */
+ int nFree; /* Number of unused bytes on the page */
+ int top; /* First byte of the cell content area */
- assert( pPage->pBt!=0 );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ pBt = pPage->pBt;
+ assert( pBt!=0 );
+ assert( pParent==0 || pParent->pBt==pBt );
+ assert( sqlite3_mutex_held(pBt->mutex) );
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
+ if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
+ /* The parent page should never change unless the file is corrupt */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ if( pPage->isInit ) return SQLITE_OK;
+ if( pPage->pParent==0 && pParent!=0 ){
+ pPage->pParent = pParent;
+ sqlite3PagerRef(pParent->pDbPage);
+ }
+ hdr = pPage->hdrOffset;
+ data = pPage->aData;
+ if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
+ assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
+ pPage->maskPage = pBt->pageSize - 1;
+ pPage->nOverflow = 0;
+ pPage->idxShift = 0;
+ usableSize = pBt->usableSize;
+ pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
+ top = get2byte(&data[hdr+5]);
+ pPage->nCell = get2byte(&data[hdr+3]);
+ if( pPage->nCell>MX_CELL(pBt) ){
+ /* To many cells for a single page. The page must be corrupt */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){
+ /* All pages must have at least one cell, except for root pages */
+ return SQLITE_CORRUPT_BKPT;
+ }
- if( !pPage->isInit ){
- int pc; /* Address of a freeblock within pPage->aData[] */
- int hdr; /* Offset to beginning of page header */
- u8 *data; /* Equal to pPage->aData */
- BtShared *pBt; /* The main btree structure */
- int usableSize; /* Amount of usable space on each page */
- int cellOffset; /* Offset from start of page to first cell pointer */
- int nFree; /* Number of unused bytes on the page */
- int top; /* First byte of the cell content area */
-
- pBt = pPage->pBt;
-
- hdr = pPage->hdrOffset;
- data = pPage->aData;
- if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
- assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
- pPage->maskPage = pBt->pageSize - 1;
- pPage->nOverflow = 0;
- usableSize = pBt->usableSize;
- pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
- top = get2byte(&data[hdr+5]);
- pPage->nCell = get2byte(&data[hdr+3]);
- if( pPage->nCell>MX_CELL(pBt) ){
- /* To many cells for a single page. The page must be corrupt */
- return SQLITE_CORRUPT_BKPT;
- }
-
- /* Compute the total free space on the page */
- pc = get2byte(&data[hdr+1]);
- nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
- while( pc>0 ){
- int next, size;
- if( pc>usableSize-4 ){
- /* Free block is off the page */
- return SQLITE_CORRUPT_BKPT;
- }
- next = get2byte(&data[pc]);
- size = get2byte(&data[pc+2]);
- if( next>0 && next<=pc+size+3 ){
- /* Free blocks must be in accending order */
- return SQLITE_CORRUPT_BKPT;
- }
- nFree += size;
- pc = next;
+ /* Compute the total free space on the page */
+ pc = get2byte(&data[hdr+1]);
+ nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
+ while( pc>0 ){
+ int next, size;
+ if( pc>usableSize-4 ){
+ /* Free block is off the page */
+ return SQLITE_CORRUPT_BKPT;
}
- pPage->nFree = nFree;
- if( nFree>=usableSize ){
- /* Free space cannot exceed total page size */
+ next = get2byte(&data[pc]);
+ size = get2byte(&data[pc+2]);
+ if( next>0 && next<=pc+size+3 ){
+ /* Free blocks must be in accending order */
return SQLITE_CORRUPT_BKPT;
}
+ nFree += size;
+ pc = next;
+ }
+ pPage->nFree = nFree;
+ if( nFree>=usableSize ){
+ /* Free space cannot exceed total page size */
+ return SQLITE_CORRUPT_BKPT;
+ }
#if 0
/* Check that all the offsets in the cell offset array are within range.
@@ -34914,8 +33475,7 @@ SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage){
}
#endif
- pPage->isInit = 1;
- }
+ pPage->isInit = 1;
return SQLITE_OK;
}
@@ -34947,25 +33507,11 @@ static void zeroPage(MemPage *pPage, int flags){
pPage->nOverflow = 0;
assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
pPage->maskPage = pBt->pageSize - 1;
+ pPage->idxShift = 0;
pPage->nCell = 0;
pPage->isInit = 1;
}
-
-/*
-** Convert a DbPage obtained from the pager into a MemPage used by
-** the btree layer.
-*/
-static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
- MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
- pPage->aData = sqlite3PagerGetData(pDbPage);
- pPage->pDbPage = pDbPage;
- pPage->pBt = pBt;
- pPage->pgno = pgno;
- pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
- return pPage;
-}
-
/*
** Get a page from the pager. Initialize the MemPage.pBt and
** MemPage.aData elements if needed.
@@ -34984,29 +33530,23 @@ SQLITE_PRIVATE int sqlite3BtreeGetPage(
int noContent /* Do not load page content if true */
){
int rc;
+ MemPage *pPage;
DbPage *pDbPage;
assert( sqlite3_mutex_held(pBt->mutex) );
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
if( rc ) return rc;
- *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
+ pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage);
+ pPage->aData = sqlite3PagerGetData(pDbPage);
+ pPage->pDbPage = pDbPage;
+ pPage->pBt = pBt;
+ pPage->pgno = pgno;
+ pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
+ *ppPage = pPage;
return SQLITE_OK;
}
/*
-** Return the size of the database file in pages. If there is any kind of
-** error, return ((unsigned int)-1).
-*/
-static Pgno pagerPagecount(BtShared *pBt){
- int nPage = -1;
- int rc;
- assert( pBt->pPage1 );
- rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
- assert( rc==SQLITE_OK || nPage==-1 );
- return (Pgno)nPage;
-}
-
-/*
** Get a page from the pager and initialize it. This routine
** is just a convenience wrapper around separate calls to
** sqlite3BtreeGetPage() and sqlite3BtreeInitPage().
@@ -35014,42 +33554,21 @@ static Pgno pagerPagecount(BtShared *pBt){
static int getAndInitPage(
BtShared *pBt, /* The database file */
Pgno pgno, /* Number of the page to get */
- MemPage **ppPage /* Write the page pointer here */
+ MemPage **ppPage, /* Write the page pointer here */
+ MemPage *pParent /* Parent of the page */
){
int rc;
- DbPage *pDbPage;
- MemPage *pPage;
-
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno==0 ){
return SQLITE_CORRUPT_BKPT;
}
-
- /* It is often the case that the page we want is already in cache.
- ** If so, get it directly. This saves us from having to call
- ** pagerPagecount() to make sure pgno is within limits, which results
- ** in a measureable performance improvements.
- */
- pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
- if( pDbPage ){
- /* Page is already in cache */
- *ppPage = pPage = btreePageFromDbPage(pDbPage, pgno, pBt);
- rc = SQLITE_OK;
- }else{
- /* Page not in cache. Acquire it. */
- if( pgno>pagerPagecount(pBt) ){
- return SQLITE_CORRUPT_BKPT;
+ rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
+ if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
+ rc = sqlite3BtreeInitPage(*ppPage, pParent);
+ if( rc!=SQLITE_OK ){
+ releasePage(*ppPage);
+ *ppPage = 0;
}
- rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
- if( rc ) return rc;
- pPage = *ppPage;
- }
- if( !pPage->isInit ){
- rc = sqlite3BtreeInitPage(pPage);
- }
- if( rc!=SQLITE_OK ){
- releasePage(pPage);
- *ppPage = 0;
}
return rc;
}
@@ -35070,6 +33589,25 @@ static void releasePage(MemPage *pPage){
}
/*
+** This routine is called when the reference count for a page
+** reaches zero. We need to unref the pParent pointer when that
+** happens.
+*/
+static void pageDestructor(DbPage *pData, int pageSize){
+ MemPage *pPage;
+ assert( (pageSize & 7)==0 );
+ pPage = (MemPage *)sqlite3PagerGetExtra(pData);
+ assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
+ if( pPage->pParent ){
+ MemPage *pParent = pPage->pParent;
+ assert( pParent->pBt==pPage->pBt );
+ pPage->pParent = 0;
+ releasePage(pParent);
+ }
+ pPage->isInit = 0;
+}
+
+/*
** During a rollback, when the pager reloads information into the cache
** so that the cache is restored to its original state at the start of
** the transaction, for each page restored this routine is called.
@@ -35077,22 +33615,21 @@ static void releasePage(MemPage *pPage){
** This routine needs to reset the extra data section at the end of the
** page to agree with the restored data.
*/
-static void pageReinit(DbPage *pData){
+static void pageReinit(DbPage *pData, int pageSize){
MemPage *pPage;
+ assert( (pageSize & 7)==0 );
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
if( pPage->isInit ){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pPage->isInit = 0;
- if( sqlite3PagerPageRefcount(pData)>0 ){
- sqlite3BtreeInitPage(pPage);
- }
+ sqlite3BtreeInitPage(pPage, pPage->pParent);
}
}
/*
** Invoke the busy handler for a btree.
*/
-static int btreeInvokeBusyHandler(void *pArg){
+static int sqlite3BtreeInvokeBusyHandler(void *pArg, int n){
BtShared *pBt = (BtShared*)pArg;
assert( pBt->db );
assert( sqlite3_mutex_held(pBt->db->mutex) );
@@ -35155,7 +33692,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
&& (db->flags & SQLITE_Vtab)==0
&& zFilename && zFilename[0]
){
- if( sqlite3GlobalConfig.sharedCacheEnabled ){
+ if( sqlite3SharedCacheEnabled ){
int nFullPathname = pVfs->mxPathname+1;
char *zFullPathname = sqlite3Malloc(nFullPathname);
sqlite3_mutex *mutexShared;
@@ -35168,7 +33705,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(mutexShared);
- for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
+ for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
assert( pBt->nRef>0 );
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
@@ -35209,6 +33746,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
rc = SQLITE_NOMEM;
goto btree_open_out;
}
+ pBt->busyHdr.xFunc = sqlite3BtreeInvokeBusyHandler;
+ pBt->busyHdr.pArg = pBt;
rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
EXTRA_SIZE, flags, vfsFlags);
if( rc==SQLITE_OK ){
@@ -35217,9 +33756,10 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
if( rc!=SQLITE_OK ){
goto btree_open_out;
}
- sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
+ sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr);
p->pBt = pBt;
+ sqlite3PagerSetDestructor(pBt->pPager, pageDestructor);
sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
pBt->pCursor = 0;
pBt->pPage1 = 0;
@@ -35261,7 +33801,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
sqlite3_mutex *mutexShared;
pBt->nRef = 1;
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
- if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
+ if( SQLITE_THREADSAFE && sqlite3Config.bCoreMutex ){
pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
rc = SQLITE_NOMEM;
@@ -35270,8 +33810,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
}
}
sqlite3_mutex_enter(mutexShared);
- pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList);
- GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt;
+ pBt->pNext = sqlite3SharedCacheList;
+ sqlite3SharedCacheList = pBt;
sqlite3_mutex_leave(mutexShared);
}
#endif
@@ -35339,10 +33879,10 @@ static int removeFromSharingList(BtShared *pBt){
sqlite3_mutex_enter(pMaster);
pBt->nRef--;
if( pBt->nRef<=0 ){
- if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
- GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;
+ if( sqlite3SharedCacheList==pBt ){
+ sqlite3SharedCacheList = pBt->pNext;
}else{
- pList = GLOBAL(BtShared*,sqlite3SharedCacheList);
+ pList = sqlite3SharedCacheList;
while( ALWAYS(pList) && pList->pNext!=pBt ){
pList=pList->pNext;
}
@@ -35915,7 +34455,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
unlockBtreeIfUnused(pBt);
}
}while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
- btreeInvokeBusyHandler(pBt) );
+ sqlite3BtreeInvokeBusyHandler(pBt, 0) );
if( rc==SQLITE_OK ){
if( p->inTrans==TRANS_NONE ){
@@ -35940,6 +34480,18 @@ trans_begun:
return rc;
}
+/*
+** Return the size of the database file in pages. Or return -1 if
+** there is any kind of error.
+*/
+static int pagerPagecount(Pager *pPager){
+ int rc;
+ int nPage;
+ rc = sqlite3PagerPagecount(pPager, &nPage);
+ return (rc==SQLITE_OK?nPage:-1);
+}
+
+
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
@@ -35956,7 +34508,7 @@ static int setChildPtrmaps(MemPage *pPage){
Pgno pgno = pPage->pgno;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- rc = sqlite3BtreeInitPage(pPage);
+ rc = sqlite3BtreeInitPage(pPage, pPage->pParent);
if( rc!=SQLITE_OK ){
goto set_child_ptrmaps_out;
}
@@ -35973,7 +34525,7 @@ static int setChildPtrmaps(MemPage *pPage){
if( !pPage->leaf ){
Pgno childPgno = get4byte(pCell);
rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno);
- if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out;
+ if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out;
}
}
@@ -36015,7 +34567,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
int i;
int nCell;
- sqlite3BtreeInitPage(pPage);
+ sqlite3BtreeInitPage(pPage, 0);
nCell = pPage->nCell;
for(i=0; i<nCell; i++){
@@ -36153,7 +34705,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin){
assert( sqlite3_mutex_held(pBt->mutex) );
iLastPg = pBt->nTrunc;
if( iLastPg==0 ){
- iLastPg = pagerPagecount(pBt);
+ iLastPg = pagerPagecount(pBt->pPager);
}
if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
@@ -36272,7 +34824,9 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){
int rc = SQLITE_OK;
Pager *pPager = pBt->pPager;
- VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager) );
+#ifndef NDEBUG
+ int nRef = sqlite3PagerRefcount(pPager);
+#endif
assert( sqlite3_mutex_held(pBt->mutex) );
invalidateAllOverflowCache(pBt);
@@ -36284,7 +34838,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){
Pgno nFree;
Pgno nPtrmap;
const int pgsz = pBt->pageSize;
- Pgno nOrig = pagerPagecount(pBt);
+ int nOrig = pagerPagecount(pBt->pPager);
if( PTRMAP_ISPAGE(pBt, nOrig) ){
return SQLITE_CORRUPT_BKPT;
@@ -36329,7 +34883,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){
return rc;
}
-#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */
+#endif
/*
** This routine does the first phase of a two-phase commit. This routine
@@ -36496,14 +35050,9 @@ SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
BtCursor *p;
sqlite3BtreeEnter(pBtree);
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- int i;
- sqlite3BtreeClearCursor(p);
+ clearCursorPosition(p);
p->eState = CURSOR_FAULT;
p->skip = errCode;
- for(i=0; i<=p->iPage; i++){
- releasePage(p->apPage[i]);
- p->apPage[i] = 0;
- }
}
sqlite3BtreeLeave(pBtree);
}
@@ -36678,9 +35227,6 @@ SQLITE_PRIVATE int sqlite3BtreeRollbackStmt(Btree *p){
** No checking is done to make sure that page iTable really is the
** root page of a b-tree. If it is not, then the cursor acquired
** will not work correctly.
-**
-** It is assumed that the sqlite3BtreeCursorSize() bytes of memory
-** pointed to by pCur have been zeroed by the caller.
*/
static int btreeCursor(
Btree *p, /* The btree */
@@ -36690,7 +35236,6 @@ static int btreeCursor(
BtCursor *pCur /* Space for new cursor */
){
int rc;
- Pgno nPage;
BtShared *pBt = p->pBt;
assert( sqlite3BtreeHoldsMutex(p) );
@@ -36713,15 +35258,11 @@ static int btreeCursor(
}
}
pCur->pgnoRoot = (Pgno)iTable;
- rc = sqlite3PagerPagecount(pBt->pPager, (int *)&nPage);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- if( iTable==1 && nPage==0 ){
+ if( iTable==1 && pagerPagecount(pBt->pPager)==0 ){
rc = SQLITE_EMPTY;
goto create_cursor_exception;
}
- rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
+ rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
@@ -36744,7 +35285,7 @@ static int btreeCursor(
return SQLITE_OK;
create_cursor_exception:
- releasePage(pCur->apPage[0]);
+ releasePage(pCur->pPage);
unlockBtreeIfUnused(pBt);
return rc;
}
@@ -36775,11 +35316,10 @@ SQLITE_PRIVATE int sqlite3BtreeCursorSize(){
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
Btree *pBtree = pCur->pBtree;
if( pBtree ){
- int i;
BtShared *pBt = pCur->pBt;
sqlite3BtreeEnter(pBtree);
pBt->db = pBtree->db;
- sqlite3BtreeClearCursor(pCur);
+ clearCursorPosition(pCur);
if( pCur->pPrev ){
pCur->pPrev->pNext = pCur->pNext;
}else{
@@ -36788,9 +35328,7 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
if( pCur->pNext ){
pCur->pNext->pPrev = pCur->pPrev;
}
- for(i=0; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- }
+ releasePage(pCur->pPage);
unlockBtreeIfUnused(pBt);
invalidateOverflowCache(pCur);
/* sqlite3_free(pCur); */
@@ -36804,15 +35342,13 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){
** The temporary cursor is not on the cursor list for the Btree.
*/
SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){
- int i;
assert( cursorHoldsMutex(pCur) );
- memcpy(pTempCur, pCur, sizeof(BtCursor));
+ memcpy(pTempCur, pCur, sizeof(*pCur));
pTempCur->pNext = 0;
pTempCur->pPrev = 0;
- for(i=0; i<=pTempCur->iPage; i++){
- sqlite3PagerRef(pTempCur->apPage[i]->pDbPage);
+ if( pTempCur->pPage ){
+ sqlite3PagerRef(pTempCur->pPage->pDbPage);
}
- assert( pTempCur->pKey==0 );
}
/*
@@ -36820,12 +35356,10 @@ SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur
** function above.
*/
SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
- int i;
assert( cursorHoldsMutex(pCur) );
- for(i=0; i<=pCur->iPage; i++){
- sqlite3PagerUnref(pCur->apPage[i]->pDbPage);
+ if( pCur->pPage ){
+ sqlite3PagerUnref(pCur->pPage->pDbPage);
}
- sqlite3_free(pCur->pKey);
}
/*
@@ -36846,9 +35380,8 @@ SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
#ifndef NDEBUG
static void assertCellInfo(BtCursor *pCur){
CellInfo info;
- int iPage = pCur->iPage;
memset(&info, 0, sizeof(info));
- sqlite3BtreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info);
+ sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &info);
assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
}
#else
@@ -36858,8 +35391,7 @@ SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
/* Use a real function in MSVC to work around bugs in that compiler. */
static void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
- int iPage = pCur->iPage;
- sqlite3BtreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
+ sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info);
pCur->validNKey = 1;
}else{
assertCellInfo(pCur);
@@ -36867,13 +35399,12 @@ SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
}
#else /* if not _MSC_VER */
/* Use a macro in all other compilers so that the function is inlined */
-#define getCellInfo(pCur) \
- if( pCur->info.nSize==0 ){ \
- int iPage = pCur->iPage; \
- sqlite3BtreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
- pCur->validNKey = 1; \
- }else{ \
- assertCellInfo(pCur); \
+#define getCellInfo(pCur) \
+ if( pCur->info.nSize==0 ){ \
+ sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \
+ pCur->validNKey = 1; \
+ }else{ \
+ assertCellInfo(pCur); \
}
#endif /* _MSC_VER */
@@ -36980,7 +35511,7 @@ static int getOverflowPage(
iGuess++;
}
- if( iGuess<=pagerPagecount(pBt) ){
+ if( iGuess<=pagerPagecount(pBt->pPager) ){
rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
if( rc!=SQLITE_OK ){
return rc;
@@ -37076,8 +35607,8 @@ static int copyPayload(
*/
static int accessPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
- u32 offset, /* Begin reading this far into payload */
- u32 amt, /* Read this many bytes */
+ int offset, /* Begin reading this far into payload */
+ int amt, /* Read this many bytes */
unsigned char *pBuf, /* Write the bytes into this buffer */
int skipKey, /* offset begins at data if this is true */
int eOp /* zero to read. non-zero to write. */
@@ -37086,12 +35617,13 @@ static int accessPayload(
int rc = SQLITE_OK;
u32 nKey;
int iIdx = 0;
- MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
- BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
+ MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */
+ BtShared *pBt; /* Btree this cursor belongs to */
assert( pPage );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
+ assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
+ assert( offset>=0 );
assert( cursorHoldsMutex(pCur) );
getCellInfo(pCur);
@@ -37101,11 +35633,9 @@ static int accessPayload(
if( skipKey ){
offset += nKey;
}
- if( offset+amt > nKey+pCur->info.nData
- || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
- ){
+ if( offset+amt > nKey+pCur->info.nData ){
/* Trying to read or write past the end of the data is an error */
- return SQLITE_CORRUPT_BKPT;
+ return SQLITE_ERROR;
}
/* Check if data must be read/written to/from the btree page itself. */
@@ -37122,8 +35652,9 @@ static int accessPayload(
offset -= pCur->info.nLocal;
}
+ pBt = pCur->pBt;
if( rc==SQLITE_OK && amt>0 ){
- const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
+ const int ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */
Pgno nextPage;
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
@@ -37224,11 +35755,12 @@ SQLITE_PRIVATE int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pB
rc = restoreCursorPosition(pCur);
if( rc==SQLITE_OK ){
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
- if( pCur->apPage[0]->intKey ){
+ assert( pCur->pPage!=0 );
+ if( pCur->pPage->intKey ){
return SQLITE_CORRUPT_BKPT;
}
- assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+ assert( pCur->pPage->intKey==0 );
+ assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0);
}
return rc;
@@ -37256,8 +35788,8 @@ SQLITE_PRIVATE int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *p
rc = restoreCursorPosition(pCur);
if( rc==SQLITE_OK ){
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
- assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+ assert( pCur->pPage!=0 );
+ assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
rc = accessPayload(pCur, offset, amt, pBuf, 1, 0);
}
return rc;
@@ -37290,13 +35822,13 @@ static const unsigned char *fetchPayload(
unsigned char *aPayload;
MemPage *pPage;
u32 nKey;
- u32 nLocal;
+ int nLocal;
- assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
+ assert( pCur!=0 && pCur->pPage!=0 );
assert( pCur->eState==CURSOR_VALID );
assert( cursorHoldsMutex(pCur) );
- pPage = pCur->apPage[pCur->iPage];
- assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
+ pPage = pCur->pPage;
+ assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
getCellInfo(pCur);
aPayload = pCur->info.pCell;
aPayload += pCur->info.nHeader;
@@ -37355,22 +35887,20 @@ SQLITE_PRIVATE const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
int rc;
- int i = pCur->iPage;
MemPage *pNewPage;
+ MemPage *pOldPage;
BtShared *pBt = pCur->pBt;
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
- if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
- return SQLITE_CORRUPT_BKPT;
- }
- rc = getAndInitPage(pBt, newPgno, &pNewPage);
+ rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage);
if( rc ) return rc;
- pCur->apPage[i+1] = pNewPage;
- pCur->aiIdx[i+1] = 0;
- pCur->iPage++;
-
+ pNewPage->idxParent = pCur->idx;
+ pOldPage = pCur->pPage;
+ pOldPage->idxShift = 0;
+ releasePage(pOldPage);
+ pCur->pPage = pNewPage;
+ pCur->idx = 0;
pCur->info.nSize = 0;
pCur->validNKey = 0;
if( pNewPage->nCell<1 ){
@@ -37379,25 +35909,25 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
return SQLITE_OK;
}
-#ifndef NDEBUG
/*
-** Page pParent is an internal (non-leaf) tree page. This function
-** asserts that page number iChild is the left-child if the iIdx'th
-** cell in page pParent. Or, if iIdx is equal to the total number of
-** cells in pParent, that page number iChild is the right-child of
-** the page.
+** Return true if the page is the virtual root of its table.
+**
+** The virtual root page is the root page for most tables. But
+** for the table rooted on page 1, sometime the real root page
+** is empty except for the right-pointer. In such cases the
+** virtual root page is the page that the right-pointer of page
+** 1 is pointing to.
*/
-static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
- assert( iIdx<=pParent->nCell );
- if( iIdx==pParent->nCell ){
- assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild );
- }else{
- assert( get4byte(findCell(pParent, iIdx))==iChild );
- }
+SQLITE_PRIVATE int sqlite3BtreeIsRootPage(MemPage *pPage){
+ MemPage *pParent;
+
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ pParent = pPage->pParent;
+ if( pParent==0 ) return 1;
+ if( pParent->pgno>1 ) return 0;
+ if( get2byte(&pParent->aData[pParent->hdrOffset+3])==0 ) return 1;
+ return 0;
}
-#else
-# define assertParentIndex(x,y,z)
-#endif
/*
** Move the cursor up to the parent page.
@@ -37408,19 +35938,25 @@ static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
** the largest cell index.
*/
SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur){
+ MemPage *pParent;
+ MemPage *pPage;
+ int idxParent;
+
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->iPage>0 );
- assert( pCur->apPage[pCur->iPage] );
- assertParentIndex(
- pCur->apPage[pCur->iPage-1],
- pCur->aiIdx[pCur->iPage-1],
- pCur->apPage[pCur->iPage]->pgno
- );
- releasePage(pCur->apPage[pCur->iPage]);
- pCur->iPage--;
+ pPage = pCur->pPage;
+ assert( pPage!=0 );
+ assert( !sqlite3BtreeIsRootPage(pPage) );
+ pParent = pPage->pParent;
+ assert( pParent!=0 );
+ idxParent = pPage->idxParent;
+ sqlite3PagerRef(pParent->pDbPage);
+ releasePage(pPage);
+ pCur->pPage = pParent;
pCur->info.nSize = 0;
pCur->validNKey = 0;
+ assert( pParent->idxShift==0 );
+ pCur->idx = idxParent;
}
/*
@@ -37440,31 +35976,25 @@ static int moveToRoot(BtCursor *pCur){
if( pCur->eState==CURSOR_FAULT ){
return pCur->skip;
}
- sqlite3BtreeClearCursor(pCur);
+ clearCursorPosition(pCur);
}
-
- if( pCur->iPage>=0 ){
- int i;
- for(i=1; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- }
+ pRoot = pCur->pPage;
+ if( pRoot && pRoot->pgno==pCur->pgnoRoot ){
+ assert( pRoot->isInit );
}else{
if(
- SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]))
+ SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0))
){
pCur->eState = CURSOR_INVALID;
return rc;
}
+ releasePage(pCur->pPage);
+ pCur->pPage = pRoot;
}
-
- pRoot = pCur->apPage[0];
- assert( pRoot->pgno==pCur->pgnoRoot );
- pCur->iPage = 0;
- pCur->aiIdx[0] = 0;
+ pCur->idx = 0;
pCur->info.nSize = 0;
pCur->atLast = 0;
pCur->validNKey = 0;
-
if( pRoot->nCell==0 && !pRoot->leaf ){
Pgno subpage;
assert( pRoot->pgno==1 );
@@ -37472,9 +36002,8 @@ static int moveToRoot(BtCursor *pCur){
assert( subpage>0 );
pCur->eState = CURSOR_VALID;
rc = moveToChild(pCur, subpage);
- }else{
- pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
}
+ pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
return rc;
}
@@ -37492,9 +36021,9 @@ static int moveToLeftmost(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
- while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
- assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
- pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
+ while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
+ assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
+ pgno = get4byte(findCell(pPage, pCur->idx));
rc = moveToChild(pCur, pgno);
}
return rc;
@@ -37517,17 +36046,17 @@ static int moveToRightmost(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
- while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
+ while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- pCur->aiIdx[pCur->iPage] = pPage->nCell;
+ pCur->idx = pPage->nCell;
rc = moveToChild(pCur, pgno);
}
if( rc==SQLITE_OK ){
- pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
+ pCur->idx = pPage->nCell - 1;
pCur->info.nSize = 0;
pCur->validNKey = 0;
}
- return rc;
+ return SQLITE_OK;
}
/* Move the cursor to the first entry in the table. Return SQLITE_OK
@@ -37542,11 +36071,11 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
if( pCur->eState==CURSOR_INVALID ){
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
+ assert( pCur->pPage->nCell==0 );
*pRes = 1;
rc = SQLITE_OK;
}else{
- assert( pCur->apPage[pCur->iPage]->nCell>0 );
+ assert( pCur->pPage->nCell>0 );
*pRes = 0;
rc = moveToLeftmost(pCur);
}
@@ -37566,7 +36095,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){
if( CURSOR_INVALID==pCur->eState ){
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
+ assert( pCur->pPage->nCell==0 );
*pRes = 1;
}else{
assert( pCur->eState==CURSOR_VALID );
@@ -37580,11 +36109,12 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
}
/* Move the cursor so that it points to an entry near the key
-** specified by pIdxKey or intKey. Return a success code.
+** specified by pKey/nKey/pUnKey. Return a success code.
**
-** For INTKEY tables, the intKey parameter is used. pIdxKey
-** must be NULL. For index tables, pIdxKey is used and intKey
-** is ignored.
+** For INTKEY tables, only the nKey parameter is used. pKey
+** and pUnKey must be NULL. For index tables, either pUnKey
+** must point to a key that has already been unpacked, or else
+** pKey/nKey describes a blob containing the key.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
@@ -37606,81 +36136,98 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
** is larger than pKey.
**
*/
-SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
- BtCursor *pCur, /* The cursor to be moved */
- UnpackedRecord *pIdxKey, /* Unpacked index key */
- i64 intKey, /* The table key */
- int biasRight, /* If true, bias the search to the high end */
- int *pRes /* Write search results here */
+SQLITE_PRIVATE int sqlite3BtreeMoveto(
+ BtCursor *pCur, /* The cursor to be moved */
+ const void *pKey, /* The key content for indices. Not used by tables */
+ UnpackedRecord *pUnKey,/* Unpacked version of pKey */
+ i64 nKey, /* Size of pKey. Or the key for tables */
+ int biasRight, /* If true, bias the search to the high end */
+ int *pRes /* Search result flag */
){
int rc;
+ char aSpace[200];
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
- if( pCur->eState==CURSOR_VALID && pCur->validNKey
- && pCur->apPage[0]->intKey
- ){
- if( pCur->info.nKey==intKey ){
+ if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){
+ if( pCur->info.nKey==nKey ){
*pRes = 0;
return SQLITE_OK;
}
- if( pCur->atLast && pCur->info.nKey<intKey ){
+ if( pCur->atLast && pCur->info.nKey<nKey ){
*pRes = -1;
return SQLITE_OK;
}
}
+
rc = moveToRoot(pCur);
if( rc ){
return rc;
}
- assert( pCur->apPage[pCur->iPage] );
- assert( pCur->apPage[pCur->iPage]->isInit );
+ assert( pCur->pPage );
+ assert( pCur->pPage->isInit );
if( pCur->eState==CURSOR_INVALID ){
*pRes = -1;
- assert( pCur->apPage[pCur->iPage]->nCell==0 );
+ assert( pCur->pPage->nCell==0 );
return SQLITE_OK;
}
- assert( pCur->apPage[0]->intKey || pIdxKey );
+ if( pCur->pPage->intKey ){
+ /* We are given an SQL table to search. The key is the integer
+ ** rowid contained in nKey. pKey and pUnKey should both be NULL */
+ assert( pUnKey==0 );
+ assert( pKey==0 );
+ }else if( pUnKey==0 ){
+ /* We are to search an SQL index using a key encoded as a blob.
+ ** The blob is found at pKey and is nKey bytes in length. Unpack
+ ** this key so that we can use it. */
+ assert( pKey!=0 );
+ pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
+ aSpace, sizeof(aSpace));
+ if( pUnKey==0 ) return SQLITE_NOMEM;
+ }else{
+ /* We are to search an SQL index using a key that is already unpacked
+ ** and handed to us in pUnKey. */
+ assert( pKey==0 );
+ }
for(;;){
int lwr, upr;
Pgno chldPg;
- MemPage *pPage = pCur->apPage[pCur->iPage];
+ MemPage *pPage = pCur->pPage;
int c = -1; /* pRes return if table is empty must be -1 */
lwr = 0;
upr = pPage->nCell-1;
- if( !pPage->intKey && pIdxKey==0 ){
+ if( !pPage->intKey && pUnKey==0 ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
if( biasRight ){
- pCur->aiIdx[pCur->iPage] = upr;
+ pCur->idx = upr;
}else{
- pCur->aiIdx[pCur->iPage] = (upr+lwr)/2;
+ pCur->idx = (upr+lwr)/2;
}
if( lwr<=upr ) for(;;){
void *pCellKey;
i64 nCellKey;
- int idx = pCur->aiIdx[pCur->iPage];
pCur->info.nSize = 0;
pCur->validNKey = 1;
if( pPage->intKey ){
u8 *pCell;
- pCell = findCell(pPage, idx) + pPage->childPtrSize;
+ pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize;
if( pPage->hasData ){
u32 dummy;
pCell += getVarint32(pCell, dummy);
}
getVarint(pCell, (u64*)&nCellKey);
- if( nCellKey==intKey ){
+ if( nCellKey==nKey ){
c = 0;
- }else if( nCellKey<intKey ){
+ }else if( nCellKey<nKey ){
c = -1;
}else{
- assert( nCellKey>intKey );
+ assert( nCellKey>nKey );
c = +1;
}
}else{
@@ -37688,7 +36235,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
pCellKey = (void *)fetchPayload(pCur, &available, 0);
nCellKey = pCur->info.nKey;
if( available>=nCellKey ){
- c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
+ c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
}else{
pCellKey = sqlite3Malloc( nCellKey );
if( pCellKey==0 ){
@@ -37696,7 +36243,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
goto moveto_finish;
}
rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
- c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
+ c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
sqlite3_free(pCellKey);
if( rc ) goto moveto_finish;
}
@@ -37704,7 +36251,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
if( c==0 ){
pCur->info.nKey = nCellKey;
if( pPage->intKey && !pPage->leaf ){
- lwr = idx;
+ lwr = pCur->idx;
upr = lwr - 1;
break;
}else{
@@ -37714,15 +36261,15 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
}
}
if( c<0 ){
- lwr = idx+1;
+ lwr = pCur->idx+1;
}else{
- upr = idx-1;
+ upr = pCur->idx-1;
}
if( lwr>upr ){
pCur->info.nKey = nCellKey;
break;
}
- pCur->aiIdx[pCur->iPage] = (lwr+upr)/2;
+ pCur->idx = (lwr+upr)/2;
}
assert( lwr==upr+1 );
assert( pPage->isInit );
@@ -37734,47 +36281,22 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
chldPg = get4byte(findCell(pPage, lwr));
}
if( chldPg==0 ){
- assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
+ assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
if( pRes ) *pRes = c;
rc = SQLITE_OK;
goto moveto_finish;
}
- pCur->aiIdx[pCur->iPage] = lwr;
+ pCur->idx = lwr;
pCur->info.nSize = 0;
pCur->validNKey = 0;
rc = moveToChild(pCur, chldPg);
if( rc ) goto moveto_finish;
}
moveto_finish:
- return rc;
-}
-
-/*
-** In this version of BtreeMoveto, pKey is a packed index record
-** such as is generated by the OP_MakeRecord opcode. Unpack the
-** record and then call BtreeMovetoUnpacked() to do the work.
-*/
-SQLITE_PRIVATE int sqlite3BtreeMoveto(
- BtCursor *pCur, /* Cursor open on the btree to be searched */
- const void *pKey, /* Packed key if the btree is an index */
- i64 nKey, /* Integer key for tables. Size of pKey for indices */
- int bias, /* Bias search to the high end */
- int *pRes /* Write search results here */
-){
- int rc; /* Status code */
- UnpackedRecord *pIdxKey; /* Unpacked index key */
- UnpackedRecord aSpace[16]; /* Temp space for pIdxKey - to avoid a malloc */
-
- if( pKey ){
- pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
- aSpace, sizeof(aSpace));
- if( pIdxKey==0 ) return SQLITE_NOMEM;
- }else{
- pIdxKey = 0;
- }
- rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
if( pKey ){
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ /* If we created our own unpacked key at the top of this
+ ** procedure, then destroy that key before returning. */
+ sqlite3VdbeDeleteUnpackedRecord(pUnKey);
}
return rc;
}
@@ -37811,7 +36333,6 @@ SQLITE_PRIVATE sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){
*/
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
int rc;
- int idx;
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
@@ -37820,6 +36341,7 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
return rc;
}
assert( pRes!=0 );
+ pPage = pCur->pPage;
if( CURSOR_INVALID==pCur->eState ){
*pRes = 1;
return SQLITE_OK;
@@ -37831,14 +36353,13 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
}
pCur->skip = 0;
- pPage = pCur->apPage[pCur->iPage];
- idx = ++pCur->aiIdx[pCur->iPage];
assert( pPage->isInit );
- assert( idx<=pPage->nCell );
+ assert( pCur->idx<pPage->nCell );
+ pCur->idx++;
pCur->info.nSize = 0;
pCur->validNKey = 0;
- if( idx>=pPage->nCell ){
+ if( pCur->idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
if( rc ) return rc;
@@ -37847,14 +36368,14 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
return rc;
}
do{
- if( pCur->iPage==0 ){
+ if( sqlite3BtreeIsRootPage(pPage) ){
*pRes = 1;
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}
sqlite3BtreeMoveToParent(pCur);
- pPage = pCur->apPage[pCur->iPage];
- }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell );
+ pPage = pCur->pPage;
+ }while( pCur->idx>=pPage->nCell );
*pRes = 0;
if( pPage->intKey ){
rc = sqlite3BtreeNext(pCur, pRes);
@@ -37880,6 +36401,7 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
*/
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int rc;
+ Pgno pgno;
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
@@ -37899,29 +36421,29 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
}
pCur->skip = 0;
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
assert( pPage->isInit );
+ assert( pCur->idx>=0 );
if( !pPage->leaf ){
- int idx = pCur->aiIdx[pCur->iPage];
- rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
+ pgno = get4byte( findCell(pPage, pCur->idx) );
+ rc = moveToChild(pCur, pgno);
if( rc ){
return rc;
}
rc = moveToRightmost(pCur);
}else{
- while( pCur->aiIdx[pCur->iPage]==0 ){
- if( pCur->iPage==0 ){
+ while( pCur->idx==0 ){
+ if( sqlite3BtreeIsRootPage(pPage) ){
pCur->eState = CURSOR_INVALID;
*pRes = 1;
return SQLITE_OK;
}
sqlite3BtreeMoveToParent(pCur);
+ pPage = pCur->pPage;
}
+ pCur->idx--;
pCur->info.nSize = 0;
pCur->validNKey = 0;
-
- pCur->aiIdx[pCur->iPage]--;
- pPage = pCur->apPage[pCur->iPage];
if( pPage->intKey && !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, pRes);
}else{
@@ -37980,7 +36502,7 @@ static int allocateBtreePage(
** the entire-list will be searched for that page.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( exact && nearby<=pagerPagecount(pBt) ){
+ if( exact && nearby<=pagerPagecount(pBt->pPager) ){
u8 eType;
assert( nearby>0 );
assert( pBt->autoVacuum );
@@ -38115,9 +36637,9 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]);
if( !searchList || iPage==nearby ){
- Pgno nPage;
+ int nPage;
*pPgno = iPage;
- nPage = pagerPagecount(pBt);
+ nPage = pagerPagecount(pBt->pPager);
if( *pPgno>nPage ){
/* Free page off the end of the file */
rc = SQLITE_CORRUPT_BKPT;
@@ -38147,7 +36669,7 @@ static int allocateBtreePage(
}else{
/* There are no pages on the freelist, so create a new page at the
** end of the file */
- int nPage = pagerPagecount(pBt);
+ int nPage = pagerPagecount(pBt->pPager);
*pPgno = nPage + 1;
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -38191,13 +36713,6 @@ static int allocateBtreePage(
end_allocate_page:
releasePage(pTrunk);
releasePage(pPrevTrunk);
- if( rc==SQLITE_OK ){
- if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
- releasePage(*ppPage);
- return SQLITE_CORRUPT_BKPT;
- }
- (*ppPage)->isInit = 0;
- }
return rc;
}
@@ -38215,6 +36730,8 @@ static int freePage(MemPage *pPage){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( pPage->pgno>1 );
pPage->isInit = 0;
+ releasePage(pPage->pParent);
+ pPage->pParent = 0;
/* Increment the free page count on pPage1 */
rc = sqlite3PagerWrite(pPage1->pDbPage);
@@ -38285,7 +36802,7 @@ static int freePage(MemPage *pPage){
put4byte(&pTrunk->aData[4], k+1);
put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
#ifndef SQLITE_SECURE_DELETE
- rc = sqlite3PagerDontWrite(pPage->pDbPage);
+ sqlite3PagerDontWrite(pPage->pDbPage);
#endif
}
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
@@ -38317,7 +36834,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
assert( ovflPgno==0 || nOvfl>0 );
while( nOvfl-- ){
MemPage *pOvfl;
- if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt) ){
+ if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt->pPager) ){
return SQLITE_CORRUPT_BKPT;
}
@@ -38379,7 +36896,7 @@ static int fillInCell(
sqlite3BtreeParseCellPtr(pPage, pCell, &info);
assert( info.nHeader==nHeader );
assert( info.nKey==nKey );
- assert( info.nData==(u32)(nData+nZero) );
+ assert( info.nData==nData+nZero );
/* Fill in the payload */
nPayload = nData + nZero;
@@ -38468,6 +36985,102 @@ static int fillInCell(
return SQLITE_OK;
}
+
+/*
+** Change the MemPage.pParent pointer on the page whose number is
+** given in the second argument so that MemPage.pParent holds the
+** pointer in the third argument.
+**
+** If the final argument, updatePtrmap, is non-zero and the database
+** is an auto-vacuum database, then the pointer-map entry for pgno
+** is updated.
+*/
+static int reparentPage(
+ BtShared *pBt, /* B-Tree structure */
+ Pgno pgno, /* Page number of child being adopted */
+ MemPage *pNewParent, /* New parent of pgno */
+ int idx, /* Index of child page pgno in pNewParent */
+ int updatePtrmap /* If true, update pointer-map for pgno */
+){
+ MemPage *pThis;
+ DbPage *pDbPage;
+
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( pNewParent!=0 );
+ if( pgno==0 ) return SQLITE_OK;
+ assert( pBt->pPager!=0 );
+ pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
+ if( pDbPage ){
+ pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage);
+ if( pThis->isInit ){
+ assert( pThis->aData==sqlite3PagerGetData(pDbPage) );
+ if( pThis->pParent!=pNewParent ){
+ if( pThis->pParent ) sqlite3PagerUnref(pThis->pParent->pDbPage);
+ pThis->pParent = pNewParent;
+ sqlite3PagerRef(pNewParent->pDbPage);
+ }
+ pThis->idxParent = idx;
+ }
+ sqlite3PagerUnref(pDbPage);
+ }
+
+ if( ISAUTOVACUUM && updatePtrmap ){
+ return ptrmapPut(pBt, pgno, PTRMAP_BTREE, pNewParent->pgno);
+ }
+
+#ifndef NDEBUG
+ /* If the updatePtrmap flag was clear, assert that the entry in the
+ ** pointer-map is already correct.
+ */
+ if( ISAUTOVACUUM ){
+ pDbPage = sqlite3PagerLookup(pBt->pPager,PTRMAP_PAGENO(pBt,pgno));
+ if( pDbPage ){
+ u8 eType;
+ Pgno ii;
+ int rc = ptrmapGet(pBt, pgno, &eType, &ii);
+ assert( rc==SQLITE_OK && ii==pNewParent->pgno && eType==PTRMAP_BTREE );
+ sqlite3PagerUnref(pDbPage);
+ }
+ }
+#endif
+
+ return SQLITE_OK;
+}
+
+
+
+/*
+** Change the pParent pointer of all children of pPage to point back
+** to pPage.
+**
+** In other words, for every child of pPage, invoke reparentPage()
+** to make sure that each child knows that pPage is its parent.
+**
+** This routine gets called after you memcpy() one page into
+** another.
+**
+** If updatePtrmap is true, then the pointer-map entries for all child
+** pages of pPage are updated.
+*/
+static int reparentChildPages(MemPage *pPage, int updatePtrmap){
+ int rc = SQLITE_OK;
+ assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ if( !pPage->leaf ){
+ int i;
+ BtShared *pBt = pPage->pBt;
+ Pgno iRight = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+
+ for(i=0; i<pPage->nCell; i++){
+ u8 *pCell = findCell(pPage, i);
+ rc = reparentPage(pBt, get4byte(pCell), pPage, i, updatePtrmap);
+ if( rc!=SQLITE_OK ) return rc;
+ }
+ rc = reparentPage(pBt, iRight, pPage, i, updatePtrmap);
+ pPage->idxShift = 0;
+ }
+ return rc;
+}
+
/*
** Remove the i-th cell from pPage. This routine effects pPage only.
** The cell content is not freed or deallocated. It is assumed that
@@ -38476,12 +37089,11 @@ static int fillInCell(
**
** "sz" must be the number of bytes in the cell.
*/
-static int dropCell(MemPage *pPage, int idx, int sz){
+static void dropCell(MemPage *pPage, int idx, int sz){
int i; /* Loop counter */
int pc; /* Offset to cell content of cell being deleted */
u8 *data; /* pPage->aData */
u8 *ptr; /* Used to move bytes around within data[] */
- int rc; /* The return code */
assert( idx>=0 && idx<pPage->nCell );
assert( sz==cellSize(pPage, idx) );
@@ -38490,13 +37102,8 @@ static int dropCell(MemPage *pPage, int idx, int sz){
data = pPage->aData;
ptr = &data[pPage->cellOffset + 2*idx];
pc = get2byte(ptr);
- if ( (pc<pPage->hdrOffset+6+(pPage->leaf?0:4)) || (pc+sz>pPage->pBt->usableSize) ) {
- return SQLITE_CORRUPT_BKPT;
- }
- rc = freeSpace(pPage, pc, sz);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ assert( pc>10 && pc+sz<=pPage->pBt->usableSize );
+ freeSpace(pPage, pc, sz);
for(i=idx+1; i<pPage->nCell; i++, ptr+=2){
ptr[0] = ptr[2];
ptr[1] = ptr[3];
@@ -38504,7 +37111,7 @@ static int dropCell(MemPage *pPage, int idx, int sz){
pPage->nCell--;
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
pPage->nFree += 2;
- return SQLITE_OK;
+ pPage->idxShift = 1;
}
/*
@@ -38551,7 +37158,7 @@ static int insertCell(
pCell = pTemp;
}
j = pPage->nOverflow++;
- assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) );
+ assert( j<sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0]) );
pPage->aOvfl[j].pCell = pCell;
pPage->aOvfl[j].idx = i;
pPage->nFree = 0;
@@ -38568,19 +37175,13 @@ static int insertCell(
end = cellOffset + 2*pPage->nCell + 2;
ins = cellOffset + 2*i;
if( end > top - sz ){
- rc = defragmentPage(pPage);
- if( rc!=SQLITE_OK ){
- return rc;
- }
+ defragmentPage(pPage);
top = get2byte(&data[hdr+5]);
assert( end + sz <= top );
}
idx = allocateSpace(pPage, sz);
assert( idx>0 );
assert( end <= get2byte(&data[hdr+5]) );
- if (idx+sz > pPage->pBt->usableSize) {
- return SQLITE_CORRUPT_BKPT;
- }
pPage->nCell++;
pPage->nFree -= 2;
memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
@@ -38590,6 +37191,7 @@ static int insertCell(
}
put2byte(&data[ins], idx);
put2byte(&data[hdr+3], pPage->nCell);
+ pPage->idxShift = 1;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pPage->pBt->autoVacuum ){
/* The cell may contain a pointer to an overflow page. If so, write
@@ -38671,7 +37273,7 @@ static void assemblePage(
#define NB (NN*2+1) /* Total pages involved in the balance */
/* Forward reference */
-static int balance(BtCursor*, int);
+static int balance(MemPage*, int);
#ifndef SQLITE_OMIT_QUICKBALANCE
/*
@@ -38691,15 +37293,13 @@ static int balance(BtCursor*, int);
** pParent is its parent. pPage must have a single overflow entry
** which is also the right-most entry on the page.
*/
-static int balance_quick(BtCursor *pCur){
+static int balance_quick(MemPage *pPage, MemPage *pParent){
int rc;
- MemPage *pNew = 0;
+ MemPage *pNew;
Pgno pgnoNew;
u8 *pCell;
u16 szCell;
CellInfo info;
- MemPage *pPage = pCur->apPage[pCur->iPage];
- MemPage *pParent = pCur->apPage[pCur->iPage-1];
BtShared *pBt = pPage->pBt;
int parentIdx = pParent->nCell; /* pParent new divider cell index */
int parentSize; /* Size of new divider cell */
@@ -38711,77 +37311,63 @@ static int balance_quick(BtCursor *pCur){
** into it. Then remove the overflow cell from pPage.
*/
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
- if( rc==SQLITE_OK ){
- pCell = pPage->aOvfl[0].pCell;
- szCell = cellSizePtr(pPage, pCell);
- zeroPage(pNew, pPage->aData[0]);
- assemblePage(pNew, 1, &pCell, &szCell);
- pPage->nOverflow = 0;
-
- /* pPage is currently the right-child of pParent. Change this
- ** so that the right-child is the new page allocated above and
- ** pPage is the next-to-right child.
- **
- ** Ignore the return value of the call to fillInCell(). fillInCell()
- ** may only return other than SQLITE_OK if it is required to allocate
- ** one or more overflow pages. Since an internal table B-Tree cell
- ** may never spill over onto an overflow page (it is a maximum of
- ** 13 bytes in size), it is not neccessary to check the return code.
- **
- ** Similarly, the insertCell() function cannot fail if the page
- ** being inserted into is already writable and the cell does not
- ** contain an overflow pointer. So ignore this return code too.
- */
- assert( pPage->nCell>0 );
- pCell = findCell(pPage, pPage->nCell-1);
- sqlite3BtreeParseCellPtr(pPage, pCell, &info);
- fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize);
- assert( parentSize<64 );
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
- insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
- put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
- put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
-
- /* If this is an auto-vacuum database, update the pointer map
- ** with entries for the new page, and any pointer from the
- ** cell on the page to an overflow page.
- */
- if( ISAUTOVACUUM ){
- rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
- if( rc==SQLITE_OK ){
- rc = ptrmapPutOvfl(pNew, 0);
- }
- }
-
- /* Release the reference to the new page. */
- releasePage(pNew);
+ if( rc!=SQLITE_OK ){
+ return rc;
}
+ pCell = pPage->aOvfl[0].pCell;
+ szCell = cellSizePtr(pPage, pCell);
+ zeroPage(pNew, pPage->aData[0]);
+ assemblePage(pNew, 1, &pCell, &szCell);
+ pPage->nOverflow = 0;
+
+ /* Set the parent of the newly allocated page to pParent. */
+ pNew->pParent = pParent;
+ sqlite3PagerRef(pParent->pDbPage);
- /* At this point the pPage->nFree variable is not set correctly with
- ** respect to the content of the page (because it was set to 0 by
- ** insertCell). So call sqlite3BtreeInitPage() to make sure it is
- ** correct.
+ /* pPage is currently the right-child of pParent. Change this
+ ** so that the right-child is the new page allocated above and
+ ** pPage is the next-to-right child.
+ **
+ ** Ignore the return value of the call to fillInCell(). fillInCell()
+ ** may only return other than SQLITE_OK if it is required to allocate
+ ** one or more overflow pages. Since an internal table B-Tree cell
+ ** may never spill over onto an overflow page (it is a maximum of
+ ** 13 bytes in size), it is not neccessary to check the return code.
**
- ** This has to be done even if an error will be returned. Normally, if
- ** an error occurs during tree balancing, the contents of MemPage are
- ** not important, as they will be recalculated when the page is rolled
- ** back. But here, in balance_quick(), it is possible that pPage has
- ** not yet been marked dirty or written into the journal file. Therefore
- ** it will not be rolled back and so it is important to make sure that
- ** the page data and contents of MemPage are consistent.
+ ** Similarly, the insertCell() function cannot fail if the page
+ ** being inserted into is already writable and the cell does not
+ ** contain an overflow pointer. So ignore this return code too.
*/
- pPage->isInit = 0;
- sqlite3BtreeInitPage(pPage);
+ assert( pPage->nCell>0 );
+ pCell = findCell(pPage, pPage->nCell-1);
+ sqlite3BtreeParseCellPtr(pPage, pCell, &info);
+ fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize);
+ assert( parentSize<64 );
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
+ put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
+ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
- /* If everything else succeeded, balance the parent page, in
- ** case the divider cell inserted caused it to become overfull.
+ /* If this is an auto-vacuum database, update the pointer map
+ ** with entries for the new page, and any pointer from the
+ ** cell on the page to an overflow page.
*/
- if( rc==SQLITE_OK ){
- releasePage(pPage);
- pCur->iPage--;
- rc = balance(pCur, 0);
+ if( ISAUTOVACUUM ){
+ rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
+ if( rc==SQLITE_OK ){
+ rc = ptrmapPutOvfl(pNew, 0);
+ }
+ if( rc!=SQLITE_OK ){
+ releasePage(pNew);
+ return rc;
+ }
}
- return rc;
+
+ /* Release the reference to the new page and balance the parent page,
+ ** in case the divider cell inserted caused it to become overfull.
+ */
+ releasePage(pNew);
+ return balance(pParent, 0);
}
#endif /* SQLITE_OMIT_QUICKBALANCE */
@@ -38814,8 +37400,7 @@ static int balance_quick(BtCursor *pCur){
** in a corrupted state. So if this routine fails, the database should
** be rolled back.
*/
-static int balance_nonroot(BtCursor *pCur){
- MemPage *pPage; /* The over or underfull page to balance */
+static int balance_nonroot(MemPage *pPage){
MemPage *pParent; /* The parent of pPage */
BtShared *pBt; /* The whole database */
int nCell = 0; /* Number of cells in apCell[] */
@@ -38850,18 +37435,15 @@ static int balance_nonroot(BtCursor *pCur){
u8 *aSpace2 = 0; /* Space for overflow dividers cells after balance */
u8 *aFrom = 0;
- pPage = pCur->apPage[pCur->iPage];
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- VVA_ONLY( pCur->pagesShuffled = 1 );
/*
** Find the parent page.
*/
- assert( pCur->iPage>0 );
assert( pPage->isInit );
assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 );
pBt = pPage->pBt;
- pParent = pCur->apPage[pCur->iPage-1];
+ pParent = pPage->pParent;
assert( pParent );
if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){
return rc;
@@ -38882,7 +37464,7 @@ static int balance_nonroot(BtCursor *pCur){
pPage->intKey &&
pPage->nOverflow==1 &&
pPage->aOvfl[0].idx==pPage->nCell &&
- pParent->pgno!=1 &&
+ pPage->pParent->pgno!=1 &&
get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno
){
assert( pPage->intKey );
@@ -38890,7 +37472,7 @@ static int balance_nonroot(BtCursor *pCur){
** TODO: Check the siblings to the left of pPage. It may be that
** they are not full and no new page is required.
*/
- return balance_quick(pCur);
+ return balance_quick(pPage, pParent);
}
#endif
@@ -38903,14 +37485,27 @@ static int balance_nonroot(BtCursor *pCur){
** to pPage. The "idx" variable is the index of that cell. If pPage
** is the rightmost child of pParent then set idx to pParent->nCell
*/
- idx = pCur->aiIdx[pCur->iPage-1];
- assertParentIndex(pParent, idx, pPage->pgno);
+ if( pParent->idxShift ){
+ Pgno pgno;
+ pgno = pPage->pgno;
+ assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
+ for(idx=0; idx<pParent->nCell; idx++){
+ if( get4byte(findCell(pParent, idx))==pgno ){
+ break;
+ }
+ }
+ assert( idx<pParent->nCell
+ || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno );
+ }else{
+ idx = pPage->idxParent;
+ }
/*
** Initialize variables so that it will be safe to jump
** directly to balance_cleanup at any moment.
*/
nOld = nNew = 0;
+ sqlite3PagerRef(pParent->pDbPage);
/*
** Find sibling pages to pPage and the cells in pParent that divide
@@ -38938,9 +37533,9 @@ static int balance_nonroot(BtCursor *pCur){
}else{
break;
}
- rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i]);
+ rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i], pParent);
if( rc ) goto balance_cleanup;
- /* apOld[i]->idxParent = k; */
+ apOld[i]->idxParent = k;
apCopy[i] = 0;
assert( i==nOld );
nOld++;
@@ -39363,6 +37958,16 @@ static int balance_nonroot(BtCursor *pCur){
}
/*
+ ** Reparent children of all cells.
+ */
+ for(i=0; i<nNew; i++){
+ rc = reparentChildPages(apNew[i], 0);
+ if( rc!=SQLITE_OK ) goto balance_cleanup;
+ }
+ rc = reparentChildPages(pParent, 0);
+ if( rc!=SQLITE_OK ) goto balance_cleanup;
+
+ /*
** Balance the parent page. Note that the current page (pPage) might
** have been added to the freelist so it might no longer be initialized.
** But the parent page will always be initialized.
@@ -39370,9 +37975,7 @@ static int balance_nonroot(BtCursor *pCur){
assert( pParent->isInit );
sqlite3ScratchFree(apCell);
apCell = 0;
- releasePage(pPage);
- pCur->iPage--;
- rc = balance(pCur, 0);
+ rc = balance(pParent, 0);
/*
** Cleanup before returning.
@@ -39386,11 +37989,9 @@ balance_cleanup:
for(i=0; i<nNew; i++){
releasePage(apNew[i]);
}
-
- /* releasePage(pParent); */
+ releasePage(pParent);
TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n",
pPage->pgno, nOld, nNew, nCell));
-
return rc;
}
@@ -39399,8 +38000,7 @@ balance_cleanup:
** page contains no cells. This is an opportunity to make the tree
** shallower by one level.
*/
-static int balance_shallower(BtCursor *pCur){
- MemPage *pPage; /* Root page of B-Tree */
+static int balance_shallower(MemPage *pPage){
MemPage *pChild; /* The only child page of pPage */
Pgno pgnoChild; /* Page number for pChild */
int rc = SQLITE_OK; /* Return code from subprocedures */
@@ -39409,9 +38009,7 @@ static int balance_shallower(BtCursor *pCur){
u8 **apCell; /* All cells from pages being balanced */
u16 *szCell; /* Local size of all cells */
- assert( pCur->iPage==0 );
- pPage = pCur->apPage[0];
-
+ assert( pPage->pParent==0 );
assert( pPage->nCell==0 );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pBt = pPage->pBt;
@@ -39435,14 +38033,13 @@ static int balance_shallower(BtCursor *pCur){
** for the right-pointer to the child page. The child page becomes
** the virtual root of the tree.
*/
- VVA_ONLY( pCur->pagesShuffled = 1 );
pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]);
assert( pgnoChild>0 );
- assert( pgnoChild<=pagerPagecount(pPage->pBt) );
+ assert( pgnoChild<=pagerPagecount(pPage->pBt->pPager) );
rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0);
if( rc ) goto end_shallow_balance;
if( pPage->pgno==1 ){
- rc = sqlite3BtreeInitPage(pChild);
+ rc = sqlite3BtreeInitPage(pChild, pPage);
if( rc ) goto end_shallow_balance;
assert( pChild->nOverflow==0 );
if( pChild->nFree>=100 ){
@@ -39468,18 +38065,24 @@ static int balance_shallower(BtCursor *pCur){
}else{
memcpy(pPage->aData, pChild->aData, pPage->pBt->usableSize);
pPage->isInit = 0;
- rc = sqlite3BtreeInitPage(pPage);
+ pPage->pParent = 0;
+ rc = sqlite3BtreeInitPage(pPage, 0);
assert( rc==SQLITE_OK );
freePage(pChild);
TRACE(("BALANCE: transfer child %d into root %d\n",
pChild->pgno, pPage->pgno));
}
+ rc = reparentChildPages(pPage, 1);
assert( pPage->nOverflow==0 );
-#ifndef SQLITE_OMIT_AUTOVACUUM
if( ISAUTOVACUUM ){
- rc = setChildPtrmaps(pPage);
+ int i;
+ for(i=0; i<pPage->nCell; i++){
+ rc = ptrmapPutOvfl(pPage, i);
+ if( rc!=SQLITE_OK ){
+ goto end_shallow_balance;
+ }
+ }
}
-#endif
releasePage(pChild);
}
end_shallow_balance:
@@ -39497,9 +38100,8 @@ end_shallow_balance:
** child. Finally, call balance_internal() on the new child
** to cause it to split.
*/
-static int balance_deeper(BtCursor *pCur){
+static int balance_deeper(MemPage *pPage){
int rc; /* Return value from subprocedures */
- MemPage *pPage; /* Pointer to the root page */
MemPage *pChild; /* Pointer to a new child page */
Pgno pgnoChild; /* Page number of the new child page */
BtShared *pBt; /* The BTree */
@@ -39507,13 +38109,10 @@ static int balance_deeper(BtCursor *pCur){
u8 *data; /* Content of the parent page */
u8 *cdata; /* Content of the child page */
int hdr; /* Offset to page header in parent */
- int cbrk; /* Offset to content of first cell in parent */
+ int brk; /* Offset to content of first cell in parent */
- assert( pCur->iPage==0 );
- assert( pCur->apPage[0]->nOverflow>0 );
-
- VVA_ONLY( pCur->pagesShuffled = 1 );
- pPage = pCur->apPage[0];
+ assert( pPage->pParent==0 );
+ assert( pPage->nOverflow>0 );
pBt = pPage->pBt;
assert( sqlite3_mutex_held(pBt->mutex) );
rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0);
@@ -39522,72 +38121,62 @@ static int balance_deeper(BtCursor *pCur){
usableSize = pBt->usableSize;
data = pPage->aData;
hdr = pPage->hdrOffset;
- cbrk = get2byte(&data[hdr+5]);
+ brk = get2byte(&data[hdr+5]);
cdata = pChild->aData;
memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
- memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
-
- assert( pChild->isInit==0 );
- rc = sqlite3BtreeInitPage(pChild);
- if( rc==SQLITE_OK ){
- int nCopy = pPage->nOverflow*sizeof(pPage->aOvfl[0]);
- memcpy(pChild->aOvfl, pPage->aOvfl, nCopy);
- pChild->nOverflow = pPage->nOverflow;
- if( pChild->nOverflow ){
- pChild->nFree = 0;
- }
- assert( pChild->nCell==pPage->nCell );
- zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF);
- put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild);
- TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno));
- if( ISAUTOVACUUM ){
- rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( rc==SQLITE_OK ){
- rc = setChildPtrmaps(pChild);
+ memcpy(&cdata[brk], &data[brk], usableSize-brk);
+ if( pChild->isInit ) return SQLITE_CORRUPT;
+ rc = sqlite3BtreeInitPage(pChild, pPage);
+ if( rc ) goto balancedeeper_out;
+ memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0]));
+ pChild->nOverflow = pPage->nOverflow;
+ if( pChild->nOverflow ){
+ pChild->nFree = 0;
+ }
+ assert( pChild->nCell==pPage->nCell );
+ zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF);
+ put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild);
+ TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno));
+ if( ISAUTOVACUUM ){
+ int i;
+ rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno);
+ if( rc ) goto balancedeeper_out;
+ for(i=0; i<pChild->nCell; i++){
+ rc = ptrmapPutOvfl(pChild, i);
+ if( rc!=SQLITE_OK ){
+ goto balancedeeper_out;
}
-#endif
}
+ rc = reparentChildPages(pChild, 1);
}
-
if( rc==SQLITE_OK ){
- pCur->iPage++;
- pCur->apPage[1] = pChild;
- pCur->aiIdx[0] = 0;
- rc = balance_nonroot(pCur);
- }else{
- releasePage(pChild);
+ rc = balance_nonroot(pChild);
}
+balancedeeper_out:
+ releasePage(pChild);
return rc;
}
/*
-** The page that pCur currently points to has just been modified in
-** some way. This function figures out if this modification means the
-** tree needs to be balanced, and if so calls the appropriate balancing
-** routine.
-**
-** Parameter isInsert is true if a new cell was just inserted into the
-** page, or false otherwise.
+** Decide if the page pPage needs to be balanced. If balancing is
+** required, call the appropriate balancing routine.
*/
-static int balance(BtCursor *pCur, int isInsert){
+static int balance(MemPage *pPage, int insert){
int rc = SQLITE_OK;
- MemPage *pPage = pCur->apPage[pCur->iPage];
-
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- if( pCur->iPage==0 ){
+ if( pPage->pParent==0 ){
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc==SQLITE_OK && pPage->nOverflow>0 ){
- rc = balance_deeper(pCur);
+ rc = balance_deeper(pPage);
}
if( rc==SQLITE_OK && pPage->nCell==0 ){
- rc = balance_shallower(pCur);
+ rc = balance_shallower(pPage);
}
}else{
if( pPage->nOverflow>0 ||
- (!isInsert && pPage->nFree>pPage->pBt->usableSize*2/3) ){
- rc = balance_nonroot(pCur);
+ (!insert && pPage->nFree>pPage->pBt->usableSize*2/3) ){
+ rc = balance_nonroot(pPage);
}
}
return rc;
@@ -39681,7 +38270,6 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
int rc;
int loc;
int szNew;
- int idx;
MemPage *pPage;
Btree *p = pCur->pBtree;
BtShared *pBt = p->pBt;
@@ -39706,15 +38294,15 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
}
/* Save the positions of any other cursors open on this table */
- sqlite3BtreeClearCursor(pCur);
+ clearCursorPosition(pCur);
if(
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
- SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
+ SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc))
){
return rc;
}
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
assert( pPage->intKey || nKey>=0 );
assert( pPage->leaf || !pPage->intKey );
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
@@ -39728,36 +38316,32 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
if( rc ) goto end_insert;
assert( szNew==cellSizePtr(pPage, newCell) );
assert( szNew<=MX_CELL_SIZE(pBt) );
- idx = pCur->aiIdx[pCur->iPage];
if( loc==0 && CURSOR_VALID==pCur->eState ){
u16 szOld;
- assert( idx<pPage->nCell );
+ assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
goto end_insert;
}
- oldCell = findCell(pPage, idx);
+ oldCell = findCell(pPage, pCur->idx);
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
szOld = cellSizePtr(pPage, oldCell);
rc = clearCell(pPage, oldCell);
if( rc ) goto end_insert;
- rc = dropCell(pPage, idx, szOld);
- if( rc!=SQLITE_OK ) {
- goto end_insert;
- }
+ dropCell(pPage, pCur->idx, szOld);
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
- idx = ++pCur->aiIdx[pCur->iPage];
+ pCur->idx++;
pCur->info.nSize = 0;
pCur->validNKey = 0;
}else{
assert( pPage->leaf );
}
- rc = insertCell(pPage, idx, newCell, szNew, 0, 0);
+ rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0);
if( rc!=SQLITE_OK ) goto end_insert;
- rc = balance(pCur, 1);
+ rc = balance(pPage, 1);
if( rc==SQLITE_OK ){
moveToRoot(pCur);
}
@@ -39767,11 +38351,10 @@ end_insert:
/*
** Delete the entry that the cursor is pointing to. The cursor
-** is left pointing at a arbitrary location.
+** is left pointing at a random location.
*/
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
- MemPage *pPage = pCur->apPage[pCur->iPage];
- int idx;
+ MemPage *pPage = pCur->pPage;
unsigned char *pCell;
int rc;
Pgno pgnoChild = 0;
@@ -39789,7 +38372,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
if( pCur->eState==CURSOR_FAULT ){
return pCur->skip;
}
- if( pCur->aiIdx[pCur->iPage]>=pPage->nCell ){
+ if( pCur->idx >= pPage->nCell ){
return SQLITE_ERROR; /* The cursor is not pointing to anything */
}
if( !pCur->wrFlag ){
@@ -39816,8 +38399,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
** data. The clearCell() call frees any overflow pages associated with the
** cell. The cell itself is still intact.
*/
- idx = pCur->aiIdx[pCur->iPage];
- pCell = findCell(pPage, idx);
+ pCell = findCell(pPage, pCur->idx);
if( !pPage->leaf ){
pgnoChild = get4byte(pCell);
}
@@ -39835,8 +38417,6 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
** to be a leaf so we can use it.
*/
BtCursor leafCur;
- MemPage *pLeafPage;
-
unsigned char *pNext;
int notUsed;
unsigned char *tempCell = 0;
@@ -39844,18 +38424,15 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
sqlite3BtreeGetTempCursor(pCur, &leafCur);
rc = sqlite3BtreeNext(&leafCur, &notUsed);
if( rc==SQLITE_OK ){
- assert( leafCur.aiIdx[leafCur.iPage]==0 );
- pLeafPage = leafCur.apPage[leafCur.iPage];
- rc = sqlite3PagerWrite(pLeafPage->pDbPage);
+ rc = sqlite3PagerWrite(leafCur.pPage->pDbPage);
}
if( rc==SQLITE_OK ){
- int leafCursorInvalid = 0;
u16 szNext;
TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n",
- pCur->pgnoRoot, pPage->pgno, pLeafPage->pgno));
- dropCell(pPage, idx, cellSizePtr(pPage, pCell));
- pNext = findCell(pLeafPage, 0);
- szNext = cellSizePtr(pLeafPage, pNext);
+ pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno));
+ dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell));
+ pNext = findCell(leafCur.pPage, leafCur.idx);
+ szNext = cellSizePtr(leafCur.pPage, pNext);
assert( MX_CELL_SIZE(pBt)>=szNext+4 );
allocateTempSpace(pBt);
tempCell = pBt->pTmpSpace;
@@ -39863,107 +38440,23 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
- rc = insertCell(pPage, idx, pNext-4, szNext+4, tempCell, 0);
- }
-
-
- /* The "if" statement in the next code block is critical. The
- ** slightest error in that statement would allow SQLite to operate
- ** correctly most of the time but produce very rare failures. To
- ** guard against this, the following macros help to verify that
- ** the "if" statement is well tested.
- */
- testcase( pPage->nOverflow==0 && pPage->nFree<pBt->usableSize*2/3
- && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
- testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3
- && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
- testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3+1
- && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
- testcase( pPage->nOverflow>0 && pPage->nFree<=pBt->usableSize*2/3
- && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
- testcase( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3))
- && pLeafPage->nFree+2+szNext == pBt->usableSize*2/3 );
-
-
- if( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3)) &&
- (pLeafPage->nFree+2+szNext > pBt->usableSize*2/3)
- ){
- /* This branch is taken if the internal node is now either overflowing
- ** or underfull and the leaf node will be underfull after the just cell
- ** copied to the internal node is deleted from it. This is a special
- ** case because the call to balance() to correct the internal node
- ** may change the tree structure and invalidate the contents of
- ** the leafCur.apPage[] and leafCur.aiIdx[] arrays, which will be
- ** used by the balance() required to correct the underfull leaf
- ** node.
- **
- ** The formula used in the expression above are based on facets of
- ** the SQLite file-format that do not change over time.
- */
- testcase( pPage->nFree==pBt->usableSize*2/3+1 );
- testcase( pLeafPage->nFree+2+szNext==pBt->usableSize*2/3+1 );
- leafCursorInvalid = 1;
- }
-
- if( rc==SQLITE_OK ){
- put4byte(findOverflowCell(pPage, idx), pgnoChild);
- VVA_ONLY( pCur->pagesShuffled = 0 );
- rc = balance(pCur, 0);
- }
-
- if( rc==SQLITE_OK && leafCursorInvalid ){
- /* The leaf-node is now underfull and so the tree needs to be
- ** rebalanced. However, the balance() operation on the internal
- ** node above may have modified the structure of the B-Tree and
- ** so the current contents of leafCur.apPage[] and leafCur.aiIdx[]
- ** may not be trusted.
- **
- ** It is not possible to copy the ancestry from pCur, as the same
- ** balance() call has invalidated the pCur->apPage[] and aiIdx[]
- ** arrays.
- **
- ** The call to saveCursorPosition() below internally saves the
- ** key that leafCur is currently pointing to. Currently, there
- ** are two copies of that key in the tree - one here on the leaf
- ** page and one on some internal node in the tree. The copy on
- ** the leaf node is always the next key in tree-order after the
- ** copy on the internal node. So, the call to sqlite3BtreeNext()
- ** calls restoreCursorPosition() to point the cursor to the copy
- ** stored on the internal node, then advances to the next entry,
- ** which happens to be the copy of the key on the internal node.
- ** Net effect: leafCur is pointing back to the duplicate cell
- ** that needs to be removed, and the leafCur.apPage[] and
- ** leafCur.aiIdx[] arrays are correct.
- */
- VVA_ONLY( Pgno leafPgno = pLeafPage->pgno );
- rc = saveCursorPosition(&leafCur);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeNext(&leafCur, &notUsed);
- }
- pLeafPage = leafCur.apPage[leafCur.iPage];
- assert( pLeafPage->pgno==leafPgno );
- assert( leafCur.aiIdx[leafCur.iPage]==0 );
+ rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0);
}
-
if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pLeafPage->pDbPage);
+ put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild);
+ rc = balance(pPage, 0);
}
if( rc==SQLITE_OK ){
- dropCell(pLeafPage, 0, szNext);
- VVA_ONLY( leafCur.pagesShuffled = 0 );
- rc = balance(&leafCur, 0);
- assert( leafCursorInvalid || !leafCur.pagesShuffled
- || !pCur->pagesShuffled );
+ dropCell(leafCur.pPage, leafCur.idx, szNext);
+ rc = balance(leafCur.pPage, 0);
}
}
sqlite3BtreeReleaseTempCursor(&leafCur);
}else{
TRACE(("DELETE: table=%d delete from leaf %d\n",
pCur->pgnoRoot, pPage->pgno));
- rc = dropCell(pPage, idx, cellSizePtr(pPage, pCell));
- if( rc==SQLITE_OK ){
- rc = balance(pCur, 0);
- }
+ dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell));
+ rc = balance(pPage, 0);
}
if( rc==SQLITE_OK ){
moveToRoot(pCur);
@@ -40129,8 +38622,8 @@ SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
static int clearDatabasePage(
BtShared *pBt, /* The BTree that contains the table */
Pgno pgno, /* Page number to clear */
- int freePageFlag, /* Deallocate page if true */
- int *pnChange
+ MemPage *pParent, /* Parent page. NULL for the root */
+ int freePageFlag /* Deallocate page if true */
){
MemPage *pPage = 0;
int rc;
@@ -40138,27 +38631,24 @@ static int clearDatabasePage(
int i;
assert( sqlite3_mutex_held(pBt->mutex) );
- if( pgno>pagerPagecount(pBt) ){
+ if( pgno>pagerPagecount(pBt->pPager) ){
return SQLITE_CORRUPT_BKPT;
}
- rc = getAndInitPage(pBt, pgno, &pPage);
+ rc = getAndInitPage(pBt, pgno, &pPage, pParent);
if( rc ) goto cleardatabasepage_out;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
+ rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1);
if( rc ) goto cleardatabasepage_out;
}
rc = clearCell(pPage, pCell);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), 1, pnChange);
+ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage->pParent, 1);
if( rc ) goto cleardatabasepage_out;
- }else if( pnChange ){
- assert( pPage->intKey );
- *pnChange += pPage->nCell;
}
if( freePageFlag ){
rc = freePage(pPage);
@@ -40179,12 +38669,8 @@ cleardatabasepage_out:
** This routine will fail with SQLITE_LOCKED if there are any open
** read cursors on the table. Open write cursors are moved to the
** root of the table.
-**
-** If pnChange is not NULL, then table iTable must be an intkey table. The
-** integer value pointed to by pnChange is incremented by the number of
-** entries in the table.
*/
-SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable){
int rc;
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
@@ -40196,7 +38682,7 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
}else if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){
/* nothing to do */
}else{
- rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
+ rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0);
}
sqlite3BtreeLeave(p);
return rc;
@@ -40222,7 +38708,7 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
** The last root page is recorded in meta[3] and the value of
** meta[3] is updated by this procedure.
*/
-static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
+static int btreeDropTable(Btree *p, int iTable, int *piMoved){
int rc;
MemPage *pPage = 0;
BtShared *pBt = p->pBt;
@@ -40244,7 +38730,7 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
rc = sqlite3BtreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
if( rc ) return rc;
- rc = sqlite3BtreeClearTable(p, iTable, 0);
+ rc = sqlite3BtreeClearTable(p, iTable);
if( rc ){
releasePage(pPage);
return rc;
@@ -40370,32 +38856,14 @@ SQLITE_PRIVATE int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
}
assert( idx>=0 && idx<=15 );
- if( pBt->pPage1 ){
- /* The b-tree is already holding a reference to page 1 of the database
- ** file. In this case the required meta-data value can be read directly
- ** from the page data of this reference. This is slightly faster than
- ** requesting a new reference from the pager layer.
- */
- pP1 = (unsigned char *)pBt->pPage1->aData;
- }else{
- /* The b-tree does not have a reference to page 1 of the database file.
- ** Obtain one from the pager layer.
- */
- rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage);
- if( rc ){
- sqlite3BtreeLeave(p);
- return rc;
- }
- pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage);
+ rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage);
+ if( rc ){
+ sqlite3BtreeLeave(p);
+ return rc;
}
+ pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage);
*pMeta = get4byte(&pP1[36 + idx*4]);
-
- /* If the b-tree is not holding a reference to page 1, then one was
- ** requested from the pager layer in the above block. Release it now.
- */
- if( !pBt->pPage1 ){
- sqlite3PagerUnref(pDbPage);
- }
+ sqlite3PagerUnref(pDbPage);
/* If autovacuumed is disabled in this build but we are trying to
** access an autovacuumed database, then make the database readonly.
@@ -40452,7 +38920,7 @@ SQLITE_PRIVATE int sqlite3BtreeFlags(BtCursor *pCur){
*/
MemPage *pPage;
restoreCursorPosition(pCur);
- pPage = pCur->apPage[pCur->iPage];
+ pPage = pCur->pPage;
assert( cursorHoldsMutex(pCur) );
assert( pPage->pBt==pCur->pBt );
return pPage ? pPage->aData[pPage->hdrOffset] : 0;
@@ -40505,9 +38973,9 @@ static void checkAppendMsg(
**
** Also check that the page number is in bounds.
*/
-static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){
+static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){
if( iPage==0 ) return 1;
- if( iPage>pCheck->nPage ){
+ if( iPage>pCheck->nPage || iPage<0 ){
checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage);
return 1;
}
@@ -40642,6 +39110,7 @@ static void checkList(
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
+ MemPage *pParent, /* Parent page */
char *zParentContext /* Parent context */
){
MemPage *pPage;
@@ -40652,7 +39121,7 @@ static int checkTreePage(
BtShared *pBt;
int usableSize;
char zContext[100];
- char *hit = 0;
+ char *hit;
sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
@@ -40667,7 +39136,7 @@ static int checkTreePage(
"unable to get the page. error code=%d", rc);
return 0;
}
- if( (rc = sqlite3BtreeInitPage(pPage))!=0 ){
+ if( (rc = sqlite3BtreeInitPage(pPage, pParent))!=0 ){
checkAppendMsg(pCheck, zContext,
"sqlite3BtreeInitPage() returns error code %d", rc);
releasePage(pPage);
@@ -40679,7 +39148,7 @@ static int checkTreePage(
depth = 0;
for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
u8 *pCell;
- u32 sz;
+ int sz;
CellInfo info;
/* Check payload overflow pages
@@ -40711,7 +39180,7 @@ static int checkTreePage(
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
}
#endif
- d2 = checkTreePage(pCheck, pgno, zContext);
+ d2 = checkTreePage(pCheck,pgno,pPage,zContext);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, zContext, "Child page depth differs");
}
@@ -40727,7 +39196,7 @@ static int checkTreePage(
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
}
#endif
- checkTreePage(pCheck, pgno, zContext);
+ checkTreePage(pCheck, pgno, pPage, zContext);
}
/* Check for complete coverage of the page
@@ -40738,23 +39207,14 @@ static int checkTreePage(
if( hit==0 ){
pCheck->mallocFailed = 1;
}else{
- u16 contentOffset = get2byte(&data[hdr+5]);
- if (contentOffset > usableSize) {
- checkAppendMsg(pCheck, 0,
- "Corruption detected in header on page %d",iPage,0);
- goto check_page_abort;
- }
- memset(hit+contentOffset, 0, usableSize-contentOffset);
- memset(hit, 1, contentOffset);
+ memset(hit, 0, usableSize );
+ memset(hit, 1, get2byte(&data[hdr+5]));
nCell = get2byte(&data[hdr+3]);
cellStart = hdr + 12 - 4*pPage->leaf;
for(i=0; i<nCell; i++){
int pc = get2byte(&data[cellStart+i*2]);
- u16 size = 1024;
+ u16 size = cellSizePtr(pPage, &data[pc]);
int j;
- if( pc<=usableSize ){
- size = cellSizePtr(pPage, &data[pc]);
- }
if( (pc+size-1)>=usableSize || pc<0 ){
checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage,0);
@@ -40789,8 +39249,7 @@ static int checkTreePage(
cnt, data[hdr+7], iPage);
}
}
-check_page_abort:
- if (hit) sqlite3PageFree(hit);
+ sqlite3PageFree(hit);
releasePage(pPage);
return depth+1;
@@ -40815,7 +39274,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
int mxErr, /* Stop reporting errors after this many */
int *pnErr /* Write number of errors seen to this variable */
){
- Pgno i;
+ int i;
int nRef;
IntegrityCk sCheck;
BtShared *pBt = p->pBt;
@@ -40831,7 +39290,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
}
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
- sCheck.nPage = pagerPagecount(sCheck.pBt);
+ sCheck.nPage = pagerPagecount(sCheck.pPager);
sCheck.mxErr = mxErr;
sCheck.nErr = 0;
sCheck.mallocFailed = 0;
@@ -40867,14 +39326,14 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
/* Check all the tables.
*/
- for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
+ for(i=0; i<nRoot && sCheck.mxErr; i++){
if( aRoot[i]==0 ) continue;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum && aRoot[i]>1 ){
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
}
#endif
- checkTreePage(&sCheck, aRoot[i], "List of tree roots: ");
+ checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: ");
}
/* Make sure every page in the file is referenced
@@ -40998,8 +39457,8 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
return SQLITE_BUSY;
}
- nToPage = pagerPagecount(pBtTo);
- nFromPage = pagerPagecount(pBtFrom);
+ nToPage = pagerPagecount(pBtTo->pPager);
+ nFromPage = pagerPagecount(pBtFrom->pPager);
iSkip = PENDING_BYTE_PAGE(pBtTo);
/* Variable nNewPage is the number of pages required to store the
@@ -41032,7 +39491,7 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
** page is still on the rollback journal, though. And that is the
** whole point of this block: to put pages on the rollback journal.
*/
- rc = sqlite3PagerDontWrite(pDbPage);
+ sqlite3PagerDontWrite(pDbPage);
}
sqlite3PagerUnref(pDbPage);
}
@@ -41076,15 +39535,11 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
}
memcpy(zTo, zFrom, nCopy);
- sqlite3PagerUnref(pFromPage);
+ sqlite3PagerUnref(pFromPage);
}
}
- if( pToPage ){
- MemPage *p = (MemPage *)sqlite3PagerGetExtra(pToPage);
- p->isInit = 0;
- sqlite3PagerUnref(pToPage);
- }
+ if( pToPage ) sqlite3PagerUnref(pToPage);
}
}
@@ -41145,7 +39600,7 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage);
if( rc==SQLITE_OK ){
char *zFrom = sqlite3PagerGetData(pFromPage);
- rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
+ rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
sqlite3PagerUnref(pFromPage);
}
}
@@ -41305,7 +39760,7 @@ SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void
if( checkReadLocks(pCsr->pBtree, pCsr->pgnoRoot, pCsr, 0) ){
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
}
- if( pCsr->eState==CURSOR_INVALID || !pCsr->apPage[pCsr->iPage]->intKey ){
+ if( pCsr->eState==CURSOR_INVALID || !pCsr->pPage->intKey ){
return SQLITE_ERROR;
}
@@ -41357,9 +39812,9 @@ SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){
*/
#define FIFOSIZE_FIRST (((128-sizeof(FifoPage))/8)+1)
#ifdef SQLITE_MALLOC_SOFT_LIMIT
-# define FIFOSIZE_MAX (int)(((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1)
+# define FIFOSIZE_MAX (((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1)
#else
-# define FIFOSIZE_MAX (int)(((262144-sizeof(FifoPage))/8)+1)
+# define FIFOSIZE_MAX (((262144-sizeof(FifoPage))/8)+1)
#endif
/*
@@ -41549,6 +40004,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
if( preserve && pMem->z==pMem->zMalloc ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
+ if( !pMem->z ){
+ pMem->flags = MEM_Null;
+ }
preserve = 0;
}else{
sqlite3DbFree(pMem->db, pMem->zMalloc);
@@ -41564,11 +40022,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
}
pMem->z = pMem->zMalloc;
- if( pMem->z==0 ){
- pMem->flags = MEM_Null;
- }else{
- pMem->flags &= ~(MEM_Ephem|MEM_Static);
- }
+ pMem->flags &= ~(MEM_Ephem|MEM_Static);
pMem->xDel = 0;
return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
}
@@ -41704,11 +40158,12 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
sqlite3_context ctx;
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
- memset(&ctx, 0, sizeof(ctx));
ctx.s.flags = MEM_Null;
ctx.s.db = pMem->db;
+ ctx.s.zMalloc = 0;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
+ ctx.isError = 0;
pFunc->xFinalize(&ctx);
assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
sqlite3DbFree(pMem->db, pMem->zMalloc);
@@ -42070,6 +40525,9 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
}
flags |= MEM_Term;
}
+ if( nByte>iLimit ){
+ return SQLITE_TOOBIG;
+ }
/* The following block sets the new values of Mem.z and Mem.xDel. It
** also sets a flag in local variable "flags" to indicate the memory
@@ -42080,9 +40538,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
- if( nByte>iLimit ){
- return SQLITE_TOOBIG;
- }
if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){
return SQLITE_NOMEM;
}
@@ -42097,9 +40552,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
pMem->xDel = xDel;
flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
}
- if( nByte>iLimit ){
- return SQLITE_TOOBIG;
- }
pMem->n = nByte;
pMem->flags = flags;
@@ -42205,21 +40657,22 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const C
** comparison function directly */
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
}else{
+ u8 origEnc = pMem1->enc;
const void *v1, *v2;
int n1, n2;
- Mem c1;
- Mem c2;
- memset(&c1, 0, sizeof(c1));
- memset(&c2, 0, sizeof(c2));
- sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
- sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
- v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
- n1 = v1==0 ? 0 : c1.n;
- v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
- n2 = v2==0 ? 0 : c2.n;
+ /* Convert the strings into the encoding that the comparison
+ ** function expects */
+ v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc);
+ n1 = v1==0 ? 0 : pMem1->n;
+ assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) );
+ v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc);
+ n2 = v2==0 ? 0 : pMem2->n;
+ assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) );
+ /* Do the comparison */
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
- sqlite3VdbeMemRelease(&c1);
- sqlite3VdbeMemRelease(&c2);
+ /* Convert the strings back into the database encoding */
+ sqlite3ValueText((sqlite3_value*)pMem1, origEnc);
+ sqlite3ValueText((sqlite3_value*)pMem2, origEnc);
return rc;
}
}
@@ -42452,7 +40905,6 @@ SQLITE_PRIVATE int sqlite3ValueFromExpr(
assert( pExpr->token.z[1]=='\'' );
assert( pExpr->token.z[pExpr->token.n-1]=='\'' );
pVal = sqlite3ValueNew(db);
- if( !pVal ) goto no_mem;
nVal = pExpr->token.n - 3;
zVal = (char*)pExpr->token.z + 2;
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
@@ -42610,23 +41062,21 @@ SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
#endif
/*
-** Resize the Vdbe.aOp array so that it is at least one op larger than
-** it was.
+** Resize the Vdbe.aOp array so that it contains at least N
+** elements.
**
-** If an out-of-memory error occurs while resizing the array, return
-** SQLITE_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain
-** unchanged (this is so that any opcodes already allocated can be
-** correctly deallocated along with the rest of the Vdbe).
+** If an out-of-memory error occurs while resizing the array,
+** Vdbe.aOp and Vdbe.nOpAlloc remain unchanged (this is so that
+** any opcodes already allocated can be correctly deallocated
+** along with the rest of the Vdbe).
*/
-static int growOpArray(Vdbe *p){
+static void resizeOpArray(Vdbe *p, int N){
VdbeOp *pNew;
- int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
- pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op));
+ pNew = sqlite3DbRealloc(p->db, p->aOp, N*sizeof(Op));
if( pNew ){
- p->nOpAlloc = nNew;
+ p->nOpAlloc = N;
p->aOp = pNew;
}
- return (pNew ? SQLITE_OK : SQLITE_NOMEM);
}
/*
@@ -42652,7 +41102,8 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
i = p->nOp;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->nOpAlloc<=i ){
- if( growOpArray(p) ){
+ resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op));
+ if( p->db->mallocFailed ){
return 0;
}
}
@@ -42778,8 +41229,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
int *aLabel = p->aLabel;
int doesStatementRollback = 0;
int hasStatementBegin = 0;
- p->readOnly = 1;
- p->usesStmtJournal = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode;
@@ -42796,11 +41245,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
}
}else if( opcode==OP_Statement ){
hasStatementBegin = 1;
- p->usesStmtJournal = 1;
}else if( opcode==OP_Destroy ){
doesStatementRollback = 1;
- }else if( opcode==OP_Transaction && pOp->p2!=0 ){
- p->readOnly = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE
}else if( opcode==OP_VUpdate || opcode==OP_VRename ){
doesStatementRollback = 1;
@@ -42829,7 +41275,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
** which can be expensive on some platforms.
*/
if( hasStatementBegin && !doesStatementRollback ){
- p->usesStmtJournal = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
if( pOp->opcode==OP_Statement ){
pOp->opcode = OP_Noop;
@@ -42853,7 +41298,11 @@ SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe *p){
SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
int addr;
assert( p->magic==VDBE_MAGIC_INIT );
- if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){
+ if( p->nOp + nOp > p->nOpAlloc ){
+ resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op));
+ assert( p->nOp+nOp<=p->nOpAlloc || p->db->mallocFailed );
+ }
+ if( p->db->mallocFailed ){
return 0;
}
addr = p->nOp;
@@ -43238,7 +41687,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){
int mask;
assert( i>=0 && i<p->db->nDb );
- assert( i<(int)sizeof(p->btreeMask)*8 );
+ assert( i<sizeof(p->btreeMask)*8 );
mask = 1<<i;
if( (p->btreeMask & mask)==0 ){
p->btreeMask |= mask;
@@ -43274,32 +41723,13 @@ SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
*/
static void releaseMemArray(Mem *p, int N){
if( p && N ){
- Mem *pEnd;
sqlite3 *db = p->db;
int malloc_failed = db->mallocFailed;
- for(pEnd=&p[N]; p<pEnd; p++){
- assert( (&p[1])==pEnd || p[0].db==p[1].db );
-
- /* This block is really an inlined version of sqlite3VdbeMemRelease()
- ** that takes advantage of the fact that the memory cell value is
- ** being set to NULL after releasing any dynamic resources.
- **
- ** The justification for duplicating code is that according to
- ** callgrind, this causes a certain test case to hit the CPU 4.7
- ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
- ** sqlite3MemRelease() were called from here. With -O2, this jumps
- ** to 6.6 percent. The test case is inserting 1000 rows into a table
- ** with no indexes using a single prepared INSERT statement, bind()
- ** and reset(). Inserts are grouped into a transaction.
- */
- if( p->flags&(MEM_Agg|MEM_Dyn) ){
- sqlite3VdbeMemRelease(p);
- }else if( p->zMalloc ){
- sqlite3DbFree(db, p->zMalloc);
- p->zMalloc = 0;
- }
-
+ while( N-->0 ){
+ assert( N<2 || p[0].db==p[1].db );
+ sqlite3VdbeMemRelease(p);
p->flags = MEM_Null;
+ p++;
}
db->mallocFailed = malloc_failed;
}
@@ -43433,7 +41863,6 @@ SQLITE_PRIVATE int sqlite3VdbeList(
pMem->z = pOp->zComment;
pMem->n = strlen(pMem->z);
pMem->enc = SQLITE_UTF8;
- pMem->type = SQLITE_TEXT;
}else
#endif
{
@@ -43524,13 +41953,17 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
*/
assert( p->nOp>0 );
- /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
+ /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. This
+ * is because the call to resizeOpArray() below may shrink the
+ * p->aOp[] array to save memory if called when in VDBE_MAGIC_RUN
+ * state.
+ */
p->magic = VDBE_MAGIC_RUN;
/* For each cursor required, also allocate a memory cell. Memory
** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
** the vdbe program. Instead they are used to allocate space for
- ** VdbeCursor/BtCursor structures. The blob of memory associated with
+ ** Cursor/BtCursor structures. The blob of memory associated with
** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
** stores the blob of memory associated with cursor 1, etc.
**
@@ -43544,16 +41977,17 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
if( p->aMem==0 ){
int nArg; /* Maximum number of args passed to a user function. */
resolveP2Values(p, &nArg);
+ /*resizeOpArray(p, p->nOp);*/
assert( nVar>=0 );
if( isExplain && nMem<10 ){
- nMem = 10;
+ p->nMem = nMem = 10;
}
p->aMem = sqlite3DbMallocZero(db,
nMem*sizeof(Mem) /* aMem */
+ nVar*sizeof(Mem) /* aVar */
+ nArg*sizeof(Mem*) /* apArg */
+ nVar*sizeof(char*) /* azVar */
- + nCursor*sizeof(VdbeCursor*)+1 /* apCsr */
+ + nCursor*sizeof(Cursor*) + 1 /* apCsr */
);
if( !db->mallocFailed ){
p->aMem--; /* aMem[] goes from 1..nMem */
@@ -43563,7 +41997,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
p->okVar = 0;
p->apArg = (Mem**)&p->aVar[nVar];
p->azVar = (char**)&p->apArg[nArg];
- p->apCsr = (VdbeCursor**)&p->azVar[nVar];
+ p->apCsr = (Cursor**)&p->azVar[nVar];
p->nCursor = nCursor;
for(n=0; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
@@ -43606,7 +42040,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
** Close a VDBE cursor and release all the resources that cursor
** happens to hold.
*/
-SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
+SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
if( pCx==0 ){
return;
}
@@ -43641,7 +42075,7 @@ static void closeAllCursorsExceptActiveVtabs(Vdbe *p){
int i;
if( p->apCsr==0 ) return;
for(i=0; i<p->nCursor; i++){
- VdbeCursor *pC = p->apCsr[i];
+ Cursor *pC = p->apCsr[i];
if( pC && (!p->inVtabMethod || !pC->pVtabCursor) ){
sqlite3VdbeFreeCursor(p, pC);
p->apCsr[i] = 0;
@@ -43709,29 +42143,28 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
**
** This call must be made after a call to sqlite3VdbeSetNumCols().
**
-** The final parameter, xDel, must be one of SQLITE_DYNAMIC, SQLITE_STATIC
-** or SQLITE_TRANSIENT. If it is SQLITE_DYNAMIC, then the buffer pointed
-** to by zName will be freed by sqlite3DbFree() when the vdbe is destroyed.
+** If N==P4_STATIC it means that zName is a pointer to a constant static
+** string and we can just copy the pointer. If it is P4_DYNAMIC, then
+** the string is freed using sqlite3DbFree(db, ) when the vdbe is finished with
+** it. Otherwise, N bytes of zName are copied.
*/
-SQLITE_PRIVATE int sqlite3VdbeSetColName(
- Vdbe *p, /* Vdbe being configured */
- int idx, /* Index of column zName applies to */
- int var, /* One of the COLNAME_* constants */
- const char *zName, /* Pointer to buffer containing name */
- void (*xDel)(void*) /* Memory management strategy for zName */
-){
+SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){
int rc;
Mem *pColName;
assert( idx<p->nResColumn );
assert( var<COLNAME_N );
- if( p->db->mallocFailed ){
- assert( !zName || xDel!=SQLITE_DYNAMIC );
- return SQLITE_NOMEM;
- }
+ if( p->db->mallocFailed ) return SQLITE_NOMEM;
assert( p->aColName!=0 );
pColName = &(p->aColName[idx+var*p->nResColumn]);
- rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel);
- assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
+ if( N==P4_DYNAMIC || N==P4_STATIC ){
+ rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC);
+ }else{
+ rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT);
+ }
+ if( rc==SQLITE_OK && N==P4_DYNAMIC ){
+ pColName->flags &= (~MEM_Static);
+ pColName->zMalloc = pColName->z;
+ }
return rc;
}
@@ -43962,17 +42395,14 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
static void checkActiveVdbeCnt(sqlite3 *db){
Vdbe *p;
int cnt = 0;
- int nWrite = 0;
p = db->pVdbe;
while( p ){
if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
cnt++;
- if( p->readOnly==0 ) nWrite++;
}
p = p->pNext;
}
assert( cnt==db->activeVdbeCnt );
- assert( nWrite==db->writeVdbeCnt );
}
#else
#define checkActiveVdbeCnt(x)
@@ -44060,15 +42490,42 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
if( isSpecialError ){
+ /* This loop does static analysis of the query to see which of the
+ ** following three categories it falls into:
+ **
+ ** Read-only
+ ** Query with statement journal
+ ** Query without statement journal
+ **
+ ** We could do something more elegant than this static analysis (i.e.
+ ** store the type of query as part of the compliation phase), but
+ ** handling malloc() or IO failure is a fairly obscure edge case so
+ ** this is probably easier. Todo: Might be an opportunity to reduce
+ ** code size a very small amount though...
+ */
+ int notReadOnly = 0;
+ int isStatement = 0;
+ assert(p->aOp || p->nOp==0);
+ for(i=0; i<p->nOp; i++){
+ switch( p->aOp[i].opcode ){
+ case OP_Transaction:
+ notReadOnly |= p->aOp[i].p2;
+ break;
+ case OP_Statement:
+ isStatement = 1;
+ break;
+ }
+ }
+
+
/* If the query was read-only, we need do no rollback at all. Otherwise,
** proceed with the special handling.
*/
- if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
- if( p->rc==SQLITE_IOERR_BLOCKED && p->usesStmtJournal ){
+ if( notReadOnly || mrc!=SQLITE_INTERRUPT ){
+ if( p->rc==SQLITE_IOERR_BLOCKED && isStatement ){
xFunc = sqlite3BtreeRollbackStmt;
p->rc = SQLITE_BUSY;
- }else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL)
- && p->usesStmtJournal ){
+ } else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && isStatement ){
xFunc = sqlite3BtreeRollbackStmt;
}else{
/* We are forced to roll back the active transaction. Before doing
@@ -44085,12 +42542,9 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
** we do either a commit or rollback of the current transaction.
**
** Note: This block also runs if one of the special errors handled
- ** above has occurred.
+ ** above has occured.
*/
- if( !sqlite3VtabInSync(db)
- && db->autoCommit
- && db->writeVdbeCnt==(p->readOnly==0)
- ){
+ if( db->autoCommit && db->activeVdbeCnt==1 ){
if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
/* The auto-commit flag is true, and the vdbe program was
** successful or hit an 'OR FAIL' constraint. This means a commit
@@ -44170,10 +42624,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
/* We have successfully halted and closed the VM. Record this fact. */
if( p->pc>=0 ){
db->activeVdbeCnt--;
- if( !p->readOnly ){
- db->writeVdbeCnt--;
- }
- assert( db->activeVdbeCnt>=db->writeVdbeCnt );
}
p->magic = VDBE_MAGIC_HALT;
checkActiveVdbeCnt(db);
@@ -44223,9 +42673,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
*/
if( p->pc>=0 ){
if( p->zErrMsg ){
- sqlite3BeginBenignMalloc();
sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT);
- sqlite3EndBenignMalloc();
db->errCode = p->rc;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
@@ -44357,15 +42805,16 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
** MoveTo now. Return an error code. If no MoveTo is pending, this
** routine does nothing and returns SQLITE_OK.
*/
-SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
+SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(Cursor *p){
if( p->deferredMoveto ){
int res, rc;
#ifdef SQLITE_TEST
extern int sqlite3_search_count;
#endif
assert( p->isTable );
- rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
+ rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
+ *p->pIncrKey = 0;
p->lastRowid = keyToInt(p->movetoTarget);
p->rowidIsValid = res==0;
if( res<0 ){
@@ -44460,7 +42909,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
if( flags&MEM_Real ){
return 7;
}
- assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
+ assert( flags&(MEM_Str|MEM_Blob) );
n = pMem->n;
if( flags & MEM_Zero ){
n += pMem->u.i;
@@ -44712,13 +43161,13 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
const void *pKey, /* The binary record */
- UnpackedRecord *pSpace,/* Space available to hold resulting object */
+ void *pSpace, /* Space available to hold resulting object */
int szSpace /* Size of pSpace[] in bytes */
){
const unsigned char *aKey = (const unsigned char *)pKey;
UnpackedRecord *p;
- int nByte, d;
- u32 idx;
+ int nByte;
+ int idx, d;
u16 u; /* Unsigned loop counter */
u32 szHdr;
Mem *pMem;
@@ -44728,13 +43177,14 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
if( nByte>szSpace ){
p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( p==0 ) return 0;
- p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
+ p->needFree = 1;
}else{
p = pSpace;
- p->flags = UNPACKED_NEED_DESTROY;
+ p->needFree = 0;
}
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nField + 1;
+ p->needDestroy = 1;
p->aMem = pMem = &((Mem*)p)[1];
idx = getVarint32(aKey, szHdr);
d = szHdr;
@@ -44742,7 +43192,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
while( idx<szHdr && u<p->nField ){
u32 serial_type;
- idx += getVarint32(&aKey[idx], serial_type);
+ idx += getVarint32( aKey+idx, serial_type);
if( d>=nKey && sqlite3VdbeSerialTypeLen(serial_type)>0 ) break;
pMem->enc = pKeyInfo->enc;
pMem->db = pKeyInfo->db;
@@ -44752,7 +43202,6 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
pMem++;
u++;
}
- assert( u<=pKeyInfo->nField + 1 );
p->nField = u;
return (void*)p;
}
@@ -44762,7 +43211,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
*/
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
if( p ){
- if( p->flags & UNPACKED_NEED_DESTROY ){
+ if( p->needDestroy ){
int i;
Mem *pMem;
for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
@@ -44771,7 +43220,7 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
}
}
}
- if( p->flags & UNPACKED_NEED_FREE ){
+ if( p->needFree ){
sqlite3DbFree(p->pKeyInfo->db, p);
}
}
@@ -44780,34 +43229,27 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
/*
** This function compares the two table rows or index records
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
-** or positive integer if key1 is less than, equal to or
-** greater than key2. The {nKey1, pKey1} key must be a blob
+** or positive integer if {nKey1, pKey1} is less than, equal to or
+** greater than pPKey2. The {nKey1, pKey1} key must be a blob
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
** key must be a parsed key such as obtained from
** sqlite3VdbeParseRecord.
**
** Key1 and Key2 do not have to contain the same number of fields.
-** The key with fewer fields is usually compares less than the
-** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
-** and the common prefixes are equal, then key1 is less than key2.
-** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
-** equal, then the keys are considered to be equal and
-** the parts beyond the common prefix are ignored.
-**
-** If the UNPACKED_IGNORE_ROWID flag is set, then the last byte of
-** the header of pKey1 is ignored. It is assumed that pKey1 is
-** an index key, and thus ends with a rowid value. The last byte
-** of the header will therefore be the serial type of the rowid:
-** one of 1, 2, 3, 4, 5, 6, 8, or 9 - the integer serial types.
-** The serial type of the final rowid will always be a single byte.
-** By ignoring this last byte of the header, we force the comparison
-** to ignore the rowid at the end of key1.
+** But if the lengths differ, Key2 must be the shorter of the two.
+**
+** Historical note: In earlier versions of this routine both Key1
+** and Key2 were blobs obtained from OP_MakeRecord. But we found
+** that in typical use the same Key2 would be submitted multiple times
+** in a row. So an optimization was added to parse the Key2 key
+** separately and submit the parsed version. In this way, we avoid
+** parsing the same Key2 multiple times in a row.
*/
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
- int nKey1, const void *pKey1, /* Left key */
- UnpackedRecord *pPKey2 /* Right key */
+ int nKey1, const void *pKey1,
+ UnpackedRecord *pPKey2
){
- int d1; /* Offset into aKey[] of next data element */
+ u32 d1; /* Offset into aKey[] of next data element */
u32 idx1; /* Offset into aKey[] of next header element */
u32 szHdr1; /* Number of bytes in header */
int i = 0;
@@ -44825,9 +43267,6 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
- if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){
- szHdr1--;
- }
nField = pKeyInfo->nField;
while( idx1<szHdr1 && i<pPKey2->nField ){
u32 serial_type1;
@@ -44851,21 +43290,17 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
}
if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1);
+ /* One of the keys ran out of fields, but all the fields up to that point
+ ** were equal. If the incrKey flag is true, then the second key is
+ ** treated as larger.
+ */
if( rc==0 ){
- /* rc==0 here means that one of the keys ran out of fields and
- ** all the fields up to that point were equal. If the UNPACKED_INCRKEY
- ** flag is set, then break the tie by treating key2 as larger.
- ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
- ** are considered to be equal. Otherwise, the longer key is the
- ** larger. As it happens, the pPKey2 will always be the longer
- ** if there is a difference.
- */
- if( pPKey2->flags & UNPACKED_INCRKEY ){
+ if( pKeyInfo->incrKey ){
rc = -1;
- }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
- /* Leave rc==0 */
- }else if( idx1<szHdr1 ){
- rc = 1;
+ }else if( !pKeyInfo->prefixIsEqual ){
+ if( d1<nKey1 ){
+ rc = 1;
+ }
}
}else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField
&& pKeyInfo->aSortOrder[i] ){
@@ -44874,7 +43309,26 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
return rc;
}
-
+
+/*
+** The argument is an index entry composed using the OP_MakeRecord opcode.
+** The last entry in this record should be an integer (specifically
+** an integer rowid). This routine returns the number of bytes in
+** that integer.
+*/
+SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8 *aKey, int nKey, int *pRowidLen){
+ u32 szHdr; /* Size of the header */
+ u32 typeRowid; /* Serial type of the rowid */
+
+ (void)getVarint32(aKey, szHdr);
+ if( szHdr>nKey ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ (void)getVarint32(&aKey[szHdr-1], typeRowid);
+ *pRowidLen = sqlite3VdbeSerialTypeLen(typeRowid);
+ return SQLITE_OK;
+}
+
/*
** pCur points at an index entry created using the OP_MakeRecord opcode.
@@ -44917,21 +43371,21 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
**
** pKey is either created without a rowid or is truncated so that it
** omits the rowid at the end. The rowid at the end of the index entry
-** is ignored as well. Hence, this routine only compares the prefixes
-** of the keys prior to the final rowid, not the entire key.
-**
-** pUnpacked may be an unpacked version of pKey,nKey. If pUnpacked is
-** supplied it is used in place of pKey,nKey.
+** is ignored as well.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
- VdbeCursor *pC, /* The cursor to compare against */
- UnpackedRecord *pUnpacked, /* Unpacked version of pKey and nKey */
+ Cursor *pC, /* The cursor to compare against */
+ UnpackedRecord *pUnpacked,
+ int nKey, const u8 *pKey, /* The key to compare */
int *res /* Write the comparison result here */
){
i64 nCellKey = 0;
int rc;
BtCursor *pCur = pC->pCursor;
+ int lenRowid;
Mem m;
+ UnpackedRecord *pRec;
+ char zSpace[200];
sqlite3BtreeKeySize(pCur, &nCellKey);
if( nCellKey<=0 ){
@@ -44941,12 +43395,24 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
m.db = 0;
m.flags = 0;
m.zMalloc = 0;
- rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
- if( rc ){
+ if( (rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m))
+ || (rc = sqlite3VdbeIdxRowidLen((u8*)m.z, m.n, &lenRowid))
+ ){
return rc;
}
- assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID );
- *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
+ if( !pUnpacked ){
+ pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
+ zSpace, sizeof(zSpace));
+ }else{
+ pRec = pUnpacked;
+ }
+ if( pRec==0 ){
+ return SQLITE_NOMEM;
+ }
+ *res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec);
+ if( !pUnpacked ){
+ sqlite3VdbeDeleteUnpackedRecord(pRec);
+ }
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}
@@ -45013,7 +43479,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
** $Id$
*/
-#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** The following structure contains pointers to the end points of a
** doubly-linked list of all compiled SQL statements that may be holding
@@ -45169,7 +43635,6 @@ int vdbeReprepare(Vdbe *p){
#endif
-#ifndef SQLITE_OMIT_DEPRECATED
/*
** Return TRUE (non-zero) of the statement supplied as an argument needs
** to be recompiled. A statement needs to be recompiled whenever the
@@ -45182,7 +43647,6 @@ SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p==0 || p->expired;
}
-#endif
/*
** The following routine destroys a virtual machine that is created by
@@ -45199,7 +43663,7 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = v->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
@@ -45241,7 +43705,7 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
Vdbe *p = (Vdbe*)pStmt;
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
@@ -45430,9 +43894,7 @@ static int sqlite3Step(Vdbe *p){
/* Assert that malloc() has not failed */
db = p->db;
- if( db->mallocFailed ){
- return SQLITE_NOMEM;
- }
+ assert( !db->mallocFailed );
if( p->pc<=0 && p->expired ){
if( p->rc==SQLITE_OK ){
@@ -45463,7 +43925,6 @@ static int sqlite3Step(Vdbe *p){
#endif
db->activeVdbeCnt++;
- if( p->readOnly==0 ) db->writeVdbeCnt++;
p->pc = 0;
stmtLruRemove(p);
}
@@ -45596,12 +44057,11 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
*/
SQLITE_PRIVATE void sqlite3InvalidFunction(
sqlite3_context *context, /* The function calling context */
- int NotUsed, /* Number of arguments to the function */
- sqlite3_value **NotUsed2 /* Value of each argument */
+ int argc, /* Number of arguments to the function */
+ sqlite3_value **argv /* Value of each argument */
){
const char *zName = context->pFunc->zName;
char *zErr;
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
zErr = sqlite3MPrintf(0,
"unable to use function %s in the requested context", zName);
sqlite3_result_error(context, zErr, -1);
@@ -45694,7 +44154,6 @@ failed:
}
}
-#ifndef SQLITE_OMIT_DEPRECATED
/*
** Return the number of times the Step function of a aggregate has been
** called.
@@ -45708,7 +44167,6 @@ SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){
assert( p && p->pFunc && p->pFunc->xStep );
return p->pMem->n;
}
-#endif
/*
** Return the number of columns in the result set for the statement pStmt.
@@ -45834,13 +44292,9 @@ SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
return val;
}
SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
- Mem *pOut = columnMem(pStmt, i);
- if( pOut->flags&MEM_Static ){
- pOut->flags &= ~MEM_Static;
- pOut->flags |= MEM_Ephem;
- }
+ sqlite3_value *pOut = columnMem(pStmt, i);
columnMallocFailure(pStmt);
- return (sqlite3_value *)pOut;
+ return pOut;
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
@@ -46010,24 +44464,17 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
** the same as binding a NULL value to the column. If the "i" parameter is
** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
**
-** A successful evaluation of this routine acquires the mutex on p.
-** the mutex is released if any kind of error occurs.
-**
** The error code stored in database p->db is overwritten with the return
** value in any case.
*/
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
- if( p==0 ) return SQLITE_MISUSE;
- sqlite3_mutex_enter(p->db->mutex);
- if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
- sqlite3Error(p->db, SQLITE_MISUSE, 0);
- sqlite3_mutex_leave(p->db->mutex);
+ if( p==0 || p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
+ if( p ) sqlite3Error(p->db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
}
if( i<1 || i>p->nVar ){
sqlite3Error(p->db, SQLITE_RANGE, 0);
- sqlite3_mutex_leave(p->db->mutex);
return SQLITE_RANGE;
}
i--;
@@ -46053,19 +44500,21 @@ static int bindText(
Mem *pVar;
int rc;
+ if( p==0 ){
+ return SQLITE_MISUSE;
+ }
+ sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- 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));
- }
- sqlite3Error(p->db, rc, 0);
- rc = sqlite3ApiExit(p->db, rc);
+ if( rc==SQLITE_OK && 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));
}
- sqlite3_mutex_leave(p->db->mutex);
+ sqlite3Error(p->db, rc, 0);
+ rc = sqlite3ApiExit(p->db, rc);
}
+ sqlite3_mutex_leave(p->db->mutex);
return rc;
}
@@ -46085,11 +44534,12 @@ SQLITE_API int sqlite3_bind_blob(
SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
+ sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
- sqlite3_mutex_leave(p->db->mutex);
}
+ sqlite3_mutex_leave(p->db->mutex);
return rc;
}
SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
@@ -46098,20 +44548,20 @@ SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
+ sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
- sqlite3_mutex_leave(p->db->mutex);
}
+ sqlite3_mutex_leave(p->db->mutex);
return rc;
}
SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
int rc;
Vdbe *p = (Vdbe*)pStmt;
+ sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
- if( rc==SQLITE_OK ){
- sqlite3_mutex_leave(p->db->mutex);
- }
+ sqlite3_mutex_leave(p->db->mutex);
return rc;
}
SQLITE_API int sqlite3_bind_text(
@@ -46137,25 +44587,27 @@ SQLITE_API int sqlite3_bind_text16(
SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
+ sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
rc = sqlite3VdbeMemCopy(&p->aVar[i-1], pValue);
if( rc==SQLITE_OK ){
rc = sqlite3VdbeChangeEncoding(&p->aVar[i-1], ENC(p->db));
}
- sqlite3_mutex_leave(p->db->mutex);
}
rc = sqlite3ApiExit(p->db, rc);
+ sqlite3_mutex_leave(p->db->mutex);
return rc;
}
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
+ sqlite3_mutex_enter(p->db->mutex);
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
- sqlite3_mutex_leave(p->db->mutex);
}
+ sqlite3_mutex_leave(p->db->mutex);
return rc;
}
@@ -46234,7 +44686,7 @@ SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zNa
** If the two statements contain a different number of bindings, then
** an SQLITE_ERROR is returned.
*/
-SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
+SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
int i, rc = SQLITE_OK;
@@ -46255,16 +44707,6 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt
return rc;
}
-#ifndef SQLITE_OMIT_DEPRECATED
-/*
-** Deprecated external interface. Internal/core SQLite code
-** should call sqlite3TransferBindings.
-*/
-SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
- return sqlite3TransferBindings(pFromStmt, pToStmt);
-}
-#endif
-
/*
** Return the sqlite3* database handle to which the prepared statement given
** in the argument belongs. This is the same database handle that was
@@ -46293,16 +44735,6 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
return pNext;
}
-/*
-** Return the value of a status counter for a prepared statement
-*/
-SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
- Vdbe *pVdbe = (Vdbe*)pStmt;
- int v = pVdbe->aCounter[op-1];
- if( resetFlag ) pVdbe->aCounter[op-1] = 0;
- return v;
-}
-
/************** End of vdbeapi.c *********************************************/
/************** Begin file vdbe.c ********************************************/
/*
@@ -46414,6 +44846,12 @@ static void updateMaxBlobsize(Mem *p){
#endif
/*
+** Release the memory associated with a register. This
+** leaves the Mem.flags field in an inconsistent state.
+*/
+#define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); }
+
+/*
** Convert the given register into a string if it isn't one
** already. Return non-zero if a malloc() fails.
*/
@@ -46474,32 +44912,32 @@ static void _storeTypeInfo(Mem *pMem){
** from the comments following the "case OP_xxxx:" statements in
** this file.
*/
-static const unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
+static unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
/*
** Return true if an opcode has any of the OPFLG_xxx properties
** specified by mask.
*/
SQLITE_PRIVATE int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){
- assert( opcode>0 && opcode<(int)sizeof(opcodeProperty) );
+ assert( opcode>0 && opcode<sizeof(opcodeProperty) );
return (opcodeProperty[opcode]&mask)!=0;
}
/*
-** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
+** Allocate cursor number iCur. Return a pointer to it. Return NULL
** if we run out of memory.
*/
-static VdbeCursor *allocateCursor(
- Vdbe *p, /* The virtual machine */
- int iCur, /* Index of the new VdbeCursor */
- Op *pOp, /* */
- int iDb, /* */
- int isBtreeCursor /* */
+static Cursor *allocateCursor(
+ Vdbe *p,
+ int iCur,
+ Op *pOp,
+ int iDb,
+ int isBtreeCursor
){
/* Find the memory cell that will be used to store the blob of memory
- ** required for this VdbeCursor structure. It is convenient to use a
+ ** required for this Cursor structure. It is convenient to use a
** vdbe memory cell to manage the memory allocation required for a
- ** VdbeCursor structure for the following reasons:
+ ** Cursor structure for the following reasons:
**
** * Sometimes cursor numbers are used for a couple of different
** purposes in a vdbe program. The different uses might require
@@ -46517,18 +44955,18 @@ static VdbeCursor *allocateCursor(
Mem *pMem = &p->aMem[p->nMem-iCur];
int nByte;
- VdbeCursor *pCx = 0;
+ Cursor *pCx = 0;
/* If the opcode of pOp is OP_SetNumColumns, then pOp->p2 contains
** the number of fields in the records contained in the table or
** index being opened. Use this to reserve space for the
- ** VdbeCursor.aType[] array.
+ ** Cursor.aType[] array.
*/
int nField = 0;
if( pOp->opcode==OP_SetNumColumns || pOp->opcode==OP_OpenEphemeral ){
nField = pOp->p2;
}
nByte =
- sizeof(VdbeCursor) +
+ sizeof(Cursor) +
(isBtreeCursor?sqlite3BtreeCursorSize():0) +
2*nField*sizeof(u32);
@@ -46538,16 +44976,15 @@ static VdbeCursor *allocateCursor(
p->apCsr[iCur] = 0;
}
if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){
- p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
+ p->apCsr[iCur] = pCx = (Cursor *)pMem->z;
memset(pMem->z, 0, nByte);
pCx->iDb = iDb;
pCx->nField = nField;
if( nField ){
- pCx->aType = (u32 *)&pMem->z[sizeof(VdbeCursor)];
+ pCx->aType = (u32 *)&pMem->z[sizeof(Cursor)];
}
if( isBtreeCursor ){
- pCx->pCursor = (BtCursor*)
- &pMem->z[sizeof(VdbeCursor)+2*nField*sizeof(u32)];
+ pCx->pCursor = (BtCursor *)&pMem->z[sizeof(Cursor)+2*nField*sizeof(u32)];
}
}
return pCx;
@@ -46945,7 +45382,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif
- UnpackedRecord aTempRec[16]; /* Space to hold a transient UnpackedRecord */
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
assert( db->magic==SQLITE_MAGIC_BUSY );
@@ -47717,7 +46153,7 @@ case OP_Function: {
MemSetTypeFlag(&ctx.s, MEM_Null);
ctx.isError = 0;
- if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ if( ctx.pFunc->needCollSeq ){
assert( pOp>p->aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
@@ -48353,20 +46789,23 @@ case OP_SetNumColumns: {
**
** The value extracted is stored in register P3.
**
+** If the KeyAsData opcode has previously executed on this cursor, then the
+** field might be extracted from the key rather than the data.
+**
** If the column contains fewer than P2 fields, then extract a NULL. Or,
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
*/
case OP_Column: {
- int payloadSize; /* Number of bytes in the record */
+ u32 payloadSize; /* Number of bytes in the record */
int p1 = pOp->p1; /* P1 value of the opcode */
int p2 = pOp->p2; /* column number to retrieve */
- VdbeCursor *pC = 0;/* The VDBE cursor */
+ Cursor *pC = 0; /* The VDBE cursor */
char *zRec; /* Pointer to complete record-data */
BtCursor *pCrsr; /* The BTree cursor */
u32 *aType; /* aType[i] holds the numeric type of the i-th column */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
- int nField; /* number of fields in the record */
+ u32 nField; /* number of fields in the record */
int len; /* The length of the serialized data for the column */
int i; /* Loop counter */
char *zData; /* Part of the record being decoded */
@@ -48391,7 +46830,7 @@ case OP_Column: {
** If the data is unavailable, zRec is set to NULL.
**
** We also compute the number of columns in the record. For cursors,
- ** the number of columns is stored in the VdbeCursor.nField element.
+ ** the number of columns is stored in the Cursor.nField element.
*/
pC = p->apCsr[p1];
assert( pC!=0 );
@@ -48414,7 +46853,7 @@ case OP_Column: {
sqlite3BtreeKeySize(pCrsr, &payloadSize64);
payloadSize = payloadSize64;
}else{
- sqlite3BtreeDataSize(pCrsr, (u32 *)&payloadSize);
+ sqlite3BtreeDataSize(pCrsr, &payloadSize);
}
nField = pC->nField;
}else{
@@ -48448,7 +46887,7 @@ case OP_Column: {
}else{
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
- int offset; /* Offset into the data */
+ u32 offset; /* Offset into the data */
int szHdrSz; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
@@ -48530,8 +46969,7 @@ case OP_Column: {
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
- if( zIdx>zEndHdr || offset>payloadSize
- || (zIdx==zEndHdr && offset!=payloadSize) ){
+ if( zIdx>zEndHdr || offset>payloadSize || (zIdx==zEndHdr && offset!=payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
@@ -48649,7 +47087,7 @@ case OP_MakeRecord: {
Mem *pRec; /* The new record */
u64 nData = 0; /* Number of bytes of data space */
int nHdr = 0; /* Number of bytes of header space */
- i64 nByte = 0; /* Data space required for this record */
+ u64 nByte = 0; /* Data space required for this record */
int nZero = 0; /* Number of zero bytes at the end of the record */
int nVarint; /* Number of bytes in a varint */
u32 serial_type; /* Type field */
@@ -48787,40 +47225,33 @@ case OP_Statement: {
** This instruction causes the VM to halt.
*/
case OP_AutoCommit: {
- int desiredAutoCommit = pOp->p1;
- int rollback = pOp->p2;
- int turnOnAC = desiredAutoCommit && !db->autoCommit;
+ u8 i = pOp->p1;
+ u8 rollback = pOp->p2;
- assert( desiredAutoCommit==1 || desiredAutoCommit==0 );
- assert( desiredAutoCommit==1 || rollback==0 );
+ assert( i==1 || i==0 );
+ assert( i==1 || rollback==0 );
assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
- if( turnOnAC && rollback && db->activeVdbeCnt>1 ){
- /* If this instruction implements a ROLLBACK and other VMs are
+ if( db->activeVdbeCnt>1 && i && !db->autoCommit ){
+ /* If this instruction implements a COMMIT or ROLLBACK, other VMs are
** still running, and a transaction is active, return an error indicating
** that the other VMs must complete first.
*/
- sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
- "SQL statements in progress");
- rc = SQLITE_BUSY;
- }else if( turnOnAC && !rollback && db->writeVdbeCnt>1 ){
- /* If this instruction implements a COMMIT and other VMs are writing
- ** return an error indicating that the other VMs must complete first.
- */
- sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
- "SQL statements in progress");
- rc = SQLITE_BUSY;
- }else if( desiredAutoCommit!=db->autoCommit ){
+ sqlite3SetString(&p->zErrMsg, db, "cannot %s transaction - "
+ "SQL statements in progress",
+ rollback ? "rollback" : "commit");
+ rc = SQLITE_ERROR;
+ }else if( i!=db->autoCommit ){
if( pOp->p2 ){
- assert( desiredAutoCommit==1 );
+ assert( i==1 );
sqlite3RollbackAll(db);
db->autoCommit = 1;
}else{
- db->autoCommit = desiredAutoCommit;
+ db->autoCommit = i;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pc = pc;
- db->autoCommit = 1-desiredAutoCommit;
+ db->autoCommit = 1-i;
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
@@ -48833,7 +47264,7 @@ case OP_AutoCommit: {
goto vdbe_return;
}else{
sqlite3SetString(&p->zErrMsg, db,
- (!desiredAutoCommit)?"cannot start a transaction within a transaction":(
+ (!i)?"cannot start a transaction within a transaction":(
(rollback)?"cannot rollback - no transaction is active":
"cannot commit - no transaction is active"));
@@ -49070,7 +47501,7 @@ case OP_OpenWrite: {
int iDb = pOp->p3;
int wrFlag;
Btree *pX;
- VdbeCursor *pCur;
+ Cursor *pCur;
Db *pDb;
assert( iDb>=0 && iDb<db->nDb );
@@ -49092,10 +47523,7 @@ case OP_OpenWrite: {
pIn2 = &p->aMem[p2];
sqlite3VdbeMemIntegerify(pIn2);
p2 = pIn2->u.i;
- if( p2<2 ) {
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
- }
+ assert( p2>=2 );
}
assert( i>=0 );
pCur = allocateCursor(p, i, &pOp[-1], iDb, 1);
@@ -49104,9 +47532,11 @@ case OP_OpenWrite: {
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor);
if( pOp->p4type==P4_KEYINFO ){
pCur->pKeyInfo = pOp->p4.pKeyInfo;
+ pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
pCur->pKeyInfo->enc = ENC(p->db);
}else{
pCur->pKeyInfo = 0;
+ pCur->pIncrKey = &pCur->bogusIncrKey;
}
switch( rc ){
case SQLITE_BUSY: {
@@ -49173,7 +47603,7 @@ case OP_OpenWrite: {
*/
case OP_OpenEphemeral: {
int i = pOp->p1;
- VdbeCursor *pCx;
+ Cursor *pCx;
static const int openFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
@@ -49206,11 +47636,13 @@ case OP_OpenEphemeral: {
(KeyInfo*)pOp->p4.z, pCx->pCursor);
pCx->pKeyInfo = pOp->p4.pKeyInfo;
pCx->pKeyInfo->enc = ENC(p->db);
+ pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
}else{
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
pCx->isTable = 1;
+ pCx->pIncrKey = &pCx->bogusIncrKey;
}
}
pCx->isIndex = !pCx->isTable;
@@ -49239,13 +47671,14 @@ case OP_OpenEphemeral: {
*/
case OP_OpenPseudo: {
int i = pOp->p1;
- VdbeCursor *pCx;
+ Cursor *pCx;
assert( i>=0 );
pCx = allocateCursor(p, i, &pOp[-1], -1, 0);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->pseudoTable = 1;
pCx->ephemPseudoTable = pOp->p2;
+ pCx->pIncrKey = &pCx->bogusIncrKey;
pCx->isTable = 1;
pCx->isIndex = 0;
break;
@@ -49328,7 +47761,7 @@ case OP_MoveLe: /* jump, in3 */
case OP_MoveGe: /* jump, in3 */
case OP_MoveGt: { /* jump, in3 */
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
@@ -49337,6 +47770,7 @@ case OP_MoveGt: { /* jump, in3 */
int res, oc;
oc = pOp->opcode;
pC->nullRow = 0;
+ *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
if( pC->isTable ){
i64 iKey = sqlite3VdbeIntValue(pIn3);
if( pOp->p2==0 ){
@@ -49346,7 +47780,7 @@ case OP_MoveGt: { /* jump, in3 */
pC->deferredMoveto = 1;
break;
}
- rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -49359,13 +47793,10 @@ case OP_MoveGt: { /* jump, in3 */
assert( nField>0 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = nField;
- if( oc==OP_MoveGt || oc==OP_MoveLe ){
- r.flags = UNPACKED_INCRKEY;
- }else{
- r.flags = 0;
- }
+ r.needFree = 0;
+ r.needDestroy = 0;
r.aMem = &p->aMem[pOp->p3];
- rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -49373,6 +47804,7 @@ case OP_MoveGt: { /* jump, in3 */
}
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
+ *pC->pIncrKey = 0;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
@@ -49430,7 +47862,7 @@ case OP_MoveGt: { /* jump, in3 */
** in the record in register P3, where N is the total number of values in
** the P3 record (the P3 record is a prefix of the P1 record).
**
-** See also: NotFound, IsUnique, NotExists
+** See also: NotFound, MoveTo, IsUnique, NotExists
*/
/* Opcode: NotFound P1 P2 P3 * *
**
@@ -49439,31 +47871,24 @@ case OP_MoveGt: { /* jump, in3 */
** to P2. If an entry does existing, fall through. The cursor is left
** pointing to the entry that matches.
**
-** See also: Found, NotExists, IsUnique
+** See also: Found, MoveTo, NotExists, IsUnique
*/
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
int i = pOp->p1;
int alreadyExists = 0;
- VdbeCursor *pC;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pC = p->apCsr[i])->pCursor!=0 ){
int res;
- UnpackedRecord *pIdxKey;
-
assert( pC->isTable==0 );
assert( pIn3->flags & MEM_Blob );
- pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
- aTempRec, sizeof(aTempRec));
- if( pIdxKey==0 ){
- goto no_mem;
- }
if( pOp->opcode==OP_Found ){
- pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+ pC->pKeyInfo->prefixIsEqual = 1;
}
- rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
+ pC->pKeyInfo->prefixIsEqual = 0;
if( rc!=SQLITE_OK ){
break;
}
@@ -49483,7 +47908,7 @@ case OP_Found: { /* jump, in3 */
**
** The P3 register contains an integer record number. Call this
** record number R. The P4 register contains an index key created
-** using MakeRecord. Call it K.
+** using MakeIdxRec. Call it K.
**
** P1 is an index. So it has no data and its key consists of a
** record generated by OP_MakeRecord where the last field is the
@@ -49501,7 +47926,7 @@ case OP_Found: { /* jump, in3 */
*/
case OP_IsUnique: { /* jump, in3 */
int i = pOp->p1;
- VdbeCursor *pCx;
+ Cursor *pCx;
BtCursor *pCrsr;
Mem *pK;
i64 R;
@@ -49519,39 +47944,45 @@ case OP_IsUnique: { /* jump, in3 */
pCrsr = pCx->pCursor;
if( pCrsr!=0 ){
int res;
- i64 v; /* The record number that matches K */
- UnpackedRecord *pIdxKey; /* Unpacked version of P4 */
+ i64 v; /* The record number on the P1 entry that matches K */
+ char *zKey; /* The value of K */
+ int nKey; /* Number of bytes in K */
+ int len; /* Number of bytes in K without the rowid at the end */
+ int szRowid; /* Size of the rowid column at the end of zKey */
/* Make sure K is a string and make zKey point to K
*/
assert( pK->flags & MEM_Blob );
- pIdxKey = sqlite3VdbeRecordUnpack(pCx->pKeyInfo, pK->n, pK->z,
- aTempRec, sizeof(aTempRec));
- if( pIdxKey==0 ){
- goto no_mem;
- }
- pIdxKey->flags |= UNPACKED_IGNORE_ROWID;
+ zKey = pK->z;
+ nKey = pK->n;
+
+ /* sqlite3VdbeIdxRowidLen() only returns other than SQLITE_OK when the
+ ** record passed as an argument corrupt. Since the record in this case
+ ** has just been created by an OP_MakeRecord instruction, and not loaded
+ ** from the database file, it is not possible for it to be corrupt.
+ ** Therefore, assert(rc==SQLITE_OK).
+ */
+ rc = sqlite3VdbeIdxRowidLen((u8*)zKey, nKey, &szRowid);
+ assert(rc==SQLITE_OK);
+ len = nKey-szRowid;
- /* Search for an entry in P1 where all but the last rowid match K
+ /* Search for an entry in P1 where all but the last four bytes match K.
** If there is no such entry, jump immediately to P2.
*/
assert( pCx->deferredMoveto==0 );
pCx->cacheStatus = CACHE_STALE;
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, pIdxKey, 0, 0, &res);
+ rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res);
if( rc!=SQLITE_OK ){
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
goto abort_due_to_error;
}
if( res<0 ){
rc = sqlite3BtreeNext(pCrsr, &res);
if( res ){
pc = pOp->p2 - 1;
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
break;
}
}
- rc = sqlite3VdbeIdxKeyCompare(pCx, pIdxKey, &res);
- sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res>0 ){
pc = pOp->p2 - 1;
@@ -49594,11 +48025,11 @@ case OP_IsUnique: { /* jump, in3 */
** NotFound assumes key is a blob constructed from MakeRecord and
** P1 is an index.
**
-** See also: Found, NotFound, IsUnique
+** See also: Found, MoveTo, NotFound, IsUnique
*/
case OP_NotExists: { /* jump, in3 */
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
BtCursor *pCrsr;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
@@ -49608,7 +48039,7 @@ case OP_NotExists: { /* jump, in3 */
assert( pIn3->flags & MEM_Int );
assert( p->apCsr[i]->isTable );
iKey = intToKey(pIn3->u.i);
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0,&res);
+ rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res);
pC->lastRowid = pIn3->u.i;
pC->rowidIsValid = res==0;
pC->nullRow = 0;
@@ -49667,7 +48098,7 @@ case OP_Sequence: { /* out2-prerelease */
case OP_NewRowid: { /* out2-prerelease */
int i = pOp->p1;
i64 v = 0;
- VdbeCursor *pC;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pC = p->apCsr[i])->pCursor==0 ){
@@ -49722,7 +48153,7 @@ case OP_NewRowid: { /* out2-prerelease */
** Others complain about 0x7ffffffffffffffffLL. The following macro seems
** to provide the constant while making all compilers happy.
*/
-# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
+# define MAX_ROWID ( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
#endif
if( !pC->useRandomRowid ){
@@ -49785,7 +48216,7 @@ case OP_NewRowid: { /* out2-prerelease */
}
if( v==0 ) continue;
x = intToKey(v);
- rx = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)x, 0, &res);
+ rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res);
cnt++;
}while( cnt<100 && rx==SQLITE_OK && res==0 );
db->priorNewRowid = v;
@@ -49835,7 +48266,7 @@ case OP_Insert: {
i64 iKey; /* The integer ROWID or key for the record to be inserted */
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
assert( pC!=0 );
@@ -49929,7 +48360,7 @@ case OP_Insert: {
case OP_Delete: {
int i = pOp->p1;
i64 iKey;
- VdbeCursor *pC;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
@@ -50000,7 +48431,7 @@ case OP_ResetCount: {
case OP_RowKey:
case OP_RowData: {
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
BtCursor *pCrsr;
u32 n;
@@ -50028,7 +48459,7 @@ case OP_RowData: {
n = n64;
}else{
sqlite3BtreeDataSize(pCrsr, &n);
- if( (int)n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
}
@@ -50054,7 +48485,7 @@ case OP_RowData: {
*/
case OP_Rowid: { /* out2-prerelease */
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
i64 v;
assert( i>=0 && i<p->nCursor );
@@ -50087,16 +48518,13 @@ case OP_Rowid: { /* out2-prerelease */
*/
case OP_NullRow: {
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
assert( pC!=0 );
pC->nullRow = 1;
pC->rowidIsValid = 0;
- if( pC->pCursor ){
- sqlite3BtreeClearCursor(pC->pCursor);
- }
break;
}
@@ -50110,7 +48538,7 @@ case OP_NullRow: {
*/
case OP_Last: { /* jump */
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
BtCursor *pCrsr;
int res;
@@ -50147,7 +48575,6 @@ case OP_Sort: { /* jump */
sqlite3_sort_count++;
sqlite3_search_count--;
#endif
- p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
/* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
@@ -50160,7 +48587,7 @@ case OP_Sort: { /* jump */
*/
case OP_Rewind: { /* jump */
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
BtCursor *pCrsr;
int res;
@@ -50205,7 +48632,7 @@ case OP_Rewind: { /* jump */
*/
case OP_Prev: /* jump */
case OP_Next: { /* jump */
- VdbeCursor *pC;
+ Cursor *pC;
BtCursor *pCrsr;
int res;
@@ -50225,7 +48652,6 @@ case OP_Next: { /* jump */
pC->cacheStatus = CACHE_STALE;
if( res==0 ){
pc = pOp->p2 - 1;
- if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
@@ -50248,7 +48674,7 @@ case OP_Next: { /* jump */
*/
case OP_IdxInsert: { /* in2 */
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
BtCursor *pCrsr;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
@@ -50267,7 +48693,7 @@ case OP_IdxInsert: { /* in2 */
break;
}
-/* Opcode: IdxDelete P1 P2 P3 * *
+/* Opcode: IdxDeleteM P1 P2 P3 * *
**
** The content of P3 registers starting at register P2 form
** an unpacked index key. This opcode removes that entry from the
@@ -50275,7 +48701,7 @@ case OP_IdxInsert: { /* in2 */
*/
case OP_IdxDelete: {
int i = pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
BtCursor *pCrsr;
assert( pOp->p3>0 );
assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem );
@@ -50286,9 +48712,10 @@ case OP_IdxDelete: {
UnpackedRecord r;
r.pKeyInfo = pC->pKeyInfo;
r.nField = pOp->p3;
- r.flags = 0;
+ r.needFree = 0;
+ r.needDestroy = 0;
r.aMem = &p->aMem[pOp->p2];
- rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
+ rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res);
if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
}
@@ -50309,7 +48736,7 @@ case OP_IdxDelete: {
case OP_IdxRowid: { /* out2-prerelease */
int i = pOp->p1;
BtCursor *pCrsr;
- VdbeCursor *pC;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
@@ -50359,7 +48786,7 @@ case OP_IdxRowid: { /* out2-prerelease */
case OP_IdxLT: /* jump, in3 */
case OP_IdxGE: { /* jump, in3 */
int i= pOp->p1;
- VdbeCursor *pC;
+ Cursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
@@ -50371,13 +48798,12 @@ case OP_IdxGE: { /* jump, in3 */
assert( pOp->p4type==P4_INT32 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = pOp->p4.i;
- if( pOp->p5 ){
- r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
- }else{
- r.flags = UNPACKED_IGNORE_ROWID;
- }
+ r.needFree = 0;
+ r.needDestroy = 0;
r.aMem = &p->aMem[pOp->p3];
- rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
+ *pC->pIncrKey = pOp->p5;
+ rc = sqlite3VdbeIdxKeyCompare(pC, &r, 0, 0, &res);
+ *pC->pIncrKey = 0;
if( pOp->opcode==OP_IdxLT ){
res = -res;
}else{
@@ -50444,7 +48870,7 @@ case OP_Destroy: { /* out2-prerelease */
break;
}
-/* Opcode: Clear P1 P2 P3
+/* Opcode: Clear P1 P2 *
**
** Delete all contents of the database table or index whose root page
** in the database file is given by P1. But, unlike Destroy, do not
@@ -50454,26 +48880,11 @@ case OP_Destroy: { /* out2-prerelease */
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
-** If the P3 value is non-zero, then the table refered to must be an
-** intkey table (an SQL table, not an index). In this case the row change
-** count is incremented by the number of rows in the table being cleared.
-** If P3 is greater than zero, then the value stored in register P3 is
-** also incremented by the number of rows in the table being cleared.
-**
** See also: Destroy
*/
case OP_Clear: {
- int nChange = 0;
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
- rc = sqlite3BtreeClearTable(
- db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0)
- );
- if( pOp->p3 ){
- p->nChange += nChange;
- if( pOp->p3>0 ){
- p->aMem[pOp->p3].u.i += nChange;
- }
- }
+ rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
break;
}
@@ -50555,10 +48966,9 @@ case OP_ParseSchema: {
(void)sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
- initData.rc = SQLITE_OK;
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
- if( rc==SQLITE_OK ) rc = initData.rc;
+ if( rc==SQLITE_ABORT ) rc = initData.rc;
sqlite3DbFree(db, zSql);
db->init.busy = 0;
(void)sqlite3SafetyOn(db);
@@ -50856,7 +49266,7 @@ case OP_AggStep: {
ctx.s.db = db;
ctx.isError = 0;
ctx.pColl = 0;
- if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ if( ctx.pFunc->needCollSeq ){
assert( pOp>p->aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
@@ -51042,7 +49452,7 @@ case OP_VDestroy: {
** table and stores that cursor in P1.
*/
case OP_VOpen: {
- VdbeCursor *pCur = 0;
+ Cursor *pCur = 0;
sqlite3_vtab_cursor *pVtabCursor = 0;
sqlite3_vtab *pVtab = pOp->p4.pVtab;
@@ -51101,7 +49511,7 @@ case OP_VFilter: { /* jump */
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
- VdbeCursor *pCur = p->apCsr[pOp->p1];
+ Cursor *pCur = p->apCsr[pOp->p1];
REGISTER_TRACE(pOp->p3, pQuery);
assert( pCur->pVtabCursor );
@@ -51158,7 +49568,7 @@ case OP_VRowid: { /* out2-prerelease */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
sqlite_int64 iRow;
- VdbeCursor *pCur = p->apCsr[pOp->p1];
+ Cursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
if( pCur->nullRow ){
@@ -51192,7 +49602,7 @@ case OP_VColumn: {
Mem *pDest;
sqlite3_context sContext;
- VdbeCursor *pCur = p->apCsr[pOp->p1];
+ Cursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &p->aMem[pOp->p3];
@@ -51250,7 +49660,7 @@ case OP_VNext: { /* jump */
const sqlite3_module *pModule;
int res = 0;
- VdbeCursor *pCur = p->apCsr[pOp->p1];
+ Cursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
if( pCur->nullRow ){
break;
@@ -51823,17 +50233,17 @@ static int blobReadWrite(
Vdbe *v;
sqlite3 *db = p->db;
+ /* Request is out of range. Return a transient error. */
+ if( (iOffset+n)>p->nByte ){
+ return SQLITE_ERROR;
+ }
sqlite3_mutex_enter(db->mutex);
- v = (Vdbe*)p->pStmt;
- if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){
- /* Request is out of range. Return a transient error. */
- rc = SQLITE_ERROR;
- sqlite3Error(db, SQLITE_ERROR, 0);
- } else if( v==0 ){
- /* If there is no statement handle, then the blob-handle has
- ** already been invalidated. Return SQLITE_ABORT in this case.
- */
+ /* If there is no statement handle, then the blob-handle has
+ ** already been invalidated. Return SQLITE_ABORT in this case.
+ */
+ v = (Vdbe*)p->pStmt;
+ if( v==0 ){
rc = SQLITE_ABORT;
}else{
/* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is
@@ -52125,1556 +50535,6 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
#endif
/************** End of journal.c *********************************************/
-/************** Begin file memjournal.c **************************************/
-/*
-** 2008 October 7
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file contains code use to implement an in-memory rollback journal.
-** The in-memory rollback journal is used to journal transactions for
-** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
-**
-** @(#) $Id$
-*/
-
-/* Forward references to internal structures */
-typedef struct MemJournal MemJournal;
-typedef struct FilePoint FilePoint;
-typedef struct FileChunk FileChunk;
-
-/* Space to hold the rollback journal is allocated in increments of
-** this many bytes.
-*/
-#define JOURNAL_CHUNKSIZE 1024
-
-/* Macro to find the minimum of two numeric values.
-*/
-#ifndef MIN
-# define MIN(x,y) ((x)<(y)?(x):(y))
-#endif
-
-/*
-** The rollback journal is composed of a linked list of these structures.
-*/
-struct FileChunk {
- FileChunk *pNext; /* Next chunk in the journal */
- u8 zChunk[JOURNAL_CHUNKSIZE]; /* Content of this chunk */
-};
-
-/*
-** An instance of this object serves as a cursor into the rollback journal.
-** The cursor can be either for reading or writing.
-*/
-struct FilePoint {
- sqlite3_int64 iOffset; /* Offset from the beginning of the file */
- FileChunk *pChunk; /* Specific chunk into which cursor points */
-};
-
-/*
-** This subclass is a subclass of sqlite3_file. Each open memory-journal
-** is an instance of this class.
-*/
-struct MemJournal {
- sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */
- FileChunk *pFirst; /* Head of in-memory chunk-list */
- FilePoint endpoint; /* Pointer to the end of the file */
- FilePoint readpoint; /* Pointer to the end of the last xRead() */
-};
-
-/*
-** Read data from the file.
-*/
-static int memjrnlRead(
- sqlite3_file *pJfd, /* The journal file from which to read */
- void *zBuf, /* Put the results here */
- int iAmt, /* Number of bytes to read */
- sqlite_int64 iOfst /* Begin reading at this offset */
-){
- MemJournal *p = (MemJournal *)pJfd;
- u8 *zOut = zBuf;
- int nRead = iAmt;
- int iChunkOffset;
- FileChunk *pChunk;
-
- assert( iOfst+iAmt<=p->endpoint.iOffset );
-
- if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
- sqlite3_int64 iOff = 0;
- for(pChunk=p->pFirst;
- pChunk && (iOff+JOURNAL_CHUNKSIZE)<=iOfst;
- pChunk=pChunk->pNext
- ){
- iOff += JOURNAL_CHUNKSIZE;
- }
- }else{
- pChunk = p->readpoint.pChunk;
- }
-
- iChunkOffset = (iOfst%JOURNAL_CHUNKSIZE);
- do {
- int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset;
- int nCopy = MIN(nRead, (JOURNAL_CHUNKSIZE - iChunkOffset));
- memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy);
- zOut += nCopy;
- nRead -= iSpace;
- iChunkOffset = 0;
- } while( nRead>=0 && (pChunk=pChunk->pNext) && nRead>0 );
- p->readpoint.iOffset = iOfst+iAmt;
- p->readpoint.pChunk = pChunk;
-
- return SQLITE_OK;
-}
-
-/*
-** Write data to the file.
-*/
-static int memjrnlWrite(
- sqlite3_file *pJfd, /* The journal file into which to write */
- const void *zBuf, /* Take data to be written from here */
- int iAmt, /* Number of bytes to write */
- sqlite_int64 iOfst /* Begin writing at this offset into the file */
-){
- MemJournal *p = (MemJournal *)pJfd;
- int nWrite = iAmt;
- u8 *zWrite = (u8 *)zBuf;
-
- /* An in-memory journal file should only ever be appended to. Random
- ** access writes are not required by sqlite.
- */
- assert(iOfst==p->endpoint.iOffset);
- UNUSED_PARAMETER(iOfst);
-
- while( nWrite>0 ){
- FileChunk *pChunk = p->endpoint.pChunk;
- int iChunkOffset = p->endpoint.iOffset%JOURNAL_CHUNKSIZE;
- int iSpace = MIN(nWrite, JOURNAL_CHUNKSIZE - iChunkOffset);
-
- if( iChunkOffset==0 ){
- /* New chunk is required to extend the file. */
- FileChunk *pNew = sqlite3_malloc(sizeof(FileChunk));
- if( !pNew ){
- return SQLITE_IOERR_NOMEM;
- }
- pNew->pNext = 0;
- if( pChunk ){
- assert( p->pFirst );
- pChunk->pNext = pNew;
- }else{
- assert( !p->pFirst );
- p->pFirst = pNew;
- }
- p->endpoint.pChunk = pNew;
- }
-
- memcpy(&p->endpoint.pChunk->zChunk[iChunkOffset], zWrite, iSpace);
- zWrite += iSpace;
- nWrite -= iSpace;
- p->endpoint.iOffset += iSpace;
- }
-
- return SQLITE_OK;
-}
-
-/*
-** Truncate the file.
-*/
-static int memjrnlTruncate(sqlite3_file *pJfd, sqlite_int64 size){
- MemJournal *p = (MemJournal *)pJfd;
- FileChunk *pChunk;
- assert(size==0);
- UNUSED_PARAMETER(size);
- pChunk = p->pFirst;
- while( pChunk ){
- FileChunk *pTmp = pChunk;
- pChunk = pChunk->pNext;
- sqlite3_free(pTmp);
- }
- sqlite3MemJournalOpen(pJfd);
- return SQLITE_OK;
-}
-
-/*
-** Close the file.
-*/
-static int memjrnlClose(sqlite3_file *pJfd){
- memjrnlTruncate(pJfd, 0);
- return SQLITE_OK;
-}
-
-
-/*
-** Sync the file.
-*/
-static int memjrnlSync(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return SQLITE_OK;
-}
-
-/*
-** Query the size of the file in bytes.
-*/
-static int memjrnlFileSize(sqlite3_file *pJfd, sqlite_int64 *pSize){
- MemJournal *p = (MemJournal *)pJfd;
- *pSize = (sqlite_int64) p->endpoint.iOffset;
- return SQLITE_OK;
-}
-
-/*
-** Table of methods for MemJournal sqlite3_file object.
-*/
-static struct sqlite3_io_methods MemJournalMethods = {
- 1, /* iVersion */
- memjrnlClose, /* xClose */
- memjrnlRead, /* xRead */
- memjrnlWrite, /* xWrite */
- memjrnlTruncate, /* xTruncate */
- memjrnlSync, /* xSync */
- memjrnlFileSize, /* xFileSize */
- 0, /* xLock */
- 0, /* xUnlock */
- 0, /* xCheckReservedLock */
- 0, /* xFileControl */
- 0, /* xSectorSize */
- 0 /* xDeviceCharacteristics */
-};
-
-/*
-** Open a journal file.
-*/
-SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *pJfd){
- MemJournal *p = (MemJournal *)pJfd;
- memset(p, 0, sqlite3MemJournalSize());
- p->pMethod = &MemJournalMethods;
-}
-
-/*
-** Return true if the file-handle passed as an argument is
-** an in-memory journal
-*/
-SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *pJfd){
- return pJfd->pMethods==&MemJournalMethods;
-}
-
-/*
-** Return the number of bytes required to store a MemJournal that uses vfs
-** pVfs to create the underlying on-disk files.
-*/
-SQLITE_PRIVATE int sqlite3MemJournalSize(){
- return sizeof(MemJournal);
-}
-
-/************** End of memjournal.c ******************************************/
-/************** Begin file walker.c ******************************************/
-/*
-** 2008 August 16
-**
-** 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 routines used for walking the parser tree for
-** an SQL statement.
-**
-** $Id$
-*/
-
-
-/*
-** Walk an expression tree. Invoke the callback once for each node
-** of the expression, while decending. (In other words, the callback
-** is invoked before visiting children.)
-**
-** The return value from the callback should be one of the WRC_*
-** constants to specify how to proceed with the walk.
-**
-** WRC_Continue Continue descending down the tree.
-**
-** WRC_Prune Do not descend into child nodes. But allow
-** the walk to continue with sibling nodes.
-**
-** WRC_Abort Do no more callbacks. Unwind the stack and
-** return the top-level walk call.
-**
-** The return value from this routine is WRC_Abort to abandon the tree walk
-** and WRC_Continue to continue.
-*/
-SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
- int rc;
- if( pExpr==0 ) return WRC_Continue;
- rc = pWalker->xExprCallback(pWalker, pExpr);
- if( rc==WRC_Continue ){
- if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
- if( sqlite3WalkExprList(pWalker, pExpr->pList) ) return WRC_Abort;
- if( sqlite3WalkSelect(pWalker, pExpr->pSelect) ){
- return WRC_Abort;
- }
- }
- return rc & WRC_Abort;
-}
-
-/*
-** Call sqlite3WalkExpr() for every expression in list p or until
-** an abort request is seen.
-*/
-SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
- int i, rc = WRC_Continue;
- struct ExprList_item *pItem;
- if( p ){
- for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
- if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
- }
- }
- return rc & WRC_Continue;
-}
-
-/*
-** Walk all expressions associated with SELECT statement p. Do
-** not invoke the SELECT callback on p, but do (of course) invoke
-** any expr callbacks and SELECT callbacks that come from subqueries.
-** Return WRC_Abort or WRC_Continue.
-*/
-SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
- if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
- if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
- if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
- if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
- return WRC_Continue;
-}
-
-/*
-** Walk the parse trees associated with all subqueries in the
-** FROM clause of SELECT statement p. Do not invoke the select
-** callback on p, but do invoke it on each FROM clause subquery
-** and on any subqueries further down in the tree. Return
-** WRC_Abort or WRC_Continue;
-*/
-SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
- SrcList *pSrc;
- int i;
- struct SrcList_item *pItem;
-
- pSrc = p->pSrc;
- if( pSrc ){
- for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
- return WRC_Abort;
- }
- }
- }
- return WRC_Continue;
-}
-
-/*
-** Call sqlite3WalkExpr() for every expression in Select statement p.
-** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
-** on the compound select chain, p->pPrior.
-**
-** Return WRC_Continue under normal conditions. Return WRC_Abort if
-** there is an abort request.
-**
-** If the Walker does not have an xSelectCallback() then this routine
-** is a no-op returning WRC_Continue.
-*/
-SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
- int rc;
- if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
- rc = WRC_Continue;
- while( p ){
- rc = pWalker->xSelectCallback(pWalker, p);
- if( rc ) break;
- if( sqlite3WalkSelectExpr(pWalker, p) ) return WRC_Abort;
- if( sqlite3WalkSelectFrom(pWalker, p) ) return WRC_Abort;
- p = p->pPrior;
- }
- return rc & WRC_Abort;
-}
-
-/************** End of walker.c **********************************************/
-/************** Begin file resolve.c *****************************************/
-/*
-** 2008 August 18
-**
-** 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 routines used for walking the parser tree and
-** resolve all identifiers by associating them with a particular
-** table and column.
-**
-** $Id$
-*/
-
-/*
-** Turn the pExpr expression into an alias for the iCol-th column of the
-** result set in pEList.
-**
-** If the result set column is a simple column reference, then this routine
-** makes an exact copy. But for any other kind of expression, this
-** routine make a copy of the result set column as the argument to the
-** TK_AS operator. The TK_AS operator causes the expression to be
-** evaluated just once and then reused for each alias.
-**
-** The reason for suppressing the TK_AS term when the expression is a simple
-** column reference is so that the column reference will be recognized as
-** usable by indices within the WHERE clause processing logic.
-**
-** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
-** that in a GROUP BY clause, the expression is evaluated twice. Hence:
-**
-** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
-**
-** Is equivalent to:
-**
-** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
-**
-** The result of random()%5 in the GROUP BY clause is probably different
-** from the result in the result-set. We might fix this someday. Or
-** then again, we might not...
-*/
-static void resolveAlias(
- Parse *pParse, /* Parsing context */
- ExprList *pEList, /* A result set */
- int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
- Expr *pExpr, /* Transform this into an alias to the result set */
- const char *zType /* "GROUP" or "ORDER" or "" */
-){
- Expr *pOrig; /* The iCol-th column of the result set */
- Expr *pDup; /* Copy of pOrig */
- sqlite3 *db; /* The database connection */
-
- assert( iCol>=0 && iCol<pEList->nExpr );
- pOrig = pEList->a[iCol].pExpr;
- assert( pOrig!=0 );
- assert( pOrig->flags & EP_Resolved );
- db = pParse->db;
- pDup = sqlite3ExprDup(db, pOrig);
- if( pDup==0 ) return;
- if( pDup->op!=TK_COLUMN && zType[0]!='G' ){
- pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
- if( pDup==0 ) return;
- if( pEList->a[iCol].iAlias==0 ){
- pEList->a[iCol].iAlias = ++pParse->nAlias;
- }
- pDup->iTable = pEList->a[iCol].iAlias;
- }
- if( pExpr->flags & EP_ExpCollate ){
- pDup->pColl = pExpr->pColl;
- pDup->flags |= EP_ExpCollate;
- }
- sqlite3ExprClear(db, pExpr);
- memcpy(pExpr, pDup, sizeof(*pExpr));
- sqlite3DbFree(db, pDup);
-}
-
-/*
-** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-** that name in the set of source tables in pSrcList and make the pExpr
-** expression node refer back to that source column. The following changes
-** are made to pExpr:
-**
-** pExpr->iDb Set the index in db->aDb[] of the database X
-** (even if X is implied).
-** pExpr->iTable Set to the cursor number for the table obtained
-** from pSrcList.
-** pExpr->pTab Points to the Table structure of X.Y (even if
-** X and/or Y are implied.)
-** pExpr->iColumn Set to the column number within the table.
-** pExpr->op Set to TK_COLUMN.
-** pExpr->pLeft Any expression this points to is deleted
-** pExpr->pRight Any expression this points to is deleted.
-**
-** The pDbToken is the name of the database (the "X"). This value may be
-** NULL meaning that name is of the form Y.Z or Z. Any available database
-** can be used. The pTableToken is the name of the table (the "Y"). This
-** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it
-** means that the form of the name is Z and that columns from any table
-** can be used.
-**
-** If the name cannot be resolved unambiguously, leave an error message
-** in pParse and return non-zero. Return zero on success.
-*/
-static int lookupName(
- Parse *pParse, /* The parsing context */
- Token *pDbToken, /* Name of the database containing table, or NULL */
- Token *pTableToken, /* Name of table containing column, or NULL */
- Token *pColumnToken, /* Name of the column. */
- NameContext *pNC, /* The name context used to resolve the name */
- Expr *pExpr /* Make this EXPR node point to the selected column */
-){
- char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
- char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
- char *zCol = 0; /* Name of the column. The "Z" */
- int i, j; /* Loop counters */
- int cnt = 0; /* Number of matching column names */
- int cntTab = 0; /* Number of matching table names */
- sqlite3 *db = pParse->db; /* The database connection */
- struct SrcList_item *pItem; /* Use for looping over pSrcList items */
- struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
- NameContext *pTopNC = pNC; /* First namecontext in the list */
- Schema *pSchema = 0; /* Schema of the expression */
-
- assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
-
- /* Dequote and zero-terminate the names */
- zDb = sqlite3NameFromToken(db, pDbToken);
- zTab = sqlite3NameFromToken(db, pTableToken);
- zCol = sqlite3NameFromToken(db, pColumnToken);
- if( db->mallocFailed ){
- goto lookupname_end;
- }
-
- /* Initialize the node to no-match */
- pExpr->iTable = -1;
- pExpr->pTab = 0;
-
- /* Start at the inner-most context and move outward until a match is found */
- while( pNC && cnt==0 ){
- ExprList *pEList;
- SrcList *pSrcList = pNC->pSrcList;
-
- if( pSrcList ){
- for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
- Table *pTab;
- int iDb;
- Column *pCol;
-
- pTab = pItem->pTab;
- assert( pTab!=0 && pTab->zName!=0 );
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( pTab->nCol>0 );
- if( zTab ){
- if( pItem->zAlias ){
- char *zTabName = pItem->zAlias;
- if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- }else{
- char *zTabName = pTab->zName;
- if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
- continue;
- }
- }
- }
- if( 0==(cntTab++) ){
- pExpr->iTable = pItem->iCursor;
- pExpr->pTab = pTab;
- pSchema = pTab->pSchema;
- pMatch = pItem;
- }
- for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- IdList *pUsing;
- cnt++;
- pExpr->iTable = pItem->iCursor;
- pExpr->pTab = pTab;
- pMatch = pItem;
- pSchema = pTab->pSchema;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- if( i<pSrcList->nSrc-1 ){
- if( pItem[1].jointype & JT_NATURAL ){
- /* If this match occurred in the left table of a natural join,
- ** then skip the right table to avoid a duplicate match */
- pItem++;
- i++;
- }else if( (pUsing = pItem[1].pUsing)!=0 ){
- /* If this match occurs on a column that is in the USING clause
- ** of a join, skip the search of the right table of the join
- ** to avoid a duplicate match there. */
- int k;
- for(k=0; k<pUsing->nId; k++){
- if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
- pItem++;
- i++;
- break;
- }
- }
- }
- }
- break;
- }
- }
- }
- }
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* If we have not already resolved the name, then maybe
- ** it is a new.* or old.* trigger argument reference
- */
- if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
- TriggerStack *pTriggerStack = pParse->trigStack;
- Table *pTab = 0;
- u32 *piColMask;
- if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->newIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- piColMask = &(pTriggerStack->newColMask);
- }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
- pExpr->iTable = pTriggerStack->oldIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- piColMask = &(pTriggerStack->oldColMask);
- }
-
- if( pTab ){
- int iCol;
- Column *pCol = pTab->aCol;
-
- pSchema = pTab->pSchema;
- cntTab++;
- for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- cnt++;
- pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
- pExpr->pTab = pTab;
- if( iCol>=0 ){
- testcase( iCol==31 );
- testcase( iCol==32 );
- *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
- }
- break;
- }
- }
- }
- }
-#endif /* !defined(SQLITE_OMIT_TRIGGER) */
-
- /*
- ** Perhaps the name is a reference to the ROWID
- */
- if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
- cnt = 1;
- pExpr->iColumn = -1;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- }
-
- /*
- ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
- ** might refer to an result-set alias. This happens, for example, when
- ** we are resolving names in the WHERE clause of the following command:
- **
- ** SELECT a+b AS x FROM table WHERE x<10;
- **
- ** In cases like this, replace pExpr with a copy of the expression that
- ** forms the result set entry ("a+b" in the example) and return immediately.
- ** Note that the expression in the result set should have already been
- ** resolved by the time the WHERE clause is resolved.
- */
- if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
- for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- Expr *pOrig;
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- assert( pExpr->pList==0 );
- assert( pExpr->pSelect==0 );
- pOrig = pEList->a[j].pExpr;
- if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
- sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
- sqlite3DbFree(db, zCol);
- return 2;
- }
- resolveAlias(pParse, pEList, j, pExpr, "");
- cnt = 1;
- pMatch = 0;
- assert( zTab==0 && zDb==0 );
- goto lookupname_end_2;
- }
- }
- }
-
- /* Advance to the next name context. The loop will exit when either
- ** we have a match (cnt>0) or when we run out of name contexts.
- */
- if( cnt==0 ){
- pNC = pNC->pNext;
- }
- }
-
- /*
- ** If X and Y are NULL (in other words if only the column name Z is
- ** supplied) and the value of Z is enclosed in double-quotes, then
- ** Z is a string literal if it doesn't match any column names. In that
- ** case, we need to return right away and not make any changes to
- ** pExpr.
- **
- ** Because no reference was made to outer contexts, the pNC->nRef
- ** fields are not changed in any context.
- */
- if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
- sqlite3DbFree(db, zCol);
- pExpr->op = TK_STRING;
- pExpr->pTab = 0;
- return 0;
- }
-
- /*
- ** cnt==0 means there was not match. cnt>1 means there were two or
- ** more matches. Either way, we have an error.
- */
- if( cnt!=1 ){
- const char *zErr;
- zErr = cnt==0 ? "no such column" : "ambiguous column name";
- if( zDb ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
- }else if( zTab ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
- }else{
- sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
- }
- pTopNC->nErr++;
- }
-
- /* If a column from a table in pSrcList is referenced, then record
- ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
- ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
- ** column number is greater than the number of bits in the bitmask
- ** then set the high-order bit of the bitmask.
- */
- if( pExpr->iColumn>=0 && pMatch!=0 ){
- int n = pExpr->iColumn;
- testcase( n==BMS-1 );
- if( n>=BMS ){
- n = BMS-1;
- }
- assert( pMatch->iCursor==pExpr->iTable );
- pMatch->colUsed |= ((Bitmask)1)<<n;
- }
-
-lookupname_end:
- /* Clean up and return
- */
- sqlite3DbFree(db, zDb);
- sqlite3DbFree(db, zTab);
- sqlite3ExprDelete(db, pExpr->pLeft);
- pExpr->pLeft = 0;
- sqlite3ExprDelete(db, pExpr->pRight);
- pExpr->pRight = 0;
- pExpr->op = TK_COLUMN;
-lookupname_end_2:
- sqlite3DbFree(db, zCol);
- if( cnt==1 ){
- assert( pNC!=0 );
- sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
- /* Increment the nRef value on all name contexts from TopNC up to
- ** the point where the name matched. */
- for(;;){
- assert( pTopNC!=0 );
- pTopNC->nRef++;
- if( pTopNC==pNC ) break;
- pTopNC = pTopNC->pNext;
- }
- return 0;
- } else {
- return 1;
- }
-}
-
-/*
-** This routine is callback for sqlite3WalkExpr().
-**
-** Resolve symbolic names into TK_COLUMN operators for the current
-** node in the expression tree. Return 0 to continue the search down
-** the tree or 2 to abort the tree walk.
-**
-** This routine also does error checking and name resolution for
-** function names. The operator for aggregate functions is changed
-** to TK_AGG_FUNCTION.
-*/
-static int resolveExprStep(Walker *pWalker, Expr *pExpr){
- NameContext *pNC;
- Parse *pParse;
-
- pNC = pWalker->u.pNC;
- assert( pNC!=0 );
- pParse = pNC->pParse;
- assert( pParse==pWalker->pParse );
-
- if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
- ExprSetProperty(pExpr, EP_Resolved);
-#ifndef NDEBUG
- if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
- SrcList *pSrcList = pNC->pSrcList;
- int i;
- for(i=0; i<pNC->pSrcList->nSrc; i++){
- assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
- }
- }
-#endif
- switch( pExpr->op ){
-
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
- /* The special operator TK_ROW means use the rowid for the first
- ** column in the FROM clause. This is used by the LIMIT and ORDER BY
- ** clause processing on UPDATE and DELETE statements.
- */
- case TK_ROW: {
- SrcList *pSrcList = pNC->pSrcList;
- struct SrcList_item *pItem;
- assert( pSrcList && pSrcList->nSrc==1 );
- pItem = pSrcList->a;
- pExpr->op = TK_COLUMN;
- pExpr->pTab = pItem->pTab;
- pExpr->iTable = pItem->iCursor;
- pExpr->iColumn = -1;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- break;
- }
-#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
-
- /* A lone identifier is the name of a column.
- */
- case TK_ID: {
- lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
- return WRC_Prune;
- }
-
- /* A table name and column name: ID.ID
- ** Or a database, table and column: ID.ID.ID
- */
- case TK_DOT: {
- Token *pColumn;
- Token *pTable;
- Token *pDb;
- Expr *pRight;
-
- /* if( pSrcList==0 ) break; */
- pRight = pExpr->pRight;
- if( pRight->op==TK_ID ){
- pDb = 0;
- pTable = &pExpr->pLeft->token;
- pColumn = &pRight->token;
- }else{
- assert( pRight->op==TK_DOT );
- pDb = &pExpr->pLeft->token;
- pTable = &pRight->pLeft->token;
- pColumn = &pRight->pRight->token;
- }
- lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
- return WRC_Prune;
- }
-
- /* Resolve function names
- */
- case TK_CONST_FUNC:
- case TK_FUNCTION: {
- ExprList *pList = pExpr->pList; /* The argument list */
- int n = pList ? pList->nExpr : 0; /* 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 */
- int auth; /* Authorization to use the function */
- int nId; /* Number of characters in function name */
- const char *zId; /* The function name. */
- FuncDef *pDef; /* Information about the function */
- int enc = ENC(pParse->db); /* The database encoding */
-
- zId = (char*)pExpr->token.z;
- nId = pExpr->token.n;
- pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
- if( pDef==0 ){
- pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
- if( pDef==0 ){
- no_such_func = 1;
- }else{
- wrong_num_args = 1;
- }
- }else{
- is_agg = pDef->xFunc==0;
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( pDef ){
- auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
- if( auth!=SQLITE_OK ){
- if( auth==SQLITE_DENY ){
- sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
- pDef->zName);
- pNC->nErr++;
- }
- pExpr->op = TK_NULL;
- return WRC_Prune;
- }
- }
-#endif
- if( is_agg && !pNC->allowAgg ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
- pNC->nErr++;
- is_agg = 0;
- }else if( no_such_func ){
- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- pNC->nErr++;
- }else if( wrong_num_args ){
- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- pNC->nErr++;
- }
- if( is_agg ){
- pExpr->op = TK_AGG_FUNCTION;
- pNC->hasAgg = 1;
- }
- if( is_agg ) pNC->allowAgg = 0;
- sqlite3WalkExprList(pWalker, pList);
- if( is_agg ) pNC->allowAgg = 1;
- /* FIX ME: Compute pExpr->affinity based on the expected return
- ** type of the function
- */
- return WRC_Prune;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_SELECT:
- case TK_EXISTS:
-#endif
- case TK_IN: {
- if( pExpr->pSelect ){
- int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
- if( pNC->isCheck ){
- sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
- }
-#endif
- sqlite3WalkSelect(pWalker, pExpr->pSelect);
- assert( pNC->nRef>=nRef );
- if( nRef!=pNC->nRef ){
- ExprSetProperty(pExpr, EP_VarSelect);
- }
- }
- break;
- }
-#ifndef SQLITE_OMIT_CHECK
- case TK_VARIABLE: {
- if( pNC->isCheck ){
- sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
- }
- break;
- }
-#endif
- }
- return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
-}
-
-/*
-** pEList is a list of expressions which are really the result set of the
-** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause.
-** This routine checks to see if pE is a simple identifier which corresponds
-** to the AS-name of one of the terms of the expression list. If it is,
-** this routine return an integer between 1 and N where N is the number of
-** elements in pEList, corresponding to the matching entry. If there is
-** no match, or if pE is not a simple identifier, then this routine
-** return 0.
-**
-** pEList has been resolved. pE has not.
-*/
-static int resolveAsName(
- Parse *pParse, /* Parsing context for error messages */
- ExprList *pEList, /* List of expressions to scan */
- Expr *pE /* Expression we are trying to match */
-){
- int i; /* Loop counter */
-
- if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
- sqlite3 *db = pParse->db;
- char *zCol = sqlite3NameFromToken(db, &pE->token);
- if( zCol==0 ){
- return -1;
- }
- for(i=0; i<pEList->nExpr; i++){
- char *zAs = pEList->a[i].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- sqlite3DbFree(db, zCol);
- return i+1;
- }
- }
- sqlite3DbFree(db, zCol);
- }
- return 0;
-}
-
-/*
-** pE is a pointer to an expression which is a single term in the
-** ORDER BY of a compound SELECT. The expression has not been
-** name resolved.
-**
-** At the point this routine is called, we already know that the
-** ORDER BY term is not an integer index into the result set. That
-** case is handled by the calling routine.
-**
-** Attempt to match pE against result set columns in the left-most
-** SELECT statement. Return the index i of the matching column,
-** as an indication to the caller that it should sort by the i-th column.
-** The left-most column is 1. In other words, the value returned is the
-** same integer value that would be used in the SQL statement to indicate
-** the column.
-**
-** If there is no match, return 0. Return -1 if an error occurs.
-*/
-static int resolveOrderByTermToExprList(
- Parse *pParse, /* Parsing context for error messages */
- Select *pSelect, /* The SELECT statement with the ORDER BY clause */
- Expr *pE /* The specific ORDER BY term */
-){
- int i; /* Loop counter */
- ExprList *pEList; /* The columns of the result set */
- NameContext nc; /* Name context for resolving pE */
-
- assert( sqlite3ExprIsInteger(pE, &i)==0 );
- pEList = pSelect->pEList;
-
- /* Resolve all names in the ORDER BY term expression
- */
- memset(&nc, 0, sizeof(nc));
- nc.pParse = pParse;
- nc.pSrcList = pSelect->pSrc;
- nc.pEList = pEList;
- nc.allowAgg = 1;
- nc.nErr = 0;
- if( sqlite3ResolveExprNames(&nc, pE) ){
- sqlite3ErrorClear(pParse);
- return 0;
- }
-
- /* Try to match the ORDER BY expression against an expression
- ** in the result set. Return an 1-based index of the matching
- ** result-set entry.
- */
- for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
- return i+1;
- }
- }
-
- /* If no match, return 0. */
- return 0;
-}
-
-/*
-** Generate an ORDER BY or GROUP BY term out-of-range error.
-*/
-static void resolveOutOfRangeError(
- Parse *pParse, /* The error context into which to write the error */
- const char *zType, /* "ORDER" or "GROUP" */
- int i, /* The index (1-based) of the term out of range */
- int mx /* Largest permissible value of i */
-){
- sqlite3ErrorMsg(pParse,
- "%r %s BY term out of range - should be "
- "between 1 and %d", i, zType, mx);
-}
-
-/*
-** Analyze the ORDER BY clause in a compound SELECT statement. Modify
-** each term of the ORDER BY clause is a constant integer between 1
-** and N where N is the number of columns in the compound SELECT.
-**
-** ORDER BY terms that are already an integer between 1 and N are
-** unmodified. ORDER BY terms that are integers outside the range of
-** 1 through N generate an error. ORDER BY terms that are expressions
-** are matched against result set expressions of compound SELECT
-** beginning with the left-most SELECT and working toward the right.
-** At the first match, the ORDER BY expression is transformed into
-** the integer column number.
-**
-** Return the number of errors seen.
-*/
-static int resolveCompoundOrderBy(
- Parse *pParse, /* Parsing context. Leave error messages here */
- Select *pSelect /* The SELECT statement containing the ORDER BY */
-){
- int i;
- ExprList *pOrderBy;
- ExprList *pEList;
- sqlite3 *db;
- int moreToDo = 1;
-
- pOrderBy = pSelect->pOrderBy;
- if( pOrderBy==0 ) return 0;
- db = pParse->db;
-#if SQLITE_MAX_COLUMN
- if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
- return 1;
- }
-#endif
- for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].done = 0;
- }
- pSelect->pNext = 0;
- while( pSelect->pPrior ){
- pSelect->pPrior->pNext = pSelect;
- pSelect = pSelect->pPrior;
- }
- while( pSelect && moreToDo ){
- struct ExprList_item *pItem;
- moreToDo = 0;
- pEList = pSelect->pEList;
- assert( pEList!=0 );
- for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
- int iCol = -1;
- Expr *pE, *pDup;
- if( pItem->done ) continue;
- pE = pItem->pExpr;
- if( sqlite3ExprIsInteger(pE, &iCol) ){
- if( iCol<0 || iCol>pEList->nExpr ){
- resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
- return 1;
- }
- }else{
- iCol = resolveAsName(pParse, pEList, pE);
- if( iCol==0 ){
- pDup = sqlite3ExprDup(db, pE);
- if( !db->mallocFailed ){
- assert(pDup);
- iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
- }
- sqlite3ExprDelete(db, pDup);
- }
- if( iCol<0 ){
- return 1;
- }
- }
- if( iCol>0 ){
- CollSeq *pColl = pE->pColl;
- int flags = pE->flags & EP_ExpCollate;
- sqlite3ExprDelete(db, pE);
- pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0, 0, 0);
- if( pE==0 ) return 1;
- pE->pColl = pColl;
- pE->flags |= EP_IntValue | flags;
- pE->iTable = iCol;
- pItem->iCol = iCol;
- pItem->done = 1;
- }else{
- moreToDo = 1;
- }
- }
- pSelect = pSelect->pNext;
- }
- for(i=0; i<pOrderBy->nExpr; i++){
- if( pOrderBy->a[i].done==0 ){
- sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
- "column in the result set", i+1);
- return 1;
- }
- }
- return 0;
-}
-
-/*
-** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
-** the SELECT statement pSelect. If any term is reference to a
-** result set expression (as determined by the ExprList.a.iCol field)
-** then convert that term into a copy of the corresponding result set
-** column.
-**
-** If any errors are detected, add an error message to pParse and
-** return non-zero. Return zero if no errors are seen.
-*/
-SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
- Parse *pParse, /* Parsing context. Leave error messages here */
- Select *pSelect, /* The SELECT statement containing the clause */
- ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */
- const char *zType /* "ORDER" or "GROUP" */
-){
- int i;
- sqlite3 *db = pParse->db;
- ExprList *pEList;
- struct ExprList_item *pItem;
-
- if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
-#if SQLITE_MAX_COLUMN
- if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
- return 1;
- }
-#endif
- pEList = pSelect->pEList;
- assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
- for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
- if( pItem->iCol ){
- if( pItem->iCol>pEList->nExpr ){
- resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
- return 1;
- }
- resolveAlias(pParse, pEList, pItem->iCol-1, pItem->pExpr, zType);
- }
- }
- return 0;
-}
-
-/*
-** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
-** The Name context of the SELECT statement is pNC. zType is either
-** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
-**
-** This routine resolves each term of the clause into an expression.
-** If the order-by term is an integer I between 1 and N (where N is the
-** number of columns in the result set of the SELECT) then the expression
-** in the resolution is a copy of the I-th result-set expression. If
-** the order-by term is an identify that corresponds to the AS-name of
-** a result-set expression, then the term resolves to a copy of the
-** result-set expression. Otherwise, the expression is resolved in
-** the usual way - using sqlite3ResolveExprNames().
-**
-** This routine returns the number of errors. If errors occur, then
-** an appropriate error message might be left in pParse. (OOM errors
-** excepted.)
-*/
-static int resolveOrderGroupBy(
- NameContext *pNC, /* The name context of the SELECT statement */
- Select *pSelect, /* The SELECT statement holding pOrderBy */
- ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */
- const char *zType /* Either "ORDER" or "GROUP", as appropriate */
-){
- int i; /* Loop counter */
- int iCol; /* Column number */
- struct ExprList_item *pItem; /* A term of the ORDER BY clause */
- Parse *pParse; /* Parsing context */
- int nResult; /* Number of terms in the result set */
-
- if( pOrderBy==0 ) return 0;
- nResult = pSelect->pEList->nExpr;
- pParse = pNC->pParse;
- for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
- Expr *pE = pItem->pExpr;
- iCol = resolveAsName(pParse, pSelect->pEList, pE);
- if( iCol<0 ){
- return 1; /* OOM error */
- }
- if( iCol>0 ){
- /* If an AS-name match is found, mark this ORDER BY column as being
- ** a copy of the iCol-th result-set column. The subsequent call to
- ** sqlite3ResolveOrderGroupBy() will convert the expression to a
- ** copy of the iCol-th result-set expression. */
- pItem->iCol = iCol;
- continue;
- }
- if( sqlite3ExprIsInteger(pE, &iCol) ){
- /* The ORDER BY term is an integer constant. Again, set the column
- ** number so that sqlite3ResolveOrderGroupBy() will convert the
- ** order-by term to a copy of the result-set expression */
- if( iCol<1 ){
- resolveOutOfRangeError(pParse, zType, i+1, nResult);
- return 1;
- }
- pItem->iCol = iCol;
- continue;
- }
-
- /* Otherwise, treat the ORDER BY term as an ordinary expression */
- pItem->iCol = 0;
- if( sqlite3ResolveExprNames(pNC, pE) ){
- return 1;
- }
- }
- return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
-}
-
-/*
-** Resolve names in the SELECT statement p and all of its descendents.
-*/
-static int resolveSelectStep(Walker *pWalker, Select *p){
- NameContext *pOuterNC; /* Context that contains this SELECT */
- NameContext sNC; /* Name context of this SELECT */
- int isCompound; /* True if p is a compound select */
- int nCompound; /* Number of compound terms processed so far */
- Parse *pParse; /* Parsing context */
- ExprList *pEList; /* Result set expression list */
- int i; /* Loop counter */
- ExprList *pGroupBy; /* The GROUP BY clause */
- Select *pLeftmost; /* Left-most of SELECT of a compound */
- sqlite3 *db; /* Database connection */
-
-
- assert( p!=0 );
- if( p->selFlags & SF_Resolved ){
- return WRC_Prune;
- }
- pOuterNC = pWalker->u.pNC;
- pParse = pWalker->pParse;
- db = pParse->db;
-
- /* Normally sqlite3SelectExpand() will be called first and will have
- ** already expanded this SELECT. However, if this is a subquery within
- ** an expression, sqlite3ResolveExprNames() will be called without a
- ** prior call to sqlite3SelectExpand(). When that happens, let
- ** sqlite3SelectPrep() do all of the processing for this SELECT.
- ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
- ** this routine in the correct order.
- */
- if( (p->selFlags & SF_Expanded)==0 ){
- sqlite3SelectPrep(pParse, p, pOuterNC);
- return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
- }
-
- isCompound = p->pPrior!=0;
- nCompound = 0;
- pLeftmost = p;
- while( p ){
- assert( (p->selFlags & SF_Expanded)!=0 );
- assert( (p->selFlags & SF_Resolved)==0 );
- p->selFlags |= SF_Resolved;
-
- /* Resolve the expressions in the LIMIT and OFFSET clauses. These
- ** are not allowed to refer to any names, so pass an empty NameContext.
- */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
- sqlite3ResolveExprNames(&sNC, p->pOffset) ){
- return WRC_Abort;
- }
-
- /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
- ** resolve the result-set expression list.
- */
- sNC.allowAgg = 1;
- sNC.pSrcList = p->pSrc;
- sNC.pNext = pOuterNC;
-
- /* Resolve names in the result set. */
- pEList = p->pEList;
- assert( pEList!=0 );
- for(i=0; i<pEList->nExpr; i++){
- Expr *pX = pEList->a[i].pExpr;
- if( sqlite3ResolveExprNames(&sNC, pX) ){
- return WRC_Abort;
- }
- }
-
- /* Recursively resolve names in all subqueries
- */
- for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
- if( pItem->pSelect ){
- const char *zSavedContext = pParse->zAuthContext;
- if( pItem->zName ) pParse->zAuthContext = pItem->zName;
- sqlite3ResolveSelectNames(pParse, pItem->pSelect, &sNC);
- pParse->zAuthContext = zSavedContext;
- if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
- }
- }
-
- /* If there are no aggregate functions in the result-set, and no GROUP BY
- ** expression, do not allow aggregates in any of the other expressions.
- */
- assert( (p->selFlags & SF_Aggregate)==0 );
- pGroupBy = p->pGroupBy;
- if( pGroupBy || sNC.hasAgg ){
- p->selFlags |= SF_Aggregate;
- }else{
- sNC.allowAgg = 0;
- }
-
- /* If a HAVING clause is present, then there must be a GROUP BY clause.
- */
- if( p->pHaving && !pGroupBy ){
- sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- return WRC_Abort;
- }
-
- /* Add the expression list to the name-context before parsing the
- ** other expressions in the SELECT statement. This is so that
- ** expressions in the WHERE clause (etc.) can refer to expressions by
- ** aliases in the result set.
- **
- ** Minor point: If this is the case, then the expression will be
- ** re-evaluated for each reference to it.
- */
- sNC.pEList = p->pEList;
- if( sqlite3ResolveExprNames(&sNC, p->pWhere) ||
- sqlite3ResolveExprNames(&sNC, p->pHaving)
- ){
- return WRC_Abort;
- }
-
- /* The ORDER BY and GROUP BY clauses may not refer to terms in
- ** outer queries
- */
- sNC.pNext = 0;
- sNC.allowAgg = 1;
-
- /* Process the ORDER BY clause for singleton SELECT statements.
- ** The ORDER BY clause for compounds SELECT statements is handled
- ** below, after all of the result-sets for all of the elements of
- ** the compound have been resolved.
- */
- if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
- return WRC_Abort;
- }
- if( db->mallocFailed ){
- return WRC_Abort;
- }
-
- /* Resolve the GROUP BY clause. At the same time, make sure
- ** the GROUP BY clause does not contain aggregate functions.
- */
- if( pGroupBy ){
- struct ExprList_item *pItem;
-
- if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
- return WRC_Abort;
- }
- for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
- if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
- sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
- "the GROUP BY clause");
- return WRC_Abort;
- }
- }
- }
-
- /* Advance to the next term of the compound
- */
- p = p->pPrior;
- nCompound++;
- }
-
- /* Resolve the ORDER BY on a compound SELECT after all terms of
- ** the compound have been resolved.
- */
- if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
- return WRC_Abort;
- }
-
- return WRC_Prune;
-}
-
-/*
-** This routine walks an expression tree and resolves references to
-** table columns and result-set columns. At the same time, do error
-** checking on function usage and set a flag if any aggregate functions
-** are seen.
-**
-** To resolve table columns references we look for nodes (or subtrees) of the
-** form X.Y.Z or Y.Z or just Z where
-**
-** X: The name of a database. Ex: "main" or "temp" or
-** the symbolic name assigned to an ATTACH-ed database.
-**
-** Y: The name of a table in a FROM clause. Or in a trigger
-** one of the special names "old" or "new".
-**
-** Z: The name of a column in table Y.
-**
-** The node at the root of the subtree is modified as follows:
-**
-** Expr.op Changed to TK_COLUMN
-** Expr.pTab Points to the Table object for X.Y
-** Expr.iColumn The column index in X.Y. -1 for the rowid.
-** Expr.iTable The VDBE cursor number for X.Y
-**
-**
-** To resolve result-set references, look for expression nodes of the
-** form Z (with no X and Y prefix) where the Z matches the right-hand
-** size of an AS clause in the result-set of a SELECT. The Z expression
-** is replaced by a copy of the left-hand side of the result-set expression.
-** Table-name and function resolution occurs on the substituted expression
-** tree. For example, in:
-**
-** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
-**
-** The "x" term of the order by is replaced by "a+b" to render:
-**
-** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
-**
-** Function calls are checked to make sure that the function is
-** defined and that the correct number of arguments are specified.
-** If the function is an aggregate function, then the pNC->hasAgg is
-** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
-** If an expression contains aggregate functions then the EP_Agg
-** property on the expression is set.
-**
-** An error message is left in pParse if anything is amiss. The number
-** if errors is returned.
-*/
-SQLITE_PRIVATE int sqlite3ResolveExprNames(
- NameContext *pNC, /* Namespace to resolve expressions in. */
- Expr *pExpr /* The expression to be analyzed. */
-){
- int savedHasAgg;
- Walker w;
-
- if( pExpr==0 ) return 0;
-#if SQLITE_MAX_EXPR_DEPTH>0
- {
- Parse *pParse = pNC->pParse;
- if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
- return 1;
- }
- pParse->nHeight += pExpr->nHeight;
- }
-#endif
- savedHasAgg = pNC->hasAgg;
- pNC->hasAgg = 0;
- w.xExprCallback = resolveExprStep;
- w.xSelectCallback = resolveSelectStep;
- w.pParse = pNC->pParse;
- w.u.pNC = pNC;
- sqlite3WalkExpr(&w, pExpr);
-#if SQLITE_MAX_EXPR_DEPTH>0
- pNC->pParse->nHeight -= pExpr->nHeight;
-#endif
- if( pNC->nErr>0 ){
- ExprSetProperty(pExpr, EP_Error);
- }
- if( pNC->hasAgg ){
- ExprSetProperty(pExpr, EP_Agg);
- }else if( savedHasAgg ){
- pNC->hasAgg = 1;
- }
- return ExprHasProperty(pExpr, EP_Error);
-}
-
-
-/*
-** Resolve all names in all expressions of a SELECT and in all
-** decendents of the SELECT, including compounds off of p->pPrior,
-** subqueries in expressions, and subqueries used as FROM clause
-** terms.
-**
-** See sqlite3ResolveExprNames() for a description of the kinds of
-** transformations that occur.
-**
-** All SELECT statements should have been expanded using
-** sqlite3SelectExpand() prior to invoking this routine.
-*/
-SQLITE_PRIVATE void sqlite3ResolveSelectNames(
- Parse *pParse, /* The parser context */
- Select *p, /* The SELECT statement being coded. */
- NameContext *pOuterNC /* Name context for parent SELECT statement */
-){
- Walker w;
-
- assert( p!=0 );
- w.xExprCallback = resolveExprStep;
- w.xSelectCallback = resolveSelectStep;
- w.pParse = pParse;
- w.u.pNC = pOuterNC;
- sqlite3WalkSelect(&w, p);
-}
-
-/************** End of resolve.c *********************************************/
/************** Begin file expr.c ********************************************/
/*
** 2001 September 15
@@ -53719,16 +50579,6 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
return sqlite3AffinityType(&pExpr->token);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
- && pExpr->pTab!=0
- ){
- /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
- ** a TK_COLUMN but was previously evaluated and cached in a register */
- int j = pExpr->iColumn;
- if( j<0 ) return SQLITE_AFF_INTEGER;
- assert( pExpr->pTab && j<pExpr->pTab->nCol );
- return pExpr->pTab->aCol[j].affinity;
- }
return pExpr->affinity;
}
@@ -53739,11 +50589,11 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
** flag. An explicit collating sequence will override implicit
** collating sequences.
*/
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){
+SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
char *zColl = 0; /* Dequoted name of collation sequence */
CollSeq *pColl;
sqlite3 *db = pParse->db;
- zColl = sqlite3NameFromToken(db, pCollName);
+ zColl = sqlite3NameFromToken(db, pName);
if( pExpr && zColl ){
pColl = sqlite3LocateCollSeq(pParse, zColl, -1);
if( pColl ){
@@ -53761,29 +50611,13 @@ SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pColl
*/
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
CollSeq *pColl = 0;
- Expr *p = pExpr;
- while( p ){
+ if( pExpr ){
int op;
- pColl = p->pColl;
- if( pColl ) break;
- op = p->op;
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) && p->pTab!=0 ){
- /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
- ** a TK_COLUMN but was previously evaluated and cached in a register */
- const char *zColl;
- int j = p->iColumn;
- if( j>=0 ){
- sqlite3 *db = pParse->db;
- zColl = p->pTab->aCol[j].zColl;
- pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);
- pExpr->pColl = pColl;
- }
- break;
- }
- if( op!=TK_CAST && op!=TK_UPLUS ){
- break;
+ pColl = pExpr->pColl;
+ op = pExpr->op;
+ if( (op==TK_CAST || op==TK_UPLUS) && !pColl ){
+ return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
}
- p = p->pLeft;
}
if( sqlite3CheckCollSeq(pParse, pColl) ){
pColl = 0;
@@ -53962,7 +50796,7 @@ static int codeCompare(
** expression depth allowed. If it is not, leave an error message in
** pParse.
*/
-SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
+static int checkExprHeight(Parse *pParse, int nHeight){
int rc = SQLITE_OK;
int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
if( nHeight>mxHeight ){
@@ -54034,7 +50868,7 @@ static void exprSetHeight(Expr *p){
*/
SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){
exprSetHeight(p);
- sqlite3ExprCheckHeight(pParse, p->nHeight);
+ checkExprHeight(pParse, p->nHeight);
}
/*
@@ -54047,6 +50881,7 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){
return nHeight;
}
#else
+ #define checkExprHeight(x,y)
#define exprSetHeight(y)
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
@@ -54114,7 +50949,7 @@ SQLITE_PRIVATE Expr *sqlite3PExpr(
){
Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken);
if( p ){
- sqlite3ExprCheckHeight(pParse, p->nHeight);
+ checkExprHeight(pParse, p->nHeight);
}
return p;
}
@@ -54279,24 +51114,16 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
}
/*
-** Clear an expression structure without deleting the structure itself.
-** Substructure is deleted.
+** Recursively delete an expression tree.
*/
-SQLITE_PRIVATE void sqlite3ExprClear(sqlite3 *db, Expr *p){
+SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
+ if( p==0 ) return;
if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z);
if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z);
sqlite3ExprDelete(db, p->pLeft);
sqlite3ExprDelete(db, p->pRight);
sqlite3ExprListDelete(db, p->pList);
sqlite3SelectDelete(db, p->pSelect);
-}
-
-/*
-** Recursively delete an expression tree.
-*/
-SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
- if( p==0 ) return;
- sqlite3ExprClear(db, p);
sqlite3DbFree(db, p);
}
@@ -54315,6 +51142,7 @@ SQLITE_PRIVATE void sqlite3DequoteExpr(sqlite3 *db, Expr *p){
sqlite3Dequote((char*)p->token.z);
}
+
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
@@ -54385,9 +51213,8 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){
|| db->mallocFailed );
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->sortOrder = pOldItem->sortOrder;
+ pItem->isAgg = pOldItem->isAgg;
pItem->done = 0;
- pItem->iCol = pOldItem->iCol;
- pItem->iAlias = pOldItem->iAlias;
}
return pNew;
}
@@ -54419,9 +51246,6 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p){
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
pNewItem->isPopulated = pOldItem->isPopulated;
- pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
- pNewItem->notIndexed = pOldItem->notIndexed;
- pNewItem->pIndex = pOldItem->pIndex;
pTab = pNewItem->pTab = pOldItem->pTab;
if( pTab ){
pTab->nRef++;
@@ -54458,6 +51282,7 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p){
if( p==0 ) return 0;
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
if( pNew==0 ) return 0;
+ pNew->isDistinct = p->isDistinct;
pNew->pEList = sqlite3ExprListDup(db, p->pEList);
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc);
pNew->pWhere = sqlite3ExprDup(db, p->pWhere);
@@ -54470,7 +51295,10 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p){
pNew->pOffset = sqlite3ExprDup(db, p->pOffset);
pNew->iLimit = 0;
pNew->iOffset = 0;
- pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
+ pNew->isResolved = p->isResolved;
+ pNew->isAgg = p->isAgg;
+ pNew->usesEphm = 0;
+ pNew->disallowOrderBy = 0;
pNew->pRightmost = 0;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
@@ -54519,7 +51347,6 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
memset(pItem, 0, sizeof(*pItem));
pItem->zName = sqlite3NameFromToken(db, pName);
pItem->pExpr = pExpr;
- pItem->iAlias = 0;
}
return pList;
@@ -54565,33 +51392,92 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
}
/*
-** These routines are Walker callbacks. Walker.u.pi is a pointer
-** to an integer. These routines are checking an expression to see
-** if it is a constant. Set *Walker.u.pi to 0 if the expression is
-** not constant.
+** Walk an expression tree. Call xFunc for each node visited. xFunc
+** is called on the node before xFunc is called on the nodes children.
**
-** These callback routines are used to implement the following:
+** The return value from xFunc determines whether the tree walk continues.
+** 0 means continue walking the tree. 1 means do not walk children
+** of the current node but continue with siblings. 2 means abandon
+** the tree walk completely.
**
-** sqlite3ExprIsConstant()
-** sqlite3ExprIsConstantNotJoin()
-** sqlite3ExprIsConstantOrFunction()
+** The return value from this routine is 1 to abandon the tree walk
+** and 0 to continue.
**
+** NOTICE: This routine does *not* descend into subqueries.
*/
-static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
+static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
+static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
+ int rc;
+ if( pExpr==0 ) return 0;
+ rc = (*xFunc)(pArg, pExpr);
+ if( rc==0 ){
+ if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1;
+ if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1;
+ if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1;
+ }
+ return rc>1;
+}
- /* If pWalker->u.i is 3 then any term of the expression that comes from
+/*
+** Call walkExprTree() for every expression in list p.
+*/
+static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){
+ int i;
+ struct ExprList_item *pItem;
+ if( !p ) return 0;
+ for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+ if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Call walkExprTree() for every expression in Select p, not including
+** expressions that are part of sub-selects in any FROM clause or the LIMIT
+** or OFFSET expressions..
+*/
+static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
+ walkExprList(p->pEList, xFunc, pArg);
+ walkExprTree(p->pWhere, xFunc, pArg);
+ walkExprList(p->pGroupBy, xFunc, pArg);
+ walkExprTree(p->pHaving, xFunc, pArg);
+ walkExprList(p->pOrderBy, xFunc, pArg);
+ if( p->pPrior ){
+ walkSelectExpr(p->pPrior, xFunc, pArg);
+ }
+ return 0;
+}
+
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
+**
+** pArg is really a pointer to an integer. If we can tell by looking
+** at pExpr that the expression that contains pExpr is not a constant
+** expression, then set *pArg to 0 and return 2 to abandon the tree walk.
+** If pExpr does does not disqualify the expression from being a constant
+** then do nothing.
+**
+** After walking the whole tree, if no nodes are found that disqualify
+** the expression as constant, then we assume the whole expression
+** is constant. See sqlite3ExprIsConstant() for additional information.
+*/
+static int exprNodeIsConstant(void *pArg, Expr *pExpr){
+ int *pN = (int*)pArg;
+
+ /* If *pArg is 3 then any term of the expression that comes from
** the ON or USING clauses of a join disqualifies the expression
** from being considered constant. */
- if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
- pWalker->u.i = 0;
- return WRC_Abort;
+ if( (*pN)==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
+ *pN = 0;
+ return 2;
}
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
- ** and pWalker->u.i==2 */
+ ** and *pArg==2 */
case TK_FUNCTION:
- if( pWalker->u.i==2 ) return 0;
+ if( (*pN)==2 ) return 0;
/* Fall through */
case TK_ID:
case TK_COLUMN:
@@ -54609,25 +51495,17 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_DOT );
testcase( pExpr->op==TK_AGG_FUNCTION );
testcase( pExpr->op==TK_AGG_COLUMN );
- pWalker->u.i = 0;
- return WRC_Abort;
+ *pN = 0;
+ return 2;
+ case TK_IN:
+ if( pExpr->pSelect ){
+ *pN = 0;
+ return 2;
+ }
default:
- return WRC_Continue;
+ return 0;
}
}
-static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
- UNUSED_PARAMETER(NotUsed);
- pWalker->u.i = 0;
- return WRC_Abort;
-}
-static int exprIsConst(Expr *p, int initFlag){
- Walker w;
- w.u.i = initFlag;
- w.xExprCallback = exprNodeIsConstant;
- w.xSelectCallback = selectNodeIsConstant;
- sqlite3WalkExpr(&w, p);
- return w.u.i;
-}
/*
** Walk an expression tree. Return 1 if the expression is constant
@@ -54638,7 +51516,9 @@ static int exprIsConst(Expr *p, int initFlag){
** a constant.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
- return exprIsConst(p, 1);
+ int isConst = 1;
+ walkExprTree(p, exprNodeIsConstant, &isConst);
+ return isConst;
}
/*
@@ -54648,7 +51528,9 @@ SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
** an ON or USING clause.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
- return exprIsConst(p, 3);
+ int isConst = 3;
+ walkExprTree(p, exprNodeIsConstant, &isConst);
+ return isConst!=0;
}
/*
@@ -54661,7 +51543,9 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
** a constant.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p){
- return exprIsConst(p, 2);
+ int isConst = 2;
+ walkExprTree(p, exprNodeIsConstant, &isConst);
+ return isConst!=0;
}
/*
@@ -54713,6 +51597,554 @@ SQLITE_PRIVATE int sqlite3IsRowid(const char *z){
return 0;
}
+/*
+** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
+** that name in the set of source tables in pSrcList and make the pExpr
+** expression node refer back to that source column. The following changes
+** are made to pExpr:
+**
+** pExpr->iDb Set the index in db->aDb[] of the database holding
+** the table.
+** pExpr->iTable Set to the cursor number for the table obtained
+** from pSrcList.
+** pExpr->iColumn Set to the column number within the table.
+** pExpr->op Set to TK_COLUMN.
+** pExpr->pLeft Any expression this points to is deleted
+** pExpr->pRight Any expression this points to is deleted.
+**
+** The pDbToken is the name of the database (the "X"). This value may be
+** NULL meaning that name is of the form Y.Z or Z. Any available database
+** can be used. The pTableToken is the name of the table (the "Y"). This
+** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it
+** means that the form of the name is Z and that columns from any table
+** can be used.
+**
+** If the name cannot be resolved unambiguously, leave an error message
+** in pParse and return non-zero. Return zero on success.
+*/
+static int lookupName(
+ Parse *pParse, /* The parsing context */
+ Token *pDbToken, /* Name of the database containing table, or NULL */
+ Token *pTableToken, /* Name of table containing column, or NULL */
+ Token *pColumnToken, /* Name of the column. */
+ NameContext *pNC, /* The name context used to resolve the name */
+ Expr *pExpr /* Make this EXPR node point to the selected column */
+){
+ char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
+ char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
+ char *zCol = 0; /* Name of the column. The "Z" */
+ int i, j; /* Loop counters */
+ int cnt = 0; /* Number of matching column names */
+ int cntTab = 0; /* Number of matching table names */
+ sqlite3 *db = pParse->db; /* The database */
+ struct SrcList_item *pItem; /* Use for looping over pSrcList items */
+ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
+ NameContext *pTopNC = pNC; /* First namecontext in the list */
+ Schema *pSchema = 0; /* Schema of the expression */
+
+ assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
+ zDb = sqlite3NameFromToken(db, pDbToken);
+ zTab = sqlite3NameFromToken(db, pTableToken);
+ zCol = sqlite3NameFromToken(db, pColumnToken);
+ if( db->mallocFailed ){
+ goto lookupname_end;
+ }
+
+ pExpr->iTable = -1;
+ while( pNC && cnt==0 ){
+ ExprList *pEList;
+ SrcList *pSrcList = pNC->pSrcList;
+
+ if( pSrcList ){
+ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
+ Table *pTab;
+ int iDb;
+ Column *pCol;
+
+ pTab = pItem->pTab;
+ assert( pTab!=0 );
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( pTab->nCol>0 );
+ if( zTab ){
+ if( pItem->zAlias ){
+ char *zTabName = pItem->zAlias;
+ if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ }else{
+ char *zTabName = pTab->zName;
+ if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
+ continue;
+ }
+ }
+ }
+ if( 0==(cntTab++) ){
+ pExpr->iTable = pItem->iCursor;
+ pSchema = pTab->pSchema;
+ pMatch = pItem;
+ }
+ for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ const char *zColl = pTab->aCol[j].zColl;
+ IdList *pUsing;
+ cnt++;
+ pExpr->iTable = pItem->iCursor;
+ pMatch = pItem;
+ pSchema = pTab->pSchema;
+ /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+ pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+ pExpr->affinity = pTab->aCol[j].affinity;
+ if( (pExpr->flags & EP_ExpCollate)==0 ){
+ pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
+ }
+ if( i<pSrcList->nSrc-1 ){
+ if( pItem[1].jointype & JT_NATURAL ){
+ /* If this match occurred in the left table of a natural join,
+ ** then skip the right table to avoid a duplicate match */
+ pItem++;
+ i++;
+ }else if( (pUsing = pItem[1].pUsing)!=0 ){
+ /* If this match occurs on a column that is in the USING clause
+ ** of a join, skip the search of the right table of the join
+ ** to avoid a duplicate match there. */
+ int k;
+ for(k=0; k<pUsing->nId; k++){
+ if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
+ pItem++;
+ i++;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* If we have not already resolved the name, then maybe
+ ** it is a new.* or old.* trigger argument reference
+ */
+ if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
+ TriggerStack *pTriggerStack = pParse->trigStack;
+ Table *pTab = 0;
+ u32 *piColMask;
+ if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
+ pExpr->iTable = pTriggerStack->newIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
+ piColMask = &(pTriggerStack->newColMask);
+ }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
+ pExpr->iTable = pTriggerStack->oldIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
+ piColMask = &(pTriggerStack->oldColMask);
+ }
+
+ if( pTab ){
+ int iCol;
+ Column *pCol = pTab->aCol;
+
+ pSchema = pTab->pSchema;
+ cntTab++;
+ for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ const char *zColl = pTab->aCol[iCol].zColl;
+ cnt++;
+ pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
+ pExpr->affinity = pTab->aCol[iCol].affinity;
+ if( (pExpr->flags & EP_ExpCollate)==0 ){
+ pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
+ }
+ pExpr->pTab = pTab;
+ if( iCol>=0 ){
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
+ }
+ break;
+ }
+ }
+ }
+ }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+
+ /*
+ ** Perhaps the name is a reference to the ROWID
+ */
+ if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+ cnt = 1;
+ pExpr->iColumn = -1;
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ }
+
+ /*
+ ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
+ ** might refer to an result-set alias. This happens, for example, when
+ ** we are resolving names in the WHERE clause of the following command:
+ **
+ ** SELECT a+b AS x FROM table WHERE x<10;
+ **
+ ** In cases like this, replace pExpr with a copy of the expression that
+ ** forms the result set entry ("a+b" in the example) and return immediately.
+ ** Note that the expression in the result set should have already been
+ ** resolved by the time the WHERE clause is resolved.
+ */
+ if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
+ for(j=0; j<pEList->nExpr; j++){
+ char *zAs = pEList->a[j].zName;
+ if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ Expr *pDup, *pOrig;
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ assert( pExpr->pList==0 );
+ assert( pExpr->pSelect==0 );
+ pOrig = pEList->a[j].pExpr;
+ if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
+ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
+ sqlite3DbFree(db, zCol);
+ return 2;
+ }
+ pDup = sqlite3ExprDup(db, pOrig);
+ if( pExpr->flags & EP_ExpCollate ){
+ pDup->pColl = pExpr->pColl;
+ pDup->flags |= EP_ExpCollate;
+ }
+ if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
+ if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
+ memcpy(pExpr, pDup, sizeof(*pExpr));
+ sqlite3DbFree(db, pDup);
+ cnt = 1;
+ pMatch = 0;
+ assert( zTab==0 && zDb==0 );
+ goto lookupname_end_2;
+ }
+ }
+ }
+
+ /* Advance to the next name context. The loop will exit when either
+ ** we have a match (cnt>0) or when we run out of name contexts.
+ */
+ if( cnt==0 ){
+ pNC = pNC->pNext;
+ }
+ }
+
+ /*
+ ** If X and Y are NULL (in other words if only the column name Z is
+ ** supplied) and the value of Z is enclosed in double-quotes, then
+ ** Z is a string literal if it doesn't match any column names. In that
+ ** case, we need to return right away and not make any changes to
+ ** pExpr.
+ **
+ ** Because no reference was made to outer contexts, the pNC->nRef
+ ** fields are not changed in any context.
+ */
+ if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
+ sqlite3DbFree(db, zCol);
+ return 0;
+ }
+
+ /*
+ ** cnt==0 means there was not match. cnt>1 means there were two or
+ ** more matches. Either way, we have an error.
+ */
+ if( cnt!=1 ){
+ const char *zErr;
+ zErr = cnt==0 ? "no such column" : "ambiguous column name";
+ if( zDb ){
+ sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
+ }else if( zTab ){
+ sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
+ }else{
+ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
+ }
+ pTopNC->nErr++;
+ }
+
+ /* If a column from a table in pSrcList is referenced, then record
+ ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
+ ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
+ ** column number is greater than the number of bits in the bitmask
+ ** then set the high-order bit of the bitmask.
+ */
+ if( pExpr->iColumn>=0 && pMatch!=0 ){
+ int n = pExpr->iColumn;
+ testcase( n==sizeof(Bitmask)*8-1 );
+ if( n>=sizeof(Bitmask)*8 ){
+ n = sizeof(Bitmask)*8-1;
+ }
+ assert( pMatch->iCursor==pExpr->iTable );
+ pMatch->colUsed |= ((Bitmask)1)<<n;
+ }
+
+lookupname_end:
+ /* Clean up and return
+ */
+ sqlite3DbFree(db, zDb);
+ sqlite3DbFree(db, zTab);
+ sqlite3ExprDelete(db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ sqlite3ExprDelete(db, pExpr->pRight);
+ pExpr->pRight = 0;
+ pExpr->op = TK_COLUMN;
+lookupname_end_2:
+ sqlite3DbFree(db, zCol);
+ if( cnt==1 ){
+ assert( pNC!=0 );
+ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
+ if( pMatch && !pMatch->pSelect ){
+ pExpr->pTab = pMatch->pTab;
+ }
+ /* Increment the nRef value on all name contexts from TopNC up to
+ ** the point where the name matched. */
+ for(;;){
+ assert( pTopNC!=0 );
+ pTopNC->nRef++;
+ if( pTopNC==pNC ) break;
+ pTopNC = pTopNC->pNext;
+ }
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
+**
+** Resolve symbolic names into TK_COLUMN operators for the current
+** node in the expression tree. Return 0 to continue the search down
+** the tree or 2 to abort the tree walk.
+**
+** This routine also does error checking and name resolution for
+** function names. The operator for aggregate functions is changed
+** to TK_AGG_FUNCTION.
+*/
+static int nameResolverStep(void *pArg, Expr *pExpr){
+ NameContext *pNC = (NameContext*)pArg;
+ Parse *pParse;
+
+ if( pExpr==0 ) return 1;
+ assert( pNC!=0 );
+ pParse = pNC->pParse;
+
+ if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
+ ExprSetProperty(pExpr, EP_Resolved);
+#ifndef NDEBUG
+ if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
+ SrcList *pSrcList = pNC->pSrcList;
+ int i;
+ for(i=0; i<pNC->pSrcList->nSrc; i++){
+ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
+ }
+ }
+#endif
+ switch( pExpr->op ){
+ /* Double-quoted strings (ex: "abc") are used as identifiers if
+ ** possible. Otherwise they remain as strings. Single-quoted
+ ** strings (ex: 'abc') are always string literals.
+ */
+ case TK_STRING: {
+ if( pExpr->token.z[0]=='\'' ) break;
+ /* Fall thru into the TK_ID case if this is a double-quoted string */
+ }
+ /* A lone identifier is the name of a column.
+ */
+ case TK_ID: {
+ lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
+ return 1;
+ }
+
+ /* A table name and column name: ID.ID
+ ** Or a database, table and column: ID.ID.ID
+ */
+ case TK_DOT: {
+ Token *pColumn;
+ Token *pTable;
+ Token *pDb;
+ Expr *pRight;
+
+ /* if( pSrcList==0 ) break; */
+ pRight = pExpr->pRight;
+ if( pRight->op==TK_ID ){
+ pDb = 0;
+ pTable = &pExpr->pLeft->token;
+ pColumn = &pRight->token;
+ }else{
+ assert( pRight->op==TK_DOT );
+ pDb = &pExpr->pLeft->token;
+ pTable = &pRight->pLeft->token;
+ pColumn = &pRight->pRight->token;
+ }
+ lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
+ return 1;
+ }
+
+ /* Resolve function names
+ */
+ case TK_CONST_FUNC:
+ case TK_FUNCTION: {
+ ExprList *pList = pExpr->pList; /* The argument list */
+ int n = pList ? pList->nExpr : 0; /* 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 */
+ int i;
+ int auth; /* Authorization to use the function */
+ int nId; /* Number of characters in function name */
+ const char *zId; /* The function name. */
+ FuncDef *pDef; /* Information about the function */
+ int enc = ENC(pParse->db); /* The database encoding */
+
+ zId = (char*)pExpr->token.z;
+ nId = pExpr->token.n;
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
+ if( pDef==0 ){
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
+ if( pDef==0 ){
+ no_such_func = 1;
+ }else{
+ wrong_num_args = 1;
+ }
+ }else{
+ is_agg = pDef->xFunc==0;
+ }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pDef ){
+ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
+ if( auth!=SQLITE_OK ){
+ if( auth==SQLITE_DENY ){
+ sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
+ pDef->zName);
+ pNC->nErr++;
+ }
+ pExpr->op = TK_NULL;
+ return 1;
+ }
+ }
+#endif
+ if( is_agg && !pNC->allowAgg ){
+ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+ pNC->nErr++;
+ is_agg = 0;
+ }else if( no_such_func ){
+ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+ pNC->nErr++;
+ }else if( wrong_num_args ){
+ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+ nId, zId);
+ pNC->nErr++;
+ }
+ if( is_agg ){
+ pExpr->op = TK_AGG_FUNCTION;
+ pNC->hasAgg = 1;
+ }
+ if( is_agg ) pNC->allowAgg = 0;
+ for(i=0; pNC->nErr==0 && i<n; i++){
+ walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
+ }
+ if( is_agg ) pNC->allowAgg = 1;
+ /* FIX ME: Compute pExpr->affinity based on the expected return
+ ** type of the function
+ */
+ return is_agg;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_SELECT:
+ case TK_EXISTS:
+#endif
+ case TK_IN: {
+ if( pExpr->pSelect ){
+ int nRef = pNC->nRef;
+#ifndef SQLITE_OMIT_CHECK
+ if( pNC->isCheck ){
+ sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
+ }
+#endif
+ sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
+ assert( pNC->nRef>=nRef );
+ if( nRef!=pNC->nRef ){
+ ExprSetProperty(pExpr, EP_VarSelect);
+ }
+ }
+ break;
+ }
+#ifndef SQLITE_OMIT_CHECK
+ case TK_VARIABLE: {
+ if( pNC->isCheck ){
+ sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
+ }
+ break;
+ }
+#endif
+ }
+ return 0;
+}
+
+/*
+** This routine walks an expression tree and resolves references to
+** table columns. Nodes of the form ID.ID or ID resolve into an
+** index to the table in the table list and a column offset. The
+** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
+** value is changed to the index of the referenced table in pTabList
+** plus the "base" value. The base value will ultimately become the
+** VDBE cursor number for a cursor that is pointing into the referenced
+** table. The Expr.iColumn value is changed to the index of the column
+** of the referenced table. The Expr.iColumn value for the special
+** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
+** alias for ROWID.
+**
+** Also resolve function names and check the functions for proper
+** usage. Make sure all function names are recognized and all functions
+** have the correct number of arguments. Leave an error message
+** in pParse->zErrMsg if anything is amiss. Return the number of errors.
+**
+** If the expression contains aggregate functions then set the EP_Agg
+** property on the expression.
+*/
+SQLITE_PRIVATE int sqlite3ExprResolveNames(
+ NameContext *pNC, /* Namespace to resolve expressions in. */
+ Expr *pExpr /* The expression to be analyzed. */
+){
+ int savedHasAgg;
+
+ if( pExpr==0 ) return 0;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ {
+ if( checkExprHeight(pNC->pParse, pExpr->nHeight + pNC->pParse->nHeight) ){
+ return 1;
+ }
+ pNC->pParse->nHeight += pExpr->nHeight;
+ }
+#endif
+ savedHasAgg = pNC->hasAgg;
+ pNC->hasAgg = 0;
+ walkExprTree(pExpr, nameResolverStep, pNC);
+#if SQLITE_MAX_EXPR_DEPTH>0
+ pNC->pParse->nHeight -= pExpr->nHeight;
+#endif
+ if( pNC->nErr>0 ){
+ ExprSetProperty(pExpr, EP_Error);
+ }
+ if( pNC->hasAgg ){
+ ExprSetProperty(pExpr, EP_Agg);
+ }else if( savedHasAgg ){
+ pNC->hasAgg = 1;
+ }
+ return ExprHasProperty(pExpr, EP_Error);
+}
+
+/*
+** A pointer instance of this structure is used to pass information
+** through walkExprTree into codeSubqueryStep().
+*/
+typedef struct QueryCoder QueryCoder;
+struct QueryCoder {
+ Parse *pParse; /* The parsing context */
+ NameContext *pNC; /* Namespace of first enclosing query */
+};
+
#ifdef SQLITE_TEST
int sqlite3_enable_in_opt = 1;
#else
@@ -54737,9 +52169,8 @@ static int isCandidateForInOpt(Select *p){
if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */
if( p==0 ) return 0; /* right-hand side of IN is SELECT */
if( p->pPrior ) return 0; /* Not a compound SELECT */
- if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
- return 0; /* No DISTINCT keyword and no aggregate functions */
- }
+ if( p->isDistinct ) return 0; /* No DISTINCT keyword */
+ if( p->isAgg ) return 0; /* Contains no aggregate functions */
if( p->pGroupBy ) return 0; /* Has no GROUP BY clause */
if( p->pLimit ) return 0; /* Has no LIMIT clause */
if( p->pOffset ) return 0;
@@ -54904,13 +52335,11 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
if( eType==0 ){
int rMayHaveNull = 0;
- eType = IN_INDEX_EPH;
if( prNotFound ){
*prNotFound = rMayHaveNull = ++pParse->nMem;
- }else if( pX->pLeft->iColumn<0 && pX->pSelect==0 ){
- eType = IN_INDEX_ROWID;
}
- sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
+ sqlite3CodeSubselect(pParse, pX, rMayHaveNull);
+ eType = IN_INDEX_EPH;
}else{
pX->iTable = iTab;
}
@@ -54929,20 +52358,9 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
**
** The pExpr parameter describes the expression that contains the IN
** operator or subquery.
-**
-** If parameter isRowid is non-zero, then expression pExpr is guaranteed
-** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
-** to some integer key column of a table B-Tree. In this case, use an
-** intkey B-Tree to store the set of IN(...) values instead of the usual
-** (slower) variable length keys B-Tree.
*/
#ifndef SQLITE_OMIT_SUBQUERY
-SQLITE_PRIVATE void sqlite3CodeSubselect(
- Parse *pParse,
- Expr *pExpr,
- int rMayHaveNull,
- int isRowid
-){
+SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHaveNull){
int testAddr = 0; /* One-time test address */
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
@@ -54970,13 +52388,12 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
char affinity;
KeyInfo keyInfo;
int addr; /* Address of OP_OpenEphemeral instruction */
- Expr *pLeft = pExpr->pLeft;
if( rMayHaveNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
}
- affinity = sqlite3ExprAffinity(pLeft);
+ affinity = sqlite3ExprAffinity(pExpr->pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
** expression it is handled the same way. A virtual table is
@@ -54992,7 +52409,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
** is used.
*/
pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
+ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
@@ -55005,11 +52422,10 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
SelectDest dest;
ExprList *pEList;
- assert( !isRowid );
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.affinity = (int)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
- if( sqlite3Select(pParse, pExpr->pSelect, &dest) ){
+ if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0) ){
return;
}
pEList = pExpr->pSelect->pEList;
@@ -55033,12 +52449,11 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
if( !affinity ){
affinity = SQLITE_AFF_NONE;
}
- keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+ keyInfo.aColl[0] = pExpr->pLeft->pColl;
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
@@ -55057,22 +52472,14 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
assert( pParse->disableColCache>0 );
pParse->disableColCache--;
-
- if( isRowid ){
- sqlite3VdbeAddOp2(v, OP_MustBeInt, r3, sqlite3VdbeCurrentAddr(v)+2);
- sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
- }else{
- sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
- sqlite3ExprCacheAffinityChange(pParse, r3, 1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
- }
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
+ sqlite3ExprCacheAffinityChange(pParse, r3, 1);
+ sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
- if( !isRowid ){
- sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
- }
+ sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
break;
}
@@ -55099,7 +52506,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(
}
sqlite3ExprDelete(pParse->db, pSel->pLimit);
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
- if( sqlite3Select(pParse, pSel, &dest) ){
+ if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0) ){
return;
}
pExpr->iColumn = dest.iParm;
@@ -55136,11 +52543,10 @@ static char *dup8bytes(Vdbe *v, const char *in){
*/
static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){
assert( z || v==0 || sqlite3VdbeDb(v)->mallocFailed );
- assert( !z || !isdigit(z[n]) );
- UNUSED_PARAMETER(n);
if( z ){
double value;
char *zV;
+ assert( !isdigit(z[n]) );
sqlite3AtoF(z, &value);
if( sqlite3IsNaN(value) ){
sqlite3VdbeAddOp2(v, OP_Null, 0, iMem);
@@ -55382,50 +52788,11 @@ SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){
}
/*
-** Generate code to store the value of the iAlias-th alias in register
-** target. The first time this is called, pExpr is evaluated to compute
-** the value of the alias. The value is stored in an auxiliary register
-** and the number of that register is returned. On subsequent calls,
-** the register number is returned without generating any code.
-**
-** Note that in order for this to work, code must be generated in the
-** same order that it is executed.
-**
-** Aliases are numbered starting with 1. So iAlias is in the range
-** of 1 to pParse->nAlias inclusive.
-**
-** pParse->aAlias[iAlias-1] records the register number where the value
-** of the iAlias-th alias is stored. If zero, that means that the
-** alias has not yet been computed.
-*/
-static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){
- sqlite3 *db = pParse->db;
- int iReg;
- if( pParse->aAlias==0 ){
- pParse->aAlias = sqlite3DbMallocZero(db,
- sizeof(pParse->aAlias[0])*pParse->nAlias );
- if( db->mallocFailed ) return 0;
- }
- assert( iAlias>0 && iAlias<=pParse->nAlias );
- iReg = pParse->aAlias[iAlias-1];
- if( iReg==0 ){
- if( pParse->disableColCache ){
- iReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
- }else{
- iReg = ++pParse->nMem;
- sqlite3ExprCode(pParse, pExpr, iReg);
- pParse->aAlias[iAlias-1] = iReg;
- }
- }
- return iReg;
-}
-
-/*
** Generate code into the current Vdbe to evaluate the given
** expression. Attempt to store the results in register "target".
** Return the register where results are stored.
**
-** With this routine, there is no guarantee that results will
+** With this routine, there is no guaranteed that results will
** be stored in target. The result might be stored in some other
** register if it is convenient to do so. The calling function
** must check the return code and move the results to the desired
@@ -55438,10 +52805,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
int regFree1 = 0; /* If non-zero free this temporary register */
int regFree2 = 0; /* If non-zero free this temporary register */
int r1, r2, r3, r4; /* Various register numbers */
- sqlite3 *db;
- db = pParse->db;
- assert( v!=0 || db->mallocFailed );
+ assert( v!=0 || pParse->db->mallocFailed );
assert( target>0 && target<=pParse->nMem );
if( v==0 ) return 0;
@@ -55487,7 +52852,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
break;
}
case TK_STRING: {
- sqlite3DequoteExpr(db, pExpr);
+ sqlite3DequoteExpr(pParse->db, pExpr);
sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0,
(char*)pExpr->token.z, pExpr->token.n);
break;
@@ -55523,10 +52888,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
inReg = pExpr->iTable;
break;
}
- case TK_AS: {
- inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft, target);
- break;
- }
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
@@ -55544,10 +52905,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
testcase( to_op==OP_ToNumeric );
testcase( to_op==OP_ToInt );
testcase( to_op==OP_ToReal );
- if( inReg!=target ){
- sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
- inReg = target;
- }
sqlite3VdbeAddOp1(v, to_op, inReg);
testcase( usedAsColumnCache(pParse, inReg, inReg) );
sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
@@ -55687,6 +53044,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
const char *zId;
int constMask = 0;
int i;
+ sqlite3 *db = pParse->db;
u8 enc = ENC(db);
CollSeq *pColl = 0;
@@ -55694,7 +53052,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
testcase( op==TK_FUNCTION );
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
- pDef = sqlite3FindFunction(db, zId, nId, nExpr, enc, 0);
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
assert( pDef!=0 );
if( pList ){
nExpr = pList->nExpr;
@@ -55726,12 +53084,12 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){
constMask |= (1<<i);
}
- if( (pDef->flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
+ if( pDef->needCollSeq && !pColl ){
pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
}
}
- if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){
- if( !pColl ) pColl = db->pDfltColl;
+ if( pDef->needCollSeq ){
+ if( !pColl ) pColl = pParse->db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
@@ -55749,7 +53107,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
testcase( op==TK_EXISTS );
testcase( op==TK_SELECT );
if( pExpr->iColumn==0 ){
- sqlite3CodeSubselect(pParse, pExpr, 0, 0);
+ sqlite3CodeSubselect(pParse, pExpr, 0);
}
inReg = pExpr->iColumn;
break;
@@ -55832,7 +53190,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
sqlite3VdbeJumpHere(v, j3);
/* Copy the value of register rNotFound (which is either NULL or 0)
- ** into the target register. This will be the result of the
+ ** into the target register. This will be the result of the
** expression.
*/
sqlite3VdbeAddOp2(v, OP_Copy, rNotFound, target);
@@ -55930,6 +53288,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
testcase( regFree1==0 );
cacheX.op = TK_REGISTER;
+ cacheX.iColumn = 0;
opCompare.op = TK_EQ;
opCompare.pLeft = &cacheX;
pTest = &opCompare;
@@ -55971,7 +53330,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
assert( pExpr->iColumn==OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail );
- sqlite3DequoteExpr(db, pExpr);
+ sqlite3DequoteExpr(pParse->db, pExpr);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, 0,
(char*)pExpr->token.z, pExpr->token.n);
} else {
@@ -56049,6 +53408,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targe
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
pExpr->iTable = iMem;
+ pExpr->iColumn = pExpr->op;
pExpr->op = TK_REGISTER;
}
return inReg;
@@ -56119,8 +53479,8 @@ static int isAppropriateForFactoring(Expr *p){
** into a register and convert the expression into a TK_REGISTER
** expression.
*/
-static int evalConstExpr(Walker *pWalker, Expr *pExpr){
- Parse *pParse = pWalker->pParse;
+static int evalConstExpr(void *pArg, Expr *pExpr){
+ Parse *pParse = (Parse*)pArg;
switch( pExpr->op ){
case TK_REGISTER: {
return 1;
@@ -56148,11 +53508,12 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
int r2;
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
+ pExpr->iColumn = pExpr->op;
pExpr->op = TK_REGISTER;
pExpr->iTable = r2;
- return WRC_Prune;
+ return 1;
}
- return WRC_Continue;
+ return 0;
}
/*
@@ -56161,11 +53522,7 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
** are TK_REGISTER opcodes that refer to the precomputed values.
*/
SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
- Walker w;
- w.xExprCallback = evalConstExpr;
- w.xSelectCallback = 0;
- w.pParse = pParse;
- sqlite3WalkExpr(&w, pExpr);
+ walkExprTree(pExpr, evalConstExpr, pParse);
}
@@ -56179,26 +53536,19 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
Parse *pParse, /* Parsing context */
ExprList *pList, /* The expression list to be coded */
int target, /* Where to write results */
- int doHardCopy /* Make a hard copy of every element */
+ int doHardCopy /* Call sqlite3ExprHardCopy on each element if true */
){
struct ExprList_item *pItem;
int i, n;
- assert( pList!=0 );
+ assert( pList!=0 || pParse->db->mallocFailed );
+ if( pList==0 ){
+ return 0;
+ }
assert( target>0 );
n = pList->nExpr;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
- if( pItem->iAlias ){
- int iReg = codeAlias(pParse, pItem->iAlias, pItem->pExpr, target+i);
- Vdbe *v = sqlite3GetVdbe(pParse);
- if( iReg!=target+i ){
- sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i);
- }
- }else{
- sqlite3ExprCode(pParse, pItem->pExpr, target+i);
- }
- if( doHardCopy ){
- sqlite3ExprHardCopy(pParse, target, n);
- }
+ sqlite3ExprCode(pParse, pItem->pExpr, target+i);
+ if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n);
}
return n;
}
@@ -56572,13 +53922,15 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
}
/*
-** This is the xExprCallback for a tree walker. It is used to
-** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
+** This is an xFunc for walkExprTree() used to implement
+** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
** for additional information.
+**
+** This routine analyzes the aggregate function at pExpr.
*/
-static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
+static int analyzeAggregate(void *pArg, Expr *pExpr){
int i;
- NameContext *pNC = pWalker->u.pNC;
+ NameContext *pNC = (NameContext *)pArg;
Parse *pParse = pNC->pParse;
SrcList *pSrcList = pNC->pSrcList;
AggInfo *pAggInfo = pNC->pAggInfo;
@@ -56586,8 +53938,6 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
switch( pExpr->op ){
case TK_AGG_COLUMN:
case TK_COLUMN: {
- testcase( pExpr->op==TK_AGG_COLUMN );
- testcase( pExpr->op==TK_COLUMN );
/* Check to see if the column is in one of the tables in the FROM
** clause of the aggregate query */
if( pSrcList ){
@@ -56649,7 +53999,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
} /* endif pExpr->iTable==pItem->iCursor */
} /* end loop over pSrcList */
}
- return WRC_Prune;
+ return 1;
}
case TK_AGG_FUNCTION: {
/* The pNC->nDepth==0 test causes aggregate functions in subqueries
@@ -56687,22 +54037,21 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
pExpr->iAgg = i;
pExpr->pAggInfo = pAggInfo;
- return WRC_Prune;
+ return 1;
}
}
}
- return WRC_Continue;
-}
-static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
- NameContext *pNC = pWalker->u.pNC;
- if( pNC->nDepth==0 ){
+
+ /* Recursively walk subqueries looking for TK_COLUMN nodes that need
+ ** to be changed to TK_AGG_COLUMN. But increment nDepth so that
+ ** TK_AGG_FUNCTION nodes in subqueries will be unchanged.
+ */
+ if( pExpr->pSelect ){
pNC->nDepth++;
- sqlite3WalkSelect(pWalker, pSelect);
+ walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
pNC->nDepth--;
- return WRC_Prune;
- }else{
- return WRC_Continue;
}
+ return 0;
}
/*
@@ -56711,14 +54060,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
** Make additional entries to the pParse->aAgg[] array as necessary.
**
** This routine should only be called after the expression has been
-** analyzed by sqlite3ResolveExprNames().
+** analyzed by sqlite3ExprResolveNames().
*/
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
- Walker w;
- w.xExprCallback = analyzeAggregate;
- w.xSelectCallback = analyzeAggregatesInSelect;
- w.u.pNC = pNC;
- sqlite3WalkExpr(&w, pExpr);
+ walkExprTree(pExpr, analyzeAggregate, pNC);
}
/*
@@ -56817,7 +54162,7 @@ SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
*/
static void renameTableFunc(
sqlite3_context *context,
- int NotUsed,
+ int argc,
sqlite3_value **argv
){
unsigned char const *zSql = sqlite3_value_text(argv[0]);
@@ -56831,8 +54176,6 @@ static void renameTableFunc(
sqlite3 *db = sqlite3_context_db_handle(context);
- UNUSED_PARAMETER(NotUsed);
-
/* The principle used to locate the table name in the CREATE TABLE
** statement is that the table name is the first non-space token that
** is immediately followed by a TK_LP or TK_USING token.
@@ -56854,7 +54197,7 @@ static void renameTableFunc(
do {
zCsr += len;
len = sqlite3GetToken(zCsr, &token);
- } while( token==TK_SPACE );
+ } while( token==TK_SPACE || token==TK_COMMENT );
assert( len>0 );
} while( token!=TK_LP && token!=TK_USING );
@@ -56874,7 +54217,7 @@ static void renameTableFunc(
*/
static void renameTriggerFunc(
sqlite3_context *context,
- int NotUsed,
+ int argc,
sqlite3_value **argv
){
unsigned char const *zSql = sqlite3_value_text(argv[0]);
@@ -56886,9 +54229,8 @@ static void renameTriggerFunc(
unsigned char const *zCsr = zSql;
int len = 0;
char *zRet;
- sqlite3 *db = sqlite3_context_db_handle(context);
- UNUSED_PARAMETER(NotUsed);
+ sqlite3 *db = sqlite3_context_db_handle(context);
/* The principle used to locate the table name in the CREATE TRIGGER
** statement is that the table name is the first token that is immediatedly
@@ -57222,11 +54564,11 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
Expr *pDflt; /* Default value for the new column */
sqlite3 *db; /* The database connection; */
- db = pParse->db;
- if( pParse->nErr || db->mallocFailed ) return;
+ if( pParse->nErr ) return;
pNew = pParse->pNewTable;
assert( pNew );
+ db = pParse->db;
assert( sqlite3BtreeHoldsAllMutexes(db) );
iDb = sqlite3SchemaToIndex(db, pNew->pSchema);
zDb = db->aDb[iDb].zName;
@@ -57490,11 +54832,11 @@ static void openStatTable(
static void analyzeOneTable(
Parse *pParse, /* Parser context */
Table *pTab, /* Table whose indices are to be analyzed */
- int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */
+ int iStatCur, /* Cursor that writes to the sqlite_stat1 table */
int iMem /* Available memory locations begin here */
){
Index *pIdx; /* An index to being analyzed */
- int iIdxCur; /* Index of VdbeCursor for index being analyzed */
+ int iIdxCur; /* Cursor number for index being analyzed */
int nCol; /* Number of columns in the index */
Vdbe *v; /* The virtual machine being built up */
int i; /* Loop counter */
@@ -57760,7 +55102,7 @@ struct analysisInfo {
** argv[0] = name of the index
** argv[1] = results of analysis - on integer for each column
*/
-static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
+static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){
analysisInfo *pInfo = (analysisInfo*)pData;
Index *pIndex;
int i, c;
@@ -57768,8 +55110,6 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
const char *z;
assert( argc==2 );
- UNUSED_PARAMETER2(NotUsed, argc);
-
if( argv==0 || argv[0]==0 || argv[1]==0 ){
return 0;
}
@@ -57872,7 +55212,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
int rc = SQLITE_OK;
if( pExpr ){
if( pExpr->op!=TK_ID ){
- rc = sqlite3ResolveExprNames(pName, pExpr);
+ rc = sqlite3ExprResolveNames(pName, pExpr);
if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span);
return SQLITE_ERROR;
@@ -57897,7 +55237,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
*/
static void attachFunc(
sqlite3_context *context,
- int NotUsed,
+ int argc,
sqlite3_value **argv
){
int i;
@@ -57909,8 +55249,6 @@ static void attachFunc(
char *zErrDyn = 0;
char zErr[128];
- UNUSED_PARAMETER(NotUsed);
-
zFile = (const char *)sqlite3_value_text(argv[0]);
zName = (const char *)sqlite3_value_text(argv[1]);
if( zFile==0 ) zFile = "";
@@ -58067,7 +55405,7 @@ attach_error:
*/
static void detachFunc(
sqlite3_context *context,
- int NotUsed,
+ int argc,
sqlite3_value **argv
){
const char *zName = (const char *)sqlite3_value_text(argv[0]);
@@ -58076,8 +55414,6 @@ static void detachFunc(
Db *pDb = 0;
char zErr[128];
- UNUSED_PARAMETER(NotUsed);
-
if( zName==0 ) zName = "";
for(i=0; i<db->nDb; i++){
pDb = &db->aDb[i];
@@ -58120,7 +55456,8 @@ detach_error:
static void codeAttach(
Parse *pParse, /* The parser context */
int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */
- FuncDef *pFunc, /* FuncDef wrapper for detachFunc() or attachFunc() */
+ const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */
+ int nFunc, /* Number of args to pass to zFunc */
Expr *pAuthArg, /* Expression to pass to authorization callback */
Expr *pFilename, /* Name of database file */
Expr *pDbname, /* Name of the database to use internally */
@@ -58129,6 +55466,7 @@ static void codeAttach(
int rc;
NameContext sName;
Vdbe *v;
+ FuncDef *pFunc;
sqlite3* db = pParse->db;
int regArgs;
@@ -58167,8 +55505,9 @@ static void codeAttach(
assert( v || db->mallocFailed );
if( v ){
- sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3);
- sqlite3VdbeChangeP5(v, pFunc->nArg);
+ sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs+3);
+ sqlite3VdbeChangeP5(v, nFunc);
+ pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);
/* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
@@ -58190,19 +55529,7 @@ attach_end:
** DETACH pDbname
*/
SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){
- static FuncDef detach_func = {
- 1, /* nArg */
- SQLITE_UTF8, /* iPrefEnc */
- 0, /* flags */
- 0, /* pUserData */
- 0, /* pNext */
- detachFunc, /* xFunc */
- 0, /* xStep */
- 0, /* xFinalize */
- "sqlite_detach", /* zName */
- 0 /* pHash */
- };
- codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname);
+ codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, pDbname);
}
/*
@@ -58211,23 +55538,22 @@ SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){
** ATTACH p AS pDbname KEY pKey
*/
SQLITE_PRIVATE void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
- static FuncDef attach_func = {
- 3, /* nArg */
- SQLITE_UTF8, /* iPrefEnc */
- 0, /* flags */
- 0, /* pUserData */
- 0, /* pNext */
- attachFunc, /* xFunc */
- 0, /* xStep */
- 0, /* xFinalize */
- "sqlite_attach", /* zName */
- 0 /* pHash */
- };
- codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey);
+ codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey);
}
#endif /* SQLITE_OMIT_ATTACH */
/*
+** Register the functions sqlite_attach and sqlite_detach.
+*/
+SQLITE_PRIVATE void sqlite3AttachFunctions(sqlite3 *db){
+#ifndef SQLITE_OMIT_ATTACH
+ static const int enc = SQLITE_UTF8;
+ sqlite3CreateFunc(db, "sqlite_attach", 3, enc, 0, attachFunc, 0, 0);
+ sqlite3CreateFunc(db, "sqlite_detach", 1, enc, 0, detachFunc, 0, 0);
+#endif
+}
+
+/*
** Initialize a DbFixer structure. This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
**
@@ -59234,7 +56560,7 @@ SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){
*/
SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){
int i = -1; /* Database number */
- size_t n; /* Number of characters in the name */
+ int n; /* Number of characters in the name */
Db *pDb; /* A database whose name space is being searched */
char *zName; /* Name we are searching for */
@@ -59278,11 +56604,7 @@ SQLITE_PRIVATE int sqlite3TwoPartName(
sqlite3 *db = pParse->db;
if( pName2 && pName2->n>0 ){
- if( db->init.busy ) {
- sqlite3ErrorMsg(pParse, "corrupt database");
- pParse->nErr++;
- return -1;
- }
+ assert( !db->init.busy );
*pUnqual = pName2;
iDb = sqlite3FindDb(db, pName1);
if( iDb<0 ){
@@ -59752,12 +57074,12 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
char *zType = 0;
int iCol = -1, i;
if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
- if( pTab->tabFlags & TF_HasPrimaryKey ){
+ if( pTab->hasPrimKey ){
sqlite3ErrorMsg(pParse,
"table \"%s\" has more than one primary key", pTab->zName);
goto primary_key_exit;
}
- pTab->tabFlags |= TF_HasPrimaryKey;
+ pTab->hasPrimKey = 1;
if( pList==0 ){
iCol = pTab->nCol - 1;
pTab->aCol[iCol].isPrimKey = 1;
@@ -59781,8 +57103,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
&& sortOrder==SQLITE_SO_ASC ){
pTab->iPKey = iCol;
pTab->keyConf = onError;
- assert( autoInc==0 || autoInc==1 );
- pTab->tabFlags |= autoInc*TF_Autoincrement;
+ pTab->autoInc = autoInc;
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
@@ -60004,7 +57325,7 @@ static char *createTableStmt(sqlite3 *db, Table *p, int isTemp){
identPut(zStmt, &k, pCol->zName);
if( (z = pCol->zType)!=0 ){
zStmt[k++] = ' ';
- assert( (int)(strlen(z)+k+1)<=n );
+ assert( strlen(z)+k+1<=n );
sqlite3_snprintf(n-k, &zStmt[k], "%s", z);
k += strlen(z);
}
@@ -60069,7 +57390,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
sNC.pParse = pParse;
sNC.pSrcList = &sSrc;
sNC.isCheck = 1;
- if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
+ if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){
return;
}
}
@@ -60142,10 +57463,10 @@ SQLITE_PRIVATE void sqlite3EndTable(
sqlite3VdbeChangeP5(v, 1);
pParse->nTab = 2;
sqlite3SelectDestInit(&dest, SRT_Table, 1);
- sqlite3Select(pParse, pSelect, &dest);
+ sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
sqlite3VdbeAddOp1(v, OP_Close, 1);
if( pParse->nErr==0 ){
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = pSelTab->nCol;
@@ -60191,7 +57512,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
- if( p->tabFlags & TF_Autoincrement ){
+ if( p->autoInc ){
Db *pDb = &db->aDb[iDb];
if( pDb->pSchema->pSeqTab==0 ){
sqlite3NestedParse(pParse,
@@ -60387,10 +57708,10 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
db->xAuth = xAuth;
#else
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
#endif
pParse->nTab = n;
if( pSelTab ){
@@ -60624,7 +57945,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
}
}
#endif
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
+ if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
goto exit_drop_table;
}
@@ -60679,7 +58000,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
** at the btree level, in case the sqlite_sequence table needs to
** move as a result of the drop (can happen in auto-vacuum mode).
*/
- if( pTab->tabFlags & TF_Autoincrement ){
+ if( pTab->autoInc ){
sqlite3NestedParse(pParse,
"DELETE FROM %s.sqlite_sequence WHERE name=%Q",
pDb->zName, pTab->zName
@@ -60749,7 +58070,6 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
ExprList *pToCol, /* Columns in the other table */
int flags /* Conflict resolution algorithms. */
){
- sqlite3 *db = pParse->db;
#ifndef SQLITE_OMIT_FOREIGN_KEY
FKey *pFKey = 0;
Table *p = pParse->pNewTable;
@@ -60757,8 +58077,10 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
int i;
int nCol;
char *z;
+ sqlite3 *db;
assert( pTo!=0 );
+ db = pParse->db;
if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end;
if( pFromCol==0 ){
int iCol = p->nCol-1;
@@ -61013,7 +58335,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
}
pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName,
pTblName->a[0].zDatabase);
- if( !pTab || db->mallocFailed ) goto exit_create_index;
+ if( !pTab ) goto exit_create_index;
assert( db->aDb[iDb].pSchema==pTab->pSchema );
}else{
assert( pName==0 );
@@ -61024,7 +58346,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
pDb = &db->aDb[iDb];
if( pTab==0 || pParse->nErr ) goto exit_create_index;
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
+ if( pTab->readOnly ){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
}
@@ -61116,10 +58438,9 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
** specified collation sequence names.
*/
for(i=0; i<pList->nExpr; i++){
- Expr *pExpr;
- CollSeq *pColl;
- if( (pExpr = pList->a[i].pExpr)!=0 && (pColl = pExpr->pColl)!=0 ){
- nExtra += (1 + strlen(pColl->zName));
+ Expr *pExpr = pList->a[i].pExpr;
+ if( pExpr ){
+ nExtra += (1 + strlen(pExpr->pColl->zName));
}
}
@@ -61186,7 +58507,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
** break backwards compatibility - it needs to be a warning.
*/
pIndex->aiColumn[i] = j;
- if( pListItem->pExpr && pListItem->pExpr->pColl ){
+ if( pListItem->pExpr ){
assert( pListItem->pExpr->pColl );
zColl = zExtra;
sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName);
@@ -61604,80 +58925,10 @@ SQLITE_PRIVATE int sqlite3IdListIndex(IdList *pList, const char *zName){
}
/*
-** Expand the space allocated for the given SrcList object by
-** creating nExtra new slots beginning at iStart. iStart is zero based.
-** New slots are zeroed.
-**
-** For example, suppose a SrcList initially contains two entries: A,B.
-** To append 3 new entries onto the end, do this:
-**
-** sqlite3SrcListEnlarge(db, pSrclist, 3, 2);
-**
-** After the call above it would contain: A, B, nil, nil, nil.
-** If the iStart argument had been 1 instead of 2, then the result
-** would have been: A, nil, nil, nil, B. To prepend the new slots,
-** the iStart value would be 0. The result then would
-** be: nil, nil, nil, A, B.
-**
-** If a memory allocation fails the SrcList is unchanged. The
-** db->mallocFailed flag will be set to true.
-*/
-SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
- sqlite3 *db, /* Database connection to notify of OOM errors */
- SrcList *pSrc, /* The SrcList to be enlarged */
- int nExtra, /* Number of new slots to add to pSrc->a[] */
- int iStart /* Index in pSrc->a[] of first new slot */
-){
- int i;
-
- /* Sanity checking on calling parameters */
- assert( iStart>=0 );
- assert( nExtra>=1 );
- if( pSrc==0 || iStart>pSrc->nSrc ){
- assert( db->mallocFailed );
- return pSrc;
- }
-
- /* Allocate additional space if needed */
- if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
- SrcList *pNew;
- int nAlloc = pSrc->nSrc+nExtra;
- pNew = sqlite3DbRealloc(db, pSrc,
- sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
- if( pNew==0 ){
- assert( db->mallocFailed );
- return pSrc;
- }
- pSrc = pNew;
- pSrc->nAlloc = nAlloc;
- }
-
- /* Move existing slots that come after the newly inserted slots
- ** out of the way */
- for(i=pSrc->nSrc-1; i>=iStart; i--){
- pSrc->a[i+nExtra] = pSrc->a[i];
- }
- pSrc->nSrc += nExtra;
-
- /* Zero the newly allocated slots */
- memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
- for(i=iStart; i<iStart+nExtra; i++){
- pSrc->a[i].iCursor = -1;
- }
-
- /* Return a pointer to the enlarged SrcList */
- return pSrc;
-}
-
-
-/*
** Append a new table name to the given SrcList. Create a new SrcList if
** need be. A new entry is created in the SrcList even if pToken is NULL.
**
-** A SrcList is returned, or NULL if there is an OOM error. The returned
-** SrcList might be the same as the SrcList that was input or it might be
-** a new one. If an OOM error does occurs, then the prior value of pList
-** that is input to this routine is automatically freed.
+** A new SrcList is returned, or NULL if malloc() fails.
**
** If pDatabase is not null, it means that the table has an optional
** database name prefix. Like this: "database.table". The pDatabase
@@ -61710,12 +58961,19 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
if( pList==0 ) return 0;
pList->nAlloc = 1;
}
- pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc);
- if( db->mallocFailed ){
- sqlite3SrcListDelete(db, pList);
- return 0;
+ if( pList->nSrc>=pList->nAlloc ){
+ SrcList *pNew;
+ pList->nAlloc *= 2;
+ pNew = sqlite3DbRealloc(db, pList,
+ sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
+ if( pNew==0 ){
+ sqlite3SrcListDelete(db, pList);
+ return 0;
+ }
+ pList = pNew;
}
- pItem = &pList->a[pList->nSrc-1];
+ pItem = &pList->a[pList->nSrc];
+ memset(pItem, 0, sizeof(pList->a[0]));
if( pDatabase && pDatabase->z==0 ){
pDatabase = 0;
}
@@ -61726,11 +58984,14 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(
}
pItem->zName = sqlite3NameFromToken(db, pTable);
pItem->zDatabase = sqlite3NameFromToken(db, pDatabase);
+ pItem->iCursor = -1;
+ pItem->isPopulated = 0;
+ pList->nSrc++;
return pList;
}
/*
-** Assign VdbeCursor index numbers to all tables in a SrcList
+** Assign cursors to all tables in a SrcList
*/
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
@@ -61758,7 +59019,6 @@ SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3DbFree(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
sqlite3DbFree(db, pItem->zAlias);
- sqlite3DbFree(db, pItem->zIndex);
sqlite3DeleteTable(pItem->pTab);
sqlite3SelectDelete(db, pItem->pSelect);
sqlite3ExprDelete(db, pItem->pOn);
@@ -61813,24 +59073,6 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(
}
/*
-** Add an INDEXED BY or NOT INDEXED clause to the most recently added
-** element of the source-list passed as the second argument.
-*/
-SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
- if( pIndexedBy && p && p->nSrc>0 ){
- struct SrcList_item *pItem = &p->a[p->nSrc-1];
- assert( pItem->notIndexed==0 && pItem->zIndex==0 );
- if( pIndexedBy->n==1 && !pIndexedBy->z ){
- /* A "NOT INDEXED" clause was supplied. See parse.y
- ** construct "indexed_opt" for details. */
- pItem->notIndexed = 1;
- }else{
- pItem->zIndex = sqlite3NameFromToken(pParse->db, pIndexedBy);
- }
- }
-}
-
-/*
** When building up a FROM clause in the parser, the join operator
** is initially attached to the left operand. But the code generator
** expects the join operator to be on the right operand. This routine
@@ -62412,87 +59654,6 @@ SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(
return pColl;
}
-/* During the search for the best function definition, this procedure
-** is called to test how well the function passed as the first argument
-** matches the request for a function with nArg arguments in a system
-** that uses encoding enc. The value returned indicates how well the
-** request is matched. A higher value indicates a better match.
-**
-** The returned value is always between 1 and 6, as follows:
-**
-** 1: A variable arguments function that prefers UTF-8 when a UTF-16
-** encoding is requested, or vice versa.
-** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
-** requested, or vice versa.
-** 3: A variable arguments function using the same text encoding.
-** 4: A function with the exact number of arguments requested that
-** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
-** 5: A function with the exact number of arguments requested that
-** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
-** 6: An exact match.
-**
-*/
-static int matchQuality(FuncDef *p, int nArg, u8 enc){
- int match = 0;
- if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
- match = 1;
- if( p->nArg==nArg || nArg==-1 ){
- match = 4;
- }
- if( enc==p->iPrefEnc ){
- match += 2;
- }
- else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
- (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
- match += 1;
- }
- }
- return match;
-}
-
-/*
-** Search a FuncDefHash for a function with the given name. Return
-** a pointer to the matching FuncDef if found, or 0 if there is no match.
-*/
-static FuncDef *functionSearch(
- FuncDefHash *pHash, /* Hash table to search */
- int h, /* Hash of the name */
- const char *zFunc, /* Name of function */
- int nFunc /* Number of bytes in zFunc */
-){
- FuncDef *p;
- for(p=pHash->a[h]; p; p=p->pHash){
- if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){
- return p;
- }
- }
- return 0;
-}
-
-/*
-** Insert a new FuncDef into a FuncDefHash hash table.
-*/
-SQLITE_PRIVATE void sqlite3FuncDefInsert(
- FuncDefHash *pHash, /* The hash table into which to insert */
- FuncDef *pDef /* The function definition to insert */
-){
- FuncDef *pOther;
- int nName = strlen(pDef->zName);
- u8 c1 = (u8)pDef->zName[0];
- int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a);
- pOther = functionSearch(pHash, h, pDef->zName, nName);
- if( pOther ){
- pDef->pNext = pOther->pNext;
- pOther->pNext = pDef;
- }else{
- pDef->pNext = 0;
- pDef->pHash = pHash->a[h];
- pHash->a[h] = pDef;
- }
-}
-
-
-
/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8. Return a
@@ -62522,60 +59683,70 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
int createFlag /* Create new entry if true and does not otherwise exist */
){
FuncDef *p; /* Iterator variable */
+ FuncDef *pFirst; /* First function with this name */
FuncDef *pBest = 0; /* Best match found so far */
- int bestScore = 0; /* Score of best match */
- int h; /* Hash value */
+ int bestmatch = 0;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
if( nArg<-1 ) nArg = -1;
- h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
- /* First search for a match amongst the application-defined functions.
- */
- p = functionSearch(&db->aFunc, h, zName, nName);
- while( p ){
- int score = matchQuality(p, nArg, enc);
- if( score>bestScore ){
- pBest = p;
- bestScore = score;
- }
- p = p->pNext;
- }
+ pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
+ for(p=pFirst; p; p=p->pNext){
+ /* During the search for the best function definition, bestmatch is set
+ ** as follows to indicate the quality of the match with the definition
+ ** pointed to by pBest:
+ **
+ ** 0: pBest is NULL. No match has been found.
+ ** 1: A variable arguments function that prefers UTF-8 when a UTF-16
+ ** encoding is requested, or vice versa.
+ ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
+ ** requested, or vice versa.
+ ** 3: A variable arguments function using the same text encoding.
+ ** 4: A function with the exact number of arguments requested that
+ ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
+ ** 5: A function with the exact number of arguments requested that
+ ** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
+ ** 6: An exact match.
+ **
+ ** A larger value of 'matchqual' indicates a more desirable match.
+ */
+ if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
+ int match = 1; /* Quality of this match */
+ if( p->nArg==nArg || nArg==-1 ){
+ match = 4;
+ }
+ if( enc==p->iPrefEnc ){
+ match += 2;
+ }
+ else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
+ (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
+ match += 1;
+ }
- /* If no match is found, search the built-in functions.
- **
- ** Except, if createFlag is true, that means that we are trying to
- ** install a new function. Whatever FuncDef structure is returned will
- ** have fields overwritten with new information appropriate for the
- ** new function. But the FuncDefs for built-in functions are read-only.
- ** So we must not search for built-ins when creating a new function.
- */
- if( !createFlag && !pBest ){
- FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
- p = functionSearch(pHash, h, zName, nName);
- while( p ){
- int score = matchQuality(p, nArg, enc);
- if( score>bestScore ){
+ if( match>bestmatch ){
pBest = p;
- bestScore = score;
+ bestmatch = match;
}
- p = p->pNext;
}
}
- /* If the createFlag parameter is true and the search did not reveal an
+ /* If the createFlag parameter is true, and the seach did not reveal an
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
- if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&
- (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
- pBest->zName = (char *)&pBest[1];
+ if( createFlag && bestmatch<6 &&
+ (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){
pBest->nArg = nArg;
+ pBest->pNext = pFirst;
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
- sqlite3FuncDefInsert(&db->aFunc, pBest);
+ if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
+ db->mallocFailed = 1;
+ sqlite3DbFree(db, pBest);
+ return 0;
+ }
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
@@ -62600,14 +59771,14 @@ SQLITE_PRIVATE void sqlite3SchemaFree(void *p){
temp1 = pSchema->tblHash;
temp2 = pSchema->trigHash;
- sqlite3HashInit(&pSchema->trigHash, 0);
+ sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0);
sqlite3HashClear(&pSchema->aFKey);
sqlite3HashClear(&pSchema->idxHash);
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
}
sqlite3HashClear(&temp2);
- sqlite3HashInit(&pSchema->tblHash, 0);
+ sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0);
for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
Table *pTab = sqliteHashData(pElem);
sqlite3DeleteTable(pTab);
@@ -62631,10 +59802,10 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
if( !p ){
db->mallocFailed = 1;
}else if ( 0==p->file_format ){
- sqlite3HashInit(&p->tblHash, 0);
- sqlite3HashInit(&p->idxHash, 0);
- sqlite3HashInit(&p->trigHash, 0);
- sqlite3HashInit(&p->aFKey, 1);
+ sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0);
+ sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0);
+ sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0);
+ sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1);
p->enc = SQLITE_UTF8;
}
return p;
@@ -62665,17 +59836,16 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
** are found, return a pointer to the last table.
*/
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
- struct SrcList_item *pItem = pSrc->a;
- Table *pTab;
- assert( pItem && pSrc->nSrc==1 );
- pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
- sqlite3DeleteTable(pItem->pTab);
- pItem->pTab = pTab;
- if( pTab ){
- pTab->nRef++;
- }
- if( sqlite3IndexedByLookup(pParse, pItem) ){
- pTab = 0;
+ Table *pTab = 0;
+ int i;
+ struct SrcList_item *pItem;
+ for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
+ pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+ sqlite3DeleteTable(pItem->pTab);
+ pItem->pTab = pTab;
+ if( pTab ){
+ pTab->nRef++;
+ }
}
return pTab;
}
@@ -62686,8 +59856,7 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
** writable return 0;
*/
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
- if( ((pTab->tabFlags & TF_Readonly)!=0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
+ if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
&& pParse->nested==0)
#ifndef SQLITE_OMIT_VIRTUALTABLE
|| (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
@@ -62734,7 +59903,7 @@ SQLITE_PRIVATE void sqlite3OpenTable(
*/
SQLITE_PRIVATE void sqlite3MaterializeView(
Parse *pParse, /* Parsing context */
- Table *pView, /* View definition */
+ Select *pView, /* View definition */
Expr *pWhere, /* Optional WHERE clause to be added */
int iCur /* Cursor number for ephemerial table */
){
@@ -62742,114 +59911,20 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
Select *pDup;
sqlite3 *db = pParse->db;
- pDup = sqlite3SelectDup(db, pView->pSelect);
+ pDup = sqlite3SelectDup(db, pView);
if( pWhere ){
SrcList *pFrom;
- Token viewName;
pWhere = sqlite3ExprDup(db, pWhere);
- viewName.z = (u8*)pView->zName;
- viewName.n = (unsigned int)strlen((const char*)viewName.z);
- pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
+ pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, 0, pDup, 0, 0);
pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
- sqlite3Select(pParse, pDup, &dest);
+ sqlite3Select(pParse, pDup, &dest, 0, 0, 0);
sqlite3SelectDelete(db, pDup);
}
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
-#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-/*
-** Generate an expression tree to implement the WHERE, ORDER BY,
-** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
-**
-** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
-** \__________________________/
-** pLimitWhere (pInClause)
-*/
-SQLITE_PRIVATE Expr *sqlite3LimitWhere(
- Parse *pParse, /* The parser context */
- SrcList *pSrc, /* the FROM clause -- which tables to scan */
- Expr *pWhere, /* The WHERE clause. May be null */
- ExprList *pOrderBy, /* The ORDER BY clause. May be null */
- Expr *pLimit, /* The LIMIT clause. May be null */
- Expr *pOffset, /* The OFFSET clause. May be null */
- char *zStmtType /* Either DELETE or UPDATE. For error messages. */
-){
- Expr *pWhereRowid = NULL; /* WHERE rowid .. */
- Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
- Expr *pSelectRowid = NULL; /* SELECT rowid ... */
- ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */
- SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */
- Select *pSelect = NULL; /* Complete SELECT tree */
-
- /* Check that there isn't an ORDER BY without a LIMIT clause.
- */
- if( pOrderBy && (pLimit == 0) ) {
- sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
- pParse->parseError = 1;
- goto limit_where_cleanup_2;
- }
-
- /* We only need to generate a select expression if there
- ** is a limit/offset term to enforce.
- */
- if( pLimit == 0 ) {
- /* if pLimit is null, pOffset will always be null as well. */
- assert( pOffset == 0 );
- return pWhere;
- }
-
- /* Generate a select expression tree to enforce the limit/offset
- ** term for the DELETE or UPDATE statement. For example:
- ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
- ** becomes:
- ** DELETE FROM table_a WHERE rowid IN (
- ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
- ** );
- */
-
- pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
- if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
- pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0);
- if( pEList == 0 ) goto limit_where_cleanup_2;
-
- /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
- ** and the SELECT subtree. */
- pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc);
- if( pSelectSrc == 0 ) {
- sqlite3ExprListDelete(pParse->db, pEList);
- goto limit_where_cleanup_2;
- }
-
- /* generate the SELECT expression tree. */
- pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,pOrderBy,0,pLimit,pOffset);
- if( pSelect == 0 ) return 0;
-
- /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
- pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
- if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
- pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
- if( pInClause == 0 ) goto limit_where_cleanup_1;
-
- pInClause->pSelect = pSelect;
- sqlite3ExprSetHeight(pParse, pInClause);
- return pInClause;
-
- /* something went wrong. clean up anything allocated. */
-limit_where_cleanup_1:
- sqlite3SelectDelete(pParse->db, pSelect);
- return 0;
-
-limit_where_cleanup_2:
- sqlite3ExprDelete(pParse->db, pWhere);
- sqlite3ExprListDelete(pParse->db, pOrderBy);
- sqlite3ExprDelete(pParse->db, pLimit);
- sqlite3ExprDelete(pParse->db, pOffset);
- return 0;
-}
-#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
/*
** Generate code for a DELETE FROM statement.
@@ -62876,8 +59951,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
NameContext sNC; /* Name context to resolve expressions in */
int iDb; /* Database number */
- int memCnt = -1; /* Memory cell used for change counting */
- int rcauth; /* Value returned by authorization callback */
+ int memCnt = 0; /* Memory cell used for change counting */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
@@ -62908,7 +59982,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
** deleted from is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
- triggers_exist = sqlite3TriggersExist(pTab, TK_DELETE, 0);
+ triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0);
isView = pTab->pSelect!=0;
#else
# define triggers_exist 0
@@ -62925,12 +59999,9 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb<db->nDb );
zDb = db->aDb[iDb].zName;
- rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
- assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
- if( rcauth==SQLITE_DENY ){
+ if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
goto delete_from_cleanup;
}
- assert(!isView || triggers_exist);
/* If pTab is really a view, make sure it has been initialized.
*/
@@ -62988,18 +60059,16 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
/* If we are trying to delete from a view, realize that view into
** a ephemeral table.
*/
-#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
- sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+ sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur);
}
-#endif
/* Resolve the column names in the WHERE clause.
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
- if( sqlite3ResolveExprNames(&sNC, pWhere) ){
+ if( sqlite3ExprResolveNames(&sNC, pWhere) ){
goto delete_from_cleanup;
}
@@ -63011,27 +60080,38 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
}
-#ifndef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Note, however, that
** this means that the row change count will be incorrect.
*/
- if( rcauth==SQLITE_OK && pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){
- assert( !isView );
- sqlite3VdbeAddOp3(v, OP_Clear, pTab->tnum, iDb, memCnt);
- if( !pParse->nested ){
- sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
+ if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){
+ if( db->flags & SQLITE_CountRows ){
+ /* If counting rows deleted, just count the total number of
+ ** entries in the table. */
+ int addr2;
+ if( !isView ){
+ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
+ }
+ sqlite3VdbeAddOp2(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);
+ addr2 = sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
+ sqlite3VdbeAddOp2(v, OP_Next, iCur, addr2);
+ sqlite3VdbeAddOp1(v, OP_Close, iCur);
}
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- assert( pIdx->pSchema==pTab->pSchema );
- sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
+ if( !isView ){
+ sqlite3VdbeAddOp2(v, OP_Clear, pTab->tnum, iDb);
+ if( !pParse->nested ){
+ sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
+ }
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ assert( pIdx->pSchema==pTab->pSchema );
+ sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
+ }
}
- }else
-#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
+ }
/* The usual case: There is a WHERE clause so we have to scan through
** the table and pick which records to delete.
*/
- {
+ else{
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
/* Begin the database scan
@@ -63144,7 +60224,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P4_STATIC);
}
delete_from_cleanup:
@@ -63300,6 +60380,7 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
** $Id$
*/
+
/*
** Return the collating function associated with a function.
*/
@@ -63341,11 +60422,10 @@ static void minmaxFunc(
*/
static void typeofFunc(
sqlite3_context *context,
- int NotUsed,
+ int argc,
sqlite3_value **argv
){
const char *z = 0;
- UNUSED_PARAMETER(NotUsed);
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_NULL: z = "null"; break;
case SQLITE_INTEGER: z = "integer"; break;
@@ -63368,7 +60448,6 @@ static void lengthFunc(
int len;
assert( argc==1 );
- UNUSED_PARAMETER(argc);
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_BLOB:
case SQLITE_INTEGER:
@@ -63399,7 +60478,6 @@ static void lengthFunc(
*/
static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
assert( argc==1 );
- UNUSED_PARAMETER(argc);
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_INTEGER: {
i64 iVal = sqlite3_value_int64(argv[0]);
@@ -63603,11 +60681,10 @@ static void ifnullFunc(
*/
static void randomFunc(
sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
+ int argc,
+ sqlite3_value **argv
){
sqlite_int64 r;
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_randomness(sizeof(r), &r);
if( (r<<1)==0 ) r = 0; /* Prevent 0x8000.... as the result so that we */
/* can always do abs() of the result */
@@ -63626,7 +60703,6 @@ static void randomBlob(
int n;
unsigned char *p;
assert( argc==1 );
- UNUSED_PARAMETER(argc);
n = sqlite3_value_int(argv[0]);
if( n<1 ){
n = 1;
@@ -63644,11 +60720,10 @@ static void randomBlob(
*/
static void last_insert_rowid(
sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
+ int arg,
+ sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
}
@@ -63658,11 +60733,10 @@ static void last_insert_rowid(
*/
static void changes(
sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
+ int arg,
+ sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_int(context, sqlite3_changes(db));
}
@@ -63672,11 +60746,10 @@ static void changes(
*/
static void total_changes(
sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
+ int arg,
+ sqlite3_value **argv
){
sqlite3 *db = sqlite3_context_db_handle(context);
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_int(context, sqlite3_total_changes(db));
}
@@ -63921,11 +60994,10 @@ static void likeFunc(
*/
static void nullifFunc(
sqlite3_context *context,
- int NotUsed,
+ int argc,
sqlite3_value **argv
){
CollSeq *pColl = sqlite3GetFuncCollSeq(context);
- UNUSED_PARAMETER(NotUsed);
if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){
sqlite3_result_value(context, argv[0]);
}
@@ -63937,10 +61009,9 @@ static void nullifFunc(
*/
static void versionFunc(
sqlite3_context *context,
- int NotUsed,
- sqlite3_value **NotUsed2
+ int argc,
+ sqlite3_value **argv
){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
}
@@ -64033,7 +61104,6 @@ static void hexFunc(
const unsigned char *pBlob;
char *zHex, *z;
assert( argc==1 );
- UNUSED_PARAMETER(argc);
pBlob = sqlite3_value_blob(argv[0]);
n = sqlite3_value_bytes(argv[0]);
assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
@@ -64059,7 +61129,6 @@ static void zeroblobFunc(
){
i64 n;
assert( argc==1 );
- UNUSED_PARAMETER(argc);
n = sqlite3_value_int64(argv[0]);
if( n>SQLITE_MAX_LENGTH ){
sqlite3_result_error_toobig(context);
@@ -64091,7 +61160,6 @@ static void replaceFunc(
int i, j; /* Loop counters */
assert( argc==3 );
- UNUSED_PARAMETER(argc);
zStr = sqlite3_value_text(argv[0]);
if( zStr==0 ) return;
nStr = sqlite3_value_bytes(argv[0]);
@@ -64170,7 +61238,7 @@ static void trimFunc(
assert( zIn==sqlite3_value_text(argv[0]) );
if( argc==1 ){
static const unsigned char lenOne[] = { 1 };
- static unsigned char * const azOne[] = { (u8*)" " };
+ static const unsigned char *azOne[] = { (u8*)" " };
nChar = 1;
aLen = (u8*)lenOne;
azChar = (unsigned char **)azOne;
@@ -64227,7 +61295,6 @@ static void trimFunc(
sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
}
-
#ifdef SQLITE_SOUNDEX
/*
** Compute the soundex encoding of a word.
@@ -64329,7 +61396,6 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
SumCtx *p;
int type;
assert( argc==1 );
- UNUSED_PARAMETER(argc);
p = sqlite3_aggregate_context(context, sizeof(*p));
type = sqlite3_value_numeric_type(argv[0]);
if( p && type!=SQLITE_NULL ){
@@ -64405,14 +61471,9 @@ static void countFinalize(sqlite3_context *context){
/*
** Routines to implement min() and max() aggregate functions.
*/
-static void minmaxStep(
- sqlite3_context *context,
- int NotUsed,
- sqlite3_value **argv
-){
+static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv){
Mem *pArg = (Mem *)argv[0];
Mem *pBest;
- UNUSED_PARAMETER(NotUsed);
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest));
@@ -64509,9 +61570,108 @@ static void groupConcatFinalize(sqlite3_context *context){
** external linkage.
*/
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
+ static const struct {
+ char *zName;
+ signed char nArg;
+ u8 argType; /* 1: 0, 2: 1, 3: 2,... N: N-1. */
+ u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */
+ u8 needCollSeq;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
+ } aFuncs[] = {
+ { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc },
+ { "min", 0, 0, SQLITE_UTF8, 1, 0 },
+ { "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc },
+ { "max", 0, 1, SQLITE_UTF8, 1, 0 },
+ { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc },
+ { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc },
+ { "substr", 2, 0, SQLITE_UTF8, 0, substrFunc },
+ { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc },
+ { "abs", 1, 0, SQLITE_UTF8, 0, absFunc },
+ { "round", 1, 0, SQLITE_UTF8, 0, roundFunc },
+ { "round", 2, 0, SQLITE_UTF8, 0, roundFunc },
+ { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc },
+ { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc },
+ { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc },
+ { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 },
+ { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 },
+ { "hex", 1, 0, SQLITE_UTF8, 0, hexFunc },
+ { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
+ { "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
+ { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob },
+ { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
+ { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
+ { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
+ { "last_insert_rowid", 0, 0, SQLITE_UTF8, 0, last_insert_rowid },
+ { "changes", 0, 0, SQLITE_UTF8, 0, changes },
+ { "total_changes", 0, 0, SQLITE_UTF8, 0, total_changes },
+ { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc },
+ { "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc },
+ { "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc },
+ { "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc },
+ { "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc },
+ { "trim", 1, 3, SQLITE_UTF8, 0, trimFunc },
+ { "trim", 2, 3, SQLITE_UTF8, 0, trimFunc },
+ { "zeroblob", 1, 0, SQLITE_UTF8, 0, zeroblobFunc },
+#ifdef SQLITE_SOUNDEX
+ { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
+#endif
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ { "load_extension", 1, 0, SQLITE_UTF8, 0, loadExt },
+ { "load_extension", 2, 0, SQLITE_UTF8, 0, loadExt },
+#endif
+ };
+ static const struct {
+ char *zName;
+ signed char nArg;
+ u8 argType;
+ u8 needCollSeq;
+ void (*xStep)(sqlite3_context*,int,sqlite3_value**);
+ void (*xFinalize)(sqlite3_context*);
+ } aAggs[] = {
+ { "min", 1, 0, 1, minmaxStep, minMaxFinalize },
+ { "max", 1, 1, 1, minmaxStep, minMaxFinalize },
+ { "sum", 1, 0, 0, sumStep, sumFinalize },
+ { "total", 1, 0, 0, sumStep, totalFinalize },
+ { "avg", 1, 0, 0, sumStep, avgFinalize },
+ { "count", 0, 0, 0, countStep, countFinalize },
+ { "count", 1, 0, 0, countStep, countFinalize },
+ { "group_concat", -1, 0, 0, groupConcatStep, groupConcatFinalize },
+ };
+ int i;
+
+ for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+ void *pArg;
+ u8 argType = aFuncs[i].argType;
+ pArg = SQLITE_INT_TO_PTR(argType);
+ sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
+ aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
+ if( aFuncs[i].needCollSeq ){
+ FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName,
+ strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0);
+ if( pFunc && aFuncs[i].needCollSeq ){
+ pFunc->needCollSeq = 1;
+ }
+ }
+ }
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions(db);
#endif
+#ifndef SQLITE_OMIT_PARSER
+ sqlite3AttachFunctions(db);
+#endif
+ for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
+ void *pArg = SQLITE_INT_TO_PTR(aAggs[i].argType);
+ sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
+ pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
+ if( aAggs[i].needCollSeq ){
+ FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName,
+ strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0);
+ if( pFunc && aAggs[i].needCollSeq ){
+ pFunc->needCollSeq = 1;
+ }
+ }
+ }
+ sqlite3RegisterDateTimeFunctions(db);
if( !db->mallocFailed ){
int rc = sqlite3_overload_function(db, "MATCH", 2);
assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
@@ -64522,6 +61682,11 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
#ifdef SQLITE_SSE
(void)sqlite3SseFunctions(db);
#endif
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
+ sqlite3RegisterLikeFunctions(db, 1);
+#else
+ sqlite3RegisterLikeFunctions(db, 0);
+#endif
}
/*
@@ -64589,93 +61754,6 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas
return 1;
}
-/*
-** All all of the FuncDef structures in the aBuiltinFunc[] array above
-** to the global function hash table. This occurs at start-time (as
-** a consequence of calling sqlite3_initialize()).
-**
-** After this routine runs
-*/
-SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
- /*
- ** The following array holds FuncDef structures for all of the functions
- ** defined in this file.
- **
- ** The array cannot be constant since changes are made to the
- ** FuncDef.pHash elements at start-time. The elements of this array
- ** are read-only after initialization is complete.
- */
- static SQLITE_WSD FuncDef aBuiltinFunc[] = {
- FUNCTION(ltrim, 1, 1, 0, trimFunc ),
- FUNCTION(ltrim, 2, 1, 0, trimFunc ),
- FUNCTION(rtrim, 1, 2, 0, trimFunc ),
- FUNCTION(rtrim, 2, 2, 0, trimFunc ),
- FUNCTION(trim, 1, 3, 0, trimFunc ),
- FUNCTION(trim, 2, 3, 0, trimFunc ),
- FUNCTION(min, -1, 0, 1, minmaxFunc ),
- FUNCTION(min, 0, 0, 1, 0 ),
- AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
- FUNCTION(max, -1, 1, 1, minmaxFunc ),
- FUNCTION(max, 0, 1, 1, 0 ),
- AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
- FUNCTION(typeof, 1, 0, 0, typeofFunc ),
- FUNCTION(length, 1, 0, 0, lengthFunc ),
- FUNCTION(substr, 2, 0, 0, substrFunc ),
- FUNCTION(substr, 3, 0, 0, substrFunc ),
- FUNCTION(abs, 1, 0, 0, absFunc ),
- FUNCTION(round, 1, 0, 0, roundFunc ),
- FUNCTION(round, 2, 0, 0, roundFunc ),
- FUNCTION(upper, 1, 0, 0, upperFunc ),
- FUNCTION(lower, 1, 0, 0, lowerFunc ),
- FUNCTION(coalesce, 1, 0, 0, 0 ),
- FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
- FUNCTION(coalesce, 0, 0, 0, 0 ),
- FUNCTION(hex, 1, 0, 0, hexFunc ),
- FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
- FUNCTION(random, -1, 0, 0, randomFunc ),
- FUNCTION(randomblob, 1, 0, 0, randomBlob ),
- FUNCTION(nullif, 2, 0, 1, nullifFunc ),
- FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
- FUNCTION(quote, 1, 0, 0, quoteFunc ),
- FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
- FUNCTION(changes, 0, 0, 0, changes ),
- FUNCTION(total_changes, 0, 0, 0, total_changes ),
- FUNCTION(replace, 3, 0, 0, replaceFunc ),
- FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
- #ifdef SQLITE_SOUNDEX
- FUNCTION(soundex, 1, 0, 0, soundexFunc ),
- #endif
- #ifndef SQLITE_OMIT_LOAD_EXTENSION
- FUNCTION(load_extension, 1, 0, 0, loadExt ),
- FUNCTION(load_extension, 2, 0, 0, loadExt ),
- #endif
- AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
- AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
- AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
- AGGREGATE(count, 0, 0, 0, countStep, countFinalize ),
- AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
- AGGREGATE(group_concat, -1, 0, 0, groupConcatStep, groupConcatFinalize),
-
- LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
- #ifdef SQLITE_CASE_SENSITIVE_LIKE
- LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
- LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
- #else
- LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
- LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
- #endif
- };
-
- int i;
- FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
- FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);
-
- for(i=0; i<ArraySize(aBuiltinFunc); i++){
- sqlite3FuncDefInsert(pHash, &aFunc[i]);
- }
- sqlite3RegisterDateTimeFunctions();
-}
-
/************** End of func.c ************************************************/
/************** Begin file insert.c ******************************************/
/*
@@ -64844,7 +61922,7 @@ static int autoIncBegin(
Table *pTab /* The table we are writing to */
){
int memId = 0; /* Register holding maximum rowid */
- if( pTab->tabFlags & TF_Autoincrement ){
+ if( pTab->autoInc ){
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int iCur = pParse->nTab;
@@ -64895,7 +61973,7 @@ static void autoIncEnd(
Table *pTab, /* Table we are inserting into */
int memId /* Memory cell holding the maximum rowid */
){
- if( pTab->tabFlags & TF_Autoincrement ){
+ if( pTab->autoInc ){
int iCur = pParse->nTab;
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
@@ -65109,7 +62187,7 @@ SQLITE_PRIVATE void sqlite3Insert(
** inserted into is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
- triggers_exist = sqlite3TriggersExist(pTab, TK_INSERT, 0);
+ triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0);
isView = pTab->pSelect!=0;
#else
# define triggers_exist 0
@@ -65211,7 +62289,7 @@ SQLITE_PRIVATE void sqlite3Insert(
VdbeComment((v, "Jump over SELECT coroutine"));
/* Resolve the expressions in the SELECT statement and execute it. */
- rc = sqlite3Select(pParse, pSelect, &dest);
+ rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
if( rc || pParse->nErr || db->mallocFailed ){
goto insert_cleanup;
}
@@ -65281,7 +62359,7 @@ SQLITE_PRIVATE void sqlite3Insert(
assert( useTempTable==0 );
nColumn = pList ? pList->nExpr : 0;
for(i=0; i<nColumn; i++){
- if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
+ if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){
goto insert_cleanup;
}
}
@@ -65615,6 +62693,7 @@ SQLITE_PRIVATE void sqlite3Insert(
regIns,
aRegIdx,
0,
+ 0,
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,
appendFlag
);
@@ -65670,7 +62749,7 @@ SQLITE_PRIVATE void sqlite3Insert(
if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P4_STATIC);
}
insert_cleanup:
@@ -65950,26 +63029,26 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
case OE_Fail: {
int j, n1, n2;
char zErrMsg[200];
- sqlite3_snprintf(ArraySize(zErrMsg), zErrMsg,
+ sqlite3_snprintf(sizeof(zErrMsg), zErrMsg,
pIdx->nColumn>1 ? "columns " : "column ");
n1 = strlen(zErrMsg);
- for(j=0; j<pIdx->nColumn && n1<ArraySize(zErrMsg)-30; j++){
+ for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
n2 = strlen(zCol);
if( j>0 ){
- sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], ", ");
+ sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], ", ");
n1 += 2;
}
- if( n1+n2>ArraySize(zErrMsg)-30 ){
- sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], "...");
+ if( n1+n2>sizeof(zErrMsg)-30 ){
+ sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "...");
n1 += 3;
break;
}else{
- sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol);
+ sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol);
n1 += n2;
}
}
- sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1],
+ sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1],
pIdx->nColumn>1 ? " are not unique" : " is not unique");
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErrMsg,0);
break;
@@ -66006,6 +63085,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
int baseCur, /* Index of a read/write cursor pointing at pTab */
int regRowid, /* Range of content */
int *aRegIdx, /* Register used by each index. 0 for unused indices */
+ int rowidChng, /* True if the record number will change */
int isUpdate, /* True for UPDATE, False for INSERT */
int newIdx, /* Index of NEW table for triggers. -1 if none */
int appendBias /* True if this is likely to be an append */
@@ -66062,7 +63142,7 @@ SQLITE_PRIVATE void sqlite3CompleteInsertion(
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(
Parse *pParse, /* Parsing context */
Table *pTab, /* Table to be opened */
- int baseCur, /* Cursor number assigned to the table */
+ int baseCur, /* Cursor number assigned to the table */
int op /* OP_OpenRead or OP_OpenWrite */
){
int i;
@@ -66212,7 +63292,7 @@ static int xferOptimization(
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pDest->tabFlags & TF_Virtual ){
+ if( pDest->isVirtual ){
return 0; /* tab1 must not be a virtual table */
}
#endif
@@ -66247,7 +63327,7 @@ static int xferOptimization(
if( pSelect->pPrior ){
return 0; /* SELECT may not be a compound query */
}
- if( pSelect->selFlags & SF_Distinct ){
+ if( pSelect->isDistinct ){
return 0; /* SELECT may not be DISTINCT */
}
pEList = pSelect->pEList;
@@ -66273,7 +63353,7 @@ static int xferOptimization(
return 0; /* tab1 and tab2 may not be the same table */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pSrc->tabFlags & TF_Virtual ){
+ if( pSrc->isVirtual ){
return 0; /* tab2 must not be a virtual table */
}
#endif
@@ -66364,7 +63444,7 @@ static int xferOptimization(
addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
}else{
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- assert( (pDest->tabFlags & TF_Autoincrement)==0 );
+ assert( pDest->autoInc==0 );
}
sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
@@ -66794,9 +63874,7 @@ struct sqlite3_api_routines {
*/
#ifndef SQLITE_CORE
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
-#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
-#endif
#define sqlite3_bind_blob sqlite3_api->bind_blob
#define sqlite3_bind_double sqlite3_api->bind_double
#define sqlite3_bind_int sqlite3_api->bind_int
@@ -66852,18 +63930,14 @@ struct sqlite3_api_routines {
#define sqlite3_errmsg sqlite3_api->errmsg
#define sqlite3_errmsg16 sqlite3_api->errmsg16
#define sqlite3_exec sqlite3_api->exec
-#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_expired sqlite3_api->expired
-#endif
#define sqlite3_finalize sqlite3_api->finalize
#define sqlite3_free sqlite3_api->free
#define sqlite3_free_table sqlite3_api->free_table
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
#define sqlite3_get_table sqlite3_api->get_table
-#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_global_recover sqlite3_api->global_recover
-#endif
#define sqlite3_interrupt sqlite3_api->interruptx
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
#define sqlite3_libversion sqlite3_api->libversion
@@ -66901,9 +63975,7 @@ struct sqlite3_api_routines {
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
#define sqlite3_total_changes sqlite3_api->total_changes
#define sqlite3_trace sqlite3_api->trace
-#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
-#endif
#define sqlite3_update_hook sqlite3_api->update_hook
#define sqlite3_user_data sqlite3_api->user_data
#define sqlite3_value_blob sqlite3_api->value_blob
@@ -67069,11 +64141,7 @@ struct sqlite3_api_routines {
*/
static const sqlite3_api_routines sqlite3Apis = {
sqlite3_aggregate_context,
-#ifndef SQLITE_OMIT_DEPRECATED
sqlite3_aggregate_count,
-#else
- 0,
-#endif
sqlite3_bind_blob,
sqlite3_bind_double,
sqlite3_bind_int,
@@ -67128,11 +64196,7 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_errmsg,
sqlite3_errmsg16,
sqlite3_exec,
-#ifndef SQLITE_OMIT_DEPRECATED
sqlite3_expired,
-#else
- 0,
-#endif
sqlite3_finalize,
sqlite3_free,
sqlite3_free_table,
@@ -67172,18 +64236,10 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_snprintf,
sqlite3_step,
sqlite3_table_column_metadata,
-#ifndef SQLITE_OMIT_DEPRECATED
sqlite3_thread_cleanup,
-#else
- 0,
-#endif
sqlite3_total_changes,
sqlite3_trace,
-#ifndef SQLITE_OMIT_DEPRECATED
sqlite3_transfer_bindings,
-#else
- 0,
-#endif
sqlite3_update_hook,
sqlite3_user_data,
sqlite3_value_blob,
@@ -67234,7 +64290,7 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_file_control,
sqlite3_memory_highwater,
sqlite3_memory_used,
-#ifdef SQLITE_MUTEX_OMIT
+#ifdef SQLITE_MUTEX_NOOP
0,
0,
0,
@@ -67427,26 +64483,10 @@ static const sqlite3_api_routines sqlite3Apis = { 0 };
** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER
** mutex must be held while accessing this list.
*/
-typedef struct sqlite3ExtType sqlite3ExtType;
-static SQLITE_WSD struct sqlite3ExtType {
+static struct {
int nExt; /* Number of entries in aExt[] */
void **aExt; /* Pointers to the extension init functions */
-} sqlite3Autoext = { 0, 0 };
-
-/* The "wsdAutoext" macro will resolve to the autoextension
-** state vector. If writable static data is unsupported on the target,
-** we have to locate the state vector at run-time. In the more common
-** case where writable static data is supported, wsdStat can refer directly
-** to the "sqlite3Autoext" state vector declared above.
-*/
-#ifdef SQLITE_OMIT_WSD
-# define wsdAutoextInit \
- sqlite3ExtType *x = &GLOBAL(sqlite3ExtType,sqlite3Autoext)
-# define wsdAutoext x[0]
-#else
-# define wsdAutoextInit
-# define wsdAutoext sqlite3Autoext
-#endif
+} autoext = { 0, 0 };
/*
@@ -67463,24 +64503,23 @@ SQLITE_API int sqlite3_auto_extension(void *xInit){
#endif
{
int i;
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
- wsdAutoextInit;
sqlite3_mutex_enter(mutex);
- for(i=0; i<wsdAutoext.nExt; i++){
- if( wsdAutoext.aExt[i]==xInit ) break;
+ for(i=0; i<autoext.nExt; i++){
+ if( autoext.aExt[i]==xInit ) break;
}
- if( i==wsdAutoext.nExt ){
- int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
+ if( i==autoext.nExt ){
+ int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);
void **aNew;
- aNew = sqlite3_realloc(wsdAutoext.aExt, nByte);
+ aNew = sqlite3_realloc(autoext.aExt, nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
- wsdAutoext.aExt = aNew;
- wsdAutoext.aExt[wsdAutoext.nExt] = xInit;
- wsdAutoext.nExt++;
+ autoext.aExt = aNew;
+ autoext.aExt[autoext.nExt] = xInit;
+ autoext.nExt++;
}
}
sqlite3_mutex_leave(mutex);
@@ -67497,14 +64536,13 @@ SQLITE_API void sqlite3_reset_auto_extension(void){
if( sqlite3_initialize()==SQLITE_OK )
#endif
{
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
- wsdAutoextInit;
sqlite3_mutex_enter(mutex);
- sqlite3_free(wsdAutoext.aExt);
- wsdAutoext.aExt = 0;
- wsdAutoext.nExt = 0;
+ sqlite3_free(autoext.aExt);
+ autoext.aExt = 0;
+ autoext.nExt = 0;
sqlite3_mutex_leave(mutex);
}
}
@@ -67518,23 +64556,22 @@ SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3 *db){
int rc = SQLITE_OK;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
- wsdAutoextInit;
- if( wsdAutoext.nExt==0 ){
+ if( autoext.nExt==0 ){
/* Common case: early out without every having to acquire a mutex */
return SQLITE_OK;
}
for(i=0; go; i++){
char *zErrmsg = 0;
-#if SQLITE_THREADSAFE
+#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
sqlite3_mutex_enter(mutex);
- if( i>=wsdAutoext.nExt ){
+ if( i>=autoext.nExt ){
xInit = 0;
go = 0;
}else{
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
- wsdAutoext.aExt[i];
+ autoext.aExt[i];
}
sqlite3_mutex_leave(mutex);
if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){
@@ -67591,7 +64628,7 @@ static int getSafetyLevel(const char *z){
return atoi(z);
}
n = strlen(z);
- for(i=0; i<ArraySize(iLength); i++){
+ for(i=0; i<sizeof(iLength); i++){
if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){
return iValue[i];
}
@@ -67701,7 +64738,7 @@ static void returnSingleInt(Parse *pParse, const char *zLabel, int value){
sqlite3VdbeAddOp2(v, OP_Integer, value, mem);
if( pParse->explain==0 ){
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P4_STATIC);
}
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
}
@@ -67741,7 +64778,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
};
int i;
const struct sPragmaType *p;
- for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){
+ for(i=0, p=aPragma; i<sizeof(aPragma)/sizeof(aPragma[0]); i++, p++){
if( sqlite3StrICmp(zLeft, p->zName)==0 ){
sqlite3 *db = pParse->db;
Vdbe *v;
@@ -67771,16 +64808,6 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
}
#endif /* SQLITE_OMIT_FLAG_PRAGMAS */
-static const char *actionName(u8 action){
- switch( action ){
- case OE_SetNull: return "SET NULL";
- case OE_SetDflt: return "SET DEFAULT";
- case OE_Restrict: return "RESTRICT";
- case OE_Cascade: return "CASCADE";
- }
- return "";
-}
-
/*
** Process a pragma statement.
**
@@ -67835,7 +64862,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
zRight = sqlite3NameFromToken(db, pValue);
}
- zDb = ((pId2 && pId2->n>0)?pDb->zName:0);
+ zDb = ((iDb>0)?pDb->zName:0);
if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
goto pragma_out;
}
@@ -67872,7 +64899,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeUsesBtree(v, iDb);
if( !zRight ){
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P4_STATIC);
pParse->nMem += 2;
addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
sqlite3VdbeChangeP1(v, addr, iDb);
@@ -67953,7 +64980,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "page_count", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "page_count", P4_STATIC);
}else
/*
@@ -67998,26 +65025,24 @@ SQLITE_PRIVATE void sqlite3Pragma(
zRet = "exclusive";
}
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P4_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}else
/*
** PRAGMA [database.]journal_mode
- ** PRAGMA [database.]journal_mode = (delete|persist|off|truncate|memory)
+ ** PRAGMA [database.]journal_mode = (delete|persist|off)
*/
if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){
int eMode;
- static char * const azModeName[] = {
- "delete", "persist", "off", "truncate", "memory"
- };
+ static const char *azModeName[] = {"delete", "persist", "off"};
if( zRight==0 ){
eMode = PAGER_JOURNALMODE_QUERY;
}else{
int n = strlen(zRight);
- eMode = sizeof(azModeName)/sizeof(azModeName[0]) - 1;
+ eMode = 2;
while( eMode>=0 && sqlite3StrNICmp(zRight, azModeName[eMode], n)!=0 ){
eMode--;
}
@@ -68053,12 +65078,10 @@ SQLITE_PRIVATE void sqlite3Pragma(
eMode = sqlite3PagerJournalMode(pPager, eMode);
}
assert( eMode==PAGER_JOURNALMODE_DELETE
- || eMode==PAGER_JOURNALMODE_TRUNCATE
|| eMode==PAGER_JOURNALMODE_PERSIST
- || eMode==PAGER_JOURNALMODE_OFF
- || eMode==PAGER_JOURNALMODE_MEMORY );
+ || eMode==PAGER_JOURNALMODE_OFF );
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", P4_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0,
azModeName[eMode], P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
@@ -68225,17 +65248,15 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( sqlite3_temp_directory ){
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
- "temp_store_directory", SQLITE_STATIC);
+ "temp_store_directory", P4_STATIC);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
}
}else{
-#ifndef SQLITE_OMIT_WSD
if( zRight[0] ){
- int rc;
int res;
- rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
- if( rc!=SQLITE_OK || res==0 ){
+ sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
+ if( res==0 ){
sqlite3ErrorMsg(pParse, "not a writable directory");
goto pragma_out;
}
@@ -68252,7 +65273,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else{
sqlite3_temp_directory = 0;
}
-#endif /* SQLITE_OMIT_WSD */
}
}else
@@ -68310,12 +65330,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
Column *pCol;
sqlite3VdbeSetNumCols(v, 6);
pParse->nMem = 6;
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P4_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P4_STATIC);
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P4_STATIC);
+ sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P4_STATIC);
+ sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P4_STATIC);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const Token *pDflt;
@@ -68327,7 +65347,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
pCol->zType ? pCol->zType : "", 0);
- sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4);
+ sqlite3VdbeAddOp2(v, OP_Integer, pCol->notNull, 4);
if( pCol->pDflt && (pDflt = &pCol->pDflt->span)->z ){
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pDflt->z, pDflt->n);
}else{
@@ -68349,9 +65369,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
pTab = pIdx->pTable;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P4_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P4_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P4_STATIC);
for(i=0; i<pIdx->nColumn; i++){
int cnum = pIdx->aiColumn[i];
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
@@ -68375,9 +65395,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i = 0;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P4_STATIC);
while(pIdx){
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
@@ -68395,9 +65415,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P4_STATIC);
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt==0 ) continue;
assert( db->aDb[i].zName!=0 );
@@ -68414,8 +65434,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
HashElem *p;
sqlite3VdbeSetNumCols(v, 2);
pParse->nMem = 2;
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC);
for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
CollSeq *pColl = (CollSeq *)sqliteHashData(p);
sqlite3VdbeAddOp2(v, OP_Integer, i++, 1);
@@ -68436,32 +65456,24 @@ SQLITE_PRIVATE void sqlite3Pragma(
pFK = pTab->pFKey;
if( pFK ){
int i = 0;
- sqlite3VdbeSetNumCols(v, 8);
- pParse->nMem = 8;
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 7, COLNAME_NAME, "match", SQLITE_STATIC);
+ sqlite3VdbeSetNumCols(v, 5);
+ pParse->nMem = 5;
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P4_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P4_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P4_STATIC);
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P4_STATIC);
+ sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P4_STATIC);
while(pFK){
int j;
for(j=0; j<pFK->nCol; j++){
char *zCol = pFK->aCol[j].zCol;
- char *zOnUpdate = (char *)actionName(pFK->updateConf);
- char *zOnDelete = (char *)actionName(pFK->deleteConf);
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
sqlite3VdbeAddOp2(v, OP_Integer, j, 2);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0);
sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
sqlite3VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 6, 0, zOnUpdate, 0);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 7, 0, zOnDelete, 0);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 8, 0, "NONE", 0);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 8);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
}
++i;
pFK = pFK->pNextFrom;
@@ -68523,7 +65535,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
pParse->nMem = 6;
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P4_STATIC);
/* Set the maximum error count */
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
@@ -68702,7 +65714,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( !zRight ){ /* "PRAGMA encoding" */
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P4_STATIC);
sqlite3VdbeAddOp2(v, OP_String8, 0, 1);
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
if( pEnc->enc==ENC(pParse->db) ){
@@ -68765,6 +65777,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
|| sqlite3StrICmp(zLeft, "user_version")==0
|| sqlite3StrICmp(zLeft, "freelist_count")==0
){
+
int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
switch( zLeft[0] ){
@@ -68803,7 +65816,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeChangeP1(v, addr, iDb);
sqlite3VdbeChangeP3(v, addr, iCookie);
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P4_TRANSIENT);
}
}else
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
@@ -68820,8 +65833,8 @@ SQLITE_PRIVATE void sqlite3Pragma(
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3VdbeSetNumCols(v, 2);
pParse->nMem = 2;
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC);
- sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P4_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P4_STATIC);
for(i=0; i<db->nDb; i++){
Btree *pBt;
Pager *pPager;
@@ -68839,7 +65852,6 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
-
}else
#endif
@@ -68932,8 +65944,7 @@ static void corruptSchema(
const char *zObj, /* Object being parsed at the point of error */
const char *zExtra /* Error information */
){
- sqlite3 *db = pData->db;
- if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
+ if( !pData->db->mallocFailed ){
if( zObj==0 ) zObj = "?";
sqlite3SetString(pData->pzErrMsg, pData->db,
"malformed database schema (%s)", zObj);
@@ -68957,25 +65968,27 @@ static void corruptSchema(
** argv[2] = SQL text for the CREATE statement.
**
*/
-SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
+SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
sqlite3 *db = pData->db;
int iDb = pData->iDb;
- assert( argc==3 );
- UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlite3_mutex_held(db->mutex) );
+ pData->rc = SQLITE_OK;
DbClearProperty(db, iDb, DB_Empty);
if( db->mallocFailed ){
corruptSchema(pData, argv[0], 0);
return SQLITE_NOMEM;
}
- assert( iDb>=0 && iDb<db->nDb );
+ assert( argc==3 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 ){
corruptSchema(pData, argv[0], 0);
- }else if( argv[2] && argv[2][0] ){
+ return 1;
+ }
+ assert( iDb>=0 && iDb<db->nDb );
+ if( argv[2] && argv[2][0] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
@@ -69001,6 +66014,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
corruptSchema(pData, argv[0], zErr);
}
sqlite3DbFree(db, zErr);
+ return 1;
}
}else if( argv[0]==0 ){
corruptSchema(pData, 0, 0);
@@ -69096,18 +66110,17 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
azArg[3] = 0;
initData.db = db;
initData.iDb = iDb;
- initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
(void)sqlite3SafetyOff(db);
- sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
+ rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
(void)sqlite3SafetyOn(db);
- if( initData.rc ){
+ if( rc ){
rc = initData.rc;
goto error_out;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
- pTab->tabFlags |= TF_Readonly;
+ pTab->readOnly = 1;
}
/* Create a cursor to hold the database open
@@ -69150,7 +66163,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
*/
if( rc==SQLITE_OK ){
int i;
- for(i=0; i<ArraySize(meta); i++){
+ for(i=0; i<sizeof(meta)/sizeof(meta[0]); i++){
rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
if( rc ){
sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
@@ -69242,7 +66255,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
db->xAuth = xAuth;
}
#endif
- if( rc==SQLITE_OK ) rc = initData.rc;
+ if( rc==SQLITE_ABORT ) rc = initData.rc;
(void)sqlite3SafetyOn(db);
sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
@@ -69507,19 +66520,19 @@ static int sqlite3Prepare(
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
if( sParse.explain==2 ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 3);
- sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", SQLITE_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P4_STATIC);
}else{
sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
- sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 5, COLNAME_NAME, "p4", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 6, COLNAME_NAME, "p5", SQLITE_STATIC);
- sqlite3VdbeSetColName(sParse.pVdbe, 7, COLNAME_NAME, "comment", SQLITE_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 5, COLNAME_NAME, "p4", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 6, COLNAME_NAME, "p5", P4_STATIC);
+ sqlite3VdbeSetColName(sParse.pVdbe, 7, COLNAME_NAME, "comment",P4_STATIC);
}
}
#endif
@@ -69596,7 +66609,7 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){
assert( pNew!=0 );
}
sqlite3VdbeSwap((Vdbe*)pNew, p);
- sqlite3TransferBindings(pNew, (sqlite3_stmt*)p);
+ sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p);
sqlite3VdbeResetStepResult((Vdbe*)pNew);
sqlite3VdbeFinalize((Vdbe*)pNew);
return 1;
@@ -69784,7 +66797,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
Select standin;
sqlite3 *db = pParse->db;
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
- assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */
+ assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */
if( pNew==0 ){
pNew = &standin;
memset(pNew, 0, sizeof(*pNew));
@@ -69798,16 +66811,16 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy;
- pNew->selFlags = isDistinct ? SF_Distinct : 0;
+ pNew->isDistinct = isDistinct;
pNew->op = TK_SELECT;
+ assert( pOffset==0 || pLimit!=0 );
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
- if( db->mallocFailed ) {
+ if( pNew==&standin) {
clearSelect(db, pNew);
- if( pNew!=&standin ) sqlite3DbFree(db, pNew);
pNew = 0;
}
return pNew;
@@ -69863,14 +66876,14 @@ SQLITE_PRIVATE int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *p
apAll[2] = pC;
for(i=0; i<3 && apAll[i]; i++){
p = apAll[i];
- for(j=0; j<ArraySize(keywords); j++){
+ for(j=0; j<sizeof(keywords)/sizeof(keywords[0]); j++){
if( p->n==keywords[j].nChar
&& sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){
jointype |= keywords[j].code;
break;
}
}
- if( j>=ArraySize(keywords) ){
+ if( j>=sizeof(keywords)/sizeof(keywords[0]) ){
jointype |= JT_ERROR;
break;
}
@@ -69922,17 +66935,15 @@ static void setToken(Token *p, const char *z){
*/
static void setQuotedToken(Parse *pParse, Token *p, const char *z){
- /* Check if the string appears to be quoted using "..." or `...`
- ** or [...] or '...' or if the string contains any " characters.
- ** If it does, then record a version of the string with the special
- ** characters escaped.
+ /* Check if the string contains any " characters. If it does, then
+ ** this function will malloc space to create a quoted version of
+ ** the string in. Otherwise, save a call to sqlite3MPrintf() by
+ ** just copying the pointer to the string.
*/
const char *z2 = z;
- if( *z2!='[' && *z2!='`' && *z2!='\'' ){
- while( *z2 ){
- if( *z2=='"' ) break;
- z2++;
- }
+ while( *z2 ){
+ if( *z2=='"' ) break;
+ z2++;
}
if( *z2 ){
@@ -70294,7 +67305,7 @@ static void selectInnerLoop(
/* If the destination is an EXISTS(...) expression, the actual
** values returned by the SELECT are not required.
*/
- sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
+ sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback);
}
nColumn = nResultCol;
@@ -70411,7 +67422,7 @@ static void selectInnerLoop(
** popping the data from the stack.
*/
case SRT_Coroutine:
- case SRT_Output: {
+ case SRT_Callback: {
if( pOrderBy ){
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
@@ -70518,10 +67529,10 @@ static void generateSortTail(
int regRowid;
iTab = pOrderBy->iECursor;
- if( eDest==SRT_Output || eDest==SRT_Coroutine ){
+ if( eDest==SRT_Callback || eDest==SRT_Coroutine ){
pseudoTab = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn);
- sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Output);
+ sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback);
}
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
codeOffset(v, p, cont);
@@ -70551,7 +67562,7 @@ static void generateSortTail(
break;
}
#endif
- case SRT_Output:
+ case SRT_Callback:
case SRT_Coroutine: {
int i;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid);
@@ -70560,7 +67571,7 @@ static void generateSortTail(
assert( regRow!=pDest->iMem+i );
sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
}
- if( eDest==SRT_Output ){
+ if( eDest==SRT_Callback ){
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
}else{
@@ -70585,7 +67596,7 @@ static void generateSortTail(
sqlite3VdbeResolveLabel(v, cont);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
sqlite3VdbeResolveLabel(v, brk);
- if( eDest==SRT_Output || eDest==SRT_Coroutine ){
+ if( eDest==SRT_Callback || eDest==SRT_Coroutine ){
sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
}
@@ -70752,13 +67763,13 @@ static void generateColumnTypes(
** column specific strings, in case the schema is reset before this
** virtual machine is deleted.
*/
- sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT);
- sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
- sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
+ sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P4_TRANSIENT);
+ sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P4_TRANSIENT);
+ sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P4_TRANSIENT);
#else
zType = columnType(&sNC, p, 0, 0, 0);
#endif
- sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
+ sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT);
}
#endif /* SQLITE_OMIT_DECLTYPE */
}
@@ -70797,8 +67808,8 @@ static void generateColumnNames(
if( p==0 ) continue;
if( pEList->a[i].zName ){
char *zName = pEList->a[i].zName;
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
- }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName));
+ }else if( p->op==TK_COLUMN && pTabList ){
Table *pTab;
char *zCol;
int iCol = p->iColumn;
@@ -70813,8 +67824,7 @@ static void generateColumnNames(
zCol = pTab->aCol[iCol].zName;
}
if( !shortNames && !fullNames ){
- sqlite3VdbeSetColName(v, i, COLNAME_NAME,
- sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC);
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);
}else if( fullNames || (!shortNames && pTabList->nSrc>1) ){
char *zName = 0;
char *zTab;
@@ -70822,13 +67832,12 @@ static void generateColumnNames(
zTab = pTabList->a[j].zAlias;
if( fullNames || zTab==0 ) zTab = pTab->zName;
zName = sqlite3MPrintf(db, "%s.%s", zTab, zCol);
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P4_DYNAMIC);
}else{
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol));
}
}else{
- sqlite3VdbeSetColName(v, i, COLNAME_NAME,
- sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC);
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);
}
}
generateColumnTypes(pParse, pTabList, pEList);
@@ -70851,36 +67860,58 @@ static const char *selectOpName(int id){
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
/*
-** Given a an expression list (which is really the list of expressions
-** that form the result set of a SELECT statement) compute appropriate
-** column names for a table that would hold the expression list.
-**
-** All column names will be unique.
-**
-** Only the column names are computed. Column.zType, Column.zColl,
-** and other fields of Column are zeroed.
-**
-** Return SQLITE_OK on success. If a memory allocation error occurs,
-** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
+** Forward declaration
*/
-static int selectColumnsFromExprList(
- Parse *pParse, /* Parsing context */
- ExprList *pEList, /* Expr list from which to derive column names */
- int *pnCol, /* Write the number of columns here */
- Column **paCol /* Write the new column list here */
-){
- sqlite3 *db = pParse->db;
- int i, j, cnt;
+static int prepSelectStmt(Parse*, Select*);
+
+/*
+** Given a SELECT statement, generate a Table structure that describes
+** the result set of that SELECT.
+*/
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
+ Table *pTab;
+ int i, j, rc;
+ ExprList *pEList;
Column *aCol, *pCol;
- int nCol;
- Expr *p;
- char *zName;
- int nName;
+ sqlite3 *db = pParse->db;
+ int savedFlags;
- *pnCol = nCol = pEList->nExpr;
- aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
- if( aCol==0 ) return SQLITE_NOMEM;
- for(i=0, pCol=aCol; i<nCol; i++, pCol++){
+ savedFlags = db->flags;
+ db->flags &= ~SQLITE_FullColNames;
+ db->flags |= SQLITE_ShortColNames;
+ rc = sqlite3SelectResolve(pParse, pSelect, 0);
+ if( rc==SQLITE_OK ){
+ while( pSelect->pPrior ) pSelect = pSelect->pPrior;
+ rc = prepSelectStmt(pParse, pSelect);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3SelectResolve(pParse, pSelect, 0);
+ }
+ }
+ db->flags = savedFlags;
+ if( rc ){
+ return 0;
+ }
+ pTab = sqlite3DbMallocZero(db, sizeof(Table) );
+ if( pTab==0 ){
+ return 0;
+ }
+ pTab->db = db;
+ pTab->nRef = 1;
+ pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
+ pEList = pSelect->pEList;
+ pTab->nCol = pEList->nExpr;
+ assert( pTab->nCol>0 );
+ pTab->aCol = aCol = sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol);
+ testcase( aCol==0 );
+ for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
+ Expr *p;
+ char *zType;
+ char *zName;
+ int nName;
+ CollSeq *pColl;
+ int cnt;
+ NameContext sNC;
+
/* Get an appropriate name for the column
*/
p = pEList->a[i].pExpr;
@@ -70888,20 +67919,14 @@ static int selectColumnsFromExprList(
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
zName = sqlite3DbStrDup(db, zName);
+ }else if( p->op==TK_COLUMN && p->pTab ){
+ /* For columns use the column name name */
+ int iCol = p->iColumn;
+ if( iCol<0 ) iCol = p->pTab->iPKey;
+ zName = sqlite3MPrintf(db, "%s", p->pTab->aCol[iCol].zName);
}else{
- Expr *pCol = p;
- Table *pTab;
- while( pCol->op==TK_DOT ) pCol = pCol->pRight;
- if( pCol->op==TK_COLUMN && (pTab = pCol->pTab)!=0 ){
- /* For columns use the column name name */
- int iCol = pCol->iColumn;
- if( iCol<0 ) iCol = pTab->iPKey;
- zName = sqlite3MPrintf(db, "%s",
- iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
- }else{
- /* Use the original text of the column expression as its name */
- zName = sqlite3MPrintf(db, "%T", &pCol->span);
- }
+ /* Use the original text of the column expression as its name */
+ zName = sqlite3MPrintf(db, "%T", &p->span);
}
if( db->mallocFailed ){
sqlite3DbFree(db, zName);
@@ -70925,94 +67950,518 @@ static int selectColumnsFromExprList(
}
}
pCol->zName = zName;
+
+ /* Get the typename, type affinity, and collating sequence for the
+ ** column.
+ */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pSrcList = pSelect->pSrc;
+ zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
+ pCol->zType = zType;
+ pCol->affinity = sqlite3ExprAffinity(p);
+ pColl = sqlite3ExprCollSeq(pParse, p);
+ if( pColl ){
+ pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
+ }
}
+ pTab->iPKey = -1;
if( db->mallocFailed ){
- int j;
- for(j=0; j<i; j++){
- sqlite3DbFree(db, aCol[j].zName);
+ sqlite3DeleteTable(pTab);
+ return 0;
+ }
+ return pTab;
+}
+
+/*
+** Prepare a SELECT statement for processing by doing the following
+** things:
+**
+** (1) Make sure VDBE cursor numbers have been assigned to every
+** element of the FROM clause.
+**
+** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
+** defines FROM clause. When views appear in the FROM clause,
+** fill pTabList->a[].pSelect with a copy of the SELECT statement
+** that implements the view. A copy is made of the view's SELECT
+** statement so that we can freely modify or delete that statement
+** without worrying about messing up the presistent representation
+** of the view.
+**
+** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
+** on joins and the ON and USING clause of joins.
+**
+** (4) Scan the list of columns in the result set (pEList) looking
+** for instances of the "*" operator or the TABLE.* operator.
+** If found, expand each "*" to be every column in every table
+** and TABLE.* to be every column in TABLE.
+**
+** Return 0 on success. If there are problems, leave an error message
+** in pParse and return non-zero.
+*/
+static int prepSelectStmt(Parse *pParse, Select *p){
+ int i, j, k, rc;
+ SrcList *pTabList;
+ ExprList *pEList;
+ struct SrcList_item *pFrom;
+ sqlite3 *db = pParse->db;
+
+ if( p==0 || p->pSrc==0 || db->mallocFailed ){
+ return 1;
+ }
+ pTabList = p->pSrc;
+ pEList = p->pEList;
+
+ /* Make sure cursor numbers have been assigned to all entries in
+ ** the FROM clause of the SELECT statement.
+ */
+ sqlite3SrcListAssignCursors(pParse, p->pSrc);
+
+ /* Look up every table named in the FROM clause of the select. If
+ ** an entry of the FROM clause is a subquery instead of a table or view,
+ ** then create a transient table structure to describe the subquery.
+ */
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab;
+ if( pFrom->pTab!=0 ){
+ /* This statement has already been prepared. There is no need
+ ** to go further. */
+ assert( i==0 );
+ return 0;
+ }
+ if( pFrom->zName==0 ){
+#ifndef SQLITE_OMIT_SUBQUERY
+ /* A sub-query in the FROM clause of a SELECT */
+ assert( pFrom->pSelect!=0 );
+ if( pFrom->zAlias==0 ){
+ pFrom->zAlias =
+ sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect);
+ }
+ assert( pFrom->pTab==0 );
+ pFrom->pTab = pTab =
+ sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
+ if( pTab==0 ){
+ return 1;
+ }
+ /* The isEphem flag indicates that the Table structure has been
+ ** dynamically allocated and may be freed at any time. In other words,
+ ** pTab is not pointing to a persistent table structure that defines
+ ** part of the schema. */
+ pTab->isEphem = 1;
+#endif
+ }else{
+ /* An ordinary table or view name in the FROM clause */
+ assert( pFrom->pTab==0 );
+ pFrom->pTab = pTab =
+ sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
+ if( pTab==0 ){
+ return 1;
+ }
+ pTab->nRef++;
+#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
+ if( pTab->pSelect || IsVirtual(pTab) ){
+ /* We reach here if the named table is a really a view */
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ){
+ return 1;
+ }
+ /* If pFrom->pSelect!=0 it means we are dealing with a
+ ** view within a view. The SELECT structure has already been
+ ** copied by the outer view so we can skip the copy step here
+ ** in the inner view.
+ */
+ if( pFrom->pSelect==0 ){
+ pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
+ }
+ }
+#endif
}
- sqlite3DbFree(db, aCol);
- *paCol = 0;
- *pnCol = 0;
- return SQLITE_NOMEM;
}
- return SQLITE_OK;
+
+ /* Process NATURAL keywords, and ON and USING clauses of joins.
+ */
+ if( sqliteProcessJoin(pParse, p) ) return 1;
+
+ /* For every "*" that occurs in the column list, insert the names of
+ ** all columns in all tables. And for every TABLE.* insert the names
+ ** of all columns in TABLE. The parser inserted a special expression
+ ** with the TK_ALL operator for each "*" that it found in the column list.
+ ** The following code just has to locate the TK_ALL expressions and expand
+ ** each one to the list of all columns in all tables.
+ **
+ ** The first loop just checks to see if there are any "*" operators
+ ** that need expanding.
+ */
+ for(k=0; k<pEList->nExpr; k++){
+ Expr *pE = pEList->a[k].pExpr;
+ if( pE->op==TK_ALL ) break;
+ if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
+ && pE->pLeft && pE->pLeft->op==TK_ID ) break;
+ }
+ rc = 0;
+ if( k<pEList->nExpr ){
+ /*
+ ** If we get here it means the result set contains one or more "*"
+ ** operators that need to be expanded. Loop through each expression
+ ** in the result set and expand them one by one.
+ */
+ struct ExprList_item *a = pEList->a;
+ ExprList *pNew = 0;
+ int flags = pParse->db->flags;
+ int longNames = (flags & SQLITE_FullColNames)!=0
+ && (flags & SQLITE_ShortColNames)==0;
+
+ for(k=0; k<pEList->nExpr; k++){
+ Expr *pE = a[k].pExpr;
+ if( pE->op!=TK_ALL &&
+ (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
+ /* This particular expression does not need to be expanded.
+ */
+ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
+ if( pNew ){
+ pNew->a[pNew->nExpr-1].zName = a[k].zName;
+ }else{
+ rc = 1;
+ }
+ a[k].pExpr = 0;
+ a[k].zName = 0;
+ }else{
+ /* This expression is a "*" or a "TABLE.*" and needs to be
+ ** expanded. */
+ int tableSeen = 0; /* Set to 1 when TABLE matches */
+ char *zTName; /* text of name of TABLE */
+ if( pE->op==TK_DOT && pE->pLeft ){
+ zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
+ }else{
+ zTName = 0;
+ }
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab = pFrom->pTab;
+ char *zTabName = pFrom->zAlias;
+ if( zTabName==0 || zTabName[0]==0 ){
+ zTabName = pTab->zName;
+ }
+ assert( zTabName );
+ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+ continue;
+ }
+ tableSeen = 1;
+ for(j=0; j<pTab->nCol; j++){
+ Expr *pExpr, *pRight;
+ char *zName = pTab->aCol[j].zName;
+
+ /* If a column is marked as 'hidden' (currently only possible
+ ** for virtual tables), do not include it in the expanded
+ ** result-set list.
+ */
+ if( IsHiddenColumn(&pTab->aCol[j]) ){
+ assert(IsVirtual(pTab));
+ continue;
+ }
+
+ if( i>0 ){
+ struct SrcList_item *pLeft = &pTabList->a[i-1];
+ if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
+ columnIndex(pLeft->pTab, zName)>=0 ){
+ /* In a NATURAL join, omit the join columns from the
+ ** table on the right */
+ continue;
+ }
+ if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
+ /* In a join with a USING clause, omit columns in the
+ ** using clause from the table on the right. */
+ continue;
+ }
+ }
+ pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+ if( pRight==0 ) break;
+ setQuotedToken(pParse, &pRight->token, zName);
+ if( longNames || pTabList->nSrc>1 ){
+ Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ if( pExpr==0 ) break;
+ setQuotedToken(pParse, &pLeft->token, zTabName);
+#if 1
+ setToken(&pExpr->span,
+ sqlite3MPrintf(db, "%s.%s", zTabName, zName));
+ pExpr->span.dyn = 1;
+#else
+ pExpr->span = pRight->token;
+ pExpr->span.dyn = 0;
+#endif
+ pExpr->token.z = 0;
+ pExpr->token.n = 0;
+ pExpr->token.dyn = 0;
+ }else{
+ pExpr = pRight;
+ pExpr->span = pExpr->token;
+ pExpr->span.dyn = 0;
+ }
+ if( longNames ){
+ pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
+ }else{
+ pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
+ }
+ }
+ }
+ if( !tableSeen ){
+ if( zTName ){
+ sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
+ }else{
+ sqlite3ErrorMsg(pParse, "no tables specified");
+ }
+ rc = 1;
+ }
+ sqlite3DbFree(db, zTName);
+ }
+ }
+ sqlite3ExprListDelete(db, pEList);
+ p->pEList = pNew;
+ }
+#if SQLITE_MAX_COLUMN
+ if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many columns in result set");
+ rc = SQLITE_ERROR;
+ }
+#endif
+ if( db->mallocFailed ){
+ rc = SQLITE_NOMEM;
+ }
+ return rc;
}
/*
-** Add type and collation information to a column list based on
-** a SELECT statement.
-**
-** The column list presumably came from selectColumnNamesFromExprList().
-** The column list has only names, not types or collations. This
-** routine goes through and adds the types and collations.
-**
-** This routine requires that all indentifiers in the SELECT
-** statement be resolved.
-*/
-static void selectAddColumnTypeAndCollation(
- Parse *pParse, /* Parsing contexts */
- int nCol, /* Number of columns */
- Column *aCol, /* List of columns */
- Select *pSelect /* SELECT used to determine types and collations */
+** pE is a pointer to an expression which is a single term in
+** ORDER BY or GROUP BY clause.
+**
+** At the point this routine is called, we already know that the
+** ORDER BY term is not an integer index into the result set. That
+** casee is handled by the calling routine.
+**
+** If pE is a well-formed expression and the SELECT statement
+** is not compound, then return 0. This indicates to the
+** caller that it should sort by the value of the ORDER BY
+** expression.
+**
+** If the SELECT is compound, then attempt to match pE against
+** result set columns in the left-most SELECT statement. Return
+** the index i of the matching column, as an indication to the
+** caller that it should sort by the i-th column. If there is
+** no match, return -1 and leave an error message in pParse.
+*/
+static int matchOrderByTermToExprList(
+ Parse *pParse, /* Parsing context for error messages */
+ Select *pSelect, /* The SELECT statement with the ORDER BY clause */
+ Expr *pE, /* The specific ORDER BY term */
+ int idx, /* When ORDER BY term is this */
+ int isCompound, /* True if this is a compound SELECT */
+ u8 *pHasAgg /* True if expression contains aggregate functions */
){
- sqlite3 *db = pParse->db;
- NameContext sNC;
- Column *pCol;
- CollSeq *pColl;
- int i;
- Expr *p;
- struct ExprList_item *a;
+ int i; /* Loop counter */
+ ExprList *pEList; /* The columns of the result set */
+ NameContext nc; /* Name context for resolving pE */
- assert( pSelect!=0 );
- assert( (pSelect->selFlags & SF_Resolved)!=0 );
- assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
- if( db->mallocFailed ) return;
- memset(&sNC, 0, sizeof(sNC));
- sNC.pSrcList = pSelect->pSrc;
- a = pSelect->pEList->a;
- for(i=0, pCol=aCol; i<nCol; i++, pCol++){
- p = a[i].pExpr;
- pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
- pCol->affinity = sqlite3ExprAffinity(p);
- pColl = sqlite3ExprCollSeq(pParse, p);
- if( pColl ){
- pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
+ assert( sqlite3ExprIsInteger(pE, &i)==0 );
+ pEList = pSelect->pEList;
+
+ /* If the term is a simple identifier that try to match that identifier
+ ** against a column name in the result set.
+ */
+ if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
+ sqlite3 *db = pParse->db;
+ char *zCol = sqlite3NameFromToken(db, &pE->token);
+ if( zCol==0 ){
+ return -1;
+ }
+ for(i=0; i<pEList->nExpr; i++){
+ char *zAs = pEList->a[i].zName;
+ if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ sqlite3DbFree(db, zCol);
+ return i+1;
+ }
}
+ sqlite3DbFree(db, zCol);
}
+
+ /* Resolve all names in the ORDER BY term expression
+ */
+ memset(&nc, 0, sizeof(nc));
+ nc.pParse = pParse;
+ nc.pSrcList = pSelect->pSrc;
+ nc.pEList = pEList;
+ nc.allowAgg = 1;
+ nc.nErr = 0;
+ if( sqlite3ExprResolveNames(&nc, pE) ){
+ if( isCompound ){
+ sqlite3ErrorClear(pParse);
+ return 0;
+ }else{
+ return -1;
+ }
+ }
+ if( nc.hasAgg && pHasAgg ){
+ *pHasAgg = 1;
+ }
+
+ /* For a compound SELECT, we need to try to match the ORDER BY
+ ** expression against an expression in the result set
+ */
+ if( isCompound ){
+ for(i=0; i<pEList->nExpr; i++){
+ if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
+ return i+1;
+ }
+ }
+ }
+ return 0;
}
+
/*
-** Given a SELECT statement, generate a Table structure that describes
-** the result set of that SELECT.
+** Analyze and ORDER BY or GROUP BY clause in a simple SELECT statement.
+** Return the number of errors seen.
+**
+** Every term of the ORDER BY or GROUP BY clause needs to be an
+** expression. If any expression is an integer constant, then
+** that expression is replaced by the corresponding
+** expression from the result set.
*/
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
- Table *pTab;
+static int processOrderGroupBy(
+ Parse *pParse, /* Parsing context. Leave error messages here */
+ Select *pSelect, /* The SELECT statement containing the clause */
+ ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */
+ int isOrder, /* 1 for ORDER BY. 0 for GROUP BY */
+ u8 *pHasAgg /* Set to TRUE if any term contains an aggregate */
+){
+ int i;
sqlite3 *db = pParse->db;
- int savedFlags;
+ ExprList *pEList;
- savedFlags = db->flags;
- db->flags &= ~SQLITE_FullColNames;
- db->flags |= SQLITE_ShortColNames;
- sqlite3SelectPrep(pParse, pSelect, 0);
- if( pParse->nErr ) return 0;
- while( pSelect->pPrior ) pSelect = pSelect->pPrior;
- db->flags = savedFlags;
- pTab = sqlite3DbMallocZero(db, sizeof(Table) );
- if( pTab==0 ){
- return 0;
+ if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
+#if SQLITE_MAX_COLUMN
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ const char *zType = isOrder ? "ORDER" : "GROUP";
+ sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
+ return 1;
}
- pTab->db = db;
- pTab->nRef = 1;
- pTab->zName = 0;
- selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
- pTab->iPKey = -1;
- if( db->mallocFailed ){
- sqlite3DeleteTable(pTab);
+#endif
+ pEList = pSelect->pEList;
+ if( pEList==0 ){
return 0;
}
- return pTab;
+ for(i=0; i<pOrderBy->nExpr; i++){
+ int iCol;
+ Expr *pE = pOrderBy->a[i].pExpr;
+ if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( iCol<=0 || iCol>pEList->nExpr ){
+ const char *zType = isOrder ? "ORDER" : "GROUP";
+ sqlite3ErrorMsg(pParse,
+ "%r %s BY term out of range - should be "
+ "between 1 and %d", i+1, zType, pEList->nExpr);
+ return 1;
+ }
+ }else{
+ iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg);
+ if( iCol<0 ){
+ return 1;
+ }
+ }
+ if( iCol>0 ){
+ CollSeq *pColl = pE->pColl;
+ int flags = pE->flags & EP_ExpCollate;
+ sqlite3ExprDelete(db, pE);
+ pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr);
+ pOrderBy->a[i].pExpr = pE;
+ if( pE && pColl && flags ){
+ pE->pColl = pColl;
+ pE->flags |= flags;
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return
+** the number of errors seen.
+**
+** If iTable>0 then make the N-th term of the ORDER BY clause refer to
+** the N-th column of table iTable.
+**
+** If iTable==0 then transform each term of the ORDER BY clause to refer
+** to a column of the result set by number.
+*/
+static int processCompoundOrderBy(
+ Parse *pParse, /* Parsing context. Leave error messages here */
+ Select *pSelect /* The SELECT statement containing the ORDER BY */
+){
+ int i;
+ ExprList *pOrderBy;
+ ExprList *pEList;
+ sqlite3 *db;
+ int moreToDo = 1;
+
+ pOrderBy = pSelect->pOrderBy;
+ if( pOrderBy==0 ) return 0;
+ db = pParse->db;
+#if SQLITE_MAX_COLUMN
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
+ return 1;
+ }
+#endif
+ for(i=0; i<pOrderBy->nExpr; i++){
+ pOrderBy->a[i].done = 0;
+ }
+ while( pSelect->pPrior ){
+ pSelect = pSelect->pPrior;
+ }
+ while( pSelect && moreToDo ){
+ moreToDo = 0;
+ pEList = pSelect->pEList;
+ if( pEList==0 ){
+ return 1;
+ }
+ for(i=0; i<pOrderBy->nExpr; i++){
+ int iCol = -1;
+ Expr *pE, *pDup;
+ if( pOrderBy->a[i].done ) continue;
+ pE = pOrderBy->a[i].pExpr;
+ if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( iCol<0 || iCol>pEList->nExpr ){
+ sqlite3ErrorMsg(pParse,
+ "%r ORDER BY term out of range - should be "
+ "between 1 and %d", i+1, pEList->nExpr);
+ return 1;
+ }
+ }else{
+ pDup = sqlite3ExprDup(db, pE);
+ if( !db->mallocFailed ){
+ assert(pDup);
+ iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
+ }
+ sqlite3ExprDelete(db, pDup);
+ if( iCol<0 ){
+ return 1;
+ }
+ }
+ if( iCol>0 ){
+ pE->op = TK_INTEGER;
+ pE->flags |= EP_IntValue;
+ pE->iTable = iCol;
+ pOrderBy->a[i].done = 1;
+ }else{
+ moreToDo = 1;
+ }
+ }
+ pSelect = pSelect->pNext;
+ }
+ for(i=0; i<pOrderBy->nExpr; i++){
+ if( pOrderBy->a[i].done==0 ){
+ sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
+ "column in the result set", i+1);
+ return 1;
+ }
+ }
+ return 0;
}
/*
@@ -71179,7 +68628,6 @@ static int multiSelect(
pPrior = p->pPrior;
assert( pPrior->pRightmost!=pPrior );
assert( pPrior->pRightmost==p->pRightmost );
- dest = *pDest;
if( pPrior->pOrderBy ){
sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
selectOpName(p->op));
@@ -71198,6 +68646,7 @@ static int multiSelect(
/* Create the destination temporary table if necessary
*/
+ dest = *pDest;
if( dest.eDest==SRT_EphemTab ){
assert( p->pEList );
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr);
@@ -71229,7 +68678,7 @@ static int multiSelect(
assert( !pPrior->pLimit );
pPrior->pLimit = p->pLimit;
pPrior->pOffset = p->pOffset;
- rc = sqlite3Select(pParse, pPrior, &dest);
+ rc = sqlite3Select(pParse, pPrior, &dest, 0, 0, 0);
p->pLimit = 0;
p->pOffset = 0;
if( rc ){
@@ -71242,7 +68691,7 @@ static int multiSelect(
addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
VdbeComment((v, "Jump ahead if LIMIT reached"));
}
- rc = sqlite3Select(pParse, p, &dest);
+ rc = sqlite3Select(pParse, p, &dest, 0, 0, 0);
pDelete = p->pPrior;
p->pPrior = pPrior;
if( rc ){
@@ -71277,7 +68726,7 @@ static int multiSelect(
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
assert( p->addrOpenEphm[0] == -1 );
p->addrOpenEphm[0] = addr;
- p->pRightmost->selFlags |= SF_UsesEphemeral;
+ p->pRightmost->usesEphm = 1;
assert( p->pEList );
}
@@ -71285,7 +68734,7 @@ static int multiSelect(
*/
assert( !pPrior->pOrderBy );
sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
- rc = sqlite3Select(pParse, pPrior, &uniondest);
+ rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0);
if( rc ){
goto multi_select_end;
}
@@ -71299,12 +68748,13 @@ static int multiSelect(
op = SRT_Union;
}
p->pPrior = 0;
+ p->disallowOrderBy = 0;
pLimit = p->pLimit;
p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
uniondest.eDest = op;
- rc = sqlite3Select(pParse, p, &uniondest);
+ rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0);
/* Query flattening in sqlite3Select() might refill p->pOrderBy.
** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
sqlite3ExprListDelete(db, p->pOrderBy);
@@ -71327,7 +68777,7 @@ static int multiSelect(
if( dest.eDest!=priorOp || unionTab!=dest.iParm ){
int iCont, iBreak, iStart;
assert( p->pEList );
- if( dest.eDest==SRT_Output ){
+ if( dest.eDest==SRT_Callback ){
Select *pFirst = p;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, 0, pFirst->pEList);
@@ -71365,13 +68815,13 @@ static int multiSelect(
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
assert( p->addrOpenEphm[0] == -1 );
p->addrOpenEphm[0] = addr;
- p->pRightmost->selFlags |= SF_UsesEphemeral;
+ p->pRightmost->usesEphm = 1;
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
- rc = sqlite3Select(pParse, pPrior, &intersectdest);
+ rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0);
if( rc ){
goto multi_select_end;
}
@@ -71387,7 +68837,7 @@ static int multiSelect(
pOffset = p->pOffset;
p->pOffset = 0;
intersectdest.iParm = tab2;
- rc = sqlite3Select(pParse, p, &intersectdest);
+ rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0);
pDelete = p->pPrior;
p->pPrior = pPrior;
sqlite3ExprDelete(db, p->pLimit);
@@ -71401,7 +68851,7 @@ static int multiSelect(
** tables.
*/
assert( p->pEList );
- if( dest.eDest==SRT_Output ){
+ if( dest.eDest==SRT_Callback ){
Select *pFirst = p;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, 0, pFirst->pEList);
@@ -71434,7 +68884,7 @@ static int multiSelect(
** SELECT might also skip this part if it has no ORDER BY clause and
** no temp tables are required.
*/
- if( p->selFlags & SF_UsesEphemeral ){
+ if( p->usesEphm ){
int i; /* Loop counter */
KeyInfo *pKeyInfo; /* Collating sequence for the result set */
Select *pLoop; /* For looping through SELECT statements */
@@ -71597,8 +69047,9 @@ static int generateOutputSubroutine(
}
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
- /* The results are stored in a sequence of registers
- ** starting at pDest->iMem. Then the co-routine yields.
+ /* Send the data to the callback function or to a subroutine. In the
+ ** case of a subroutine, the subroutine itself is responsible for
+ ** popping the data from the stack.
*/
case SRT_Coroutine: {
if( pDest->iMem==0 ){
@@ -71610,11 +69061,7 @@ static int generateOutputSubroutine(
break;
}
- /* Results are stored in a sequence of registers. Then the
- ** OP_ResultRow opcode is used to cause sqlite3_step() to return
- ** the next row of result.
- */
- case SRT_Output: {
+ case SRT_Callback: {
sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem);
sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem);
break;
@@ -71767,15 +69214,15 @@ static int multiSelectOrderBy(
int labelEnd; /* Label for the end of the overall SELECT stmt */
int j1; /* Jump instructions that get retargetted */
int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
- KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
+ KeyInfo *pKeyDup; /* Comparison information for duplicate removal */
KeyInfo *pKeyMerge; /* Comparison information for merging rows */
sqlite3 *db; /* Database connection */
ExprList *pOrderBy; /* The ORDER BY clause */
int nOrderBy; /* Number of terms in the ORDER BY clause */
int *aPermute; /* Mapping from ORDER BY terms to result set columns */
+ u8 NotUsed; /* Dummy variables */
assert( p->pOrderBy!=0 );
- assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */
db = pParse->db;
v = pParse->pVdbe;
if( v==0 ) return SQLITE_NOMEM;
@@ -71790,6 +69237,9 @@ static int multiSelectOrderBy(
assert( pPrior->pOrderBy==0 );
pOrderBy = p->pOrderBy;
assert( pOrderBy );
+ if( processCompoundOrderBy(pParse, p) ){
+ return SQLITE_ERROR;
+ }
nOrderBy = pOrderBy->nExpr;
/* For operators other than UNION ALL we have to make sure that
@@ -71798,10 +69248,11 @@ static int multiSelectOrderBy(
*/
if( op!=TK_ALL ){
for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
- struct ExprList_item *pItem;
- for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
- assert( pItem->iCol>0 );
- if( pItem->iCol==i ) break;
+ for(j=0; j<nOrderBy; j++){
+ Expr *pTerm = pOrderBy->a[j].pExpr;
+ assert( pTerm->op==TK_INTEGER );
+ assert( (pTerm->flags & EP_IntValue)!=0 );
+ if( pTerm->iTable==i ) break;
}
if( j==nOrderBy ){
Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0);
@@ -71809,7 +69260,7 @@ static int multiSelectOrderBy(
pNew->flags |= EP_IntValue;
pNew->iTable = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0);
- pOrderBy->a[nOrderBy++].iCol = i;
+ nOrderBy++;
}
}
}
@@ -71823,10 +69274,12 @@ static int multiSelectOrderBy(
*/
aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy);
if( aPermute ){
- struct ExprList_item *pItem;
- for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
- assert( pItem->iCol>0 && pItem->iCol<=p->pEList->nExpr );
- aPermute[i] = pItem->iCol - 1;
+ for(i=0; i<nOrderBy; i++){
+ Expr *pTerm = pOrderBy->a[i].pExpr;
+ assert( pTerm->op==TK_INTEGER );
+ assert( (pTerm->flags & EP_IntValue)!=0 );
+ aPermute[i] = pTerm->iTable-1;
+ assert( aPermute[i]>=0 && aPermute[i]<p->pEList->nExpr );
}
pKeyMerge =
sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
@@ -71865,7 +69318,7 @@ static int multiSelectOrderBy(
regPrev = 0;
}else{
int nExpr = p->pEList->nExpr;
- assert( nOrderBy>=nExpr || db->mallocFailed );
+ assert( nOrderBy>=nExpr );
regPrev = sqlite3GetTempRange(pParse, nExpr+1);
sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
pKeyDup = sqlite3DbMallocZero(db,
@@ -71885,9 +69338,9 @@ static int multiSelectOrderBy(
*/
p->pPrior = 0;
pPrior->pRightmost = 0;
- sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
+ processOrderGroupBy(pParse, p, p->pOrderBy, 1, &NotUsed);
if( pPrior->pPrior==0 ){
- sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
+ processOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, 1, &NotUsed);
}
/* Compute the limit registers */
@@ -71927,7 +69380,7 @@ static int multiSelectOrderBy(
*/
VdbeNoopComment((v, "Begin coroutine for left SELECT"));
pPrior->iLimit = regLimitA;
- sqlite3Select(pParse, pPrior, &destA);
+ sqlite3Select(pParse, pPrior, &destA, 0, 0, 0);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
VdbeNoopComment((v, "End coroutine for left SELECT"));
@@ -71941,7 +69394,7 @@ static int multiSelectOrderBy(
savedOffset = p->iOffset;
p->iLimit = regLimitB;
p->iOffset = 0;
- sqlite3Select(pParse, p, &destB);
+ sqlite3Select(pParse, p, &destB, 0, 0, 0);
p->iLimit = savedLimit;
p->iOffset = savedOffset;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
@@ -72056,7 +69509,7 @@ static int multiSelectOrderBy(
/* Set the number of output columns
*/
- if( pDest->eDest==SRT_Output ){
+ if( pDest->eDest==SRT_Callback ){
Select *pFirst = pPrior;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, 0, pFirst->pEList);
@@ -72150,9 +69603,6 @@ static void substSelect(
int iTable, /* Table to be replaced */
ExprList *pEList /* Substitute values */
){
- SrcList *pSrc;
- struct SrcList_item *pItem;
- int i;
if( !p ) return;
substExprList(db, p->pEList, iTable, pEList);
substExprList(db, p->pGroupBy, iTable, pEList);
@@ -72160,12 +69610,6 @@ static void substSelect(
substExpr(db, p->pHaving, iTable, pEList);
substExpr(db, p->pWhere, iTable, pEList);
substSelect(db, p->pPrior, iTable, pEList);
- pSrc = p->pSrc;
- if( pSrc ){
- for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- substSelect(db, pItem->pSelect, iTable, pEList);
- }
- }
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
@@ -72203,8 +69647,8 @@ static void substSelect(
**
** (2) The subquery is not an aggregate or the outer query is not a join.
**
-** (3) The subquery is not the right operand of a left outer join
-** (Originally ticket #306. Strenghtened by ticket #3300)
+** (3) The subquery is not the right operand of a left outer join, or
+** the subquery is not itself a join. (Ticket #306)
**
** (4) The subquery is not DISTINCT or the outer query is not a join.
**
@@ -72226,8 +69670,8 @@ static void substSelect(
**
** (11) The subquery and the outer query do not both have ORDER BY clauses.
**
-** (12) Not implemented. Subsumed into restriction (3). Was previously
-** a separate restriction deriving from ticket #350.
+** (12) The subquery is not the right term of a LEFT OUTER JOIN or the
+** subquery has no WHERE clause. (added by ticket #350)
**
** (13) The subquery and outer query do not both use LIMIT
**
@@ -72257,9 +69701,6 @@ static void substSelect(
** ORDER by clause of the parent must be simple references to
** columns of the sub-query.
**
-** (19) The subquery does not use LIMIT or the outer query does not
-** have a WHERE clause.
-**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
@@ -72292,9 +69733,7 @@ static int flattenSubquery(
/* Check to see if flattening is permitted. Return 0 if not.
*/
- assert( p!=0 );
if( p==0 ) return 0;
- assert( p->pPrior==0 ); /* Unable to flatten compound queries */
pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
pSubitem = &pSrc->a[iFrom];
@@ -72316,21 +69755,17 @@ static int flattenSubquery(
return 0; /* Restriction (15) */
}
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
- if( ((pSub->selFlags & SF_Distinct)!=0 || pSub->pLimit)
+ if( (pSub->isDistinct || pSub->pLimit)
&& (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */
return 0;
}
- if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
- return 0; /* Restriction (6) */
- }
- if( p->pOrderBy && pSub->pOrderBy ){
+ if( p->isDistinct && subqueryIsAgg ) return 0; /* Restriction (6) */
+ if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){
return 0; /* Restriction (11) */
}
if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
- if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
- /* OBSOLETE COMMENT 1:
- ** Restriction 3: If the subquery is a join, make sure the subquery is
+ /* Restriction 3: If the subquery is a join, make sure the subquery is
** not used as the right operand of an outer join. Examples of why this
** is not allowed:
**
@@ -72341,9 +69776,12 @@ static int flattenSubquery(
** (t1 LEFT OUTER JOIN t2) JOIN t3
**
** which is not at all the same thing.
- **
- ** OBSOLETE COMMENT 2:
- ** Restriction 12: If the subquery is the right operand of a left outer
+ */
+ if( pSubSrc->nSrc>1 && (pSubitem->jointype & JT_OUTER)!=0 ){
+ return 0;
+ }
+
+ /* Restriction 12: If the subquery is the right operand of a left outer
** join, make sure the subquery has no WHERE clause.
** An examples of why this is not allowed:
**
@@ -72355,13 +69793,8 @@ static int flattenSubquery(
**
** But the t2.x>0 test will always fail on a NULL row of t2, which
** effectively converts the OUTER JOIN into an INNER JOIN.
- **
- ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
- ** Ticket #3300 shows that flattening the right term of a LEFT JOIN
- ** is fraught with danger. Best to avoid the whole thing. If the
- ** subquery is the right term of a LEFT JOIN, then do not flatten.
*/
- if( (pSubitem->jointype & JT_OUTER)!=0 ){
+ if( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){
return 0;
}
@@ -72371,11 +69804,11 @@ static int flattenSubquery(
** queries.
*/
if( pSub->pPrior ){
- if( p->pPrior || isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
+ if( p->pPrior || isAgg || p->isDistinct || pSrc->nSrc!=1 ){
return 0;
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
- if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
+ if( pSub1->isAgg || pSub1->isDistinct
|| (pSub1->pPrior && pSub1->op!=TK_ALL)
|| !pSub1->pSrc || pSub1->pSrc->nSrc!=1
){
@@ -72387,165 +69820,96 @@ static int flattenSubquery(
if( p->pOrderBy ){
int ii;
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
- if( p->pOrderBy->a[ii].iCol==0 ) return 0;
+ Expr *pExpr = p->pOrderBy->a[ii].pExpr;
+ if( pExpr->op!=TK_COLUMN || pExpr->iTable!=iParent ){
+ return 0;
+ }
}
}
}
- /***** If we reach this point, flattening is permitted. *****/
-
- /* Authorize the subquery */
pParse->zAuthContext = pSubitem->zName;
sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
pParse->zAuthContext = zSavedAuthContext;
- /* If the sub-query is a compound SELECT statement, then (by restrictions
- ** 17 and 18 above) it must be a UNION ALL and the parent query must
- ** be of the form:
+ /* If the sub-query is a compound SELECT statement, then it must be
+ ** a UNION ALL and the parent query must be of the form:
**
** SELECT <expr-list> FROM (<sub-query>) <where-clause>
**
** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
- ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or
+ ** creates N copies of the parent query without any ORDER BY, LIMIT or
** OFFSET clauses and joins them to the left-hand-side of the original
** using UNION ALL operators. In this case N is the number of simple
** select statements in the compound sub-query.
- **
- ** Example:
- **
- ** SELECT a+1 FROM (
- ** SELECT x FROM tab
- ** UNION ALL
- ** SELECT y FROM tab
- ** UNION ALL
- ** SELECT abs(z*2) FROM tab2
- ** ) WHERE a!=5 ORDER BY 1
- **
- ** Transformed into:
- **
- ** SELECT x+1 FROM tab WHERE x+1!=5
- ** UNION ALL
- ** SELECT y+1 FROM tab WHERE y+1!=5
- ** UNION ALL
- ** SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5
- ** ORDER BY 1
- **
- ** We call this the "compound-subquery flattening".
*/
for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){
Select *pNew;
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
+ Expr *pOffset = p->pOffset;
Select *pPrior = p->pPrior;
p->pOrderBy = 0;
p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlite3SelectDup(db, p);
- p->pLimit = pLimit;
+ pNew->pPrior = pPrior;
+ p->pPrior = pNew;
p->pOrderBy = pOrderBy;
- p->pSrc = pSrc;
p->op = TK_ALL;
+ p->pSrc = pSrc;
+ p->pLimit = pLimit;
+ p->pOffset = pOffset;
p->pRightmost = 0;
- if( pNew==0 ){
- pNew = pPrior;
- }else{
- pNew->pPrior = pPrior;
- pNew->pRightmost = 0;
- }
- p->pPrior = pNew;
- if( db->mallocFailed ) return 1;
+ pNew->pRightmost = 0;
}
- /* Begin flattening the iFrom-th entry of the FROM clause
- ** in the outer query.
+ /* If we reach this point, it means flattening is permitted for the
+ ** iFrom-th entry of the FROM clause in the outer query.
*/
pSub = pSub1 = pSubitem->pSelect;
-
- /* Delete the transient table structure associated with the
- ** subquery
- */
- sqlite3DbFree(db, pSubitem->zDatabase);
- sqlite3DbFree(db, pSubitem->zName);
- sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
- pSubitem->zName = 0;
- pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
-
- /* Defer deleting the Table object associated with the
- ** subquery until code generation is
- ** complete, since there may still exist Expr.pTab entries that
- ** refer to the subquery even after flattening. Ticket #3346.
- */
- if( pSubitem->pTab!=0 ){
- Table *pTabToDel = pSubitem->pTab;
- if( pTabToDel->nRef==1 ){
- pTabToDel->pNextZombie = pParse->pZombieTab;
- pParse->pZombieTab = pTabToDel;
- }else{
- pTabToDel->nRef--;
- }
- pSubitem->pTab = 0;
- }
-
- /* The following loop runs once for each term in a compound-subquery
- ** flattening (as described above). If we are doing a different kind
- ** of flattening - a flattening other than a compound-subquery flattening -
- ** then this loop only runs once.
- **
- ** This loop moves all of the FROM elements of the subquery into the
- ** the FROM clause of the outer query. Before doing this, remember
- ** the cursor number for the original outer query FROM element in
- ** iParent. The iParent cursor will never be used. Subsequent code
- ** will scan expressions looking for iParent references and replace
- ** those references with expressions that resolve to the subquery FROM
- ** elements we are now copying in.
- */
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
- int nSubSrc;
+ int nSubSrc = pSubSrc->nSrc;
int jointype = 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 */
-
+ pSubSrc = pSub->pSrc;
+ pSrc = pParent->pSrc;
+
+ /* Move all of the FROM elements of the subquery into the
+ ** the FROM clause of the outer query. Before doing this, remember
+ ** the cursor number for the original outer query FROM element in
+ ** iParent. The iParent cursor will never be used. Subsequent code
+ ** will scan expressions looking for iParent references and replace
+ ** those references with expressions that resolve to the subquery FROM
+ ** elements we are now copying in.
+ */
if( pSrc ){
- assert( pParent==p ); /* First time through the loop */
+ pSubitem = &pSrc->a[iFrom];
+ nSubSrc = pSubSrc->nSrc;
jointype = pSubitem->jointype;
- }else{
- assert( pParent!=p ); /* 2nd and subsequent times through the loop */
- pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pSrc==0 ){
- assert( db->mallocFailed );
- break;
+ sqlite3DeleteTable(pSubitem->pTab);
+ sqlite3DbFree(db, pSubitem->zDatabase);
+ sqlite3DbFree(db, pSubitem->zName);
+ sqlite3DbFree(db, pSubitem->zAlias);
+ pSubitem->pTab = 0;
+ pSubitem->zDatabase = 0;
+ pSubitem->zName = 0;
+ pSubitem->zAlias = 0;
+ }
+ if( nSubSrc!=1 || !pSrc ){
+ int extra = nSubSrc - 1;
+ for(i=(pSrc?1:0); i<nSubSrc; i++){
+ pSrc = sqlite3SrcListAppend(db, pSrc, 0, 0);
+ if( pSrc==0 ){
+ pParent->pSrc = 0;
+ return 1;
+ }
}
- }
-
- /* 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
- ** of the subquery.
- **
- ** Example:
- **
- ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
- **
- ** The outer query has 3 slots in its FROM clause. One slot of the
- ** outer query (the middle slot) is used by the subquery. The next
- ** block of code will expand the out query to 4 slots. The middle
- ** slot is expanded to two slots in order to make space for the
- ** two elements in the FROM clause of the subquery.
- */
- if( nSubSrc>1 ){
- pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
- if( db->mallocFailed ){
- break;
+ pParent->pSrc = pSrc;
+ for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){
+ pSrc->a[i] = pSrc->a[i-extra];
}
}
-
- /* Transfer the FROM clause terms from the subquery into the
- ** outer query.
- */
for(i=0; i<nSubSrc; i++){
pSrc->a[i+iFrom] = pSubSrc->a[i];
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
@@ -72606,7 +69970,7 @@ static int flattenSubquery(
/* The flattened query is distinct if either the inner or the
** outer query is distinct.
*/
- pParent->selFlags |= pSub->selFlags & SF_Distinct;
+ pParent->isDistinct = pParent->isDistinct || pSub->isDistinct;
/*
** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
@@ -72640,7 +70004,7 @@ static int flattenSubquery(
** 2. There is a single expression in the result set, and it is
** either min(x) or max(x), where x is a column reference.
*/
-static int minMaxQuery(Select *p){
+static int minMaxQuery(Parse *pParse, Select *p){
Expr *pExpr;
ExprList *pEList = p->pEList;
@@ -72659,400 +70023,133 @@ static int minMaxQuery(Select *p){
}
/*
-** If the source-list item passed as an argument was augmented with an
-** INDEXED BY clause, then try to locate the specified index. If there
-** was such a clause and the named index cannot be found, return
-** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
-** pFrom->pIndex and return SQLITE_OK.
+** This routine resolves any names used in the result set of the
+** supplied SELECT statement. If the SELECT statement being resolved
+** is a sub-select, then pOuterNC is a pointer to the NameContext
+** of the parent SELECT.
*/
-SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
- if( pFrom->pTab && pFrom->zIndex ){
- Table *pTab = pFrom->pTab;
- char *zIndex = pFrom->zIndex;
- Index *pIdx;
- for(pIdx=pTab->pIndex;
- pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
- pIdx=pIdx->pNext
- );
- if( !pIdx ){
- sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0);
- return SQLITE_ERROR;
- }
- pFrom->pIndex = pIdx;
+SQLITE_PRIVATE int sqlite3SelectResolve(
+ Parse *pParse, /* The parser context */
+ Select *p, /* The SELECT statement being coded. */
+ NameContext *pOuterNC /* The outer name context. May be NULL. */
+){
+ ExprList *pEList; /* Result set. */
+ int i; /* For-loop variable used in multiple places */
+ NameContext sNC; /* Local name-context */
+ ExprList *pGroupBy; /* The group by clause */
+
+ /* If this routine has run before, return immediately. */
+ if( p->isResolved ){
+ assert( !pOuterNC );
+ return SQLITE_OK;
}
- return SQLITE_OK;
-}
-
-/*
-** This routine is a Walker callback for "expanding" a SELECT statement.
-** "Expanding" means to do the following:
-**
-** (1) Make sure VDBE cursor numbers have been assigned to every
-** element of the FROM clause.
-**
-** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
-** defines FROM clause. When views appear in the FROM clause,
-** fill pTabList->a[].pSelect with a copy of the SELECT statement
-** that implements the view. A copy is made of the view's SELECT
-** statement so that we can freely modify or delete that statement
-** without worrying about messing up the presistent representation
-** of the view.
-**
-** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
-** on joins and the ON and USING clause of joins.
-**
-** (4) Scan the list of columns in the result set (pEList) looking
-** for instances of the "*" operator or the TABLE.* operator.
-** If found, expand each "*" to be every column in every table
-** and TABLE.* to be every column in TABLE.
-**
-*/
-static int selectExpander(Walker *pWalker, Select *p){
- Parse *pParse = pWalker->pParse;
- int i, j, k;
- SrcList *pTabList;
- ExprList *pEList;
- struct SrcList_item *pFrom;
- sqlite3 *db = pParse->db;
+ p->isResolved = 1;
- if( db->mallocFailed ){
- return WRC_Abort;
+ /* If there have already been errors, do nothing. */
+ if( pParse->nErr>0 ){
+ return SQLITE_ERROR;
}
- if( p->pSrc==0 || (p->selFlags & SF_Expanded)!=0 ){
- return WRC_Prune;
+
+ /* Prepare the select statement. This call will allocate all cursors
+ ** required to handle the tables and subqueries in the FROM clause.
+ */
+ if( prepSelectStmt(pParse, p) ){
+ return SQLITE_ERROR;
}
- p->selFlags |= SF_Expanded;
- pTabList = p->pSrc;
- pEList = p->pEList;
- /* Make sure cursor numbers have been assigned to all entries in
- ** the FROM clause of the SELECT statement.
+ /* Resolve the expressions in the LIMIT and OFFSET clauses. These
+ ** are not allowed to refer to any names, so pass an empty NameContext.
*/
- sqlite3SrcListAssignCursors(pParse, pTabList);
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ if( sqlite3ExprResolveNames(&sNC, p->pLimit) ||
+ sqlite3ExprResolveNames(&sNC, p->pOffset) ){
+ return SQLITE_ERROR;
+ }
- /* Look up every table named in the FROM clause of the select. If
- ** an entry of the FROM clause is a subquery instead of a table or view,
- ** then create a transient table structure to describe the subquery.
+ /* Set up the local name-context to pass to ExprResolveNames() to
+ ** resolve the expression-list.
*/
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab;
- if( pFrom->pTab!=0 ){
- /* This statement has already been prepared. There is no need
- ** to go further. */
- assert( i==0 );
- return WRC_Prune;
- }
- if( pFrom->zName==0 ){
-#ifndef SQLITE_OMIT_SUBQUERY
- Select *pSel = pFrom->pSelect;
- /* A sub-query in the FROM clause of a SELECT */
- assert( pSel!=0 );
- assert( pFrom->pTab==0 );
- sqlite3WalkSelect(pWalker, pSel);
- pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return WRC_Abort;
- pTab->db = db;
- pTab->nRef = 1;
- pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
- while( pSel->pPrior ){ pSel = pSel->pPrior; }
- selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
- pTab->iPKey = -1;
- pTab->tabFlags |= TF_Ephemeral;
-#endif
- }else{
- /* An ordinary table or view name in the FROM clause */
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab =
- sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
- if( pTab==0 ) return WRC_Abort;
- pTab->nRef++;
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
- if( pTab->pSelect || IsVirtual(pTab) ){
- /* We reach here if the named table is a really a view */
- if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
+ sNC.allowAgg = 1;
+ sNC.pSrcList = p->pSrc;
+ sNC.pNext = pOuterNC;
- /* If pFrom->pSelect!=0 it means we are dealing with a
- ** view within a view. The SELECT structure has already been
- ** copied by the outer view so we can skip the copy step here
- ** in the inner view.
- */
- if( pFrom->pSelect==0 ){
- pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
- sqlite3WalkSelect(pWalker, pFrom->pSelect);
- }
- }
-#endif
+ /* Resolve names in the result set. */
+ pEList = p->pEList;
+ if( !pEList ) return SQLITE_ERROR;
+ for(i=0; i<pEList->nExpr; i++){
+ Expr *pX = pEList->a[i].pExpr;
+ if( sqlite3ExprResolveNames(&sNC, pX) ){
+ return SQLITE_ERROR;
}
+ }
- /* Locate the index named by the INDEXED BY clause, if any. */
- if( sqlite3IndexedByLookup(pParse, pFrom) ){
- return WRC_Abort;
- }
+ /* If there are no aggregate functions in the result-set, and no GROUP BY
+ ** expression, do not allow aggregates in any of the other expressions.
+ */
+ assert( !p->isAgg );
+ pGroupBy = p->pGroupBy;
+ if( pGroupBy || sNC.hasAgg ){
+ p->isAgg = 1;
+ }else{
+ sNC.allowAgg = 0;
}
- /* Process NATURAL keywords, and ON and USING clauses of joins.
+ /* If a HAVING clause is present, then there must be a GROUP BY clause.
*/
- if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
- return WRC_Abort;
+ if( p->pHaving && !pGroupBy ){
+ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+ return SQLITE_ERROR;
}
- /* For every "*" that occurs in the column list, insert the names of
- ** all columns in all tables. And for every TABLE.* insert the names
- ** of all columns in TABLE. The parser inserted a special expression
- ** with the TK_ALL operator for each "*" that it found in the column list.
- ** The following code just has to locate the TK_ALL expressions and expand
- ** each one to the list of all columns in all tables.
+ /* Add the expression list to the name-context before parsing the
+ ** other expressions in the SELECT statement. This is so that
+ ** expressions in the WHERE clause (etc.) can refer to expressions by
+ ** aliases in the result set.
**
- ** The first loop just checks to see if there are any "*" operators
- ** that need expanding.
+ ** Minor point: If this is the case, then the expression will be
+ ** re-evaluated for each reference to it.
*/
- for(k=0; k<pEList->nExpr; k++){
- Expr *pE = pEList->a[k].pExpr;
- if( pE->op==TK_ALL ) break;
- if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
- && pE->pLeft && pE->pLeft->op==TK_ID ) break;
+ sNC.pEList = p->pEList;
+ if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
+ sqlite3ExprResolveNames(&sNC, p->pHaving) ){
+ return SQLITE_ERROR;
}
- if( k<pEList->nExpr ){
- /*
- ** If we get here it means the result set contains one or more "*"
- ** operators that need to be expanded. Loop through each expression
- ** in the result set and expand them one by one.
- */
- struct ExprList_item *a = pEList->a;
- ExprList *pNew = 0;
- int flags = pParse->db->flags;
- int longNames = (flags & SQLITE_FullColNames)!=0
- && (flags & SQLITE_ShortColNames)==0;
-
- for(k=0; k<pEList->nExpr; k++){
- Expr *pE = a[k].pExpr;
- if( pE->op!=TK_ALL &&
- (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
- /* This particular expression does not need to be expanded.
- */
- pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
- if( pNew ){
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
- }
- a[k].pExpr = 0;
- a[k].zName = 0;
- }else{
- /* This expression is a "*" or a "TABLE.*" and needs to be
- ** expanded. */
- int tableSeen = 0; /* Set to 1 when TABLE matches */
- char *zTName; /* text of name of TABLE */
- if( pE->op==TK_DOT && pE->pLeft ){
- zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
- }else{
- zTName = 0;
- }
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
- char *zTabName = pFrom->zAlias;
- if( zTabName==0 || zTabName[0]==0 ){
- zTabName = pTab->zName;
- }
- if( db->mallocFailed ) break;
- if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
- continue;
- }
- tableSeen = 1;
- for(j=0; j<pTab->nCol; j++){
- Expr *pExpr, *pRight;
- char *zName = pTab->aCol[j].zName;
-
- /* If a column is marked as 'hidden' (currently only possible
- ** for virtual tables), do not include it in the expanded
- ** result-set list.
- */
- if( IsHiddenColumn(&pTab->aCol[j]) ){
- assert(IsVirtual(pTab));
- continue;
- }
-
- if( i>0 ){
- struct SrcList_item *pLeft = &pTabList->a[i-1];
- if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
- columnIndex(pLeft->pTab, zName)>=0 ){
- /* In a NATURAL join, omit the join columns from the
- ** table on the right */
- continue;
- }
- if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
- /* In a join with a USING clause, omit columns in the
- ** using clause from the table on the right. */
- continue;
- }
- }
- pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
- if( pRight==0 ) break;
- setQuotedToken(pParse, &pRight->token, zName);
- if( longNames || pTabList->nSrc>1 ){
- Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
- if( pExpr==0 ) break;
- setQuotedToken(pParse, &pLeft->token, zTabName);
- setToken(&pExpr->span,
- sqlite3MPrintf(db, "%s.%s", zTabName, zName));
- pExpr->span.dyn = 1;
- pExpr->token.z = 0;
- pExpr->token.n = 0;
- pExpr->token.dyn = 0;
- }else{
- pExpr = pRight;
- pExpr->span = pExpr->token;
- pExpr->span.dyn = 0;
- }
- if( longNames ){
- pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
- }else{
- pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
- }
- }
- }
- if( !tableSeen ){
- if( zTName ){
- sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
- }else{
- sqlite3ErrorMsg(pParse, "no tables specified");
- }
- }
- sqlite3DbFree(db, zTName);
- }
+ if( p->pPrior==0 ){
+ if( processOrderGroupBy(pParse, p, p->pOrderBy, 1, &sNC.hasAgg) ){
+ return SQLITE_ERROR;
}
- sqlite3ExprListDelete(db, pEList);
- p->pEList = pNew;
}
-#if SQLITE_MAX_COLUMN
- if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many columns in result set");
+ if( processOrderGroupBy(pParse, p, pGroupBy, 0, &sNC.hasAgg) ){
+ return SQLITE_ERROR;
}
-#endif
- return WRC_Continue;
-}
-/*
-** No-op routine for the parse-tree walker.
-**
-** When this routine is the Walker.xExprCallback then expression trees
-** are walked without any actions being taken at each node. Presumably,
-** when this routine is used for Walker.xExprCallback then
-** Walker.xSelectCallback is set to do something useful for every
-** subquery in the parser tree.
-*/
-static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return WRC_Continue;
-}
-
-/*
-** This routine "expands" a SELECT statement and all of its subqueries.
-** For additional information on what it means to "expand" a SELECT
-** statement, see the comment on the selectExpand worker callback above.
-**
-** Expanding a SELECT statement is the first step in processing a
-** SELECT statement. The SELECT statement must be expanded before
-** name resolution is performed.
-**
-** If anything goes wrong, an error message is written into pParse.
-** The calling function can detect the problem by looking at pParse->nErr
-** and/or pParse->db->mallocFailed.
-*/
-static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
- Walker w;
- w.xSelectCallback = selectExpander;
- w.xExprCallback = exprWalkNoop;
- w.pParse = pParse;
- sqlite3WalkSelect(&w, pSelect);
-}
-
-
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()
-** interface.
-**
-** For each FROM-clause subquery, add Column.zType and Column.zColl
-** information to the Table structure that represents the result set
-** of that subquery.
-**
-** The Table structure that represents the result set was constructed
-** by selectExpander() but the type and collation information was omitted
-** at that point because identifiers had not yet been resolved. This
-** routine is called after identifier resolution.
-*/
-static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
- Parse *pParse;
- int i;
- SrcList *pTabList;
- struct SrcList_item *pFrom;
+ if( pParse->db->mallocFailed ){
+ return SQLITE_NOMEM;
+ }
- assert( p->selFlags & SF_Resolved );
- if( (p->selFlags & SF_HasTypeInfo)==0 ){
- p->selFlags |= SF_HasTypeInfo;
- pParse = pWalker->pParse;
- pTabList = p->pSrc;
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
- if( pTab && (pTab->tabFlags & TF_Ephemeral)!=0 ){
- /* A sub-query in the FROM clause of a SELECT */
- Select *pSel = pFrom->pSelect;
- assert( pSel );
- while( pSel->pPrior ) pSel = pSel->pPrior;
- selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
+ /* Make sure the GROUP BY clause does not contain aggregate functions.
+ */
+ if( pGroupBy ){
+ struct ExprList_item *pItem;
+
+ for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
+ if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
+ sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
+ "the GROUP BY clause");
+ return SQLITE_ERROR;
}
}
}
- return WRC_Continue;
-}
-#endif
-
-/*
-** This routine adds datatype and collating sequence information to
-** the Table structures of all FROM-clause subqueries in a
-** SELECT statement.
-**
-** Use this routine after name resolution.
-*/
-static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
-#ifndef SQLITE_OMIT_SUBQUERY
- Walker w;
- w.xSelectCallback = selectAddSubqueryTypeInfo;
- w.xExprCallback = exprWalkNoop;
- w.pParse = pParse;
- sqlite3WalkSelect(&w, pSelect);
-#endif
-}
-
-
-/*
-** This routine sets of a SELECT statement for processing. The
-** following is accomplished:
-**
-** * VDBE Cursor numbers are assigned to all FROM-clause terms.
-** * Ephemeral Table objects are created for all FROM-clause subqueries.
-** * ON and USING clauses are shifted into WHERE statements
-** * Wildcards "*" and "TABLE.*" in result sets are expanded.
-** * Identifiers in expression are matched to tables.
-**
-** This routine acts recursively on all subqueries within the SELECT.
-*/
-SQLITE_PRIVATE void sqlite3SelectPrep(
- Parse *pParse, /* The parser context */
- Select *p, /* The SELECT statement being coded. */
- NameContext *pOuterNC /* Name context for container */
-){
- sqlite3 *db;
- if( p==0 ) return;
- db = pParse->db;
- if( p->selFlags & SF_HasTypeInfo ) return;
- if( pParse->nErr || db->mallocFailed ) return;
- sqlite3SelectExpand(pParse, p);
- if( pParse->nErr || db->mallocFailed ) return;
- sqlite3ResolveSelectNames(pParse, p, pOuterNC);
- if( pParse->nErr || db->mallocFailed ) return;
- sqlite3SelectAddTypeInfo(pParse, p);
+ /* If this is one SELECT of a compound, be sure to resolve names
+ ** in the other SELECTs.
+ */
+ if( p->pPrior ){
+ return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC);
+ }else{
+ return SQLITE_OK;
+ }
}
/*
@@ -73133,11 +70230,11 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
assert( nArg==1 );
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
}
- if( pF->pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ if( pF->pFunc->needCollSeq ){
CollSeq *pColl = 0;
struct ExprList_item *pItem;
int j;
- assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */
+ assert( pList!=0 ); /* pList!=0 if pF->pFunc->needCollSeq is true */
for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
}
@@ -73162,7 +70259,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
}
/*
-** Generate code for the SELECT statement given in the p argument.
+** Generate code for the given SELECT statement.
**
** The results are distributed in various ways depending on the
** contents of the SelectDest structure pointed to by argument pDest
@@ -73170,43 +70267,33 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
**
** pDest->eDest Result
** ------------ -------------------------------------------
-** SRT_Output Generate a row of output (using the OP_ResultRow
-** opcode) for each row in the result set.
+** SRT_Callback Invoke the callback for each row of the result.
**
-** SRT_Mem Only valid if the result is a single column.
-** Store the first column of the first result row
-** in register pDest->iParm then abandon the rest
-** of the query. This destination implies "LIMIT 1".
+** SRT_Mem Store first result in memory cell pDest->iParm
**
-** SRT_Set The result must be a single column. Store each
-** row of result as the key in table pDest->iParm.
-** Apply the affinity pDest->affinity before storing
-** results. Used to implement "IN (SELECT ...)".
+** SRT_Set Store results as keys of table pDest->iParm.
+** Apply the affinity pDest->affinity before storing them.
**
** SRT_Union Store results as a key in a temporary table pDest->iParm.
**
** SRT_Except Remove results from the temporary table pDest->iParm.
**
-** SRT_Table Store results in temporary table pDest->iParm.
-** This is like SRT_EphemTab except that the table
-** is assumed to already be open.
+** SRT_Table Store results in temporary table pDest->iParm
**
** SRT_EphemTab Create an temporary table pDest->iParm and store
** the result there. The cursor is left open after
-** returning. This is like SRT_Table except that
-** this destination uses OP_OpenEphemeral to create
-** the table first.
+** returning.
**
-** SRT_Coroutine Generate a co-routine that returns a new row of
-** results each time it is invoked. The entry point
-** of the co-routine is stored in register pDest->iParm.
+** SRT_Coroutine Invoke a co-routine to compute a single row of
+** the result
**
** SRT_Exists Store a 1 in memory cell pDest->iParm if the result
** set is not empty.
**
-** SRT_Discard Throw the results away. This is used by SELECT
-** statements within triggers whose only purpose is
-** the side-effects of functions.
+** SRT_Discard Throw the results away.
+**
+** See the selectInnerLoop() function for a canonical listing of the
+** allowed values of eDest and their meanings.
**
** This routine returns the number of errors. If any errors are
** encountered, then an appropriate error message is left in
@@ -73214,11 +70301,35 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
**
** This routine does NOT free the Select structure passed in. The
** calling function needs to do that.
+**
+** The pParent, parentTab, and *pParentAgg fields are filled in if this
+** SELECT is a subquery. This routine may try to combine this SELECT
+** with its parent to form a single flat query. In so doing, it might
+** change the parent query from a non-aggregate to an aggregate query.
+** For that reason, the pParentAgg flag is passed as a pointer, so it
+** can be changed.
+**
+** Example 1: The meaning of the pParent parameter.
+**
+** SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3;
+** \ \_______ subquery _______/ /
+** \ /
+** \____________________ outer query ___________________/
+**
+** This routine is called for the outer query first. For that call,
+** pParent will be NULL. During the processing of the outer query, this
+** routine is called recursively to handle the subquery. For the recursive
+** call, pParent will point to the outer query. Because the subquery is
+** the second element in a three-way join, the parentTab parameter will
+** be 1 (the 2nd value of a 0-indexed array.)
*/
SQLITE_PRIVATE int sqlite3Select(
Parse *pParse, /* The parser context */
Select *p, /* The SELECT statement being coded. */
- SelectDest *pDest /* What to do with the query results */
+ SelectDest *pDest, /* What to do with the query results */
+ Select *pParent, /* Another SELECT for which this is a sub-query */
+ int parentTab, /* Index in pParent->pSrc of this query */
+ int *pParentAgg /* True if pParent uses aggregate functions */
){
int i, j; /* Loop counters */
WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */
@@ -73254,10 +70365,9 @@ SQLITE_PRIVATE int sqlite3Select(
*/
assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
- p->selFlags &= ~SF_Distinct;
+ p->isDistinct = 0;
}
- sqlite3SelectPrep(pParse, p, 0);
- if( pParse->nErr ){
+ if( sqlite3SelectResolve(pParse, p, 0) ){
goto select_end;
}
p->pOrderBy = pOrderBy;
@@ -73266,7 +70376,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* Make local copies of the parameters for this query.
*/
pTabList = p->pSrc;
- isAgg = (p->selFlags & SF_Aggregate)!=0;
+ isAgg = p->isAgg;
pEList = p->pEList;
if( pEList==0 ) goto select_end;
@@ -73295,8 +70405,18 @@ SQLITE_PRIVATE int sqlite3Select(
SelectDest dest;
Select *pSub = pItem->pSelect;
int isAggSub;
+ char *zName = pItem->zName;
if( pSub==0 || pItem->isPopulated ) continue;
+ if( zName!=0 ){ /* An sql view */
+ const char *zSavedAuthContext = pParse->zAuthContext;
+ pParse->zAuthContext = zName;
+ rc = sqlite3SelectResolve(pParse, pSub, 0);
+ pParse->zAuthContext = zSavedAuthContext;
+ if( rc ){
+ goto select_end;
+ }
+ }
/* Increment Parse.nHeight by the height of the largest expression
** tree refered to by this, the parent select. The child select
@@ -73308,18 +70428,15 @@ SQLITE_PRIVATE int sqlite3Select(
pParse->nHeight += sqlite3SelectExprHeight(p);
/* Check to see if the subquery can be absorbed into the parent. */
- isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
+ isAggSub = pSub->isAgg;
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
if( isAggSub ){
- isAgg = 1;
- p->selFlags |= SF_Aggregate;
+ p->isAgg = isAgg = 1;
}
i = -1;
}else{
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- assert( pItem->isPopulated==0 );
- sqlite3Select(pParse, pSub, &dest);
- pItem->isPopulated = 1;
+ sqlite3Select(pParse, pSub, &dest, p, i, &isAgg);
}
if( pParse->nErr || db->mallocFailed ){
goto select_end;
@@ -73335,7 +70452,7 @@ SQLITE_PRIVATE int sqlite3Select(
pWhere = p->pWhere;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
- isDistinct = (p->selFlags & SF_Distinct)!=0;
+ isDistinct = p->isDistinct;
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* If there is are a sequence of queries, do the earlier ones first.
@@ -73370,12 +70487,12 @@ SQLITE_PRIVATE int sqlite3Select(
#endif
/* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
- ** GROUP BY might use an index, DISTINCT never does.
+ ** GROUP BY may use an index, DISTINCT never does.
*/
- if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && !p->pGroupBy ){
+ if( p->isDistinct && !p->isAgg && !p->pGroupBy ){
p->pGroupBy = sqlite3ExprListDup(db, p->pEList);
pGroupBy = p->pGroupBy;
- p->selFlags &= ~SF_Distinct;
+ p->isDistinct = 0;
isDistinct = 0;
}
@@ -73458,25 +70575,20 @@ SQLITE_PRIVATE int sqlite3Select(
** processed */
int iAbortFlag; /* Mem address which causes query abort if positive */
int groupBySort; /* Rows come from source in GROUP BY order */
- int addrEnd; /* End of processing for this SELECT */
- /* Remove any and all aliases between the result set and the
- ** GROUP BY clause.
- */
- if( pGroupBy ){
- int i; /* Loop counter */
- struct ExprList_item *pItem; /* For looping over expression in a list */
- for(i=p->pEList->nExpr, pItem=p->pEList->a; i>0; i--, pItem++){
- pItem->iAlias = 0;
- }
- for(i=pGroupBy->nExpr, pItem=pGroupBy->a; i>0; i--, pItem++){
- pItem->iAlias = 0;
- }
- }
+ /* The following variables hold addresses or labels for parts of the
+ ** virtual machine program we are putting together */
+ int addrOutputRow; /* Start of subroutine that outputs a result row */
+ int regOutputRow; /* Return address register for output subroutine */
+ int addrSetAbort; /* Set the abort flag and return */
+ int addrInitializeLoop; /* Start of code that initializes the input loop */
+ int addrTopOfLoop; /* Top of the input loop */
+ int addrEnd; /* End of all processing */
+ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
+ int addrReset; /* Subroutine for resetting the accumulator */
+ int regReset; /* Return address register for reset subroutine */
-
- /* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(v);
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
@@ -73505,14 +70617,11 @@ SQLITE_PRIVATE int sqlite3Select(
*/
if( pGroupBy ){
KeyInfo *pKeyInfo; /* Keying information for the group by clause */
- int j1; /* A-vs-B comparision jump */
- int addrOutputRow; /* Start of subroutine that outputs a result row */
- int regOutputRow; /* Return address register for output subroutine */
- int addrSetAbort; /* Set the abort flag and return */
- int addrTopOfLoop; /* Top of the input loop */
- int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
- int addrReset; /* Subroutine for resetting the accumulator */
- int regReset; /* Return address register for reset subroutine */
+ int j1;
+
+ /* Create labels that we will be needing
+ */
+ addrInitializeLoop = sqlite3VdbeMakeLabel(v);
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
@@ -73529,10 +70638,6 @@ SQLITE_PRIVATE int sqlite3Select(
*/
iUseFlag = ++pParse->nMem;
iAbortFlag = ++pParse->nMem;
- regOutputRow = ++pParse->nMem;
- addrOutputRow = sqlite3VdbeMakeLabel(v);
- regReset = ++pParse->nMem;
- addrReset = sqlite3VdbeMakeLabel(v);
iAMem = pParse->nMem + 1;
pParse->nMem += pGroupBy->nExpr;
iBMem = pParse->nMem + 1;
@@ -73541,12 +70646,47 @@ SQLITE_PRIVATE int sqlite3Select(
VdbeComment((v, "clear abort flag"));
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrInitializeLoop);
+
+ /* Generate a subroutine that outputs a single row of the result
+ ** set. This subroutine first looks at the iUseFlag. If iUseFlag
+ ** is less than or equal to zero, the subroutine is a no-op. If
+ ** the processing calls for the query to abort, this subroutine
+ ** increments the iAbortFlag memory location before returning in
+ ** order to signal the caller to abort.
+ */
+ addrSetAbort = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
+ VdbeComment((v, "set abort flag"));
+ regOutputRow = ++pParse->nMem;
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ addrOutputRow = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
+ VdbeComment((v, "Groupby result generator entry point"));
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ finalizeAggFunctions(pParse, &sAggInfo);
+ if( pHaving ){
+ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
+ }
+ selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
+ distinct, pDest,
+ addrOutputRow+1, addrSetAbort);
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ VdbeComment((v, "end groupby result generator"));
+
+ /* Generate a subroutine that will reset the group-by accumulator
+ */
+ addrReset = sqlite3VdbeCurrentAddr(v);
+ regReset = ++pParse->nMem;
+ resetAccumulator(pParse, &sAggInfo);
+ sqlite3VdbeAddOp1(v, OP_Return, regReset);
/* 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
** it might be a single loop that uses an index to extract information
** in the right order to begin with.
*/
+ sqlite3VdbeResolveLabel(v, addrInitializeLoop);
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
if( pWInfo==0 ) goto select_end;
@@ -73586,14 +70726,20 @@ SQLITE_PRIVATE int sqlite3Select(
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
if( pCol->iSorterColumn>=j ){
int r1 = j + regBase;
- int r2;
-
- r2 = sqlite3ExprCodeGetColumn(pParse,
+#ifndef NDEBUG
+ int r2 =
+#endif
+ sqlite3ExprCodeGetColumn(pParse,
pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
- if( r1!=r2 ){
- sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
- }
j++;
+
+ /* sAggInfo.aCol[] only contains one entry per column. So
+ ** The reference to pCol->iColumn,pCol->iTable must have been
+ ** the first reference to that column. Hence,
+ ** sqliteExprCodeGetColumn is guaranteed to put the result in
+ ** the column requested.
+ */
+ assert( r1==r2 );
}
}
regRecord = sqlite3GetTempReg(pParse);
@@ -73664,43 +70810,7 @@ SQLITE_PRIVATE int sqlite3Select(
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
VdbeComment((v, "output final row"));
-
- /* Jump over the subroutines
- */
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd);
-
- /* Generate a subroutine that outputs a single row of the result
- ** set. This subroutine first looks at the iUseFlag. If iUseFlag
- ** is less than or equal to zero, the subroutine is a no-op. If
- ** the processing calls for the query to abort, this subroutine
- ** increments the iAbortFlag memory location before returning in
- ** order to signal the caller to abort.
- */
- addrSetAbort = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
- VdbeComment((v, "set abort flag"));
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- sqlite3VdbeResolveLabel(v, addrOutputRow);
- addrOutputRow = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
- VdbeComment((v, "Groupby result generator entry point"));
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- finalizeAggFunctions(pParse, &sAggInfo);
- if( pHaving ){
- sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
- }
- selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
- distinct, pDest,
- addrOutputRow+1, addrSetAbort);
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- VdbeComment((v, "end groupby result generator"));
-
- /* Generate a subroutine that will reset the group-by accumulator
- */
- sqlite3VdbeResolveLabel(v, addrReset);
- resetAccumulator(pParse, &sAggInfo);
- sqlite3VdbeAddOp1(v, OP_Return, regReset);
-
+
} /* endif pGroupBy */
else {
ExprList *pMinMax = 0;
@@ -73732,7 +70842,7 @@ SQLITE_PRIVATE int sqlite3Select(
** satisfying the 'ORDER BY' clause than it does in other cases.
** Refer to code and comments in where.c for details.
*/
- flag = minMaxQuery(p);
+ flag = minMaxQuery(pParse, p);
if( flag ){
pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList);
if( pMinMax && !db->mallocFailed ){
@@ -73778,6 +70888,19 @@ SQLITE_PRIVATE int sqlite3Select(
generateSortTail(pParse, p, v, pEList->nExpr, pDest);
}
+#ifndef SQLITE_OMIT_SUBQUERY
+ /* If this was a subquery, we have now converted the subquery into a
+ ** temporary table. So set the SrcList_item.isPopulated flag to prevent
+ ** this subquery from being evaluated again and to force the use of
+ ** the temporary table.
+ */
+ if( pParent ){
+ assert( pParent->pSrc->nSrc>parentTab );
+ assert( pParent->pSrc->a[parentTab].pSelect==p );
+ pParent->pSrc->a[parentTab].isPopulated = 1;
+ }
+#endif
+
/* Jump here to skip this query
*/
sqlite3VdbeResolveLabel(v, iEnd);
@@ -73792,9 +70915,10 @@ SQLITE_PRIVATE int sqlite3Select(
*/
select_end:
- /* Identify column names if results of the SELECT are to be output.
+ /* Identify column names if we will be using them in a callback. This
+ ** step is skipped if the output is going to some other destination.
*/
- if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
+ if( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){
generateColumnNames(pParse, pTabList, pEList);
}
@@ -74706,6 +71830,7 @@ static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
** TRIGGER_AFTER.
*/
SQLITE_PRIVATE int sqlite3TriggersExist(
+ Parse *pParse, /* Used to check for recursive triggers */
Table *pTab, /* The table the contains the triggers */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
ExprList *pChanges /* Columns that change in an UPDATE statement */
@@ -74781,7 +71906,8 @@ static int codeTriggerProgram(
SelectDest dest;
sqlite3SelectDestInit(&dest, SRT_Discard, 0);
- sqlite3Select(pParse, ss, &dest);
+ sqlite3SelectResolve(pParse, ss, 0);
+ sqlite3Select(pParse, ss, &dest, 0, 0, 0);
sqlite3SelectDelete(db, ss);
}
break;
@@ -74930,7 +72056,7 @@ SQLITE_PRIVATE int sqlite3CodeRowTrigger(
/* code the WHEN clause */
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
whenExpr = sqlite3ExprDup(db, p->pWhen);
- if( db->mallocFailed || sqlite3ResolveExprNames(&sNC, whenExpr) ){
+ if( db->mallocFailed || sqlite3ExprResolveNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
sqlite3ExprDelete(db, whenExpr);
return 1;
@@ -75098,7 +72224,7 @@ SQLITE_PRIVATE void sqlite3Update(
** updated is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
- triggers_exist = sqlite3TriggersExist(pTab, TK_UPDATE, pChanges);
+ triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges);
isView = pTab->pSelect!=0;
#else
# define triggers_exist 0
@@ -75150,7 +72276,7 @@ SQLITE_PRIVATE void sqlite3Update(
*/
chngRowid = 0;
for(i=0; i<pChanges->nExpr; i++){
- if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
+ if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
@@ -75284,16 +72410,14 @@ SQLITE_PRIVATE void sqlite3Update(
/* If we are trying to update a view, realize that view into
** a ephemeral table.
*/
-#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
- sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+ sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur);
}
-#endif
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
- if( sqlite3ResolveExprNames(&sNC, pWhere) ){
+ if( sqlite3ExprResolveNames(&sNC, pWhere) ){
goto update_cleanup;
}
@@ -75389,7 +72513,6 @@ SQLITE_PRIVATE void sqlite3Update(
*/
if( chngRowid ){
sqlite3ExprCodeAndCache(pParse, pRowidExpr, regRowid);
- sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
}else{
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regRowid);
}
@@ -75481,7 +72604,7 @@ SQLITE_PRIVATE void sqlite3Update(
/* Create the new index entries and the new record.
*/
sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid,
- aRegIdx, 1, -1, 0);
+ aRegIdx, chngRowid, 1, -1, 0);
}
/* Increment the row counter
@@ -75524,7 +72647,7 @@ SQLITE_PRIVATE void sqlite3Update(
if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
sqlite3VdbeSetNumCols(v, 1);
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P4_STATIC);
}
update_cleanup:
@@ -75608,7 +72731,7 @@ static void updateVirtualTable(
/* fill the ephemeral table
*/
sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
- sqlite3Select(pParse, pSelect, &dest);
+ sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
/* Generate code to scan the ephemeral table and call VUpdate. */
iReg = ++pParse->nMem;
@@ -75719,14 +72842,12 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
- Pager *pMainPager; /* Pager for database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
char *zSql = 0; /* SQL statements */
int saved_flags; /* Saved value of the db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
Db *pDb = 0; /* Database to detach at end of vacuum */
- int isMemDb; /* True is vacuuming a :memory: database */
int nRes;
/* Save the current value of the write-schema flag before setting it. */
@@ -75741,8 +72862,6 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
goto end_of_vacuum;
}
pMain = db->aDb[0].pBt;
- pMainPager = sqlite3BtreePager(pMain);
- isMemDb = sqlite3PagerFile(pMainPager)->pMethods==0;
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
@@ -75779,7 +72898,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
#endif
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes)
- || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes))
+ || sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes)
|| db->mallocFailed
){
rc = SQLITE_NOMEM;
@@ -75889,7 +73008,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
assert( 1==sqlite3BtreeIsInTrans(pMain) );
/* Copy Btree meta values */
- for(i=0; i<ArraySize(aCopy); i+=2){
+ for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){
rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
@@ -75900,9 +73019,6 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
-#endif
rc = sqlite3BtreeCommit(pMain);
}
@@ -75986,8 +73102,6 @@ static int createModule(
db->mallocFailed = 1;
}
sqlite3ResetInternalSchema(db, 0);
- }else if( xDestroy ){
- xDestroy(pAux);
}
rc = sqlite3ApiExit(db, SQLITE_OK);
sqlite3_mutex_leave(db->mutex);
@@ -76128,7 +73242,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 );
- pTable->tabFlags |= TF_Virtual;
+ pTable->isVirtual = 1;
pTable->nModuleArg = 0;
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
@@ -76384,7 +73498,7 @@ SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
Module *pMod;
int rc = SQLITE_OK;
- if( !pTab || (pTab->tabFlags & TF_Virtual)==0 || pTab->pVtab ){
+ if( !pTab || !pTab->isVirtual || pTab->pVtab ){
return SQLITE_OK;
}
@@ -76445,7 +73559,7 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab,
const char *zModule;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
- assert(pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVtab);
+ assert(pTab && pTab->isVirtual && !pTab->pVtab);
pMod = pTab->pMod;
zModule = pTab->azModuleArg[0];
@@ -76486,7 +73600,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE;
}
- assert((pTab->tabFlags & TF_Virtual)!=0 && pTab->nCol==0 && pTab->aCol==0);
+ assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
memset(&sParse, 0, sizeof(Parse));
sParse.declareVtab = 1;
@@ -76496,7 +73610,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) &&
sParse.pNewTable &&
!sParse.pNewTable->pSelect &&
- (sParse.pNewTable->tabFlags & TF_Virtual)==0
+ !sParse.pNewTable->isVirtual
){
pTab->aCol = sParse.pNewTable->aCol;
pTab->nCol = sParse.pNewTable->nCol;
@@ -76652,7 +73766,7 @@ SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){
** virtual module xSync() callback. It is illegal to write to
** virtual module tables in this case, so return SQLITE_LOCKED.
*/
- if( sqlite3VtabInSync(db) ){
+ if( 0==db->aVTrans && db->nVTrans>0 ){
return SQLITE_LOCKED;
}
if( !pVtab ){
@@ -76715,7 +73829,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
if( pExpr->op!=TK_COLUMN ) return pDef;
pTab = pExpr->pTab;
if( pTab==0 ) return pDef;
- if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
+ if( !pTab->isVirtual ) return pDef;
pVtab = pTab->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
@@ -76749,7 +73863,6 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
return pDef;
}
*pNew = *pDef;
- pNew->zName = (char *)&pNew[1];
memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1);
pNew->xFunc = xFunc;
pNew->pUserData = pArg;
@@ -76804,6 +73917,11 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
*/
/*
+** The number of bits in a Bitmask. "BMS" means "BitMask Size".
+*/
+#define BMS (sizeof(Bitmask)*8)
+
+/*
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
@@ -76917,7 +74035,7 @@ struct WhereClause {
*/
struct ExprMaskSet {
int n; /* Number of assigned cursor values */
- int ix[BMS]; /* Cursor assigned to each bit */
+ int ix[sizeof(Bitmask)*8]; /* Cursor assigned to each bit */
};
@@ -77098,9 +74216,9 @@ static void createMask(ExprMaskSet *pMaskSet, int iCursor){
** tree.
**
** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ResolveExprNames() on the expression. See
+** previously invoked sqlite3ExprResolveNames() on the expression. See
** the header comment on that routine for additional information.
-** The sqlite3ResolveExprNames() routines looks for column names and
+** The sqlite3ExprResolveNames() routines looks for column names and
** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
** the VDBE cursor number of the table. This routine just has to
** translate the cursor numbers into bitmask values and OR all
@@ -77174,12 +74292,10 @@ static int allowedOp(int op){
** attached to the right. For the same reason the EP_ExpCollate flag
** is not commuted.
*/
-static void exprCommute(Parse *pParse, Expr *pExpr){
+static void exprCommute(Expr *pExpr){
u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
- pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
- pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
@@ -77299,7 +74415,7 @@ static void exprAnalyzeAll(
** literal that does not begin with a wildcard.
*/
static int isLikeOrGlob(
- Parse *pParse, /* Parsing and code generating context */
+ sqlite3 *db, /* The database */
Expr *pExpr, /* Test this expression */
int *pnPattern, /* Number of non-wildcard prefix characters */
int *pisComplete, /* True if the only wildcard is % in the last character */
@@ -77311,7 +74427,6 @@ static int isLikeOrGlob(
int c, cnt;
char wc[3];
CollSeq *pColl;
- sqlite3 *db = pParse->db;
if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
return 0;
@@ -77329,7 +74444,7 @@ static int isLikeOrGlob(
if( pLeft->op!=TK_COLUMN ){
return 0;
}
- pColl = sqlite3ExprCollSeq(pParse, pLeft);
+ pColl = pLeft->pColl;
assert( pColl!=0 || pLeft->iColumn==-1 );
if( pColl==0 ){
/* No collation is defined for the ROWID. Use the default. */
@@ -77569,7 +74684,7 @@ static void exprAnalyze(
pDup = pExpr;
pNew = pTerm;
}
- exprCommute(pParse, pDup);
+ exprCommute(pDup);
pLeft = pDup->pLeft;
pNew->leftCursor = pLeft->iTable;
pNew->leftColumn = pLeft->iColumn;
@@ -77690,7 +74805,7 @@ or_not_possible:
** The last character of the prefix "abc" is incremented to form the
** termination condition "abd".
*/
- if( isLikeOrGlob(pParse, pExpr, &nPattern, &isComplete, &noCase) ){
+ if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete, &noCase) ){
Expr *pLeft, *pRight;
Expr *pStr1, *pStr2;
Expr *pNewExpr1, *pNewExpr2;
@@ -78064,7 +75179,7 @@ static double bestVirtualIndex(
** to this virtual table */
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+ if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
testcase( pTerm->eOperator==WO_IN );
testcase( pTerm->eOperator==WO_ISNULL );
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
@@ -78114,7 +75229,7 @@ static double bestVirtualIndex(
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+ if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
testcase( pTerm->eOperator==WO_IN );
testcase( pTerm->eOperator==WO_ISNULL );
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
@@ -78251,16 +75366,6 @@ static double bestVirtualIndex(
** * Whether or not there must be separate lookups in the
** index and in the main table.
**
-** If there was an INDEXED BY clause attached to the table in the SELECT
-** statement, then this function only considers strategies using the
-** named index. If one cannot be found, then the returned cost is
-** SQLITE_BIG_DBL. If a strategy can be found that uses the named index,
-** then the cost is calculated in the usual way.
-**
-** If a NOT INDEXED clause was attached to the table in the SELECT
-** statement, then no indexes are considered. However, the selected
-** stategy may still take advantage of the tables built-in rowid
-** index.
*/
static double bestIndex(
Parse *pParse, /* The parsing context */
@@ -78288,9 +75393,6 @@ static double bestIndex(
WHERETRACE(("bestIndex: tbl=%s notReady=%llx\n", pSrc->pTab->zName, notReady));
lowestCost = SQLITE_BIG_DBL;
pProbe = pSrc->pTab->pIndex;
- if( pSrc->notIndexed ){
- pProbe = 0;
- }
/* If the table has no indices and there are no terms in the where
** clause that refer to the ROWID, then we will never be able to do
@@ -78307,77 +75409,74 @@ static double bestIndex(
return 0.0;
}
- /* Check for a rowid=EXPR or rowid IN (...) constraints. If there was
- ** an INDEXED BY clause attached to this table, skip this step.
+ /* Check for a rowid=EXPR or rowid IN (...) constraints
*/
- if( !pSrc->pIndex ){
- pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
- if( pTerm ){
- Expr *pExpr;
- *ppIndex = 0;
- bestFlags = WHERE_ROWID_EQ;
- if( pTerm->eOperator & WO_EQ ){
- /* Rowid== is always the best pick. Look no further. Because only
- ** a single row is generated, output is always in sorted order */
- *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
- *pnEq = 1;
- WHERETRACE(("... best is rowid\n"));
- return 0.0;
- }else if( (pExpr = pTerm->pExpr)->pList!=0 ){
- /* Rowid IN (LIST): cost is NlogN where N is the number of list
- ** elements. */
- lowestCost = pExpr->pList->nExpr;
- lowestCost *= estLog(lowestCost);
- }else{
- /* Rowid IN (SELECT): cost is NlogN where N is the number of rows
- ** in the result of the inner select. We have no way to estimate
- ** that value so make a wild guess. */
- lowestCost = 200;
- }
- WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost));
- }
-
- /* Estimate the cost of a table scan. If we do not know how many
- ** entries are in the table, use 1 million as a guess.
- */
- cost = pProbe ? pProbe->aiRowEst[0] : 1000000;
- WHERETRACE(("... table scan base cost: %.9g\n", cost));
- flags = WHERE_ROWID_RANGE;
-
- /* Check for constraints on a range of rowids in a table scan.
- */
- pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0);
- if( pTerm ){
- if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){
- flags |= WHERE_TOP_LIMIT;
- cost /= 3; /* Guess that rowid<EXPR eliminates two-thirds or rows */
- }
- if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
- flags |= WHERE_BTM_LIMIT;
- cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */
- }
- WHERETRACE(("... rowid range reduces cost to %.9g\n", cost));
+ pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
+ if( pTerm ){
+ Expr *pExpr;
+ *ppIndex = 0;
+ bestFlags = WHERE_ROWID_EQ;
+ if( pTerm->eOperator & WO_EQ ){
+ /* Rowid== is always the best pick. Look no further. Because only
+ ** a single row is generated, output is always in sorted order */
+ *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
+ *pnEq = 1;
+ WHERETRACE(("... best is rowid\n"));
+ return 0.0;
+ }else if( (pExpr = pTerm->pExpr)->pList!=0 ){
+ /* Rowid IN (LIST): cost is NlogN where N is the number of list
+ ** elements. */
+ lowestCost = pExpr->pList->nExpr;
+ lowestCost *= estLog(lowestCost);
}else{
- flags = 0;
+ /* Rowid IN (SELECT): cost is NlogN where N is the number of rows
+ ** in the result of the inner select. We have no way to estimate
+ ** that value so make a wild guess. */
+ lowestCost = 200;
}
-
- /* If the table scan does not satisfy the ORDER BY clause, increase
- ** the cost by NlogN to cover the expense of sorting. */
- if( pOrderBy ){
- if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){
- flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
- if( rev ){
- flags |= WHERE_REVERSE;
- }
- }else{
- cost += cost*estLog(cost);
- WHERETRACE(("... sorting increases cost to %.9g\n", cost));
- }
+ WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost));
+ }
+
+ /* Estimate the cost of a table scan. If we do not know how many
+ ** entries are in the table, use 1 million as a guess.
+ */
+ cost = pProbe ? pProbe->aiRowEst[0] : 1000000;
+ WHERETRACE(("... table scan base cost: %.9g\n", cost));
+ flags = WHERE_ROWID_RANGE;
+
+ /* Check for constraints on a range of rowids in a table scan.
+ */
+ pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0);
+ if( pTerm ){
+ if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){
+ flags |= WHERE_TOP_LIMIT;
+ cost /= 3; /* Guess that rowid<EXPR eliminates two-thirds or rows */
}
- if( cost<lowestCost ){
- lowestCost = cost;
- bestFlags = flags;
+ if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
+ flags |= WHERE_BTM_LIMIT;
+ cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */
}
+ WHERETRACE(("... rowid range reduces cost to %.9g\n", cost));
+ }else{
+ flags = 0;
+ }
+
+ /* If the table scan does not satisfy the ORDER BY clause, increase
+ ** the cost by NlogN to cover the expense of sorting. */
+ if( pOrderBy ){
+ if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){
+ flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
+ if( rev ){
+ flags |= WHERE_REVERSE;
+ }
+ }else{
+ cost += cost*estLog(cost);
+ WHERETRACE(("... sorting increases cost to %.9g\n", cost));
+ }
+ }
+ if( cost<lowestCost ){
+ lowestCost = cost;
+ bestFlags = flags;
}
/* If the pSrc table is the right table of a LEFT JOIN then we may not
@@ -78393,10 +75492,7 @@ static double bestIndex(
/* Look at each index.
*/
- if( pSrc->pIndex ){
- pProbe = pSrc->pIndex;
- }
- for(; pProbe; pProbe=(pSrc->pIndex ? 0 : pProbe->pNext)){
+ for(; pProbe; pProbe=pProbe->pNext){
int i; /* Loop counter */
double inMultiplier = 1;
@@ -78581,7 +75677,9 @@ static int codeEqualityTerm(
Vdbe *v = pParse->pVdbe;
int iReg; /* Register holding results */
- assert( iTarget>0 );
+ if( iTarget<=0 ){
+ iReg = iTarget = sqlite3GetTempReg(pParse);
+ }
if( pX->op==TK_EQ ){
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
}else if( pX->op==TK_ISNULL ){
@@ -78709,9 +75807,10 @@ static int nQPlan = 0; /* Next free slow in _query_plan[] */
/*
** Free a WhereInfo structure
*/
-static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
+static void whereInfoFree(WhereInfo *pWInfo){
if( pWInfo ){
int i;
+ sqlite3 *db = pWInfo->pParse->db;
for(i=0; i<pWInfo->nLevel; i++){
sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
if( pInfo ){
@@ -78861,7 +75960,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWInfo = sqlite3DbMallocZero(db,
sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
if( db->mallocFailed ){
- goto whereBeginError;
+ goto whereBeginNoMem;
}
pWInfo->nLevel = pTabList->nSrc;
pWInfo->pParse = pParse;
@@ -78908,7 +76007,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
*/
exprAnalyzeAll(pTabList, &wc);
if( db->mallocFailed ){
- goto whereBeginError;
+ goto whereBeginNoMem;
}
/* Chose the best index to use for each table in the FROM clause.
@@ -78918,7 +76017,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** pWInfo->a[].pIdx The index to use for this level of the loop.
** pWInfo->a[].flags WHERE_xxx flags associated with pIdx
** pWInfo->a[].nEq The number of == and IN constraints
- ** pWInfo->a[].iFrom Which term of the FROM clause is being coded
+ ** pWInfo->a[].iFrom When term of the FROM clause is being coded
** pWInfo->a[].iTabCur The VDBE cursor for the database table
** pWInfo->a[].iIdxCur The VDBE cursor for the index
**
@@ -79015,18 +76114,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor);
pLevel->iFrom = bestJ;
-
- /* Check that if the table scanned by this loop iteration had an
- ** INDEXED BY clause attached to it, that the named index is being
- ** used for the scan. If not, then query compilation has failed.
- ** Return an error.
- */
- pIdx = pTabList->a[bestJ].pIndex;
- assert( !pIdx || !pBest || pIdx==pBest );
- if( pIdx && pBest!=pIdx ){
- sqlite3ErrorMsg(pParse, "cannot use index: %s", pIdx->zName);
- goto whereBeginError;
- }
}
WHERETRACE(("*** Optimizer Finished ***\n"));
@@ -79087,7 +76174,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
+ if( pTab->isEphem || pTab->pSelect ) continue;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pLevel->pBestIdx ){
int iCur = pTabItem->iCursor;
@@ -79098,7 +76185,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
- if( !pWInfo->okOnePass && pTab->nCol<BMS ){
+ if( !pWInfo->okOnePass && pTab->nCol<(sizeof(Bitmask)*8) ){
Bitmask b = pTabItem->colUsed;
int n = 0;
for(; b; b=b>>1, n++){}
@@ -79127,7 +76214,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
*/
notReady = ~(Bitmask)0;
for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
- int j, k;
+ int j;
int iCur = pTabItem->iCursor; /* The VDBE cursor for the table */
Index *pIdx; /* The index we will be using */
int nxt; /* Where to jump to continue with the next IN case */
@@ -79220,17 +76307,15 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** construct.
*/
int r1;
- int rtmp = sqlite3GetTempReg(pParse);
pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0);
assert( pTerm!=0 );
assert( pTerm->pExpr!=0 );
assert( pTerm->leftCursor==iCur );
assert( omitTable==0 );
- r1 = codeEqualityTerm(pParse, pTerm, pLevel, rtmp);
+ r1 = codeEqualityTerm(pParse, pTerm, pLevel, 0);
nxt = pLevel->nxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
- sqlite3ReleaseTempReg(pParse, rtmp);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
}else if( pLevel->flags & WHERE_ROWID_RANGE ){
@@ -79250,26 +76335,16 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
if( pStart ){
Expr *pX;
- int r1;
+ int r1, regFree1;
pX = pStart->pExpr;
assert( pX!=0 );
assert( pStart->leftCursor==iCur );
-
- /* The ForceInt instruction may modify the register that it operates
- ** on. For example it may replace a real value with an integer one,
- ** or if p3 is true it may increment the register value. For this
- ** reason we need to make sure that register r1 is really a newly
- ** allocated temporary register, and not part of the column-cache.
- ** For this reason we cannot use sqlite3ExprCodeTemp() here.
- */
- r1 = sqlite3GetTempReg(pParse);
- sqlite3ExprCode(pParse, pX->pRight, r1);
-
+ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &regFree1);
sqlite3VdbeAddOp3(v, OP_ForceInt, r1, brk,
pX->op==TK_LE || pX->op==TK_GT);
sqlite3VdbeAddOp3(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk, r1);
VdbeComment((v, "pk"));
- sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3ReleaseTempReg(pParse, regFree1);
disableTerm(pLevel, pStart);
}else{
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
@@ -79497,14 +76572,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pLevel->op = OP_Next;
pLevel->p1 = iCur;
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, brk);
- pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}
notReady &= ~getMask(&maskSet, iCur);
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
*/
- k = 0;
for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){
Expr *pE;
testcase( pTerm->flags & TERM_VIRTUAL );
@@ -79516,10 +76589,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
continue;
}
- pParse->disableColCache += k;
sqlite3ExprIfFalse(pParse, pE, cont, SQLITE_JUMPIFNULL);
- pParse->disableColCache -= k;
- k = 1;
pTerm->flags |= TERM_CODED;
}
@@ -79601,9 +76671,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
return pWInfo;
/* Jump here if malloc fails */
-whereBeginError:
+whereBeginNoMem:
whereClauseClear(&wc);
- whereInfoFree(db, pWInfo);
+ whereInfoFree(pWInfo);
return 0;
}
@@ -79627,7 +76697,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeResolveLabel(v, pLevel->cont);
if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
- sqlite3VdbeChangeP5(v, pLevel->p5);
}
if( pLevel->nIn ){
struct InLoop *pIn;
@@ -79664,7 +76733,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
- if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
+ if( pTab->isEphem || pTab->pSelect ) continue;
if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
}
@@ -79717,7 +76786,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Final cleanup
*/
- whereInfoFree(db, pWInfo);
+ whereInfoFree(pWInfo);
return;
}
@@ -79814,23 +76883,23 @@ struct AttachKey { int type; Token key; };
** defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
-#define YYNOCODE 249
+#define YYNOCODE 248
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 59
#define sqlite3ParserTOKENTYPE Token
typedef union {
sqlite3ParserTOKENTYPE yy0;
- Select* yy43;
- TriggerStep* yy75;
- struct LimitVal yy84;
- struct LikeOp yy86;
- struct {int value; int mask;} yy207;
- ExprList* yy242;
- int yy316;
- IdList* yy352;
- struct TrigEvent yy354;
- SrcList* yy419;
- Expr* yy450;
+ int yy46;
+ struct LikeOp yy72;
+ Expr* yy172;
+ ExprList* yy174;
+ Select* yy219;
+ struct LimitVal yy234;
+ TriggerStep* yy243;
+ struct TrigEvent yy370;
+ SrcList* yy373;
+ struct {int value; int mask;} yy405;
+ IdList* yy432;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -79839,8 +76908,8 @@ typedef union {
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 598
-#define YYNRULE 315
+#define YYNSTATE 589
+#define YYNRULE 313
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
@@ -79848,11 +76917,7 @@ typedef union {
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
-#if 0
-static YYMINORTYPE yyzerominor;
-#else
static const YYMINORTYPE yyzerominor;
-#endif
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
@@ -79902,420 +76967,416 @@ static const YYMINORTYPE yyzerominor;
** yy_default[] Default action for each state.
*/
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 296, 914, 120, 597, 2, 172, 425, 425, 62, 62,
- /* 10 */ 62, 62, 210, 64, 64, 64, 64, 65, 65, 66,
- /* 20 */ 66, 66, 67, 212, 398, 395, 432, 438, 69, 64,
- /* 30 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 212,
- /* 40 */ 458, 456, 327, 168, 61, 60, 301, 442, 443, 439,
- /* 50 */ 439, 63, 63, 62, 62, 62, 62, 256, 64, 64,
- /* 60 */ 64, 64, 65, 65, 66, 66, 66, 67, 212, 296,
- /* 70 */ 498, 425, 425, 212, 427, 83, 68, 469, 70, 154,
- /* 80 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
- /* 90 */ 212, 68, 307, 70, 154, 432, 438, 454, 214, 59,
- /* 100 */ 65, 65, 66, 66, 66, 67, 212, 429, 429, 429,
- /* 110 */ 497, 583, 296, 61, 60, 301, 442, 443, 439, 439,
- /* 120 */ 63, 63, 62, 62, 62, 62, 321, 64, 64, 64,
- /* 130 */ 64, 65, 65, 66, 66, 66, 67, 212, 432, 438,
- /* 140 */ 95, 66, 66, 66, 67, 212, 403, 256, 421, 35,
- /* 150 */ 57, 67, 212, 175, 417, 499, 61, 60, 301, 442,
- /* 160 */ 443, 439, 439, 63, 63, 62, 62, 62, 62, 19,
- /* 170 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
- /* 180 */ 212, 296, 225, 532, 299, 581, 109, 422, 242, 458,
- /* 190 */ 416, 335, 414, 21, 502, 503, 346, 403, 527, 176,
- /* 200 */ 160, 454, 214, 580, 579, 344, 500, 432, 438, 149,
- /* 210 */ 150, 404, 405, 539, 514, 418, 151, 541, 8, 498,
- /* 220 */ 538, 577, 578, 427, 296, 61, 60, 301, 442, 443,
- /* 230 */ 439, 439, 63, 63, 62, 62, 62, 62, 196, 64,
- /* 240 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 212,
- /* 250 */ 432, 438, 454, 598, 398, 395, 429, 429, 429, 369,
- /* 260 */ 558, 481, 404, 405, 372, 576, 213, 296, 61, 60,
- /* 270 */ 301, 442, 443, 439, 439, 63, 63, 62, 62, 62,
- /* 280 */ 62, 321, 64, 64, 64, 64, 65, 65, 66, 66,
- /* 290 */ 66, 67, 212, 432, 438, 555, 503, 304, 557, 532,
- /* 300 */ 218, 557, 552, 421, 36, 234, 397, 2, 542, 21,
- /* 310 */ 540, 61, 60, 301, 442, 443, 439, 439, 63, 63,
- /* 320 */ 62, 62, 62, 62, 388, 64, 64, 64, 64, 65,
- /* 330 */ 65, 66, 66, 66, 67, 212, 415, 530, 85, 381,
- /* 340 */ 78, 323, 296, 210, 304, 527, 493, 492, 379, 274,
- /* 350 */ 273, 379, 274, 273, 347, 463, 241, 387, 268, 210,
- /* 360 */ 533, 581, 210, 403, 20, 224, 144, 464, 432, 438,
- /* 370 */ 485, 164, 114, 248, 349, 253, 350, 177, 554, 580,
- /* 380 */ 465, 420, 331, 81, 257, 419, 61, 60, 301, 442,
- /* 390 */ 443, 439, 439, 63, 63, 62, 62, 62, 62, 391,
- /* 400 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
- /* 410 */ 212, 296, 224, 203, 249, 496, 403, 440, 837, 114,
- /* 420 */ 248, 349, 253, 350, 177, 250, 321, 152, 404, 405,
- /* 430 */ 321, 257, 303, 324, 155, 445, 445, 432, 438, 317,
- /* 440 */ 400, 389, 213, 68, 209, 70, 154, 422, 421, 35,
- /* 450 */ 393, 202, 421, 42, 481, 61, 60, 301, 442, 443,
- /* 460 */ 439, 439, 63, 63, 62, 62, 62, 62, 422, 64,
- /* 470 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 212,
- /* 480 */ 296, 404, 405, 183, 513, 422, 351, 354, 355, 403,
- /* 490 */ 77, 335, 79, 489, 216, 183, 334, 356, 351, 354,
- /* 500 */ 355, 433, 434, 406, 407, 408, 432, 438, 235, 356,
- /* 510 */ 386, 68, 291, 70, 154, 456, 531, 168, 198, 302,
- /* 520 */ 449, 450, 436, 437, 61, 60, 301, 442, 443, 439,
- /* 530 */ 439, 63, 63, 62, 62, 62, 62, 394, 64, 64,
- /* 540 */ 64, 64, 65, 65, 66, 66, 66, 67, 212, 296,
- /* 550 */ 321, 435, 422, 260, 404, 405, 321, 183, 153, 321,
- /* 560 */ 351, 354, 355, 446, 332, 321, 595, 905, 321, 905,
- /* 570 */ 1, 356, 421, 28, 403, 432, 438, 376, 421, 42,
- /* 580 */ 477, 421, 35, 213, 548, 366, 548, 421, 50, 159,
- /* 590 */ 421, 50, 422, 61, 60, 301, 442, 443, 439, 439,
- /* 600 */ 63, 63, 62, 62, 62, 62, 592, 64, 64, 64,
- /* 610 */ 64, 65, 65, 66, 66, 66, 67, 212, 296, 337,
- /* 620 */ 217, 463, 256, 94, 339, 326, 449, 450, 172, 340,
- /* 630 */ 425, 345, 532, 464, 312, 595, 904, 313, 904, 404,
- /* 640 */ 405, 588, 21, 226, 432, 438, 465, 243, 504, 324,
- /* 650 */ 322, 445, 445, 421, 3, 459, 230, 308, 505, 194,
- /* 660 */ 278, 296, 61, 60, 301, 442, 443, 439, 439, 63,
- /* 670 */ 63, 62, 62, 62, 62, 592, 64, 64, 64, 64,
- /* 680 */ 65, 65, 66, 66, 66, 67, 212, 432, 438, 213,
- /* 690 */ 179, 180, 181, 422, 324, 425, 445, 445, 281, 262,
- /* 700 */ 279, 402, 194, 481, 296, 61, 60, 301, 442, 443,
- /* 710 */ 439, 439, 63, 63, 62, 62, 62, 62, 377, 64,
- /* 720 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 212,
- /* 730 */ 432, 438, 591, 295, 115, 268, 422, 266, 211, 264,
- /* 740 */ 373, 324, 246, 445, 445, 56, 256, 296, 61, 71,
- /* 750 */ 301, 442, 443, 439, 439, 63, 63, 62, 62, 62,
- /* 760 */ 62, 377, 64, 64, 64, 64, 65, 65, 66, 66,
- /* 770 */ 66, 67, 212, 432, 438, 550, 269, 474, 18, 549,
- /* 780 */ 280, 309, 343, 380, 171, 160, 256, 268, 5, 268,
- /* 790 */ 296, 368, 60, 301, 442, 443, 439, 439, 63, 63,
- /* 800 */ 62, 62, 62, 62, 321, 64, 64, 64, 64, 65,
- /* 810 */ 65, 66, 66, 66, 67, 212, 432, 438, 403, 10,
- /* 820 */ 403, 310, 268, 403, 268, 485, 421, 29, 566, 22,
- /* 830 */ 568, 420, 428, 425, 376, 419, 301, 442, 443, 439,
- /* 840 */ 439, 63, 63, 62, 62, 62, 62, 321, 64, 64,
- /* 850 */ 64, 64, 65, 65, 66, 66, 66, 67, 212, 73,
- /* 860 */ 328, 485, 4, 569, 268, 570, 300, 268, 147, 421,
- /* 870 */ 24, 321, 359, 321, 325, 73, 328, 491, 4, 455,
- /* 880 */ 321, 342, 300, 404, 405, 404, 405, 367, 404, 405,
- /* 890 */ 325, 330, 321, 421, 33, 421, 54, 321, 425, 178,
- /* 900 */ 229, 458, 421, 53, 321, 227, 321, 330, 228, 478,
- /* 910 */ 165, 321, 315, 119, 421, 99, 333, 458, 321, 421,
- /* 920 */ 97, 76, 75, 311, 268, 519, 421, 102, 421, 103,
- /* 930 */ 74, 319, 320, 421, 108, 427, 467, 76, 75, 490,
- /* 940 */ 421, 110, 452, 452, 321, 520, 74, 319, 320, 73,
- /* 950 */ 328, 427, 4, 210, 298, 321, 300, 321, 156, 257,
- /* 960 */ 321, 210, 185, 182, 325, 284, 421, 17, 429, 429,
- /* 970 */ 429, 430, 431, 12, 593, 378, 188, 421, 100, 421,
- /* 980 */ 34, 330, 421, 98, 429, 429, 429, 430, 431, 12,
- /* 990 */ 475, 458, 422, 162, 480, 321, 422, 306, 231, 232,
- /* 1000 */ 233, 105, 484, 632, 476, 321, 486, 447, 321, 23,
- /* 1010 */ 422, 76, 75, 594, 207, 178, 286, 421, 25, 254,
- /* 1020 */ 74, 319, 320, 287, 321, 427, 321, 421, 55, 321,
- /* 1030 */ 421, 111, 321, 471, 321, 205, 515, 557, 511, 363,
- /* 1040 */ 472, 204, 321, 516, 206, 321, 421, 112, 421, 113,
- /* 1050 */ 321, 421, 26, 321, 421, 37, 421, 38, 429, 429,
- /* 1060 */ 429, 430, 431, 12, 421, 27, 521, 421, 39, 321,
- /* 1070 */ 298, 158, 421, 40, 255, 421, 41, 321, 483, 321,
- /* 1080 */ 173, 523, 321, 182, 321, 522, 321, 384, 283, 273,
- /* 1090 */ 321, 421, 43, 297, 534, 321, 476, 321, 210, 421,
- /* 1100 */ 44, 421, 45, 321, 421, 30, 421, 31, 421, 46,
- /* 1110 */ 508, 509, 421, 47, 259, 321, 182, 421, 48, 421,
- /* 1120 */ 49, 321, 358, 390, 182, 421, 32, 321, 261, 518,
- /* 1130 */ 517, 553, 561, 182, 173, 412, 191, 421, 11, 562,
- /* 1140 */ 573, 92, 92, 421, 51, 590, 263, 294, 265, 421,
- /* 1150 */ 52, 267, 272, 371, 146, 374, 375, 275, 276, 277,
- /* 1160 */ 565, 575, 285, 288, 289, 587, 470, 451, 236, 453,
- /* 1170 */ 329, 244, 473, 514, 251, 524, 560, 163, 401, 572,
- /* 1180 */ 426, 525, 282, 528, 409, 7, 410, 411, 385, 318,
- /* 1190 */ 85, 237, 338, 526, 84, 336, 353, 58, 80, 215,
- /* 1200 */ 170, 468, 121, 86, 341, 348, 305, 501, 506, 124,
- /* 1210 */ 511, 222, 360, 423, 252, 186, 512, 510, 221, 223,
- /* 1220 */ 238, 507, 239, 535, 240, 292, 424, 529, 536, 537,
- /* 1230 */ 293, 543, 187, 189, 245, 362, 482, 488, 247, 190,
- /* 1240 */ 364, 89, 545, 192, 117, 370, 132, 556, 563, 195,
- /* 1250 */ 382, 383, 314, 133, 134, 571, 138, 135, 136, 584,
- /* 1260 */ 589, 585, 142, 399, 101, 413, 220, 586, 270, 104,
- /* 1270 */ 141, 633, 634, 166, 167, 441, 444, 72, 460, 448,
- /* 1280 */ 457, 546, 143, 157, 6, 461, 14, 479, 169, 462,
- /* 1290 */ 93, 466, 82, 122, 13, 174, 487, 96, 123, 161,
- /* 1300 */ 494, 495, 87, 125, 126, 116, 258, 88, 127, 184,
- /* 1310 */ 250, 361, 219, 107, 544, 145, 128, 193, 365, 118,
- /* 1320 */ 352, 357, 173, 271, 130, 9, 316, 559, 197, 90,
- /* 1330 */ 547, 131, 129, 15, 199, 551, 564, 200, 567, 201,
- /* 1340 */ 139, 137, 582, 91, 16, 106, 140, 208, 574, 392,
- /* 1350 */ 396, 290, 148, 596,
+ /* 0 */ 292, 903, 124, 588, 409, 172, 2, 418, 61, 61,
+ /* 10 */ 61, 61, 519, 63, 63, 63, 63, 64, 64, 65,
+ /* 20 */ 65, 65, 66, 210, 447, 212, 425, 431, 68, 63,
+ /* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 210,
+ /* 40 */ 391, 388, 396, 451, 60, 59, 297, 435, 436, 432,
+ /* 50 */ 432, 62, 62, 61, 61, 61, 61, 263, 63, 63,
+ /* 60 */ 63, 63, 64, 64, 65, 65, 65, 66, 210, 292,
+ /* 70 */ 493, 494, 418, 489, 208, 82, 67, 420, 69, 154,
+ /* 80 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
+ /* 90 */ 210, 67, 462, 69, 154, 425, 431, 574, 264, 58,
+ /* 100 */ 64, 64, 65, 65, 65, 66, 210, 397, 398, 422,
+ /* 110 */ 422, 422, 292, 60, 59, 297, 435, 436, 432, 432,
+ /* 120 */ 62, 62, 61, 61, 61, 61, 317, 63, 63, 63,
+ /* 130 */ 63, 64, 64, 65, 65, 65, 66, 210, 425, 431,
+ /* 140 */ 94, 65, 65, 65, 66, 210, 396, 210, 414, 34,
+ /* 150 */ 56, 298, 442, 443, 410, 418, 60, 59, 297, 435,
+ /* 160 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 208,
+ /* 170 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
+ /* 180 */ 210, 292, 372, 524, 295, 572, 113, 408, 522, 451,
+ /* 190 */ 331, 317, 407, 20, 244, 340, 519, 396, 478, 531,
+ /* 200 */ 505, 447, 212, 571, 570, 245, 530, 425, 431, 149,
+ /* 210 */ 150, 397, 398, 414, 41, 211, 151, 533, 488, 489,
+ /* 220 */ 418, 568, 569, 420, 292, 60, 59, 297, 435, 436,
+ /* 230 */ 432, 432, 62, 62, 61, 61, 61, 61, 317, 63,
+ /* 240 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 210,
+ /* 250 */ 425, 431, 447, 333, 215, 422, 422, 422, 363, 299,
+ /* 260 */ 414, 41, 397, 398, 366, 567, 211, 292, 60, 59,
+ /* 270 */ 297, 435, 436, 432, 432, 62, 62, 61, 61, 61,
+ /* 280 */ 61, 396, 63, 63, 63, 63, 64, 64, 65, 65,
+ /* 290 */ 65, 66, 210, 425, 431, 491, 300, 524, 474, 66,
+ /* 300 */ 210, 214, 474, 229, 411, 286, 534, 20, 449, 523,
+ /* 310 */ 168, 60, 59, 297, 435, 436, 432, 432, 62, 62,
+ /* 320 */ 61, 61, 61, 61, 474, 63, 63, 63, 63, 64,
+ /* 330 */ 64, 65, 65, 65, 66, 210, 209, 480, 317, 77,
+ /* 340 */ 292, 239, 300, 55, 484, 490, 397, 398, 181, 547,
+ /* 350 */ 494, 345, 348, 349, 67, 152, 69, 154, 339, 524,
+ /* 360 */ 414, 35, 350, 241, 221, 370, 425, 431, 579, 20,
+ /* 370 */ 164, 118, 243, 343, 248, 344, 176, 322, 442, 443,
+ /* 380 */ 414, 3, 80, 252, 60, 59, 297, 435, 436, 432,
+ /* 390 */ 432, 62, 62, 61, 61, 61, 61, 174, 63, 63,
+ /* 400 */ 63, 63, 64, 64, 65, 65, 65, 66, 210, 292,
+ /* 410 */ 221, 550, 236, 487, 510, 353, 317, 118, 243, 343,
+ /* 420 */ 248, 344, 176, 181, 317, 532, 345, 348, 349, 252,
+ /* 430 */ 223, 415, 155, 464, 511, 425, 431, 350, 414, 34,
+ /* 440 */ 465, 211, 177, 175, 160, 525, 414, 34, 338, 549,
+ /* 450 */ 449, 323, 168, 60, 59, 297, 435, 436, 432, 432,
+ /* 460 */ 62, 62, 61, 61, 61, 61, 415, 63, 63, 63,
+ /* 470 */ 63, 64, 64, 65, 65, 65, 66, 210, 292, 542,
+ /* 480 */ 335, 517, 504, 541, 456, 572, 302, 19, 331, 144,
+ /* 490 */ 317, 390, 317, 330, 2, 362, 457, 294, 483, 373,
+ /* 500 */ 269, 268, 252, 571, 425, 431, 589, 391, 388, 458,
+ /* 510 */ 208, 495, 414, 49, 414, 49, 303, 586, 894, 230,
+ /* 520 */ 894, 496, 60, 59, 297, 435, 436, 432, 432, 62,
+ /* 530 */ 62, 61, 61, 61, 61, 201, 63, 63, 63, 63,
+ /* 540 */ 64, 64, 65, 65, 65, 66, 210, 292, 317, 181,
+ /* 550 */ 439, 255, 345, 348, 349, 370, 153, 583, 308, 251,
+ /* 560 */ 309, 452, 76, 350, 78, 382, 211, 426, 427, 415,
+ /* 570 */ 414, 27, 319, 425, 431, 440, 1, 22, 586, 893,
+ /* 580 */ 396, 893, 544, 478, 320, 263, 438, 438, 429, 430,
+ /* 590 */ 415, 60, 59, 297, 435, 436, 432, 432, 62, 62,
+ /* 600 */ 61, 61, 61, 61, 237, 63, 63, 63, 63, 64,
+ /* 610 */ 64, 65, 65, 65, 66, 210, 292, 428, 583, 374,
+ /* 620 */ 224, 93, 517, 9, 159, 396, 557, 396, 456, 67,
+ /* 630 */ 396, 69, 154, 399, 400, 401, 320, 328, 438, 438,
+ /* 640 */ 457, 336, 425, 431, 361, 397, 398, 320, 433, 438,
+ /* 650 */ 438, 582, 291, 458, 238, 327, 318, 222, 546, 292,
+ /* 660 */ 60, 59, 297, 435, 436, 432, 432, 62, 62, 61,
+ /* 670 */ 61, 61, 61, 225, 63, 63, 63, 63, 64, 64,
+ /* 680 */ 65, 65, 65, 66, 210, 425, 431, 482, 313, 392,
+ /* 690 */ 397, 398, 397, 398, 207, 397, 398, 825, 273, 517,
+ /* 700 */ 251, 200, 292, 60, 59, 297, 435, 436, 432, 432,
+ /* 710 */ 62, 62, 61, 61, 61, 61, 470, 63, 63, 63,
+ /* 720 */ 63, 64, 64, 65, 65, 65, 66, 210, 425, 431,
+ /* 730 */ 171, 160, 263, 263, 304, 415, 276, 395, 274, 263,
+ /* 740 */ 517, 517, 263, 517, 192, 292, 60, 70, 297, 435,
+ /* 750 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 379,
+ /* 760 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
+ /* 770 */ 210, 425, 431, 384, 559, 305, 306, 251, 415, 320,
+ /* 780 */ 560, 438, 438, 561, 540, 360, 540, 387, 292, 196,
+ /* 790 */ 59, 297, 435, 436, 432, 432, 62, 62, 61, 61,
+ /* 800 */ 61, 61, 371, 63, 63, 63, 63, 64, 64, 65,
+ /* 810 */ 65, 65, 66, 210, 425, 431, 396, 275, 251, 251,
+ /* 820 */ 172, 250, 418, 415, 386, 367, 178, 179, 180, 469,
+ /* 830 */ 311, 123, 156, 5, 297, 435, 436, 432, 432, 62,
+ /* 840 */ 62, 61, 61, 61, 61, 317, 63, 63, 63, 63,
+ /* 850 */ 64, 64, 65, 65, 65, 66, 210, 72, 324, 194,
+ /* 860 */ 4, 317, 263, 317, 296, 263, 415, 414, 28, 317,
+ /* 870 */ 257, 317, 321, 72, 324, 317, 4, 119, 165, 177,
+ /* 880 */ 296, 397, 398, 414, 23, 414, 32, 418, 321, 326,
+ /* 890 */ 421, 414, 53, 414, 52, 317, 158, 414, 98, 451,
+ /* 900 */ 317, 263, 317, 277, 317, 326, 378, 471, 261, 317,
+ /* 910 */ 259, 18, 478, 445, 445, 451, 317, 414, 96, 75,
+ /* 920 */ 74, 469, 414, 101, 414, 102, 414, 112, 73, 315,
+ /* 930 */ 316, 414, 114, 420, 294, 75, 74, 481, 414, 16,
+ /* 940 */ 381, 317, 279, 467, 73, 315, 316, 72, 324, 420,
+ /* 950 */ 4, 208, 317, 183, 296, 317, 186, 128, 84, 208,
+ /* 960 */ 8, 341, 321, 414, 99, 422, 422, 422, 423, 424,
+ /* 970 */ 11, 623, 380, 307, 414, 33, 413, 414, 97, 326,
+ /* 980 */ 412, 422, 422, 422, 423, 424, 11, 415, 413, 451,
+ /* 990 */ 415, 162, 412, 317, 499, 500, 226, 227, 228, 104,
+ /* 1000 */ 448, 476, 317, 173, 507, 317, 509, 508, 317, 75,
+ /* 1010 */ 74, 329, 205, 21, 281, 414, 24, 418, 73, 315,
+ /* 1020 */ 316, 282, 317, 420, 414, 54, 460, 414, 115, 317,
+ /* 1030 */ 414, 116, 502, 203, 147, 549, 514, 468, 128, 202,
+ /* 1040 */ 317, 473, 204, 317, 414, 117, 317, 477, 317, 584,
+ /* 1050 */ 317, 414, 25, 317, 249, 422, 422, 422, 423, 424,
+ /* 1060 */ 11, 506, 414, 36, 512, 414, 37, 317, 414, 26,
+ /* 1070 */ 414, 38, 414, 39, 526, 414, 40, 317, 254, 317,
+ /* 1080 */ 128, 317, 418, 317, 256, 377, 278, 268, 585, 414,
+ /* 1090 */ 42, 293, 317, 352, 317, 128, 208, 513, 258, 414,
+ /* 1100 */ 43, 414, 44, 414, 29, 414, 30, 545, 260, 128,
+ /* 1110 */ 317, 553, 317, 173, 414, 45, 414, 46, 317, 262,
+ /* 1120 */ 383, 554, 317, 91, 564, 317, 91, 317, 581, 189,
+ /* 1130 */ 290, 357, 414, 47, 414, 48, 267, 365, 368, 369,
+ /* 1140 */ 414, 31, 270, 271, 414, 10, 272, 414, 50, 414,
+ /* 1150 */ 51, 556, 566, 280, 283, 284, 578, 146, 419, 405,
+ /* 1160 */ 231, 505, 444, 325, 516, 463, 163, 446, 552, 394,
+ /* 1170 */ 466, 563, 246, 515, 518, 520, 402, 403, 404, 7,
+ /* 1180 */ 314, 84, 232, 334, 347, 83, 332, 57, 170, 79,
+ /* 1190 */ 213, 461, 125, 85, 337, 342, 492, 502, 497, 301,
+ /* 1200 */ 498, 416, 105, 219, 247, 218, 503, 501, 233, 220,
+ /* 1210 */ 287, 234, 527, 528, 235, 529, 417, 521, 354, 288,
+ /* 1220 */ 184, 121, 185, 240, 535, 475, 242, 356, 187, 479,
+ /* 1230 */ 188, 358, 537, 88, 190, 548, 364, 193, 132, 376,
+ /* 1240 */ 555, 375, 133, 134, 135, 310, 562, 138, 136, 575,
+ /* 1250 */ 576, 577, 580, 100, 393, 406, 217, 142, 624, 625,
+ /* 1260 */ 103, 141, 265, 166, 167, 434, 71, 453, 441, 437,
+ /* 1270 */ 450, 143, 538, 157, 120, 454, 161, 472, 455, 169,
+ /* 1280 */ 459, 81, 6, 12, 13, 92, 95, 126, 216, 127,
+ /* 1290 */ 111, 485, 486, 17, 86, 346, 106, 122, 253, 107,
+ /* 1300 */ 87, 108, 182, 245, 355, 145, 351, 536, 129, 359,
+ /* 1310 */ 312, 130, 543, 173, 539, 266, 191, 109, 289, 551,
+ /* 1320 */ 195, 14, 131, 198, 197, 558, 137, 199, 139, 140,
+ /* 1330 */ 15, 565, 89, 90, 573, 110, 385, 206, 148, 389,
+ /* 1340 */ 285, 587,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 16, 140, 141, 142, 143, 21, 23, 23, 69, 70,
- /* 10 */ 71, 72, 110, 74, 75, 76, 77, 78, 79, 80,
- /* 20 */ 81, 82, 83, 84, 1, 2, 42, 43, 73, 74,
+ /* 0 */ 16, 139, 140, 141, 168, 21, 144, 23, 69, 70,
+ /* 10 */ 71, 72, 176, 74, 75, 76, 77, 78, 79, 80,
+ /* 20 */ 81, 82, 83, 84, 78, 79, 42, 43, 73, 74,
/* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 40 */ 58, 162, 163, 164, 60, 61, 62, 63, 64, 65,
- /* 50 */ 66, 67, 68, 69, 70, 71, 72, 148, 74, 75,
+ /* 40 */ 1, 2, 23, 58, 60, 61, 62, 63, 64, 65,
+ /* 50 */ 66, 67, 68, 69, 70, 71, 72, 147, 74, 75,
/* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 70 */ 88, 88, 88, 84, 92, 22, 219, 220, 221, 222,
+ /* 70 */ 185, 186, 88, 88, 110, 22, 217, 92, 219, 220,
/* 80 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 90 */ 84, 219, 183, 221, 222, 42, 43, 78, 79, 46,
- /* 100 */ 78, 79, 80, 81, 82, 83, 84, 125, 126, 127,
- /* 110 */ 170, 239, 16, 60, 61, 62, 63, 64, 65, 66,
- /* 120 */ 67, 68, 69, 70, 71, 72, 148, 74, 75, 76,
+ /* 90 */ 84, 217, 218, 219, 220, 42, 43, 238, 188, 46,
+ /* 100 */ 78, 79, 80, 81, 82, 83, 84, 88, 89, 124,
+ /* 110 */ 125, 126, 16, 60, 61, 62, 63, 64, 65, 66,
+ /* 120 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76,
/* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43,
- /* 140 */ 44, 80, 81, 82, 83, 84, 23, 148, 170, 171,
- /* 150 */ 19, 83, 84, 156, 23, 170, 60, 61, 62, 63,
- /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 19,
+ /* 140 */ 44, 80, 81, 82, 83, 84, 23, 84, 169, 170,
+ /* 150 */ 19, 164, 165, 166, 23, 23, 60, 61, 62, 63,
+ /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 110,
/* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 180 */ 84, 16, 183, 148, 151, 148, 21, 190, 148, 58,
- /* 190 */ 169, 213, 157, 158, 186, 187, 218, 23, 177, 202,
- /* 200 */ 203, 78, 79, 166, 167, 208, 161, 42, 43, 78,
- /* 210 */ 79, 88, 89, 177, 178, 170, 181, 182, 68, 88,
- /* 220 */ 184, 98, 99, 92, 16, 60, 61, 62, 63, 64,
- /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 22, 74,
+ /* 180 */ 84, 16, 123, 147, 150, 147, 21, 167, 168, 58,
+ /* 190 */ 211, 147, 156, 157, 92, 216, 176, 23, 147, 176,
+ /* 200 */ 177, 78, 79, 165, 166, 103, 183, 42, 43, 78,
+ /* 210 */ 79, 88, 89, 169, 170, 228, 180, 181, 169, 88,
+ /* 220 */ 88, 98, 99, 92, 16, 60, 61, 62, 63, 64,
+ /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 147, 74,
/* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 250 */ 42, 43, 78, 0, 1, 2, 125, 126, 127, 226,
- /* 260 */ 11, 162, 88, 89, 231, 228, 229, 16, 60, 61,
+ /* 250 */ 42, 43, 78, 209, 210, 124, 125, 126, 224, 208,
+ /* 260 */ 169, 170, 88, 89, 230, 227, 228, 16, 60, 61,
/* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 280 */ 72, 148, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 290 */ 82, 83, 84, 42, 43, 186, 187, 16, 49, 148,
- /* 300 */ 201, 49, 18, 170, 171, 154, 142, 143, 157, 158,
- /* 310 */ 182, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 320 */ 69, 70, 71, 72, 91, 74, 75, 76, 77, 78,
- /* 330 */ 79, 80, 81, 82, 83, 84, 168, 169, 122, 55,
- /* 340 */ 132, 16, 16, 110, 16, 177, 20, 20, 99, 100,
- /* 350 */ 101, 99, 100, 101, 80, 12, 223, 124, 148, 110,
- /* 360 */ 182, 148, 110, 23, 19, 84, 21, 24, 42, 43,
- /* 370 */ 148, 90, 91, 92, 93, 94, 95, 96, 94, 166,
- /* 380 */ 37, 107, 39, 132, 103, 111, 60, 61, 62, 63,
- /* 390 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 189,
- /* 400 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 410 */ 84, 16, 84, 156, 92, 20, 23, 92, 134, 91,
- /* 420 */ 92, 93, 94, 95, 96, 103, 148, 22, 88, 89,
- /* 430 */ 148, 103, 210, 106, 156, 108, 109, 42, 43, 144,
- /* 440 */ 145, 228, 229, 219, 149, 221, 222, 190, 170, 171,
- /* 450 */ 240, 156, 170, 171, 162, 60, 61, 62, 63, 64,
- /* 460 */ 65, 66, 67, 68, 69, 70, 71, 72, 190, 74,
- /* 470 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 480 */ 16, 88, 89, 90, 20, 190, 93, 94, 95, 23,
- /* 490 */ 131, 213, 133, 201, 212, 90, 218, 104, 93, 94,
- /* 500 */ 95, 42, 43, 7, 8, 9, 42, 43, 191, 104,
- /* 510 */ 215, 219, 159, 221, 222, 162, 163, 164, 156, 165,
- /* 520 */ 166, 167, 63, 64, 60, 61, 62, 63, 64, 65,
- /* 530 */ 66, 67, 68, 69, 70, 71, 72, 242, 74, 75,
- /* 540 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 550 */ 148, 92, 190, 20, 88, 89, 148, 90, 156, 148,
- /* 560 */ 93, 94, 95, 20, 187, 148, 19, 20, 148, 22,
- /* 570 */ 19, 104, 170, 171, 23, 42, 43, 148, 170, 171,
- /* 580 */ 114, 170, 171, 229, 99, 100, 101, 170, 171, 148,
- /* 590 */ 170, 171, 190, 60, 61, 62, 63, 64, 65, 66,
- /* 600 */ 67, 68, 69, 70, 71, 72, 59, 74, 75, 76,
- /* 610 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 211,
- /* 620 */ 212, 12, 148, 21, 213, 165, 166, 167, 21, 148,
- /* 630 */ 23, 148, 148, 24, 217, 19, 20, 217, 22, 88,
- /* 640 */ 89, 157, 158, 214, 42, 43, 37, 148, 39, 106,
- /* 650 */ 148, 108, 109, 170, 171, 20, 146, 183, 49, 156,
- /* 660 */ 14, 16, 60, 61, 62, 63, 64, 65, 66, 67,
- /* 670 */ 68, 69, 70, 71, 72, 59, 74, 75, 76, 77,
- /* 680 */ 78, 79, 80, 81, 82, 83, 84, 42, 43, 229,
- /* 690 */ 99, 100, 101, 190, 106, 88, 108, 109, 52, 14,
- /* 700 */ 54, 148, 156, 162, 16, 60, 61, 62, 63, 64,
- /* 710 */ 65, 66, 67, 68, 69, 70, 71, 72, 215, 74,
- /* 720 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 730 */ 42, 43, 245, 246, 148, 148, 190, 52, 193, 54,
- /* 740 */ 237, 106, 201, 108, 109, 200, 148, 16, 60, 61,
- /* 750 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 760 */ 72, 215, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 770 */ 82, 83, 84, 42, 43, 25, 189, 22, 232, 29,
- /* 780 */ 134, 183, 16, 237, 202, 203, 148, 148, 192, 148,
- /* 790 */ 16, 41, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 800 */ 69, 70, 71, 72, 148, 74, 75, 76, 77, 78,
- /* 810 */ 79, 80, 81, 82, 83, 84, 42, 43, 23, 19,
- /* 820 */ 23, 183, 148, 23, 148, 148, 170, 171, 189, 19,
- /* 830 */ 189, 107, 148, 23, 148, 111, 62, 63, 64, 65,
- /* 840 */ 66, 67, 68, 69, 70, 71, 72, 148, 74, 75,
- /* 850 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 860 */ 17, 148, 19, 189, 148, 189, 23, 148, 113, 170,
- /* 870 */ 171, 148, 16, 148, 31, 16, 17, 80, 19, 162,
- /* 880 */ 148, 115, 23, 88, 89, 88, 89, 210, 88, 89,
- /* 890 */ 31, 48, 148, 170, 171, 170, 171, 148, 88, 43,
- /* 900 */ 214, 58, 170, 171, 148, 189, 148, 48, 189, 114,
- /* 910 */ 19, 148, 243, 244, 170, 171, 148, 58, 148, 170,
- /* 920 */ 171, 78, 79, 210, 148, 30, 170, 171, 170, 171,
- /* 930 */ 87, 88, 89, 170, 171, 92, 148, 78, 79, 80,
- /* 940 */ 170, 171, 125, 126, 148, 50, 87, 88, 89, 16,
- /* 950 */ 17, 92, 19, 110, 98, 148, 23, 148, 156, 103,
- /* 960 */ 148, 110, 156, 22, 31, 189, 170, 171, 125, 126,
- /* 970 */ 127, 128, 129, 130, 20, 124, 156, 170, 171, 170,
- /* 980 */ 171, 48, 170, 171, 125, 126, 127, 128, 129, 130,
- /* 990 */ 204, 58, 190, 5, 148, 148, 190, 102, 10, 11,
- /* 1000 */ 12, 13, 148, 112, 22, 148, 148, 20, 148, 22,
- /* 1010 */ 190, 78, 79, 59, 26, 43, 28, 170, 171, 148,
- /* 1020 */ 87, 88, 89, 35, 148, 92, 148, 170, 171, 148,
- /* 1030 */ 170, 171, 148, 27, 148, 47, 148, 49, 97, 234,
- /* 1040 */ 34, 53, 148, 179, 56, 148, 170, 171, 170, 171,
- /* 1050 */ 148, 170, 171, 148, 170, 171, 170, 171, 125, 126,
- /* 1060 */ 127, 128, 129, 130, 170, 171, 179, 170, 171, 148,
- /* 1070 */ 98, 89, 170, 171, 148, 170, 171, 148, 20, 148,
- /* 1080 */ 22, 20, 148, 22, 148, 179, 148, 99, 100, 101,
- /* 1090 */ 148, 170, 171, 105, 148, 148, 114, 148, 110, 170,
- /* 1100 */ 171, 170, 171, 148, 170, 171, 170, 171, 170, 171,
- /* 1110 */ 7, 8, 170, 171, 20, 148, 22, 170, 171, 170,
- /* 1120 */ 171, 148, 20, 135, 22, 170, 171, 148, 148, 91,
- /* 1130 */ 92, 20, 20, 22, 22, 150, 233, 170, 171, 20,
- /* 1140 */ 20, 22, 22, 170, 171, 20, 148, 22, 148, 170,
- /* 1150 */ 171, 148, 148, 148, 192, 148, 148, 148, 148, 148,
- /* 1160 */ 148, 148, 148, 148, 148, 148, 173, 230, 194, 230,
- /* 1170 */ 225, 205, 173, 178, 173, 173, 195, 6, 147, 195,
- /* 1180 */ 162, 162, 205, 162, 147, 22, 147, 147, 205, 155,
- /* 1190 */ 122, 195, 119, 173, 120, 118, 174, 121, 131, 224,
- /* 1200 */ 112, 153, 153, 98, 117, 98, 40, 172, 172, 19,
- /* 1210 */ 97, 84, 15, 190, 172, 152, 172, 174, 227, 227,
- /* 1220 */ 196, 180, 197, 172, 198, 175, 199, 180, 172, 172,
- /* 1230 */ 175, 153, 152, 152, 206, 153, 207, 207, 206, 153,
- /* 1240 */ 38, 131, 153, 152, 60, 153, 19, 185, 195, 185,
- /* 1250 */ 153, 15, 153, 188, 188, 195, 185, 188, 188, 33,
- /* 1260 */ 138, 153, 216, 1, 160, 20, 176, 153, 235, 176,
- /* 1270 */ 216, 112, 112, 112, 112, 92, 107, 19, 11, 20,
- /* 1280 */ 20, 236, 19, 19, 116, 20, 116, 114, 22, 20,
- /* 1290 */ 238, 20, 22, 19, 22, 116, 115, 238, 20, 112,
- /* 1300 */ 20, 20, 19, 19, 19, 32, 20, 19, 19, 96,
- /* 1310 */ 103, 16, 44, 241, 17, 21, 98, 98, 36, 244,
- /* 1320 */ 44, 44, 22, 134, 19, 5, 247, 1, 123, 68,
- /* 1330 */ 51, 102, 45, 19, 113, 45, 1, 14, 17, 117,
- /* 1340 */ 102, 113, 20, 68, 19, 14, 123, 136, 124, 57,
- /* 1350 */ 3, 137, 19, 4,
+ /* 280 */ 72, 23, 74, 75, 76, 77, 78, 79, 80, 81,
+ /* 290 */ 82, 83, 84, 42, 43, 160, 16, 147, 161, 83,
+ /* 300 */ 84, 210, 161, 153, 169, 158, 156, 157, 161, 162,
+ /* 310 */ 163, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ /* 320 */ 69, 70, 71, 72, 161, 74, 75, 76, 77, 78,
+ /* 330 */ 79, 80, 81, 82, 83, 84, 192, 200, 147, 131,
+ /* 340 */ 16, 200, 16, 199, 20, 169, 88, 89, 90, 185,
+ /* 350 */ 186, 93, 94, 95, 217, 22, 219, 220, 147, 147,
+ /* 360 */ 169, 170, 104, 200, 84, 147, 42, 43, 156, 157,
+ /* 370 */ 90, 91, 92, 93, 94, 95, 96, 164, 165, 166,
+ /* 380 */ 169, 170, 131, 103, 60, 61, 62, 63, 64, 65,
+ /* 390 */ 66, 67, 68, 69, 70, 71, 72, 155, 74, 75,
+ /* 400 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
+ /* 410 */ 84, 11, 221, 20, 30, 16, 147, 91, 92, 93,
+ /* 420 */ 94, 95, 96, 90, 147, 181, 93, 94, 95, 103,
+ /* 430 */ 212, 189, 155, 27, 50, 42, 43, 104, 169, 170,
+ /* 440 */ 34, 228, 43, 201, 202, 181, 169, 170, 206, 49,
+ /* 450 */ 161, 162, 163, 60, 61, 62, 63, 64, 65, 66,
+ /* 460 */ 67, 68, 69, 70, 71, 72, 189, 74, 75, 76,
+ /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 25,
+ /* 480 */ 211, 147, 20, 29, 12, 147, 102, 19, 211, 21,
+ /* 490 */ 147, 141, 147, 216, 144, 41, 24, 98, 20, 99,
+ /* 500 */ 100, 101, 103, 165, 42, 43, 0, 1, 2, 37,
+ /* 510 */ 110, 39, 169, 170, 169, 170, 182, 19, 20, 190,
+ /* 520 */ 22, 49, 60, 61, 62, 63, 64, 65, 66, 67,
+ /* 530 */ 68, 69, 70, 71, 72, 155, 74, 75, 76, 77,
+ /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 147, 90,
+ /* 550 */ 20, 20, 93, 94, 95, 147, 155, 59, 215, 225,
+ /* 560 */ 215, 20, 130, 104, 132, 227, 228, 42, 43, 189,
+ /* 570 */ 169, 170, 16, 42, 43, 20, 19, 22, 19, 20,
+ /* 580 */ 23, 22, 18, 147, 106, 147, 108, 109, 63, 64,
+ /* 590 */ 189, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ /* 600 */ 69, 70, 71, 72, 147, 74, 75, 76, 77, 78,
+ /* 610 */ 79, 80, 81, 82, 83, 84, 16, 92, 59, 55,
+ /* 620 */ 212, 21, 147, 19, 147, 23, 188, 23, 12, 217,
+ /* 630 */ 23, 219, 220, 7, 8, 9, 106, 186, 108, 109,
+ /* 640 */ 24, 147, 42, 43, 208, 88, 89, 106, 92, 108,
+ /* 650 */ 109, 244, 245, 37, 147, 39, 147, 182, 94, 16,
+ /* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ /* 670 */ 70, 71, 72, 145, 74, 75, 76, 77, 78, 79,
+ /* 680 */ 80, 81, 82, 83, 84, 42, 43, 80, 142, 143,
+ /* 690 */ 88, 89, 88, 89, 148, 88, 89, 133, 14, 147,
+ /* 700 */ 225, 155, 16, 60, 61, 62, 63, 64, 65, 66,
+ /* 710 */ 67, 68, 69, 70, 71, 72, 114, 74, 75, 76,
+ /* 720 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43,
+ /* 730 */ 201, 202, 147, 147, 182, 189, 52, 147, 54, 147,
+ /* 740 */ 147, 147, 147, 147, 155, 16, 60, 61, 62, 63,
+ /* 750 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 213,
+ /* 760 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ /* 770 */ 84, 42, 43, 188, 188, 182, 182, 225, 189, 106,
+ /* 780 */ 188, 108, 109, 188, 99, 100, 101, 241, 16, 155,
+ /* 790 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
+ /* 800 */ 71, 72, 213, 74, 75, 76, 77, 78, 79, 80,
+ /* 810 */ 81, 82, 83, 84, 42, 43, 23, 133, 225, 225,
+ /* 820 */ 21, 225, 23, 189, 239, 236, 99, 100, 101, 22,
+ /* 830 */ 242, 243, 155, 191, 62, 63, 64, 65, 66, 67,
+ /* 840 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77,
+ /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 22,
+ /* 860 */ 19, 147, 147, 147, 23, 147, 189, 169, 170, 147,
+ /* 870 */ 14, 147, 31, 16, 17, 147, 19, 147, 19, 43,
+ /* 880 */ 23, 88, 89, 169, 170, 169, 170, 88, 31, 48,
+ /* 890 */ 147, 169, 170, 169, 170, 147, 89, 169, 170, 58,
+ /* 900 */ 147, 147, 147, 188, 147, 48, 188, 114, 52, 147,
+ /* 910 */ 54, 19, 147, 124, 125, 58, 147, 169, 170, 78,
+ /* 920 */ 79, 114, 169, 170, 169, 170, 169, 170, 87, 88,
+ /* 930 */ 89, 169, 170, 92, 98, 78, 79, 80, 169, 170,
+ /* 940 */ 91, 147, 188, 22, 87, 88, 89, 16, 17, 92,
+ /* 950 */ 19, 110, 147, 155, 23, 147, 155, 22, 121, 110,
+ /* 960 */ 68, 80, 31, 169, 170, 124, 125, 126, 127, 128,
+ /* 970 */ 129, 112, 123, 208, 169, 170, 107, 169, 170, 48,
+ /* 980 */ 111, 124, 125, 126, 127, 128, 129, 189, 107, 58,
+ /* 990 */ 189, 5, 111, 147, 7, 8, 10, 11, 12, 13,
+ /* 1000 */ 161, 20, 147, 22, 178, 147, 91, 92, 147, 78,
+ /* 1010 */ 79, 147, 26, 19, 28, 169, 170, 23, 87, 88,
+ /* 1020 */ 89, 35, 147, 92, 169, 170, 147, 169, 170, 147,
+ /* 1030 */ 169, 170, 97, 47, 113, 49, 20, 203, 22, 53,
+ /* 1040 */ 147, 147, 56, 147, 169, 170, 147, 147, 147, 20,
+ /* 1050 */ 147, 169, 170, 147, 147, 124, 125, 126, 127, 128,
+ /* 1060 */ 129, 147, 169, 170, 178, 169, 170, 147, 169, 170,
+ /* 1070 */ 169, 170, 169, 170, 147, 169, 170, 147, 20, 147,
+ /* 1080 */ 22, 147, 88, 147, 147, 99, 100, 101, 59, 169,
+ /* 1090 */ 170, 105, 147, 20, 147, 22, 110, 178, 147, 169,
+ /* 1100 */ 170, 169, 170, 169, 170, 169, 170, 20, 147, 22,
+ /* 1110 */ 147, 20, 147, 22, 169, 170, 169, 170, 147, 147,
+ /* 1120 */ 134, 20, 147, 22, 20, 147, 22, 147, 20, 232,
+ /* 1130 */ 22, 233, 169, 170, 169, 170, 147, 147, 147, 147,
+ /* 1140 */ 169, 170, 147, 147, 169, 170, 147, 169, 170, 169,
+ /* 1150 */ 170, 147, 147, 147, 147, 147, 147, 191, 161, 149,
+ /* 1160 */ 193, 177, 229, 223, 161, 172, 6, 229, 194, 146,
+ /* 1170 */ 172, 194, 172, 172, 172, 161, 146, 146, 146, 22,
+ /* 1180 */ 154, 121, 194, 118, 173, 119, 116, 120, 112, 130,
+ /* 1190 */ 222, 152, 152, 98, 115, 98, 171, 97, 171, 40,
+ /* 1200 */ 179, 189, 19, 84, 171, 226, 171, 173, 195, 226,
+ /* 1210 */ 174, 196, 171, 171, 197, 171, 198, 179, 15, 174,
+ /* 1220 */ 151, 60, 151, 204, 152, 205, 204, 152, 151, 205,
+ /* 1230 */ 152, 38, 152, 130, 151, 184, 152, 184, 19, 15,
+ /* 1240 */ 194, 152, 187, 187, 187, 152, 194, 184, 187, 33,
+ /* 1250 */ 152, 152, 137, 159, 1, 20, 175, 214, 112, 112,
+ /* 1260 */ 175, 214, 234, 112, 112, 92, 19, 11, 20, 107,
+ /* 1270 */ 20, 19, 235, 19, 32, 20, 112, 114, 20, 22,
+ /* 1280 */ 20, 22, 117, 22, 117, 237, 237, 19, 44, 20,
+ /* 1290 */ 240, 20, 20, 231, 19, 44, 19, 243, 20, 19,
+ /* 1300 */ 19, 19, 96, 103, 16, 21, 44, 17, 98, 36,
+ /* 1310 */ 246, 45, 45, 22, 51, 133, 98, 19, 5, 1,
+ /* 1320 */ 122, 19, 102, 14, 113, 17, 113, 115, 102, 122,
+ /* 1330 */ 19, 123, 68, 68, 20, 14, 57, 135, 19, 3,
+ /* 1340 */ 136, 4,
};
-#define YY_SHIFT_USE_DFLT (-99)
-#define YY_SHIFT_MAX 396
+#define YY_SHIFT_USE_DFLT (-62)
+#define YY_SHIFT_MAX 389
static const short yy_shift_ofst[] = {
- /* 0 */ 23, 843, 988, -16, 843, 933, 933, 393, 123, 252,
- /* 10 */ -98, 96, 933, 933, 933, 933, 933, -45, 249, 174,
- /* 20 */ 340, -17, 19, 19, 53, 165, 208, 251, 326, 395,
- /* 30 */ 464, 533, 602, 645, 688, 645, 645, 645, 645, 645,
- /* 40 */ 645, 645, 645, 645, 645, 645, 645, 645, 645, 645,
- /* 50 */ 645, 645, 645, 731, 774, 774, 859, 933, 933, 933,
- /* 60 */ 933, 933, 933, 933, 933, 933, 933, 933, 933, 933,
- /* 70 */ 933, 933, 933, 933, 933, 933, 933, 933, 933, 933,
- /* 80 */ 933, 933, 933, 933, 933, 933, 933, 933, 933, 933,
- /* 90 */ 933, 933, 933, 933, 933, 933, 933, -61, -61, 6,
- /* 100 */ 6, 281, 22, 61, 856, 284, 340, 340, 68, -17,
- /* 110 */ -11, -99, -99, -99, 131, 328, 609, 609, 547, 616,
- /* 120 */ 253, 607, 340, 607, 340, 340, 340, 340, 340, 340,
- /* 130 */ 340, 340, 340, 340, 340, 340, 340, 340, 340, 340,
- /* 140 */ 340, 233, 851, -98, -98, -98, -99, -99, -99, -18,
- /* 150 */ -18, 405, 467, 327, 551, 543, 635, 343, 466, 795,
- /* 160 */ 800, 797, 496, 340, 340, 274, 340, 340, 810, 340,
- /* 170 */ 340, 982, 340, 340, 340, 588, 982, 340, 340, 895,
- /* 180 */ 895, 895, 340, 340, 340, 588, 340, 340, 588, 340,
- /* 190 */ 750, 485, 340, 340, 588, 340, 340, 340, 588, 340,
- /* 200 */ 340, 340, 588, 588, 340, 340, 340, 340, 340, 345,
- /* 210 */ 724, 755, -17, 817, 817, 359, 1006, 1006, 766, 1006,
- /* 220 */ 972, 1006, -17, 1006, -17, 941, 216, 766, 766, 216,
- /* 230 */ 1171, 1171, 1171, 1171, 1163, -98, 1068, 1073, 1074, 1077,
- /* 240 */ 1076, 1067, 1088, 1088, 1105, 1087, 1105, 1087, 1107, 1107,
- /* 250 */ 1166, 1107, 1113, 1107, 1190, 1127, 1127, 1166, 1107, 1107,
- /* 260 */ 1107, 1190, 1197, 1088, 1197, 1088, 1197, 1088, 1088, 1202,
- /* 270 */ 1110, 1197, 1088, 1184, 1184, 1227, 1068, 1088, 1236, 1236,
- /* 280 */ 1236, 1236, 1068, 1184, 1227, 1088, 1226, 1226, 1088, 1088,
- /* 290 */ 1122, -99, -99, -99, -99, -99, 459, 646, 591, 685,
- /* 300 */ 891, 325, 987, 1058, 322, 1103, 1038, 1061, 1094, 1102,
- /* 310 */ 1111, 1112, 1119, 1120, 150, 1125, 954, 1262, 1245, 1159,
- /* 320 */ 1160, 1161, 1162, 1183, 1169, 1258, 1259, 1260, 1263, 1267,
- /* 330 */ 1264, 1265, 1266, 1269, 1271, 1270, 1168, 1272, 1170, 1270,
- /* 340 */ 1173, 1274, 1179, 1181, 1278, 1187, 1280, 1281, 1273, 1268,
- /* 350 */ 1283, 1276, 1284, 1286, 1285, 1288, 1277, 1289, 1213, 1207,
- /* 360 */ 1295, 1297, 1294, 1218, 1282, 1279, 1287, 1300, 1290, 1189,
- /* 370 */ 1219, 1305, 1320, 1326, 1229, 1261, 1275, 1205, 1314, 1221,
- /* 380 */ 1335, 1323, 1222, 1321, 1228, 1238, 1223, 1325, 1224, 1322,
- /* 390 */ 1331, 1292, 1211, 1214, 1333, 1347, 1349,
+ /* 0 */ 39, 841, 986, -16, 841, 931, 931, 258, 123, -36,
+ /* 10 */ 96, 931, 931, 931, 931, 931, -45, 400, 174, 19,
+ /* 20 */ 132, -54, -54, 53, 165, 208, 251, 324, 393, 462,
+ /* 30 */ 531, 600, 643, 686, 643, 643, 643, 643, 643, 643,
+ /* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643,
+ /* 50 */ 643, 643, 729, 772, 772, 857, 931, 931, 931, 931,
+ /* 60 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
+ /* 70 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
+ /* 80 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
+ /* 90 */ 931, 931, 931, 931, 931, 931, -61, -61, 6, 6,
+ /* 100 */ 280, 22, 61, 399, 564, 19, 19, 19, 19, 19,
+ /* 110 */ 19, 19, 216, 132, 63, -62, -62, -62, 131, 326,
+ /* 120 */ 472, 472, 498, 559, 506, 799, 19, 799, 19, 19,
+ /* 130 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ /* 140 */ 19, 849, 59, -36, -36, -36, -62, -62, -62, -15,
+ /* 150 */ -15, 333, 459, 478, 557, 530, 541, 616, 602, 793,
+ /* 160 */ 604, 607, 626, 19, 19, 881, 19, 19, 994, 19,
+ /* 170 */ 19, 807, 19, 19, 673, 807, 19, 19, 384, 384,
+ /* 180 */ 384, 19, 19, 673, 19, 19, 673, 19, 454, 685,
+ /* 190 */ 19, 19, 673, 19, 19, 19, 673, 19, 19, 19,
+ /* 200 */ 673, 673, 19, 19, 19, 19, 19, 468, 869, 921,
+ /* 210 */ 132, 789, 789, 432, 406, 406, 406, 836, 406, 132,
+ /* 220 */ 406, 132, 935, 837, 837, 1160, 1160, 1160, 1160, 1157,
+ /* 230 */ -36, 1060, 1065, 1066, 1070, 1067, 1059, 1076, 1076, 1095,
+ /* 240 */ 1079, 1095, 1079, 1097, 1097, 1159, 1097, 1100, 1097, 1183,
+ /* 250 */ 1119, 1119, 1159, 1097, 1097, 1097, 1183, 1203, 1076, 1203,
+ /* 260 */ 1076, 1203, 1076, 1076, 1193, 1103, 1203, 1076, 1161, 1161,
+ /* 270 */ 1219, 1060, 1076, 1224, 1224, 1224, 1224, 1060, 1161, 1219,
+ /* 280 */ 1076, 1216, 1216, 1076, 1076, 1115, -62, -62, -62, -62,
+ /* 290 */ -62, -62, 525, 684, 727, 856, 859, 556, 555, 981,
+ /* 300 */ 102, 987, 915, 1016, 1058, 1073, 1087, 1091, 1101, 1104,
+ /* 310 */ 892, 1108, 1029, 1253, 1235, 1146, 1147, 1151, 1152, 1173,
+ /* 320 */ 1162, 1247, 1248, 1250, 1252, 1256, 1254, 1255, 1257, 1258,
+ /* 330 */ 1260, 1259, 1165, 1261, 1167, 1259, 1163, 1268, 1269, 1164,
+ /* 340 */ 1271, 1272, 1242, 1244, 1275, 1251, 1277, 1278, 1280, 1281,
+ /* 350 */ 1262, 1282, 1206, 1200, 1288, 1290, 1284, 1210, 1273, 1263,
+ /* 360 */ 1266, 1291, 1267, 1182, 1218, 1298, 1313, 1318, 1220, 1264,
+ /* 370 */ 1265, 1198, 1302, 1211, 1309, 1212, 1308, 1213, 1226, 1207,
+ /* 380 */ 1311, 1208, 1314, 1321, 1279, 1202, 1204, 1319, 1336, 1337,
};
-#define YY_REDUCE_USE_DFLT (-144)
-#define YY_REDUCE_MAX 295
+#define YY_REDUCE_USE_DFLT (-165)
+#define YY_REDUCE_MAX 291
static const short yy_reduce_ofst[] = {
- /* 0 */ -139, 278, 295, 292, 402, -22, 408, 35, 37, 546,
- /* 10 */ -3, -128, 133, 282, 411, 417, 420, -143, 503, 213,
- /* 20 */ 151, 353, 354, 460, 224, 224, 224, 224, 224, 224,
- /* 30 */ 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
- /* 40 */ 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
- /* 50 */ 224, 224, 224, 224, 224, 224, 483, 656, 699, 723,
- /* 60 */ 725, 732, 744, 749, 756, 758, 763, 770, 796, 807,
- /* 70 */ 809, 812, 847, 857, 860, 876, 878, 881, 884, 886,
- /* 80 */ 894, 897, 902, 905, 921, 929, 931, 934, 936, 938,
- /* 90 */ 942, 947, 949, 955, 967, 973, 979, 224, 224, 224,
- /* 100 */ 224, 168, 224, 224, 36, 33, 210, 484, 224, -121,
- /* 110 */ 224, 224, 224, 224, 45, 21, 8, 109, 487, 487,
- /* 120 */ 164, 99, 222, 541, -91, -1, 474, 598, 587, 677,
- /* 130 */ 638, 429, 713, 639, 641, 674, 676, 716, 719, 686,
- /* 140 */ 776, 257, 362, 802, 806, 820, 545, 582, 669, -60,
- /* 150 */ -15, 128, 178, 317, 40, 317, 317, 377, 441, 481,
- /* 160 */ 499, 502, 510, 553, 586, 596, 502, 684, 717, 768,
- /* 170 */ 788, 786, 846, 854, 858, 317, 786, 871, 888, 864,
- /* 180 */ 887, 906, 926, 946, 980, 317, 998, 1000, 317, 1003,
- /* 190 */ 903, 805, 1004, 1005, 317, 1007, 1008, 1009, 317, 1010,
- /* 200 */ 1011, 1012, 317, 317, 1013, 1014, 1015, 1016, 1017, 985,
- /* 210 */ 962, 974, 1018, 937, 939, 945, 993, 999, 966, 1001,
- /* 220 */ 995, 1002, 1019, 1020, 1021, 1022, 981, 977, 983, 984,
- /* 230 */ 1031, 1037, 1039, 1040, 1034, 1023, 996, 1024, 1025, 1026,
- /* 240 */ 1027, 975, 1048, 1049, 1028, 1029, 1032, 1030, 1035, 1036,
- /* 250 */ 1041, 1042, 1043, 1044, 1050, 991, 992, 1047, 1051, 1056,
- /* 260 */ 1057, 1055, 1063, 1078, 1080, 1082, 1081, 1086, 1089, 1033,
- /* 270 */ 1045, 1091, 1092, 1062, 1064, 1046, 1053, 1097, 1065, 1066,
- /* 280 */ 1069, 1070, 1060, 1071, 1054, 1099, 1052, 1059, 1108, 1114,
- /* 290 */ 1072, 1104, 1090, 1093, 1075, 1079,
+ /* 0 */ -138, 277, 546, 137, 401, -21, 44, 36, 38, 242,
+ /* 10 */ -141, 191, 91, 269, 343, 345, -126, 589, 338, 150,
+ /* 20 */ 147, -13, 213, 412, 412, 412, 412, 412, 412, 412,
+ /* 30 */ 412, 412, 412, 412, 412, 412, 412, 412, 412, 412,
+ /* 40 */ 412, 412, 412, 412, 412, 412, 412, 412, 412, 412,
+ /* 50 */ 412, 412, 412, 412, 412, 211, 698, 714, 716, 722,
+ /* 60 */ 724, 728, 748, 753, 755, 757, 762, 769, 794, 805,
+ /* 70 */ 808, 846, 855, 858, 861, 875, 882, 893, 896, 899,
+ /* 80 */ 901, 903, 906, 920, 930, 932, 934, 936, 945, 947,
+ /* 90 */ 963, 965, 971, 975, 978, 980, 412, 412, 412, 412,
+ /* 100 */ 20, 412, 412, 23, 34, 334, 475, 552, 593, 594,
+ /* 110 */ 585, 212, 412, 289, 412, 412, 412, 412, 135, -164,
+ /* 120 */ -115, 164, 407, 407, 350, 141, 51, 163, 596, -90,
+ /* 130 */ 436, 218, 765, 438, 586, 592, 595, 715, 718, 408,
+ /* 140 */ 754, 380, 634, 677, 798, 801, 144, 529, 588, 49,
+ /* 150 */ 176, 244, 264, 329, 457, 329, 329, 451, 477, 494,
+ /* 160 */ 507, 509, 528, 590, 730, 642, 509, 743, 839, 864,
+ /* 170 */ 879, 834, 894, 900, 329, 834, 907, 914, 826, 886,
+ /* 180 */ 919, 927, 937, 329, 951, 961, 329, 972, 897, 898,
+ /* 190 */ 989, 990, 329, 991, 992, 995, 329, 996, 999, 1004,
+ /* 200 */ 329, 329, 1005, 1006, 1007, 1008, 1009, 1010, 966, 967,
+ /* 210 */ 997, 933, 938, 940, 993, 998, 1000, 984, 1001, 1003,
+ /* 220 */ 1002, 1014, 1011, 974, 977, 1023, 1030, 1031, 1032, 1026,
+ /* 230 */ 1012, 988, 1013, 1015, 1017, 1018, 968, 1039, 1040, 1019,
+ /* 240 */ 1020, 1022, 1024, 1025, 1027, 1021, 1033, 1034, 1035, 1036,
+ /* 250 */ 979, 983, 1038, 1041, 1042, 1044, 1045, 1069, 1072, 1071,
+ /* 260 */ 1075, 1077, 1078, 1080, 1028, 1037, 1083, 1084, 1051, 1053,
+ /* 270 */ 1043, 1046, 1089, 1055, 1056, 1057, 1061, 1052, 1063, 1047,
+ /* 280 */ 1093, 1048, 1049, 1098, 1099, 1050, 1094, 1081, 1085, 1062,
+ /* 290 */ 1054, 1064,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 603, 832, 913, 719, 913, 832, 913, 913, 859, 913,
- /* 10 */ 723, 888, 830, 913, 913, 913, 913, 804, 913, 859,
- /* 20 */ 913, 635, 859, 859, 755, 913, 913, 913, 913, 913,
- /* 30 */ 913, 913, 913, 756, 913, 834, 829, 825, 827, 826,
- /* 40 */ 833, 757, 746, 753, 760, 735, 872, 762, 763, 769,
- /* 50 */ 770, 889, 887, 792, 791, 810, 913, 913, 913, 913,
- /* 60 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 70 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 80 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 90 */ 913, 913, 913, 913, 913, 913, 913, 794, 816, 793,
- /* 100 */ 803, 628, 795, 796, 688, 623, 913, 913, 797, 913,
- /* 110 */ 798, 811, 812, 813, 913, 913, 913, 913, 913, 913,
- /* 120 */ 603, 719, 913, 719, 913, 913, 913, 913, 913, 913,
- /* 130 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 140 */ 913, 913, 913, 913, 913, 913, 713, 723, 906, 913,
- /* 150 */ 913, 679, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 160 */ 913, 913, 611, 609, 913, 711, 913, 913, 637, 913,
- /* 170 */ 913, 721, 913, 913, 913, 726, 727, 913, 913, 913,
- /* 180 */ 913, 913, 913, 913, 913, 625, 913, 913, 700, 913,
- /* 190 */ 865, 913, 913, 913, 879, 913, 913, 913, 877, 913,
- /* 200 */ 913, 913, 702, 765, 845, 913, 892, 894, 913, 913,
- /* 210 */ 711, 720, 913, 913, 913, 828, 749, 749, 737, 749,
- /* 220 */ 658, 749, 913, 749, 913, 661, 759, 737, 737, 759,
- /* 230 */ 608, 608, 608, 608, 678, 913, 759, 750, 752, 742,
- /* 240 */ 754, 913, 728, 728, 736, 741, 736, 741, 690, 690,
- /* 250 */ 675, 690, 661, 690, 838, 842, 842, 675, 690, 690,
- /* 260 */ 690, 838, 620, 728, 620, 728, 620, 728, 728, 869,
- /* 270 */ 871, 620, 728, 692, 692, 771, 759, 728, 699, 699,
- /* 280 */ 699, 699, 759, 692, 771, 728, 891, 891, 728, 728,
- /* 290 */ 899, 645, 663, 663, 906, 911, 913, 913, 913, 913,
- /* 300 */ 778, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 310 */ 913, 913, 913, 913, 852, 913, 913, 913, 913, 783,
- /* 320 */ 779, 913, 780, 913, 705, 913, 913, 913, 913, 913,
- /* 330 */ 913, 913, 913, 913, 913, 831, 913, 743, 913, 751,
- /* 340 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 350 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 360 */ 913, 913, 913, 913, 913, 913, 867, 868, 913, 913,
- /* 370 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 380 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 390 */ 913, 898, 913, 913, 901, 604, 913, 599, 601, 602,
- /* 400 */ 606, 607, 610, 632, 633, 634, 612, 613, 614, 615,
- /* 410 */ 616, 617, 618, 624, 626, 644, 646, 630, 648, 709,
- /* 420 */ 710, 775, 703, 704, 708, 631, 786, 777, 781, 782,
- /* 430 */ 784, 785, 799, 800, 802, 808, 815, 818, 801, 806,
- /* 440 */ 807, 809, 814, 817, 706, 707, 821, 638, 639, 642,
- /* 450 */ 643, 855, 857, 856, 858, 641, 640, 787, 790, 823,
- /* 460 */ 824, 880, 881, 882, 883, 884, 819, 729, 822, 805,
- /* 470 */ 744, 747, 748, 745, 712, 722, 731, 732, 733, 734,
- /* 480 */ 717, 718, 724, 740, 773, 774, 738, 739, 725, 714,
- /* 490 */ 715, 716, 820, 776, 788, 789, 649, 650, 783, 651,
- /* 500 */ 652, 653, 691, 694, 695, 696, 654, 673, 676, 677,
- /* 510 */ 655, 662, 656, 657, 664, 665, 666, 669, 670, 671,
- /* 520 */ 672, 667, 668, 839, 840, 843, 841, 659, 660, 674,
- /* 530 */ 647, 636, 629, 680, 683, 684, 685, 686, 687, 689,
- /* 540 */ 681, 682, 627, 619, 621, 730, 861, 870, 866, 862,
- /* 550 */ 863, 864, 622, 835, 836, 693, 767, 768, 860, 873,
- /* 560 */ 875, 772, 876, 878, 874, 903, 697, 698, 701, 844,
- /* 570 */ 885, 758, 761, 764, 766, 846, 847, 848, 849, 850,
- /* 580 */ 853, 854, 851, 886, 890, 893, 895, 896, 897, 900,
- /* 590 */ 902, 907, 908, 909, 912, 910, 605, 600,
+ /* 0 */ 595, 820, 902, 710, 902, 820, 902, 902, 848, 714,
+ /* 10 */ 877, 818, 902, 902, 902, 902, 792, 902, 848, 902,
+ /* 20 */ 626, 848, 848, 743, 902, 902, 902, 902, 902, 902,
+ /* 30 */ 902, 902, 744, 902, 822, 817, 813, 815, 814, 821,
+ /* 40 */ 745, 734, 741, 748, 726, 861, 750, 751, 757, 758,
+ /* 50 */ 878, 876, 780, 779, 798, 902, 902, 902, 902, 902,
+ /* 60 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 70 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 80 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 90 */ 902, 902, 902, 902, 902, 902, 782, 804, 781, 791,
+ /* 100 */ 619, 783, 784, 679, 614, 902, 902, 902, 902, 902,
+ /* 110 */ 902, 902, 785, 902, 786, 799, 800, 801, 902, 902,
+ /* 120 */ 902, 902, 902, 902, 595, 710, 902, 710, 902, 902,
+ /* 130 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 140 */ 902, 902, 902, 902, 902, 902, 704, 714, 895, 902,
+ /* 150 */ 902, 670, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 160 */ 902, 902, 602, 600, 902, 702, 902, 902, 628, 902,
+ /* 170 */ 902, 712, 902, 902, 717, 718, 902, 902, 902, 902,
+ /* 180 */ 902, 902, 902, 616, 902, 902, 691, 902, 854, 902,
+ /* 190 */ 902, 902, 868, 902, 902, 902, 866, 902, 902, 902,
+ /* 200 */ 693, 753, 834, 902, 881, 883, 902, 902, 702, 711,
+ /* 210 */ 902, 902, 902, 816, 737, 737, 737, 649, 737, 902,
+ /* 220 */ 737, 902, 652, 747, 747, 599, 599, 599, 599, 669,
+ /* 230 */ 902, 747, 738, 740, 730, 742, 902, 719, 719, 727,
+ /* 240 */ 729, 727, 729, 681, 681, 666, 681, 652, 681, 826,
+ /* 250 */ 831, 831, 666, 681, 681, 681, 826, 611, 719, 611,
+ /* 260 */ 719, 611, 719, 719, 858, 860, 611, 719, 683, 683,
+ /* 270 */ 759, 747, 719, 690, 690, 690, 690, 747, 683, 759,
+ /* 280 */ 719, 880, 880, 719, 719, 888, 636, 654, 654, 863,
+ /* 290 */ 895, 900, 902, 902, 902, 902, 766, 902, 902, 902,
+ /* 300 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 310 */ 841, 902, 902, 902, 902, 771, 767, 902, 768, 902,
+ /* 320 */ 696, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 330 */ 902, 819, 902, 731, 902, 739, 902, 902, 902, 902,
+ /* 340 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 350 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 360 */ 856, 857, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 370 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 380 */ 902, 902, 902, 902, 887, 902, 902, 890, 596, 902,
+ /* 390 */ 590, 593, 592, 594, 598, 601, 623, 624, 625, 603,
+ /* 400 */ 604, 605, 606, 607, 608, 609, 615, 617, 635, 637,
+ /* 410 */ 621, 639, 700, 701, 763, 694, 695, 699, 622, 774,
+ /* 420 */ 765, 769, 770, 772, 773, 787, 788, 790, 796, 803,
+ /* 430 */ 806, 789, 794, 795, 797, 802, 805, 697, 698, 809,
+ /* 440 */ 629, 630, 633, 634, 844, 846, 845, 847, 632, 631,
+ /* 450 */ 775, 778, 811, 812, 869, 870, 871, 872, 873, 807,
+ /* 460 */ 720, 810, 793, 732, 735, 736, 733, 703, 713, 722,
+ /* 470 */ 723, 724, 725, 708, 709, 715, 728, 761, 762, 716,
+ /* 480 */ 705, 706, 707, 808, 764, 776, 777, 640, 641, 771,
+ /* 490 */ 642, 643, 644, 682, 685, 686, 687, 645, 664, 667,
+ /* 500 */ 668, 646, 653, 647, 648, 655, 656, 657, 660, 661,
+ /* 510 */ 662, 663, 658, 659, 827, 828, 832, 830, 829, 650,
+ /* 520 */ 651, 665, 638, 627, 620, 671, 674, 675, 676, 677,
+ /* 530 */ 678, 680, 672, 673, 618, 610, 612, 721, 850, 859,
+ /* 540 */ 855, 851, 852, 853, 613, 823, 824, 684, 755, 756,
+ /* 550 */ 849, 862, 864, 760, 865, 867, 892, 688, 689, 692,
+ /* 560 */ 833, 874, 746, 749, 752, 754, 835, 836, 837, 838,
+ /* 570 */ 839, 842, 843, 840, 875, 879, 882, 884, 885, 886,
+ /* 580 */ 889, 891, 896, 897, 898, 901, 899, 597, 591,
};
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
@@ -80446,10 +77507,9 @@ static const YYCODETYPE yyFallback[] = {
0, /* DOT => nothing */
0, /* FROM => nothing */
0, /* JOIN => nothing */
- 0, /* INDEXED => nothing */
- 0, /* BY => nothing */
0, /* USING => nothing */
0, /* ORDER => nothing */
+ 0, /* BY => nothing */
0, /* GROUP => nothing */
0, /* HAVING => nothing */
0, /* LIMIT => nothing */
@@ -80575,40 +77635,40 @@ static const char *const yyTokenName[] = {
"UPDATE", "INSERT", "SET", "DEFERRABLE",
"FOREIGN", "DROP", "UNION", "ALL",
"EXCEPT", "INTERSECT", "SELECT", "DISTINCT",
- "DOT", "FROM", "JOIN", "INDEXED",
- "BY", "USING", "ORDER", "GROUP",
- "HAVING", "LIMIT", "WHERE", "INTO",
- "VALUES", "INTEGER", "FLOAT", "BLOB",
- "REGISTER", "VARIABLE", "CASE", "WHEN",
- "THEN", "ELSE", "INDEX", "ALTER",
- "TO", "ADD", "COLUMNKW", "error",
- "input", "cmdlist", "ecmd", "explain",
- "cmdx", "cmd", "transtype", "trans_opt",
- "nm", "create_table", "create_table_args", "temp",
- "ifnotexists", "dbnm", "columnlist", "conslist_opt",
- "select", "column", "columnid", "type",
- "carglist", "id", "ids", "typetoken",
- "typename", "signed", "plus_num", "minus_num",
- "carg", "ccons", "term", "expr",
- "onconf", "sortorder", "autoinc", "idxlist_opt",
- "refargs", "defer_subclause", "refarg", "refact",
- "init_deferred_pred_opt", "conslist", "tcons", "idxlist",
- "defer_subclause_opt", "orconf", "resolvetype", "raisetype",
- "ifexists", "fullname", "oneselect", "multiselect_op",
- "distinct", "selcollist", "from", "where_opt",
- "groupby_opt", "having_opt", "orderby_opt", "limit_opt",
- "sclp", "as", "seltablist", "stl_prefix",
- "joinop", "indexed_opt", "on_opt", "using_opt",
- "seltablist_paren", "joinop2", "inscollist", "sortlist",
- "sortitem", "nexprlist", "setlist", "insert_cmd",
- "inscollist_opt", "itemlist", "exprlist", "likeop",
- "escape", "between_op", "in_op", "case_operand",
- "case_exprlist", "case_else", "uniqueflag", "collate",
- "nmnum", "plus_opt", "number", "trigger_decl",
- "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
- "when_clause", "trigger_cmd", "database_kw_opt", "key_opt",
- "add_column_fullname", "kwcolumn_opt", "create_vtab", "vtabarglist",
- "vtabarg", "vtabargtoken", "lp", "anylist",
+ "DOT", "FROM", "JOIN", "USING",
+ "ORDER", "BY", "GROUP", "HAVING",
+ "LIMIT", "WHERE", "INTO", "VALUES",
+ "INTEGER", "FLOAT", "BLOB", "REGISTER",
+ "VARIABLE", "CASE", "WHEN", "THEN",
+ "ELSE", "INDEX", "ALTER", "TO",
+ "ADD", "COLUMNKW", "error", "input",
+ "cmdlist", "ecmd", "cmdx", "cmd",
+ "explain", "transtype", "trans_opt", "nm",
+ "create_table", "create_table_args", "temp", "ifnotexists",
+ "dbnm", "columnlist", "conslist_opt", "select",
+ "column", "columnid", "type", "carglist",
+ "id", "ids", "typetoken", "typename",
+ "signed", "plus_num", "minus_num", "carg",
+ "ccons", "term", "expr", "onconf",
+ "sortorder", "autoinc", "idxlist_opt", "refargs",
+ "defer_subclause", "refarg", "refact", "init_deferred_pred_opt",
+ "conslist", "tcons", "idxlist", "defer_subclause_opt",
+ "orconf", "resolvetype", "raisetype", "ifexists",
+ "fullname", "oneselect", "multiselect_op", "distinct",
+ "selcollist", "from", "where_opt", "groupby_opt",
+ "having_opt", "orderby_opt", "limit_opt", "sclp",
+ "as", "seltablist", "stl_prefix", "joinop",
+ "on_opt", "using_opt", "seltablist_paren", "joinop2",
+ "inscollist", "sortlist", "sortitem", "nexprlist",
+ "setlist", "insert_cmd", "inscollist_opt", "itemlist",
+ "exprlist", "likeop", "escape", "between_op",
+ "in_op", "case_operand", "case_exprlist", "case_else",
+ "uniqueflag", "idxitem", "collate", "nmnum",
+ "plus_opt", "number", "trigger_decl", "trigger_cmd_list",
+ "trigger_time", "trigger_event", "foreach_clause", "when_clause",
+ "trigger_cmd", "database_kw_opt", "key_opt", "add_column_fullname",
+ "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg",
+ "vtabargtoken", "lp", "anylist",
};
#endif /* NDEBUG */
@@ -80619,12 +77679,12 @@ static const char *const yyRuleName[] = {
/* 0 */ "input ::= cmdlist",
/* 1 */ "cmdlist ::= cmdlist ecmd",
/* 2 */ "cmdlist ::= ecmd",
- /* 3 */ "ecmd ::= SEMI",
- /* 4 */ "ecmd ::= explain cmdx SEMI",
- /* 5 */ "explain ::=",
- /* 6 */ "explain ::= EXPLAIN",
- /* 7 */ "explain ::= EXPLAIN QUERY PLAN",
- /* 8 */ "cmdx ::= cmd",
+ /* 3 */ "cmdx ::= cmd",
+ /* 4 */ "ecmd ::= SEMI",
+ /* 5 */ "ecmd ::= explain cmdx SEMI",
+ /* 6 */ "explain ::=",
+ /* 7 */ "explain ::= EXPLAIN",
+ /* 8 */ "explain ::= EXPLAIN QUERY PLAN",
/* 9 */ "cmd ::= BEGIN transtype trans_opt",
/* 10 */ "trans_opt ::=",
/* 11 */ "trans_opt ::= TRANSACTION",
@@ -80742,7 +77802,7 @@ static const char *const yyRuleName[] = {
/* 123 */ "from ::= FROM seltablist",
/* 124 */ "stl_prefix ::= seltablist joinop",
/* 125 */ "stl_prefix ::=",
- /* 126 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
+ /* 126 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt",
/* 127 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
/* 128 */ "seltablist_paren ::= select",
/* 129 */ "seltablist_paren ::= seltablist",
@@ -80755,182 +77815,180 @@ static const char *const yyRuleName[] = {
/* 136 */ "joinop ::= JOIN_KW nm nm JOIN",
/* 137 */ "on_opt ::= ON expr",
/* 138 */ "on_opt ::=",
- /* 139 */ "indexed_opt ::=",
- /* 140 */ "indexed_opt ::= INDEXED BY nm",
- /* 141 */ "indexed_opt ::= NOT INDEXED",
- /* 142 */ "using_opt ::= USING LP inscollist RP",
- /* 143 */ "using_opt ::=",
- /* 144 */ "orderby_opt ::=",
- /* 145 */ "orderby_opt ::= ORDER BY sortlist",
- /* 146 */ "sortlist ::= sortlist COMMA sortitem sortorder",
- /* 147 */ "sortlist ::= sortitem sortorder",
- /* 148 */ "sortitem ::= expr",
- /* 149 */ "sortorder ::= ASC",
- /* 150 */ "sortorder ::= DESC",
- /* 151 */ "sortorder ::=",
- /* 152 */ "groupby_opt ::=",
- /* 153 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 154 */ "having_opt ::=",
- /* 155 */ "having_opt ::= HAVING expr",
- /* 156 */ "limit_opt ::=",
- /* 157 */ "limit_opt ::= LIMIT expr",
- /* 158 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 159 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 160 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
- /* 161 */ "where_opt ::=",
- /* 162 */ "where_opt ::= WHERE expr",
- /* 163 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
- /* 164 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 165 */ "setlist ::= nm EQ expr",
- /* 166 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
- /* 167 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
- /* 168 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
- /* 169 */ "insert_cmd ::= INSERT orconf",
- /* 170 */ "insert_cmd ::= REPLACE",
- /* 171 */ "itemlist ::= itemlist COMMA expr",
- /* 172 */ "itemlist ::= expr",
- /* 173 */ "inscollist_opt ::=",
- /* 174 */ "inscollist_opt ::= LP inscollist RP",
- /* 175 */ "inscollist ::= inscollist COMMA nm",
- /* 176 */ "inscollist ::= nm",
- /* 177 */ "expr ::= term",
- /* 178 */ "expr ::= LP expr RP",
- /* 179 */ "term ::= NULL",
- /* 180 */ "expr ::= ID",
- /* 181 */ "expr ::= JOIN_KW",
- /* 182 */ "expr ::= nm DOT nm",
- /* 183 */ "expr ::= nm DOT nm DOT nm",
- /* 184 */ "term ::= INTEGER|FLOAT|BLOB",
- /* 185 */ "term ::= STRING",
- /* 186 */ "expr ::= REGISTER",
- /* 187 */ "expr ::= VARIABLE",
- /* 188 */ "expr ::= expr COLLATE ids",
- /* 189 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 190 */ "expr ::= ID LP distinct exprlist RP",
- /* 191 */ "expr ::= ID LP STAR RP",
- /* 192 */ "term ::= CTIME_KW",
- /* 193 */ "expr ::= expr AND expr",
- /* 194 */ "expr ::= expr OR expr",
- /* 195 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 196 */ "expr ::= expr EQ|NE expr",
- /* 197 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 198 */ "expr ::= expr PLUS|MINUS expr",
- /* 199 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 200 */ "expr ::= expr CONCAT expr",
- /* 201 */ "likeop ::= LIKE_KW",
- /* 202 */ "likeop ::= NOT LIKE_KW",
- /* 203 */ "likeop ::= MATCH",
- /* 204 */ "likeop ::= NOT MATCH",
- /* 205 */ "escape ::= ESCAPE expr",
- /* 206 */ "escape ::=",
- /* 207 */ "expr ::= expr likeop expr escape",
- /* 208 */ "expr ::= expr ISNULL|NOTNULL",
- /* 209 */ "expr ::= expr IS NULL",
- /* 210 */ "expr ::= expr NOT NULL",
- /* 211 */ "expr ::= expr IS NOT NULL",
- /* 212 */ "expr ::= NOT expr",
- /* 213 */ "expr ::= BITNOT expr",
- /* 214 */ "expr ::= MINUS expr",
- /* 215 */ "expr ::= PLUS expr",
- /* 216 */ "between_op ::= BETWEEN",
- /* 217 */ "between_op ::= NOT BETWEEN",
- /* 218 */ "expr ::= expr between_op expr AND expr",
- /* 219 */ "in_op ::= IN",
- /* 220 */ "in_op ::= NOT IN",
- /* 221 */ "expr ::= expr in_op LP exprlist RP",
- /* 222 */ "expr ::= LP select RP",
- /* 223 */ "expr ::= expr in_op LP select RP",
- /* 224 */ "expr ::= expr in_op nm dbnm",
- /* 225 */ "expr ::= EXISTS LP select RP",
- /* 226 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 227 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 228 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 229 */ "case_else ::= ELSE expr",
- /* 230 */ "case_else ::=",
- /* 231 */ "case_operand ::= expr",
- /* 232 */ "case_operand ::=",
- /* 233 */ "exprlist ::= nexprlist",
- /* 234 */ "exprlist ::=",
- /* 235 */ "nexprlist ::= nexprlist COMMA expr",
- /* 236 */ "nexprlist ::= expr",
- /* 237 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
- /* 238 */ "uniqueflag ::= UNIQUE",
- /* 239 */ "uniqueflag ::=",
- /* 240 */ "idxlist_opt ::=",
- /* 241 */ "idxlist_opt ::= LP idxlist RP",
- /* 242 */ "idxlist ::= idxlist COMMA nm collate sortorder",
- /* 243 */ "idxlist ::= nm collate sortorder",
- /* 244 */ "collate ::=",
- /* 245 */ "collate ::= COLLATE ids",
- /* 246 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 247 */ "cmd ::= VACUUM",
- /* 248 */ "cmd ::= VACUUM nm",
- /* 249 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 250 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 251 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
- /* 252 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 253 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 254 */ "cmd ::= PRAGMA nm dbnm",
- /* 255 */ "nmnum ::= plus_num",
- /* 256 */ "nmnum ::= nm",
- /* 257 */ "plus_num ::= plus_opt number",
- /* 258 */ "minus_num ::= MINUS number",
- /* 259 */ "number ::= INTEGER|FLOAT",
- /* 260 */ "plus_opt ::= PLUS",
- /* 261 */ "plus_opt ::=",
- /* 262 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 263 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 264 */ "trigger_time ::= BEFORE",
- /* 265 */ "trigger_time ::= AFTER",
- /* 266 */ "trigger_time ::= INSTEAD OF",
- /* 267 */ "trigger_time ::=",
- /* 268 */ "trigger_event ::= DELETE|INSERT",
- /* 269 */ "trigger_event ::= UPDATE",
- /* 270 */ "trigger_event ::= UPDATE OF inscollist",
- /* 271 */ "foreach_clause ::=",
- /* 272 */ "foreach_clause ::= FOR EACH ROW",
- /* 273 */ "when_clause ::=",
- /* 274 */ "when_clause ::= WHEN expr",
- /* 275 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 276 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 277 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 278 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 279 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 280 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 281 */ "trigger_cmd ::= select",
- /* 282 */ "expr ::= RAISE LP IGNORE RP",
- /* 283 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 284 */ "raisetype ::= ROLLBACK",
- /* 285 */ "raisetype ::= ABORT",
- /* 286 */ "raisetype ::= FAIL",
- /* 287 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 288 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 289 */ "cmd ::= DETACH database_kw_opt expr",
- /* 290 */ "key_opt ::=",
- /* 291 */ "key_opt ::= KEY expr",
- /* 292 */ "database_kw_opt ::= DATABASE",
- /* 293 */ "database_kw_opt ::=",
- /* 294 */ "cmd ::= REINDEX",
- /* 295 */ "cmd ::= REINDEX nm dbnm",
- /* 296 */ "cmd ::= ANALYZE",
- /* 297 */ "cmd ::= ANALYZE nm dbnm",
- /* 298 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 299 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 300 */ "add_column_fullname ::= fullname",
- /* 301 */ "kwcolumn_opt ::=",
- /* 302 */ "kwcolumn_opt ::= COLUMNKW",
- /* 303 */ "cmd ::= create_vtab",
- /* 304 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 305 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
- /* 306 */ "vtabarglist ::= vtabarg",
- /* 307 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 308 */ "vtabarg ::=",
- /* 309 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 310 */ "vtabargtoken ::= ANY",
- /* 311 */ "vtabargtoken ::= lp anylist RP",
- /* 312 */ "lp ::= LP",
- /* 313 */ "anylist ::=",
- /* 314 */ "anylist ::= anylist ANY",
+ /* 139 */ "using_opt ::= USING LP inscollist RP",
+ /* 140 */ "using_opt ::=",
+ /* 141 */ "orderby_opt ::=",
+ /* 142 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 143 */ "sortlist ::= sortlist COMMA sortitem sortorder",
+ /* 144 */ "sortlist ::= sortitem sortorder",
+ /* 145 */ "sortitem ::= expr",
+ /* 146 */ "sortorder ::= ASC",
+ /* 147 */ "sortorder ::= DESC",
+ /* 148 */ "sortorder ::=",
+ /* 149 */ "groupby_opt ::=",
+ /* 150 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 151 */ "having_opt ::=",
+ /* 152 */ "having_opt ::= HAVING expr",
+ /* 153 */ "limit_opt ::=",
+ /* 154 */ "limit_opt ::= LIMIT expr",
+ /* 155 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 156 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 157 */ "cmd ::= DELETE FROM fullname where_opt",
+ /* 158 */ "where_opt ::=",
+ /* 159 */ "where_opt ::= WHERE expr",
+ /* 160 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt",
+ /* 161 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 162 */ "setlist ::= nm EQ expr",
+ /* 163 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
+ /* 164 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
+ /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
+ /* 166 */ "insert_cmd ::= INSERT orconf",
+ /* 167 */ "insert_cmd ::= REPLACE",
+ /* 168 */ "itemlist ::= itemlist COMMA expr",
+ /* 169 */ "itemlist ::= expr",
+ /* 170 */ "inscollist_opt ::=",
+ /* 171 */ "inscollist_opt ::= LP inscollist RP",
+ /* 172 */ "inscollist ::= inscollist COMMA nm",
+ /* 173 */ "inscollist ::= nm",
+ /* 174 */ "expr ::= term",
+ /* 175 */ "expr ::= LP expr RP",
+ /* 176 */ "term ::= NULL",
+ /* 177 */ "expr ::= ID",
+ /* 178 */ "expr ::= JOIN_KW",
+ /* 179 */ "expr ::= nm DOT nm",
+ /* 180 */ "expr ::= nm DOT nm DOT nm",
+ /* 181 */ "term ::= INTEGER|FLOAT|BLOB",
+ /* 182 */ "term ::= STRING",
+ /* 183 */ "expr ::= REGISTER",
+ /* 184 */ "expr ::= VARIABLE",
+ /* 185 */ "expr ::= expr COLLATE ids",
+ /* 186 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 187 */ "expr ::= ID LP distinct exprlist RP",
+ /* 188 */ "expr ::= ID LP STAR RP",
+ /* 189 */ "term ::= CTIME_KW",
+ /* 190 */ "expr ::= expr AND expr",
+ /* 191 */ "expr ::= expr OR expr",
+ /* 192 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 193 */ "expr ::= expr EQ|NE expr",
+ /* 194 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 195 */ "expr ::= expr PLUS|MINUS expr",
+ /* 196 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 197 */ "expr ::= expr CONCAT expr",
+ /* 198 */ "likeop ::= LIKE_KW",
+ /* 199 */ "likeop ::= NOT LIKE_KW",
+ /* 200 */ "likeop ::= MATCH",
+ /* 201 */ "likeop ::= NOT MATCH",
+ /* 202 */ "escape ::= ESCAPE expr",
+ /* 203 */ "escape ::=",
+ /* 204 */ "expr ::= expr likeop expr escape",
+ /* 205 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 206 */ "expr ::= expr IS NULL",
+ /* 207 */ "expr ::= expr NOT NULL",
+ /* 208 */ "expr ::= expr IS NOT NULL",
+ /* 209 */ "expr ::= NOT expr",
+ /* 210 */ "expr ::= BITNOT expr",
+ /* 211 */ "expr ::= MINUS expr",
+ /* 212 */ "expr ::= PLUS expr",
+ /* 213 */ "between_op ::= BETWEEN",
+ /* 214 */ "between_op ::= NOT BETWEEN",
+ /* 215 */ "expr ::= expr between_op expr AND expr",
+ /* 216 */ "in_op ::= IN",
+ /* 217 */ "in_op ::= NOT IN",
+ /* 218 */ "expr ::= expr in_op LP exprlist RP",
+ /* 219 */ "expr ::= LP select RP",
+ /* 220 */ "expr ::= expr in_op LP select RP",
+ /* 221 */ "expr ::= expr in_op nm dbnm",
+ /* 222 */ "expr ::= EXISTS LP select RP",
+ /* 223 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 224 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 225 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 226 */ "case_else ::= ELSE expr",
+ /* 227 */ "case_else ::=",
+ /* 228 */ "case_operand ::= expr",
+ /* 229 */ "case_operand ::=",
+ /* 230 */ "exprlist ::= nexprlist",
+ /* 231 */ "exprlist ::=",
+ /* 232 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 233 */ "nexprlist ::= expr",
+ /* 234 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
+ /* 235 */ "uniqueflag ::= UNIQUE",
+ /* 236 */ "uniqueflag ::=",
+ /* 237 */ "idxlist_opt ::=",
+ /* 238 */ "idxlist_opt ::= LP idxlist RP",
+ /* 239 */ "idxlist ::= idxlist COMMA idxitem collate sortorder",
+ /* 240 */ "idxlist ::= idxitem collate sortorder",
+ /* 241 */ "idxitem ::= nm",
+ /* 242 */ "collate ::=",
+ /* 243 */ "collate ::= COLLATE ids",
+ /* 244 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 245 */ "cmd ::= VACUUM",
+ /* 246 */ "cmd ::= VACUUM nm",
+ /* 247 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 248 */ "cmd ::= PRAGMA nm dbnm EQ ON",
+ /* 249 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
+ /* 250 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 251 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 252 */ "cmd ::= PRAGMA nm dbnm",
+ /* 253 */ "nmnum ::= plus_num",
+ /* 254 */ "nmnum ::= nm",
+ /* 255 */ "plus_num ::= plus_opt number",
+ /* 256 */ "minus_num ::= MINUS number",
+ /* 257 */ "number ::= INTEGER|FLOAT",
+ /* 258 */ "plus_opt ::= PLUS",
+ /* 259 */ "plus_opt ::=",
+ /* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
+ /* 261 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 262 */ "trigger_time ::= BEFORE",
+ /* 263 */ "trigger_time ::= AFTER",
+ /* 264 */ "trigger_time ::= INSTEAD OF",
+ /* 265 */ "trigger_time ::=",
+ /* 266 */ "trigger_event ::= DELETE|INSERT",
+ /* 267 */ "trigger_event ::= UPDATE",
+ /* 268 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 269 */ "foreach_clause ::=",
+ /* 270 */ "foreach_clause ::= FOR EACH ROW",
+ /* 271 */ "when_clause ::=",
+ /* 272 */ "when_clause ::= WHEN expr",
+ /* 273 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 274 */ "trigger_cmd_list ::=",
+ /* 275 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
+ /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
+ /* 277 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
+ /* 278 */ "trigger_cmd ::= DELETE FROM nm where_opt",
+ /* 279 */ "trigger_cmd ::= select",
+ /* 280 */ "expr ::= RAISE LP IGNORE RP",
+ /* 281 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 282 */ "raisetype ::= ROLLBACK",
+ /* 283 */ "raisetype ::= ABORT",
+ /* 284 */ "raisetype ::= FAIL",
+ /* 285 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 286 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 287 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 288 */ "key_opt ::=",
+ /* 289 */ "key_opt ::= KEY expr",
+ /* 290 */ "database_kw_opt ::= DATABASE",
+ /* 291 */ "database_kw_opt ::=",
+ /* 292 */ "cmd ::= REINDEX",
+ /* 293 */ "cmd ::= REINDEX nm dbnm",
+ /* 294 */ "cmd ::= ANALYZE",
+ /* 295 */ "cmd ::= ANALYZE nm dbnm",
+ /* 296 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 297 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 298 */ "add_column_fullname ::= fullname",
+ /* 299 */ "kwcolumn_opt ::=",
+ /* 300 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 301 */ "cmd ::= create_vtab",
+ /* 302 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 303 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
+ /* 304 */ "vtabarglist ::= vtabarg",
+ /* 305 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 306 */ "vtabarg ::=",
+ /* 307 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 308 */ "vtabargtoken ::= ANY",
+ /* 309 */ "vtabargtoken ::= lp anylist RP",
+ /* 310 */ "lp ::= LP",
+ /* 311 */ "anylist ::=",
+ /* 312 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */
@@ -80979,8 +78037,6 @@ SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(size_t)){
pParser->yyidxMax = 0;
#endif
#if YYSTACKDEPTH<=0
- pParser->yystack = NULL;
- pParser->yystksz = 0;
yyGrowStack(pParser);
#endif
}
@@ -81009,68 +78065,68 @@ static void yy_destructor(
** which appear on the RHS of the rule, but which are not used
** inside the C code.
*/
- case 156: /* select */
- case 190: /* oneselect */
- case 208: /* seltablist_paren */
+ case 155: /* select */
+ case 189: /* oneselect */
+ case 206: /* seltablist_paren */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy43));
+sqlite3SelectDelete(pParse->db, (yypminor->yy219));
}
break;
- case 170: /* term */
- case 171: /* expr */
- case 195: /* where_opt */
- case 197: /* having_opt */
- case 206: /* on_opt */
- case 212: /* sortitem */
- case 220: /* escape */
- case 223: /* case_operand */
- case 225: /* case_else */
- case 236: /* when_clause */
- case 239: /* key_opt */
+ case 169: /* term */
+ case 170: /* expr */
+ case 194: /* where_opt */
+ case 196: /* having_opt */
+ case 204: /* on_opt */
+ case 210: /* sortitem */
+ case 218: /* escape */
+ case 221: /* case_operand */
+ case 223: /* case_else */
+ case 235: /* when_clause */
+ case 238: /* key_opt */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy450));
+sqlite3ExprDelete(pParse->db, (yypminor->yy172));
}
break;
- case 175: /* idxlist_opt */
- case 183: /* idxlist */
- case 193: /* selcollist */
- case 196: /* groupby_opt */
- case 198: /* orderby_opt */
- case 200: /* sclp */
- case 211: /* sortlist */
- case 213: /* nexprlist */
- case 214: /* setlist */
- case 217: /* itemlist */
- case 218: /* exprlist */
- case 224: /* case_exprlist */
+ case 174: /* idxlist_opt */
+ case 182: /* idxlist */
+ case 192: /* selcollist */
+ case 195: /* groupby_opt */
+ case 197: /* orderby_opt */
+ case 199: /* sclp */
+ case 209: /* sortlist */
+ case 211: /* nexprlist */
+ case 212: /* setlist */
+ case 215: /* itemlist */
+ case 216: /* exprlist */
+ case 222: /* case_exprlist */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy242));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy174));
}
break;
- case 189: /* fullname */
- case 194: /* from */
- case 202: /* seltablist */
- case 203: /* stl_prefix */
+ case 188: /* fullname */
+ case 193: /* from */
+ case 201: /* seltablist */
+ case 202: /* stl_prefix */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy419));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy373));
}
break;
- case 207: /* using_opt */
- case 210: /* inscollist */
- case 216: /* inscollist_opt */
+ case 205: /* using_opt */
+ case 208: /* inscollist */
+ case 214: /* inscollist_opt */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy352));
+sqlite3IdListDelete(pParse->db, (yypminor->yy432));
}
break;
- case 232: /* trigger_cmd_list */
- case 237: /* trigger_cmd */
+ case 231: /* trigger_cmd_list */
+ case 236: /* trigger_cmd */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy75));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy243));
}
break;
- case 234: /* trigger_event */
+ case 233: /* trigger_event */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy354).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy370).b);
}
break;
default: break; /* If no destructor action specified: do nothing */
@@ -81302,321 +78358,319 @@ static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
+ { 139, 1 },
+ { 140, 2 },
{ 140, 1 },
- { 141, 2 },
- { 141, 1 },
{ 142, 1 },
- { 142, 3 },
- { 143, 0 },
- { 143, 1 },
- { 143, 3 },
+ { 141, 1 },
+ { 141, 3 },
+ { 144, 0 },
{ 144, 1 },
- { 145, 3 },
- { 147, 0 },
- { 147, 1 },
- { 147, 2 },
+ { 144, 3 },
+ { 143, 3 },
{ 146, 0 },
{ 146, 1 },
- { 146, 1 },
- { 146, 1 },
- { 145, 2 },
- { 145, 2 },
- { 145, 2 },
- { 145, 2 },
- { 149, 6 },
- { 152, 0 },
- { 152, 3 },
- { 151, 1 },
+ { 146, 2 },
+ { 145, 0 },
+ { 145, 1 },
+ { 145, 1 },
+ { 145, 1 },
+ { 143, 2 },
+ { 143, 2 },
+ { 143, 2 },
+ { 143, 2 },
+ { 148, 6 },
{ 151, 0 },
- { 150, 4 },
- { 150, 2 },
- { 154, 3 },
- { 154, 1 },
- { 157, 3 },
- { 158, 1 },
+ { 151, 3 },
+ { 150, 1 },
+ { 150, 0 },
+ { 149, 4 },
+ { 149, 2 },
+ { 153, 3 },
+ { 153, 1 },
+ { 156, 3 },
+ { 157, 1 },
+ { 160, 1 },
{ 161, 1 },
+ { 147, 1 },
+ { 147, 1 },
+ { 147, 1 },
+ { 158, 0 },
+ { 158, 1 },
{ 162, 1 },
- { 148, 1 },
- { 148, 1 },
- { 148, 1 },
- { 159, 0 },
- { 159, 1 },
+ { 162, 4 },
+ { 162, 6 },
{ 163, 1 },
- { 163, 4 },
- { 163, 6 },
+ { 163, 2 },
{ 164, 1 },
- { 164, 2 },
- { 165, 1 },
- { 165, 1 },
- { 160, 2 },
- { 160, 0 },
+ { 164, 1 },
+ { 159, 2 },
+ { 159, 0 },
+ { 167, 3 },
+ { 167, 1 },
+ { 168, 2 },
+ { 168, 4 },
+ { 168, 3 },
{ 168, 3 },
+ { 168, 2 },
+ { 168, 2 },
+ { 168, 3 },
+ { 168, 5 },
+ { 168, 2 },
+ { 168, 4 },
+ { 168, 4 },
{ 168, 1 },
- { 169, 2 },
- { 169, 4 },
- { 169, 3 },
- { 169, 3 },
- { 169, 2 },
- { 169, 2 },
- { 169, 3 },
- { 169, 5 },
- { 169, 2 },
- { 169, 4 },
- { 169, 4 },
- { 169, 1 },
- { 169, 2 },
- { 174, 0 },
- { 174, 1 },
- { 176, 0 },
- { 176, 2 },
+ { 168, 2 },
+ { 173, 0 },
+ { 173, 1 },
+ { 175, 0 },
+ { 175, 2 },
+ { 177, 2 },
+ { 177, 3 },
+ { 177, 3 },
+ { 177, 3 },
+ { 178, 2 },
{ 178, 2 },
- { 178, 3 },
- { 178, 3 },
- { 178, 3 },
+ { 178, 1 },
+ { 178, 1 },
+ { 176, 3 },
+ { 176, 2 },
+ { 179, 0 },
{ 179, 2 },
{ 179, 2 },
- { 179, 1 },
- { 179, 1 },
- { 177, 3 },
- { 177, 2 },
- { 180, 0 },
- { 180, 2 },
+ { 154, 0 },
+ { 154, 2 },
+ { 180, 3 },
{ 180, 2 },
- { 155, 0 },
- { 155, 2 },
- { 181, 3 },
+ { 180, 1 },
{ 181, 2 },
- { 181, 1 },
- { 182, 2 },
- { 182, 7 },
- { 182, 5 },
- { 182, 5 },
- { 182, 10 },
+ { 181, 7 },
+ { 181, 5 },
+ { 181, 5 },
+ { 181, 10 },
+ { 183, 0 },
+ { 183, 1 },
+ { 171, 0 },
+ { 171, 3 },
{ 184, 0 },
- { 184, 1 },
- { 172, 0 },
- { 172, 3 },
- { 185, 0 },
- { 185, 2 },
- { 186, 1 },
- { 186, 1 },
- { 186, 1 },
- { 145, 4 },
- { 188, 2 },
- { 188, 0 },
- { 145, 8 },
- { 145, 4 },
- { 145, 1 },
- { 156, 1 },
- { 156, 3 },
+ { 184, 2 },
+ { 185, 1 },
+ { 185, 1 },
+ { 185, 1 },
+ { 143, 4 },
+ { 187, 2 },
+ { 187, 0 },
+ { 143, 8 },
+ { 143, 4 },
+ { 143, 1 },
+ { 155, 1 },
+ { 155, 3 },
+ { 190, 1 },
+ { 190, 2 },
+ { 190, 1 },
+ { 189, 9 },
{ 191, 1 },
- { 191, 2 },
{ 191, 1 },
- { 190, 9 },
- { 192, 1 },
- { 192, 1 },
- { 192, 0 },
+ { 191, 0 },
+ { 199, 2 },
+ { 199, 0 },
+ { 192, 3 },
+ { 192, 2 },
+ { 192, 4 },
{ 200, 2 },
+ { 200, 1 },
{ 200, 0 },
- { 193, 3 },
+ { 193, 0 },
{ 193, 2 },
- { 193, 4 },
- { 201, 2 },
- { 201, 1 },
- { 201, 0 },
- { 194, 0 },
- { 194, 2 },
+ { 202, 2 },
+ { 202, 0 },
+ { 201, 6 },
+ { 201, 7 },
+ { 206, 1 },
+ { 206, 1 },
+ { 152, 0 },
+ { 152, 2 },
+ { 188, 2 },
+ { 203, 1 },
{ 203, 2 },
- { 203, 0 },
- { 202, 7 },
- { 202, 7 },
- { 208, 1 },
- { 208, 1 },
- { 153, 0 },
- { 153, 2 },
- { 189, 2 },
- { 204, 1 },
+ { 203, 3 },
+ { 203, 4 },
{ 204, 2 },
- { 204, 3 },
- { 204, 4 },
- { 206, 2 },
- { 206, 0 },
+ { 204, 0 },
+ { 205, 4 },
{ 205, 0 },
- { 205, 3 },
- { 205, 2 },
- { 207, 4 },
- { 207, 0 },
- { 198, 0 },
- { 198, 3 },
- { 211, 4 },
- { 211, 2 },
- { 212, 1 },
- { 173, 1 },
- { 173, 1 },
- { 173, 0 },
- { 196, 0 },
- { 196, 3 },
{ 197, 0 },
- { 197, 2 },
- { 199, 0 },
- { 199, 2 },
- { 199, 4 },
- { 199, 4 },
- { 145, 5 },
+ { 197, 3 },
+ { 209, 4 },
+ { 209, 2 },
+ { 210, 1 },
+ { 172, 1 },
+ { 172, 1 },
+ { 172, 0 },
{ 195, 0 },
- { 195, 2 },
- { 145, 7 },
- { 214, 5 },
- { 214, 3 },
- { 145, 8 },
- { 145, 5 },
- { 145, 6 },
- { 215, 2 },
+ { 195, 3 },
+ { 196, 0 },
+ { 196, 2 },
+ { 198, 0 },
+ { 198, 2 },
+ { 198, 4 },
+ { 198, 4 },
+ { 143, 4 },
+ { 194, 0 },
+ { 194, 2 },
+ { 143, 6 },
+ { 212, 5 },
+ { 212, 3 },
+ { 143, 8 },
+ { 143, 5 },
+ { 143, 6 },
+ { 213, 2 },
+ { 213, 1 },
+ { 215, 3 },
{ 215, 1 },
- { 217, 3 },
- { 217, 1 },
- { 216, 0 },
- { 216, 3 },
- { 210, 3 },
- { 210, 1 },
- { 171, 1 },
- { 171, 3 },
+ { 214, 0 },
+ { 214, 3 },
+ { 208, 3 },
+ { 208, 1 },
{ 170, 1 },
- { 171, 1 },
- { 171, 1 },
- { 171, 3 },
- { 171, 5 },
+ { 170, 3 },
+ { 169, 1 },
{ 170, 1 },
{ 170, 1 },
- { 171, 1 },
- { 171, 1 },
- { 171, 3 },
- { 171, 6 },
- { 171, 5 },
- { 171, 4 },
+ { 170, 3 },
+ { 170, 5 },
+ { 169, 1 },
+ { 169, 1 },
{ 170, 1 },
- { 171, 3 },
- { 171, 3 },
- { 171, 3 },
- { 171, 3 },
- { 171, 3 },
- { 171, 3 },
- { 171, 3 },
- { 171, 3 },
- { 219, 1 },
- { 219, 2 },
+ { 170, 1 },
+ { 170, 3 },
+ { 170, 6 },
+ { 170, 5 },
+ { 170, 4 },
+ { 169, 1 },
+ { 170, 3 },
+ { 170, 3 },
+ { 170, 3 },
+ { 170, 3 },
+ { 170, 3 },
+ { 170, 3 },
+ { 170, 3 },
+ { 170, 3 },
+ { 217, 1 },
+ { 217, 2 },
+ { 217, 1 },
+ { 217, 2 },
+ { 218, 2 },
+ { 218, 0 },
+ { 170, 4 },
+ { 170, 2 },
+ { 170, 3 },
+ { 170, 3 },
+ { 170, 4 },
+ { 170, 2 },
+ { 170, 2 },
+ { 170, 2 },
+ { 170, 2 },
{ 219, 1 },
{ 219, 2 },
+ { 170, 5 },
+ { 220, 1 },
{ 220, 2 },
- { 220, 0 },
- { 171, 4 },
- { 171, 2 },
- { 171, 3 },
- { 171, 3 },
- { 171, 4 },
- { 171, 2 },
- { 171, 2 },
- { 171, 2 },
- { 171, 2 },
- { 221, 1 },
- { 221, 2 },
- { 171, 5 },
- { 222, 1 },
- { 222, 2 },
- { 171, 5 },
- { 171, 3 },
- { 171, 5 },
- { 171, 4 },
- { 171, 4 },
- { 171, 5 },
- { 224, 5 },
- { 224, 4 },
- { 225, 2 },
- { 225, 0 },
- { 223, 1 },
+ { 170, 5 },
+ { 170, 3 },
+ { 170, 5 },
+ { 170, 4 },
+ { 170, 4 },
+ { 170, 5 },
+ { 222, 5 },
+ { 222, 4 },
+ { 223, 2 },
{ 223, 0 },
- { 218, 1 },
- { 218, 0 },
- { 213, 3 },
- { 213, 1 },
- { 145, 11 },
- { 226, 1 },
+ { 221, 1 },
+ { 221, 0 },
+ { 216, 1 },
+ { 216, 0 },
+ { 211, 3 },
+ { 211, 1 },
+ { 143, 11 },
+ { 224, 1 },
+ { 224, 0 },
+ { 174, 0 },
+ { 174, 3 },
+ { 182, 5 },
+ { 182, 3 },
+ { 225, 1 },
{ 226, 0 },
- { 175, 0 },
- { 175, 3 },
- { 183, 5 },
- { 183, 3 },
- { 227, 0 },
- { 227, 2 },
- { 145, 4 },
- { 145, 1 },
- { 145, 2 },
- { 145, 5 },
- { 145, 5 },
- { 145, 5 },
- { 145, 5 },
- { 145, 6 },
- { 145, 3 },
- { 228, 1 },
- { 228, 1 },
+ { 226, 2 },
+ { 143, 4 },
+ { 143, 1 },
+ { 143, 2 },
+ { 143, 5 },
+ { 143, 5 },
+ { 143, 5 },
+ { 143, 5 },
+ { 143, 6 },
+ { 143, 3 },
+ { 227, 1 },
+ { 227, 1 },
+ { 165, 2 },
{ 166, 2 },
- { 167, 2 },
- { 230, 1 },
{ 229, 1 },
- { 229, 0 },
- { 145, 5 },
- { 231, 11 },
+ { 228, 1 },
+ { 228, 0 },
+ { 143, 5 },
+ { 230, 11 },
+ { 232, 1 },
+ { 232, 1 },
+ { 232, 2 },
+ { 232, 0 },
{ 233, 1 },
{ 233, 1 },
- { 233, 2 },
- { 233, 0 },
- { 234, 1 },
- { 234, 1 },
+ { 233, 3 },
+ { 234, 0 },
{ 234, 3 },
{ 235, 0 },
- { 235, 3 },
- { 236, 0 },
- { 236, 2 },
- { 232, 3 },
- { 232, 2 },
- { 237, 6 },
- { 237, 8 },
- { 237, 5 },
- { 237, 4 },
- { 237, 1 },
- { 171, 4 },
- { 171, 6 },
- { 187, 1 },
- { 187, 1 },
- { 187, 1 },
- { 145, 4 },
- { 145, 6 },
- { 145, 3 },
- { 239, 0 },
- { 239, 2 },
- { 238, 1 },
+ { 235, 2 },
+ { 231, 3 },
+ { 231, 0 },
+ { 236, 6 },
+ { 236, 8 },
+ { 236, 5 },
+ { 236, 4 },
+ { 236, 1 },
+ { 170, 4 },
+ { 170, 6 },
+ { 186, 1 },
+ { 186, 1 },
+ { 186, 1 },
+ { 143, 4 },
+ { 143, 6 },
+ { 143, 3 },
{ 238, 0 },
- { 145, 1 },
- { 145, 3 },
- { 145, 1 },
- { 145, 3 },
- { 145, 6 },
- { 145, 6 },
+ { 238, 2 },
+ { 237, 1 },
+ { 237, 0 },
+ { 143, 1 },
+ { 143, 3 },
+ { 143, 1 },
+ { 143, 3 },
+ { 143, 6 },
+ { 143, 6 },
+ { 239, 1 },
+ { 240, 0 },
{ 240, 1 },
- { 241, 0 },
- { 241, 1 },
- { 145, 1 },
- { 145, 4 },
- { 242, 7 },
- { 243, 1 },
- { 243, 3 },
- { 244, 0 },
- { 244, 2 },
+ { 143, 1 },
+ { 143, 4 },
+ { 241, 7 },
+ { 242, 1 },
+ { 242, 3 },
+ { 243, 0 },
+ { 243, 2 },
+ { 244, 1 },
+ { 244, 3 },
{ 245, 1 },
- { 245, 3 },
- { 246, 1 },
- { 247, 0 },
- { 247, 2 },
+ { 246, 0 },
+ { 246, 2 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -81674,8 +78728,8 @@ static void yy_reduce(
case 0: /* input ::= cmdlist */
case 1: /* cmdlist ::= cmdlist ecmd */
case 2: /* cmdlist ::= ecmd */
- case 3: /* ecmd ::= SEMI */
- case 4: /* ecmd ::= explain cmdx SEMI */
+ case 4: /* ecmd ::= SEMI */
+ case 5: /* ecmd ::= explain cmdx SEMI */
case 10: /* trans_opt ::= */
case 11: /* trans_opt ::= TRANSACTION */
case 12: /* trans_opt ::= TRANSACTION nm */
@@ -81694,45 +78748,45 @@ static void yy_reduce(
case 83: /* conslist ::= conslist tcons */
case 84: /* conslist ::= tcons */
case 85: /* tcons ::= CONSTRAINT nm */
- case 260: /* plus_opt ::= PLUS */
- case 261: /* plus_opt ::= */
- case 271: /* foreach_clause ::= */
- case 272: /* foreach_clause ::= FOR EACH ROW */
- case 292: /* database_kw_opt ::= DATABASE */
- case 293: /* database_kw_opt ::= */
- case 301: /* kwcolumn_opt ::= */
- case 302: /* kwcolumn_opt ::= COLUMNKW */
- case 306: /* vtabarglist ::= vtabarg */
- case 307: /* vtabarglist ::= vtabarglist COMMA vtabarg */
- case 309: /* vtabarg ::= vtabarg vtabargtoken */
- case 313: /* anylist ::= */
+ case 258: /* plus_opt ::= PLUS */
+ case 259: /* plus_opt ::= */
+ case 269: /* foreach_clause ::= */
+ case 270: /* foreach_clause ::= FOR EACH ROW */
+ case 290: /* database_kw_opt ::= DATABASE */
+ case 291: /* database_kw_opt ::= */
+ case 299: /* kwcolumn_opt ::= */
+ case 300: /* kwcolumn_opt ::= COLUMNKW */
+ case 304: /* vtabarglist ::= vtabarg */
+ case 305: /* vtabarglist ::= vtabarglist COMMA vtabarg */
+ case 307: /* vtabarg ::= vtabarg vtabargtoken */
+ case 311: /* anylist ::= */
{
}
break;
- case 5: /* explain ::= */
+ case 3: /* cmdx ::= cmd */
+{ sqlite3FinishCoding(pParse); }
+ break;
+ case 6: /* explain ::= */
{ sqlite3BeginParse(pParse, 0); }
break;
- case 6: /* explain ::= EXPLAIN */
+ case 7: /* explain ::= EXPLAIN */
{ sqlite3BeginParse(pParse, 1); }
break;
- case 7: /* explain ::= EXPLAIN QUERY PLAN */
+ case 8: /* explain ::= EXPLAIN QUERY PLAN */
{ sqlite3BeginParse(pParse, 2); }
break;
- case 8: /* cmdx ::= cmd */
-{ sqlite3FinishCoding(pParse); }
- break;
case 9: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy316);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy46);}
break;
case 13: /* transtype ::= */
-{yygotominor.yy316 = TK_DEFERRED;}
+{yygotominor.yy46 = TK_DEFERRED;}
break;
case 14: /* transtype ::= DEFERRED */
case 15: /* transtype ::= IMMEDIATE */
case 16: /* transtype ::= EXCLUSIVE */
case 107: /* multiselect_op ::= UNION */
case 109: /* multiselect_op ::= EXCEPT|INTERSECT */
-{yygotominor.yy316 = yymsp[0].major;}
+{yygotominor.yy46 = yymsp[0].major;}
break;
case 17: /* cmd ::= COMMIT trans_opt */
case 18: /* cmd ::= END trans_opt */
@@ -81743,7 +78797,7 @@ static void yy_reduce(
break;
case 21: /* create_table ::= CREATE temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy316,0,0,yymsp[-2].minor.yy316);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy46,0,0,yymsp[-2].minor.yy46);
}
break;
case 22: /* ifnotexists ::= */
@@ -81755,9 +78809,9 @@ static void yy_reduce(
case 101: /* ifexists ::= */
case 112: /* distinct ::= ALL */
case 113: /* distinct ::= */
- case 216: /* between_op ::= BETWEEN */
- case 219: /* in_op ::= IN */
-{yygotominor.yy316 = 0;}
+ case 213: /* between_op ::= BETWEEN */
+ case 216: /* in_op ::= IN */
+{yygotominor.yy46 = 0;}
break;
case 23: /* ifnotexists ::= IF NOT EXISTS */
case 24: /* temp ::= TEMP */
@@ -81765,9 +78819,9 @@ static void yy_reduce(
case 78: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 100: /* ifexists ::= IF EXISTS */
case 111: /* distinct ::= DISTINCT */
- case 217: /* between_op ::= NOT BETWEEN */
- case 220: /* in_op ::= NOT IN */
-{yygotominor.yy316 = 1;}
+ case 214: /* between_op ::= NOT BETWEEN */
+ case 217: /* in_op ::= NOT IN */
+{yygotominor.yy46 = 1;}
break;
case 26: /* create_table_args ::= LP columnlist conslist_opt RP */
{
@@ -81776,8 +78830,8 @@ static void yy_reduce(
break;
case 27: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy43);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43);
+ sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy219);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy219);
}
break;
case 30: /* column ::= columnid type carglist */
@@ -81802,13 +78856,13 @@ static void yy_reduce(
case 119: /* as ::= AS nm */
case 120: /* as ::= ids */
case 131: /* dbnm ::= DOT nm */
- case 140: /* indexed_opt ::= INDEXED BY nm */
- case 245: /* collate ::= COLLATE ids */
- case 255: /* nmnum ::= plus_num */
- case 256: /* nmnum ::= nm */
- case 257: /* plus_num ::= plus_opt number */
- case 258: /* minus_num ::= MINUS number */
- case 259: /* number ::= INTEGER|FLOAT */
+ case 241: /* idxitem ::= nm */
+ case 243: /* collate ::= COLLATE ids */
+ case 253: /* nmnum ::= plus_num */
+ case 254: /* nmnum ::= nm */
+ case 255: /* plus_num ::= plus_opt number */
+ case 256: /* minus_num ::= MINUS number */
+ case 257: /* number ::= INTEGER|FLOAT */
{yygotominor.yy0 = yymsp[0].minor.yy0;}
break;
case 38: /* type ::= typetoken */
@@ -81831,15 +78885,14 @@ static void yy_reduce(
break;
case 50: /* ccons ::= DEFAULT term */
case 52: /* ccons ::= DEFAULT PLUS term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy450);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy172);}
break;
case 51: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy450);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy172);}
break;
case 53: /* ccons ::= DEFAULT MINUS term */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy450, 0, 0);
- sqlite3ExprSpan(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy172, 0, 0);
sqlite3AddDefaultValue(pParse,p);
}
break;
@@ -81850,55 +78903,55 @@ static void yy_reduce(
}
break;
case 56: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy316);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy46);}
break;
case 57: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy316,yymsp[0].minor.yy316,yymsp[-2].minor.yy316);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy46,yymsp[-2].minor.yy46);}
break;
case 58: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy316,0,0,0,0);}
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy46,0,0,0,0);}
break;
case 59: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy450);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy172);}
break;
case 60: /* ccons ::= REFERENCES nm idxlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy242,yymsp[0].minor.yy316);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy174,yymsp[0].minor.yy46);}
break;
case 61: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy316);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy46);}
break;
case 62: /* ccons ::= COLLATE ids */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 65: /* refargs ::= */
-{ yygotominor.yy316 = OE_Restrict * 0x010101; }
+{ yygotominor.yy46 = OE_Restrict * 0x010101; }
break;
case 66: /* refargs ::= refargs refarg */
-{ yygotominor.yy316 = (yymsp[-1].minor.yy316 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
+{ yygotominor.yy46 = (yymsp[-1].minor.yy46 & yymsp[0].minor.yy405.mask) | yymsp[0].minor.yy405.value; }
break;
case 67: /* refarg ::= MATCH nm */
-{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; }
+{ yygotominor.yy405.value = 0; yygotominor.yy405.mask = 0x000000; }
break;
case 68: /* refarg ::= ON DELETE refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy316; yygotominor.yy207.mask = 0x0000ff; }
+{ yygotominor.yy405.value = yymsp[0].minor.yy46; yygotominor.yy405.mask = 0x0000ff; }
break;
case 69: /* refarg ::= ON UPDATE refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy316<<8; yygotominor.yy207.mask = 0x00ff00; }
+{ yygotominor.yy405.value = yymsp[0].minor.yy46<<8; yygotominor.yy405.mask = 0x00ff00; }
break;
case 70: /* refarg ::= ON INSERT refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy316<<16; yygotominor.yy207.mask = 0xff0000; }
+{ yygotominor.yy405.value = yymsp[0].minor.yy46<<16; yygotominor.yy405.mask = 0xff0000; }
break;
case 71: /* refact ::= SET NULL */
-{ yygotominor.yy316 = OE_SetNull; }
+{ yygotominor.yy46 = OE_SetNull; }
break;
case 72: /* refact ::= SET DEFAULT */
-{ yygotominor.yy316 = OE_SetDflt; }
+{ yygotominor.yy46 = OE_SetDflt; }
break;
case 73: /* refact ::= CASCADE */
-{ yygotominor.yy316 = OE_Cascade; }
+{ yygotominor.yy46 = OE_Cascade; }
break;
case 74: /* refact ::= RESTRICT */
-{ yygotominor.yy316 = OE_Restrict; }
+{ yygotominor.yy46 = OE_Restrict; }
break;
case 75: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
case 76: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
@@ -81906,8 +78959,8 @@ static void yy_reduce(
case 93: /* onconf ::= ON CONFLICT resolvetype */
case 95: /* orconf ::= OR resolvetype */
case 96: /* resolvetype ::= raisetype */
- case 169: /* insert_cmd ::= INSERT orconf */
-{yygotominor.yy316 = yymsp[0].minor.yy316;}
+ case 166: /* insert_cmd ::= INSERT orconf */
+{yygotominor.yy46 = yymsp[0].minor.yy46;}
break;
case 80: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
@@ -81916,96 +78969,96 @@ static void yy_reduce(
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
break;
case 86: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy242,yymsp[0].minor.yy316,yymsp[-2].minor.yy316,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy174,yymsp[0].minor.yy46,yymsp[-2].minor.yy46,0);}
break;
case 87: /* tcons ::= UNIQUE LP idxlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy242,yymsp[0].minor.yy316,0,0,0,0);}
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy174,yymsp[0].minor.yy46,0,0,0,0);}
break;
case 88: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy450);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy172);}
break;
case 89: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy242, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[-1].minor.yy316);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy316);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy174, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy174, yymsp[-1].minor.yy46);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy46);
}
break;
case 92: /* onconf ::= */
case 94: /* orconf ::= */
-{yygotominor.yy316 = OE_Default;}
+{yygotominor.yy46 = OE_Default;}
break;
case 97: /* resolvetype ::= IGNORE */
-{yygotominor.yy316 = OE_Ignore;}
+{yygotominor.yy46 = OE_Ignore;}
break;
case 98: /* resolvetype ::= REPLACE */
- case 170: /* insert_cmd ::= REPLACE */
-{yygotominor.yy316 = OE_Replace;}
+ case 167: /* insert_cmd ::= REPLACE */
+{yygotominor.yy46 = OE_Replace;}
break;
case 99: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy419, 0, yymsp[-1].minor.yy316);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy373, 0, yymsp[-1].minor.yy46);
}
break;
case 102: /* cmd ::= CREATE temp VIEW ifnotexists nm dbnm AS select */
{
- sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy43, yymsp[-6].minor.yy316, yymsp[-4].minor.yy316);
+ sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy219, yymsp[-6].minor.yy46, yymsp[-4].minor.yy46);
}
break;
case 103: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy419, 1, yymsp[-1].minor.yy316);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy373, 1, yymsp[-1].minor.yy46);
}
break;
case 104: /* cmd ::= select */
{
- SelectDest dest = {SRT_Output, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy43, &dest);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43);
+ SelectDest dest = {SRT_Callback, 0, 0, 0, 0};
+ sqlite3Select(pParse, yymsp[0].minor.yy219, &dest, 0, 0, 0);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy219);
}
break;
case 105: /* select ::= oneselect */
case 128: /* seltablist_paren ::= select */
-{yygotominor.yy43 = yymsp[0].minor.yy43;}
+{yygotominor.yy219 = yymsp[0].minor.yy219;}
break;
case 106: /* select ::= select multiselect_op oneselect */
{
- if( yymsp[0].minor.yy43 ){
- yymsp[0].minor.yy43->op = yymsp[-1].minor.yy316;
- yymsp[0].minor.yy43->pPrior = yymsp[-2].minor.yy43;
+ if( yymsp[0].minor.yy219 ){
+ yymsp[0].minor.yy219->op = yymsp[-1].minor.yy46;
+ yymsp[0].minor.yy219->pPrior = yymsp[-2].minor.yy219;
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy43);
+ sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy219);
}
- yygotominor.yy43 = yymsp[0].minor.yy43;
+ yygotominor.yy219 = yymsp[0].minor.yy219;
}
break;
case 108: /* multiselect_op ::= UNION ALL */
-{yygotominor.yy316 = TK_ALL;}
+{yygotominor.yy46 = TK_ALL;}
break;
case 110: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yygotominor.yy43 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy242,yymsp[-5].minor.yy419,yymsp[-4].minor.yy450,yymsp[-3].minor.yy242,yymsp[-2].minor.yy450,yymsp[-1].minor.yy242,yymsp[-7].minor.yy316,yymsp[0].minor.yy84.pLimit,yymsp[0].minor.yy84.pOffset);
+ yygotominor.yy219 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy174,yymsp[-5].minor.yy373,yymsp[-4].minor.yy172,yymsp[-3].minor.yy174,yymsp[-2].minor.yy172,yymsp[-1].minor.yy174,yymsp[-7].minor.yy46,yymsp[0].minor.yy234.pLimit,yymsp[0].minor.yy234.pOffset);
}
break;
case 114: /* sclp ::= selcollist COMMA */
- case 241: /* idxlist_opt ::= LP idxlist RP */
-{yygotominor.yy242 = yymsp[-1].minor.yy242;}
+ case 238: /* idxlist_opt ::= LP idxlist RP */
+{yygotominor.yy174 = yymsp[-1].minor.yy174;}
break;
case 115: /* sclp ::= */
- case 144: /* orderby_opt ::= */
- case 152: /* groupby_opt ::= */
- case 234: /* exprlist ::= */
- case 240: /* idxlist_opt ::= */
-{yygotominor.yy242 = 0;}
+ case 141: /* orderby_opt ::= */
+ case 149: /* groupby_opt ::= */
+ case 231: /* exprlist ::= */
+ case 237: /* idxlist_opt ::= */
+{yygotominor.yy174 = 0;}
break;
case 116: /* selcollist ::= sclp expr as */
{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[-1].minor.yy450,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy174,yymsp[-1].minor.yy172,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0);
}
break;
case 117: /* selcollist ::= sclp STAR */
{
Expr *p = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0);
- yygotominor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy242, p, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy174, p, 0);
}
break;
case 118: /* selcollist ::= sclp nm DOT STAR */
@@ -82013,653 +79066,635 @@ static void yy_reduce(
Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242, pDot, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy174, pDot, 0);
}
break;
case 121: /* as ::= */
{yygotominor.yy0.n = 0;}
break;
case 122: /* from ::= */
-{yygotominor.yy419 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy419));}
+{yygotominor.yy373 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy373));}
break;
case 123: /* from ::= FROM seltablist */
{
- yygotominor.yy419 = yymsp[0].minor.yy419;
- sqlite3SrcListShiftJoinType(yygotominor.yy419);
+ yygotominor.yy373 = yymsp[0].minor.yy373;
+ sqlite3SrcListShiftJoinType(yygotominor.yy373);
}
break;
case 124: /* stl_prefix ::= seltablist joinop */
{
- yygotominor.yy419 = yymsp[-1].minor.yy419;
- if( yygotominor.yy419 && yygotominor.yy419->nSrc>0 ) yygotominor.yy419->a[yygotominor.yy419->nSrc-1].jointype = yymsp[0].minor.yy316;
+ yygotominor.yy373 = yymsp[-1].minor.yy373;
+ if( yygotominor.yy373 && yygotominor.yy373->nSrc>0 ) yygotominor.yy373->a[yygotominor.yy373->nSrc-1].jointype = yymsp[0].minor.yy46;
}
break;
case 125: /* stl_prefix ::= */
-{yygotominor.yy419 = 0;}
+{yygotominor.yy373 = 0;}
break;
- case 126: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ case 126: /* seltablist ::= stl_prefix nm dbnm as on_opt using_opt */
{
- yygotominor.yy419 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy419,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy450,yymsp[0].minor.yy352);
- sqlite3SrcListIndexedBy(pParse, yygotominor.yy419, &yymsp[-2].minor.yy0);
+ yygotominor.yy373 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy373,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy172,yymsp[0].minor.yy432);
}
break;
case 127: /* seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt */
{
- yygotominor.yy419 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy419,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy43,yymsp[-1].minor.yy450,yymsp[0].minor.yy352);
+ yygotominor.yy373 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy373,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy219,yymsp[-1].minor.yy172,yymsp[0].minor.yy432);
}
break;
case 129: /* seltablist_paren ::= seltablist */
{
- sqlite3SrcListShiftJoinType(yymsp[0].minor.yy419);
- yygotominor.yy43 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy419,0,0,0,0,0,0,0);
+ sqlite3SrcListShiftJoinType(yymsp[0].minor.yy373);
+ yygotominor.yy219 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy373,0,0,0,0,0,0,0);
}
break;
case 130: /* dbnm ::= */
- case 139: /* indexed_opt ::= */
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
break;
case 132: /* fullname ::= nm dbnm */
-{yygotominor.yy419 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
+{yygotominor.yy373 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
break;
case 133: /* joinop ::= COMMA|JOIN */
-{ yygotominor.yy316 = JT_INNER; }
+{ yygotominor.yy46 = JT_INNER; }
break;
case 134: /* joinop ::= JOIN_KW JOIN */
-{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
break;
case 135: /* joinop ::= JOIN_KW nm JOIN */
-{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
+{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
break;
case 136: /* joinop ::= JOIN_KW nm nm JOIN */
-{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
+{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
break;
case 137: /* on_opt ::= ON expr */
- case 148: /* sortitem ::= expr */
- case 155: /* having_opt ::= HAVING expr */
- case 162: /* where_opt ::= WHERE expr */
- case 177: /* expr ::= term */
- case 205: /* escape ::= ESCAPE expr */
- case 229: /* case_else ::= ELSE expr */
- case 231: /* case_operand ::= expr */
-{yygotominor.yy450 = yymsp[0].minor.yy450;}
+ case 145: /* sortitem ::= expr */
+ case 152: /* having_opt ::= HAVING expr */
+ case 159: /* where_opt ::= WHERE expr */
+ case 174: /* expr ::= term */
+ case 202: /* escape ::= ESCAPE expr */
+ case 226: /* case_else ::= ELSE expr */
+ case 228: /* case_operand ::= expr */
+{yygotominor.yy172 = yymsp[0].minor.yy172;}
break;
case 138: /* on_opt ::= */
- case 154: /* having_opt ::= */
- case 161: /* where_opt ::= */
- case 206: /* escape ::= */
- case 230: /* case_else ::= */
- case 232: /* case_operand ::= */
-{yygotominor.yy450 = 0;}
- break;
- case 141: /* indexed_opt ::= NOT INDEXED */
-{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
+ case 151: /* having_opt ::= */
+ case 158: /* where_opt ::= */
+ case 203: /* escape ::= */
+ case 227: /* case_else ::= */
+ case 229: /* case_operand ::= */
+{yygotominor.yy172 = 0;}
break;
- case 142: /* using_opt ::= USING LP inscollist RP */
- case 174: /* inscollist_opt ::= LP inscollist RP */
-{yygotominor.yy352 = yymsp[-1].minor.yy352;}
+ case 139: /* using_opt ::= USING LP inscollist RP */
+ case 171: /* inscollist_opt ::= LP inscollist RP */
+{yygotominor.yy432 = yymsp[-1].minor.yy432;}
break;
- case 143: /* using_opt ::= */
- case 173: /* inscollist_opt ::= */
-{yygotominor.yy352 = 0;}
+ case 140: /* using_opt ::= */
+ case 170: /* inscollist_opt ::= */
+{yygotominor.yy432 = 0;}
break;
- case 145: /* orderby_opt ::= ORDER BY sortlist */
- case 153: /* groupby_opt ::= GROUP BY nexprlist */
- case 233: /* exprlist ::= nexprlist */
-{yygotominor.yy242 = yymsp[0].minor.yy242;}
+ case 142: /* orderby_opt ::= ORDER BY sortlist */
+ case 150: /* groupby_opt ::= GROUP BY nexprlist */
+ case 230: /* exprlist ::= nexprlist */
+{yygotominor.yy174 = yymsp[0].minor.yy174;}
break;
- case 146: /* sortlist ::= sortlist COMMA sortitem sortorder */
+ case 143: /* sortlist ::= sortlist COMMA sortitem sortorder */
{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242,yymsp[-1].minor.yy450,0);
- if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy174,yymsp[-1].minor.yy172,0);
+ if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
}
break;
- case 147: /* sortlist ::= sortitem sortorder */
+ case 144: /* sortlist ::= sortitem sortorder */
{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy450,0);
- if( yygotominor.yy242 && yygotominor.yy242->a ) yygotominor.yy242->a[0].sortOrder = yymsp[0].minor.yy316;
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy172,0);
+ if( yygotominor.yy174 && yygotominor.yy174->a ) yygotominor.yy174->a[0].sortOrder = yymsp[0].minor.yy46;
}
break;
- case 149: /* sortorder ::= ASC */
- case 151: /* sortorder ::= */
-{yygotominor.yy316 = SQLITE_SO_ASC;}
+ case 146: /* sortorder ::= ASC */
+ case 148: /* sortorder ::= */
+{yygotominor.yy46 = SQLITE_SO_ASC;}
break;
- case 150: /* sortorder ::= DESC */
-{yygotominor.yy316 = SQLITE_SO_DESC;}
+ case 147: /* sortorder ::= DESC */
+{yygotominor.yy46 = SQLITE_SO_DESC;}
break;
- case 156: /* limit_opt ::= */
-{yygotominor.yy84.pLimit = 0; yygotominor.yy84.pOffset = 0;}
+ case 153: /* limit_opt ::= */
+{yygotominor.yy234.pLimit = 0; yygotominor.yy234.pOffset = 0;}
break;
- case 157: /* limit_opt ::= LIMIT expr */
-{yygotominor.yy84.pLimit = yymsp[0].minor.yy450; yygotominor.yy84.pOffset = 0;}
+ case 154: /* limit_opt ::= LIMIT expr */
+{yygotominor.yy234.pLimit = yymsp[0].minor.yy172; yygotominor.yy234.pOffset = 0;}
break;
- case 158: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yygotominor.yy84.pLimit = yymsp[-2].minor.yy450; yygotominor.yy84.pOffset = yymsp[0].minor.yy450;}
+ case 155: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yygotominor.yy234.pLimit = yymsp[-2].minor.yy172; yygotominor.yy234.pOffset = yymsp[0].minor.yy172;}
break;
- case 159: /* limit_opt ::= LIMIT expr COMMA expr */
-{yygotominor.yy84.pOffset = yymsp[-2].minor.yy450; yygotominor.yy84.pLimit = yymsp[0].minor.yy450;}
+ case 156: /* limit_opt ::= LIMIT expr COMMA expr */
+{yygotominor.yy234.pOffset = yymsp[-2].minor.yy172; yygotominor.yy234.pLimit = yymsp[0].minor.yy172;}
break;
- case 160: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
-{
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy419, &yymsp[-1].minor.yy0);
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy419,yymsp[0].minor.yy450);
-}
+ case 157: /* cmd ::= DELETE FROM fullname where_opt */
+{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy373,yymsp[0].minor.yy172);}
break;
- case 163: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
+ case 160: /* cmd ::= UPDATE orconf fullname SET setlist where_opt */
{
- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy419, &yymsp[-3].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy242,"set list");
- sqlite3Update(pParse,yymsp[-4].minor.yy419,yymsp[-1].minor.yy242,yymsp[0].minor.yy450,yymsp[-5].minor.yy316);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy174,"set list");
+ sqlite3Update(pParse,yymsp[-3].minor.yy373,yymsp[-1].minor.yy174,yymsp[0].minor.yy172,yymsp[-4].minor.yy46);
}
break;
- case 164: /* setlist ::= setlist COMMA nm EQ expr */
-{yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242,yymsp[0].minor.yy450,&yymsp[-2].minor.yy0);}
+ case 161: /* setlist ::= setlist COMMA nm EQ expr */
+{yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
break;
- case 165: /* setlist ::= nm EQ expr */
-{yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy450,&yymsp[-2].minor.yy0);}
+ case 162: /* setlist ::= nm EQ expr */
+{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
break;
- case 166: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */
-{sqlite3Insert(pParse, yymsp[-5].minor.yy419, yymsp[-1].minor.yy242, 0, yymsp[-4].minor.yy352, yymsp[-7].minor.yy316);}
+ case 163: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */
+{sqlite3Insert(pParse, yymsp[-5].minor.yy373, yymsp[-1].minor.yy174, 0, yymsp[-4].minor.yy432, yymsp[-7].minor.yy46);}
break;
- case 167: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
-{sqlite3Insert(pParse, yymsp[-2].minor.yy419, 0, yymsp[0].minor.yy43, yymsp[-1].minor.yy352, yymsp[-4].minor.yy316);}
+ case 164: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
+{sqlite3Insert(pParse, yymsp[-2].minor.yy373, 0, yymsp[0].minor.yy219, yymsp[-1].minor.yy432, yymsp[-4].minor.yy46);}
break;
- case 168: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
-{sqlite3Insert(pParse, yymsp[-3].minor.yy419, 0, 0, yymsp[-2].minor.yy352, yymsp[-5].minor.yy316);}
+ case 165: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
+{sqlite3Insert(pParse, yymsp[-3].minor.yy373, 0, 0, yymsp[-2].minor.yy432, yymsp[-5].minor.yy46);}
break;
- case 171: /* itemlist ::= itemlist COMMA expr */
- case 235: /* nexprlist ::= nexprlist COMMA expr */
-{yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[0].minor.yy450,0);}
+ case 168: /* itemlist ::= itemlist COMMA expr */
+ case 232: /* nexprlist ::= nexprlist COMMA expr */
+{yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy174,yymsp[0].minor.yy172,0);}
break;
- case 172: /* itemlist ::= expr */
- case 236: /* nexprlist ::= expr */
-{yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy450,0);}
+ case 169: /* itemlist ::= expr */
+ case 233: /* nexprlist ::= expr */
+{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,0);}
break;
- case 175: /* inscollist ::= inscollist COMMA nm */
-{yygotominor.yy352 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy352,&yymsp[0].minor.yy0);}
+ case 172: /* inscollist ::= inscollist COMMA nm */
+{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy432,&yymsp[0].minor.yy0);}
break;
- case 176: /* inscollist ::= nm */
-{yygotominor.yy352 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
+ case 173: /* inscollist ::= nm */
+{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
break;
- case 178: /* expr ::= LP expr RP */
-{yygotominor.yy450 = yymsp[-1].minor.yy450; sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+ case 175: /* expr ::= LP expr RP */
+{yygotominor.yy172 = yymsp[-1].minor.yy172; sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
break;
- case 179: /* term ::= NULL */
- case 184: /* term ::= INTEGER|FLOAT|BLOB */
- case 185: /* term ::= STRING */
-{yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
+ case 176: /* term ::= NULL */
+ case 181: /* term ::= INTEGER|FLOAT|BLOB */
+ case 182: /* term ::= STRING */
+{yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
break;
- case 180: /* expr ::= ID */
- case 181: /* expr ::= JOIN_KW */
-{yygotominor.yy450 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+ case 177: /* expr ::= ID */
+ case 178: /* expr ::= JOIN_KW */
+{yygotominor.yy172 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
break;
- case 182: /* expr ::= nm DOT nm */
+ case 179: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
}
break;
- case 183: /* expr ::= nm DOT nm DOT nm */
+ case 180: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
}
break;
- case 186: /* expr ::= REGISTER */
-{yygotominor.yy450 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+ case 183: /* expr ::= REGISTER */
+{yygotominor.yy172 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
break;
- case 187: /* expr ::= VARIABLE */
+ case 184: /* expr ::= VARIABLE */
{
Token *pToken = &yymsp[0].minor.yy0;
- Expr *pExpr = yygotominor.yy450 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
+ Expr *pExpr = yygotominor.yy172 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
sqlite3ExprAssignVarNumber(pParse, pExpr);
}
break;
- case 188: /* expr ::= expr COLLATE ids */
+ case 185: /* expr ::= expr COLLATE ids */
{
- yygotominor.yy450 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy450, &yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy172, &yymsp[0].minor.yy0);
}
break;
- case 189: /* expr ::= CAST LP expr AS typetoken RP */
+ case 186: /* expr ::= CAST LP expr AS typetoken RP */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy450, 0, &yymsp[-1].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy172, 0, &yymsp[-1].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
}
break;
- case 190: /* expr ::= ID LP distinct exprlist RP */
+ case 187: /* expr ::= ID LP distinct exprlist RP */
{
- if( yymsp[-1].minor.yy242 && yymsp[-1].minor.yy242->nExpr>SQLITE_MAX_FUNCTION_ARG ){
+ if( yymsp[-1].minor.yy174 && yymsp[-1].minor.yy174->nExpr>SQLITE_MAX_FUNCTION_ARG ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
}
- yygotominor.yy450 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
- if( yymsp[-2].minor.yy316 && yygotominor.yy450 ){
- yygotominor.yy450->flags |= EP_Distinct;
+ yygotominor.yy172 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy174, &yymsp[-4].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+ if( yymsp[-2].minor.yy46 && yygotominor.yy172 ){
+ yygotominor.yy172->flags |= EP_Distinct;
}
}
break;
- case 191: /* expr ::= ID LP STAR RP */
+ case 188: /* expr ::= ID LP STAR RP */
{
- yygotominor.yy450 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
break;
- case 192: /* term ::= CTIME_KW */
+ case 189: /* term ::= CTIME_KW */
{
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
** treated as functions that return constants */
- yygotominor.yy450 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->op = TK_CONST_FUNC;
- yygotominor.yy450->span = yymsp[0].minor.yy0;
+ yygotominor.yy172 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->op = TK_CONST_FUNC;
+ yygotominor.yy172->span = yymsp[0].minor.yy0;
}
}
break;
- case 193: /* expr ::= expr AND expr */
- case 194: /* expr ::= expr OR expr */
- case 195: /* expr ::= expr LT|GT|GE|LE expr */
- case 196: /* expr ::= expr EQ|NE expr */
- case 197: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- case 198: /* expr ::= expr PLUS|MINUS expr */
- case 199: /* expr ::= expr STAR|SLASH|REM expr */
- case 200: /* expr ::= expr CONCAT expr */
-{yygotominor.yy450 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy450,yymsp[0].minor.yy450,0);}
+ case 190: /* expr ::= expr AND expr */
+ case 191: /* expr ::= expr OR expr */
+ case 192: /* expr ::= expr LT|GT|GE|LE expr */
+ case 193: /* expr ::= expr EQ|NE expr */
+ case 194: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ case 195: /* expr ::= expr PLUS|MINUS expr */
+ case 196: /* expr ::= expr STAR|SLASH|REM expr */
+ case 197: /* expr ::= expr CONCAT expr */
+{yygotominor.yy172 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy172,yymsp[0].minor.yy172,0);}
break;
- case 201: /* likeop ::= LIKE_KW */
- case 203: /* likeop ::= MATCH */
-{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 0;}
+ case 198: /* likeop ::= LIKE_KW */
+ case 200: /* likeop ::= MATCH */
+{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 0;}
break;
- case 202: /* likeop ::= NOT LIKE_KW */
- case 204: /* likeop ::= NOT MATCH */
-{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 1;}
+ case 199: /* likeop ::= NOT LIKE_KW */
+ case 201: /* likeop ::= NOT MATCH */
+{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 1;}
break;
- case 207: /* expr ::= expr likeop expr escape */
+ case 204: /* expr ::= expr likeop expr escape */
{
ExprList *pList;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy450, 0);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy450, 0);
- if( yymsp[0].minor.yy450 ){
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy450, 0);
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy172, 0);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy172, 0);
+ if( yymsp[0].minor.yy172 ){
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy172, 0);
}
- yygotominor.yy450 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy86.eOperator);
- if( yymsp[-2].minor.yy86.not ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy450->span, &yymsp[-1].minor.yy450->span);
- if( yygotominor.yy450 ) yygotominor.yy450->flags |= EP_InfixFunc;
+ yygotominor.yy172 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy72.eOperator);
+ if( yymsp[-2].minor.yy72.not ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy172->span, &yymsp[-1].minor.yy172->span);
+ if( yygotominor.yy172 ) yygotominor.yy172->flags |= EP_InfixFunc;
}
break;
- case 208: /* expr ::= expr ISNULL|NOTNULL */
+ case 205: /* expr ::= expr ISNULL|NOTNULL */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy450->span,&yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy172->span,&yymsp[0].minor.yy0);
}
break;
- case 209: /* expr ::= expr IS NULL */
+ case 206: /* expr ::= expr IS NULL */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0);
}
break;
- case 210: /* expr ::= expr NOT NULL */
+ case 207: /* expr ::= expr NOT NULL */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0);
}
break;
- case 211: /* expr ::= expr IS NOT NULL */
+ case 208: /* expr ::= expr IS NOT NULL */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,&yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,&yymsp[0].minor.yy0);
}
break;
- case 212: /* expr ::= NOT expr */
- case 213: /* expr ::= BITNOT expr */
+ case 209: /* expr ::= NOT expr */
+ case 210: /* expr ::= BITNOT expr */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+ yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
}
break;
- case 214: /* expr ::= MINUS expr */
+ case 211: /* expr ::= MINUS expr */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
}
break;
- case 215: /* expr ::= PLUS expr */
+ case 212: /* expr ::= PLUS expr */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
}
break;
- case 218: /* expr ::= expr between_op expr AND expr */
+ case 215: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy450, 0);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy450, 0);
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy450, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pList = pList;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy172, 0);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy172, 0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy172, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy450->span);
+ if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy172->span);
}
break;
- case 221: /* expr ::= expr in_op LP exprlist RP */
+ case 218: /* expr ::= expr in_op LP exprlist RP */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy450, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pList = yymsp[-1].minor.yy242;
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy172, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pList = yymsp[-1].minor.yy174;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy174);
}
- if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy0);
+ if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0);
}
break;
- case 222: /* expr ::= LP select RP */
+ case 219: /* expr ::= LP select RP */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pSelect = yymsp[-1].minor.yy43;
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pSelect = yymsp[-1].minor.yy219;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
}
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
}
break;
- case 223: /* expr ::= expr in_op LP select RP */
+ case 220: /* expr ::= expr in_op LP select RP */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy450, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pSelect = yymsp[-1].minor.yy43;
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy172, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pSelect = yymsp[-1].minor.yy219;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
}
- if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy0);
+ if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0);
}
break;
- case 224: /* expr ::= expr in_op nm dbnm */
+ case 221: /* expr ::= expr in_op nm dbnm */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy450, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy172, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
}else{
sqlite3SrcListDelete(pParse->db, pSrc);
}
- if( yymsp[-2].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
+ if( yymsp[-2].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
}
break;
- case 225: /* expr ::= EXISTS LP select RP */
+ case 222: /* expr ::= EXISTS LP select RP */
{
- Expr *p = yygotominor.yy450 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+ Expr *p = yygotominor.yy172 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
if( p ){
- p->pSelect = yymsp[-1].minor.yy43;
+ p->pSelect = yymsp[-1].minor.yy219;
sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
}
}
break;
- case 226: /* expr ::= CASE case_operand case_exprlist case_else END */
+ case 223: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pList = yymsp[-2].minor.yy242;
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pList = yymsp[-2].minor.yy174;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy242);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy174);
}
- sqlite3ExprSpan(yygotominor.yy450, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy172, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 227: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ case 224: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[-2].minor.yy450, 0);
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yygotominor.yy242, yymsp[0].minor.yy450, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174, yymsp[-2].minor.yy172, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yygotominor.yy174, yymsp[0].minor.yy172, 0);
}
break;
- case 228: /* case_exprlist ::= WHEN expr THEN expr */
+ case 225: /* case_exprlist ::= WHEN expr THEN expr */
{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy450, 0);
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yygotominor.yy242, yymsp[0].minor.yy450, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy172, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yygotominor.yy174, yymsp[0].minor.yy172, 0);
}
break;
- case 237: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
+ case 234: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
{
sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
- sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy242, yymsp[-9].minor.yy316,
- &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy316);
+ sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy174, yymsp[-9].minor.yy46,
+ &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46);
}
break;
- case 238: /* uniqueflag ::= UNIQUE */
- case 285: /* raisetype ::= ABORT */
-{yygotominor.yy316 = OE_Abort;}
+ case 235: /* uniqueflag ::= UNIQUE */
+ case 283: /* raisetype ::= ABORT */
+{yygotominor.yy46 = OE_Abort;}
break;
- case 239: /* uniqueflag ::= */
-{yygotominor.yy316 = OE_None;}
+ case 236: /* uniqueflag ::= */
+{yygotominor.yy46 = OE_None;}
break;
- case 242: /* idxlist ::= idxlist COMMA nm collate sortorder */
+ case 239: /* idxlist ::= idxlist COMMA idxitem collate sortorder */
{
Expr *p = 0;
if( yymsp[-1].minor.yy0.n>0 ){
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy0);
}
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, p, &yymsp[-2].minor.yy0);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy242, "index");
- if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174, p, &yymsp[-2].minor.yy0);
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index");
+ if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
}
break;
- case 243: /* idxlist ::= nm collate sortorder */
+ case 240: /* idxlist ::= idxitem collate sortorder */
{
Expr *p = 0;
if( yymsp[-1].minor.yy0.n>0 ){
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy0);
}
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy242, "index");
- if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0);
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index");
+ if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
}
break;
- case 244: /* collate ::= */
+ case 242: /* collate ::= */
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
break;
- case 246: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy419, yymsp[-1].minor.yy316);}
+ case 244: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy373, yymsp[-1].minor.yy46);}
break;
- case 247: /* cmd ::= VACUUM */
- case 248: /* cmd ::= VACUUM nm */
+ case 245: /* cmd ::= VACUUM */
+ case 246: /* cmd ::= VACUUM nm */
{sqlite3Vacuum(pParse);}
break;
- case 249: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
- case 250: /* cmd ::= PRAGMA nm dbnm EQ ON */
- case 251: /* cmd ::= PRAGMA nm dbnm EQ DELETE */
+ case 247: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 248: /* cmd ::= PRAGMA nm dbnm EQ ON */
+ case 249: /* cmd ::= PRAGMA nm dbnm EQ DELETE */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 252: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 250: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{
sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);
}
break;
- case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 251: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 254: /* cmd ::= PRAGMA nm dbnm */
+ case 252: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 262: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
+ case 260: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy75, &all);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy243, &all);
}
break;
- case 263: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy316, yymsp[-4].minor.yy354.a, yymsp[-4].minor.yy354.b, yymsp[-2].minor.yy419, yymsp[0].minor.yy450, yymsp[-10].minor.yy316, yymsp[-8].minor.yy316);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[0].minor.yy172, yymsp[-10].minor.yy46, yymsp[-8].minor.yy46);
yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
}
break;
- case 264: /* trigger_time ::= BEFORE */
- case 267: /* trigger_time ::= */
-{ yygotominor.yy316 = TK_BEFORE; }
+ case 262: /* trigger_time ::= BEFORE */
+ case 265: /* trigger_time ::= */
+{ yygotominor.yy46 = TK_BEFORE; }
break;
- case 265: /* trigger_time ::= AFTER */
-{ yygotominor.yy316 = TK_AFTER; }
+ case 263: /* trigger_time ::= AFTER */
+{ yygotominor.yy46 = TK_AFTER; }
break;
- case 266: /* trigger_time ::= INSTEAD OF */
-{ yygotominor.yy316 = TK_INSTEAD;}
+ case 264: /* trigger_time ::= INSTEAD OF */
+{ yygotominor.yy46 = TK_INSTEAD;}
break;
- case 268: /* trigger_event ::= DELETE|INSERT */
- case 269: /* trigger_event ::= UPDATE */
-{yygotominor.yy354.a = yymsp[0].major; yygotominor.yy354.b = 0;}
+ case 266: /* trigger_event ::= DELETE|INSERT */
+ case 267: /* trigger_event ::= UPDATE */
+{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;}
break;
- case 270: /* trigger_event ::= UPDATE OF inscollist */
-{yygotominor.yy354.a = TK_UPDATE; yygotominor.yy354.b = yymsp[0].minor.yy352;}
+ case 268: /* trigger_event ::= UPDATE OF inscollist */
+{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;}
break;
- case 273: /* when_clause ::= */
- case 290: /* key_opt ::= */
-{ yygotominor.yy450 = 0; }
+ case 271: /* when_clause ::= */
+ case 288: /* key_opt ::= */
+{ yygotominor.yy172 = 0; }
break;
- case 274: /* when_clause ::= WHEN expr */
- case 291: /* key_opt ::= KEY expr */
-{ yygotominor.yy450 = yymsp[0].minor.yy450; }
+ case 272: /* when_clause ::= WHEN expr */
+ case 289: /* key_opt ::= KEY expr */
+{ yygotominor.yy172 = yymsp[0].minor.yy172; }
break;
- case 275: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 273: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
-/*
- if( yymsp[-2].minor.yy75 ){
- yymsp[-2].minor.yy75->pLast->pNext = yymsp[-1].minor.yy75;
+ if( yymsp[-2].minor.yy243 ){
+ yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243;
}else{
- yymsp[-2].minor.yy75 = yymsp[-1].minor.yy75;
+ yymsp[-2].minor.yy243 = yymsp[-1].minor.yy243;
}
-*/
- assert( yymsp[-2].minor.yy75!=0 );
- yymsp[-2].minor.yy75->pLast->pNext = yymsp[-1].minor.yy75;
- yymsp[-2].minor.yy75->pLast = yymsp[-1].minor.yy75;
- yygotominor.yy75 = yymsp[-2].minor.yy75;
+ yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243;
+ yygotominor.yy243 = yymsp[-2].minor.yy243;
}
break;
- case 276: /* trigger_cmd_list ::= trigger_cmd SEMI */
-{
- /* if( yymsp[-1].minor.yy75 ) */
- assert( yymsp[-1].minor.yy75!=0 );
- yymsp[-1].minor.yy75->pLast = yymsp[-1].minor.yy75;
- yygotominor.yy75 = yymsp[-1].minor.yy75;
-}
+ case 274: /* trigger_cmd_list ::= */
+{ yygotominor.yy243 = 0; }
break;
- case 277: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
-{ yygotominor.yy75 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy242, yymsp[0].minor.yy450, yymsp[-4].minor.yy316); }
+ case 275: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
+{ yygotominor.yy243 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); }
break;
- case 278: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
-{yygotominor.yy75 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy352, yymsp[-1].minor.yy242, 0, yymsp[-7].minor.yy316);}
+ case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
+{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);}
break;
- case 279: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
-{yygotominor.yy75 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy352, 0, yymsp[0].minor.yy43, yymsp[-4].minor.yy316);}
+ case 277: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
+{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);}
break;
- case 280: /* trigger_cmd ::= DELETE FROM nm where_opt */
-{yygotominor.yy75 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy450);}
+ case 278: /* trigger_cmd ::= DELETE FROM nm where_opt */
+{yygotominor.yy243 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy172);}
break;
- case 281: /* trigger_cmd ::= select */
-{yygotominor.yy75 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy43); }
+ case 279: /* trigger_cmd ::= select */
+{yygotominor.yy243 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy219); }
break;
- case 282: /* expr ::= RAISE LP IGNORE RP */
+ case 280: /* expr ::= RAISE LP IGNORE RP */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->iColumn = OE_Ignore;
- sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->iColumn = OE_Ignore;
+ sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
}
}
break;
- case 283: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 281: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
- if( yygotominor.yy450 ) {
- yygotominor.yy450->iColumn = yymsp[-3].minor.yy316;
- sqlite3ExprSpan(yygotominor.yy450, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ if( yygotominor.yy172 ) {
+ yygotominor.yy172->iColumn = yymsp[-3].minor.yy46;
+ sqlite3ExprSpan(yygotominor.yy172, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
}
}
break;
- case 284: /* raisetype ::= ROLLBACK */
-{yygotominor.yy316 = OE_Rollback;}
+ case 282: /* raisetype ::= ROLLBACK */
+{yygotominor.yy46 = OE_Rollback;}
break;
- case 286: /* raisetype ::= FAIL */
-{yygotominor.yy316 = OE_Fail;}
+ case 284: /* raisetype ::= FAIL */
+{yygotominor.yy46 = OE_Fail;}
break;
- case 287: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 285: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy419,yymsp[-1].minor.yy316);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46);
}
break;
- case 288: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 286: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, yymsp[0].minor.yy450);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy172);
}
break;
- case 289: /* cmd ::= DETACH database_kw_opt expr */
+ case 287: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy450);
+ sqlite3Detach(pParse, yymsp[0].minor.yy172);
}
break;
- case 294: /* cmd ::= REINDEX */
+ case 292: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 295: /* cmd ::= REINDEX nm dbnm */
+ case 293: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 296: /* cmd ::= ANALYZE */
+ case 294: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 297: /* cmd ::= ANALYZE nm dbnm */
+ case 295: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 298: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 296: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy419,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy0);
}
break;
- case 299: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+ case 297: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
break;
- case 300: /* add_column_fullname ::= fullname */
+ case 298: /* add_column_fullname ::= fullname */
{
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy419);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373);
}
break;
- case 303: /* cmd ::= create_vtab */
+ case 301: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 304: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 302: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 305: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */
+ case 303: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */
{
sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 308: /* vtabarg ::= */
+ case 306: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 310: /* vtabargtoken ::= ANY */
- case 311: /* vtabargtoken ::= lp anylist RP */
- case 312: /* lp ::= LP */
- case 314: /* anylist ::= anylist ANY */
+ case 308: /* vtabargtoken ::= ANY */
+ case 309: /* vtabargtoken ::= lp anylist RP */
+ case 310: /* lp ::= LP */
+ case 312: /* anylist ::= anylist ANY */
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
};
@@ -82982,89 +80017,89 @@ const unsigned char ebcdicToAscii[] = {
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
-/* Hash score: 167 */
+/* Hash score: 165 */
static int keywordCode(const char *z, int n){
- /* zText[] encodes 783 bytes of keywords in 528 bytes */
- static const char zText[528] =
- "REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECTABLE"
- "FTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTSCONSTRAINT"
- "ERSECTRIGGEREFERENCESUNIQUERYATTACHAVINGROUPDATEMPORARYBEGINNER"
- "ENAMEBETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATE"
- "DETACHIMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMIT"
- "WHENWHEREPLACEAFTERESTRICTANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT"
- "CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROM"
- "FULLGLOBYIFINTOFFSETISNULLORDERIGHTOUTEROLLBACKROWUNIONUSINGVACUUM"
+ /* zText[] encodes 775 bytes of keywords in 526 bytes */
+ static const char zText[526] =
+ "BEFOREIGNOREGEXPLAINSTEADDESCAPEACHECKEYCONSTRAINTERSECTABLEFT"
+ "HENDATABASELECTRANSACTIONATURALTERAISELSEXCEPTRIGGEREFERENCES"
+ "UNIQUERYATTACHAVINGROUPDATEMPORARYBEGINNEREINDEXCLUSIVEXISTSBETWEEN"
+ "OTNULLIKECASCADEFERRABLECASECOLLATECREATECURRENT_DATEDELETEDETACH"
+ "IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN"
+ "WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICT"
+ "CROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOB"
+ "YIFINTOFFSETISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUM"
"VIEWINITIALLY";
static const unsigned char aHash[127] = {
- 65, 94, 110, 63, 0, 44, 0, 0, 71, 0, 66, 0, 0,
- 104, 12, 67, 15, 0, 108, 74, 105, 101, 0, 19, 0, 0,
- 114, 0, 112, 78, 0, 22, 82, 0, 9, 0, 0, 59, 60,
- 0, 58, 6, 0, 39, 79, 91, 0, 111, 90, 0, 0, 45,
- 0, 92, 24, 0, 17, 0, 115, 40, 23, 0, 5, 99, 25,
- 85, 0, 0, 117, 95, 50, 116, 47, 7, 42, 0, 80, 0,
- 89, 26, 0, 88, 0, 0, 0, 84, 81, 86, 77, 98, 14,
- 34, 97, 0, 70, 0, 18, 76, 100, 31, 0, 113, 69, 106,
- 52, 46, 73, 0, 0, 83, 102, 0, 109, 0, 35, 0, 0,
- 28, 0, 75, 48, 53, 0, 20, 51, 0, 43,
+ 63, 92, 109, 61, 0, 38, 0, 0, 69, 0, 64, 0, 0,
+ 102, 4, 65, 7, 0, 108, 72, 103, 99, 0, 22, 0, 0,
+ 113, 0, 111, 106, 0, 18, 80, 0, 1, 0, 0, 56, 57,
+ 0, 55, 11, 0, 33, 77, 89, 0, 110, 88, 0, 0, 45,
+ 0, 90, 54, 0, 20, 0, 114, 34, 19, 0, 10, 97, 28,
+ 83, 0, 0, 116, 93, 47, 115, 41, 12, 44, 0, 78, 0,
+ 87, 29, 0, 86, 0, 0, 0, 82, 79, 84, 75, 96, 6,
+ 14, 95, 0, 68, 0, 21, 76, 98, 27, 0, 112, 67, 104,
+ 49, 40, 71, 0, 0, 81, 100, 0, 107, 0, 15, 0, 0,
+ 24, 0, 73, 42, 50, 0, 16, 48, 0, 37,
};
- static const unsigned char aNext[117] = {
- 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 3, 38, 0, 32, 21, 0, 0, 0, 0, 29, 0,
- 0, 37, 0, 0, 0, 1, 55, 0, 0, 56, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 30, 0,
- 16, 33, 10, 0, 0, 0, 0, 0, 0, 0, 11, 61, 68,
- 0, 8, 0, 93, 87, 0, 96, 0, 49, 0, 0, 64, 0,
- 41, 103, 0, 27, 107, 36, 62, 72, 0, 0, 57, 0, 0,
+ static const unsigned char aNext[116] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0,
+ 17, 0, 0, 0, 36, 39, 0, 0, 25, 0, 0, 31, 0,
+ 0, 0, 43, 52, 0, 0, 0, 53, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 51, 0, 0, 0, 0, 26, 0, 8, 46,
+ 2, 0, 0, 0, 0, 0, 0, 0, 3, 58, 66, 0, 13,
+ 0, 91, 85, 0, 94, 0, 74, 0, 0, 62, 0, 35, 101,
+ 0, 0, 105, 23, 30, 60, 70, 0, 0, 59, 0, 0,
};
- static const unsigned char aLen[117] = {
- 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
- 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
- 11, 2, 7, 5, 5, 9, 6, 10, 9, 7, 10, 6, 5,
- 6, 6, 5, 6, 4, 9, 2, 5, 5, 6, 7, 7, 3,
- 4, 4, 7, 3, 6, 4, 7, 6, 12, 6, 9, 4, 6,
- 5, 4, 7, 6, 5, 6, 7, 5, 4, 5, 7, 5, 8,
- 3, 7, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7,
- 8, 8, 2, 4, 4, 4, 4, 4, 2, 2, 4, 6, 2,
- 3, 6, 5, 5, 5, 8, 3, 5, 5, 6, 4, 9, 3,
+ static const unsigned char aLen[116] = {
+ 6, 7, 3, 6, 6, 7, 7, 3, 4, 6, 4, 5, 3,
+ 10, 9, 5, 4, 4, 3, 8, 2, 6, 11, 2, 7, 5,
+ 5, 4, 6, 7, 10, 6, 5, 6, 6, 5, 6, 4, 9,
+ 2, 5, 5, 7, 5, 9, 6, 7, 7, 3, 4, 4, 7,
+ 3, 10, 4, 7, 6, 12, 6, 6, 9, 4, 6, 5, 4,
+ 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7,
+ 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8,
+ 2, 4, 4, 4, 4, 4, 2, 2, 4, 6, 2, 3, 6,
+ 5, 8, 5, 5, 8, 3, 5, 5, 6, 4, 9, 3,
};
- static const unsigned short int aOffset[117] = {
- 0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
- 36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
- 86, 95, 96, 101, 105, 109, 117, 123, 130, 138, 144, 154, 157,
- 162, 167, 172, 175, 179, 179, 183, 188, 191, 195, 201, 207, 207,
- 210, 213, 217, 218, 222, 228, 232, 239, 245, 257, 263, 272, 274,
- 280, 285, 287, 294, 299, 304, 310, 316, 321, 325, 328, 335, 339,
- 347, 349, 356, 358, 360, 369, 373, 379, 385, 393, 398, 398, 414,
- 421, 428, 429, 436, 440, 444, 448, 452, 455, 457, 459, 462, 462,
- 465, 468, 474, 478, 483, 487, 495, 498, 503, 508, 514, 518, 523,
+ static const unsigned short int aOffset[116] = {
+ 0, 2, 2, 6, 10, 13, 18, 23, 25, 26, 31, 33, 37,
+ 40, 47, 55, 58, 61, 63, 65, 70, 71, 76, 85, 86, 91,
+ 95, 99, 102, 107, 113, 123, 126, 131, 136, 141, 144, 148, 148,
+ 152, 157, 160, 164, 166, 169, 177, 183, 189, 189, 192, 195, 199,
+ 200, 204, 214, 218, 225, 231, 243, 249, 255, 264, 266, 272, 277,
+ 279, 286, 291, 296, 302, 308, 313, 317, 320, 326, 330, 337, 339,
+ 346, 348, 350, 359, 363, 369, 375, 383, 388, 388, 404, 411, 418,
+ 419, 426, 430, 434, 438, 442, 445, 447, 449, 452, 452, 455, 458,
+ 464, 468, 476, 480, 485, 493, 496, 501, 506, 512, 516, 521,
};
- static const unsigned char aCode[117] = {
- TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
- TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
- TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
- TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
- TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
- TK_EXCEPT, TK_TRANSACTION,TK_ON, TK_JOIN_KW, TK_ALTER,
- TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_CONSTRAINT, TK_INTERSECT,
- TK_TRIGGER, TK_REFERENCES, TK_UNIQUE, TK_QUERY, TK_ATTACH,
- TK_HAVING, TK_GROUP, TK_UPDATE, TK_TEMP, TK_TEMP,
- TK_OR, TK_BEGIN, TK_JOIN_KW, TK_RENAME, TK_BETWEEN,
- TK_NOTNULL, TK_NOT, TK_NULL, TK_LIKE_KW, TK_CASCADE,
- TK_ASC, TK_DELETE, TK_CASE, TK_COLLATE, TK_CREATE,
- TK_CTIME_KW, TK_DETACH, TK_IMMEDIATE, TK_JOIN, TK_INSERT,
- TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT,
- TK_VALUES, TK_VIRTUAL, TK_LIMIT, TK_WHEN, TK_WHERE,
- TK_REPLACE, TK_AFTER, TK_RESTRICT, TK_AND, TK_DEFAULT,
- TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, TK_COLUMNKW,
- TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW,
- TK_PRIMARY, TK_DEFERRED, TK_DISTINCT, TK_IS, TK_DROP,
- TK_FAIL, TK_FROM, TK_JOIN_KW, TK_LIKE_KW, TK_BY,
- TK_IF, TK_INTO, TK_OFFSET, TK_OF, TK_SET,
- TK_ISNULL, TK_ORDER, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK,
- TK_ROW, TK_UNION, TK_USING, TK_VACUUM, TK_VIEW,
- TK_INITIALLY, TK_ALL,
+ static const unsigned char aCode[116] = {
+ TK_BEFORE, TK_FOREIGN, TK_FOR, TK_IGNORE, TK_LIKE_KW,
+ TK_EXPLAIN, TK_INSTEAD, TK_ADD, TK_DESC, TK_ESCAPE,
+ TK_EACH, TK_CHECK, TK_KEY, TK_CONSTRAINT, TK_INTERSECT,
+ TK_TABLE, TK_JOIN_KW, TK_THEN, TK_END, TK_DATABASE,
+ TK_AS, TK_SELECT, TK_TRANSACTION,TK_ON, TK_JOIN_KW,
+ TK_ALTER, TK_RAISE, TK_ELSE, TK_EXCEPT, TK_TRIGGER,
+ TK_REFERENCES, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING,
+ TK_GROUP, TK_UPDATE, TK_TEMP, TK_TEMP, TK_OR,
+ TK_BEGIN, TK_JOIN_KW, TK_REINDEX, TK_INDEX, TK_EXCLUSIVE,
+ TK_EXISTS, TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NULL,
+ TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DEFERRABLE, TK_CASE,
+ TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DELETE, TK_DETACH,
+ TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN,
+ TK_ANALYZE, TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL,
+ TK_LIMIT, TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER,
+ TK_REPLACE, TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO,
+ TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT,
+ TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED,
+ TK_DISTINCT, TK_IS, TK_DROP, TK_FAIL, TK_FROM,
+ TK_JOIN_KW, TK_LIKE_KW, TK_BY, TK_IF, TK_INTO,
+ TK_OFFSET, TK_OF, TK_SET, TK_ISNULL, TK_ORDER,
+ TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW,
+ TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY,
+ TK_ALL,
};
int h, i;
if( n<2 ) return TK_ID;
@@ -83149,7 +80184,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
case '-': {
if( z[1]=='-' ){
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
- *tokenType = TK_SPACE;
+ *tokenType = TK_COMMENT;
return i;
}
*tokenType = TK_MINUS;
@@ -83182,7 +80217,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
- *tokenType = TK_SPACE;
+ *tokenType = TK_COMMENT;
return i;
}
case '%': {
@@ -83263,12 +80298,9 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
}
}
- if( c=='\'' ){
+ if( c ){
*tokenType = TK_STRING;
return i+1;
- }else if( c!=0 ){
- *tokenType = TK_ID;
- return i+1;
}else{
*tokenType = TK_ILLEGAL;
return i;
@@ -83438,7 +80470,8 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
break;
}
switch( tokenType ){
- case TK_SPACE: {
+ case TK_SPACE:
+ case TK_COMMENT: {
if( db->u1.isInterrupted ){
pParse->rc = SQLITE_INTERRUPT;
sqlite3SetString(pzErrMsg, db, "interrupt");
@@ -83521,12 +80554,6 @@ abort_parse:
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->apVarExpr);
- sqlite3DbFree(db, pParse->aAlias);
- while( pParse->pZombieTab ){
- Table *p = pParse->pZombieTab;
- pParse->pZombieTab = p->pNextZombie;
- sqlite3DeleteTable(p);
- }
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}
@@ -83897,39 +80924,6 @@ SQLITE_PRIVATE int sqlite3RtreeInit(sqlite3 *db);
/************** End of rtree.h ***********************************************/
/************** Continuing where we left off in main.c ***********************/
#endif
-#ifdef SQLITE_ENABLE_ICU
-/************** Include sqliteicu.h in the middle of main.c ******************/
-/************** Begin file sqliteicu.h ***************************************/
-/*
-** 2008 May 26
-**
-** 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 header file is used by programs that want to link against the
-** ICU extension. All it does is declare the sqlite3IcuInit() interface.
-*/
-
-#if 0
-extern "C" {
-#endif /* __cplusplus */
-
-SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db);
-
-#if 0
-} /* extern "C" */
-#endif /* __cplusplus */
-
-
-/************** End of sqliteicu.h *******************************************/
-/************** Continuing where we left off in main.c ***********************/
-#endif
/*
** The version of the library
@@ -83962,135 +80956,68 @@ SQLITE_API char *sqlite3_temp_directory = 0;
** Initialize SQLite.
**
** This routine must be called to initialize the memory allocation,
-** VFS, and mutex subsystems prior to doing any serious work with
+** VFS, and mutex subsystesms prior to doing any serious work with
** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
** sqlite3_open().
**
** This routine is a no-op except on its very first call for the process,
** or for the first call after a call to sqlite3_shutdown.
-**
-** The first thread to call this routine runs the initialization to
-** completion. If subsequent threads call this routine before the first
-** thread has finished the initialization process, then the subsequent
-** threads must block until the first thread finishes with the initialization.
-**
-** The first thread might call this routine recursively. Recursive
-** calls to this routine should not block, of course. Otherwise the
-** initialization process would never complete.
-**
-** Let X be the first thread to enter this routine. Let Y be some other
-** thread. Then while the initial invocation of this routine by X is
-** incomplete, it is required that:
-**
-** * Calls to this routine from Y must block until the outer-most
-** call by X completes.
-**
-** * Recursive calls to this routine from thread X return immediately
-** without blocking.
*/
SQLITE_API int sqlite3_initialize(void){
- sqlite3_mutex *pMaster; /* The main static mutex */
- int rc; /* Result code */
-
-#ifdef SQLITE_OMIT_WSD
- rc = sqlite3_wsd_init(4096, 24);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-#endif
+ static int inProgress = 0;
+ int rc;
- /* If SQLite is already completely initialized, then this call
- ** to sqlite3_initialize() should be a no-op. But the initialization
- ** must be complete. So isInit must not be set until the very end
- ** of this routine.
- */
- if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
+ /* If SQLite is already initialized, this call is a no-op. */
+ if( sqlite3Config.isInit ) return SQLITE_OK;
- /* Make sure the mutex subsystem is initialized. If unable to
- ** initialize the mutex subsystem, return early with the error.
- ** If the system is so sick that we are unable to allocate a mutex,
- ** there is not much SQLite is going to be able to do.
- **
- ** The mutex subsystem must take care of serializing its own
- ** initialization.
- */
+ /* Make sure the mutex system is initialized. */
rc = sqlite3MutexInit();
- if( rc ) return rc;
- /* Initialize the malloc() system and the recursive pInitMutex mutex.
- ** This operation is protected by the STATIC_MASTER mutex. Note that
- ** MutexAlloc() is called for a static mutex prior to initializing the
- ** malloc subsystem - this implies that the allocation of a static
- ** mutex must not require support from the malloc subsystem.
- */
- pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
- sqlite3_mutex_enter(pMaster);
- if( !sqlite3GlobalConfig.isMallocInit ){
- rc = sqlite3MallocInit();
- }
- if( rc==SQLITE_OK ){
- sqlite3GlobalConfig.isMallocInit = 1;
- if( !sqlite3GlobalConfig.pInitMutex ){
- sqlite3GlobalConfig.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
- if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){
- rc = SQLITE_NOMEM;
- }
- }
- }
if( rc==SQLITE_OK ){
- sqlite3GlobalConfig.nRefInitMutex++;
- }
- sqlite3_mutex_leave(pMaster);
-
- /* If unable to initialize the malloc subsystem, then return early.
- ** There is little hope of getting SQLite to run if the malloc
- ** subsystem cannot be initialized.
- */
- if( rc!=SQLITE_OK ){
- return rc;
- }
- /* Do the rest of the initialization under the recursive mutex so
- ** that we will be able to handle recursive calls into
- ** sqlite3_initialize(). The recursive calls normally come through
- ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
- ** recursive calls might also be possible.
- */
- sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex);
- if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){
- FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
- sqlite3GlobalConfig.inProgress = 1;
- memset(pHash, 0, sizeof(sqlite3GlobalFunctions));
- sqlite3RegisterGlobalFunctions();
- rc = sqlite3_os_init();
+ /* Initialize the malloc() system and the recursive pInitMutex mutex.
+ ** This operation is protected by the STATIC_MASTER mutex.
+ */
+ sqlite3_mutex *pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ sqlite3_mutex_enter(pMaster);
+ if( !sqlite3Config.isMallocInit ){
+ rc = sqlite3MallocInit();
+ }
if( rc==SQLITE_OK ){
- rc = sqlite3PcacheInitialize();
- sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
- sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
+ sqlite3Config.isMallocInit = 1;
+ if( !sqlite3Config.pInitMutex ){
+ sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
+ if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+ }
+ sqlite3_mutex_leave(pMaster);
+ if( rc!=SQLITE_OK ){
+ return rc;
}
- sqlite3GlobalConfig.inProgress = 0;
- sqlite3GlobalConfig.isInit = (rc==SQLITE_OK ? 1 : 0);
- }
- sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);
- /* Go back under the static mutex and clean up the recursive
- ** mutex to prevent a resource leak.
- */
- sqlite3_mutex_enter(pMaster);
- sqlite3GlobalConfig.nRefInitMutex--;
- if( sqlite3GlobalConfig.nRefInitMutex<=0 ){
- assert( sqlite3GlobalConfig.nRefInitMutex==0 );
- sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
- sqlite3GlobalConfig.pInitMutex = 0;
+ /* Enter the recursive pInitMutex mutex. After doing so, if the
+ ** sqlite3Config.isInit flag is true, then some other thread has
+ ** finished doing the initialization. If the inProgress flag is
+ ** true, then this function is being called recursively from within
+ ** the sqlite3_os_init() call below. In either case, exit early.
+ */
+ sqlite3_mutex_enter(sqlite3Config.pInitMutex);
+ if( sqlite3Config.isInit || inProgress ){
+ sqlite3_mutex_leave(sqlite3Config.pInitMutex);
+ return SQLITE_OK;
+ }
+ sqlite3StatusReset();
+ inProgress = 1;
+ rc = sqlite3_os_init();
+ inProgress = 0;
+ sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
+ sqlite3_mutex_leave(sqlite3Config.pInitMutex);
}
- sqlite3_mutex_leave(pMaster);
- /* The following is just a sanity check to make sure SQLite has
- ** been compiled correctly. It is important to run this code, but
- ** we don't want to run it too often and soak up CPU cycles for no
- ** reason. So we run it once during initialization.
- */
+ /* Check NaN support. */
#ifndef NDEBUG
/* This section of code's only "output" is via assert() statements. */
if ( rc==SQLITE_OK ){
@@ -84113,14 +81040,19 @@ SQLITE_API int sqlite3_initialize(void){
** routine is not threadsafe. Not by a long shot.
*/
SQLITE_API int sqlite3_shutdown(void){
- sqlite3GlobalConfig.isMallocInit = 0;
- sqlite3PcacheShutdown();
- if( sqlite3GlobalConfig.isInit ){
+ sqlite3_mutex_free(sqlite3Config.pInitMutex);
+ sqlite3Config.pInitMutex = 0;
+ sqlite3Config.isMallocInit = 0;
+ if( sqlite3Config.isInit ){
sqlite3_os_end();
}
- sqlite3MallocEnd();
- sqlite3MutexEnd();
- sqlite3GlobalConfig.isInit = 0;
+ if( sqlite3Config.m.xShutdown ){
+ sqlite3MallocEnd();
+ }
+ if( sqlite3Config.mutex.xMutexEnd ){
+ sqlite3MutexEnd();
+ }
+ sqlite3Config.isInit = 0;
return SQLITE_OK;
}
@@ -84139,106 +81071,84 @@ SQLITE_API int sqlite3_config(int op, ...){
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
** the SQLite library is in use. */
- if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE;
+ if( sqlite3Config.isInit ) return SQLITE_MISUSE;
va_start(ap, op);
switch( op ){
-
- /* Mutex configuration options are only available in a threadsafe
- ** compile.
- */
-#if SQLITE_THREADSAFE
case SQLITE_CONFIG_SINGLETHREAD: {
/* Disable all mutexing */
- sqlite3GlobalConfig.bCoreMutex = 0;
- sqlite3GlobalConfig.bFullMutex = 0;
+ sqlite3Config.bCoreMutex = 0;
+ sqlite3Config.bFullMutex = 0;
break;
}
case SQLITE_CONFIG_MULTITHREAD: {
/* Disable mutexing of database connections */
/* Enable mutexing of core data structures */
- sqlite3GlobalConfig.bCoreMutex = 1;
- sqlite3GlobalConfig.bFullMutex = 0;
+ sqlite3Config.bCoreMutex = 1;
+ sqlite3Config.bFullMutex = 0;
break;
}
case SQLITE_CONFIG_SERIALIZED: {
/* Enable all mutexing */
- sqlite3GlobalConfig.bCoreMutex = 1;
- sqlite3GlobalConfig.bFullMutex = 1;
+ sqlite3Config.bCoreMutex = 1;
+ sqlite3Config.bFullMutex = 1;
break;
}
- case SQLITE_CONFIG_MUTEX: {
- /* Specify an alternative mutex implementation */
- sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
- break;
- }
- case SQLITE_CONFIG_GETMUTEX: {
- /* Retrieve the current mutex implementation */
- *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex;
- break;
- }
-#endif
-
-
case SQLITE_CONFIG_MALLOC: {
/* Specify an alternative malloc implementation */
- sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*);
+ sqlite3Config.m = *va_arg(ap, sqlite3_mem_methods*);
break;
}
case SQLITE_CONFIG_GETMALLOC: {
/* Retrieve the current malloc() implementation */
- if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
- *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m;
+ if( sqlite3Config.m.xMalloc==0 ) sqlite3MemSetDefault();
+ *va_arg(ap, sqlite3_mem_methods*) = sqlite3Config.m;
+ break;
+ }
+ case SQLITE_CONFIG_MUTEX: {
+ /* Specify an alternative mutex implementation */
+ sqlite3Config.mutex = *va_arg(ap, sqlite3_mutex_methods*);
+ break;
+ }
+ case SQLITE_CONFIG_GETMUTEX: {
+ /* Retrieve the current mutex implementation */
+ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3Config.mutex;
break;
}
case SQLITE_CONFIG_MEMSTATUS: {
/* Enable or disable the malloc status collection */
- sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
+ sqlite3Config.bMemstat = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_SCRATCH: {
/* Designate a buffer for scratch memory space */
- sqlite3GlobalConfig.pScratch = va_arg(ap, void*);
- sqlite3GlobalConfig.szScratch = va_arg(ap, int);
- sqlite3GlobalConfig.nScratch = va_arg(ap, int);
+ sqlite3Config.pScratch = va_arg(ap, void*);
+ sqlite3Config.szScratch = va_arg(ap, int);
+ sqlite3Config.nScratch = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_PAGECACHE: {
/* Designate a buffer for scratch memory space */
- sqlite3GlobalConfig.pPage = va_arg(ap, void*);
- sqlite3GlobalConfig.szPage = va_arg(ap, int);
- sqlite3GlobalConfig.nPage = va_arg(ap, int);
- break;
- }
-
- case SQLITE_CONFIG_PCACHE: {
- /* Specify an alternative malloc implementation */
- sqlite3GlobalConfig.pcache = *va_arg(ap, sqlite3_pcache_methods*);
- break;
- }
-
- case SQLITE_CONFIG_GETPCACHE: {
- if( sqlite3GlobalConfig.pcache.xInit==0 ){
- sqlite3PCacheSetDefault();
- }
- *va_arg(ap, sqlite3_pcache_methods*) = sqlite3GlobalConfig.pcache;
+ sqlite3Config.pPage = va_arg(ap, void*);
+ sqlite3Config.szPage = va_arg(ap, int);
+ sqlite3Config.nPage = va_arg(ap, int);
break;
}
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
case SQLITE_CONFIG_HEAP: {
/* Designate a buffer for heap memory space */
- sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
- sqlite3GlobalConfig.nHeap = va_arg(ap, int);
- sqlite3GlobalConfig.mnReq = va_arg(ap, int);
+ sqlite3Config.pHeap = va_arg(ap, void*);
+ sqlite3Config.nHeap = va_arg(ap, int);
+ sqlite3Config.mnReq = va_arg(ap, int);
- if( sqlite3GlobalConfig.pHeap==0 ){
+ if( sqlite3Config.pHeap==0 ){
/* If the heap pointer is NULL, then restore the malloc implementation
** back to NULL pointers too. This will cause the malloc to go
** back to its default implementation when sqlite3_initialize() is
** run.
*/
- memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
+ memset(&sqlite3Config.m, 0, sizeof(sqlite3Config.m));
}else{
/* The heap pointer is not NULL, then install one of the
** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
@@ -84246,19 +81156,27 @@ SQLITE_API int sqlite3_config(int op, ...){
** the default case and return an error.
*/
#ifdef SQLITE_ENABLE_MEMSYS3
- sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
+ sqlite3Config.m = *sqlite3MemGetMemsys3();
#endif
#ifdef SQLITE_ENABLE_MEMSYS5
- sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5();
+ sqlite3Config.m = *sqlite3MemGetMemsys5();
#endif
}
break;
}
#endif
+#if defined(SQLITE_ENABLE_MEMSYS6)
+ case SQLITE_CONFIG_CHUNKALLOC: {
+ sqlite3Config.nSmall = va_arg(ap, int);
+ sqlite3Config.m = *sqlite3MemGetMemsys6();
+ break;
+ }
+#endif
+
case SQLITE_CONFIG_LOOKASIDE: {
- sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
- sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
+ sqlite3Config.szLookaside = va_arg(ap, int);
+ sqlite3Config.nLookaside = va_arg(ap, int);
break;
}
@@ -84289,13 +81207,12 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
}
if( sz<0 ) sz = 0;
if( cnt<0 ) cnt = 0;
+ sz = (sz+7)&~7;
if( pBuf==0 ){
- sz = (sz + 7)&~7;
sqlite3BeginBenignMalloc();
pStart = sqlite3Malloc( sz*cnt );
sqlite3EndBenignMalloc();
}else{
- sz = sz&~7;
pStart = pBuf;
}
if( db->lookaside.bMalloced ){
@@ -84324,13 +81241,6 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
}
/*
-** Return the mutex associated with a database connection.
-*/
-SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){
- return db->mutex;
-}
-
-/*
** Configuration settings for an individual database connection
*/
SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
@@ -84417,7 +81327,6 @@ static int nocaseCollatingFunc(
){
int r = sqlite3StrNICmp(
(const char *)pKey1, (const char *)pKey2, (nKey1<nKey2)?nKey1:nKey2);
- UNUSED_PARAMETER(NotUsed);
if( 0==r ){
r = nKey1-nKey2;
}
@@ -84500,17 +81409,14 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
sqlite3ResetInternalSchema(db, 0);
assert( db->nDb<=2 );
assert( db->aDb==db->aDbStatic );
- for(j=0; j<ArraySize(db->aFunc.a); j++){
- FuncDef *pNext, *pHash, *p;
- for(p=db->aFunc.a[j]; p; p=pHash){
- pHash = p->pHash;
- while( p ){
- pNext = p->pNext;
- sqlite3DbFree(db, p);
- p = pNext;
- }
+ for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
+ FuncDef *pFunc, *pNext;
+ for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
+ pNext = pFunc->pNext;
+ sqlite3DbFree(db, pFunc);
}
}
+
for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
CollSeq *pColl = (CollSeq *)sqliteHashData(i);
/* Invoke any destructors registered for collation sequence user data. */
@@ -84533,6 +81439,7 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
sqlite3HashClear(&db->aModule);
#endif
+ sqlite3HashClear(&db->aFunc);
sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
if( db->pErr ){
sqlite3ValueFree(db->pErr);
@@ -84551,7 +81458,6 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
sqlite3_mutex_leave(db->mutex);
db->magic = SQLITE_MAGIC_CLOSED;
sqlite3_mutex_free(db->mutex);
- assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
@@ -85182,15 +82088,6 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db){
}
return db->errCode & db->errMask;
}
-SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
- if( db && !sqlite3SafetyCheckSickOrOk(db) ){
- return SQLITE_MISUSE;
- }
- if( !db || db->mallocFailed ){
- return SQLITE_NOMEM;
- }
- return db->errCode;
-}
/*
** Create a new collating function for database "db". The name is zName
@@ -85305,11 +82202,11 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_VDBE_OP<40
# error SQLITE_MAX_VDBE_OP must be at least 40
#endif
-#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000
-# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000
+#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127
+# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127
#endif
-#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>30
-# error SQLITE_MAX_ATTACHED must be between 0 and 30
+#if SQLITE_MAX_ATTACH<0 || SQLITE_MAX_ATTACH>30
+# error SQLITE_MAX_ATTACH must be between 0 and 30
#endif
#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
@@ -85317,9 +82214,6 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_VARIABLE_NUMBER<1
# error SQLITE_MAX_VARIABLE_NUMBER must be at least 1
#endif
-#if SQLITE_MAX_COLUMN>32767
-# error SQLITE_MAX_COLUMN must not exceed 32767
-#endif
/*
@@ -85361,21 +82255,15 @@ static int openDatabase(
sqlite3 *db;
int rc;
CollSeq *pColl;
- int isThreadsafe;
+ int isThreadsafe = 1;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ) return rc;
#endif
- if( sqlite3GlobalConfig.bCoreMutex==0 ){
+ if( flags&SQLITE_OPEN_NOMUTEX ){
isThreadsafe = 0;
- }else if( flags & SQLITE_OPEN_NOMUTEX ){
- isThreadsafe = 0;
- }else if( flags & SQLITE_OPEN_FULLMUTEX ){
- isThreadsafe = 1;
- }else{
- isThreadsafe = sqlite3GlobalConfig.bFullMutex;
}
/* Remove harmful bits from the flags parameter */
@@ -85387,14 +82275,13 @@ static int openDatabase(
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_MASTER_JOURNAL |
- SQLITE_OPEN_NOMUTEX |
- SQLITE_OPEN_FULLMUTEX
+ SQLITE_OPEN_NOMUTEX
);
/* Allocate the sqlite data structure */
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
- if( isThreadsafe ){
+ if( sqlite3Config.bFullMutex && isThreadsafe ){
db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
if( db->mutex==0 ){
sqlite3_free(db);
@@ -85422,14 +82309,16 @@ static int openDatabase(
| SQLITE_LoadExtension
#endif
;
- sqlite3HashInit(&db->aCollSeq, 0);
+ sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
+ sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3HashInit(&db->aModule, 0);
+ sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0);
#endif
db->pVfs = sqlite3_vfs_find(zVfs);
if( !db->pVfs ){
rc = SQLITE_ERROR;
+ db->magic = SQLITE_MAGIC_SICK;
sqlite3Error(db, rc, "no such vfs: %s", zVfs);
goto opendb_out;
}
@@ -85443,6 +82332,7 @@ static int openDatabase(
createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
if( db->mallocFailed ){
+ db->magic = SQLITE_MAGIC_SICK;
goto opendb_out;
}
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
@@ -85464,10 +82354,8 @@ static int openDatabase(
flags | SQLITE_OPEN_MAIN_DB,
&db->aDb[0].pBt);
if( rc!=SQLITE_OK ){
- if( rc==SQLITE_IOERR_NOMEM ){
- rc = SQLITE_NOMEM;
- }
sqlite3Error(db, rc, 0);
+ db->magic = SQLITE_MAGIC_SICK;
goto opendb_out;
}
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
@@ -85526,6 +82414,7 @@ static int openDatabase(
#ifdef SQLITE_ENABLE_ICU
if( !db->mallocFailed && rc==SQLITE_OK ){
+ extern int sqlite3IcuInit(sqlite3*);
rc = sqlite3IcuInit(db);
}
#endif
@@ -85549,20 +82438,16 @@ static int openDatabase(
#endif
/* Enable the lookaside-malloc subsystem */
- setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
- sqlite3GlobalConfig.nLookaside);
+ setupLookaside(db, 0, sqlite3Config.szLookaside, sqlite3Config.nLookaside);
opendb_out:
if( db ){
- assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
+ assert( db->mutex!=0 || isThreadsafe==0 || sqlite3Config.bFullMutex==0 );
sqlite3_mutex_leave(db->mutex);
}
- rc = sqlite3_errcode(db);
- if( rc==SQLITE_NOMEM ){
+ if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
sqlite3_close(db);
db = 0;
- }else if( rc!=SQLITE_OK ){
- db->magic = SQLITE_MAGIC_SICK;
}
*ppDb = db;
return sqlite3ApiExit(0, rc);
@@ -85727,7 +82612,6 @@ SQLITE_API int sqlite3_collation_needed16(
#endif /* SQLITE_OMIT_UTF16 */
#ifndef SQLITE_OMIT_GLOBALRECOVER
-#ifndef SQLITE_OMIT_DEPRECATED
/*
** This function is now an anachronism. It used to be used to recover from a
** malloc() failure, but SQLite now does this automatically.
@@ -85736,7 +82620,6 @@ SQLITE_API int sqlite3_global_recover(void){
return SQLITE_OK;
}
#endif
-#endif
/*
** Test to see whether or not the database connection is in autocommit
@@ -85761,7 +82644,6 @@ SQLITE_PRIVATE int sqlite3Corrupt(void){
}
#endif
-#ifndef SQLITE_OMIT_DEPRECATED
/*
** This is a convenience routine that makes sure that all thread-specific
** data for this thread has been deallocated.
@@ -85771,7 +82653,6 @@ SQLITE_PRIVATE int sqlite3Corrupt(void){
*/
SQLITE_API void sqlite3_thread_cleanup(void){
}
-#endif
/*
** Return meta information about a specific column of a database table.
@@ -85852,7 +82733,7 @@ SQLITE_API int sqlite3_table_column_metadata(
zCollSeq = pCol->zColl;
notnull = pCol->notNull!=0;
primarykey = pCol->isPrimKey!=0;
- autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
+ autoinc = pTab->iPKey==iCol && pTab->autoInc;
}else{
zDataType = "INTEGER";
primarykey = 1;
@@ -88105,7 +84986,7 @@ typedef struct QueryTerm {
short int nPhrase; /* How many following terms are part of the same phrase */
short int iPhrase; /* This is the i-th term of a phrase. */
short int iColumn; /* Column of the index that must match this term */
- short int nNear; /* term followed by a NEAR operator with span=(nNear-1) */
+ signed char nNear; /* term followed by a NEAR operator with span=(nNear-1) */
signed char isOr; /* this term is preceded by "OR" */
signed char isNot; /* this term is preceded by "-" */
signed char isPrefix; /* this term is followed by "*" */
@@ -90086,10 +86967,10 @@ static int checkColumnSpecifier(
}
/*
-** Parse the text at zSegment[0..nSegment-1]. Add additional terms
+** Parse the text at pSegment[0..nSegment-1]. Add additional terms
** to the query being assemblied in pQuery.
**
-** inPhrase is true if zSegment[0..nSegement-1] is contained within
+** inPhrase is true if pSegment[0..nSegement-1] is contained within
** double-quotes. If inPhrase is true, then the first term
** is marked with the number of terms in the phrase less one and
** OR and "-" syntax is ignored. If inPhrase is false, then every
@@ -90097,7 +86978,7 @@ static int checkColumnSpecifier(
*/
static int tokenizeSegment(
sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */
- const char *zSegment, int nSegment, /* Query expression being parsed */
+ const char *pSegment, int nSegment, /* Query expression being parsed */
int inPhrase, /* True if within "..." */
Query *pQuery /* Append results here */
){
@@ -90107,45 +86988,49 @@ static int tokenizeSegment(
int iCol;
int nTerm = 1;
- int rc = pModule->xOpen(pTokenizer, zSegment, nSegment, &pCursor);
+ int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
if( rc!=SQLITE_OK ) return rc;
pCursor->pTokenizer = pTokenizer;
while( 1 ){
- const char *zToken;
+ const char *pToken;
int nToken, iBegin, iEnd, iPos;
rc = pModule->xNext(pCursor,
- &zToken, &nToken,
+ &pToken, &nToken,
&iBegin, &iEnd, &iPos);
if( rc!=SQLITE_OK ) break;
if( !inPhrase &&
- zSegment[iEnd]==':' &&
- (iCol = checkColumnSpecifier(pQuery->pFts, zToken, nToken))>=0 ){
+ pSegment[iEnd]==':' &&
+ (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){
pQuery->nextColumn = iCol;
continue;
}
if( !inPhrase && pQuery->nTerms>0 && nToken==2
- && zSegment[iBegin+0]=='O'
- && zSegment[iBegin+1]=='R'
+ && pSegment[iBegin+0]=='O'
+ && pSegment[iBegin+1]=='R'
){
pQuery->nextIsOr = 1;
continue;
}
if( !inPhrase && pQuery->nTerms>0 && !pQuery->nextIsOr && nToken==4
- && memcmp(&zSegment[iBegin], "NEAR", 4)==0
+ && pSegment[iBegin+0]=='N'
+ && pSegment[iBegin+1]=='E'
+ && pSegment[iBegin+2]=='A'
+ && pSegment[iBegin+3]=='R'
){
QueryTerm *pTerm = &pQuery->pTerms[pQuery->nTerms-1];
if( (iBegin+6)<nSegment
- && zSegment[iBegin+4] == '/'
- && isdigit(zSegment[iBegin+5])
+ && pSegment[iBegin+4] == '/'
+ && pSegment[iBegin+5]>='0' && pSegment[iBegin+5]<='9'
){
- int k;
- pTerm->nNear = 0;
- for(k=5; (iBegin+k)<=nSegment && isdigit(zSegment[iBegin+k]); k++){
- pTerm->nNear = pTerm->nNear*10 + (zSegment[iBegin+k] - '0');
+ pTerm->nNear = (pSegment[iBegin+5] - '0');
+ nToken += 2;
+ if( pSegment[iBegin+6]>='0' && pSegment[iBegin+6]<=9 ){
+ pTerm->nNear = pTerm->nNear * 10 + (pSegment[iBegin+6] - '0');
+ iEnd++;
}
- pModule->xNext(pCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
+ pModule->xNext(pCursor, &pToken, &nToken, &iBegin, &iEnd, &iPos);
} else {
pTerm->nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM;
}
@@ -90153,11 +87038,11 @@ static int tokenizeSegment(
continue;
}
- queryAdd(pQuery, zToken, nToken);
- if( !inPhrase && iBegin>0 && zSegment[iBegin-1]=='-' ){
+ queryAdd(pQuery, pToken, nToken);
+ if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
}
- if( iEnd<nSegment && zSegment[iEnd]=='*' ){
+ if( iEnd<nSegment && pSegment[iEnd]=='*' ){
pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1;
}
pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm;
@@ -93829,13 +90714,6 @@ SQLITE_PRIVATE void *sqlite3Fts3HashInsert(
return old_data;
}
if( data==0 ) return 0;
- if( pH->htsize==0 ){
- fts3Rehash(pH,8);
- if( pH->htsize==0 ){
- pH->count = 0;
- return data;
- }
- }
new_elem = (fts3HashElem*)fts3HashMalloc( sizeof(fts3HashElem) );
if( new_elem==0 ) return data;
if( pH->copyKey && pKey!=0 ){
@@ -93850,6 +90728,14 @@ SQLITE_PRIVATE void *sqlite3Fts3HashInsert(
}
new_elem->nKey = nKey;
pH->count++;
+ if( pH->htsize==0 ){
+ fts3Rehash(pH,8);
+ if( pH->htsize==0 ){
+ pH->count = 0;
+ fts3HashFree(new_elem);
+ return data;
+ }
+ }
if( pH->count > pH->htsize ){
fts3Rehash(pH,pH->htsize*2);
}
@@ -95158,8 +92044,10 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(
#ifndef SQLITE_CORE
+ #include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#else
+ #include "sqlite3.h"
#endif
@@ -95323,12 +92211,8 @@ struct RtreeCell {
RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2];
};
-#ifndef MAX
-# define MAX(x,y) ((x) < (y) ? (y) : (x))
-#endif
-#ifndef MIN
-# define MIN(x,y) ((x) > (y) ? (y) : (x))
-#endif
+#define MAX(x,y) ((x) < (y) ? (y) : (x))
+#define MIN(x,y) ((x) > (y) ? (y) : (x))
/*
** Functions to deserialize a 16 bit integer, 32 bit real number and
@@ -95701,7 +92585,7 @@ static void nodeGetCell(
** the virtual table module xCreate() and xConnect() methods.
*/
static int rtreeInit(
- sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int
+ sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int, int
);
/*
@@ -95714,7 +92598,7 @@ static int rtreeCreate(
sqlite3_vtab **ppVtab,
char **pzErr
){
- return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1);
+ return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1, (int)pAux);
}
/*
@@ -95727,7 +92611,7 @@ static int rtreeConnect(
sqlite3_vtab **ppVtab,
char **pzErr
){
- return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0);
+ return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0, (int)pAux);
}
/*
@@ -96217,13 +93101,6 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
pIdxInfo->idxNum = 1;
pIdxInfo->aConstraintUsage[ii].argvIndex = 1;
pIdxInfo->aConstraintUsage[jj].omit = 1;
-
- /* This strategy involves a two rowid lookups on an B-Tree structures
- ** and then a linear search of an R-Tree node. This should be
- ** considered almost as quick as a direct rowid lookup (for which
- ** sqlite uses an internal cost of 0.0).
- */
- pIdxInfo->estimatedCost = 10.0;
return SQLITE_OK;
}
@@ -96277,8 +93154,6 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
return SQLITE_NOMEM;
}
- assert( iIdx>=0 );
- pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1));
return rc;
}
@@ -96326,25 +93201,6 @@ static void cellUnion(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
}
/*
-** Return true if the area covered by p2 is a subset of the area covered
-** by p1. False otherwise.
-*/
-static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
- int ii;
- int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
- for(ii=0; ii<(pRtree->nDim*2); ii+=2){
- RtreeCoord *a1 = &p1->aCoord[ii];
- RtreeCoord *a2 = &p2->aCoord[ii];
- if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
- || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
- ){
- return 0;
- }
- }
- return 1;
-}
-
-/*
** Return the amount cell p would grow by if it were unioned with pCell.
*/
static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){
@@ -96510,7 +93366,7 @@ static void AdjustTree(
int iCell = nodeParentIndex(pRtree, p);
nodeGetCell(pRtree, pParent, iCell, &cell);
- if( !cellContains(pRtree, &cell, pCell) ){
+ if( cellGrowth(pRtree, &cell, pCell)>0.0 ){
cellUnion(pRtree, &cell, pCell);
nodeOverwriteCell(pRtree, pParent, &cell, iCell);
}
@@ -97752,18 +94608,18 @@ static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){
*/
static int rtreeInit(
sqlite3 *db, /* Database connection */
- void *pAux, /* One of the RTREE_COORD_* constants */
+ void *pAux, /* Pointer to head of rtree list */
int argc, const char *const*argv, /* Parameters to CREATE TABLE statement */
sqlite3_vtab **ppVtab, /* OUT: New virtual table */
char **pzErr, /* OUT: Error message, if any */
- int isCreate /* True for xCreate, false for xConnect */
+ int isCreate, /* True for xCreate, false for xConnect */
+ int eCoordType /* One of the RTREE_COORD_* constants */
){
int rc = SQLITE_OK;
int iPageSize = 0;
Rtree *pRtree;
int nDb; /* Length of string argv[1] */
int nName; /* Length of string argv[2] */
- int eCoordType = (int)pAux;
const char *aErrMsg[] = {
0, /* 0 */
@@ -97996,8 +94852,10 @@ SQLITE_API int sqlite3_extension_init(
#ifndef SQLITE_CORE
+ #include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#else
+ #include "sqlite3.h"
#endif
/*
@@ -98454,265 +95312,3 @@ SQLITE_API int sqlite3_extension_init(
#endif
/************** End of icu.c *************************************************/
-/************** Begin file fts3_icu.c ****************************************/
-/*
-** 2007 June 22
-**
-** 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 implements a tokenizer for fts3 based on the ICU library.
-**
-** $Id$
-*/
-
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
-#ifdef SQLITE_ENABLE_ICU
-
-
-#include <unicode/ubrk.h>
-#include <unicode/utf16.h>
-
-typedef struct IcuTokenizer IcuTokenizer;
-typedef struct IcuCursor IcuCursor;
-
-struct IcuTokenizer {
- sqlite3_tokenizer base;
- char *zLocale;
-};
-
-struct IcuCursor {
- sqlite3_tokenizer_cursor base;
-
- UBreakIterator *pIter; /* ICU break-iterator object */
- int nChar; /* Number of UChar elements in pInput */
- UChar *aChar; /* Copy of input using utf-16 encoding */
- int *aOffset; /* Offsets of each character in utf-8 input */
-
- int nBuffer;
- char *zBuffer;
-
- int iToken;
-};
-
-/*
-** Create a new tokenizer instance.
-*/
-static int icuCreate(
- int argc, /* Number of entries in argv[] */
- const char * const *argv, /* Tokenizer creation arguments */
- sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
-){
- IcuTokenizer *p;
- int n = 0;
-
- if( argc>0 ){
- n = strlen(argv[0])+1;
- }
- p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
- if( !p ){
- return SQLITE_NOMEM;
- }
- memset(p, 0, sizeof(IcuTokenizer));
-
- if( n ){
- p->zLocale = (char *)&p[1];
- memcpy(p->zLocale, argv[0], n);
- }
-
- *ppTokenizer = (sqlite3_tokenizer *)p;
-
- return SQLITE_OK;
-}
-
-/*
-** Destroy a tokenizer
-*/
-static int icuDestroy(sqlite3_tokenizer *pTokenizer){
- IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
- sqlite3_free(p);
- return SQLITE_OK;
-}
-
-/*
-** Prepare to begin tokenizing a particular string. The input
-** string to be tokenized is pInput[0..nBytes-1]. A cursor
-** used to incrementally tokenize this string is returned in
-** *ppCursor.
-*/
-static int icuOpen(
- sqlite3_tokenizer *pTokenizer, /* The tokenizer */
- const char *zInput, /* Input string */
- int nInput, /* Length of zInput in bytes */
- sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
-){
- IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
- IcuCursor *pCsr;
-
- const int32_t opt = U_FOLD_CASE_DEFAULT;
- UErrorCode status = U_ZERO_ERROR;
- int nChar;
-
- UChar32 c;
- int iInput = 0;
- int iOut = 0;
-
- *ppCursor = 0;
-
- if( nInput<0 ){
- nInput = strlen(zInput);
- }
- nChar = nInput+1;
- pCsr = (IcuCursor *)sqlite3_malloc(
- sizeof(IcuCursor) + /* IcuCursor */
- nChar * sizeof(UChar) + /* IcuCursor.aChar[] */
- (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
- );
- if( !pCsr ){
- return SQLITE_NOMEM;
- }
- memset(pCsr, 0, sizeof(IcuCursor));
- pCsr->aChar = (UChar *)&pCsr[1];
- pCsr->aOffset = (int *)&pCsr->aChar[nChar];
-
- pCsr->aOffset[iOut] = iInput;
- U8_NEXT(zInput, iInput, nInput, c);
- while( c>0 ){
- int isError = 0;
- c = u_foldCase(c, opt);
- U16_APPEND(pCsr->aChar, iOut, nChar, c, isError);
- if( isError ){
- sqlite3_free(pCsr);
- return SQLITE_ERROR;
- }
- pCsr->aOffset[iOut] = iInput;
-
- if( iInput<nInput ){
- U8_NEXT(zInput, iInput, nInput, c);
- }else{
- c = 0;
- }
- }
-
- pCsr->pIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status);
- if( !U_SUCCESS(status) ){
- sqlite3_free(pCsr);
- return SQLITE_ERROR;
- }
- pCsr->nChar = iOut;
-
- ubrk_first(pCsr->pIter);
- *ppCursor = (sqlite3_tokenizer_cursor *)pCsr;
- return SQLITE_OK;
-}
-
-/*
-** Close a tokenization cursor previously opened by a call to icuOpen().
-*/
-static int icuClose(sqlite3_tokenizer_cursor *pCursor){
- IcuCursor *pCsr = (IcuCursor *)pCursor;
- ubrk_close(pCsr->pIter);
- sqlite3_free(pCsr->zBuffer);
- sqlite3_free(pCsr);
- return SQLITE_OK;
-}
-
-/*
-** Extract the next token from a tokenization cursor.
-*/
-static int icuNext(
- sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
- const char **ppToken, /* OUT: *ppToken is the token text */
- int *pnBytes, /* OUT: Number of bytes in token */
- int *piStartOffset, /* OUT: Starting offset of token */
- int *piEndOffset, /* OUT: Ending offset of token */
- int *piPosition /* OUT: Position integer of token */
-){
- IcuCursor *pCsr = (IcuCursor *)pCursor;
-
- int iStart = 0;
- int iEnd = 0;
- int nByte = 0;
-
- while( iStart==iEnd ){
- UChar32 c;
-
- iStart = ubrk_current(pCsr->pIter);
- iEnd = ubrk_next(pCsr->pIter);
- if( iEnd==UBRK_DONE ){
- return SQLITE_DONE;
- }
-
- while( iStart<iEnd ){
- int iWhite = iStart;
- U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
- if( u_isspace(c) ){
- iStart = iWhite;
- }else{
- break;
- }
- }
- assert(iStart<=iEnd);
- }
-
- do {
- UErrorCode status = U_ZERO_ERROR;
- if( nByte ){
- char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte);
- if( !zNew ){
- return SQLITE_NOMEM;
- }
- pCsr->zBuffer = zNew;
- pCsr->nBuffer = nByte;
- }
-
- u_strToUTF8(
- pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */
- &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */
- &status /* Output success/failure */
- );
- } while( nByte>pCsr->nBuffer );
-
- *ppToken = pCsr->zBuffer;
- *pnBytes = nByte;
- *piStartOffset = pCsr->aOffset[iStart];
- *piEndOffset = pCsr->aOffset[iEnd];
- *piPosition = pCsr->iToken++;
-
- return SQLITE_OK;
-}
-
-/*
-** The set of routines that implement the simple tokenizer
-*/
-static const sqlite3_tokenizer_module icuTokenizerModule = {
- 0, /* iVersion */
- icuCreate, /* xCreate */
- icuDestroy, /* xCreate */
- icuOpen, /* xOpen */
- icuClose, /* xClose */
- icuNext, /* xNext */
-};
-
-/*
-** Set *ppModule to point at the implementation of the ICU tokenizer.
-*/
-SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(
- sqlite3_tokenizer_module const**ppModule
-){
- *ppModule = &icuTokenizerModule;
-}
-
-#endif /* defined(SQLITE_ENABLE_ICU) */
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
-
-/************** End of fts3_icu.c ********************************************/
-
-#if defined(_MSC_VER) && _MSC_VER < 1300
-#pragma optimize("", on)
-#endif