diff options
Diffstat (limited to 'ext/sqlite3/libsqlite/sqlite3.c')
-rw-r--r-- | ext/sqlite3/libsqlite/sqlite3.c | 20088 |
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, ¬Used); 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, ¬Used); - } - 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, ®Free1); 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, ®Free1); 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 |