X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=libs%2Fsqlite3%2Fsqlite3.c;h=fb8a199d5b2f7978a7d0ede469b39797fc70cbf3;hb=30c26abc85a6331fecdcb6b03813710bfbc63d3f;hp=c39340cb25991c3ee57fb96d966dcb649e2b4062;hpb=e7848d3900faf539dddfa6c7b3aac13ddc099e15;p=fms.git diff --git a/libs/sqlite3/sqlite3.c b/libs/sqlite3/sqlite3.c index c39340c..fb8a199 100644 --- a/libs/sqlite3/sqlite3.c +++ b/libs/sqlite3/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.6.3. By combining all the individual C code files into this +** version 3.6.6.2. 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 @@ -11,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 -** 6364 lines past this header comment.) Additional code files may be +** 6728 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-09-22 10:45:10 UTC. +** This amalgamation was generated on 2008-11-26 17:54:40 UTC. */ #define SQLITE_CORE 1 #define SQLITE_AMALGAMATION 1 @@ -41,7 +41,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.772 2008/09/12 16:03:48 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.798 2008/11/19 16:52:44 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -487,7 +487,7 @@ SQLITE_PRIVATE void sqlite3Coverage(int); ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.398 2008/09/10 13:09:24 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.415 2008/11/19 01:20:26 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -509,29 +509,20 @@ extern "C" { #endif /* -** Add the ability to mark interfaces as deprecated. -*/ -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) - /* GCC added the deprecated attribute in version 3.1 */ - #define SQLITE_DEPRECATED __attribute__ ((deprecated)) -#elif defined(_MSC_VER) && (_MSC_VER>1200) - #define SQLITE_DEPRECATED __declspec(deprecated) -#else - #define SQLITE_DEPRECATED -#endif - -/* -** Add the ability to mark interfaces as experimental. +** 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. */ -#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) - /* I can confirm that it does not work on version 4.1.0... */ - /* First appears in GCC docs for version 4.3.0 */ - #define SQLITE_EXPERIMENTAL __attribute__ ((warning ("is experimental"))) -#elif defined(_MSC_VER) && (_MSC_VER>1200) - #define SQLITE_EXPERIMENTAL __declspec(deprecated("was declared experimental")) -#else - #define SQLITE_EXPERIMENTAL -#endif +#define SQLITE_DEPRECATED +#define SQLITE_EXPERIMENTAL /* ** Ensure these symbols were not defined by some previous header file. @@ -573,8 +564,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.3" -#define SQLITE_VERSION_NUMBER 3006003 +#define SQLITE_VERSION "3.6.6.2" +#define SQLITE_VERSION_NUMBER 3006006 /* ** CAPI3REF: Run-Time Library Version Numbers {H10020} @@ -639,16 +630,11 @@ SQLITE_API int sqlite3_libversion_number(void); ** ** INVARIANTS: ** -** {H10101} The [sqlite3_threadsafe()] function shall return nonzero if -** and only if -** SQLite was compiled with the its mutexes enabled by default. +** {H10101} The [sqlite3_threadsafe()] function shall return zero if +** and only if SQLite was compiled with mutexing code omitted. ** ** {H10102} The value returned by the [sqlite3_threadsafe()] function -** 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. +** shall remain the same across calls to [sqlite3_config()]. */ SQLITE_API int sqlite3_threadsafe(void); @@ -745,7 +731,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 -** return SQLITE_OK. +** be a harmless no-op returning SQLITE_OK. ** ** {H12019} When [sqlite3_close(C)] is invoked on a [database connection] C ** that has a pending transaction, the transaction shall be @@ -849,12 +835,14 @@ 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()], +** and message accessible via [sqlite3_errcode()], +** [sqlite3_extended_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. ** @@ -1056,7 +1044,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 @@ -1088,7 +1076,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. ** @@ -1151,6 +1139,12 @@ 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 { @@ -1377,24 +1371,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 @@ -1412,11 +1406,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); @@ -1425,7 +1419,7 @@ SQLITE_API int sqlite3_os_init(void); SQLITE_API int sqlite3_os_end(void); /* -** CAPI3REF: Configuring The SQLite Library {H10145} +** CAPI3REF: Configuring The SQLite Library {H14100} ** EXPERIMENTAL ** ** The sqlite3_config() interface is used to make global configuration @@ -1448,14 +1442,103 @@ 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 {H10180} +** CAPI3REF: Configure database connections {H14200} ** EXPERIMENTAL ** ** The sqlite3_db_config() interface is used to make configuration @@ -1472,6 +1555,38 @@ 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, ...); @@ -1616,7 +1731,10 @@ struct sqlite3_mem_methods { ** **
SQLITE_CONFIG_PAGECACHE
**
This option specifies a static memory buffer that SQLite can use for -** the database page cache. There are three arguments: A pointer to the +** 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 ** 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. @@ -1661,6 +1779,17 @@ struct sqlite3_mem_methods { ** size of each lookaside buffer slot and the second is the number of ** slots allocated to each database connection.
** +**
SQLITE_CONFIG_PCACHE
+**
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.
+** +**
SQLITE_CONFIG_GETPCACHE
+**
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.
+** ** */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ @@ -1674,8 +1803,10 @@ 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* */ -#define SQLITE_CONFIG_CHUNKALLOC 12 /* int threshold */ +/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ #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} @@ -1737,17 +1868,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 INSERTs +** successful [INSERT] into the database from the [database connection] +** in the first argument. If no successful [INSERT]s ** 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 @@ -1756,23 +1887,24 @@ 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 returns the rowid -** of the most recent successful INSERT performed on the same +** {H12221} The [sqlite3_last_insert_rowid()] function shall return 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 inserts. +** trigger context, or zero if there have been no qualifying +** [INSERT] statements. ** -** {H12223} The [sqlite3_last_insert_rowid()] function returns the +** {H12223} The [sqlite3_last_insert_rowid()] function shall return 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 @@ -1787,8 +1919,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. ** @@ -1822,13 +1954,15 @@ 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. (This is much faster than going -** through and deleting individual elements from the table.) Because of this +** by dropping and recreating the table. Doing so is much faster than going +** through and deleting individual elements from the table. Because of this ** optimization, the deletions in "DELETE FROM table" are not row changes and ** will not be counted by the sqlite3_changes() or [sqlite3_total_changes()] ** functions, regardless of the number of elements that were originally ** in the table. To get an accurate count of the number of rows deleted, use -** "DELETE FROM table WHERE 1" instead. +** "DELETE FROM table WHERE 1" instead. Or recompile using the +** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the +** optimization on all queries. ** ** INVARIANTS: ** @@ -1870,7 +2004,9 @@ 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. +** "DELETE FROM table WHERE 1" instead. Or recompile using the +** [SQLITE_OMIT_TRUNCATE_OPTIMIZATION] compile-time option to disable the +** optimization on all queries. ** ** See also the [sqlite3_changes()] interface. ** @@ -2349,7 +2485,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_free(). +** was not obtained from sqlite3_malloc() or sqlite3_realloc(). ** ** The sqlite3_realloc() interface attempts to resize a ** prior memory allocation to be at least N bytes, where N is the @@ -2720,7 +2856,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 /* Function Name NULL */ +#define SQLITE_FUNCTION 31 /* NULL Function Name */ #define SQLITE_COPY 0 /* No longer used */ /* @@ -3003,7 +3139,10 @@ 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. +** 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. ** ** The sqlite3_errmsg() and sqlite3_errmsg16() return English-language ** text that describes the error, as either UTF-8 or UTF-16 respectively. @@ -3012,6 +3151,16 @@ 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. @@ -3022,6 +3171,10 @@ 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, @@ -3033,15 +3186,18 @@ 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_errmsg()], or [sqlite3_errmsg16()]. +** [sqlite3_errcode()], [sqlite3_extended_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_errmsg()], or [sqlite3_errmsg16()]. +** [sqlite3_errcode()], [sqlite3_extended_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*); @@ -3310,7 +3466,7 @@ SQLITE_API int sqlite3_prepare16_v2( ); /* -** CAPIREF: Retrieving Statement SQL {H13100} +** CAPI3REF: Retrieving Statement SQL {H13100} ** ** 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 @@ -4468,14 +4624,16 @@ 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 want they do. +** using these functions, we are not going to tell you what 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 /* ** CAPI3REF: Obtaining SQL Function Parameter Values {H15100} @@ -6108,6 +6266,7 @@ 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. ** @@ -6221,6 +6380,7 @@ 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. @@ -6290,6 +6450,7 @@ 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. */ @@ -6588,6 +6749,17 @@ 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} +** +** 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} ** ** {H11301} The [sqlite3_file_control()] interface makes a direct call to the @@ -6682,29 +6854,6 @@ SQLITE_API int sqlite3_test_control(int op, ...); */ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag); -/* -** CAPI3REF: Database Connection Status {H17201} -** 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 SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); - - -SQLITE_API int sqlite3_wsd_init(int N, int J); -SQLITE_API void *sqlite3_wsd_find(void *K, int L); /* ** CAPI3REF: Status Parameters {H17250} @@ -6794,7 +6943,27 @@ SQLITE_API void *sqlite3_wsd_find(void *K, int L); #define SQLITE_STATUS_SCRATCH_SIZE 8 /* -** CAPI3REF: Status Parameters for database connections {H17275} +** CAPI3REF: Database Connection Status {H17500} +** 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} ** EXPERIMENTAL ** ** Status verbs for [sqlite3_db_status()]. @@ -6807,6 +6976,201 @@ SQLITE_API void *sqlite3_wsd_find(void *K, int L); */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 + +/* +** CAPI3REF: Prepared Statement Status {H17550} +** 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} +** 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: +** +**
+**
SQLITE_STMTSTATUS_FULLSCAN_STEP
+**
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.
+** +**
SQLITE_STMTSTATUS_SORT
+**
This is the number of sort operations that have occurred. +** A non-zero value in this counter may indicate an opportunity to +** improvement performance through careful use of indices.
+** +**
+*/ +#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: +** +** +**
createFlagExpected Behaviour +**
0NULL should be returned. No new cache entry is created. +**
1If 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. +**
2If 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. +**
+** +** 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. @@ -6838,7 +7202,7 @@ SQLITE_API void *sqlite3_wsd_find(void *K, int L); ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** -** $Id: hash.h,v 1.11 2007/09/04 14:31:47 danielk1977 Exp $ +** $Id: hash.h,v 1.12 2008/10/10 17:41:29 drh Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ @@ -6856,14 +7220,13 @@ typedef struct HashElem HashElem; ** this structure opaque. */ struct 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 */ + 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 */ } *ht; }; @@ -6880,31 +7243,9 @@ 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 keytype, int copyKey); +SQLITE_PRIVATE void sqlite3HashInit(Hash*, int copyKey); SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData); SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const void *pKey, int nKey); SQLITE_PRIVATE HashElem *sqlite3HashFindElem(const Hash*, const void *pKey, int nKey); @@ -7053,43 +7394,44 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); #define TK_DOT 112 #define TK_FROM 113 #define TK_JOIN 114 -#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_FUNCTION 147 -#define TK_COLUMN 148 -#define TK_AGG_FUNCTION 149 -#define TK_AGG_COLUMN 150 -#define TK_CONST_FUNC 151 +#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_FUNCTION 148 +#define TK_COLUMN 149 +#define TK_AGG_FUNCTION 150 +#define TK_AGG_COLUMN 151 +#define TK_CONST_FUNC 152 /************** End of parse.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -7241,7 +7583,8 @@ SQLITE_PRIVATE const int sqlite3one; #else SQLITE_PRIVATE const int sqlite3one; #endif -#if defined(i386) || defined(__i386__) || defined(_M_IX86) +#if defined(i386) || defined(__i386__) || defined(_M_IX86)\ + || defined(__x86_64) || defined(__x86_64__) # define SQLITE_BIGENDIAN 0 # define SQLITE_LITTLEENDIAN 1 # define SQLITE_UTF16NATIVE SQLITE_UTF16LE @@ -7297,7 +7640,7 @@ struct BusyHandler { ** A convenience macro that returns the number of elements in ** an array. */ -#define ArraySize(X) (sizeof(X)/sizeof(X[0])) +#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) /* ** The following value as a destructor means to use sqlite3DbFree(). @@ -7316,13 +7659,15 @@ struct BusyHandler { ** buffer that holds real variable. The constant is also the initializer ** for the run-time allocated buffer. ** -** In the usually case where WSD is supported, the SQLITE_WSD and GLOBAL +** 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 @@ -7330,6 +7675,25 @@ struct BusyHandler { #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; @@ -7389,7 +7753,7 @@ typedef struct WhereLevel WhereLevel; ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.103 2008/08/13 19:11:48 drh Exp $ +** @(#) $Id: btree.h,v 1.105 2008/10/27 13:59:34 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -7493,7 +7857,7 @@ 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); +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, 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); @@ -7546,6 +7910,7 @@ 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); @@ -7619,7 +7984,7 @@ SQLITE_PRIVATE void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.138 2008/08/20 22:06:48 drh Exp $ +** $Id: vdbe.h,v 1.139 2008/10/31 10:53:23 danielk1977 Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -7755,7 +8120,7 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Affinity 2 #define OP_Column 3 #define OP_SetCookie 4 -#define OP_Real 125 /* same as TK_FLOAT */ +#define OP_Real 126 /* same as TK_FLOAT */ #define OP_Sequence 5 #define OP_MoveGt 6 #define OP_Ge 72 /* same as TK_GE */ @@ -7765,7 +8130,7 @@ typedef struct VdbeOpList VdbeOpList; #define OP_OpenWrite 9 #define OP_NotNull 66 /* same as TK_NOTNULL */ #define OP_If 10 -#define OP_ToInt 141 /* same as TK_TO_INT */ +#define OP_ToInt 142 /* same as TK_TO_INT */ #define OP_String8 88 /* same as TK_STRING */ #define OP_VRowid 11 #define OP_CollSeq 12 @@ -7811,7 +8176,7 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Gosub 47 #define OP_Divide 81 /* same as TK_SLASH */ #define OP_Integer 48 -#define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/ +#define OP_ToNumeric 141 /* 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 */ @@ -7835,7 +8200,7 @@ typedef struct VdbeOpList VdbeOpList; #define OP_IfNot 85 #define OP_DropTable 86 #define OP_MakeRecord 89 -#define OP_ToBlob 139 /* same as TK_TO_BLOB */ +#define OP_ToBlob 140 /* same as TK_TO_BLOB */ #define OP_ResultRow 90 #define OP_Delete 91 #define OP_AggFinal 92 @@ -7849,9 +8214,9 @@ typedef struct VdbeOpList VdbeOpList; #define OP_Le 70 /* same as TK_LE */ #define OP_VerifyCookie 99 #define OP_AggStep 100 -#define OP_ToText 138 /* same as TK_TO_TEXT */ +#define OP_ToText 139 /* same as TK_TO_TEXT */ #define OP_Not 16 /* same as TK_NOT */ -#define OP_ToReal 142 /* same as TK_TO_REAL */ +#define OP_ToReal 143 /* same as TK_TO_REAL */ #define OP_SetNumColumns 101 #define OP_Transaction 102 #define OP_VFilter 103 @@ -7881,7 +8246,7 @@ typedef struct VdbeOpList VdbeOpList; #define OP_IfZero 123 #define OP_BitNot 87 /* same as TK_BITNOT */ #define OP_VCreate 124 -#define OP_Found 126 +#define OP_Found 125 #define OP_IfPos 127 #define OP_NullRow 128 #define OP_Jump 129 @@ -7895,6 +8260,7 @@ 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 @@ -7923,9 +8289,10 @@ 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, 0x02, 0x11, 0x05,\ +/* 120 */ 0x11, 0x00, 0x00, 0x05, 0x00, 0x11, 0x02, 0x05,\ /* 128 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\ -/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,} +/* 136 */ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,\ +} /************** End of opcodes.h *********************************************/ /************** Continuing where we left off in vdbe.h ***********************/ @@ -7962,7 +8329,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 *, int); +SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*)); SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*); SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*); SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n); @@ -8008,7 +8375,7 @@ SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...); ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.83 2008/09/18 17:34:44 danielk1977 Exp $ +** @(#) $Id: pager.h,v 1.87 2008/11/19 10:22:33 danielk1977 Exp $ */ #ifndef _PAGER_H_ @@ -8060,13 +8427,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*, void(*)(DbPage*), int,int,int); -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler); +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 int sqlite3PagerSetPagesize(Pager*, u16*); SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int); @@ -8076,6 +8445,7 @@ 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*); @@ -8151,7 +8521,7 @@ void enable_simulated_io_errors(void); ** This header file defines the interface that the sqlite page cache ** subsystem. ** -** @(#) $Id: pcache.h,v 1.11 2008/09/18 17:34:44 danielk1977 Exp $ +** @(#) $Id: pcache.h,v 1.16 2008/11/19 16:52:44 danielk1977 Exp $ */ #ifndef _PCACHE_H_ @@ -8173,25 +8543,19 @@ struct PgHdr { 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 */ - void *apSave[2]; /* Journal entries for in-memory databases */ - /********************************************************************** - ** Elements above are accessible at any time by the owner of the cache - ** without the need for a mutex. The elements that follow can only be - ** accessed while holding the SQLITE_MUTEX_STATIC_LRU mutex. - */ - PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */ - PgHdr *pNext, *pPrev; /* List of clean or dirty pages */ - PgHdr *pNextLru, *pPrevLru; /* Part of global LRU list */ + + 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_IN_JOURNAL 0x001 /* Page is in rollback journal */ #define PGHDR_DIRTY 0x002 /* Page has changed */ #define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before ** writing this page to the database */ @@ -8207,8 +8571,6 @@ SQLITE_PRIVATE void sqlite3PcacheShutdown(void); ** These routines implement SQLITE_CONFIG_PAGECACHE. */ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n); -SQLITE_PRIVATE void *sqlite3PCacheMalloc(int sz); -SQLITE_PRIVATE void sqlite3PCacheFree(void*); /* Create a new pager cache. ** Under memory stress, invoke xStress to try to make pages clean. @@ -8218,7 +8580,6 @@ 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 */ - void (*xDestroy)(PgHdr *), /* Called to destroy a page */ int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */ void *pStress, /* Argument to xStress */ PCache *pToInit /* Preallocated space for the PCache */ @@ -8249,11 +8610,6 @@ 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); -/* Routines used to implement transactions on memory-only databases. */ -SQLITE_PRIVATE int sqlite3PcachePreserve(PgHdr*, int); /* Preserve current page content */ -SQLITE_PRIVATE void sqlite3PcacheCommit(PCache*, int); /* Drop preserved copy */ -SQLITE_PRIVATE void sqlite3PcacheRollback(PCache*, int, void (*xReiniter)(PgHdr*)); - /* Get a list of all dirty pages in the cache, sorted by page number */ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*); @@ -8261,17 +8617,7 @@ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*); SQLITE_PRIVATE void sqlite3PcacheClose(PCache*); /* Clear flags from pages of the page cache */ -SQLITE_PRIVATE void sqlite3PcacheClearFlags(PCache*, int mask); - -/* Assert flags settings on all pages. Debugging only */ -#ifndef NDEBUG -SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask); -#else -# define sqlite3PcacheAssertFlags(A,B,C) -#endif - -/* Return true if the number of dirty pages is 0 or 1 */ -SQLITE_PRIVATE int sqlite3PcacheZeroOrOneDirtyPages(PCache*); +SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *); /* Discard the contents of the cache */ SQLITE_PRIVATE int sqlite3PcacheClear(PCache*); @@ -8282,14 +8628,18 @@ 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*); -/* Iterate through all pages currently stored in the cache. This interface -** is only available if SQLITE_CHECK_PAGES is defined when the library is -** built. +#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 sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)); +SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)); +#endif /* Set and get the suggested cache-size for the specified pager-cache. ** @@ -8297,13 +8647,21 @@ SQLITE_PRIVATE void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)) ** the total number of pages cached by purgeable pager-caches to the sum ** of the suggested cache-sizes. */ -SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *); 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_ */ @@ -8613,28 +8971,21 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); ** Source files should #include the sqliteInt.h file and let that file ** include this one indirectly. ** -** $Id: mutex.h,v 1.8 2008/06/26 10:41:19 danielk1977 Exp $ +** $Id: mutex.h,v 1.9 2008/10/07 15:25:48 drh Exp $ */ -#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_NOOP For single-threaded applications that -** do not desire error checking. +** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The +** mutexes implemention cannot 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_NOOP For single-threaded applications. No +** mutual exclusion is provided. But this +** implementation can be overridden at +** start-time. ** ** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix. ** @@ -8642,25 +8993,22 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); ** ** SQLITE_MUTEX_OS2 For multi-threaded applications on OS/2. */ -#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 +#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 #endif -#ifdef SQLITE_MUTEX_NOOP +#ifdef SQLITE_MUTEX_OMIT /* ** If this is a no-op implementation, implement everything as macros. */ @@ -8674,9 +9022,7 @@ SQLITE_PRIVATE int sqlite3OsCloseFree(sqlite3_file *); #define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8) #define sqlite3MutexInit() SQLITE_OK #define sqlite3MutexEnd() -#endif - -#endif /* SQLITE_MUTEX_APPDEF */ +#endif /* defined(SQLITE_OMIT_MUTEX) */ /************** End of mutex.h ***********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ @@ -8837,7 +9183,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 */ - int magic; /* Magic number for detect library misuse */ + u32 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 */ @@ -8851,6 +9197,7 @@ 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 */ @@ -8953,9 +9300,8 @@ struct sqlite3 { ** points to a linked list of these structures. */ struct FuncDef { - i8 nArg; /* Number of arguments. -1 means unlimited */ + 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 */ @@ -8969,9 +9315,10 @@ struct FuncDef { /* ** 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_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 @@ -8999,11 +9346,13 @@ struct FuncDef { ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_UTF8, bNC, 0, SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName} + {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, 0, flags, (void *)arg, 0, likeFunc, 0, 0, #zName} + {nArg, SQLITE_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0} #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ - {nArg, SQLITE_UTF8, nc, 0, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal, #zName} + {nArg, SQLITE_UTF8, nc*8, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0} /* @@ -9573,6 +9922,11 @@ 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. @@ -9603,6 +9957,9 @@ struct SrcList { Expr *pOn; /* The ON clause of a join */ IdList *pUsing; /* The USING clause of a join */ Bitmask colUsed; /* Bit N (1<" clause */ + Index *pIndex; /* Index structure corresponding to zIndex, if any */ } a[1]; /* One entry for each identifier on the list */ }; @@ -9648,7 +10005,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; /* Opcode used to terminate the loop */ + int op, p1, p2, p5; /* 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 { @@ -10104,6 +10461,7 @@ 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 */ @@ -10118,7 +10476,6 @@ struct Sqlite3Config { 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 */ }; @@ -10201,14 +10558,18 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void*); SQLITE_PRIVATE void *sqlite3PageMalloc(int); SQLITE_PRIVATE void sqlite3PageFree(void*); SQLITE_PRIVATE void sqlite3MemSetDefault(void); -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetDefault(void); -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys6(void); SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void)); SQLITE_PRIVATE int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64); -#ifndef SQLITE_MUTEX_NOOP +#ifdef SQLITE_ENABLE_MEMSYS3 +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void); +#endif +#ifdef SQLITE_ENABLE_MEMSYS5 +SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); +#endif + + +#ifndef SQLITE_MUTEX_OMIT SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void); SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int); SQLITE_PRIVATE int sqlite3MutexInit(void); @@ -10250,6 +10611,7 @@ 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*); @@ -10292,9 +10654,12 @@ 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 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 void sqlite3SrcListShiftJoinType(SrcList*); SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*); SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*); @@ -10309,6 +10674,9 @@ 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); @@ -10359,7 +10727,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,int); +SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*, Table*, 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*); @@ -10373,7 +10741,6 @@ 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 int sqlite3GetBuiltinFunction(const char *, int, FuncDef **); #ifdef SQLITE_DEBUG SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3*); SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3*); @@ -10395,7 +10762,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(Parse*, Table*, int, ExprList*); +SQLITE_PRIVATE int sqlite3TriggersExist(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*); @@ -10408,7 +10775,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(A,B,C,D,E,F) 0 +# define sqlite3TriggersExist(B,C,D,E,F) 0 # define sqlite3DeleteTrigger(A,B) # define sqlite3DropTriggerPtr(A,B) # define sqlite3UnlinkAndDeleteTrigger(A,B,C) @@ -10476,8 +10843,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), &(B))) -#define putVarint32(A,B) (((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), (u32 *)&(B))) +#define putVarint32(A,B) (((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B))) #define getVarint sqlite3GetVarint #define putVarint sqlite3PutVarint @@ -10522,7 +10889,7 @@ 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); +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*); @@ -10539,7 +10906,6 @@ 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 *); @@ -10589,11 +10955,13 @@ 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*); @@ -10646,6 +11014,10 @@ 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 *); @@ -10914,7 +11286,7 @@ SQLITE_API int sqlite3_db_status( ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.90 2008/09/03 17:11:16 drh Exp $ +** $Id: date.c,v 1.94 2008/11/19 09:05:27 danielk1977 Exp $ ** ** SQLite processes all times and dates as Julian Day numbers. The ** dates and times are stored as the number of days since noon @@ -11416,7 +11788,7 @@ static int parseModifier(const char *zMod, DateTime *p){ double r; char *z, zBuf[30]; z = zBuf; - for(n=0; niJD -= c1; @@ -11784,7 +12156,7 @@ static void strftimeFunc( } if( ndb->aLimit[SQLITE_LIMIT_LENGTH] ){ + }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){ sqlite3_result_error_toobig(context); return; }else{ @@ -11863,9 +12235,10 @@ static void strftimeFunc( */ static void ctimeFunc( sqlite3_context *context, - int argc, - sqlite3_value **argv + int NotUsed, + sqlite3_value **NotUsed2 ){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); timeFunc(context, 0, 0); } @@ -11876,9 +12249,10 @@ static void ctimeFunc( */ static void cdateFunc( sqlite3_context *context, - int argc, - sqlite3_value **argv + int NotUsed, + sqlite3_value **NotUsed2 ){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); dateFunc(context, 0, 0); } @@ -11889,9 +12263,10 @@ static void cdateFunc( */ static void ctimestampFunc( sqlite3_context *context, - int argc, - sqlite3_value **argv + int NotUsed, + sqlite3_value **NotUsed2 ){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); datetimeFunc(context, 0, 0); } #endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */ @@ -11959,9 +12334,9 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc), FUNCTION(current_date, 0, 0, 0, cdateFunc ), #else - FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc), - FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc), - FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc), + 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 }; int i; @@ -11990,7 +12365,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ ** This file contains OS interface code that is common to all ** architectures. ** -** $Id: os.c,v 1.122 2008/09/02 17:18:52 danielk1977 Exp $ +** $Id: os.c,v 1.124 2008/10/07 15:25:48 drh Exp $ */ #define _SQLITE_OS_C_ 1 #undef _SQLITE_OS_C_ @@ -12012,7 +12387,7 @@ SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){ ** sqlite3OsLock() ** */ -#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) && 0 +#if defined(SQLITE_TEST) && (SQLITE_OS_WIN==0) #define DO_OS_MALLOC_TEST if (1) { \ void *pTstAlloc = sqlite3Malloc(10); \ if (!pTstAlloc) return SQLITE_IOERR_NOMEM; \ @@ -12175,14 +12550,14 @@ static sqlite3_vfs * SQLITE_WSD vfsList = 0; */ SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){ sqlite3_vfs *pVfs = 0; -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE sqlite3_mutex *mutex; #endif #ifndef SQLITE_OMIT_AUTOINIT int rc = sqlite3_initialize(); if( rc ) return 0; #endif -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); @@ -12244,7 +12619,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){ -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); @@ -12347,6 +12722,69 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){ #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: mem0.c,v 1.1 2008/10/28 18:58:20 drh Exp $ +*/ + +/* +** 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 @@ -12367,7 +12805,7 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){ ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. ** -** $Id: mem1.c,v 1.26 2008/09/01 18:34:20 danielk1977 Exp $ +** $Id: mem1.c,v 1.28 2008/11/19 09:05:27 danielk1977 Exp $ */ /* @@ -12459,6 +12897,7 @@ static int sqlite3MemRoundup(int n){ ** Initialize this module. */ static int sqlite3MemInit(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); return SQLITE_OK; } @@ -12466,10 +12905,17 @@ static int sqlite3MemInit(void *NotUsed){ ** Deinitialize this module. */ static void sqlite3MemShutdown(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); return; } -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetDefault(void){ +/* +** 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, @@ -12480,17 +12926,7 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetDefault(void){ sqlite3MemShutdown, 0 }; - return &defaultMethods; -} - -/* -** 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){ - sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault()); + sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); } #endif /* SQLITE_SYSTEM_MALLOC */ @@ -12518,7 +12954,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){ ** This file contains implementations of the low-level memory allocation ** routines specified in the sqlite3_mem_methods object. ** -** $Id: mem2.c,v 1.39 2008/09/01 18:34:20 danielk1977 Exp $ +** $Id: mem2.c,v 1.40 2008/10/28 18:58:20 drh Exp $ */ /* @@ -12820,8 +13256,11 @@ static void *sqlite3MemRealloc(void *pPrior, int nByte){ return pNew; } - -SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetDefault(void){ +/* +** 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, @@ -12832,15 +13271,7 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetDefault(void){ sqlite3MemShutdown, 0 }; - return &defaultMethods; -} - -/* -** Populate the low-level memory allocation function pointers in -** sqlite3GlobalConfig.m with pointers to the routines in this file. -*/ -SQLITE_PRIVATE void sqlite3MemSetDefault(void){ - sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault()); + sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods); } /* @@ -12966,7 +13397,7 @@ SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){ ** This version of the memory allocation subsystem is included ** in the build only if SQLITE_ENABLE_MEMSYS3 is defined. ** -** $Id: mem3.c,v 1.23 2008/09/02 17:52:52 danielk1977 Exp $ +** $Id: mem3.c,v 1.25 2008/11/19 16:52:44 danielk1977 Exp $ */ /* @@ -13193,7 +13624,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, int nBlock){ +static void *memsys3Checkout(u32 i, u32 nBlock){ u32 x; assert( sqlite3_mutex_held(mem3.mutex) ); assert( i>=1 ); @@ -13211,7 +13642,7 @@ static void *memsys3Checkout(u32 i, int nBlock){ ** Return a pointer to the new allocation. Or, if the master chunk ** is not large enough, return 0. */ -static void *memsys3FromMaster(int nBlock){ +static void *memsys3FromMaster(u32 nBlock){ assert( sqlite3_mutex_held(mem3.mutex) ); assert( mem3.szMaster>=nBlock ); if( nBlock>=mem3.szMaster-1 ){ @@ -13297,8 +13728,8 @@ static void memsys3Merge(u32 *pRoot){ */ static void *memsys3MallocUnsafe(int nByte){ u32 i; - int nBlock; - int toFree; + u32 nBlock; + u32 toFree; assert( sqlite3_mutex_held(mem3.mutex) ); assert( sizeof(Mem3Block)==8 ); @@ -13494,6 +13925,7 @@ void *memsys3Realloc(void *pPrior, int nBytes){ ** Initialize this module. */ static int memsys3Init(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); if( !sqlite3GlobalConfig.pHeap ){ return SQLITE_ERROR; } @@ -13518,6 +13950,7 @@ static int memsys3Init(void *NotUsed){ ** Deinitialize this module. */ static void memsys3Shutdown(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); return; } @@ -13530,7 +13963,7 @@ static void memsys3Shutdown(void *NotUsed){ SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){ #ifdef SQLITE_DEBUG FILE *out; - int i, j; + u32 i, j; u32 size; if( zFilename==0 || zFilename[0]==0 ){ out = stdout; @@ -13595,6 +14028,8 @@ SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){ }else{ fclose(out); } +#else + UNUSED_PARAMETER(zFilename); #endif } @@ -13652,38 +14087,16 @@ SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){ ** This version of the memory allocation subsystem is included ** in the build only if SQLITE_ENABLE_MEMSYS5 is defined. ** -** $Id: mem5.c,v 1.14 2008/09/02 17:52:52 danielk1977 Exp $ +** $Id: mem5.c,v 1.19 2008/11/19 16:52:44 danielk1977 Exp $ */ /* ** This version of the memory allocator is used only when -** SQLITE_POW2_MEMORY_SIZE is defined. +** SQLITE_ENABLE_MEMSYS5 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)<mem5.maxRequest ){ + if( (u32)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; iFullSz0 ); - assert( mem5.currentOut>=0 ); + assert( mem5.currentOut>=(size*mem5.nAtom) ); mem5.currentCount--; mem5.currentOut -= size*mem5.nAtom; assert( mem5.currentOut>0 || mem5.currentCount==0 ); @@ -14030,13 +14442,15 @@ static int memsys5Init(void *NotUsed){ int nMinLog; /* Log of minimum allocation size in bytes*/ int iOffset; + UNUSED_PARAMETER(NotUsed); + if( !zByte ){ return SQLITE_ERROR; } nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq); mem5.nAtom = (1<mem5.nAtom ){ + while( (int)sizeof(Mem5Link)>mem5.nAtom ){ mem5.nAtom = mem5.nAtom << 1; } @@ -14066,6 +14480,7 @@ static int memsys5Init(void *NotUsed){ ** Deinitialize this module. */ static void memsys5Shutdown(void *NotUsed){ + UNUSED_PARAMETER(NotUsed); return; } @@ -14109,6 +14524,8 @@ SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){ }else{ fclose(out); } +#else + UNUSED_PARAMETER(zFilename); #endif } @@ -14134,506 +14551,6 @@ 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: mem6.c,v 1.10 2008/09/02 17:52:52 danielk1977 Exp $ -*/ - -#ifdef SQLITE_ENABLE_MEMSYS6 - - -/* -** Maximum size of any "small" allocation is ((1<zPool[(idx)*pChunk->nAtom])) - -static SQLITE_WSD 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 = { 48642791 }; - -#define mem6 GLOBAL(struct Mem6Global, 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 && inBlock ); - 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 && inBlock ); - 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( xnBlock ); - 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 && iBlocknBlock ); - assert( ((u8 *)pOld-pChunk->zPool)%pChunk->nAtom==0 ); - assert( (pChunk->aCtrl[iBlock] & CTRL_FREE)==0 ); - - iLogsize = pChunk->aCtrl[iBlock] & CTRL_LOGSIZE; - size = 1<nBlock ); - - pChunk->aCtrl[iBlock] |= CTRL_FREE; - pChunk->aCtrl[iBlock+size-1] |= CTRL_FREE; - - pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize; - while( iLogsize>iLogsize) & 1 ){ - iBuddy = iBlock - size; - }else{ - iBuddy = iBlock + size; - } - assert( iBuddy>=0 ); - if( (iBuddy+(1<pChunk->nBlock ) break; - if( pChunk->aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break; - memsys6Unlink(pChunk, iBuddy, iLogsize); - iLogsize++; - if( iBuddyaCtrl[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 && inBlock ); - 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<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<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<cnt>0; } -static int noopMutexNotheld(sqlite3_mutex *p){ +static int debugMutexNotheld(sqlite3_mutex *p){ return p==0 || p->cnt==0; } /* ** Initialize and deinitialize the mutex subsystem. */ -static int noopMutexInit(void){ return SQLITE_OK; } -static int noopMutexEnd(void){ return SQLITE_OK; } +static int debugMutexInit(void){ return SQLITE_OK; } +static int debugMutexEnd(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 *noopMutexAlloc(int id){ +static sqlite3_mutex *debugMutexAlloc(int id){ static sqlite3_mutex aStatic[6]; sqlite3_mutex *pNew = 0; switch( id ){ @@ -14851,7 +14830,7 @@ static sqlite3_mutex *noopMutexAlloc(int id){ /* ** This routine deallocates a previously allocated mutex. */ -static void noopMutexFree(sqlite3_mutex *p){ +static void debugMutexFree(sqlite3_mutex *p){ assert( p->cnt==0 ); assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ); sqlite3_free(p); @@ -14868,12 +14847,12 @@ static void noopMutexFree(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 noopMutexEnter(sqlite3_mutex *p){ - assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); +static void debugMutexEnter(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) ); p->cnt++; } -static int noopMutexTry(sqlite3_mutex *p){ - assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); +static int debugMutexTry(sqlite3_mutex *p){ + assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) ); p->cnt++; return SQLITE_OK; } @@ -14884,31 +14863,31 @@ static int noopMutexTry(sqlite3_mutex *p){ ** is undefined if the mutex is not currently entered or ** is not currently allocated. SQLite will never do either. */ -static void noopMutexLeave(sqlite3_mutex *p){ - assert( noopMutexHeld(p) ); +static void debugMutexLeave(sqlite3_mutex *p){ + assert( debugMutexHeld(p) ); p->cnt--; - assert( p->id==SQLITE_MUTEX_RECURSIVE || noopMutexNotheld(p) ); + assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(p) ); } SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ static sqlite3_mutex_methods sMutex = { - noopMutexInit, - noopMutexEnd, - noopMutexAlloc, - noopMutexFree, - noopMutexEnter, - noopMutexTry, - noopMutexLeave, - - noopMutexHeld, - noopMutexNotheld + debugMutexInit, + debugMutexEnd, + debugMutexAlloc, + debugMutexFree, + debugMutexEnter, + debugMutexTry, + debugMutexLeave, + + debugMutexHeld, + debugMutexNotheld }; return &sMutex; } -#endif /* SQLITE_MUTEX_NOOP_DEBUG */ +#endif /* defined(SQLITE_MUTEX_NOOP) && defined(SQLITE_DEBUG) */ -/************** End of mutex.c ***********************************************/ +/************** End of mutex_noop.c ******************************************/ /************** Begin file mutex_os2.c ***************************************/ /* ** 2007 August 28 @@ -15198,7 +15177,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads ** -** $Id: mutex_unix.c,v 1.13 2008/07/16 12:33:24 drh Exp $ +** $Id: mutex_unix.c,v 1.15 2008/11/17 19:18:55 danielk1977 Exp $ */ /* @@ -15247,7 +15226,7 @@ struct sqlite3_mutex { ** make sure no assert() statements are evaluated and hence these ** routines are never called. */ -#ifndef NDEBUG +#if !defined(NDEBUG) || defined(SQLITE_DEBUG) static int pthreadMutexHeld(sqlite3_mutex *p){ return (p->nRef!=0 && pthread_equal(p->owner, pthread_self())); } @@ -15343,7 +15322,7 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){ } default: { assert( iType-2 >= 0 ); - assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) ); + assert( iType-2 < ArraySize(staticMutexes) ); p = &staticMutexes[iType-2]; p->id = iType; break; @@ -15525,7 +15504,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ ************************************************************************* ** This file contains the C functions that implement mutexes for win32 ** -** $Id: mutex_w32.c,v 1.11 2008/06/26 10:41:19 danielk1977 Exp $ +** $Id: mutex_w32.c,v 1.12 2008/11/10 20:01:41 shane Exp $ */ /* @@ -15554,7 +15533,14 @@ 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 @@ -15569,7 +15555,7 @@ struct sqlite3_mutex { return osType==2; } #endif /* SQLITE_OS_WINCE */ - +#endif #ifdef SQLITE_DEBUG /* @@ -15772,7 +15758,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ ** ** Memory allocation functions used throughout sqlite. ** -** $Id: malloc.c,v 1.41 2008/09/04 04:32:49 shane Exp $ +** $Id: malloc.c,v 1.48 2008/11/19 09:05:27 danielk1977 Exp $ */ /* @@ -15782,9 +15768,10 @@ SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){ */ static void softHeapLimitEnforcer( void *NotUsed, - sqlite3_int64 inUse, + sqlite3_int64 NotUsed2, int allocSize ){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); sqlite3_release_memory(allocSize); } @@ -15826,6 +15813,7 @@ SQLITE_API int sqlite3_release_memory(int n){ nRet += sqlite3PcacheReleaseMemory(n-nRet); return nRet; #else + UNUSED_PARAMETER(n); return SQLITE_OK; #endif } @@ -15859,7 +15847,7 @@ static SQLITE_WSD struct Mem0Global { */ u32 *aScratchFree; u32 *aPageFree; -} mem0 = { 62560955 }; +} mem0 = { 62560955, 0, 0, 0, 0, 0, 0, 0, 0 }; #define mem0 GLOBAL(struct Mem0Global, mem0) @@ -15953,6 +15941,7 @@ SQLITE_PRIVATE int sqlite3MemoryAlarm( return SQLITE_OK; } +#ifndef SQLITE_OMIT_DEPRECATED /* ** Deprecated external interface. Internal/core SQLite code ** should call sqlite3MemoryAlarm. @@ -15964,6 +15953,7 @@ SQLITE_API int sqlite3_memory_alarm( ){ return sqlite3MemoryAlarm(xCallback, pArg, iThreshold); } +#endif /* ** Trigger the alarm @@ -16142,7 +16132,7 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){ i /= sqlite3GlobalConfig.szScratch; assert( i>=0 && i=db->lookaside.pStart && plookaside.pEnd; } +#else +#define isLookaside(A,B) 0 +#endif /* ** Return the size of a memory allocation previously obtained from @@ -16371,9 +16365,24 @@ 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 ){ @@ -16389,6 +16398,11 @@ 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; @@ -16509,7 +16523,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 ){ + if( db && (db->mallocFailed || rc==SQLITE_IOERR_NOMEM) ){ sqlite3Error(db, SQLITE_NOMEM, 0); db->mallocFailed = 0; rc = SQLITE_NOMEM; @@ -16526,7 +16540,7 @@ SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){ ** an historical reference. Most of the "enhancements" have been backed ** out so that the functionality is now the same as standard printf(). ** -** $Id: printf.c,v 1.94 2008/08/22 14:08:36 drh Exp $ +** $Id: printf.c,v 1.96 2008/11/20 18:20:28 drh Exp $ ** ************************************************************************** ** @@ -16657,7 +16671,6 @@ 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 @@ -16694,7 +16707,7 @@ static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ */ static void appendSpace(StrAccum *pAccum, int N){ static const char zSpaces[] = " "; - while( N>=sizeof(zSpaces)-1 ){ + while( N>=(int)sizeof(zSpaces)-1 ){ sqlite3StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1); N -= sizeof(zSpaces)-1; } @@ -16857,7 +16870,7 @@ SQLITE_PRIVATE void sqlite3VXPrintf( } /* Fetch the info entry for the field */ infop = 0; - for(idx=0; idxflags & FLAG_INTERN)==0 ){ @@ -17166,7 +17179,10 @@ SQLITE_PRIVATE void sqlite3VXPrintf( n += i + 1 + needQuote*2; if( n>etBUFSIZE ){ bufpt = zExtra = sqlite3Malloc( n ); - if( bufpt==0 ) return; + if( bufpt==0 ){ + pAccum->mallocFailed = 1; + return; + } }else{ bufpt = buf; } @@ -17470,7 +17486,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){ ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** -** $Id: random.c,v 1.26 2008/09/02 00:52:52 drh Exp $ +** $Id: random.c,v 1.27 2008/10/07 15:25:48 drh Exp $ */ @@ -17560,7 +17576,7 @@ static int randomByte(void){ */ SQLITE_API void sqlite3_randomness(int N, void *pBuf){ unsigned char *zBuf = pBuf; -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); #endif sqlite3_mutex_enter(mutex); @@ -17616,7 +17632,7 @@ SQLITE_PRIVATE void sqlite3PrngResetState(void){ ** This file contains routines used to translate between UTF-8, ** UTF-16, UTF-16BE, and UTF-16LE. ** -** $Id: utf.c,v 1.65 2008/08/12 15:04:59 danielk1977 Exp $ +** $Id: utf.c,v 1.66 2008/11/07 03:29:34 drh Exp $ ** ** Notes on UTF-8: ** @@ -17658,7 +17674,7 @@ SQLITE_PRIVATE void sqlite3PrngResetState(void){ ** 6000 lines long) it was split up into several smaller files and ** this header information was factored out. ** -** $Id: vdbeInt.h,v 1.154 2008/08/13 19:11:48 drh Exp $ +** $Id: vdbeInt.h,v 1.158 2008/11/17 15:31:48 danielk1977 Exp $ */ #ifndef _VDBEINT_H_ #define _VDBEINT_H_ @@ -17693,12 +17709,12 @@ typedef unsigned char Bool; ** Every cursor that the virtual machine has open is represented by an ** instance of the following structure. ** -** If the Cursor.isTriggerRow flag is set it means that this cursor is +** If the VdbeCursor.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 Cursor.pData and -** the rowid is in Cursor.iKey. +** a row trigger. The data for the row is stored in VdbeCursor.pData and +** the rowid is in VdbeCursor.iKey. */ -struct Cursor { +struct VdbeCursor { 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 */ @@ -17736,10 +17752,10 @@ struct Cursor { 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 Cursor Cursor; +typedef struct VdbeCursor VdbeCursor; /* -** A value for Cursor.cacheValid that means the cache is always invalid. +** A value for VdbeCursor.cacheValid that means the cache is always invalid. */ #define CACHE_STALE 0 @@ -17934,16 +17950,16 @@ struct Vdbe { Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ int nCursor; /* Number of slots in apCsr[] */ - Cursor **apCsr; /* One element of this array for each open cursor */ + VdbeCursor **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 */ - int magic; /* Magic number for sanity checking */ + u32 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; /* Cursor row cache generation counter */ + int cacheCtr; /* VdbeCursor 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 */ @@ -17962,14 +17978,17 @@ 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 @@ -17993,9 +18012,9 @@ struct Vdbe { /* ** Function prototypes */ -SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, Cursor*); +SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*); void sqliteVdbePopStack(Vdbe*,int); -SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(Cursor*); +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor*); #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, Op*); #endif @@ -18006,7 +18025,7 @@ 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(Cursor*,UnpackedRecord*,int*); +SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*); SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *, i64 *); SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*); @@ -18254,7 +18273,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){ return SQLITE_NOMEM; } zIn = (u8*)pMem->z; - zTerm = &zIn[pMem->n]; + zTerm = &zIn[pMem->n&~1]; while( zInn &= ~1; len = pMem->n * 2 + 1; }else{ /* When converting from UTF-8 to UTF-16 the maximum growth is caused @@ -18575,7 +18595,7 @@ SQLITE_PRIVATE void sqlite3UtfSelfTest(void){ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.241 2008/07/28 19:34:54 drh Exp $ +** $Id: util.c,v 1.242 2008/11/17 19:18:55 danielk1977 Exp $ */ @@ -18615,7 +18635,7 @@ SQLITE_PRIVATE int sqlite3IsNaN(double x){ SQLITE_PRIVATE int sqlite3Strlen(sqlite3 *db, const char *z){ const char *z2 = z; int len; - size_t x; + int x; while( *z2 ){ z2++; } x = z2 - z; len = 0x7fffffff & x; @@ -19492,7 +19512,7 @@ SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3 *db){ ** used as an argument to sqlite3_errmsg() or sqlite3_close(). */ SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){ - int magic; + u32 magic; if( db==0 ) return 0; magic = db->magic; if( magic!=SQLITE_MAGIC_OPEN && @@ -19500,7 +19520,7 @@ SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){ return 1; } SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ - int magic; + u32 magic; if( db==0 ) return 0; magic = db->magic; if( magic!=SQLITE_MAGIC_SICK && @@ -19525,29 +19545,19 @@ SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){ ** This is the implementation of generic hash-tables ** used in SQLite. ** -** $Id: hash.c,v 1.30 2008/06/20 14:59:51 danielk1977 Exp $ +** $Id: hash.c,v 1.31 2008/10/10 17:41:29 drh Exp $ */ /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** ** "pNew" is a pointer to the hash table that is to be initialized. -** 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. +** "copyKey" is true if the hash table should make its own private +** copy of keys and false if it should just use the supplied pointer. */ -SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){ +SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew, int copyKey){ assert( pNew!=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->copyKey = copyKey!=0; pNew->first = 0; pNew->count = 0; pNew->htsize = 0; @@ -19578,33 +19588,6 @@ 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 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 */ @@ -19730,7 +19640,6 @@ 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 ){ @@ -19752,9 +19661,8 @@ 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 = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); + int h = strHash(elem->pKey, elem->nKey) & (new_size-1); next_elem = elem->next; insertElement(pH, &new_ht[h], elem); } @@ -19772,15 +19680,13 @@ 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( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){ + if( strCompare(elem->pKey,elem->nKey,pKey,nKey)==0 ){ return elem; } elem = elem->next; @@ -19834,12 +19740,9 @@ 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; - xHash = hashFunction(pH->keyClass); - assert( xHash!=0 ); - h = (*xHash)(pKey,nKey); + h = strHash(pKey,nKey); elem = findElementGivenHash(pH,pKey,nKey, h % pH->htsize); return elem; } @@ -19874,12 +19777,9 @@ 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 ); - xHash = hashFunction(pH->keyClass); - assert( xHash!=0 ); - hraw = (*xHash)(pKey, nKey); + hraw = strHash(pKey, nKey); if( pH->htsize ){ h = hraw % pH->htsize; elem = findElementGivenHash(pH,pKey,nKey,h); @@ -20064,8 +19964,8 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 122 */ "VUpdate", /* 123 */ "IfZero", /* 124 */ "VCreate", - /* 125 */ "Real", - /* 126 */ "Found", + /* 125 */ "Found", + /* 126 */ "Real", /* 127 */ "IfPos", /* 128 */ "NullRow", /* 129 */ "Jump", @@ -20077,11 +19977,12 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ /* 135 */ "NotUsed_135", /* 136 */ "NotUsed_136", /* 137 */ "NotUsed_137", - /* 138 */ "ToText", - /* 139 */ "ToBlob", - /* 140 */ "ToNumeric", - /* 141 */ "ToInt", - /* 142 */ "ToReal", + /* 138 */ "NotUsed_138", + /* 139 */ "ToText", + /* 140 */ "ToBlob", + /* 141 */ "ToNumeric", + /* 142 */ "ToInt", + /* 143 */ "ToReal", }; return azName[i]; } @@ -20103,7 +20004,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){ ** ** This file contains code that is specific to OS/2. ** -** $Id: os_os2.c,v 1.56 2008/08/22 13:47:57 pweilbacher Exp $ +** $Id: os_os2.c,v 1.59 2008/11/18 23:03:40 pweilbacher Exp $ */ @@ -20446,6 +20347,7 @@ 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; } @@ -20493,7 +20395,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; + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_TRUNCATE; } #ifdef SQLITE_TEST @@ -20517,7 +20419,14 @@ 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 } /* @@ -20528,13 +20437,13 @@ static int os2FileSize( sqlite3_file *id, sqlite3_int64 *pSize ){ FILESTATUS3 fsts3FileInfo; memset(&fsts3FileInfo, 0, sizeof(fsts3FileInfo)); assert( id!=0 ); - SimulateIOError( return SQLITE_IOERR ); + SimulateIOError( return SQLITE_IOERR_FSTAT ); rc = DosQueryFileInfo( ((os2File*)id)->h, FIL_STANDARD, &fsts3FileInfo, sizeof(FILESTATUS3) ); if( rc == NO_ERROR ){ *pSize = fsts3FileInfo.cbFile; return SQLITE_OK; }else{ - return SQLITE_IOERR; + return SQLITE_IOERR_FSTAT; } } @@ -21186,7 +21095,7 @@ static int os2Delete( rc = DosDelete( (PSZ)zFilenameCp ); free( zFilenameCp ); OSTRACE2( "DELETE \"%s\"\n", zFilename ); - return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR; + return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_DELETE; } /* @@ -21450,21 +21359,41 @@ SQLITE_API int sqlite3_os_end(void){ ** ** This file contains code that is specific to Unix systems. ** -** $Id: os_unix.c,v 1.201 2008/09/15 04:20:32 danielk1977 Exp $ +** $Id: os_unix.c,v 1.216 2008/11/19 16:52:44 danielk1977 Exp $ */ #if SQLITE_OS_UNIX /* This file is used on unix only */ /* -** If SQLITE_ENABLE_LOCKING_STYLE is defined, then several different -** locking implementations are provided: +** If SQLITE_ENABLE_LOCKING_STYLE is defined and is non-zero, then several +** alternative locking implementations are provided: ** ** * POSIX locking (the default), ** * No locking, ** * Dot-file locking, ** * flock() locking, -** * AFP locking (OSX only). +** * 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. */ -/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */ +#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. +*/ +#if defined(__RTP__) || defined(_WRS_KERNEL) +# define IS_VXWORKS 1 +#else +# define IS_VXWORKS 0 +#endif /* ** These #defines should enable >2GB file support on Posix if the @@ -21497,10 +21426,16 @@ SQLITE_API int sqlite3_os_end(void){ #include #include -#ifdef SQLITE_ENABLE_LOCKING_STYLE -#include -#include -#include +#if SQLITE_ENABLE_LOCKING_STYLE +# include +# if IS_VXWORKS +# define lstat stat +# include +# include +# else +# include +# include +# endif #endif /* SQLITE_ENABLE_LOCKING_STYLE */ /* @@ -21539,7 +21474,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 */ -#ifdef SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_ENABLE_LOCKING_STYLE void *lockingContext; /* Locking style specific state */ #endif int h; /* The file descriptor */ @@ -21549,6 +21484,10 @@ struct unixFile { 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 }; /* @@ -21959,7 +21898,11 @@ 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 @@ -21989,7 +21932,11 @@ 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 }; /* @@ -22005,6 +21952,10 @@ 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 */ }; @@ -22017,6 +21968,18 @@ 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. @@ -22029,6 +21992,8 @@ static struct openCnt *openList = 0; ** 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 */ @@ -22037,6 +22002,7 @@ static struct openCnt *openList = 0; #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 @@ -22047,10 +22013,10 @@ static struct openCnt *openList = 0; /* ** Helper functions to obtain and relinquish the global mutex. */ -static void enterMutex(){ +static void enterMutex(void){ sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } -static void leaveMutex(){ +static void leaveMutex(void){ sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)); } @@ -22151,16 +22117,19 @@ static int lockTrace(int fd, int op, struct flock *p){ #define fcntl lockTrace #endif /* SQLITE_LOCK_TRACE */ +#ifdef __linux__ /* -** 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. -*/ +** 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). +*/ static void *threadLockingTest(void *pArg){ struct threadTestData *pData = (struct threadTestData*)pArg; - pData->result = fcntl(pData->fd, F_SETLK, &pData->lock); + pData->result = fcntl(pData->fd, F_GETLK, &pData->lock); return pArg; } @@ -22171,26 +22140,39 @@ static void *threadLockingTest(void *pArg){ */ static void testThreadLockingBehavior(int fd_orig){ int fd; - struct threadTestData d[2]; - pthread_t t[2]; + int rc; + struct threadTestData d; + struct flock l; + pthread_t t; fd = dup(fd_orig); if( fd<0 ) return; - 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); + 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); close(fd); - threadsOverrideEachOthersLocks = d[0].result==0 && d[1].result==0; + if( d.result!=0 ) return; + threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK); +} +#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 */ /* @@ -22240,10 +22222,103 @@ static void releaseOpenCnt(struct openCnt *pOpen){ } } -#ifdef SQLITE_ENABLE_LOCKING_STYLE +#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 /* ** 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; @@ -22260,9 +22335,10 @@ 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. - */ - return LOCKING_STYLE_DOTFILE; + ** 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); } #endif @@ -22277,12 +22353,23 @@ 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 ){ -#ifdef SQLITE_ENABLE_LOCKING_STYLE +#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 struct Mapping { const char *zFilesystem; int eLockingStyle; @@ -22322,9 +22409,12 @@ static int detectLockingStyle( /* Default case. Handles, amongst others, "nfs". */ return testLockingStyle(fd); -#endif +#endif /* if IS_VXWORKS */ 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 @@ -22335,6 +22425,9 @@ 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 */ ){ @@ -22372,7 +22465,11 @@ 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); @@ -22381,7 +22478,11 @@ 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; @@ -22425,6 +22526,10 @@ 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++; } @@ -22489,7 +22594,11 @@ 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); @@ -22555,6 +22664,7 @@ 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; } @@ -22658,6 +22768,20 @@ 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. @@ -22672,9 +22796,7 @@ static int full_fsync(int fd, int fullSync, int dataOnly){ */ #ifdef SQLITE_NO_SYNC rc = SQLITE_OK; -#else - -#if HAVE_FULLFSYNC +#elif HAVE_FULLFSYNC if( fullSync ){ rc = fcntl(fd, F_FULLFSYNC, 0); }else{ @@ -22693,12 +22815,17 @@ 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 /* HAVE_FULLFSYNC */ -#endif /* defined(SQLITE_NO_SYNC) */ +#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */ + if( IS_VXWORKS && rc!= -1 ){ + rc = 0; + } return rc; } @@ -22729,6 +22856,11 @@ 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); @@ -23282,6 +23414,25 @@ 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)); @@ -23324,7 +23475,9 @@ static int unixClose(sqlite3_file *id){ } -#ifdef SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_ENABLE_LOCKING_STYLE + +#if !IS_VXWORKS #pragma mark AFP Support /* @@ -23772,6 +23925,8 @@ 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 @@ -23800,7 +23955,7 @@ static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) { reserved = 1; }else{ /* file does not exist, we could have it if we want it */ - int tErrno = errno; + int tErrno = errno; if( ENOENT != tErrno ){ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK); pFile->lastErrno = tErrno; @@ -23823,9 +23978,10 @@ static int dotlockLock(sqlite3_file *id, int locktype) { ** 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; } @@ -23900,14 +24056,142 @@ 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); } - return closeUnixFile(id); + 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; } +#endif /* IS_VXWORKS */ #endif /* SQLITE_ENABLE_LOCKING_STYLE */ @@ -23916,16 +24200,19 @@ static int dotlockClose(sqlite3_file *id) { */ typedef void nolockLockingContext; -static int nolockCheckReservedLock(sqlite3_file *id, int *pResOut) { +static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){ + UNUSED_PARAMETER(NotUsed); *pResOut = 0; return SQLITE_OK; } -static int nolockLock(sqlite3_file *id, int locktype) { +static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); return SQLITE_OK; } -static int nolockUnlock(sqlite3_file *id, int locktype) { +static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); return SQLITE_OK; } @@ -23933,7 +24220,11 @@ static int nolockUnlock(sqlite3_file *id, int locktype) { ** Close a file. */ static int nolockClose(sqlite3_file *id) { - return closeUnixFile(id); + int rc; + if( IS_VXWORKS ) enterMutex(); + rc = closeUnixFile(id); + if( IS_VXWORKS ) leaveMutex(); + return rc; } @@ -23960,14 +24251,16 @@ 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 *id){ +static int unixSectorSize(sqlite3_file *NotUsed){ + UNUSED_PARAMETER(NotUsed); return SQLITE_DEFAULT_SECTOR_SIZE; } /* -** Return the device characteristics for the file. This is always 0. +** Return the device characteristics for the file. This is always 0 for unix. */ -static int unixDeviceCharacteristics(sqlite3_file *id){ +static int unixDeviceCharacteristics(sqlite3_file *NotUsed){ + UNUSED_PARAMETER(NotUsed); return 0; } @@ -23985,7 +24278,8 @@ 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 noLock, /* Omit locking if true */ + int isDelete /* Delete on close if true */ ){ int eLockingStyle; unixFile *pNew = (unixFile *)pId; @@ -24014,10 +24308,17 @@ static int fillInUnixFile( static sqlite3_io_methods aIoMethod[] = { IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock) ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock) -#ifdef SQLITE_ENABLE_LOCKING_STYLE +#if 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 @@ -24028,15 +24329,60 @@ 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{ @@ -24047,12 +24393,18 @@ 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; } -#ifdef SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_ENABLE_LOCKING_STYLE + +#if !IS_VXWORKS case LOCKING_STYLE_AFP: { /* AFP locking uses the file path so it needs to be included in ** the afpLockingContext. @@ -24070,6 +24422,7 @@ static int fillInUnixFile( } break; } +#endif case LOCKING_STYLE_DOTFILE: { /* Dotfile locking uses the file path so it needs to be included in @@ -24088,6 +24441,30 @@ 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; @@ -24095,6 +24472,13 @@ static int fillInUnixFile( } 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); @@ -24164,7 +24548,7 @@ static int getTempname(int nBuf, char *zBuf){ SimulateIOError( return SQLITE_IOERR ); azDirs[0] = sqlite3_temp_directory; - for(i=0; i= nBuf ){ + if( (strlen(zDir) + strlen(SQLITE_TEMP_FILE_PREFIX) + 17) >= (size_t)nBuf ){ return SQLITE_ERROR; } @@ -24293,6 +24677,7 @@ 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); @@ -24303,7 +24688,11 @@ static int unixOpen( return SQLITE_CANTOPEN; } if( isDelete ){ +#if IS_VXWORKS + zPath = zName; +#else unlink(zName); +#endif } if( pOutFlags ){ *pOutFlags = flags; @@ -24323,27 +24712,35 @@ static int unixOpen( #endif noLock = eType!=SQLITE_OPEN_MAIN_DB; - return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock); + return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); } /* ** Delete the file at zPath. If the dirSync argument is true, fsync() ** the directory after deleting the file. */ -static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ +static int unixDelete(sqlite3_vfs *NotUsed, 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( fsync(fd) ){ +#if IS_VXWORKS + if( fsync(fd)==-1 ) +#else + if( fsync(fd) ) +#endif + { rc = SQLITE_IOERR_DIR_FSYNC; } close(fd); } } +#endif return rc; } @@ -24358,12 +24755,13 @@ static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){ ** Otherwise return 0. */ static int unixAccess( - sqlite3_vfs *pVfs, + sqlite3_vfs *NotUsed, const char *zPath, int flags, int *pResOut ){ int amode = 0; + UNUSED_PARAMETER(NotUsed); SimulateIOError( return SQLITE_IOERR_ACCESS; ); switch( flags ){ case SQLITE_ACCESS_EXISTS: @@ -24408,6 +24806,20 @@ 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); @@ -24446,6 +24858,7 @@ static int unixFullPathname( zFull[j] = 0; } #endif +#endif } @@ -24455,7 +24868,8 @@ static int unixFullPathname( ** within the shared library, and closing the shared library. */ #include -static void *unixDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ +static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){ + UNUSED_PARAMETER(NotUsed); return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); } @@ -24466,8 +24880,9 @@ static void *unixDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ ** is available, zBufOut is left unmodified and SQLite uses a default ** error message. */ -static void unixDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ +static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){ char *zErr; + UNUSED_PARAMETER(NotUsed); enterMutex(); zErr = dlerror(); if( zErr ){ @@ -24475,10 +24890,12 @@ static void unixDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ } leaveMutex(); } -static void *unixDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){ +static void *unixDlSym(sqlite3_vfs *NotUsed, void *pHandle, const char*zSymbol){ + UNUSED_PARAMETER(NotUsed); return dlsym(pHandle, zSymbol); } -static void unixDlClose(sqlite3_vfs *pVfs, void *pHandle){ +static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){ + UNUSED_PARAMETER(NotUsed); dlclose(pHandle); } #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ @@ -24491,9 +24908,9 @@ static void unixDlClose(sqlite3_vfs *pVfs, void *pHandle){ /* ** Write nBuf bytes of random data to the supplied buffer zBuf. */ -static int unixRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ - - assert(nBuf>=(sizeof(time_t)+sizeof(int))); +static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ + UNUSED_PARAMETER(NotUsed); + assert((size_t)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 @@ -24518,13 +24935,15 @@ static int unixRandomness(sqlite3_vfs *pVfs, 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{ - read(fd, zBuf, nBuf); + nBuf = read(fd, zBuf, nBuf); close(fd); } } #endif - return SQLITE_OK; + return nBuf; } @@ -24536,8 +24955,15 @@ static int unixRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ ** might be greater than or equal to the argument, but not less ** than the argument. */ -static int unixSleep(sqlite3_vfs *pVfs, int microseconds){ -#if defined(HAVE_USLEEP) && HAVE_USLEEP +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 usleep(microseconds); return microseconds; #else @@ -24545,6 +24971,7 @@ static int unixSleep(sqlite3_vfs *pVfs, int microseconds){ sleep(seconds); return seconds*1000000; #endif + UNUSED_PARAMETER(NotUsed); } /* @@ -24560,8 +24987,12 @@ 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 *pVfs, double *prNow){ -#ifdef NO_GETTOD +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) time_t t; time(&t); *prNow = t/86400.0 + 2440587.5; @@ -24570,15 +25001,20 @@ static int unixCurrentTime(sqlite3_vfs *pVfs, 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 *pVfs, int nBuf, char *zBuf){ +static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){ + UNUSED_PARAMETER(NotUsed); + UNUSED_PARAMETER(NotUsed2); + UNUSED_PARAMETER(NotUsed3); return 0; } @@ -24613,19 +25049,23 @@ SQLITE_API int sqlite3_os_init(void){ } static sqlite3_vfs unixVfs = UNIXVFS("unix", 0); -#ifdef SQLITE_ENABLE_LOCKING_STYLE +#if SQLITE_ENABLE_LOCKING_STYLE 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-none", LOCKING_STYLE_NONE), + UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM), }; 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; } @@ -24655,7 +25095,7 @@ SQLITE_API int sqlite3_os_end(void){ ** ** This file contains code that is specific to windows. ** -** $Id: os_win.c,v 1.133 2008/09/01 22:15:19 shane Exp $ +** $Id: os_win.c,v 1.140 2008/11/19 21:35:47 shane Exp $ */ #if SQLITE_OS_WIN /* This file is used for windows only */ @@ -24947,7 +25387,7 @@ SQLITE_API int sqlite3_open_file_count = 0; ** Determine if we are dealing with WindowsCE - which has a much ** reduced API. */ -#if defined(SQLITE_OS_WINCE) +#if SQLITE_OS_WINCE # define AreFileApisANSI() 1 #endif @@ -25126,7 +25566,7 @@ static char *unicodeToMbcs(const WCHAR *zWideFilename){ ** Convert multibyte character string to UTF-8. Space to hold the ** returned string is obtained from malloc(). */ -static char *mbcsToUtf8(const char *zFilename){ +SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ char *zFilenameUtf8; WCHAR *zTmpWide; @@ -25483,7 +25923,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); @@ -25539,6 +25979,7 @@ 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; } @@ -25586,14 +26027,20 @@ 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); - SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); - SetEndOfFile(pFile->h); - return SQLITE_OK; + 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; } #ifdef SQLITE_TEST @@ -25617,11 +26064,18 @@ 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 } /* @@ -25657,11 +26111,15 @@ 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; } @@ -25673,8 +26131,12 @@ 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; } @@ -25947,8 +26409,12 @@ 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; @@ -25978,17 +26444,23 @@ 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 = mbcsToUtf8(zMbcsPath); + zUtf8 = sqlite3_win32_mbcs_to_utf8(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; @@ -26050,7 +26522,9 @@ static int winOpen( DWORD dwShareMode; DWORD dwCreationDisposition; DWORD dwFlagsAndAttributes = 0; - int isTemp; +#if SQLITE_OS_WINCE + int isTemp = 0; +#endif winFile *pFile = (winFile*)id; void *zConverted; /* Filename in OS encoding */ const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ @@ -26091,19 +26565,20 @@ 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, @@ -26113,6 +26588,11 @@ 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, @@ -26122,6 +26602,7 @@ static int winOpen( dwFlagsAndAttributes, NULL ); +#endif } if( h==INVALID_HANDLE_VALUE ){ free(zConverted); @@ -26181,7 +26662,7 @@ static int winDelete( int syncDir /* Not used on win32 */ ){ int cnt = 0; - int rc; + DWORD rc; DWORD error; void *zConverted = convertUtf8Filename(zFilename); if( zConverted==0 ){ @@ -26193,19 +26674,25 @@ 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; } @@ -26226,8 +26713,14 @@ 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 ){ @@ -26286,6 +26779,11 @@ 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; @@ -26296,8 +26794,9 @@ static int winFullPathname( } GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); free(zConverted); - zOut = mbcsToUtf8(zTemp); + zOut = sqlite3_win32_mbcs_to_utf8(zTemp); free(zTemp); +#endif } if( zOut ){ sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); @@ -26326,8 +26825,14 @@ 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; @@ -26361,6 +26866,11 @@ 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); @@ -26383,6 +26893,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ memcpy(&zBuf[n], &i, sizeof(i)); n += sizeof(i); } +#endif return n; } @@ -26518,12 +27029,14 @@ 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 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. +** 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. ** But sometimes (for example when during a DROP of a large table) most -** or all of the pages get journalled. In those cases, the bitmap becomes -** dense. The algorithm needs to handle both cases well. +** 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. ** ** The size of the bitmap is fixed when the object is created. ** @@ -26538,20 +27051,41 @@ SQLITE_API int sqlite3_os_end(void){ ** start of a transaction, and is thus usually less than a few thousand, ** but can be as large as 2 billion for a really big database. ** -** @(#) $Id: bitvec.c,v 1.6 2008/06/20 14:59:51 danielk1977 Exp $ +** @(#) $Id: bitvec.c,v 1.9 2008/11/19 18:30:35 shane Exp $ */ +/* 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-12)/sizeof(Bitvec*))*sizeof(Bitvec*)) -#define BITVEC_NCHAR BITVEC_USIZE -#define BITVEC_NBIT (BITVEC_NCHAR*8) -#define BITVEC_NINT (BITVEC_USIZE/4) +#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_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. @@ -26575,11 +27109,15 @@ SQLITE_API int sqlite3_os_end(void){ ** to hold deal with values between 1 and iDivisor. */ struct Bitvec { - u32 iSize; /* Maximum bit index */ - u32 nSet; /* Number of bits that are set */ - u32 iDivisor; /* Number of bits handled by each apSub[] entry */ + 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. */ union { - u8 aBitmap[BITVEC_NCHAR]; /* Bitmap representation */ + BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */ u32 aHash[BITVEC_NINT]; /* Hash table representation */ Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */ } u; @@ -26608,16 +27146,19 @@ 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; - if( p->iSize<=BITVEC_NBIT ){ - i--; - return (p->u.aBitmap[i/8] & (1<<(i&7)))!=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->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); + if( p->iSize<=BITVEC_NBIT ){ + return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0; + } else{ + u32 h = BITVEC_HASH(i++); while( p->u.aHash[h] ){ if( p->u.aHash[h]==i ) return 1; h++; @@ -26630,40 +27171,64 @@ 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 ); - 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; + i--; + while((p->iSize > BITVEC_NBIT) && p->iDivisor) { + u32 bin = i/p->iDivisor; + i = i%p->iDivisor; if( p->u.apSub[bin]==0 ){ sqlite3BeginBenignMalloc(); p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor ); sqlite3EndBenignMalloc(); if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM; } - return sqlite3BitvecSet(p->u.apSub[bin], i); + p = p->u.apSub[bin]; + } + if( p->iSize<=BITVEC_NBIT ){ + p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1)); + return SQLITE_OK; } - h = BITVEC_HASH(i); - while( p->u.aHash[h] ){ + 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 { if( p->u.aHash[h]==i ) return SQLITE_OK; h++; - if( h==BITVEC_NINT ) h = 0; - } - p->nSet++; + 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( p->nSet>=BITVEC_MXHASH ){ - int j, rc; + unsigned int j; + int rc; u32 aiValues[BITVEC_NINT]; memcpy(aiValues, p->u.aHash, sizeof(aiValues)); - memset(p->u.apSub, 0, sizeof(p->u.apSub[0])*BITVEC_NPTR); + memset(p->u.apSub, 0, sizeof(aiValues)); p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR; rc = sqlite3BitvecSet(p, i); for(j=0; jnSet++; p->u.aHash[h] = i; return SQLITE_OK; } /* -** Clear the i-th bit. Return 0 on success and an error code if -** anything goes wrong. +** Clear the i-th bit. */ SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i){ assert( p!=0 ); assert( i>0 ); - if( p->iSize<=BITVEC_NBIT ){ - 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); + 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))); }else{ - int j; + unsigned int j; u32 aiValues[BITVEC_NINT]; memcpy(aiValues, p->u.aHash, sizeof(aiValues)); - memset(p->u.aHash, 0, sizeof(p->u.aHash[0])*BITVEC_NINT); + memset(p->u.aHash, 0, sizeof(aiValues)); p->nSet = 0; for(j=0; jnSet++; + while( p->u.aHash[h] ){ + h++; + if( h>=BITVEC_NINT ) h = 0; + } + p->u.aHash[h] = aiValues[j]; } } } @@ -26711,7 +27285,7 @@ SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i){ SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){ if( p==0 ) return; if( p->iDivisor ){ - int i; + unsigned int i; for(i=0; iu.apSub[i]); } @@ -26844,105 +27418,28 @@ bitvec_end: ************************************************************************* ** This file implements that page cache. ** -** @(#) $Id: pcache.c,v 1.31 2008/09/21 15:14:04 drh Exp $ +** @(#) $Id: pcache.c,v 1.38 2008/11/19 16:52:44 danielk1977 Exp $ */ /* ** A complete page cache is an instance of this structure. -** -** A cache may only be deleted by its owner and while holding the -** SQLITE_MUTEX_STATUS_LRU mutex. */ struct PCache { - /********************************************************************* - ** The first group of elements may be read or written at any time by - ** the cache owner without holding the mutex. No thread other than the - ** cache owner is permitted to access these elements at any time. - */ PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pSynced; /* Last synced page in dirty page list */ - int nRef; /* Number of pinned pages */ - int nPinned; /* Number of pinned and/or dirty pages */ + int nRef; /* Number of referenced pages */ int nMax; /* Configured cache size */ int nMin; /* Configured minimum cache size */ - /********************************************************************** - ** The next group of elements are fixed when the cache is created and - ** may not be changed afterwards. These elements can read at any time by - ** the cache owner or by any thread holding the the mutex. Non-owner - ** threads must hold the mutex when reading these elements to prevent - ** the entire PCache object from being deleted during the read. - */ 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 */ - void (*xDestroy)(PgHdr*); /* Called when refcnt goes 1->0 */ int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ void *pStress; /* Argument to xStress */ - /********************************************************************** - ** The final group of elements can only be accessed while holding the - ** mutex. Both the cache owner and any other thread must hold the mutex - ** to read or write any of these elements. - */ - int nPage; /* Total number of pages in apHash */ - int nHash; /* Number of slots in apHash[] */ - PgHdr **apHash; /* Hash table for fast lookup by pgno */ - PgHdr *pClean; /* List of clean pages in use */ + sqlite3_pcache *pCache; /* Pluggable cache module */ + PgHdr *pPage1; }; /* -** Free slots in the page block allocator -*/ -typedef struct PgFreeslot PgFreeslot; -struct PgFreeslot { - PgFreeslot *pNext; /* Next free slot */ -}; - -/* -** Global data for the page cache. -*/ -static SQLITE_WSD struct PCacheGlobal { - int isInit; /* True when initialized */ - 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 */ - PgHdr *pLruHead, *pLruTail; /* LRU list of unused clean pgs */ - - /* 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 */ -} pcache = {0}; - -/* -** All code in this file should access the global pcache structure via the -** alias "pcache_g". This ensures that the WSD emulation is used when -** compiling for systems that do not support real WSD. -*/ -#define pcache_g (GLOBAL(struct PCacheGlobal, pcache)) - -/* -** All global variables used by this module (all of which are grouped -** together in global structure "pcache" above) are protected by the static -** SQLITE_MUTEX_STATIC_LRU mutex. A pointer to this mutex is stored in -** variable "pcache.mutex". -** -** Some elements of the PCache and PgHdr structures are protected by the -** SQLITE_MUTEX_STATUS_LRU mutex and other are not. The protected -** elements are grouped at the end of the structures and are clearly -** marked. -** -** Use the following macros must surround all access (read or write) -** of protected elements. The mutex is not recursive and may not be -** entered more than once. The pcacheMutexHeld() macro should only be -** used within an assert() to verify that the mutex is being held. -*/ -#define pcacheEnterMutex() sqlite3_mutex_enter(pcache_g.mutex) -#define pcacheExitMutex() sqlite3_mutex_leave(pcache_g.mutex) -#define pcacheMutexHeld() sqlite3_mutex_held(pcache_g.mutex) - -/* ** 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 @@ -26958,48 +27455,6 @@ static SQLITE_WSD struct PCacheGlobal { #if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT) /* -** This routine verifies that the number of entries in the hash table -** is pCache->nPage. This routine is used within assert() statements -** only and is therefore disabled during production builds. -*/ -static int pcacheCheckHashCount(PCache *pCache){ - int i; - int nPage = 0; - for(i=0; inHash; i++){ - PgHdr *p; - for(p=pCache->apHash[i]; p; p=p->pNextHash){ - nPage++; - } - } - assert( nPage==pCache->nPage ); - return 1; -} -#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */ - - -#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT) -/* -** Based on the current value of PCache.nRef and the contents of the -** PCache.pDirty list, return the expected value of the PCache.nPinned -** counter. This is only used in debugging builds, as follows: -** -** expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) ); -*/ -static int pcachePinnedCount(PCache *pCache){ - PgHdr *p; - int nPinned = pCache->nRef; - for(p=pCache->pDirty; p; p=p->pNext){ - if( p->nRef==0 ){ - nPinned++; - } - } - return nPinned; -} -#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */ - - -#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: @@ -27007,438 +27462,86 @@ static int pcachePinnedCount(PCache *pCache){ ** expensive_assert( pcacheCheckSynced(pCache) ); */ static int pcacheCheckSynced(PCache *pCache){ - PgHdr *p = pCache->pDirtyTail; - for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pPrev){ + 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 a page from its hash table (PCache.apHash[]). -*/ -static void pcacheRemoveFromHash(PgHdr *pPage){ - assert( pcacheMutexHeld() ); - if( pPage->pPrevHash ){ - pPage->pPrevHash->pNextHash = pPage->pNextHash; - }else{ - PCache *pCache = pPage->pCache; - u32 h = pPage->pgno % pCache->nHash; - assert( pCache->apHash[h]==pPage ); - pCache->apHash[h] = pPage->pNextHash; - } - if( pPage->pNextHash ){ - pPage->pNextHash->pPrevHash = pPage->pPrevHash; - } - pPage->pCache->nPage--; - expensive_assert( pcacheCheckHashCount(pPage->pCache) ); -} - -/* -** Insert a page into the hash table -** -** The mutex must be held by the caller. -*/ -static void pcacheAddToHash(PgHdr *pPage){ - PCache *pCache = pPage->pCache; - u32 h = pPage->pgno % pCache->nHash; - assert( pcacheMutexHeld() ); - pPage->pNextHash = pCache->apHash[h]; - pPage->pPrevHash = 0; - if( pCache->apHash[h] ){ - pCache->apHash[h]->pPrevHash = pPage; - } - pCache->apHash[h] = pPage; - pCache->nPage++; - expensive_assert( pcacheCheckHashCount(pCache) ); -} - -/* -** Attempt to increase the size the hash table to contain -** at least nHash buckets. -*/ -static int pcacheResizeHash(PCache *pCache, int nHash){ - PgHdr *p; - PgHdr **pNew; - assert( pcacheMutexHeld() ); -#ifdef SQLITE_MALLOC_SOFT_LIMIT - if( nHash*sizeof(PgHdr*)>SQLITE_MALLOC_SOFT_LIMIT ){ - nHash = SQLITE_MALLOC_SOFT_LIMIT/sizeof(PgHdr *); - } -#endif - pcacheExitMutex(); - pNew = (PgHdr **)sqlite3Malloc(sizeof(PgHdr*)*nHash); - pcacheEnterMutex(); - if( !pNew ){ - return SQLITE_NOMEM; - } - memset(pNew, 0, sizeof(PgHdr *)*nHash); - sqlite3_free(pCache->apHash); - pCache->apHash = pNew; - pCache->nHash = nHash; - pCache->nPage = 0; - - for(p=pCache->pClean; p; p=p->pNext){ - pcacheAddToHash(p); - } - for(p=pCache->pDirty; p; p=p->pNext){ - pcacheAddToHash(p); - } - return SQLITE_OK; -} - -/* -** Remove a page from a linked list that is headed by *ppHead. -** *ppHead is either PCache.pClean or PCache.pDirty. -*/ -static void pcacheRemoveFromList(PgHdr **ppHead, PgHdr *pPage){ - int isDirtyList = (ppHead==&pPage->pCache->pDirty); - assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty ); - assert( pcacheMutexHeld() || ppHead!=&pPage->pCache->pClean ); - - if( pPage->pPrev ){ - pPage->pPrev->pNext = pPage->pNext; - }else{ - assert( *ppHead==pPage ); - *ppHead = pPage->pNext; - } - if( pPage->pNext ){ - pPage->pNext->pPrev = pPage->pPrev; - } - - if( isDirtyList ){ - PCache *pCache = pPage->pCache; - assert( pPage->pNext || pCache->pDirtyTail==pPage ); - if( !pPage->pNext ){ - pCache->pDirtyTail = pPage->pPrev; - } - if( pCache->pSynced==pPage ){ - PgHdr *pSynced = pPage->pPrev; - while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){ - pSynced = pSynced->pPrev; - } - pCache->pSynced = pSynced; - } - } -} - /* -** Add a page from a linked list that is headed by *ppHead. -** *ppHead is either PCache.pClean or PCache.pDirty. +** Remove page pPage from the list of dirty pages. */ -static void pcacheAddToList(PgHdr **ppHead, PgHdr *pPage){ - int isDirtyList = (ppHead==&pPage->pCache->pDirty); - assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty ); +static void pcacheRemoveFromDirtyList(PgHdr *pPage){ + PCache *p = pPage->pCache; - if( (*ppHead) ){ - (*ppHead)->pPrev = pPage; - } - pPage->pNext = *ppHead; - pPage->pPrev = 0; - *ppHead = pPage; + assert( pPage->pDirtyNext || pPage==p->pDirtyTail ); + assert( pPage->pDirtyPrev || pPage==p->pDirty ); - if( isDirtyList ){ - PCache *pCache = pPage->pCache; - if( !pCache->pDirtyTail ){ - assert( pPage->pNext==0 ); - pCache->pDirtyTail = pPage; - } - if( !pCache->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ - pCache->pSynced = pPage; + /* 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; } -} -/* -** Remove a page from the global LRU list -*/ -static void pcacheRemoveFromLruList(PgHdr *pPage){ - assert( sqlite3_mutex_held(pcache_g.mutex) ); - assert( (pPage->flags&PGHDR_DIRTY)==0 ); - if( pPage->pCache->bPurgeable==0 ) return; - if( pPage->pNextLru ){ - assert( pcache_g.pLruTail!=pPage ); - pPage->pNextLru->pPrevLru = pPage->pPrevLru; + if( pPage->pDirtyNext ){ + pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev; }else{ - assert( pcache_g.pLruTail==pPage ); - pcache_g.pLruTail = pPage->pPrevLru; + assert( pPage==p->pDirtyTail ); + p->pDirtyTail = pPage->pDirtyPrev; } - if( pPage->pPrevLru ){ - assert( pcache_g.pLruHead!=pPage ); - pPage->pPrevLru->pNextLru = pPage->pNextLru; + if( pPage->pDirtyPrev ){ + pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext; }else{ - assert( pcache_g.pLruHead==pPage ); - pcache_g.pLruHead = pPage->pNextLru; + assert( pPage==p->pDirty ); + p->pDirty = pPage->pDirtyNext; } -} + pPage->pDirtyNext = 0; + pPage->pDirtyPrev = 0; -/* -** Add a page to the global LRU list. The page is normally added -** to the front of the list so that it will be the last page recycled. -** However, if the PGHDR_REUSE_UNLIKELY bit is set, the page is added -** to the end of the LRU list so that it will be the next to be recycled. -*/ -static void pcacheAddToLruList(PgHdr *pPage){ - assert( sqlite3_mutex_held(pcache_g.mutex) ); - assert( (pPage->flags&PGHDR_DIRTY)==0 ); - if( pPage->pCache->bPurgeable==0 ) return; - if( pcache_g.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){ - /* If reuse is unlikely. Put the page at the end of the LRU list - ** where it will be recycled sooner rather than later. - */ - assert( pcache_g.pLruHead ); - pPage->pNextLru = 0; - pPage->pPrevLru = pcache_g.pLruTail; - pcache_g.pLruTail->pNextLru = pPage; - pcache_g.pLruTail = pPage; - pPage->flags &= ~PGHDR_REUSE_UNLIKELY; - }else{ - /* If reuse is possible. the page goes at the beginning of the LRU - ** list so that it will be the last to be recycled. - */ - if( pcache_g.pLruHead ){ - pcache_g.pLruHead->pPrevLru = pPage; - } - pPage->pNextLru = pcache_g.pLruHead; - pcache_g.pLruHead = pPage; - pPage->pPrevLru = 0; - if( pcache_g.pLruTail==0 ){ - pcache_g.pLruTail = pPage; - } - } -} - -/*********************************************** Memory Allocation *********** -** -** Initialize the page cache memory pool. -** -** This must be called at start-time when no page cache lines are -** checked out. This function is not threadsafe. -*/ -SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){ - PgFreeslot *p; - sz &= ~7; - pcache_g.szSlot = sz; - pcache_g.pStart = pBuf; - pcache_g.pFree = 0; - while( n-- ){ - p = (PgFreeslot*)pBuf; - p->pNext = pcache_g.pFree; - pcache_g.pFree = p; - pBuf = (void*)&((char*)pBuf)[sz]; - } - pcache_g.pEnd = pBuf; + expensive_assert( pcacheCheckSynced(p) ); } /* -** Allocate a page cache line. Look in the page cache memory pool first -** and use an element from it first if available. If nothing is available -** in the page cache memory pool, go to the general purpose memory allocator. +** Add page pPage to the head of the dirty list (PCache1.pDirty is set to +** pPage). */ -static void *pcacheMalloc(int sz, PCache *pCache){ - assert( sqlite3_mutex_held(pcache_g.mutex) ); - if( sz<=pcache_g.szSlot && pcache_g.pFree ){ - PgFreeslot *p = pcache_g.pFree; - pcache_g.pFree = p->pNext; - sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1); - return (void*)p; - }else{ - void *p; +static void pcacheAddToDirtyList(PgHdr *pPage){ + PCache *p = pPage->pCache; - /* 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. - */ - pcacheExitMutex(); - p = sqlite3Malloc(sz); - pcacheEnterMutex(); + assert( pPage->pDirtyNext==0 && pPage->pDirtyPrev==0 && p->pDirty!=pPage ); - if( p ){ - sz = sqlite3MallocSize(p); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); - } - return p; + pPage->pDirtyNext = p->pDirty; + if( pPage->pDirtyNext ){ + assert( pPage->pDirtyNext->pDirtyPrev==0 ); + pPage->pDirtyNext->pDirtyPrev = pPage; } -} -SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){ - void *p; - pcacheEnterMutex(); - p = pcacheMalloc(sz, 0); - pcacheExitMutex(); - return p; -} - -/* -** Release a pager memory allocation -*/ -static void pcacheFree(void *p){ - assert( sqlite3_mutex_held(pcache_g.mutex) ); - if( p==0 ) return; - if( p>=pcache_g.pStart && ppNext = pcache_g.pFree; - pcache_g.pFree = pSlot; - }else{ - int iSize = sqlite3MallocSize(p); - sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize); - sqlite3_free(p); - } -} -SQLITE_PRIVATE void sqlite3PageFree(void *p){ - pcacheEnterMutex(); - pcacheFree(p); - pcacheExitMutex(); -} - -/* -** Allocate a new page. -*/ -static PgHdr *pcachePageAlloc(PCache *pCache){ - PgHdr *p; - int sz = sizeof(*p) + pCache->szPage + pCache->szExtra; - assert( sqlite3_mutex_held(pcache_g.mutex) ); - p = pcacheMalloc(sz, pCache); - if( p==0 ) return 0; - memset(p, 0, sizeof(PgHdr)); - p->pData = (void*)&p[1]; - p->pExtra = (void*)&((char*)p->pData)[pCache->szPage]; - if( pCache->bPurgeable ){ - pcache_g.nCurrentPage++; + p->pDirty = pPage; + if( !p->pDirtyTail ){ + p->pDirtyTail = pPage; } - return p; -} - -/* -** Deallocate a page -*/ -static void pcachePageFree(PgHdr *p){ - assert( sqlite3_mutex_held(pcache_g.mutex) ); - if( p->pCache->bPurgeable ){ - pcache_g.nCurrentPage--; - } - pcacheFree(p->apSave[0]); - pcacheFree(p->apSave[1]); - pcacheFree(p); -} - -#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT -/* -** Return the number of bytes that will be returned to the heap when -** the argument is passed to pcachePageFree(). -*/ -static int pcachePageSize(PgHdr *p){ - assert( sqlite3_mutex_held(pcache_g.mutex) ); - assert( !pcache_g.pStart ); - assert( p->apSave[0]==0 ); - assert( p->apSave[1]==0 ); - assert( p && p->pCache ); - return sqlite3MallocSize(p); -} -#endif - -/* -** Attempt to 'recycle' a page from the global LRU list. Only clean, -** unreferenced pages from purgeable caches are eligible for recycling. -** -** This function removes page pcache.pLruTail from the global LRU list, -** and from the hash-table and PCache.pClean list of the owner pcache. -** There should be no other references to the page. -** -** A pointer to the recycled page is returned, or NULL if no page is -** eligible for recycling. -*/ -static PgHdr *pcacheRecyclePage(){ - PgHdr *p = 0; - assert( sqlite3_mutex_held(pcache_g.mutex) ); - - if( (p=pcache_g.pLruTail) ){ - assert( (p->flags&PGHDR_DIRTY)==0 ); - pcacheRemoveFromLruList(p); - pcacheRemoveFromHash(p); - pcacheRemoveFromList(&p->pCache->pClean, p); + if( !p->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){ + p->pSynced = pPage; } - - return p; + expensive_assert( pcacheCheckSynced(p) ); } /* -** Obtain space for a page. Try to recycle an old page if the limit on the -** number of pages has been reached. If the limit has not been reached or -** there are no pages eligible for recycling, allocate a new page. -** -** Return a pointer to the new page, or NULL if an OOM condition occurs. +** 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 int pcacheRecycleOrAlloc(PCache *pCache, PgHdr **ppPage){ - PgHdr *p = 0; - - int szPage = pCache->szPage; - int szExtra = pCache->szExtra; - - assert( pcache_g.isInit ); - assert( sqlite3_mutex_held(pcache_g.mutex) ); - - *ppPage = 0; - - /* If we have reached either the global or the local limit for - ** pinned+dirty pages, and there is at least one dirty page, - ** invoke the xStress callback to cause a page to become clean. - */ - expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) ); - expensive_assert( pcacheCheckSynced(pCache) ); - if( pCache->xStress - && pCache->pDirty - && (pCache->nPinned>=(pcache_g.nMaxPage+pCache->nMin-pcache_g.nMinPage) - || pCache->nPinned>=pCache->nMax) - ){ - PgHdr *pPg; - assert(pCache->pDirtyTail); - - for(pPg=pCache->pSynced; - pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC)); - pPg=pPg->pPrev - ); - if( !pPg ){ - for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pPrev); - } - if( pPg ){ - int rc; - pcacheExitMutex(); - rc = pCache->xStress(pCache->pStress, pPg); - pcacheEnterMutex(); - if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ - return rc; - } +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); } - - /* If either the local or the global page limit has been reached, - ** try to recycle a page. - */ - if( pCache->bPurgeable && (pCache->nPage>=pCache->nMax-1 || - pcache_g.nCurrentPage>=pcache_g.nMaxPage) ){ - p = pcacheRecyclePage(); - } - - /* If a page has been recycled but it is the wrong size, free it. */ - if( p && (p->pCache->szPage!=szPage || p->pCache->szPage!=szExtra) ){ - pcachePageFree(p); - p = 0; - } - - if( !p ){ - p = pcachePageAlloc(pCache); - } - - *ppPage = p; - return (p?SQLITE_OK:SQLITE_NOMEM); } /*************************************************** General Interfaces ****** @@ -27447,19 +27550,15 @@ static int pcacheRecycleOrAlloc(PCache *pCache, PgHdr **ppPage){ ** functions are threadsafe. */ SQLITE_PRIVATE int sqlite3PcacheInitialize(void){ - assert( pcache_g.isInit==0 ); - memset(&pcache_g, 0, sizeof(pcache)); - if( sqlite3GlobalConfig.bCoreMutex ){ - /* No need to check the return value of sqlite3_mutex_alloc(). - ** Allocating a static mutex cannot fail. - */ - pcache_g.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU); + if( sqlite3GlobalConfig.pcache.xInit==0 ){ + sqlite3PCacheSetDefault(); } - pcache_g.isInit = 1; - return SQLITE_OK; + return sqlite3GlobalConfig.pcache.xInit(sqlite3GlobalConfig.pcache.pArg); } SQLITE_PRIVATE void sqlite3PcacheShutdown(void){ - memset(&pcache_g, 0, sizeof(pcache)); + if( sqlite3GlobalConfig.pcache.xShutdown ){ + sqlite3GlobalConfig.pcache.xShutdown(sqlite3GlobalConfig.pcache.pArg); + } } /* @@ -27468,44 +27567,39 @@ SQLITE_PRIVATE void sqlite3PcacheShutdown(void){ 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. +** 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 */ - void (*xDestroy)(PgHdr*), /* Called to destroy a page */ int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */ void *pStress, /* Argument to xStress */ PCache *p /* Preallocated space for the PCache */ ){ - assert( pcache_g.isInit ); memset(p, 0, sizeof(PCache)); p->szPage = szPage; p->szExtra = szExtra; p->bPurgeable = bPurgeable; - p->xDestroy = xDestroy; p->xStress = xStress; p->pStress = pStress; p->nMax = 100; p->nMin = 10; - - pcacheEnterMutex(); - if( bPurgeable ){ - pcache_g.nMaxPage += p->nMax; - pcache_g.nMinPage += p->nMin; - } - - pcacheExitMutex(); } /* -** Change the page size for PCache object. This can only happen -** when the cache is empty. +** 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->nPage==0); + assert( pCache->nRef==0 && pCache->pDirty==0 ); + if( pCache->pCache ){ + sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache); + pCache->pCache = 0; + } pCache->szPage = szPage; } @@ -27518,95 +27612,102 @@ SQLITE_PRIVATE int sqlite3PcacheFetch( int createFlag, /* If true, create page if it does not exist already */ PgHdr **ppPage /* Write the page here */ ){ - int rc = SQLITE_OK; PgHdr *pPage = 0; + int eCreate; - assert( pcache_g.isInit ); assert( pCache!=0 ); assert( pgno>0 ); - expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) ); - - pcacheEnterMutex(); - - /* Search the hash table for the requested page. Exit early if it is found. */ - if( pCache->apHash ){ - u32 h = pgno % pCache->nHash; - for(pPage=pCache->apHash[h]; pPage; pPage=pPage->pNextHash){ - if( pPage->pgno==pgno ){ - if( pPage->nRef==0 ){ - if( 0==(pPage->flags&PGHDR_DIRTY) ){ - pcacheRemoveFromLruList(pPage); - pCache->nPinned++; - } - pCache->nRef++; - } - pPage->nRef++; - break; - } + + /* 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 && createFlag ){ - if( pCache->nHash<=pCache->nPage ){ - rc = pcacheResizeHash(pCache, pCache->nHash<256 ? 256 : pCache->nHash*2); + 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( rc==SQLITE_OK ){ - rc = pcacheRecycleOrAlloc(pCache, &pPage); + if( pPg ){ + int rc; + rc = pCache->xStress(pCache->pStress, pPg); + if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ + return rc; + } } - if( rc==SQLITE_OK ){ - pPage->pPager = 0; - pPage->flags = 0; - pPage->pDirty = 0; - pPage->pgno = pgno; - pPage->pCache = pCache; - pPage->nRef = 1; + + pPage = sqlite3GlobalConfig.pcache.xFetch(pCache->pCache, pgno, 2); + } + + if( pPage ){ + if( 0==pPage->nRef ){ pCache->nRef++; - pCache->nPinned++; - pcacheAddToList(&pCache->pClean, pPage); - pcacheAddToHash(pPage); + } + 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; } } - - pcacheExitMutex(); - *ppPage = pPage; - expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) ); - assert( pPage || !createFlag || rc!=SQLITE_OK ); - return rc; + return (pPage==0 && eCreate) ? SQLITE_NOMEM : SQLITE_OK; } /* -** Dereference a page. When the reference count reaches zero, -** move the page to the LRU list if it is clean. +** 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; - if( p->pCache->xDestroy ){ - p->pCache->xDestroy(p); - } pCache->nRef--; if( (p->flags&PGHDR_DIRTY)==0 ){ - pCache->nPinned--; - pcacheEnterMutex(); - if( pcache_g.nCurrentPage>pcache_g.nMaxPage ){ - pcacheRemoveFromList(&pCache->pClean, p); - pcacheRemoveFromHash(p); - pcachePageFree(p); - }else{ - pcacheAddToLruList(p); - } - pcacheExitMutex(); + pcacheUnpin(p); }else{ - /* Move the page to the head of the caches dirty list. */ - pcacheRemoveFromList(&pCache->pDirty, p); - pcacheAddToList(&pCache->pDirty, p); + /* 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++; @@ -27620,58 +27721,43 @@ SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){ SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){ PCache *pCache; assert( p->nRef==1 ); - assert( 0==(p->flags&PGHDR_DIRTY) ); + if( p->flags&PGHDR_DIRTY ){ + pcacheRemoveFromDirtyList(p); + } pCache = p->pCache; pCache->nRef--; - pCache->nPinned--; - pcacheEnterMutex(); - pcacheRemoveFromList(&pCache->pClean, p); - pcacheRemoveFromHash(p); - pcachePageFree(p); - pcacheExitMutex(); + 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 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; - if( p->flags & PGHDR_DIRTY ) return; - assert( (p->flags & PGHDR_DIRTY)==0 ); assert( p->nRef>0 ); - pCache = p->pCache; - pcacheEnterMutex(); - pcacheRemoveFromList(&pCache->pClean, p); - pcacheAddToList(&pCache->pDirty, p); - pcacheExitMutex(); - p->flags |= PGHDR_DIRTY; -} - -static void pcacheMakeClean(PgHdr *p){ - PCache *pCache = p->pCache; - assert( p->apSave[0]==0 && p->apSave[1]==0 ); - assert( p->flags & PGHDR_DIRTY ); - pcacheRemoveFromList(&pCache->pDirty, p); - pcacheAddToList(&pCache->pClean, p); - p->flags &= ~PGHDR_DIRTY; - if( p->nRef==0 ){ - pcacheAddToLruList(p); - pCache->nPinned--; + if( 0==(p->flags & PGHDR_DIRTY) ){ + pCache = p->pCache; + p->flags |= PGHDR_DIRTY; + pcacheAddToDirtyList( p); } - expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) ); } /* -** Make sure the page is marked as clean. If it isn't clean already, +** 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) ){ - pcacheEnterMutex(); - pcacheMakeClean(p); - pcacheExitMutex(); + pcacheRemoveFromDirtyList(p); + p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC); + if( p->nRef==0 ){ + pcacheUnpin(p); + } } } @@ -27680,114 +27766,62 @@ SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){ */ SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){ PgHdr *p; - pcacheEnterMutex(); while( (p = pCache->pDirty)!=0 ){ - assert( p->apSave[0]==0 && p->apSave[1]==0 ); - pcacheRemoveFromList(&pCache->pDirty, p); - p->flags &= ~PGHDR_DIRTY; - pcacheAddToList(&pCache->pClean, p); - if( p->nRef==0 ){ - pcacheAddToLruList(p); - pCache->nPinned--; - } + sqlite3PcacheMakeClean(p); } - sqlite3PcacheAssertFlags(pCache, 0, PGHDR_DIRTY); - expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) ); - pcacheExitMutex(); } /* -** Change the page number of page p to newPgno. If newPgno is 0, then the -** page object is added to the clean-list and the PGHDR_REUSE_UNLIKELY -** flag set. +** Clear the PGHDR_NEED_SYNC flag from all dirty pages. */ -SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ - assert( p->nRef>0 ); - pcacheEnterMutex(); - pcacheRemoveFromHash(p); - p->pgno = newPgno; - if( newPgno==0 ){ - pcacheFree(p->apSave[0]); - pcacheFree(p->apSave[1]); - p->apSave[0] = 0; - p->apSave[1] = 0; - if( (p->flags & PGHDR_DIRTY) ){ - pcacheMakeClean(p); - } - p->flags = PGHDR_REUSE_UNLIKELY; +SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){ + PgHdr *p; + for(p=pCache->pDirty; p; p=p->pDirtyNext){ + p->flags &= ~PGHDR_NEED_SYNC; } - pcacheAddToHash(p); - pcacheExitMutex(); + pCache->pSynced = pCache->pDirtyTail; } /* -** Remove all content from a page cache +** Change the page number of page p to newPgno. */ -static void pcacheClear(PCache *pCache){ - PgHdr *p, *pNext; - assert( sqlite3_mutex_held(pcache_g.mutex) ); - for(p=pCache->pClean; p; p=pNext){ - pNext = p->pNext; - pcacheRemoveFromLruList(p); - pcachePageFree(p); - } - for(p=pCache->pDirty; p; p=pNext){ - pNext = p->pNext; - pcachePageFree(p); +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); } - pCache->pClean = 0; - pCache->pDirty = 0; - pCache->pDirtyTail = 0; - pCache->nPage = 0; - pCache->nPinned = 0; - memset(pCache->apHash, 0, pCache->nHash*sizeof(pCache->apHash[0])); } - /* -** Drop every cache entry whose page number is greater than "pgno". +** 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){ - PgHdr *p, *pNext; - PgHdr *pDirty = pCache->pDirty; - pcacheEnterMutex(); - for(p=pCache->pClean; p||pDirty; p=pNext){ - if( !p ){ - p = pDirty; - pDirty = 0; - } - pNext = p->pNext; - if( p->pgno>pgno ){ - if( p->nRef==0 ){ - pcacheRemoveFromHash(p); - if( p->flags&PGHDR_DIRTY ){ - pcacheRemoveFromList(&pCache->pDirty, p); - pCache->nPinned--; - }else{ - pcacheRemoveFromList(&pCache->pClean, p); - pcacheRemoveFromLruList(p); - } - pcachePageFree(p); - }else{ - /* If there are references to the page, it cannot be freed. In this - ** case, zero the page content instead. - */ - memset(p->pData, 0, pCache->szPage); + 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); } } - } - pcacheExitMutex(); -} - -/* -** If there are currently more than pcache.nMaxPage pages allocated, try -** to recycle pages to reduce the number allocated to pcache.nMaxPage. -*/ -static void pcacheEnforceMaxPage(){ - PgHdr *p; - assert( sqlite3_mutex_held(pcache_g.mutex) ); - while( pcache_g.nCurrentPage>pcache_g.nMaxPage && (p = pcacheRecyclePage()) ){ - pcachePageFree(p); + if( pgno==0 && pCache->pPage1 ){ + memset(pCache->pPage1->pData, 0, pCache->szPage); + pgno = 1; + } + sqlite3GlobalConfig.pcache.xTruncate(pCache->pCache, pgno+1); } } @@ -27795,117 +27829,22 @@ static void pcacheEnforceMaxPage(){ ** Close a cache. */ SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){ - pcacheEnterMutex(); - - /* Free all the pages used by this pager and remove them from the LRU list. */ - pcacheClear(pCache); - if( pCache->bPurgeable ){ - pcache_g.nMaxPage -= pCache->nMax; - pcache_g.nMinPage -= pCache->nMin; - pcacheEnforceMaxPage(); - } - sqlite3_free(pCache->apHash); - pcacheExitMutex(); -} - -/* -** Preserve the content of the page. It is assumed that the content -** has not been preserved already. -** -** If idJournal==0 then this is for the overall transaction. -** If idJournal==1 then this is for the statement journal. -** -** This routine is used for in-memory databases only. -** -** Return SQLITE_OK or SQLITE_NOMEM if a memory allocation fails. -*/ -SQLITE_PRIVATE int sqlite3PcachePreserve(PgHdr *p, int idJournal){ - void *x; - int sz; - assert( p->pCache->bPurgeable==0 ); - assert( p->apSave[idJournal]==0 ); - sz = p->pCache->szPage; - p->apSave[idJournal] = x = sqlite3PageMalloc( sz ); - if( x==0 ) return SQLITE_NOMEM; - memcpy(x, p->pData, sz); - return SQLITE_OK; -} - -/* -** Commit a change previously preserved. -*/ -SQLITE_PRIVATE void sqlite3PcacheCommit(PCache *pCache, int idJournal){ - PgHdr *p; - int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff; - pcacheEnterMutex(); /* Mutex is required to call pcacheFree() */ - for(p=pCache->pDirty; p; p=p->pNext){ - if( p->apSave[idJournal] ){ - pcacheFree(p->apSave[idJournal]); - p->apSave[idJournal] = 0; - } - p->flags &= mask; - } - pcacheExitMutex(); -} - -/* -** Rollback a change previously preserved. -*/ -SQLITE_PRIVATE void sqlite3PcacheRollback( - PCache *pCache, /* Pager cache */ - int idJournal, /* Which copy to rollback to */ - void (*xReiniter)(PgHdr*) /* Called on each rolled back page */ -){ - PgHdr *p; - int sz; - int mask = idJournal==0 ? ~PGHDR_IN_JOURNAL : 0xffffff; - pcacheEnterMutex(); /* Mutex is required to call pcacheFree() */ - sz = pCache->szPage; - for(p=pCache->pDirty; p; p=p->pNext){ - if( p->apSave[idJournal] ){ - memcpy(p->pData, p->apSave[idJournal], sz); - pcacheFree(p->apSave[idJournal]); - p->apSave[idJournal] = 0; - if( xReiniter ){ - xReiniter(p); - } - } - p->flags &= mask; - } - pcacheExitMutex(); -} - -#ifndef NDEBUG -/* -** Assert flags settings on all pages. Debugging only. -*/ -SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache *pCache, int trueMask, int falseMask){ - PgHdr *p; - for(p=pCache->pDirty; p; p=p->pNext){ - assert( (p->flags&trueMask)==trueMask ); - assert( (p->flags&falseMask)==0 ); - } - for(p=pCache->pClean; p; p=p->pNext){ - assert( (p->flags&trueMask)==trueMask ); - assert( (p->flags&falseMask)==0 ); + if( pCache->pCache ){ + sqlite3GlobalConfig.pcache.xDestroy(pCache->pCache); } } -#endif /* ** Discard the contents of the cache. */ SQLITE_PRIVATE int sqlite3PcacheClear(PCache *pCache){ - assert(pCache->nRef==0); - pcacheEnterMutex(); - pcacheClear(pCache); - pcacheExitMutex(); + sqlite3PcacheTruncate(pCache, 0); return SQLITE_OK; } /* ** Merge two lists of pages connected by pDirty and in pgno order. -** Do not both fixing the pPrevDirty pointers. +** Do not both fixing the pDirtyPrev pointers. */ static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ PgHdr result, *pTail; @@ -27933,7 +27872,7 @@ static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){ /* ** Sort the list of pages in accending order by pgno. Pages are -** connected by pDirty pointers. The pPrevDirty pointers are +** connected by pDirty pointers. The pDirtyPrev pointers are ** corrupted by this sort. */ #define N_SORT_BUCKET_ALLOC 25 @@ -27982,93 +27921,758 @@ static PgHdr *pcacheSortDirtyList(PgHdr *pIn){ */ SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){ PgHdr *p; - for(p=pCache->pDirty; p; p=p->pNext){ - p->pDirty = p->pNext; + for(p=pCache->pDirty; p; p=p->pDirtyNext){ + p->pDirty = p->pDirtyNext; } return pcacheSortDirtyList(pCache->pDirty); } /* -** Return the total number of outstanding page references. +** 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){ - assert( pCache->nPage>=0 ); - return pCache->nPage; + int nPage = 0; + if( pCache->pCache ){ + nPage = sqlite3GlobalConfig.pcache.xPagecount(pCache->pCache); + } + return nPage; } -#ifdef SQLITE_CHECK_PAGES +#ifdef SQLITE_TEST /* -** This function is used by the pager.c module to iterate through all -** pages in the cache. At present, this is only required if the -** SQLITE_CHECK_PAGES macro (used for debugging) is specified. +** Get the suggested cache-size value. */ -SQLITE_PRIVATE void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)){ - PgHdr *p; - for(p=pCache->pClean; p; p=p->pNext){ - xIter(p); +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); } - for(p=pCache->pDirty; p; p=p->pNext){ - xIter(p); +} + +#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 -/* -** Set flags on all pages in the page cache + +/************** 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: pcache1.c,v 1.3 2008/11/19 09:05:27 danielk1977 Exp $ */ -SQLITE_PRIVATE void sqlite3PcacheClearFlags(PCache *pCache, int mask){ - PgHdr *p; - /* Obtain the global mutex before modifying any PgHdr.flags variables - ** or traversing the LRU list. - */ - pcacheEnterMutex(); - mask = ~mask; - for(p=pCache->pDirty; p; p=p->pNext){ - p->flags &= mask; +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 && ppNext = pcache1.pFree; + pcache1.pFree = pSlot; + }else{ + int iSize = sqlite3MallocSize(p); + sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize); + sqlite3_free(p); } - for(p=pCache->pClean; p; p=p->pNext){ - p->flags &= mask; +} + +/* +** 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; +} - if( 0==(mask&PGHDR_NEED_SYNC) ){ - pCache->pSynced = pCache->pDirtyTail; - assert( !pCache->pSynced || (pCache->pSynced->flags&PGHDR_NEED_SYNC)==0 ); +/* +** Free a page object allocated by pcache1AllocPage(). +*/ +static void pcache1FreePage(PgHdr1 *p){ + if( p ){ + if( p->pCache->bPurgeable ){ + pcache1.nCurrentPage--; + } + pcache1Free(p); } +} - pcacheExitMutex(); +/* +** 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; } /* -** Set the suggested cache-size value. +** Free an allocated buffer obtained from sqlite3PageMalloc(). */ -SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){ - return pCache->nMax; +SQLITE_PRIVATE void sqlite3PageFree(void *p){ + pcache1EnterMutex(); + pcache1Free(p); + pcache1LeaveMutex(); } +/******************************************************************************/ +/******** General Implementation Functions ************************************/ + /* -** Set the suggested cache-size value. +** 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. */ -SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ - if( mxPage<10 ){ - mxPage = 10; +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; inHash; 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; hnHash; 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 ){ - pcacheEnterMutex(); - pcache_g.nMaxPage -= pCache->nMax; - pcache_g.nMaxPage += mxPage; - pcacheEnforceMaxPage(); - pcacheExitMutex(); + pcache1EnterMutex(); + pcache1.nMaxPage += (nMax - pCache->nMax); + pCache->nMax = nMax; + pcache1EnforceMaxPage(); + pcache1LeaveMutex(); } - pCache->nMax = mxPage; +} + +/* +** 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 @@ -28083,40 +28687,45 @@ SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){ */ SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){ int nFree = 0; - if( pcache_g.pStart==0 ){ - PgHdr *p; - pcacheEnterMutex(); - while( (nReq<0 || nFreepNextLru){ + for(p=pcache1.pLruHead; p; p=p->pLruNext){ nRecyclable++; } - - *pnCurrent = pcache_g.nCurrentPage; - *pnMax = pcache_g.nMaxPage; - *pnMin = pcache_g.nMinPage; + *pnCurrent = pcache1.nCurrentPage; + *pnMax = pcache1.nMaxPage; + *pnMin = pcache1.nMinPage; *pnRecyclable = nRecyclable; } #endif -/************** End of pcache.c **********************************************/ +/************** End of pcache1.c *********************************************/ /************** Begin file pager.c *******************************************/ /* ** 2001 September 15 @@ -28138,7 +28747,7 @@ SQLITE_PRIVATE void sqlite3PcacheStats( ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.493 2008/09/19 09:14:44 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.506.2.1 2008/11/26 14:55:02 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO @@ -28295,11 +28904,12 @@ 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 */ - 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() */ + 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 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 */ @@ -28316,13 +28926,14 @@ struct Pager { 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*/ - BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ + int (*xBusyHandler)(void*); /* Function to call when busy */ + void *pBusyHandlerArg; /* Context argument for xBusyHandler */ 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() */ - int sectorSize; /* Assumed sector size during rollback */ + u32 sectorSize; /* Assumed sector size during rollback */ #ifdef SQLITE_TEST int nHit, nMiss; /* Cache hits and missing */ int nRead, nWrite; /* Database pages read/written */ @@ -28414,7 +29025,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) ((PENDING_BYTE/((x)->pageSize))+1) +#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1)) /* ** The maximum legal page number is (2^31 - 1). @@ -28428,11 +29039,11 @@ static const unsigned char aJournalMagic[] = { */ static int pageInStatement(PgHdr *pPg){ Pager *pPager = pPg->pPager; - if( MEMDB ){ - return pPg->apSave[1]!=0; - }else{ - return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno); - } + return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno); +} + +static int pageInJournal(PgHdr *pPg){ + return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno); } /* @@ -28577,7 +29188,7 @@ static u32 pager_datahash(int nByte, unsigned char *pData){ static u32 pager_pagehash(PgHdr *pPage){ return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData); } -static u32 pager_set_pagehash(PgHdr *pPage){ +static void pager_set_pagehash(PgHdr *pPage){ pPage->pageHash = pager_pagehash(pPage); } @@ -28589,7 +29200,7 @@ static u32 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 || MEMDB + assert( !pPg->pageHash || pPager->errCode || (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) ); } @@ -28614,7 +29225,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, int nMaster){ +static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){ int rc; u32 len; i64 szJ; @@ -28746,8 +29357,8 @@ static int zeroJournalHdr(Pager *pPager, int doTruncate){ static int writeJournalHdr(Pager *pPager){ int rc = SQLITE_OK; char *zHeader = pPager->pTmpSpace; - int nHeader = pPager->pageSize; - int nWrite; + u32 nHeader = pPager->pageSize; + u32 nWrite; if( nHeader>JOURNAL_HDR_SZ(pPager) ){ nHeader = JOURNAL_HDR_SZ(pPager); @@ -28783,7 +29394,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) + if( (pPager->noSync) || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY) || (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND) ){ put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff); @@ -28879,8 +29490,12 @@ 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, (u32 *)&pPager->sectorSize); + rc = read32bits(pPager->jfd, jrnlOff+12, &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; @@ -28915,7 +29530,8 @@ 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( !zMaster || pPager->setMaster ) return SQLITE_OK; + if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ) return SQLITE_OK; pPager->setMaster = 1; len = strlen(zMaster); @@ -28999,50 +29615,46 @@ static void pager_reset(Pager *pPager){ */ static void pager_unlock(Pager *pPager){ if( !pPager->exclusiveMode ){ - 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; - sqlite3BitvecDestroy(pPager->pAlwaysRollback); - pPager->pAlwaysRollback = 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; - } + 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 || pPager->errCode==SQLITE_OK ){ - pPager->state = PAGER_UNLOCK; - pPager->changeCountDone = 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->state = PAGER_UNLOCK; + pPager->changeCountDone = 0; } } @@ -29080,7 +29692,6 @@ static void pagerUnlockAndRollback(Pager *p){ static int pager_end_transaction(Pager *pPager, int hasMaster){ int rc = SQLITE_OK; int rc2 = SQLITE_OK; - assert( !MEMDB ); if( pPager->statestmtOpen = 0; } if( pPager->journalOpen ){ - if( pPager->exclusiveMode + 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 || pPager->journalMode==PAGER_JOURNALMODE_PERSIST ){ rc = zeroJournalHdr(pPager, hasMaster); @@ -29098,6 +29720,7 @@ 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 ){ @@ -29108,13 +29731,10 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){ pPager->pInJournal = 0; sqlite3BitvecDestroy(pPager->pAlwaysRollback); pPager->pAlwaysRollback = 0; - sqlite3PcacheCleanAll(pPager->pPCache); #ifdef SQLITE_CHECK_PAGES - sqlite3PcacheIterate(pPager->pPCache, pager_set_pagehash); + sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); #endif - sqlite3PcacheClearFlags(pPager->pPCache, - PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC - ); + sqlite3PcacheCleanAll(pPager->pPCache); pPager->dirtyCache = 0; pPager->nRec = 0; }else{ @@ -29131,7 +29751,9 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){ pPager->setMaster = 0; pPager->needSync = 0; /* lruListSetFirstSynced(pPager); */ - pPager->dbSize = -1; + if( !MEMDB ){ + pPager->dbSizeValid = 0; + } pPager->dbModified = 0; return (rc==SQLITE_OK?rc2:rc); @@ -29167,9 +29789,6 @@ 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. @@ -29279,7 +29898,9 @@ static int pager_playback_one_page( if( pPager->xReiniter ){ pPager->xReiniter(pPg); } - if( isMainJrnl ) makeClean(pPg); + if( isMainJrnl ){ + sqlite3PcacheMakeClean(pPg); + } #ifdef SQLITE_CHECK_PAGES pPg->pageHash = pager_pagehash(pPg); #endif @@ -29418,7 +30039,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, int nPage){ +static int pager_truncate(Pager *pPager, Pgno nPage){ int rc = SQLITE_OK; if( pPager->state>=PAGER_EXCLUSIVE && pPager->fd->pMethods ){ i64 currentSize, newSize; @@ -29614,7 +30235,7 @@ static int pager_playback(Pager *pPager, int isHot){ ** 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; + rc = SQLITE_CORRUPT_BKPT; goto end_playback; } } @@ -29631,7 +30252,7 @@ end_playback: if( rc==SQLITE_OK ){ rc = pager_end_transaction(pPager, zMaster[0]!='\0'); } - if( rc==SQLITE_OK && zMaster[0] ){ + if( rc==SQLITE_OK && zMaster[0] && res ){ /* If there was a master journal and this routine will return success, ** see if it is possible to delete the master journal. */ @@ -29781,7 +30402,7 @@ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){ - pPager->noSync = level==1 || pPager->tempFile || MEMDB; + pPager->noSync = level==1 || pPager->tempFile; pPager->fullSync = level==3 && !pPager->tempFile; pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL); if( pPager->noSync ) pPager->needSync = 0; @@ -29842,7 +30463,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen( sqlite3_vfs *pVfs, /* The virtual file system to use */ Pager **ppPager, /* Return the Pager structure here */ const char *zFilename, /* Name of the database file to open */ - void (*xDesc)(DbPage*), /* Page destructor function */ int nExtra, /* Extra bytes append to each in-memory page */ int flags, /* flags controlling this file */ int vfsFlags /* flags passed through to sqlite3_vfs.xOpen() */ @@ -29856,12 +30476,18 @@ SQLITE_PRIVATE int sqlite3PagerOpen( int readOnly = 0; int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; int noReadlock = (flags & PAGER_NO_READLOCK)!=0; - int journalFileSize = sqlite3JournalSize(pVfs); + int journalFileSize; int pcacheSize = sqlite3PcacheSize(); 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; @@ -29879,7 +30505,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen( if( strcmp(zFilename,":memory:")==0 ){ memDb = 1; zPathname[0] = 0; - useJournal = 0; }else #endif { @@ -29897,7 +30522,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen( sizeof(*pPager) + /* Pager structure */ pcacheSize + /* PCache object */ journalFileSize + /* The journal file structure */ - pVfs->szOsFile * 3 + /* The main db and two journal files */ + pVfs->szOsFile + /* The main db file */ + journalFileSize * 2 + /* The two journal files */ 3*nPathname + 40 /* zFilename, zDirectory, zJournal */ ); if( !pPager ){ @@ -29908,9 +30534,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen( pPtr = ((u8 *)&pPager[1]) + pcacheSize; pPager->vfsFlags = vfsFlags; pPager->fd = (sqlite3_file*)&pPtr[pVfs->szOsFile*0]; - 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->stfd = (sqlite3_file*)&pPtr[pVfs->szOsFile]; + pPager->jfd = (sqlite3_file*)&pPtr[pVfs->szOsFile+journalFileSize]; + pPager->zFilename = (char*)&pPtr[pVfs->szOsFile+2*journalFileSize]; pPager->zDirectory = &pPager->zFilename[nPathname+1]; pPager->zJournal = &pPager->zDirectory[nPathname+1]; pPager->pVfs = pVfs; @@ -29922,7 +30548,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( /* Open the pager file. */ if( zFilename && zFilename[0] && !memDb ){ - if( nPathname>(pVfs->mxPathname - sizeof("-journal")) ){ + if( nPathname>(pVfs->mxPathname - (int)sizeof("-journal")) ){ rc = SQLITE_CANTOPEN; }else{ int fout = 0; @@ -29960,10 +30586,14 @@ SQLITE_PRIVATE int sqlite3PagerOpen( } } } - }else if( !memDb ){ + }else{ /* 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; @@ -29984,7 +30614,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); } nExtra = FORCE_ALIGNMENT(nExtra); - sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, xDesc, + sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, !memDb?pagerStress:0, (void *)pPager, pPager->pPCache); PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename); @@ -30009,7 +30639,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( /* pPager->stmtOpen = 0; */ /* pPager->stmtInUse = 0; */ /* pPager->nRef = 0; */ - pPager->dbSize = memDb-1; + pPager->dbSizeValid = memDb; pPager->pageSize = szPageDflt; /* pPager->stmtSize = 0; */ /* pPager->stmtJSize = 0; */ @@ -30035,11 +30665,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen( /* pPager->pLast = 0; */ pPager->nExtra = nExtra; pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; - assert(pPager->fd->pMethods||memDb||tempFile); - if( !memDb ){ - setSectorSize(pPager); + assert(pPager->fd->pMethods||tempFile); + setSectorSize(pPager); + if( memDb ){ + pPager->journalMode = PAGER_JOURNALMODE_MEMORY; } - /* pPager->pBusyHandler = 0; */ + /* pPager->xBusyHandler = 0; */ + /* pPager->pBusyHandlerArg = 0; */ /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ *ppPager = pPager; return SQLITE_OK; @@ -30048,8 +30680,13 @@ SQLITE_PRIVATE int sqlite3PagerOpen( /* ** Set the busy handler function. */ -SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){ - pPager->pBusyHandler = pBusyHandler; +SQLITE_PRIVATE void sqlite3PagerSetBusyhandler( + Pager *pPager, + int (*xBusyHandler)(void *), + void *pBusyHandlerArg +){ + pPager->xBusyHandler = xBusyHandler; + pPager->pBusyHandlerArg = pBusyHandlerArg; } /* @@ -30158,7 +30795,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(MEMDB||pPager->fd->pMethods||pPager->tempFile); + assert(pPager->fd->pMethods||pPager->tempFile); if( pPager->fd->pMethods ){ IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) rc = sqlite3OsRead(pPager->fd, pDest, N, 0); @@ -30186,7 +30823,7 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){ rc = pPager->errCode; return rc; } - if( pPager->dbSize>=0 ){ + if( pPager->dbSizeValid ){ n = pPager->dbSize; } else { assert(pPager->fd->pMethods||pPager->tempFile); @@ -30202,6 +30839,7 @@ 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) ){ @@ -30254,15 +30892,14 @@ 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->dbSize<0 || MEMDB ); + assert( pPager->state>=PAGER_SHARED || pPager->dbSizeValid==0 ); 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 && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); + }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) ); if( rc==SQLITE_OK ){ pPager->state = locktype; IOTRACE(("LOCK %p %d\n", pPager, locktype)) @@ -30276,25 +30913,19 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){ */ SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){ int rc = SQLITE_OK; - assert( pPager->state>=PAGER_SHARED || MEMDB ); - + assert( pPager->state>=PAGER_SHARED ); sqlite3PagerPagecount(pPager, 0); if( pPager->errCode ){ rc = pPager->errCode; - }else if( nPage<(unsigned)pPager->dbSize ){ - if( MEMDB ){ - pPager->dbSize = nPage; - pager_truncate_cache(pPager); - }else{ - 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); - } + }else if( nPagedbSize ){ + 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); } } @@ -30322,7 +30953,9 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){ pPager->errCode = 0; pPager->exclusiveMode = 0; pager_reset(pPager); - pagerUnlockAndRollback(pPager); + if( !MEMDB ){ + pagerUnlockAndRollback(pPager); + } enable_simulated_io_errors(); sqlite3EndBenignMalloc(); PAGERTRACE2("CLOSE %d\n", PAGERID(pPager)); @@ -30398,7 +31031,8 @@ static int syncJournal(Pager *pPager){ ** (assuming there is a journal and it needs to be synced.) */ if( pPager->needSync ){ - if( !pPager->tempFile ){ + assert( !pPager->tempFile ); + if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){ int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); assert( pPager->journalOpen ); @@ -30441,19 +31075,9 @@ static int syncJournal(Pager *pPager){ /* Erase the needSync flag from every page. */ - sqlite3PcacheClearFlags(pPager->pPCache, PGHDR_NEED_SYNC); + sqlite3PcacheClearSyncFlags(pPager->pPCache); } -#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{ - sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_NEED_SYNC); - } -#endif - return rc; } @@ -30554,6 +31178,7 @@ static int pagerStress(void *p, PgHdr *pPg){ 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; @@ -30687,140 +31312,135 @@ static int pagerSharedLock(Pager *pPager){ if( pPager->state==PAGER_UNLOCK || isErrorReset ){ sqlite3_vfs *pVfs = pPager->pVfs; - if( !MEMDB ){ - int isHotJournal; - 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); - } - assert( pPager->state>=SHARED_LOCK ); + 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 a journal file exists, and there is no RESERVED lock on the - ** database file, then it either needs to be played back or deleted. + 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( !isErrorReset ){ - rc = hasHotJournal(pPager, &isHotJournal); + if( pPager->statefd, EXCLUSIVE_LOCK); 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->statefd, 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( 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; + /* 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); } - } - } - if( rc!=SQLITE_OK ){ - if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK - && rc!=SQLITE_IOERR_NOMEM - ){ + }else{ + /* If the journal does not exist, that means some other process + ** has already rolled it back */ rc = SQLITE_BUSY; } - goto failed; } - pPager->journalOpen = 1; - pPager->journalStarted = 0; - pPager->journalOff = 0; - pPager->setMaster = 0; - pPager->journalHdr = 0; + } + if( rc!=SQLITE_OK ){ + goto failed; + } + 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; - } - assert(pPager->state==PAGER_SHARED || - (pPager->exclusiveMode && pPager->state>PAGER_SHARED) - ); + /* 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) + ); + } - 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( 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->errCode ){ + rc = pPager->errCode; + goto failed; + } - 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)); + 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 ){ + goto failed; } + }else{ + memset(dbFileVers, 0, sizeof(dbFileVers)); + } - if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ - pager_reset(pPager); - } + if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ + pager_reset(pPager); } } assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED ); @@ -30923,7 +31543,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire( assert( pPager->state==PAGER_UNLOCK || sqlite3PcacheRefCount(pPager->pPCache)>0 - || pgno==1 + || pgno==1 ); /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page @@ -30959,10 +31579,6 @@ SQLITE_PRIVATE int sqlite3PagerAcquire( int nMax; PAGER_INCR(pPager->nMiss); pPg->pPager = pPager; - if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){ - assert( !MEMDB ); - pPg->flags |= PGHDR_IN_JOURNAL; - } memset(pPg->pExtra, 0, pPager->nExtra); rc = sqlite3PagerPagecount(pPager, &nMax); @@ -31063,7 +31679,6 @@ 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 ); @@ -31080,13 +31695,18 @@ 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; @@ -31161,28 +31781,23 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){ assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->pInJournal==0 ); - sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL); - 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 ){ - 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); + 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( 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 ** time a (read or write) transaction was successfully concluded @@ -31207,23 +31822,6 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){ } /* -** Make a page dirty. Set its dirty flag and add it to the dirty -** page list. -*/ -static void makeDirty(PgHdr *pPg){ - sqlite3PcacheMakeDirty(pPg); -} - -/* -** Make a page clean. Clear its dirty bit and remove it from the -** dirty page list. -*/ -static void makeClean(PgHdr *pPg){ - sqlite3PcacheMakeClean(pPg); -} - - -/* ** 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. @@ -31274,10 +31872,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. */ - makeDirty(pPg); - if( (pPg->flags&PGHDR_IN_JOURNAL) - && (pageInStatement(pPg) || pPager->stmtInUse==0) - ){ + sqlite3PcacheMakeDirty(pPg); + if( pageInJournal(pPg) && (pageInStatement(pPg) || pPager->stmtInUse==0) ){ pPager->dirtyCache = 1; pPager->dbModified = 1; }else{ @@ -31307,57 +31903,49 @@ 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( !(pPg->flags&PGHDR_IN_JOURNAL) && (pPager->journalOpen || MEMDB) ){ - if( (int)pPg->pgno <= pPager->origDbSize ){ - if( MEMDB ){ - PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); - rc = sqlite3PcachePreserve(pPg, 0); - if( rc!=SQLITE_OK ){ - return rc; - } - }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->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( !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; + } - 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); + if( !pPager->noSync ){ + pPg->flags |= PGHDR_NEED_SYNC; + } + if( pPager->stmtInUse ){ + sqlite3BitvecSet(pPager->pInStmt, pPg->pgno); } }else{ if( !pPager->journalStarted && !pPager->noSync ){ @@ -31370,7 +31958,6 @@ static int pager_write(PgHdr *pPg){ if( pPg->flags&PGHDR_NEED_SYNC ){ pPager->needSync = 1; } - pPg->flags |= PGHDR_IN_JOURNAL; } /* If the statement journal is open and the page is not in it, @@ -31380,40 +31967,31 @@ static int pager_write(PgHdr *pPg){ */ if( pPager->stmtInUse && !pageInStatement(pPg) - && (int)pPg->pgno<=pPager->stmtSize + && pPg->pgno<=pPager->stmtSize ){ - assert( (pPg->flags&PGHDR_IN_JOURNAL) - || (int)pPg->pgno>pPager->origDbSize ); - if( MEMDB ){ - rc = sqlite3PcachePreserve(pPg, 1); - if( rc!=SQLITE_OK ){ - return rc; - } - PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); - }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); + 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; } + 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<(int)pPg->pgno ){ + if( pPager->dbSizepgno ){ pPager->dbSize = pPg->pgno; - if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){ + if( pPager->dbSize==(PAGER_MJ_PGNO(pPager)-1) ){ pPager->dbSize++; } } @@ -31437,7 +32015,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){ Pager *pPager = pPg->pPager; Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); - if( !MEMDB && nPagePerSector>1 ){ + if( 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 */ @@ -31447,6 +32025,7 @@ 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; @@ -31528,7 +32107,9 @@ SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){ /* ** 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. +** 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. ** ** 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 @@ -31554,7 +32135,7 @@ SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage *pDbPage){ Pager *pPager = pPg->pPager; int rc; - if( MEMDB || pPg->pgno>pPager->origDbSize ){ + if( pPg->pgno>pPager->origDbSize ){ return SQLITE_OK; } if( pPager->pAlwaysRollback==0 ){ @@ -31568,7 +32149,7 @@ SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage *pDbPage){ if( rc==SQLITE_OK && (pPg->flags&PGHDR_DIRTY) && !pPager->stmtInUse ){ assert( pPager->state>=PAGER_SHARED ); - if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){ + if( pPager->dbSize==pPg->pgno && pPager->origDbSizedbSize ){ /* 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 @@ -31615,10 +32196,10 @@ SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){ ){ return; } - assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */ #ifdef SQLITE_SECURE_DELETE - if( (pPg->flags & PGHDR_IN_JOURNAL)!=0 || (int)pPg->pgno>pPager->origDbSize ){ + if( sqlite3BitvecTest(pPager->pInJournal, pPg->pgno)!=0 + || pPg->pgno>pPager->origDbSize ){ return; } #endif @@ -31637,7 +32218,6 @@ SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){ assert( pPager->pInJournal!=0 ); sqlite3BitvecSet(pPager->pInJournal, pPg->pgno); - pPg->flags |= PGHDR_IN_JOURNAL; pPg->flags &= ~PGHDR_NEED_READ; if( pPager->stmtInUse ){ assert( pPager->stmtSize >= pPager->origDbSize ); @@ -31818,7 +32398,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne( ** file. */ Pgno i; - int iSkip = PAGER_MJ_PGNO(pPager); + Pgno 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); @@ -31907,16 +32487,9 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ return SQLITE_OK; } PAGERTRACE2("COMMIT %d\n", PAGERID(pPager)); - if( MEMDB ){ - sqlite3PcacheCommit(pPager->pPCache, 0); - sqlite3PcacheCleanAll(pPager->pPCache); - sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL); - pPager->state = PAGER_SHARED; - }else{ - assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache ); - rc = pager_end_transaction(pPager, pPager->setMaster); - rc = pager_error(pPager, rc); - } + assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dirtyCache ); + rc = pager_end_transaction(pPager, pPager->setMaster); + rc = pager_error(pPager, rc); return rc; } @@ -31935,16 +32508,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ int rc = SQLITE_OK; PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager)); - if( MEMDB ){ - sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter); - sqlite3PcacheRollback(pPager->pPCache, 0, pPager->xReiniter); - sqlite3PcacheCleanAll(pPager->pPCache); - sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL); - pPager->dbSize = pPager->origDbSize; - pager_truncate_cache(pPager); - pPager->stmtInUse = 0; - pPager->state = PAGER_SHARED; - }else if( !pPager->dirtyCache || !pPager->journalOpen ){ + if( !pPager->dirtyCache || !pPager->journalOpen ){ rc = pager_end_transaction(pPager, pPager->setMaster); }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ if( pPager->state>=PAGER_EXCLUSIVE ){ @@ -31963,7 +32527,9 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){ rc = pager_playback(pPager, 0); } - pPager->dbSize = -1; + if( !MEMDB ){ + pPager->dbSizeValid = 0; + } /* 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 @@ -31989,6 +32555,13 @@ 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); +} + #ifdef SQLITE_TEST /* ** This routine is used for testing and analysis only. @@ -31998,7 +32571,7 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ a[0] = sqlite3PcacheRefCount(pPager->pPCache); a[1] = sqlite3PcachePagecount(pPager->pPCache); a[2] = sqlite3PcacheGetCachesize(pPager->pPCache); - a[3] = pPager->dbSize; + a[3] = pPager->dbSizeValid ? (int) pPager->dbSize : -1; a[4] = pPager->state; a[5] = pPager->errCode; a[6] = pPager->nHit; @@ -32024,13 +32597,8 @@ static int pagerStmtBegin(Pager *pPager){ int rc; assert( !pPager->stmtInUse ); assert( pPager->state>=PAGER_SHARED ); - assert( pPager->dbSize>=0 ); + assert( pPager->dbSizeValid ); 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; @@ -32047,9 +32615,13 @@ static int pagerStmtBegin(Pager *pPager){ pPager->stmtHdrOff = 0; pPager->stmtCksum = pPager->cksumInit; if( !pPager->stmtOpen ){ - rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL); - if( rc ){ - goto stmt_begin_failed; + if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ){ + sqlite3MemJournalOpen(pPager->stfd); + }else{ + rc = sqlite3PagerOpentemp(pPager, pPager->stfd, SQLITE_OPEN_SUBJOURNAL); + if( rc ){ + goto stmt_begin_failed; + } } pPager->stmtOpen = 1; pPager->stmtNRec = 0; @@ -32076,14 +32648,13 @@ SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager *pPager){ SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager *pPager){ if( pPager->stmtInUse ){ PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); - if( !MEMDB ){ - sqlite3BitvecDestroy(pPager->pInStmt); - pPager->pInStmt = 0; - }else{ - sqlite3PcacheCommit(pPager->pPCache, 1); - } + sqlite3BitvecDestroy(pPager->pInStmt); + pPager->pInStmt = 0; pPager->stmtNRec = 0; pPager->stmtInUse = 0; + if( sqlite3IsMemJournal(pPager->stfd) ){ + sqlite3OsTruncate(pPager->stfd, 0); + } } pPager->stmtAutoopen = 0; return SQLITE_OK; @@ -32096,14 +32667,7 @@ SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager *pPager){ int rc; if( pPager->stmtInUse ){ PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager)); - if( MEMDB ){ - sqlite3PcacheRollback(pPager->pPCache, 1, pPager->xReiniter); - pPager->dbSize = pPager->stmtSize; - pager_truncate_cache(pPager); - rc = SQLITE_OK; - }else{ - rc = pager_stmt_playback(pPager); - } + rc = pager_stmt_playback(pPager); sqlite3PagerStmtCommit(pPager); }else{ rc = SQLITE_OK; @@ -32215,7 +32779,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i */ if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){ needSyncPgno = pPg->pgno; - assert( (pPg->flags&PGHDR_IN_JOURNAL) || (int)pgno>pPager->origDbSize ); + assert( pageInJournal(pPg) || pPg->pgno>pPager->origDbSize ); assert( pPg->flags&PGHDR_DIRTY ); assert( pPager->needSync ); } @@ -32225,24 +32789,19 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i ** page pgno before the 'move' operation, it needs to be retained ** for the page moved there. */ - pPg->flags &= ~(PGHDR_NEED_SYNC|PGHDR_IN_JOURNAL); + pPg->flags &= ~PGHDR_NEED_SYNC; pPgOld = pager_lookup(pPager, pgno); assert( !pPgOld || pPgOld->nRef==1 ); if( pPgOld ){ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC); } - if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){ - assert( !MEMDB ); - pPg->flags |= PGHDR_IN_JOURNAL; - } sqlite3PcacheMove(pPg, pgno); if( pPgOld ){ - sqlite3PcacheMove(pPgOld, 0); - sqlite3PcacheRelease(pPgOld); + sqlite3PcacheDrop(pPgOld); } - makeDirty(pPg); + sqlite3PcacheMakeDirty(pPg); pPager->dirtyCache = 1; pPager->dbModified = 1; @@ -32269,7 +32828,7 @@ 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 && (int)needSyncPgno<=pPager->origDbSize ){ + if( pPager->pInJournal && needSyncPgno<=pPager->origDbSize ){ sqlite3BitvecClear(pPager->pInJournal, needSyncPgno); } return rc; @@ -32277,8 +32836,7 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i pPager->needSync = 1; assert( pPager->noSync==0 && !MEMDB ); pPgHdr->flags |= PGHDR_NEED_SYNC; - pPgHdr->flags |= PGHDR_IN_JOURNAL; - makeDirty(pPgHdr); + sqlite3PcacheMakeDirty(pPgHdr); sqlite3PagerUnref(pPgHdr); } @@ -32290,7 +32848,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 ); + assert( pPg->nRef>0 || pPg->pPager->memDb ); return pPg->pData; } @@ -32326,24 +32884,34 @@ 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 or -** PAGER_JOURNALMODE_PERSIST. 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 +** 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. ** -** The returned value is either PAGER_JOURNALMODE_DELETE or -** PAGER_JOURNALMODE_PERSIST, indicating the current (possibly updated) +** The returned indicate the current (possibly updated) ** journal-mode. */ SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *pPager, int eMode){ - 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; + 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 ); + } } return (int)pPager->journalMode; } @@ -32374,7 +32942,7 @@ SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ ** ************************************************************************* ** -** $Id: btmutex.c,v 1.10 2008/07/14 19:39:17 drh Exp $ +** $Id: btmutex.c,v 1.12 2008/11/17 19:18:55 danielk1977 Exp $ ** ** This file contains code used to implement mutexes on Btree objects. ** This code really belongs in btree.c. But btree.c is getting too @@ -32394,7 +32962,7 @@ SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *pPager, i64 iLimit){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btreeInt.h,v 1.31 2008/09/18 17:34:44 danielk1977 Exp $ +** $Id: btreeInt.h,v 1.36 2008/11/19 10:22:33 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -32651,7 +33219,6 @@ 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 */ @@ -32661,7 +33228,6 @@ 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 */ @@ -32673,22 +33239,9 @@ 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 */ }; /* -** Possible values for the MemPage.isInit variable. When a page is first -** loaded or if the data stored in the MemPage struct is invalidated, -** MemPage.isInit is set to PAGE_ISINIT_NONE. If the MemPage structure -** is fully initialized, then MemPage.isInit is set to PAGE_ISINIT_FULL. -** MemPage.isInit is set to PAGE_ISINIT_DATA when the MemPage struct is -** populated, but the MemPage.pParent variable is not necessarily correct. -*/ -#define PAGE_ISINIT_NONE 0 -#define PAGE_ISINIT_DATA 1 -#define PAGE_ISINIT_FULL 2 - -/* ** The in-memory image of a disk page has the auxiliary information appended ** to the end. EXTRA_SIZE is the number of bytes of space needed to hold ** that extra information. @@ -32779,7 +33332,6 @@ 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 */ @@ -32807,6 +33359,17 @@ 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. ** @@ -32826,8 +33389,6 @@ 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 */ @@ -32840,6 +33401,12 @@ 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] */ }; /* @@ -32882,7 +33449,7 @@ struct BtCursor { #ifdef SQLITE_OMIT_DISKIO # define PENDING_BYTE_PAGE(pBt) 0x7fffffff #else -# define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) +# define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/(pBt)->pageSize)+1)) #endif /* @@ -32989,7 +33556,7 @@ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ - int nPage; /* Number of pages in the database */ + Pgno 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 */ @@ -33009,13 +33576,12 @@ 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, MemPage *pParent); +SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage); 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 ********************************************/ @@ -33063,7 +33629,6 @@ 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. @@ -33095,7 +33660,6 @@ SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){ pLater->locked = 1; } } -#endif /* SQLITE_MUTEX_NOOP */ } /* @@ -33252,7 +33816,7 @@ SQLITE_PRIVATE void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree } #endif assert( pArray->nMutex>=0 ); - assert( pArray->nMutexaBtree)/sizeof(pArray->aBtree[0])-1 ); + assert( pArray->nMutexaBtree)-1 ); pBt = pBtree->pBt; for(i=0; inMutex; i++){ assert( pArray->aBtree[i]!=pBtree ); @@ -33331,7 +33895,7 @@ SQLITE_PRIVATE void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.516 2008/09/19 16:39:38 danielk1977 Exp $ +** $Id: btree.c,v 1.539.2.2 2008/11/26 14:55:02 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -33355,6 +33919,20 @@ 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 @@ -33622,7 +34200,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->pPage->intKey){ + if( rc==SQLITE_OK && 0==pCur->apPage[0]->intKey){ void *pKey = sqlite3Malloc(pCur->nKey); if( pKey ){ rc = sqlite3BtreeKey(pCur, 0, pCur->nKey, pKey); @@ -33635,11 +34213,15 @@ static int saveCursorPosition(BtCursor *pCur){ rc = SQLITE_NOMEM; } } - assert( !pCur->pPage->intKey || !pCur->pKey ); + assert( !pCur->apPage[0]->intKey || !pCur->pKey ); if( rc==SQLITE_OK ){ - releasePage(pCur->pPage); - pCur->pPage = 0; + int i; + for(i=0; i<=pCur->iPage; i++){ + releasePage(pCur->apPage[i]); + pCur->apPage[i] = 0; + } + pCur->iPage = -1; pCur->eState = CURSOR_REQUIRESEEK; } @@ -33671,7 +34253,7 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ /* ** Clear the current cursor position. */ -static void clearCursorPosition(BtCursor *pCur){ +SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); sqlite3_free(pCur->pKey); pCur->pKey = 0; @@ -33709,7 +34291,7 @@ SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur){ /* ** Determine whether or not a cursor has moved from the position it -** was last placed at. Cursor can move when the row they are pointing +** was last placed at. Cursors 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 @@ -33738,7 +34320,8 @@ SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){ ** input page number. */ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ - int nPagesPerMapPage, iPtrMap, ret; + int nPagesPerMapPage; + Pgno iPtrMap, ret; assert( sqlite3_mutex_held(pBt->mutex) ); nPagesPerMapPage = (pBt->usableSize/5)+1; iPtrMap = (pgno-2)/nPagesPerMapPage; @@ -34005,7 +34588,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 void defragmentPage(MemPage *pPage){ +static int 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 */ @@ -34037,9 +34620,15 @@ static void defragmentPage(MemPage *pPage){ u8 *pAddr; /* The i-th cell pointer */ pAddr = &data[cellOffset + i*2]; pc = get2byte(pAddr); - assert( pcpBt->usableSize ); + if( pc>=usableSize ){ + return SQLITE_CORRUPT_BKPT; + } size = cellSizePtr(pPage, &temp[pc]); cbrk -= size; + if( cbrkusableSize ){ + return SQLITE_CORRUPT_BKPT; + } + assert( cbrk+size<=usableSize && cbrk>=0 ); memcpy(&data[cbrk], &temp[pc], size); put2byte(pAddr, cbrk); } @@ -34050,6 +34639,10 @@ static void defragmentPage(MemPage *pPage){ 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; } /* @@ -34128,7 +34721,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 void freeSpace(MemPage *pPage, int start, int size){ +static int freeSpace(MemPage *pPage, int start, int size){ int addr, pbegin, hdr; unsigned char *data = pPage->aData; @@ -34150,10 +34743,14 @@ static void freeSpace(MemPage *pPage, int start, int size){ addr = hdr + 1; while( (pbegin = get2byte(&data[addr]))0 ){ assert( pbegin<=pPage->pBt->usableSize-4 ); - assert( pbegin>addr ); + if( pbegin<=addr ) { + return SQLITE_CORRUPT_BKPT; + } addr = pbegin; } - assert( pbegin<=pPage->pBt->usableSize-4 ); + if ( pbegin>pPage->pBt->usableSize-4 ) { + return SQLITE_CORRUPT_BKPT; + } assert( pbegin>addr || pbegin==0 ); put2byte(&data[addr], start); put2byte(&data[start], pbegin); @@ -34170,7 +34767,9 @@ static void freeSpace(MemPage *pPage, int start, int size){ psize = get2byte(&data[pbegin+2]); if( pbegin + psize + 3 >= pnext && pnext>0 ){ int frag = pnext - (pbegin+psize); - assert( frag<=data[pPage->hdrOffset+7] ); + if( (frag<0) || (frag>data[pPage->hdrOffset+7]) ){ + return SQLITE_CORRUPT_BKPT; + } data[pPage->hdrOffset+7] -= frag; put2byte(&data[pbegin], get2byte(&data[pnext])); put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin); @@ -34187,6 +34786,7 @@ static void freeSpace(MemPage *pPage, int start, int size){ top = get2byte(&data[hdr+5]); put2byte(&data[hdr+5], top + get2byte(&data[pbegin+2])); } + return SQLITE_OK; } /* @@ -34229,57 +34829,38 @@ 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, /* 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 */ +SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage){ - pBt = pPage->pBt; - assert( pBt!=0 ); - assert( pParent==0 || pParent->pBt==pBt ); - assert( sqlite3_mutex_held(pBt->mutex) ); + assert( pPage->pBt!=0 ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) ); assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) ); - if( pPage==pParent ){ - return SQLITE_CORRUPT_BKPT; - } - if( (pPage->pParent!=pParent) - && (pPage->pParent!=0 || pPage->isInit==PAGE_ISINIT_FULL) ){ - /* The parent page should never change unless the file is corrupt */ - return SQLITE_CORRUPT_BKPT; - } - if( pPage->isInit==PAGE_ISINIT_FULL ) return SQLITE_OK; - if( pParent!=0 ){ - pPage->pParent = pParent; - sqlite3PagerRef(pParent->pDbPage); - } - if( pPage->isInit==PAGE_ISINIT_NONE ){ + + 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; - pPage->idxShift = 0; usableSize = pBt->usableSize; pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; top = get2byte(&data[hdr+5]); @@ -34288,10 +34869,6 @@ SQLITE_PRIVATE int sqlite3BtreeInitPage( /* 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; - } /* Compute the total free space on the page */ pc = get2byte(&data[hdr+1]); @@ -34316,7 +34893,6 @@ SQLITE_PRIVATE int sqlite3BtreeInitPage( /* 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. @@ -34338,7 +34914,8 @@ SQLITE_PRIVATE int sqlite3BtreeInitPage( } #endif - pPage->isInit = PAGE_ISINIT_FULL; + pPage->isInit = 1; + } return SQLITE_OK; } @@ -34370,9 +34947,8 @@ 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 = PAGE_ISINIT_FULL; + pPage->isInit = 1; } @@ -34418,14 +34994,16 @@ SQLITE_PRIVATE int sqlite3BtreeGetPage( } /* -** Return the size of the database file in pages. Or return -1 if -** there is any kind of error. +** Return the size of the database file in pages. If there is any kind of +** error, return ((unsigned int)-1). */ -static int pagerPagecount(Pager *pPager){ +static Pgno pagerPagecount(BtShared *pBt){ + int nPage = -1; int rc; - int nPage; - rc = sqlite3PagerPagecount(pPager, &nPage); - return (rc==SQLITE_OK?nPage:-1); + assert( pBt->pPage1 ); + rc = sqlite3PagerPagecount(pBt->pPager, &nPage); + assert( rc==SQLITE_OK || nPage==-1 ); + return (Pgno)nPage; } /* @@ -34436,15 +35014,13 @@ static int pagerPagecount(Pager *pPager){ static int getAndInitPage( BtShared *pBt, /* The database file */ Pgno pgno, /* Number of the page to get */ - MemPage **ppPage, /* Write the page pointer here */ - MemPage *pParent /* Parent of the page */ + MemPage **ppPage /* Write the page pointer here */ ){ int rc; DbPage *pDbPage; MemPage *pPage; assert( sqlite3_mutex_held(pBt->mutex) ); - assert( !pParent || pParent->isInit==PAGE_ISINIT_FULL ); if( pgno==0 ){ return SQLITE_CORRUPT_BKPT; } @@ -34461,21 +35037,15 @@ static int getAndInitPage( rc = SQLITE_OK; }else{ /* Page not in cache. Acquire it. */ - if( pgno>pagerPagecount(pBt->pPager) ){ + if( pgno>pagerPagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0); if( rc ) return rc; pPage = *ppPage; } - if( pPage->isInit!=PAGE_ISINIT_FULL ){ - rc = sqlite3BtreeInitPage(pPage, pParent); - }else if( pParent && (pPage==pParent || pPage->pParent!=pParent) ){ - /* This condition indicates a loop in the b-tree structure (the scenario - ** where database corruption has caused a page to be a direct or - ** indirect descendant of itself). - */ - rc = SQLITE_CORRUPT_BKPT; + if( !pPage->isInit ){ + rc = sqlite3BtreeInitPage(pPage); } if( rc!=SQLITE_OK ){ releasePage(pPage); @@ -34500,30 +35070,6 @@ 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){ - MemPage *pPage; - pPage = (MemPage *)sqlite3PagerGetExtra(pData); - if( pPage ){ - assert( pPage->isInit!=PAGE_ISINIT_FULL - || sqlite3_mutex_held(pPage->pBt->mutex) - ); - if( pPage->pParent ){ - MemPage *pParent = pPage->pParent; - assert( pParent->pBt==pPage->pBt ); - pPage->pParent = 0; - releasePage(pParent); - } - if( pPage->isInit==PAGE_ISINIT_FULL ){ - pPage->isInit = PAGE_ISINIT_DATA; - } - } -} - -/* ** 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. @@ -34534,19 +35080,19 @@ static void pageDestructor(DbPage *pData){ static void pageReinit(DbPage *pData){ MemPage *pPage; pPage = (MemPage *)sqlite3PagerGetExtra(pData); - if( pPage->isInit==PAGE_ISINIT_FULL ){ + if( pPage->isInit ){ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pPage->isInit = 0; - sqlite3BtreeInitPage(pPage, pPage->pParent); - }else if( pPage->isInit==PAGE_ISINIT_DATA ){ - pPage->isInit = 0; + if( sqlite3PagerPageRefcount(pData)>0 ){ + sqlite3BtreeInitPage(pPage); + } } } /* ** Invoke the busy handler for a btree. */ -static int sqlite3BtreeInvokeBusyHandler(void *pArg, int n){ +static int btreeInvokeBusyHandler(void *pArg){ BtShared *pBt = (BtShared*)pArg; assert( pBt->db ); assert( sqlite3_mutex_held(pBt->db->mutex) ); @@ -34663,9 +35209,7 @@ 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, pageDestructor, + rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, EXTRA_SIZE, flags, vfsFlags); if( rc==SQLITE_OK ){ rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); @@ -34673,7 +35217,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( if( rc!=SQLITE_OK ){ goto btree_open_out; } - sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr); + sqlite3PagerSetBusyhandler(pBt->pPager, btreeInvokeBusyHandler, pBt); p->pBt = pBt; sqlite3PagerSetReiniter(pBt->pPager, pageReinit); @@ -35371,7 +35915,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ unlockBtreeIfUnused(pBt); } }while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && - sqlite3BtreeInvokeBusyHandler(pBt, 0) ); + btreeInvokeBusyHandler(pBt) ); if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ @@ -35396,7 +35940,6 @@ trans_begun: return rc; } - #ifndef SQLITE_OMIT_AUTOVACUUM /* @@ -35413,7 +35956,7 @@ static int setChildPtrmaps(MemPage *pPage){ Pgno pgno = pPage->pgno; assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - rc = sqlite3BtreeInitPage(pPage, pPage->pParent); + rc = sqlite3BtreeInitPage(pPage); if( rc!=SQLITE_OK ){ goto set_child_ptrmaps_out; } @@ -35430,7 +35973,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; } } @@ -35472,7 +36015,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ int i; int nCell; - sqlite3BtreeInitPage(pPage, 0); + sqlite3BtreeInitPage(pPage); nCell = pPage->nCell; for(i=0; imutex) ); iLastPg = pBt->nTrunc; if( iLastPg==0 ){ - iLastPg = pagerPagecount(pBt->pPager); + iLastPg = pagerPagecount(pBt); } if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ @@ -35729,9 +36272,7 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ int rc = SQLITE_OK; Pager *pPager = pBt->pPager; -#ifndef NDEBUG - int nRef = sqlite3PagerRefcount(pPager); -#endif + VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager) ); assert( sqlite3_mutex_held(pBt->mutex) ); invalidateAllOverflowCache(pBt); @@ -35743,7 +36284,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ Pgno nFree; Pgno nPtrmap; const int pgsz = pBt->pageSize; - int nOrig = pagerPagecount(pBt->pPager); + Pgno nOrig = pagerPagecount(pBt); if( PTRMAP_ISPAGE(pBt, nOrig) ){ return SQLITE_CORRUPT_BKPT; @@ -35788,7 +36329,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ return rc; } -#endif +#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ /* ** This routine does the first phase of a two-phase commit. This routine @@ -35955,9 +36496,14 @@ SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ BtCursor *p; sqlite3BtreeEnter(pBtree); for(p=pBtree->pBt->pCursor; p; p=p->pNext){ - clearCursorPosition(p); + int i; + sqlite3BtreeClearCursor(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); } @@ -36132,6 +36678,9 @@ 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 */ @@ -36141,6 +36690,7 @@ static int btreeCursor( BtCursor *pCur /* Space for new cursor */ ){ int rc; + Pgno nPage; BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); @@ -36163,11 +36713,15 @@ static int btreeCursor( } } pCur->pgnoRoot = (Pgno)iTable; - if( iTable==1 && pagerPagecount(pBt->pPager)==0 ){ + rc = sqlite3PagerPagecount(pBt->pPager, (int *)&nPage); + if( rc!=SQLITE_OK ){ + return rc; + } + if( iTable==1 && nPage==0 ){ rc = SQLITE_EMPTY; goto create_cursor_exception; } - rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); + rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]); if( rc!=SQLITE_OK ){ goto create_cursor_exception; } @@ -36190,7 +36744,7 @@ static int btreeCursor( return SQLITE_OK; create_cursor_exception: - releasePage(pCur->pPage); + releasePage(pCur->apPage[0]); unlockBtreeIfUnused(pBt); return rc; } @@ -36221,10 +36775,11 @@ 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; - clearCursorPosition(pCur); + sqlite3BtreeClearCursor(pCur); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; }else{ @@ -36233,7 +36788,9 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor *pCur){ if( pCur->pNext ){ pCur->pNext->pPrev = pCur->pPrev; } - releasePage(pCur->pPage); + for(i=0; i<=pCur->iPage; i++){ + releasePage(pCur->apPage[i]); + } unlockBtreeIfUnused(pBt); invalidateOverflowCache(pCur); /* sqlite3_free(pCur); */ @@ -36247,13 +36804,15 @@ 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(*pCur)); + memcpy(pTempCur, pCur, sizeof(BtCursor)); pTempCur->pNext = 0; pTempCur->pPrev = 0; - if( pTempCur->pPage ){ - sqlite3PagerRef(pTempCur->pPage->pDbPage); + for(i=0; i<=pTempCur->iPage; i++){ + sqlite3PagerRef(pTempCur->apPage[i]->pDbPage); } + assert( pTempCur->pKey==0 ); } /* @@ -36261,10 +36820,12 @@ SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur ** function above. */ SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ + int i; assert( cursorHoldsMutex(pCur) ); - if( pCur->pPage ){ - sqlite3PagerUnref(pCur->pPage->pDbPage); + for(i=0; i<=pCur->iPage; i++){ + sqlite3PagerUnref(pCur->apPage[i]->pDbPage); } + sqlite3_free(pCur->pKey); } /* @@ -36285,8 +36846,9 @@ 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->pPage, pCur->idx, &info); + sqlite3BtreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); } #else @@ -36296,7 +36858,8 @@ 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 ){ - sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); + int iPage = pCur->iPage; + sqlite3BtreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); pCur->validNKey = 1; }else{ assertCellInfo(pCur); @@ -36304,12 +36867,13 @@ 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 ){ \ - sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \ - pCur->validNKey = 1; \ - }else{ \ - assertCellInfo(pCur); \ +#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); \ } #endif /* _MSC_VER */ @@ -36416,7 +36980,7 @@ static int getOverflowPage( iGuess++; } - if( iGuess<=pagerPagecount(pBt->pPager) ){ + if( iGuess<=pagerPagecount(pBt) ){ rc = ptrmapGet(pBt, iGuess, &eType, &pgno); if( rc!=SQLITE_OK ){ return rc; @@ -36512,8 +37076,8 @@ static int copyPayload( */ static int accessPayload( BtCursor *pCur, /* Cursor pointing to entry to read from */ - int offset, /* Begin reading this far into payload */ - int amt, /* Read this many bytes */ + u32 offset, /* Begin reading this far into payload */ + u32 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. */ @@ -36522,13 +37086,12 @@ static int accessPayload( int rc = SQLITE_OK; u32 nKey; int iIdx = 0; - MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ - BtShared *pBt; /* Btree this cursor belongs to */ + MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */ + BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); - assert( pCur->idx>=0 && pCur->idxnCell ); - assert( offset>=0 ); + assert( pCur->aiIdx[pCur->iPage]nCell ); assert( cursorHoldsMutex(pCur) ); getCellInfo(pCur); @@ -36538,7 +37101,9 @@ static int accessPayload( if( skipKey ){ offset += nKey; } - if( offset+amt > nKey+pCur->info.nData ){ + if( offset+amt > nKey+pCur->info.nData + || &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] + ){ /* Trying to read or write past the end of the data is an error */ return SQLITE_CORRUPT_BKPT; } @@ -36557,9 +37122,8 @@ static int accessPayload( offset -= pCur->info.nLocal; } - pBt = pCur->pBt; if( rc==SQLITE_OK && amt>0 ){ - const int ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ + const u32 ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ Pgno nextPage; nextPage = get4byte(&aPayload[pCur->info.nLocal]); @@ -36660,12 +37224,11 @@ 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->pPage!=0 ); - if( pCur->pPage->intKey ){ + assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); + if( pCur->apPage[0]->intKey ){ return SQLITE_CORRUPT_BKPT; } - assert( pCur->pPage->intKey==0 ); - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0); } return rc; @@ -36693,8 +37256,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->pPage!=0 ); - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); rc = accessPayload(pCur, offset, amt, pBuf, 1, 0); } return rc; @@ -36727,13 +37290,13 @@ static const unsigned char *fetchPayload( unsigned char *aPayload; MemPage *pPage; u32 nKey; - int nLocal; + u32 nLocal; - assert( pCur!=0 && pCur->pPage!=0 ); + assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]); assert( pCur->eState==CURSOR_VALID ); assert( cursorHoldsMutex(pCur) ); - pPage = pCur->pPage; - assert( pCur->idx>=0 && pCur->idxnCell ); + pPage = pCur->apPage[pCur->iPage]; + assert( pCur->aiIdx[pCur->iPage]nCell ); getCellInfo(pCur); aPayload = pCur->info.pCell; aPayload += pCur->info.nHeader; @@ -36792,20 +37355,22 @@ 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 ); - rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); + assert( pCur->iPageiPage>=(BTCURSOR_MAX_DEPTH-1) ){ + return SQLITE_CORRUPT_BKPT; + } + rc = getAndInitPage(pBt, newPgno, &pNewPage); if( rc ) return rc; - pNewPage->idxParent = pCur->idx; - pOldPage = pCur->pPage; - pOldPage->idxShift = 0; - releasePage(pOldPage); - pCur->pPage = pNewPage; - pCur->idx = 0; + pCur->apPage[i+1] = pNewPage; + pCur->aiIdx[i+1] = 0; + pCur->iPage++; + pCur->info.nSize = 0; pCur->validNKey = 0; if( pNewPage->nCell<1 ){ @@ -36814,25 +37379,25 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ return SQLITE_OK; } +#ifndef NDEBUG /* -** 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. +** 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. */ -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; +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 ); + } } +#else +# define assertParentIndex(x,y,z) +#endif /* ** Move the cursor up to the parent page. @@ -36843,26 +37408,19 @@ SQLITE_PRIVATE int sqlite3BtreeIsRootPage(MemPage *pPage){ ** the largest cell index. */ SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur){ - MemPage *pParent; - MemPage *pPage; - int idxParent; - assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - pPage = pCur->pPage; - assert( pPage!=0 ); - assert( !sqlite3BtreeIsRootPage(pPage) ); - pParent = pPage->pParent; - assert( pParent!=0 ); - assert( pPage->pDbPage->nRef>0 ); - idxParent = pPage->idxParent; - sqlite3PagerRef(pParent->pDbPage); - releasePage(pPage); - pCur->pPage = pParent; + 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--; pCur->info.nSize = 0; pCur->validNKey = 0; - assert( pParent->idxShift==0 ); - pCur->idx = idxParent; } /* @@ -36882,40 +37440,31 @@ static int moveToRoot(BtCursor *pCur){ if( pCur->eState==CURSOR_FAULT ){ return pCur->skip; } - clearCursorPosition(pCur); + sqlite3BtreeClearCursor(pCur); } - pRoot = pCur->pPage; - if( pRoot && pRoot->isInit ){ - /* If the page the cursor is currently pointing to is fully initialized, - ** then the root page can be found by following the MemPage.pParent - ** pointers. This is faster than requesting a reference to the root - ** page from the pager layer. - */ - while( pRoot->pParent ){ - assert( pRoot->isInit==PAGE_ISINIT_FULL ); - pRoot = pRoot->pParent; - } - assert( pRoot->isInit==PAGE_ISINIT_FULL ); - if( pRoot!=pCur->pPage ){ - sqlite3PagerRef(pRoot->pDbPage); - releasePage(pCur->pPage); - pCur->pPage = pRoot; + + if( pCur->iPage>=0 ){ + int i; + for(i=1; i<=pCur->iPage; i++){ + releasePage(pCur->apPage[i]); } }else{ if( - SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) + SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0])) ){ pCur->eState = CURSOR_INVALID; return rc; } - releasePage(pCur->pPage); - pCur->pPage = pRoot; } - assert( pCur->pPage->pgno==pCur->pgnoRoot ); - pCur->idx = 0; + + pRoot = pCur->apPage[0]; + assert( pRoot->pgno==pCur->pgnoRoot ); + pCur->iPage = 0; + pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->atLast = 0; pCur->validNKey = 0; + if( pRoot->nCell==0 && !pRoot->leaf ){ Pgno subpage; assert( pRoot->pgno==1 ); @@ -36923,8 +37472,9 @@ 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; } @@ -36942,9 +37492,9 @@ static int moveToLeftmost(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ - assert( pCur->idx>=0 && pCur->idxnCell ); - pgno = get4byte(findCell(pPage, pCur->idx)); + while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ + assert( pCur->aiIdx[pCur->iPage]nCell ); + pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage])); rc = moveToChild(pCur, pgno); } return rc; @@ -36967,13 +37517,13 @@ static int moveToRightmost(BtCursor *pCur){ assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); - while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ + while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); - pCur->idx = pPage->nCell; + pCur->aiIdx[pCur->iPage] = pPage->nCell; rc = moveToChild(pCur, pgno); } if( rc==SQLITE_OK ){ - pCur->idx = pPage->nCell - 1; + pCur->aiIdx[pCur->iPage] = pPage->nCell-1; pCur->info.nSize = 0; pCur->validNKey = 0; } @@ -36992,11 +37542,11 @@ SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( pCur->eState==CURSOR_INVALID ){ - assert( pCur->pPage->nCell==0 ); + assert( pCur->apPage[pCur->iPage]->nCell==0 ); *pRes = 1; rc = SQLITE_OK; }else{ - assert( pCur->pPage->nCell>0 ); + assert( pCur->apPage[pCur->iPage]->nCell>0 ); *pRes = 0; rc = moveToLeftmost(pCur); } @@ -37016,7 +37566,7 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( CURSOR_INVALID==pCur->eState ){ - assert( pCur->pPage->nCell==0 ); + assert( pCur->apPage[pCur->iPage]->nCell==0 ); *pRes = 1; }else{ assert( pCur->eState==CURSOR_VALID ); @@ -37070,7 +37620,9 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( /* 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->pPage->intKey ){ + if( pCur->eState==CURSOR_VALID && pCur->validNKey + && pCur->apPage[0]->intKey + ){ if( pCur->info.nKey==intKey ){ *pRes = 0; return SQLITE_OK; @@ -37085,18 +37637,18 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( if( rc ){ return rc; } - assert( pCur->pPage ); - assert( pCur->pPage->isInit==PAGE_ISINIT_FULL ); + assert( pCur->apPage[pCur->iPage] ); + assert( pCur->apPage[pCur->iPage]->isInit ); if( pCur->eState==CURSOR_INVALID ){ *pRes = -1; - assert( pCur->pPage->nCell==0 ); + assert( pCur->apPage[pCur->iPage]->nCell==0 ); return SQLITE_OK; } - assert( pCur->pPage->intKey || pIdxKey ); + assert( pCur->apPage[0]->intKey || pIdxKey ); for(;;){ int lwr, upr; Pgno chldPg; - MemPage *pPage = pCur->pPage; + MemPage *pPage = pCur->apPage[pCur->iPage]; int c = -1; /* pRes return if table is empty must be -1 */ lwr = 0; upr = pPage->nCell-1; @@ -37105,18 +37657,19 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( goto moveto_finish; } if( biasRight ){ - pCur->idx = upr; + pCur->aiIdx[pCur->iPage] = upr; }else{ - pCur->idx = (upr+lwr)/2; + pCur->aiIdx[pCur->iPage] = (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, pCur->idx) + pPage->childPtrSize; + pCell = findCell(pPage, idx) + pPage->childPtrSize; if( pPage->hasData ){ u32 dummy; pCell += getVarint32(pCell, dummy); @@ -37151,7 +37704,7 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( if( c==0 ){ pCur->info.nKey = nCellKey; if( pPage->intKey && !pPage->leaf ){ - lwr = pCur->idx; + lwr = idx; upr = lwr - 1; break; }else{ @@ -37161,18 +37714,18 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( } } if( c<0 ){ - lwr = pCur->idx+1; + lwr = idx+1; }else{ - upr = pCur->idx-1; + upr = idx-1; } if( lwr>upr ){ pCur->info.nKey = nCellKey; break; } - pCur->idx = (lwr+upr)/2; + pCur->aiIdx[pCur->iPage] = (lwr+upr)/2; } assert( lwr==upr+1 ); - assert( pPage->isInit==PAGE_ISINIT_FULL ); + assert( pPage->isInit ); if( pPage->leaf ){ chldPg = 0; }else if( lwr>=pPage->nCell ){ @@ -37181,12 +37734,12 @@ SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked( chldPg = get4byte(findCell(pPage, lwr)); } if( chldPg==0 ){ - assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + assert( pCur->aiIdx[pCur->iPage]apPage[pCur->iPage]->nCell ); if( pRes ) *pRes = c; rc = SQLITE_OK; goto moveto_finish; } - pCur->idx = lwr; + pCur->aiIdx[pCur->iPage] = lwr; pCur->info.nSize = 0; pCur->validNKey = 0; rc = moveToChild(pCur, chldPg); @@ -37258,6 +37811,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ */ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; + int idx; MemPage *pPage; assert( cursorHoldsMutex(pCur) ); @@ -37266,7 +37820,6 @@ 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; @@ -37278,13 +37831,14 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ } pCur->skip = 0; - assert( pPage->isInit==PAGE_ISINIT_FULL ); - assert( pCur->idxnCell ); + pPage = pCur->apPage[pCur->iPage]; + idx = ++pCur->aiIdx[pCur->iPage]; + assert( pPage->isInit ); + assert( idx<=pPage->nCell ); - pCur->idx++; pCur->info.nSize = 0; pCur->validNKey = 0; - if( pCur->idx>=pPage->nCell ){ + if( idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); if( rc ) return rc; @@ -37293,14 +37847,14 @@ SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ return rc; } do{ - if( sqlite3BtreeIsRootPage(pPage) ){ + if( pCur->iPage==0 ){ *pRes = 1; pCur->eState = CURSOR_INVALID; return SQLITE_OK; } sqlite3BtreeMoveToParent(pCur); - pPage = pCur->pPage; - }while( pCur->idx>=pPage->nCell ); + pPage = pCur->apPage[pCur->iPage]; + }while( pCur->aiIdx[pCur->iPage]>=pPage->nCell ); *pRes = 0; if( pPage->intKey ){ rc = sqlite3BtreeNext(pCur, pRes); @@ -37326,7 +37880,6 @@ 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) ); @@ -37346,29 +37899,29 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ } pCur->skip = 0; - pPage = pCur->pPage; - assert( pPage->isInit==PAGE_ISINIT_FULL ); - assert( pCur->idx>=0 ); + pPage = pCur->apPage[pCur->iPage]; + assert( pPage->isInit ); if( !pPage->leaf ){ - pgno = get4byte( findCell(pPage, pCur->idx) ); - rc = moveToChild(pCur, pgno); + int idx = pCur->aiIdx[pCur->iPage]; + rc = moveToChild(pCur, get4byte(findCell(pPage, idx))); if( rc ){ return rc; } rc = moveToRightmost(pCur); }else{ - while( pCur->idx==0 ){ - if( sqlite3BtreeIsRootPage(pPage) ){ + while( pCur->aiIdx[pCur->iPage]==0 ){ + if( pCur->iPage==0 ){ 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{ @@ -37427,7 +37980,7 @@ static int allocateBtreePage( ** the entire-list will be searched for that page. */ #ifndef SQLITE_OMIT_AUTOVACUUM - if( exact && nearby<=pagerPagecount(pBt->pPager) ){ + if( exact && nearby<=pagerPagecount(pBt) ){ u8 eType; assert( nearby>0 ); assert( pBt->autoVacuum ); @@ -37562,9 +38115,9 @@ static int allocateBtreePage( iPage = get4byte(&aData[8+closest*4]); if( !searchList || iPage==nearby ){ - int nPage; + Pgno nPage; *pPgno = iPage; - nPage = pagerPagecount(pBt->pPager); + nPage = pagerPagecount(pBt); if( *pPgno>nPage ){ /* Free page off the end of the file */ rc = SQLITE_CORRUPT_BKPT; @@ -37594,7 +38147,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->pPager); + int nPage = pagerPagecount(pBt); *pPgno = nPage + 1; #ifndef SQLITE_OMIT_AUTOVACUUM @@ -37639,7 +38192,7 @@ end_allocate_page: releasePage(pTrunk); releasePage(pPrevTrunk); if( rc==SQLITE_OK ){ - if( (*ppPage)->isInit==PAGE_ISINIT_FULL ){ + if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ releasePage(*ppPage); return SQLITE_CORRUPT_BKPT; } @@ -37662,8 +38215,6 @@ 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); @@ -37766,7 +38317,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){ assert( ovflPgno==0 || nOvfl>0 ); while( nOvfl-- ){ MemPage *pOvfl; - if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt->pPager) ){ + if( ovflPgno==0 || ovflPgno>pagerPagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } @@ -37828,7 +38379,7 @@ static int fillInCell( sqlite3BtreeParseCellPtr(pPage, pCell, &info); assert( info.nHeader==nHeader ); assert( info.nKey==nKey ); - assert( info.nData==nData+nZero ); + assert( info.nData==(u32)(nData+nZero) ); /* Fill in the payload */ nPayload = nData + nZero; @@ -37917,102 +38468,6 @@ 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==PAGE_ISINIT_FULL ){ - 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; inCell; 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 @@ -38021,11 +38476,12 @@ static int reparentChildPages(MemPage *pPage, int updatePtrmap){ ** ** "sz" must be the number of bytes in the cell. */ -static void dropCell(MemPage *pPage, int idx, int sz){ +static int 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 && idxnCell ); assert( sz==cellSize(pPage, idx) ); @@ -38034,8 +38490,13 @@ static void dropCell(MemPage *pPage, int idx, int sz){ data = pPage->aData; ptr = &data[pPage->cellOffset + 2*idx]; pc = get2byte(ptr); - assert( pc>10 && pc+sz<=pPage->pBt->usableSize ); - freeSpace(pPage, pc, sz); + if ( (pchdrOffset+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; + } for(i=idx+1; inCell; i++, ptr+=2){ ptr[0] = ptr[2]; ptr[1] = ptr[3]; @@ -38043,7 +38504,7 @@ static void dropCell(MemPage *pPage, int idx, int sz){ pPage->nCell--; put2byte(&data[pPage->hdrOffset+3], pPage->nCell); pPage->nFree += 2; - pPage->idxShift = 1; + return SQLITE_OK; } /* @@ -38090,7 +38551,7 @@ static int insertCell( pCell = pTemp; } j = pPage->nOverflow++; - assert( jaOvfl)/sizeof(pPage->aOvfl[0]) ); + assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) ); pPage->aOvfl[j].pCell = pCell; pPage->aOvfl[j].idx = i; pPage->nFree = 0; @@ -38107,13 +38568,19 @@ static int insertCell( end = cellOffset + 2*pPage->nCell + 2; ins = cellOffset + 2*i; if( end > top - sz ){ - defragmentPage(pPage); + rc = defragmentPage(pPage); + if( rc!=SQLITE_OK ){ + return rc; + } 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); @@ -38123,7 +38590,6 @@ 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 @@ -38205,7 +38671,7 @@ static void assemblePage( #define NB (NN*2+1) /* Total pages involved in the balance */ /* Forward reference */ -static int balance(MemPage*, int); +static int balance(BtCursor*, int); #ifndef SQLITE_OMIT_QUICKBALANCE /* @@ -38225,13 +38691,15 @@ static int balance(MemPage*, 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(MemPage *pPage, MemPage *pParent){ +static int balance_quick(BtCursor *pCur){ int rc; MemPage *pNew = 0; 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 */ @@ -38250,10 +38718,6 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){ assemblePage(pNew, 1, &pCell, &szCell); pPage->nOverflow = 0; - /* Set the parent of the newly allocated page to pParent. */ - pNew->pParent = pParent; - sqlite3PagerRef(pParent->pDbPage); - /* 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. @@ -38307,14 +38771,15 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){ ** the page data and contents of MemPage are consistent. */ pPage->isInit = 0; - sqlite3BtreeInitPage(pPage, pPage->pParent); - sqlite3PagerUnref(pPage->pParent->pDbPage); + sqlite3BtreeInitPage(pPage); /* If everything else succeeded, balance the parent page, in ** case the divider cell inserted caused it to become overfull. */ if( rc==SQLITE_OK ){ - rc = balance(pParent, 0); + releasePage(pPage); + pCur->iPage--; + rc = balance(pCur, 0); } return rc; } @@ -38349,7 +38814,8 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){ ** in a corrupted state. So if this routine fails, the database should ** be rolled back. */ -static int balance_nonroot(MemPage *pPage){ +static int balance_nonroot(BtCursor *pCur){ + MemPage *pPage; /* The over or underfull page to balance */ MemPage *pParent; /* The parent of pPage */ BtShared *pBt; /* The whole database */ int nCell = 0; /* Number of cells in apCell[] */ @@ -38384,15 +38850,18 @@ static int balance_nonroot(MemPage *pPage){ 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( pPage->isInit==PAGE_ISINIT_FULL ); + assert( pCur->iPage>0 ); + assert( pPage->isInit ); assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 ); pBt = pPage->pBt; - pParent = pPage->pParent; + pParent = pCur->apPage[pCur->iPage-1]; assert( pParent ); if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){ return rc; @@ -38413,7 +38882,7 @@ static int balance_nonroot(MemPage *pPage){ pPage->intKey && pPage->nOverflow==1 && pPage->aOvfl[0].idx==pPage->nCell && - pPage->pParent->pgno!=1 && + pParent->pgno!=1 && get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno ){ assert( pPage->intKey ); @@ -38421,7 +38890,7 @@ static int balance_nonroot(MemPage *pPage){ ** 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(pPage, pParent); + return balance_quick(pCur); } #endif @@ -38434,27 +38903,14 @@ static int balance_nonroot(MemPage *pPage){ ** 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 */ - if( pParent->idxShift ){ - Pgno pgno; - pgno = pPage->pgno; - assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); - for(idx=0; idxnCell; idx++){ - if( get4byte(findCell(pParent, idx))==pgno ){ - break; - } - } - assert( idxnCell - || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno ); - }else{ - idx = pPage->idxParent; - } + idx = pCur->aiIdx[pCur->iPage-1]; + assertParentIndex(pParent, idx, pPage->pgno); /* ** 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 @@ -38482,9 +38938,9 @@ static int balance_nonroot(MemPage *pPage){ }else{ break; } - rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i], pParent); + rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i]); if( rc ) goto balance_cleanup; - apOld[i]->idxParent = k; + /* apOld[i]->idxParent = k; */ apCopy[i] = 0; assert( i==nOld ); nOld++; @@ -38907,24 +39363,16 @@ static int balance_nonroot(MemPage *pPage){ } /* - ** Reparent children of all cells. - */ - for(i=0; iisInit==PAGE_ISINIT_FULL ); + assert( pParent->isInit ); sqlite3ScratchFree(apCell); apCell = 0; - rc = balance(pParent, 0); + releasePage(pPage); + pCur->iPage--; + rc = balance(pCur, 0); /* ** Cleanup before returning. @@ -38939,7 +39387,7 @@ balance_cleanup: releasePage(apNew[i]); } - releasePage(pParent); + /* releasePage(pParent); */ TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n", pPage->pgno, nOld, nNew, nCell)); @@ -38951,7 +39399,8 @@ balance_cleanup: ** page contains no cells. This is an opportunity to make the tree ** shallower by one level. */ -static int balance_shallower(MemPage *pPage){ +static int balance_shallower(BtCursor *pCur){ + MemPage *pPage; /* Root page of B-Tree */ MemPage *pChild; /* The only child page of pPage */ Pgno pgnoChild; /* Page number for pChild */ int rc = SQLITE_OK; /* Return code from subprocedures */ @@ -38960,7 +39409,9 @@ static int balance_shallower(MemPage *pPage){ u8 **apCell; /* All cells from pages being balanced */ u16 *szCell; /* Local size of all cells */ - assert( pPage->pParent==0 ); + assert( pCur->iPage==0 ); + pPage = pCur->apPage[0]; + assert( pPage->nCell==0 ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pBt = pPage->pBt; @@ -38984,13 +39435,14 @@ static int balance_shallower(MemPage *pPage){ ** 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->pPager) ); + assert( pgnoChild<=pagerPagecount(pPage->pBt) ); rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0); if( rc ) goto end_shallow_balance; if( pPage->pgno==1 ){ - rc = sqlite3BtreeInitPage(pChild, pPage); + rc = sqlite3BtreeInitPage(pChild); if( rc ) goto end_shallow_balance; assert( pChild->nOverflow==0 ); if( pChild->nFree>=100 ){ @@ -39016,24 +39468,18 @@ static int balance_shallower(MemPage *pPage){ }else{ memcpy(pPage->aData, pChild->aData, pPage->pBt->usableSize); pPage->isInit = 0; - pPage->pParent = 0; - rc = sqlite3BtreeInitPage(pPage, 0); + rc = sqlite3BtreeInitPage(pPage); 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 ){ - int i; - for(i=0; inCell; i++){ - rc = ptrmapPutOvfl(pPage, i); - if( rc!=SQLITE_OK ){ - goto end_shallow_balance; - } - } + rc = setChildPtrmaps(pPage); } +#endif releasePage(pChild); } end_shallow_balance: @@ -39051,8 +39497,9 @@ end_shallow_balance: ** child. Finally, call balance_internal() on the new child ** to cause it to split. */ -static int balance_deeper(MemPage *pPage){ +static int balance_deeper(BtCursor *pCur){ 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 */ @@ -39062,8 +39509,11 @@ static int balance_deeper(MemPage *pPage){ int hdr; /* Offset to page header in parent */ int cbrk; /* Offset to content of first cell in parent */ - assert( pPage->pParent==0 ); - assert( pPage->nOverflow>0 ); + assert( pCur->iPage==0 ); + assert( pCur->apPage[0]->nOverflow>0 ); + + VVA_ONLY( pCur->pagesShuffled = 1 ); + pPage = pCur->apPage[0]; pBt = pPage->pBt; assert( sqlite3_mutex_held(pBt->mutex) ); rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); @@ -39076,58 +39526,68 @@ static int balance_deeper(MemPage *pPage){ cdata = pChild->aData; memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr); memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk); - if( pChild->isInit==PAGE_ISINIT_FULL ) 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; inCell; i++){ - rc = ptrmapPutOvfl(pChild, i); - if( rc!=SQLITE_OK ){ - goto balancedeeper_out; + + 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); } +#endif } - rc = reparentChildPages(pChild, 1); } + if( rc==SQLITE_OK ){ - rc = balance_nonroot(pChild); + pCur->iPage++; + pCur->apPage[1] = pChild; + pCur->aiIdx[0] = 0; + rc = balance_nonroot(pCur); + }else{ + releasePage(pChild); } -balancedeeper_out: - releasePage(pChild); return rc; } /* -** Decide if the page pPage needs to be balanced. If balancing is -** required, call the appropriate balancing routine. +** 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. */ -static int balance(MemPage *pPage, int insert){ +static int balance(BtCursor *pCur, int isInsert){ int rc = SQLITE_OK; + MemPage *pPage = pCur->apPage[pCur->iPage]; + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); - if( pPage->pParent==0 ){ + if( pCur->iPage==0 ){ rc = sqlite3PagerWrite(pPage->pDbPage); if( rc==SQLITE_OK && pPage->nOverflow>0 ){ - rc = balance_deeper(pPage); + rc = balance_deeper(pCur); } if( rc==SQLITE_OK && pPage->nCell==0 ){ - rc = balance_shallower(pPage); + rc = balance_shallower(pCur); } }else{ if( pPage->nOverflow>0 || - (!insert && pPage->nFree>pPage->pBt->usableSize*2/3) ){ - rc = balance_nonroot(pPage); + (!isInsert && pPage->nFree>pPage->pBt->usableSize*2/3) ){ + rc = balance_nonroot(pCur); } } return rc; @@ -39221,6 +39681,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( int rc; int loc; int szNew; + int idx; MemPage *pPage; Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; @@ -39245,7 +39706,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( } /* Save the positions of any other cursors open on this table */ - clearCursorPosition(pCur); + sqlite3BtreeClearCursor(pCur); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) @@ -39253,13 +39714,13 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( return rc; } - pPage = pCur->pPage; + pPage = pCur->apPage[pCur->iPage]; assert( pPage->intKey || nKey>=0 ); assert( pPage->leaf || !pPage->intKey ); TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", pCur->pgnoRoot, nKey, nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); - assert( pPage->isInit==PAGE_ISINIT_FULL ); + assert( pPage->isInit ); allocateTempSpace(pBt); newCell = pBt->pTmpSpace; if( newCell==0 ) return SQLITE_NOMEM; @@ -39267,32 +39728,36 @@ 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( pCur->idx>=0 && pCur->idxnCell ); + assert( idxnCell ); rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ){ goto end_insert; } - oldCell = findCell(pPage, pCur->idx); + oldCell = findCell(pPage, idx); if( !pPage->leaf ){ memcpy(newCell, oldCell, 4); } szOld = cellSizePtr(pPage, oldCell); rc = clearCell(pPage, oldCell); if( rc ) goto end_insert; - dropCell(pPage, pCur->idx, szOld); + rc = dropCell(pPage, idx, szOld); + if( rc!=SQLITE_OK ) { + goto end_insert; + } }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); - pCur->idx++; + idx = ++pCur->aiIdx[pCur->iPage]; pCur->info.nSize = 0; pCur->validNKey = 0; }else{ assert( pPage->leaf ); } - rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0); + rc = insertCell(pPage, idx, newCell, szNew, 0, 0); if( rc!=SQLITE_OK ) goto end_insert; - rc = balance(pPage, 1); + rc = balance(pCur, 1); if( rc==SQLITE_OK ){ moveToRoot(pCur); } @@ -39302,10 +39767,11 @@ end_insert: /* ** Delete the entry that the cursor is pointing to. The cursor -** is left pointing at a random location. +** is left pointing at a arbitrary location. */ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ - MemPage *pPage = pCur->pPage; + MemPage *pPage = pCur->apPage[pCur->iPage]; + int idx; unsigned char *pCell; int rc; Pgno pgnoChild = 0; @@ -39313,7 +39779,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ BtShared *pBt = p->pBt; assert( cursorHoldsMutex(pCur) ); - assert( pPage->isInit==PAGE_ISINIT_FULL ); + assert( pPage->isInit ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; @@ -39323,7 +39789,7 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ if( pCur->eState==CURSOR_FAULT ){ return pCur->skip; } - if( pCur->idx >= pPage->nCell ){ + if( pCur->aiIdx[pCur->iPage]>=pPage->nCell ){ return SQLITE_ERROR; /* The cursor is not pointing to anything */ } if( !pCur->wrFlag ){ @@ -39350,7 +39816,8 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ ** data. The clearCell() call frees any overflow pages associated with the ** cell. The cell itself is still intact. */ - pCell = findCell(pPage, pCur->idx); + idx = pCur->aiIdx[pCur->iPage]; + pCell = findCell(pPage, idx); if( !pPage->leaf ){ pgnoChild = get4byte(pCell); } @@ -39368,6 +39835,8 @@ 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; @@ -39375,15 +39844,18 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ sqlite3BtreeGetTempCursor(pCur, &leafCur); rc = sqlite3BtreeNext(&leafCur, ¬Used); if( rc==SQLITE_OK ){ - rc = sqlite3PagerWrite(leafCur.pPage->pDbPage); + assert( leafCur.aiIdx[leafCur.iPage]==0 ); + pLeafPage = leafCur.apPage[leafCur.iPage]; + rc = sqlite3PagerWrite(pLeafPage->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, leafCur.pPage->pgno)); - dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); - pNext = findCell(leafCur.pPage, leafCur.idx); - szNext = cellSizePtr(leafCur.pPage, pNext); + pCur->pgnoRoot, pPage->pgno, pLeafPage->pgno)); + dropCell(pPage, idx, cellSizePtr(pPage, pCell)); + pNext = findCell(pLeafPage, 0); + szNext = cellSizePtr(pLeafPage, pNext); assert( MX_CELL_SIZE(pBt)>=szNext+4 ); allocateTempSpace(pBt); tempCell = pBt->pTmpSpace; @@ -39391,23 +39863,107 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ rc = SQLITE_NOMEM; } if( rc==SQLITE_OK ){ - rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0); + 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->nFreeusableSize*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 ); } + if( rc==SQLITE_OK ){ - put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild); - rc = balance(pPage, 0); + rc = sqlite3PagerWrite(pLeafPage->pDbPage); } if( rc==SQLITE_OK ){ - dropCell(leafCur.pPage, leafCur.idx, szNext); - rc = balance(leafCur.pPage, 0); + dropCell(pLeafPage, 0, szNext); + VVA_ONLY( leafCur.pagesShuffled = 0 ); + rc = balance(&leafCur, 0); + assert( leafCursorInvalid || !leafCur.pagesShuffled + || !pCur->pagesShuffled ); } } sqlite3BtreeReleaseTempCursor(&leafCur); }else{ TRACE(("DELETE: table=%d delete from leaf %d\n", pCur->pgnoRoot, pPage->pgno)); - dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); - rc = balance(pPage, 0); + rc = dropCell(pPage, idx, cellSizePtr(pPage, pCell)); + if( rc==SQLITE_OK ){ + rc = balance(pCur, 0); + } } if( rc==SQLITE_OK ){ moveToRoot(pCur); @@ -39573,8 +40129,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 */ - MemPage *pParent, /* Parent page. NULL for the root */ - int freePageFlag /* Deallocate page if true */ + int freePageFlag, /* Deallocate page if true */ + int *pnChange ){ MemPage *pPage = 0; int rc; @@ -39582,24 +40138,27 @@ static int clearDatabasePage( int i; assert( sqlite3_mutex_held(pBt->mutex) ); - if( pgno>pagerPagecount(pBt->pPager) ){ + if( pgno>pagerPagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } - rc = getAndInitPage(pBt, pgno, &pPage, pParent); + rc = getAndInitPage(pBt, pgno, &pPage); if( rc ) goto cleardatabasepage_out; for(i=0; inCell; i++){ pCell = findCell(pPage, i); if( !pPage->leaf ){ - rc = clearDatabasePage(pBt, get4byte(pCell), pPage, 1); + rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); if( rc ) goto cleardatabasepage_out; } rc = clearCell(pPage, pCell); if( rc ) goto cleardatabasepage_out; } if( !pPage->leaf ){ - rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage, 1); + rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; + }else if( pnChange ){ + assert( pPage->intKey ); + *pnChange += pPage->nCell; } if( freePageFlag ){ rc = freePage(pPage); @@ -39620,8 +40179,12 @@ 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){ +SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){ int rc; BtShared *pBt = p->pBt; sqlite3BtreeEnter(p); @@ -39633,7 +40196,7 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable){ }else if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){ /* nothing to do */ }else{ - rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0); + rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange); } sqlite3BtreeLeave(p); return rc; @@ -39659,7 +40222,7 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable){ ** 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, int iTable, int *piMoved){ +static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){ int rc; MemPage *pPage = 0; BtShared *pBt = p->pBt; @@ -39681,7 +40244,7 @@ static int btreeDropTable(Btree *p, int iTable, int *piMoved){ rc = sqlite3BtreeGetPage(pBt, (Pgno)iTable, &pPage, 0); if( rc ) return rc; - rc = sqlite3BtreeClearTable(p, iTable); + rc = sqlite3BtreeClearTable(p, iTable, 0); if( rc ){ releasePage(pPage); return rc; @@ -39889,7 +40452,7 @@ SQLITE_PRIVATE int sqlite3BtreeFlags(BtCursor *pCur){ */ MemPage *pPage; restoreCursorPosition(pCur); - pPage = pCur->pPage; + pPage = pCur->apPage[pCur->iPage]; assert( cursorHoldsMutex(pCur) ); assert( pPage->pBt==pCur->pBt ); return pPage ? pPage->aData[pPage->hdrOffset] : 0; @@ -39942,9 +40505,9 @@ static void checkAppendMsg( ** ** Also check that the page number is in bounds. */ -static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ +static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){ if( iPage==0 ) return 1; - if( iPage>pCheck->nPage || iPage<0 ){ + if( iPage>pCheck->nPage ){ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } @@ -40079,7 +40642,6 @@ 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; @@ -40090,7 +40652,7 @@ static int checkTreePage( BtShared *pBt; int usableSize; char zContext[100]; - char *hit; + char *hit = 0; sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); @@ -40105,7 +40667,7 @@ static int checkTreePage( "unable to get the page. error code=%d", rc); return 0; } - if( (rc = sqlite3BtreeInitPage(pPage, pParent))!=0 ){ + if( (rc = sqlite3BtreeInitPage(pPage))!=0 ){ checkAppendMsg(pCheck, zContext, "sqlite3BtreeInitPage() returns error code %d", rc); releasePage(pPage); @@ -40117,7 +40679,7 @@ static int checkTreePage( depth = 0; for(i=0; inCell && pCheck->mxErr; i++){ u8 *pCell; - int sz; + u32 sz; CellInfo info; /* Check payload overflow pages @@ -40149,7 +40711,7 @@ static int checkTreePage( checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); } #endif - d2 = checkTreePage(pCheck,pgno,pPage,zContext); + d2 = checkTreePage(pCheck, pgno, zContext); if( i>0 && d2!=depth ){ checkAppendMsg(pCheck, zContext, "Child page depth differs"); } @@ -40165,7 +40727,7 @@ static int checkTreePage( checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0); } #endif - checkTreePage(pCheck, pgno, pPage, zContext); + checkTreePage(pCheck, pgno, zContext); } /* Check for complete coverage of the page @@ -40176,8 +40738,14 @@ static int checkTreePage( if( hit==0 ){ pCheck->mallocFailed = 1; }else{ - memset(hit, 0, usableSize ); - memset(hit, 1, get2byte(&data[hdr+5])); + 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); nCell = get2byte(&data[hdr+3]); cellStart = hdr + 12 - 4*pPage->leaf; for(i=0; ipBt; @@ -40262,7 +40831,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( } sCheck.pBt = pBt; sCheck.pPager = pBt->pPager; - sCheck.nPage = pagerPagecount(sCheck.pPager); + sCheck.nPage = pagerPagecount(sCheck.pBt); sCheck.mxErr = mxErr; sCheck.nErr = 0; sCheck.mallocFailed = 0; @@ -40298,14 +40867,14 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( /* Check all the tables. */ - for(i=0; iautoVacuum && aRoot[i]>1 ){ checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); } #endif - checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: "); + checkTreePage(&sCheck, aRoot[i], "List of tree roots: "); } /* Make sure every page in the file is referenced @@ -40429,8 +40998,8 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){ return SQLITE_BUSY; } - nToPage = pagerPagecount(pBtTo->pPager); - nFromPage = pagerPagecount(pBtFrom->pPager); + nToPage = pagerPagecount(pBtTo); + nFromPage = pagerPagecount(pBtFrom); iSkip = PENDING_BYTE_PAGE(pBtTo); /* Variable nNewPage is the number of pages required to store the @@ -40507,7 +41076,7 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){ } memcpy(zTo, zFrom, nCopy); - sqlite3PagerUnref(pFromPage); + sqlite3PagerUnref(pFromPage); } } @@ -40736,7 +41305,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->pPage->intKey ){ + if( pCsr->eState==CURSOR_INVALID || !pCsr->apPage[pCsr->iPage]->intKey ){ return SQLITE_ERROR; } @@ -40778,7 +41347,7 @@ SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){ ** This file implements a FIFO queue of rowids used for processing ** UPDATE and DELETE statements. ** -** $Id: vdbefifo.c,v 1.8 2008/07/28 19:34:54 drh Exp $ +** $Id: vdbefifo.c,v 1.9 2008/11/17 19:18:55 danielk1977 Exp $ */ /* @@ -40788,9 +41357,9 @@ SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *pCur){ */ #define FIFOSIZE_FIRST (((128-sizeof(FifoPage))/8)+1) #ifdef SQLITE_MALLOC_SOFT_LIMIT -# define FIFOSIZE_MAX (((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1) +# define FIFOSIZE_MAX (int)(((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1) #else -# define FIFOSIZE_MAX (((262144-sizeof(FifoPage))/8)+1) +# define FIFOSIZE_MAX (int)(((262144-sizeof(FifoPage))/8)+1) #endif /* @@ -40912,7 +41481,7 @@ SQLITE_PRIVATE void sqlite3VdbeFifoClear(Fifo *pFifo){ ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value ** -** $Id: vdbemem.c,v 1.123 2008/09/16 12:06:08 danielk1977 Exp $ +** $Id: vdbemem.c,v 1.126 2008/11/11 00:21:30 drh Exp $ */ /* @@ -40980,9 +41549,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)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); @@ -40998,7 +41564,11 @@ SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ } pMem->z = pMem->zMalloc; - pMem->flags &= ~(MEM_Ephem|MEM_Static); + if( pMem->z==0 ){ + pMem->flags = MEM_Null; + }else{ + pMem->flags &= ~(MEM_Ephem|MEM_Static); + } pMem->xDel = 0; return (pMem->z ? SQLITE_OK : SQLITE_NOMEM); } @@ -41500,9 +42070,6 @@ 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 @@ -41513,6 +42080,9 @@ 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; } @@ -41527,6 +42097,9 @@ 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; @@ -41879,6 +42452,7 @@ 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, @@ -41953,7 +42527,7 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ ** to version 2.8.7, all this code was combined into the vdbe.c source file. ** But that file was getting too big so this subroutines were split out. ** -** $Id: vdbeaux.c,v 1.411 2008/09/19 18:32:27 danielk1977 Exp $ +** $Id: vdbeaux.c,v 1.420 2008/11/17 19:18:55 danielk1977 Exp $ */ @@ -42036,21 +42610,23 @@ SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe *p, FILE *trace){ #endif /* -** Resize the Vdbe.aOp array so that it contains at least N -** elements. +** Resize the Vdbe.aOp array so that it is at least one op larger than +** it was. ** -** 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). +** 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). */ -static void resizeOpArray(Vdbe *p, int N){ +static int growOpArray(Vdbe *p){ VdbeOp *pNew; - pNew = sqlite3DbRealloc(p->db, p->aOp, N*sizeof(Op)); + int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op))); + pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op)); if( pNew ){ - p->nOpAlloc = N; + p->nOpAlloc = nNew; p->aOp = pNew; } + return (pNew ? SQLITE_OK : SQLITE_NOMEM); } /* @@ -42076,8 +42652,7 @@ 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 ){ - resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op)); - if( p->db->mallocFailed ){ + if( growOpArray(p) ){ return 0; } } @@ -42203,6 +42778,8 @@ 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; @@ -42219,8 +42796,11 @@ 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; @@ -42249,6 +42829,7 @@ 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; @@ -42272,11 +42853,7 @@ 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 ){ - resizeOpArray(p, p->nOpAlloc ? p->nOpAlloc*2 : 1024/sizeof(Op)); - assert( p->nOp+nOp<=p->nOpAlloc || p->db->mallocFailed ); - } - if( p->db->mallocFailed ){ + if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){ return 0; } addr = p->nOp; @@ -42661,7 +43238,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe *p, int i){ int mask; assert( i>=0 && idb->nDb ); - assert( ibtreeMask)*8 ); + assert( i<(int)sizeof(p->btreeMask)*8 ); mask = 1<btreeMask & mask)==0 ){ p->btreeMask |= mask; @@ -42947,17 +43524,13 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( */ assert( p->nOp>0 ); - /* 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. - */ + /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */ 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 - ** Cursor/BtCursor structures. The blob of memory associated with + ** VdbeCursor/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. ** @@ -42971,17 +43544,16 @@ 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 ){ - p->nMem = nMem = 10; + nMem = 10; } p->aMem = sqlite3DbMallocZero(db, nMem*sizeof(Mem) /* aMem */ + nVar*sizeof(Mem) /* aVar */ + nArg*sizeof(Mem*) /* apArg */ + nVar*sizeof(char*) /* azVar */ - + nCursor*sizeof(Cursor*) + 1 /* apCsr */ + + nCursor*sizeof(VdbeCursor*)+1 /* apCsr */ ); if( !db->mallocFailed ){ p->aMem--; /* aMem[] goes from 1..nMem */ @@ -42991,7 +43563,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady( p->okVar = 0; p->apArg = (Mem**)&p->aVar[nVar]; p->azVar = (char**)&p->apArg[nArg]; - p->apCsr = (Cursor**)&p->azVar[nVar]; + p->apCsr = (VdbeCursor**)&p->azVar[nVar]; p->nCursor = nCursor; for(n=0; naVar[n].flags = MEM_Null; @@ -43034,7 +43606,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, Cursor *pCx){ +SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){ if( pCx==0 ){ return; } @@ -43069,7 +43641,7 @@ static void closeAllCursorsExceptActiveVtabs(Vdbe *p){ int i; if( p->apCsr==0 ) return; for(i=0; inCursor; i++){ - Cursor *pC = p->apCsr[i]; + VdbeCursor *pC = p->apCsr[i]; if( pC && (!p->inVtabMethod || !pC->pVtabCursor) ){ sqlite3VdbeFreeCursor(p, pC); p->apCsr[i] = 0; @@ -43137,28 +43709,29 @@ SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){ ** ** This call must be made after a call to sqlite3VdbeSetNumCols(). ** -** 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. +** 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. */ -SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){ +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 */ +){ int rc; Mem *pColName; assert( idxnResColumn ); assert( vardb->mallocFailed ) return SQLITE_NOMEM; + if( p->db->mallocFailed ){ + assert( !zName || xDel!=SQLITE_DYNAMIC ); + return SQLITE_NOMEM; + } assert( p->aColName!=0 ); pColName = &(p->aColName[idx+var*p->nResColumn]); - 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; - } + rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, xDel); + assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 ); return rc; } @@ -43389,14 +43962,17 @@ 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) @@ -43484,42 +44060,15 @@ 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; inOp; 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( notReadOnly || mrc!=SQLITE_INTERRUPT ){ - if( p->rc==SQLITE_IOERR_BLOCKED && isStatement ){ + if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){ + if( p->rc==SQLITE_IOERR_BLOCKED && p->usesStmtJournal ){ xFunc = sqlite3BtreeRollbackStmt; p->rc = SQLITE_BUSY; - } else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && isStatement ){ + }else if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) + && p->usesStmtJournal ){ xFunc = sqlite3BtreeRollbackStmt; }else{ /* We are forced to roll back the active transaction. Before doing @@ -43536,9 +44085,12 @@ 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 occured. + ** above has occurred. */ - if( db->autoCommit && db->activeVdbeCnt==1 ){ + if( !sqlite3VtabInSync(db) + && db->autoCommit + && db->writeVdbeCnt==(p->readOnly==0) + ){ 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 @@ -43618,6 +44170,10 @@ 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); @@ -43667,7 +44223,9 @@ 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; @@ -43799,7 +44357,7 @@ 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(Cursor *p){ +SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){ if( p->deferredMoveto ){ int res, rc; #ifdef SQLITE_TEST @@ -43902,7 +44460,7 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){ if( flags&MEM_Real ){ return 7; } - assert( flags&(MEM_Str|MEM_Blob) ); + assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) ); n = pMem->n; if( flags & MEM_Zero ){ n += pMem->u.i; @@ -44159,8 +44717,8 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack( ){ const unsigned char *aKey = (const unsigned char *)pKey; UnpackedRecord *p; - int nByte; - int idx, d; + int nByte, d; + u32 idx; u16 u; /* Unsigned loop counter */ u32 szHdr; Mem *pMem; @@ -44184,7 +44742,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack( while( idxnField ){ 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; @@ -44249,7 +44807,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, /* Left key */ UnpackedRecord *pPKey2 /* Right key */ ){ - u32 d1; /* Offset into aKey[] of next data element */ + int 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; @@ -44366,7 +44924,7 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){ ** supplied it is used in place of pKey,nKey. */ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare( - Cursor *pC, /* The cursor to compare against */ + VdbeCursor *pC, /* The cursor to compare against */ UnpackedRecord *pUnpacked, /* Unpacked version of pKey and nKey */ int *res /* Write the comparison result here */ ){ @@ -44452,7 +45010,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){ ** This file contains code use to implement APIs that are part of the ** VDBE. ** -** $Id: vdbeapi.c,v 1.141 2008/09/04 12:03:43 shane Exp $ +** $Id: vdbeapi.c,v 1.149 2008/11/19 09:05:27 danielk1977 Exp $ */ #if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) @@ -44611,6 +45169,7 @@ 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 @@ -44623,6 +45182,7 @@ 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 @@ -44639,7 +45199,7 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){ rc = SQLITE_OK; }else{ Vdbe *v = (Vdbe*)pStmt; -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE sqlite3_mutex *mutex = v->db->mutex; #endif sqlite3_mutex_enter(mutex); @@ -44681,7 +45241,7 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ int i; int rc = SQLITE_OK; Vdbe *p = (Vdbe*)pStmt; -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex; #endif sqlite3_mutex_enter(mutex); @@ -44903,6 +45463,7 @@ static int sqlite3Step(Vdbe *p){ #endif db->activeVdbeCnt++; + if( p->readOnly==0 ) db->writeVdbeCnt++; p->pc = 0; stmtLruRemove(p); } @@ -45035,11 +45596,12 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){ */ SQLITE_PRIVATE void sqlite3InvalidFunction( sqlite3_context *context, /* The function calling context */ - int argc, /* Number of arguments to the function */ - sqlite3_value **argv /* Value of each argument */ + int NotUsed, /* Number of arguments to the function */ + sqlite3_value **NotUsed2 /* 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); @@ -45132,6 +45694,7 @@ failed: } } +#ifndef SQLITE_OMIT_DEPRECATED /* ** Return the number of times the Step function of a aggregate has been ** called. @@ -45145,6 +45708,7 @@ 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. @@ -45270,9 +45834,13 @@ 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){ - sqlite3_value *pOut = columnMem(pStmt, i); + Mem *pOut = columnMem(pStmt, i); + if( pOut->flags&MEM_Static ){ + pOut->flags &= ~MEM_Static; + pOut->flags |= MEM_Ephem; + } columnMallocFailure(pStmt); - return pOut; + return (sqlite3_value *)pOut; } #ifndef SQLITE_OMIT_UTF16 SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ @@ -45442,17 +46010,24 @@ 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 || p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ - if( p ) sqlite3Error(p->db, SQLITE_MISUSE, 0); + 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); 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--; @@ -45478,21 +46053,19 @@ 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 && zData!=0 ){ - pVar = &p->aVar[i-1]; - rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel); - if( rc==SQLITE_OK && encoding!=0 ){ - rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); + if( rc==SQLITE_OK ){ + if( 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); } - sqlite3Error(p->db, rc, 0); - rc = sqlite3ApiExit(p->db, rc); + sqlite3_mutex_leave(p->db->mutex); } - sqlite3_mutex_leave(p->db->mutex); return rc; } @@ -45512,12 +46085,11 @@ 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){ @@ -45526,20 +46098,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); - sqlite3_mutex_leave(p->db->mutex); + if( rc==SQLITE_OK ){ + sqlite3_mutex_leave(p->db->mutex); + } return rc; } SQLITE_API int sqlite3_bind_text( @@ -45565,27 +46137,25 @@ 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; } @@ -45685,6 +46255,7 @@ 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. @@ -45692,6 +46263,7 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt 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 @@ -45721,6 +46293,16 @@ 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 ********************************************/ /* @@ -45768,7 +46350,7 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.779 2008/09/22 06:13:32 danielk1977 Exp $ +** $Id: vdbe.c,v 1.788 2008/11/17 15:31:48 danielk1977 Exp $ */ /* @@ -45899,25 +46481,25 @@ static const unsigned char opcodeProperty[] = OPFLG_INITIALIZER; ** specified by mask. */ SQLITE_PRIVATE int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){ - assert( opcode>0 && opcode0 && opcode<(int)sizeof(opcodeProperty) ); return (opcodeProperty[opcode]&mask)!=0; } /* -** Allocate cursor number iCur. Return a pointer to it. Return NULL +** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL ** if we run out of memory. */ -static Cursor *allocateCursor( - Vdbe *p, - int iCur, - Op *pOp, - int iDb, - int isBtreeCursor +static VdbeCursor *allocateCursor( + Vdbe *p, /* The virtual machine */ + int iCur, /* Index of the new VdbeCursor */ + Op *pOp, /* */ + int iDb, /* */ + int isBtreeCursor /* */ ){ /* Find the memory cell that will be used to store the blob of memory - ** required for this Cursor structure. It is convenient to use a + ** required for this VdbeCursor structure. It is convenient to use a ** vdbe memory cell to manage the memory allocation required for a - ** Cursor structure for the following reasons: + ** VdbeCursor 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 @@ -45935,18 +46517,18 @@ static Cursor *allocateCursor( Mem *pMem = &p->aMem[p->nMem-iCur]; int nByte; - Cursor *pCx = 0; + VdbeCursor *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 - ** Cursor.aType[] array. + ** VdbeCursor.aType[] array. */ int nField = 0; if( pOp->opcode==OP_SetNumColumns || pOp->opcode==OP_OpenEphemeral ){ nField = pOp->p2; } nByte = - sizeof(Cursor) + + sizeof(VdbeCursor) + (isBtreeCursor?sqlite3BtreeCursorSize():0) + 2*nField*sizeof(u32); @@ -45956,15 +46538,16 @@ static Cursor *allocateCursor( p->apCsr[iCur] = 0; } if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){ - p->apCsr[iCur] = pCx = (Cursor *)pMem->z; + p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z; memset(pMem->z, 0, nByte); pCx->iDb = iDb; pCx->nField = nField; if( nField ){ - pCx->aType = (u32 *)&pMem->z[sizeof(Cursor)]; + pCx->aType = (u32 *)&pMem->z[sizeof(VdbeCursor)]; } if( isBtreeCursor ){ - pCx->pCursor = (BtCursor *)&pMem->z[sizeof(Cursor)+2*nField*sizeof(u32)]; + pCx->pCursor = (BtCursor*) + &pMem->z[sizeof(VdbeCursor)+2*nField*sizeof(u32)]; } } return pCx; @@ -46364,7 +46947,6 @@ SQLITE_PRIVATE int sqlite3VdbeExec( #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 ); sqlite3BtreeMutexArrayEnter(&p->aMutex); @@ -47135,7 +47717,7 @@ case OP_Function: { MemSetTypeFlag(&ctx.s, MEM_Null); ctx.isError = 0; - if( ctx.pFunc->needCollSeq ){ + if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); @@ -47771,23 +48353,20 @@ 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: { - u32 payloadSize; /* Number of bytes in the record */ + int payloadSize; /* Number of bytes in the record */ int p1 = pOp->p1; /* P1 value of the opcode */ int p2 = pOp->p2; /* column number to retrieve */ - Cursor *pC = 0; /* The VDBE cursor */ + VdbeCursor *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 */ - u32 nField; /* number of fields in the record */ + int nField; /* number of fields in the record */ int len; /* The length of the serialized data for the column */ int i; /* Loop counter */ char *zData; /* Part of the record being decoded */ @@ -47812,7 +48391,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 Cursor.nField element. + ** the number of columns is stored in the VdbeCursor.nField element. */ pC = p->apCsr[p1]; assert( pC!=0 ); @@ -47835,7 +48414,7 @@ case OP_Column: { sqlite3BtreeKeySize(pCrsr, &payloadSize64); payloadSize = payloadSize64; }else{ - sqlite3BtreeDataSize(pCrsr, &payloadSize); + sqlite3BtreeDataSize(pCrsr, (u32 *)&payloadSize); } nField = pC->nField; }else{ @@ -47869,7 +48448,7 @@ case OP_Column: { }else{ u8 *zIdx; /* Index into header */ u8 *zEndHdr; /* Pointer to first byte after the header */ - u32 offset; /* Offset into the data */ + int 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 */ @@ -48070,7 +48649,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 */ - u64 nByte = 0; /* Data space required for this record */ + i64 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 */ @@ -48208,33 +48787,40 @@ case OP_Statement: { ** This instruction causes the VM to halt. */ case OP_AutoCommit: { - u8 i = pOp->p1; - u8 rollback = pOp->p2; + int desiredAutoCommit = pOp->p1; + int rollback = pOp->p2; + int turnOnAC = desiredAutoCommit && !db->autoCommit; - assert( i==1 || i==0 ); - assert( i==1 || rollback==0 ); + assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); + assert( desiredAutoCommit==1 || rollback==0 ); assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ - if( db->activeVdbeCnt>1 && i && !db->autoCommit ){ - /* If this instruction implements a COMMIT or ROLLBACK, other VMs are + if( turnOnAC && rollback && db->activeVdbeCnt>1 ){ + /* If this instruction implements a ROLLBACK and other VMs are ** still running, and a transaction is active, return an error indicating ** that the other VMs must complete first. */ - sqlite3SetString(&p->zErrMsg, db, "cannot %s transaction - " - "SQL statements in progress", - rollback ? "rollback" : "commit"); - rc = SQLITE_ERROR; - }else if( i!=db->autoCommit ){ + 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 ){ if( pOp->p2 ){ - assert( i==1 ); + assert( desiredAutoCommit==1 ); sqlite3RollbackAll(db); db->autoCommit = 1; }else{ - db->autoCommit = i; + db->autoCommit = desiredAutoCommit; if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ p->pc = pc; - db->autoCommit = 1-i; + db->autoCommit = 1-desiredAutoCommit; p->rc = rc = SQLITE_BUSY; goto vdbe_return; } @@ -48247,7 +48833,7 @@ case OP_AutoCommit: { goto vdbe_return; }else{ sqlite3SetString(&p->zErrMsg, db, - (!i)?"cannot start a transaction within a transaction":( + (!desiredAutoCommit)?"cannot start a transaction within a transaction":( (rollback)?"cannot rollback - no transaction is active": "cannot commit - no transaction is active")); @@ -48484,7 +49070,7 @@ case OP_OpenWrite: { int iDb = pOp->p3; int wrFlag; Btree *pX; - Cursor *pCur; + VdbeCursor *pCur; Db *pDb; assert( iDb>=0 && iDbnDb ); @@ -48506,7 +49092,10 @@ case OP_OpenWrite: { pIn2 = &p->aMem[p2]; sqlite3VdbeMemIntegerify(pIn2); p2 = pIn2->u.i; - assert( p2>=2 ); + if( p2<2 ) { + rc = SQLITE_CORRUPT_BKPT; + goto abort_due_to_error; + } } assert( i>=0 ); pCur = allocateCursor(p, i, &pOp[-1], iDb, 1); @@ -48584,7 +49173,7 @@ case OP_OpenWrite: { */ case OP_OpenEphemeral: { int i = pOp->p1; - Cursor *pCx; + VdbeCursor *pCx; static const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | @@ -48650,7 +49239,7 @@ case OP_OpenEphemeral: { */ case OP_OpenPseudo: { int i = pOp->p1; - Cursor *pCx; + VdbeCursor *pCx; assert( i>=0 ); pCx = allocateCursor(p, i, &pOp[-1], -1, 0); if( pCx==0 ) goto no_mem; @@ -48739,7 +49328,7 @@ case OP_MoveLe: /* jump, in3 */ case OP_MoveGe: /* jump, in3 */ case OP_MoveGt: { /* jump, in3 */ int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; @@ -48856,7 +49445,7 @@ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ int i = pOp->p1; int alreadyExists = 0; - Cursor *pC; + VdbeCursor *pC; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor!=0 ){ @@ -48912,7 +49501,7 @@ case OP_Found: { /* jump, in3 */ */ case OP_IsUnique: { /* jump, in3 */ int i = pOp->p1; - Cursor *pCx; + VdbeCursor *pCx; BtCursor *pCrsr; Mem *pK; i64 R; @@ -49009,7 +49598,7 @@ case OP_IsUnique: { /* jump, in3 */ */ case OP_NotExists: { /* jump, in3 */ int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; BtCursor *pCrsr; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); @@ -49078,7 +49667,7 @@ case OP_Sequence: { /* out2-prerelease */ case OP_NewRowid: { /* out2-prerelease */ int i = pOp->p1; i64 v = 0; - Cursor *pC; + VdbeCursor *pC; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor==0 ){ @@ -49133,7 +49722,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 ( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) +# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff ) #endif if( !pC->useRandomRowid ){ @@ -49246,7 +49835,7 @@ case OP_Insert: { i64 iKey; /* The integer ROWID or key for the record to be inserted */ int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -49340,7 +49929,7 @@ case OP_Insert: { case OP_Delete: { int i = pOp->p1; i64 iKey; - Cursor *pC; + VdbeCursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; @@ -49411,7 +50000,7 @@ case OP_ResetCount: { case OP_RowKey: case OP_RowData: { int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; BtCursor *pCrsr; u32 n; @@ -49439,7 +50028,7 @@ case OP_RowData: { n = n64; }else{ sqlite3BtreeDataSize(pCrsr, &n); - if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ + if( (int)n>db->aLimit[SQLITE_LIMIT_LENGTH] ){ goto too_big; } } @@ -49465,7 +50054,7 @@ case OP_RowData: { */ case OP_Rowid: { /* out2-prerelease */ int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; i64 v; assert( i>=0 && inCursor ); @@ -49498,13 +50087,16 @@ case OP_Rowid: { /* out2-prerelease */ */ case OP_NullRow: { int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); pC->nullRow = 1; pC->rowidIsValid = 0; + if( pC->pCursor ){ + sqlite3BtreeClearCursor(pC->pCursor); + } break; } @@ -49518,7 +50110,7 @@ case OP_NullRow: { */ case OP_Last: { /* jump */ int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; BtCursor *pCrsr; int res; @@ -49555,6 +50147,7 @@ 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 * * * @@ -49567,7 +50160,7 @@ case OP_Sort: { /* jump */ */ case OP_Rewind: { /* jump */ int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; BtCursor *pCrsr; int res; @@ -49612,7 +50205,7 @@ case OP_Rewind: { /* jump */ */ case OP_Prev: /* jump */ case OP_Next: { /* jump */ - Cursor *pC; + VdbeCursor *pC; BtCursor *pCrsr; int res; @@ -49632,6 +50225,7 @@ 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 @@ -49654,7 +50248,7 @@ case OP_Next: { /* jump */ */ case OP_IdxInsert: { /* in2 */ int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; BtCursor *pCrsr; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); @@ -49673,7 +50267,7 @@ case OP_IdxInsert: { /* in2 */ break; } -/* Opcode: IdxDeleteM P1 P2 P3 * * +/* Opcode: IdxDelete P1 P2 P3 * * ** ** The content of P3 registers starting at register P2 form ** an unpacked index key. This opcode removes that entry from the @@ -49681,7 +50275,7 @@ case OP_IdxInsert: { /* in2 */ */ case OP_IdxDelete: { int i = pOp->p1; - Cursor *pC; + VdbeCursor *pC; BtCursor *pCrsr; assert( pOp->p3>0 ); assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem ); @@ -49715,7 +50309,7 @@ case OP_IdxDelete: { case OP_IdxRowid: { /* out2-prerelease */ int i = pOp->p1; BtCursor *pCrsr; - Cursor *pC; + VdbeCursor *pC; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); @@ -49765,7 +50359,7 @@ case OP_IdxRowid: { /* out2-prerelease */ case OP_IdxLT: /* jump, in3 */ case OP_IdxGE: { /* jump, in3 */ int i= pOp->p1; - Cursor *pC; + VdbeCursor *pC; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); @@ -49850,7 +50444,7 @@ case OP_Destroy: { /* out2-prerelease */ break; } -/* Opcode: Clear P1 P2 * +/* Opcode: Clear P1 P2 P3 ** ** 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 @@ -49860,11 +50454,26 @@ 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<p2))!=0 ); - rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1); + 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; + } + } break; } @@ -50247,7 +50856,7 @@ case OP_AggStep: { ctx.s.db = db; ctx.isError = 0; ctx.pColl = 0; - if( ctx.pFunc->needCollSeq ){ + if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); @@ -50433,7 +51042,7 @@ case OP_VDestroy: { ** table and stores that cursor in P1. */ case OP_VOpen: { - Cursor *pCur = 0; + VdbeCursor *pCur = 0; sqlite3_vtab_cursor *pVtabCursor = 0; sqlite3_vtab *pVtab = pOp->p4.pVtab; @@ -50492,7 +51101,7 @@ case OP_VFilter: { /* jump */ sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; - Cursor *pCur = p->apCsr[pOp->p1]; + VdbeCursor *pCur = p->apCsr[pOp->p1]; REGISTER_TRACE(pOp->p3, pQuery); assert( pCur->pVtabCursor ); @@ -50549,7 +51158,7 @@ case OP_VRowid: { /* out2-prerelease */ sqlite3_vtab *pVtab; const sqlite3_module *pModule; sqlite_int64 iRow; - Cursor *pCur = p->apCsr[pOp->p1]; + VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); if( pCur->nullRow ){ @@ -50583,7 +51192,7 @@ case OP_VColumn: { Mem *pDest; sqlite3_context sContext; - Cursor *pCur = p->apCsr[pOp->p1]; + VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); pDest = &p->aMem[pOp->p3]; @@ -50641,7 +51250,7 @@ case OP_VNext: { /* jump */ const sqlite3_module *pModule; int res = 0; - Cursor *pCur = p->apCsr[pOp->p1]; + VdbeCursor *pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); if( pCur->nullRow ){ break; @@ -50941,7 +51550,7 @@ abort_due_to_interrupt: ** ** This file contains code used to implement incremental BLOB I/O. ** -** $Id: vdbeblob.c,v 1.25 2008/07/28 19:34:54 drh Exp $ +** $Id: vdbeblob.c,v 1.26 2008/10/02 14:49:02 danielk1977 Exp $ */ @@ -51214,17 +51823,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); - - /* 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 ){ + + 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. + */ rc = SQLITE_ABORT; }else{ /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is @@ -51516,6 +52125,253 @@ 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: memjournal.c,v 1.5 2008/11/19 16:52:44 danielk1977 Exp $ +*/ + +/* 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 @@ -51667,7 +52523,7 @@ SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){ ** resolve all identifiers by associating them with a particular ** table and column. ** -** $Id: resolve.c,v 1.5 2008/08/29 02:14:03 drh Exp $ +** $Id: resolve.c,v 1.11 2008/11/17 19:18:55 danielk1977 Exp $ */ /* @@ -51727,8 +52583,7 @@ static void resolveAlias( 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); + sqlite3ExprClear(db, pExpr); memcpy(pExpr, pDup, sizeof(*pExpr)); sqlite3DbFree(db, pDup); } @@ -51971,6 +52826,7 @@ static int lookupName( if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ sqlite3DbFree(db, zCol); pExpr->op = TK_STRING; + pExpr->pTab = 0; return 0; } @@ -51999,9 +52855,9 @@ static int lookupName( */ 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; + testcase( n==BMS-1 ); + if( n>=BMS ){ + n = BMS-1; } assert( pMatch->iCursor==pExpr->iTable ); pMatch->colUsed |= ((Bitmask)1)<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: { @@ -52814,7 +53690,7 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames( ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.394 2008/09/17 00:13:12 drh Exp $ +** $Id: expr.c,v 1.404 2008/11/19 16:52:44 danielk1977 Exp $ */ /* @@ -52843,7 +53719,9 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){ return sqlite3AffinityType(&pExpr->token); } #endif - if( (op==TK_COLUMN || op==TK_REGISTER) && pExpr->pTab!=0 ){ + 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; @@ -52889,7 +53767,7 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ pColl = p->pColl; if( pColl ) break; op = p->op; - if( (op==TK_COLUMN || op==TK_REGISTER) && p->pTab!=0 ){ + 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; @@ -53401,16 +54279,24 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ } /* -** Recursively delete an expression tree. +** Clear an expression structure without deleting the structure itself. +** Substructure is deleted. */ -SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){ - if( p==0 ) return; +SQLITE_PRIVATE void sqlite3ExprClear(sqlite3 *db, Expr *p){ 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); } @@ -53533,6 +54419,9 @@ 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++; @@ -53726,7 +54615,8 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ return WRC_Continue; } } -static int selectNodeIsConstant(Walker *pWalker, Select *pSelect){ +static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ + UNUSED_PARAMETER(NotUsed); pWalker->u.i = 0; return WRC_Abort; } @@ -54014,11 +54904,13 @@ 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_EPH; + sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID); }else{ pX->iTable = iTab; } @@ -54037,9 +54929,20 @@ 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 " IN (?, ?, ?)", where 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){ +SQLITE_PRIVATE void sqlite3CodeSubselect( + Parse *pParse, + Expr *pExpr, + int rMayHaveNull, + int isRowid +){ int testAddr = 0; /* One-time test address */ Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; @@ -54067,12 +54970,13 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHav 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(pExpr->pLeft); + affinity = sqlite3ExprAffinity(pLeft); /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' ** expression it is handled the same way. A virtual table is @@ -54088,7 +54992,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHav ** is used. */ pExpr->iTable = pParse->nTab++; - addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; @@ -54101,6 +55005,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHav SelectDest dest; ExprList *pEList; + assert( !isRowid ); sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable); dest.affinity = (int)affinity; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); @@ -54133,6 +55038,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHav /* Loop through each expression in . */ 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; @@ -54151,14 +55057,22 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHav r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); assert( pParse->disableColCache>0 ); pParse->disableColCache--; - sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); - sqlite3ExprCacheAffinityChange(pParse, r3, 1); - sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); + + 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); + } } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); } - sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); + if( !isRowid ){ + sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO); + } break; } @@ -54222,10 +55136,11 @@ 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); @@ -54483,7 +55398,7 @@ SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){ ** 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){ +static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){ sqlite3 *db = pParse->db; int iReg; if( pParse->aAlias==0 ){ @@ -54494,9 +55409,13 @@ static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr){ assert( iAlias>0 && iAlias<=pParse->nAlias ); iReg = pParse->aAlias[iAlias-1]; if( iReg==0 ){ - iReg = ++pParse->nMem; - sqlite3ExprCode(pParse, pExpr, iReg); - pParse->aAlias[iAlias-1] = iReg; + if( pParse->disableColCache ){ + iReg = sqlite3ExprCodeTarget(pParse, pExpr, target); + }else{ + iReg = ++pParse->nMem; + sqlite3ExprCode(pParse, pExpr, iReg); + pParse->aAlias[iAlias-1] = iReg; + } } return iReg; } @@ -54605,7 +55524,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) break; } case TK_AS: { - inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft); + inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft, target); break; } #ifndef SQLITE_OMIT_CAST @@ -54625,6 +55544,10 @@ 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); @@ -54803,11 +55726,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){ constMask |= (1<needCollSeq && !pColl ){ + if( (pDef->flags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); } } - if( pDef->needCollSeq ){ + if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){ if( !pColl ) pColl = db->pDfltColl; sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); } @@ -54826,7 +55749,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); + sqlite3CodeSubselect(pParse, pExpr, 0, 0); } inReg = pExpr->iColumn; break; @@ -54909,7 +55832,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); @@ -55265,9 +56188,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList( n = pList->nExpr; for(pItem=pList->a, i=0; iiAlias ){ - int iReg = codeAlias(pParse, pItem->iAlias, pItem->pExpr); + int iReg = codeAlias(pParse, pItem->iAlias, pItem->pExpr, target+i); Vdbe *v = sqlite3GetVdbe(pParse); - sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i); + if( iReg!=target+i ){ + sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i); + } }else{ sqlite3ExprCode(pParse, pItem->pExpr, target+i); } @@ -55867,7 +56792,7 @@ SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.48 2008/08/08 14:19:41 drh Exp $ +** $Id: alter.c,v 1.50 2008/11/19 09:05:27 danielk1977 Exp $ */ /* @@ -55892,7 +56817,7 @@ SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){ */ static void renameTableFunc( sqlite3_context *context, - int argc, + int NotUsed, sqlite3_value **argv ){ unsigned char const *zSql = sqlite3_value_text(argv[0]); @@ -55906,6 +56831,8 @@ 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. @@ -55947,7 +56874,7 @@ static void renameTableFunc( */ static void renameTriggerFunc( sqlite3_context *context, - int argc, + int NotUsed, sqlite3_value **argv ){ unsigned char const *zSql = sqlite3_value_text(argv[0]); @@ -55959,9 +56886,10 @@ static void renameTriggerFunc( unsigned char const *zCsr = zSql; int len = 0; char *zRet; - sqlite3 *db = sqlite3_context_db_handle(context); + UNUSED_PARAMETER(NotUsed); + /* 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 ** preceded by either TK_ON or TK_DOT and immediatedly followed by one @@ -56294,11 +57222,11 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ Expr *pDflt; /* Default value for the new column */ sqlite3 *db; /* The database connection; */ - if( pParse->nErr ) return; + db = pParse->db; + if( pParse->nErr || db->mallocFailed ) return; pNew = pParse->pNewTable; assert( pNew ); - db = pParse->db; assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zName; @@ -56488,7 +57416,7 @@ exit_begin_add_column: ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.43 2008/07/28 19:34:53 drh Exp $ +** @(#) $Id: analyze.c,v 1.46 2008/11/19 16:52:44 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_ANALYZE @@ -56562,11 +57490,11 @@ static void openStatTable( static void analyzeOneTable( Parse *pParse, /* Parser context */ Table *pTab, /* Table whose indices are to be analyzed */ - int iStatCur, /* Cursor that writes to the sqlite_stat1 table */ + int iStatCur, /* Index of VdbeCursor that writes the sqlite_stat1 table */ int iMem /* Available memory locations begin here */ ){ Index *pIdx; /* An index to being analyzed */ - int iIdxCur; /* Cursor number for index being analyzed */ + int iIdxCur; /* Index of VdbeCursor for index being analyzed */ int nCol; /* Number of columns in the index */ Vdbe *v; /* The virtual machine being built up */ int i; /* Loop counter */ @@ -56832,7 +57760,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 **azNotUsed){ +static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){ analysisInfo *pInfo = (analysisInfo*)pData; Index *pIndex; int i, c; @@ -56840,6 +57768,8 @@ static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){ const char *z; assert( argc==2 ); + UNUSED_PARAMETER2(NotUsed, argc); + if( argv==0 || argv[0]==0 || argv[1]==0 ){ return 0; } @@ -56915,7 +57845,7 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.78 2008/08/20 16:35:10 drh Exp $ +** $Id: attach.c,v 1.80 2008/11/19 09:05:27 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_ATTACH @@ -56967,7 +57897,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr) */ static void attachFunc( sqlite3_context *context, - int argc, + int NotUsed, sqlite3_value **argv ){ int i; @@ -56979,6 +57909,8 @@ 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 = ""; @@ -57135,7 +58067,7 @@ attach_error: */ static void detachFunc( sqlite3_context *context, - int argc, + int NotUsed, sqlite3_value **argv ){ const char *zName = (const char *)sqlite3_value_text(argv[0]); @@ -57144,6 +58076,8 @@ static void detachFunc( Db *pDb = 0; char zErr[128]; + UNUSED_PARAMETER(NotUsed); + if( zName==0 ) zName = ""; for(i=0; inDb; i++){ pDb = &db->aDb[i]; @@ -57186,8 +58120,7 @@ detach_error: static void codeAttach( Parse *pParse, /* The parser context */ int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */ - const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */ - int nFunc, /* Number of args to pass to zFunc */ + FuncDef *pFunc, /* FuncDef wrapper for detachFunc() or attachFunc() */ Expr *pAuthArg, /* Expression to pass to authorization callback */ Expr *pFilename, /* Name of database file */ Expr *pDbname, /* Name of the database to use internally */ @@ -57196,7 +58129,6 @@ static void codeAttach( int rc; NameContext sName; Vdbe *v; - FuncDef *pFunc; sqlite3* db = pParse->db; int regArgs; @@ -57235,9 +58167,8 @@ static void codeAttach( assert( v || db->mallocFailed ); if( v ){ - sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-nFunc, regArgs+3); - sqlite3VdbeChangeP5(v, nFunc); - pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0); + sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3); + sqlite3VdbeChangeP5(v, pFunc->nArg); sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF); /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this @@ -57259,7 +58190,19 @@ attach_end: ** DETACH pDbname */ SQLITE_PRIVATE void sqlite3Detach(Parse *pParse, Expr *pDbname){ - codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, 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); } /* @@ -57268,22 +58211,23 @@ 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){ - codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, 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); } #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. ** @@ -57688,7 +58632,7 @@ SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.496 2008/08/20 16:35:10 drh Exp $ +** $Id: build.c,v 1.503 2008/11/17 19:18:55 danielk1977 Exp $ */ /* @@ -58290,7 +59234,7 @@ SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *p, int iDb){ */ SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){ int i = -1; /* Database number */ - int n; /* Number of characters in the name */ + size_t n; /* Number of characters in the name */ Db *pDb; /* A database whose name space is being searched */ char *zName; /* Name we are searching for */ @@ -58334,7 +59278,11 @@ SQLITE_PRIVATE int sqlite3TwoPartName( sqlite3 *db = pParse->db; if( pName2 && pName2->n>0 ){ - assert( !db->init.busy ); + if( db->init.busy ) { + sqlite3ErrorMsg(pParse, "corrupt database"); + pParse->nErr++; + return -1; + } *pUnqual = pName2; iDb = sqlite3FindDb(db, pName1); if( iDb<0 ){ @@ -59056,7 +60004,7 @@ static char *createTableStmt(sqlite3 *db, Table *p, int isTemp){ identPut(zStmt, &k, pCol->zName); if( (z = pCol->zType)!=0 ){ zStmt[k++] = ' '; - assert( strlen(z)+k+1<=n ); + assert( (int)(strlen(z)+k+1)<=n ); sqlite3_snprintf(n-k, &zStmt[k], "%s", z); k += strlen(z); } @@ -60065,7 +61013,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex( } pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName, pTblName->a[0].zDatabase); - if( !pTab ) goto exit_create_index; + if( !pTab || db->mallocFailed ) goto exit_create_index; assert( db->aDb[iDb].pSchema==pTab->pSchema ); }else{ assert( pName==0 ); @@ -60656,10 +61604,80 @@ 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; ia[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 new SrcList is returned, or NULL if malloc() fails. +** 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. ** ** If pDatabase is not null, it means that the table has an optional ** database name prefix. Like this: "database.table". The pDatabase @@ -60692,19 +61710,12 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListAppend( if( pList==0 ) return 0; pList->nAlloc = 1; } - 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; + pList = sqlite3SrcListEnlarge(db, pList, 1, pList->nSrc); + if( db->mallocFailed ){ + sqlite3SrcListDelete(db, pList); + return 0; } - pItem = &pList->a[pList->nSrc]; - memset(pItem, 0, sizeof(pList->a[0])); + pItem = &pList->a[pList->nSrc-1]; if( pDatabase && pDatabase->z==0 ){ pDatabase = 0; } @@ -60715,14 +61726,11 @@ 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 cursors to all tables in a SrcList +** Assign VdbeCursor index numbers to all tables in a SrcList */ SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; @@ -60750,6 +61758,7 @@ 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); @@ -60804,6 +61813,24 @@ 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 @@ -61177,7 +62204,7 @@ SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ ** This file contains functions used to access the internal hash tables ** of user defined functions and collation sequences. ** -** $Id: callback.c,v 1.31 2008/09/09 12:31:34 drh Exp $ +** $Id: callback.c,v 1.32 2008/10/10 17:41:29 drh Exp $ */ @@ -61573,14 +62600,14 @@ SQLITE_PRIVATE void sqlite3SchemaFree(void *p){ temp1 = pSchema->tblHash; temp2 = pSchema->trigHash; - sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&pSchema->trigHash, 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, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&pSchema->tblHash, 0); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); sqlite3DeleteTable(pTab); @@ -61604,10 +62631,10 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ if( !p ){ db->mallocFailed = 1; }else if ( 0==p->file_format ){ - 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); + sqlite3HashInit(&p->tblHash, 0); + sqlite3HashInit(&p->idxHash, 0); + sqlite3HashInit(&p->trigHash, 0); + sqlite3HashInit(&p->aFKey, 1); p->enc = SQLITE_UTF8; } return p; @@ -61629,7 +62656,7 @@ SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.175 2008/09/01 21:59:43 shane Exp $ +** $Id: delete.c,v 1.187 2008/11/19 09:05:27 danielk1977 Exp $ */ /* @@ -61638,16 +62665,17 @@ 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){ - Table *pTab = 0; - int i; - struct SrcList_item *pItem; - for(i=0, pItem=pSrc->a; inSrc; i++, pItem++){ - pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase); - sqlite3DeleteTable(pItem->pTab); - pItem->pTab = pTab; - if( pTab ){ - pTab->nRef++; - } + 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; } return pTab; } @@ -61731,6 +62759,97 @@ SQLITE_PRIVATE void sqlite3MaterializeView( } #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. @@ -61757,7 +62876,8 @@ 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 = 0; /* Memory cell used for change counting */ + int memCnt = -1; /* Memory cell used for change counting */ + int rcauth; /* Value returned by authorization callback */ #ifndef SQLITE_OMIT_TRIGGER int isView; /* True if attempting to delete from a view */ @@ -61788,7 +62908,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( ** deleted from is a view */ #ifndef SQLITE_OMIT_TRIGGER - triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0); + triggers_exist = sqlite3TriggersExist(pTab, TK_DELETE, 0); isView = pTab->pSelect!=0; #else # define triggers_exist 0 @@ -61805,9 +62925,12 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDbnDb ); zDb = db->aDb[iDb].zName; - if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ + rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb); + assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); + if( rcauth==SQLITE_DENY ){ goto delete_from_cleanup; } + assert(!isView || triggers_exist); /* If pTab is really a view, make sure it has been initialized. */ @@ -61888,38 +63011,27 @@ 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( 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); + 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( !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); - } + 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 @@ -62032,7 +63144,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", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC); } delete_from_cleanup: @@ -62185,7 +63297,7 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey( ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.203 2008/09/03 17:11:16 drh Exp $ +** $Id: func.c,v 1.206 2008/11/19 16:52:44 danielk1977 Exp $ */ /* @@ -62229,10 +63341,11 @@ static void minmaxFunc( */ static void typeofFunc( sqlite3_context *context, - int argc, + int NotUsed, 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; @@ -62255,6 +63368,7 @@ static void lengthFunc( int len; assert( argc==1 ); + UNUSED_PARAMETER(argc); switch( sqlite3_value_type(argv[0]) ){ case SQLITE_BLOB: case SQLITE_INTEGER: @@ -62285,6 +63399,7 @@ 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]); @@ -62488,10 +63603,11 @@ static void ifnullFunc( */ static void randomFunc( sqlite3_context *context, - int argc, - sqlite3_value **argv + int NotUsed, + sqlite3_value **NotUsed2 ){ 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 */ @@ -62510,6 +63626,7 @@ 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; @@ -62527,10 +63644,11 @@ static void randomBlob( */ static void last_insert_rowid( sqlite3_context *context, - int arg, - sqlite3_value **argv + int NotUsed, + sqlite3_value **NotUsed2 ){ sqlite3 *db = sqlite3_context_db_handle(context); + UNUSED_PARAMETER2(NotUsed, NotUsed2); sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); } @@ -62540,10 +63658,11 @@ static void last_insert_rowid( */ static void changes( sqlite3_context *context, - int arg, - sqlite3_value **argv + int NotUsed, + sqlite3_value **NotUsed2 ){ sqlite3 *db = sqlite3_context_db_handle(context); + UNUSED_PARAMETER2(NotUsed, NotUsed2); sqlite3_result_int(context, sqlite3_changes(db)); } @@ -62553,10 +63672,11 @@ static void changes( */ static void total_changes( sqlite3_context *context, - int arg, - sqlite3_value **argv + int NotUsed, + sqlite3_value **NotUsed2 ){ sqlite3 *db = sqlite3_context_db_handle(context); + UNUSED_PARAMETER2(NotUsed, NotUsed2); sqlite3_result_int(context, sqlite3_total_changes(db)); } @@ -62801,10 +63921,11 @@ static void likeFunc( */ static void nullifFunc( sqlite3_context *context, - int argc, + int NotUsed, sqlite3_value **argv ){ CollSeq *pColl = sqlite3GetFuncCollSeq(context); + UNUSED_PARAMETER(NotUsed); if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){ sqlite3_result_value(context, argv[0]); } @@ -62816,9 +63937,10 @@ static void nullifFunc( */ static void versionFunc( sqlite3_context *context, - int argc, - sqlite3_value **argv + int NotUsed, + sqlite3_value **NotUsed2 ){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); } @@ -62911,6 +64033,7 @@ 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 */ @@ -62936,6 +64059,7 @@ 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); @@ -62967,6 +64091,7 @@ 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]); @@ -63204,6 +64329,7 @@ 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 ){ @@ -63279,9 +64405,14 @@ static void countFinalize(sqlite3_context *context){ /* ** Routines to implement min() and max() aggregate functions. */ -static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void minmaxStep( + sqlite3_context *context, + int NotUsed, + 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)); @@ -63381,9 +64512,6 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ #ifndef SQLITE_OMIT_ALTERTABLE sqlite3AlterFunctions(db); #endif -#ifndef SQLITE_OMIT_PARSER - sqlite3AttachFunctions(db); -#endif if( !db->mallocFailed ){ int rc = sqlite3_overload_function(db, "MATCH", 2); assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); @@ -63564,7 +64692,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.249 2008/08/20 16:35:10 drh Exp $ +** $Id: insert.c,v 1.253 2008/11/19 09:05:27 danielk1977 Exp $ */ /* @@ -63981,7 +65109,7 @@ SQLITE_PRIVATE void sqlite3Insert( ** inserted into is a view */ #ifndef SQLITE_OMIT_TRIGGER - triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0); + triggers_exist = sqlite3TriggersExist(pTab, TK_INSERT, 0); isView = pTab->pSelect!=0; #else # define triggers_exist 0 @@ -64487,7 +65615,6 @@ SQLITE_PRIVATE void sqlite3Insert( regIns, aRegIdx, 0, - 0, (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1, appendFlag ); @@ -64543,7 +65670,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", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC); } insert_cleanup: @@ -64823,26 +65950,26 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( case OE_Fail: { int j, n1, n2; char zErrMsg[200]; - sqlite3_snprintf(sizeof(zErrMsg), zErrMsg, + sqlite3_snprintf(ArraySize(zErrMsg), zErrMsg, pIdx->nColumn>1 ? "columns " : "column "); n1 = strlen(zErrMsg); - for(j=0; jnColumn && n1nColumn && n1aCol[pIdx->aiColumn[j]].zName; n2 = strlen(zCol); if( j>0 ){ - sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], ", "); + sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], ", "); n1 += 2; } - if( n1+n2>sizeof(zErrMsg)-30 ){ - sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "..."); + if( n1+n2>ArraySize(zErrMsg)-30 ){ + sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], "..."); n1 += 3; break; }else{ - sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol); + sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol); n1 += n2; } } - sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], + sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], pIdx->nColumn>1 ? " are not unique" : " is not unique"); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErrMsg,0); break; @@ -64879,7 +66006,6 @@ 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 */ @@ -64936,7 +66062,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; @@ -65451,7 +66577,7 @@ exec_out: ** This file contains code used to dynamically load extensions into ** the SQLite library. ** -** $Id: loadext.c,v 1.54 2008/09/02 00:52:52 drh Exp $ +** $Id: loadext.c,v 1.56 2008/10/12 00:27:53 shane Exp $ */ #ifndef SQLITE_CORE @@ -65476,7 +66602,7 @@ exec_out: ** as extensions by SQLite should #include this file instead of ** sqlite3.h. ** -** @(#) $Id: sqlite3ext.h,v 1.24 2008/06/30 15:09:29 danielk1977 Exp $ +** @(#) $Id: sqlite3ext.h,v 1.25 2008/10/12 00:27:54 shane Exp $ */ #ifndef _SQLITE3EXT_H_ #define _SQLITE3EXT_H_ @@ -65668,7 +66794,9 @@ 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 @@ -65724,14 +66852,18 @@ 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 @@ -65769,7 +66901,9 @@ 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 @@ -65935,7 +67069,11 @@ 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, @@ -65990,7 +67128,11 @@ 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, @@ -66030,10 +67172,18 @@ 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, @@ -66084,7 +67234,7 @@ static const sqlite3_api_routines sqlite3Apis = { sqlite3_file_control, sqlite3_memory_highwater, sqlite3_memory_used, -#ifdef SQLITE_MUTEX_NOOP +#ifdef SQLITE_MUTEX_OMIT 0, 0, 0, @@ -66313,7 +67463,7 @@ SQLITE_API int sqlite3_auto_extension(void *xInit){ #endif { int i; -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif wsdAutoextInit; @@ -66347,7 +67497,7 @@ SQLITE_API void sqlite3_reset_auto_extension(void){ if( sqlite3_initialize()==SQLITE_OK ) #endif { -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif wsdAutoextInit; @@ -66375,7 +67525,7 @@ SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3 *db){ } for(i=0; go; i++){ char *zErrmsg = 0; -#ifndef SQLITE_MUTEX_NOOP +#if SQLITE_THREADSAFE sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); #endif sqlite3_mutex_enter(mutex); @@ -66413,7 +67563,7 @@ SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3 *db){ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.187 2008/09/16 14:38:03 danielk1977 Exp $ +** $Id: pragma.c,v 1.194 2008/11/17 19:18:55 danielk1977 Exp $ */ /* Ignore this whole file if pragmas are disabled @@ -66441,7 +67591,7 @@ static int getSafetyLevel(const char *z){ return atoi(z); } n = strlen(z); - for(i=0; iexplain==0 ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC); } sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); } @@ -66591,7 +67741,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ }; int i; const struct sPragmaType *p; - for(i=0, p=aPragma; izName)==0 ){ sqlite3 *db = pParse->db; Vdbe *v; @@ -66621,6 +67771,16 @@ 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. ** @@ -66712,7 +67872,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeUsesBtree(v, iDb); if( !zRight ){ sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", SQLITE_STATIC); pParse->nMem += 2; addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); sqlite3VdbeChangeP1(v, addr, iDb); @@ -66793,7 +67953,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", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "page_count", SQLITE_STATIC); }else /* @@ -66838,24 +67998,26 @@ SQLITE_PRIVATE void sqlite3Pragma( zRet = "exclusive"; } sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", SQLITE_STATIC); sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, zRet, 0); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); }else /* ** PRAGMA [database.]journal_mode - ** PRAGMA [database.]journal_mode = (delete|persist|off) + ** PRAGMA [database.]journal_mode = (delete|persist|off|truncate|memory) */ if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){ int eMode; - static char * const azModeName[] = {"delete", "persist", "off"}; + static char * const azModeName[] = { + "delete", "persist", "off", "truncate", "memory" + }; if( zRight==0 ){ eMode = PAGER_JOURNALMODE_QUERY; }else{ int n = strlen(zRight); - eMode = 2; + eMode = sizeof(azModeName)/sizeof(azModeName[0]) - 1; while( eMode>=0 && sqlite3StrNICmp(zRight, azModeName[eMode], n)!=0 ){ eMode--; } @@ -66891,10 +68053,12 @@ 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_OFF + || eMode==PAGER_JOURNALMODE_MEMORY ); sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC); sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, azModeName[eMode], P4_STATIC); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); @@ -67061,7 +68225,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( sqlite3_temp_directory ){ sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, - "temp_store_directory", P4_STATIC); + "temp_store_directory", SQLITE_STATIC); sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_temp_directory, 0); sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); } @@ -67146,12 +68310,12 @@ SQLITE_PRIVATE void sqlite3Pragma( Column *pCol; sqlite3VdbeSetNumCols(v, 6); pParse->nMem = 6; - 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); + 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); sqlite3ViewGetColumnNames(pParse, pTab); for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ const Token *pDflt; @@ -67163,7 +68327,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, 4); + sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4); if( pCol->pDflt && (pDflt = &pCol->pDflt->span)->z ){ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pDflt->z, pDflt->n); }else{ @@ -67185,9 +68349,9 @@ SQLITE_PRIVATE void sqlite3Pragma( pTab = pIdx->pTable; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P4_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P4_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC); for(i=0; inColumn; i++){ int cnum = pIdx->aiColumn[i]; sqlite3VdbeAddOp2(v, OP_Integer, i, 1); @@ -67211,9 +68375,9 @@ SQLITE_PRIVATE void sqlite3Pragma( int i = 0; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC); while(pIdx){ sqlite3VdbeAddOp2(v, OP_Integer, i, 1); sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0); @@ -67231,9 +68395,9 @@ SQLITE_PRIVATE void sqlite3Pragma( if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 3); pParse->nMem = 3; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); - sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", SQLITE_STATIC); for(i=0; inDb; i++){ if( db->aDb[i].pBt==0 ) continue; assert( db->aDb[i].zName!=0 ); @@ -67250,8 +68414,8 @@ SQLITE_PRIVATE void sqlite3Pragma( HashElem *p; sqlite3VdbeSetNumCols(v, 2); pParse->nMem = 2; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P4_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC); for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ CollSeq *pColl = (CollSeq *)sqliteHashData(p); sqlite3VdbeAddOp2(v, OP_Integer, i++, 1); @@ -67272,24 +68436,32 @@ SQLITE_PRIVATE void sqlite3Pragma( pFK = pTab->pFKey; if( pFK ){ int i = 0; - 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); + 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); while(pFK){ int j; for(j=0; jnCol; 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); - sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5); + 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); } ++i; pFK = pFK->pNextFrom; @@ -67351,7 +68523,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( sqlite3ReadSchema(pParse) ) goto pragma_out; pParse->nMem = 6; sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE_STATIC); /* Set the maximum error count */ mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; @@ -67530,7 +68702,7 @@ SQLITE_PRIVATE void sqlite3Pragma( if( !zRight ){ /* "PRAGMA encoding" */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", SQLITE_STATIC); sqlite3VdbeAddOp2(v, OP_String8, 0, 1); for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ if( pEnc->enc==ENC(pParse->db) ){ @@ -67631,7 +68803,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3VdbeChangeP1(v, addr, iDb); sqlite3VdbeChangeP3(v, addr, iCookie); sqlite3VdbeSetNumCols(v, 1); - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P4_TRANSIENT); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT); } }else #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ @@ -67648,8 +68820,8 @@ SQLITE_PRIVATE void sqlite3Pragma( Vdbe *v = sqlite3GetVdbe(pParse); sqlite3VdbeSetNumCols(v, 2); pParse->nMem = 2; - sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P4_STATIC); - sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC); for(i=0; inDb; i++){ Btree *pBt; Pager *pPager; @@ -67748,7 +68920,7 @@ pragma_out: ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.97 2008/09/08 09:06:19 danielk1977 Exp $ +** $Id: prepare.c,v 1.101 2008/11/19 16:52:44 danielk1977 Exp $ */ /* @@ -67785,11 +68957,13 @@ static void corruptSchema( ** argv[2] = SQL text for the CREATE statement. ** */ -SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ +SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ 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) ); DbClearProperty(db, iDb, DB_Empty); if( db->mallocFailed ){ @@ -67797,7 +68971,6 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char return SQLITE_NOMEM; } - assert( argc==3 ); assert( iDb>=0 && iDbnDb ); if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */ if( argv[1]==0 ){ @@ -67977,7 +69150,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ */ if( rc==SQLITE_OK ){ int i; - for(i=0; ipBt, i+1, (u32 *)&meta[i]); if( rc ){ sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); @@ -68334,19 +69507,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", P4_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P4_STATIC); - sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P4_STATIC); + 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); }else{ sqlite3VdbeSetNumCols(sParse.pVdbe, 8); - 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); + 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); } } #endif @@ -68559,7 +69732,7 @@ SQLITE_API int sqlite3_prepare16_v2( ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.475 2008/09/17 00:13:12 drh Exp $ +** $Id: select.c,v 1.486 2008/11/19 09:05:27 danielk1977 Exp $ */ @@ -68611,7 +69784,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( Select standin; sqlite3 *db = pParse->db; pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); - assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */ + assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */ if( pNew==0 ){ pNew = &standin; memset(pNew, 0, sizeof(*pNew)); @@ -68627,7 +69800,6 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pNew->pOrderBy = pOrderBy; pNew->selFlags = isDistinct ? SF_Distinct : 0; pNew->op = TK_SELECT; - assert( pOffset==0 || pLimit!=0 ); pNew->pLimit = pLimit; pNew->pOffset = pOffset; pNew->addrOpenEphm[0] = -1; @@ -68691,14 +69863,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; jn==keywords[j].nChar && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){ jointype |= keywords[j].code; break; } } - if( j>=sizeof(keywords)/sizeof(keywords[0]) ){ + if( j>=ArraySize(keywords) ){ jointype |= JT_ERROR; break; } @@ -69580,13 +70752,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, P4_TRANSIENT); - sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P4_TRANSIENT); - sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P4_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT); #else zType = columnType(&sNC, p, 0, 0, 0); #endif - sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT); } #endif /* SQLITE_OMIT_DECLTYPE */ } @@ -69625,7 +70797,7 @@ static void generateColumnNames( if( p==0 ) continue; if( pEList->a[i].zName ){ char *zName = pEList->a[i].zName; - sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName)); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){ Table *pTab; char *zCol; @@ -69641,7 +70813,8 @@ static void generateColumnNames( zCol = pTab->aCol[iCol].zName; } if( !shortNames && !fullNames ){ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, + sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC); }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ char *zName = 0; char *zTab; @@ -69649,12 +70822,13 @@ 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, P4_DYNAMIC); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC); }else{ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol)); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT); } }else{ - sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, + sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC); } } generateColumnTypes(pParse, pTabList, pEList); @@ -70593,7 +71767,7 @@ 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; /* Comparison information for duplicate removal */ + KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */ KeyInfo *pKeyMerge; /* Comparison information for merging rows */ sqlite3 *db; /* Database connection */ ExprList *pOrderBy; /* The ORDER BY clause */ @@ -70601,6 +71775,7 @@ static int multiSelectOrderBy( int *aPermute; /* Mapping from ORDER BY terms to result set columns */ 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; @@ -70690,7 +71865,7 @@ static int multiSelectOrderBy( regPrev = 0; }else{ int nExpr = p->pEList->nExpr; - assert( nOrderBy>=nExpr ); + assert( nOrderBy>=nExpr || db->mallocFailed ); regPrev = sqlite3GetTempRange(pParse, nExpr+1); sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); pKeyDup = sqlite3DbMallocZero(db, @@ -71117,7 +72292,9 @@ 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 && iFromnSrc ); pSubitem = &pSrc->a[iFrom]; @@ -71229,92 +72406,146 @@ static int flattenSubquery( ** SELECT FROM () ** ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block - ** creates N copies of the parent query without any ORDER BY, LIMIT or + ** creates N-1 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); - pNew->pPrior = pPrior; - p->pPrior = pNew; + p->pLimit = pLimit; p->pOrderBy = pOrderBy; - p->op = TK_ALL; p->pSrc = pSrc; - p->pLimit = pLimit; - p->pOffset = pOffset; + p->op = TK_ALL; p->pRightmost = 0; - pNew->pRightmost = 0; + if( pNew==0 ){ + pNew = pPrior; + }else{ + pNew->pPrior = pPrior; + pNew->pRightmost = 0; + } + p->pPrior = pNew; + if( db->mallocFailed ) return 1; } /* Begin flattening 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 = pSubSrc->nSrc; + int nSubSrc; int jointype = 0; - 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. - */ + pSubSrc = pSub->pSrc; /* FROM clause of subquery */ + nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */ + pSrc = pParent->pSrc; /* FROM clause of the outer query */ + if( pSrc ){ - Table *pTabToDel; - pSubitem = &pSrc->a[iFrom]; - nSubSrc = pSubSrc->nSrc; + assert( pParent==p ); /* First time through the loop */ jointype = pSubitem->jointype; - sqlite3DbFree(db, pSubitem->zDatabase); - sqlite3DbFree(db, pSubitem->zName); - sqlite3DbFree(db, pSubitem->zAlias); - pSubitem->zDatabase = 0; - pSubitem->zName = 0; - pSubitem->zAlias = 0; - - /* If the FROM element is a subquery, defer deleting the Table - ** object associated with that subquery until code generation is - ** complete, since there may still exist Expr.pTab entires that - ** refer to the subquery even after flattening. Ticket #3346. - */ - if( (pTabToDel = pSubitem->pTab)!=0 ){ - if( pTabToDel->nRef==1 ){ - pTabToDel->pNextZombie = pParse->pZombieTab; - pParse->pZombieTab = pTabToDel; - }else{ - pTabToDel->nRef--; - } + }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; } - pSubitem->pTab = 0; } - if( nSubSrc!=1 || !pSrc ){ - int extra = nSubSrc - 1; - for(i=(pSrc?1:0); ipSrc = 0; - return 1; - } - } - pParent->pSrc = pSrc; - for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){ - pSrc->a[i] = pSrc->a[i-extra]; + + /* 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; } } + + /* Transfer the FROM clause terms from the subquery into the + ** outer query. + */ for(i=0; ia[i+iFrom] = pSubSrc->a[i]; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); @@ -71409,7 +72640,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(Parse *pParse, Select *p){ +static int minMaxQuery(Select *p){ Expr *pExpr; ExprList *pEList = p->pEList; @@ -71428,6 +72659,31 @@ static int minMaxQuery(Parse *pParse, 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. +*/ +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; + } + return SQLITE_OK; +} + +/* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: ** @@ -71527,6 +72783,11 @@ static int selectExpander(Walker *pWalker, Select *p){ } #endif } + + /* Locate the index named by the INDEXED BY clause, if any. */ + if( sqlite3IndexedByLookup(pParse, pFrom) ){ + return WRC_Abort; + } } /* Process NATURAL keywords, and ON and USING clauses of joins. @@ -71679,7 +72940,8 @@ static int selectExpander(Walker *pWalker, Select *p){ ** Walker.xSelectCallback is set to do something useful for every ** subquery in the parser tree. */ -static int exprWalkNoop(Walker *pWalker, Expr *pExpr){ +static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ + UNUSED_PARAMETER2(NotUsed, NotUsed2); return WRC_Continue; } @@ -71871,11 +73133,11 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ assert( nArg==1 ); codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); } - if( pF->pFunc->needCollSeq ){ + if( pF->pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ CollSeq *pColl = 0; struct ExprList_item *pItem; int j; - assert( pList!=0 ); /* pList!=0 if pF->pFunc->needCollSeq is true */ + assert( pList!=0 ); /* pList!=0 if pF->pFunc has NEEDCOLL */ for(j=0, pItem=pList->a; !pColl && jpExpr); } @@ -72470,7 +73732,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(pParse, p); + flag = minMaxQuery(p); if( flag ){ pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList); if( pMinMax && !db->mallocFailed ){ @@ -72852,7 +74114,7 @@ SQLITE_API void sqlite3_free_table( ************************************************************************* ** ** -** $Id: trigger.c,v 1.129 2008/08/20 16:35:10 drh Exp $ +** $Id: trigger.c,v 1.130 2008/11/19 09:05:27 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_TRIGGER @@ -73444,7 +74706,6 @@ 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 */ @@ -73708,7 +74969,7 @@ SQLITE_PRIVATE int sqlite3CodeRowTrigger( ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.184 2008/09/01 21:59:43 shane Exp $ +** $Id: update.c,v 1.187 2008/11/19 09:05:27 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE @@ -73837,7 +75098,7 @@ SQLITE_PRIVATE void sqlite3Update( ** updated is a view */ #ifndef SQLITE_OMIT_TRIGGER - triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges); + triggers_exist = sqlite3TriggersExist(pTab, TK_UPDATE, pChanges); isView = pTab->pSelect!=0; #else # define triggers_exist 0 @@ -74128,6 +75389,7 @@ SQLITE_PRIVATE void sqlite3Update( */ if( chngRowid ){ sqlite3ExprCodeAndCache(pParse, pRowidExpr, regRowid); + sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid); }else{ sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regRowid); } @@ -74219,7 +75481,7 @@ SQLITE_PRIVATE void sqlite3Update( /* Create the new index entries and the new record. */ sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, - aRegIdx, chngRowid, 1, -1, 0); + aRegIdx, 1, -1, 0); } /* Increment the row counter @@ -74262,7 +75524,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", P4_STATIC); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC); } update_cleanup: @@ -74392,7 +75654,7 @@ static void updateVirtualTable( ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.83 2008/08/26 21:07:27 drh Exp $ +** $Id: vacuum.c,v 1.84 2008/11/17 19:18:55 danielk1977 Exp $ */ #if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH) @@ -74627,7 +75889,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ assert( 1==sqlite3BtreeIsInTrans(pMain) ); /* Copy Btree meta values */ - for(i=0; imallocFailed = 1; } sqlite3ResetInternalSchema(db, 0); + }else if( xDestroy ){ + xDestroy(pAux); } rc = sqlite3ApiExit(db, SQLITE_OK); sqlite3_mutex_leave(db->mutex); @@ -75388,7 +76652,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( 0==db->aVTrans && db->nVTrans>0 ){ + if( sqlite3VtabInSync(db) ){ return SQLITE_LOCKED; } if( !pVtab ){ @@ -75536,13 +76800,8 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.322 2008/09/06 14:19:11 danielk1977 Exp $ -*/ - -/* -** The number of bits in a Bitmask. "BMS" means "BitMask Size". +** $Id: where.c,v 1.330 2008/11/17 19:18:55 danielk1977 Exp $ */ -#define BMS (sizeof(Bitmask)*8) /* ** Trace output macros @@ -75658,7 +76917,7 @@ struct WhereClause { */ struct ExprMaskSet { int n; /* Number of assigned cursor values */ - int ix[sizeof(Bitmask)*8]; /* Cursor assigned to each bit */ + int ix[BMS]; /* Cursor assigned to each bit */ }; @@ -76992,6 +78251,16 @@ 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 */ @@ -77019,6 +78288,9 @@ 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 @@ -77035,74 +78307,77 @@ static double bestIndex( return 0.0; } - /* Check for a rowid=EXPR or rowid IN (...) constraints - */ - 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. + /* Check for a rowid=EXPR or rowid IN (...) constraints. If there was + ** an INDEXED BY clause attached to this table, skip this step. */ - 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 rowidEXPR eliminates two-thirds of rows */ + 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)); } - 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; + + /* 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 rowidEXPR eliminates two-thirds of rows */ } + WHERETRACE(("... rowid range reduces cost to %.9g\n", cost)); }else{ - cost += cost*estLog(cost); - WHERETRACE(("... sorting increases cost to %.9g\n", cost)); + 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( costpNext){ + if( pSrc->pIndex ){ + pProbe = pSrc->pIndex; + } + for(; pProbe; pProbe=(pSrc->pIndex ? 0 : pProbe->pNext)){ int i; /* Loop counter */ double inMultiplier = 1; @@ -77303,9 +78581,7 @@ static int codeEqualityTerm( Vdbe *v = pParse->pVdbe; int iReg; /* Register holding results */ - if( iTarget<=0 ){ - iReg = iTarget = sqlite3GetTempReg(pParse); - } + assert( iTarget>0 ); if( pX->op==TK_EQ ){ iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget); }else if( pX->op==TK_ISNULL ){ @@ -77433,10 +78709,9 @@ static int nQPlan = 0; /* Next free slow in _query_plan[] */ /* ** Free a WhereInfo structure */ -static void whereInfoFree(WhereInfo *pWInfo){ +static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ if( pWInfo ){ int i; - sqlite3 *db = pWInfo->pParse->db; for(i=0; inLevel; i++){ sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo; if( pInfo ){ @@ -77586,7 +78861,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( pWInfo = sqlite3DbMallocZero(db, sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel)); if( db->mallocFailed ){ - goto whereBeginNoMem; + goto whereBeginError; } pWInfo->nLevel = pTabList->nSrc; pWInfo->pParse = pParse; @@ -77633,7 +78908,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ exprAnalyzeAll(pTabList, &wc); if( db->mallocFailed ){ - goto whereBeginNoMem; + goto whereBeginError; } /* Chose the best index to use for each table in the FROM clause. @@ -77643,7 +78918,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 When term of the FROM clause is being coded + ** pWInfo->a[].iFrom Which term of the FROM clause is being coded ** pWInfo->a[].iTabCur The VDBE cursor for the database table ** pWInfo->a[].iIdxCur The VDBE cursor for the index ** @@ -77740,6 +79015,18 @@ 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")); @@ -77811,7 +79098,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<(sizeof(Bitmask)*8) ){ + if( !pWInfo->okOnePass && pTab->nColcolUsed; int n = 0; for(; b; b=b>>1, n++){} @@ -77840,7 +79127,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( */ notReady = ~(Bitmask)0; for(i=0, pLevel=pWInfo->a; inSrc; i++, pLevel++){ - int j; + int j, k; 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 */ @@ -77933,16 +79220,17 @@ 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, 0); + r1 = codeEqualityTerm(pParse, pTerm, pLevel, rtmp); nxt = pLevel->nxt; sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt); sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1); - sqlite3ReleaseTempReg(pParse, r1); + sqlite3ReleaseTempReg(pParse, rtmp); VdbeComment((v, "pk")); pLevel->op = OP_Noop; }else if( pLevel->flags & WHERE_ROWID_RANGE ){ @@ -77962,16 +79250,26 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( } if( pStart ){ Expr *pX; - int r1, regFree1; + int r1; pX = pStart->pExpr; assert( pX!=0 ); assert( pStart->leftCursor==iCur ); - r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, ®Free1); + + /* 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); + 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, regFree1); + sqlite3ReleaseTempReg(pParse, r1); disableTerm(pLevel, pStart); }else{ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, brk); @@ -78199,12 +79497,14 @@ 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 ); @@ -78216,7 +79516,10 @@ 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; } @@ -78298,9 +79601,9 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( return pWInfo; /* Jump here if malloc fails */ -whereBeginNoMem: +whereBeginError: whereClauseClear(&wc); - whereInfoFree(pWInfo); + whereInfoFree(db, pWInfo); return 0; } @@ -78324,6 +79627,7 @@ 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; @@ -78413,7 +79717,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){ /* Final cleanup */ - whereInfoFree(pWInfo); + whereInfoFree(db, pWInfo); return; } @@ -78510,23 +79814,23 @@ struct AttachKey { int type; Token key; }; ** defined, then do no error processing. */ #define YYCODETYPE unsigned char -#define YYNOCODE 247 +#define YYNOCODE 249 #define YYACTIONTYPE unsigned short int #define YYWILDCARD 59 #define sqlite3ParserTOKENTYPE Token typedef union { sqlite3ParserTOKENTYPE yy0; - struct TrigEvent yy30; - Expr* yy62; - SrcList* yy151; - struct LimitVal yy220; - struct LikeOp yy222; - IdList* yy240; - int yy280; - struct {int value; int mask;} yy359; - TriggerStep* yy360; - Select* yy375; - ExprList* yy418; + 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; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -78535,8 +79839,8 @@ typedef union { #define sqlite3ParserARG_PDECL ,Parse *pParse #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse -#define YYNSTATE 590 -#define YYNRULE 312 +#define YYNSTATE 598 +#define YYNRULE 315 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) @@ -78598,417 +79902,420 @@ static const YYMINORTYPE yyzerominor; ** yy_default[] Default action for each state. */ static const YYACTIONTYPE yy_action[] = { - /* 0 */ 292, 903, 120, 589, 2, 172, 419, 419, 62, 62, - /* 10 */ 62, 62, 209, 64, 64, 64, 64, 65, 65, 66, - /* 20 */ 66, 66, 67, 211, 392, 389, 426, 432, 69, 64, - /* 30 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 211, - /* 40 */ 448, 213, 397, 452, 61, 60, 297, 436, 437, 433, - /* 50 */ 433, 63, 63, 62, 62, 62, 62, 264, 64, 64, - /* 60 */ 64, 64, 65, 65, 66, 66, 66, 67, 211, 292, - /* 70 */ 317, 419, 419, 490, 211, 83, 68, 421, 70, 154, + /* 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 */ 211, 489, 415, 36, 181, 426, 432, 448, 265, 59, - /* 100 */ 65, 65, 66, 66, 66, 67, 211, 398, 399, 423, - /* 110 */ 423, 423, 292, 61, 60, 297, 436, 437, 433, 433, - /* 120 */ 63, 63, 62, 62, 62, 62, 317, 64, 64, 64, - /* 130 */ 64, 65, 65, 66, 66, 66, 67, 211, 426, 432, - /* 140 */ 95, 313, 394, 475, 237, 172, 208, 419, 415, 35, - /* 150 */ 57, 67, 211, 201, 411, 475, 61, 60, 297, 436, - /* 160 */ 437, 433, 433, 63, 63, 62, 62, 62, 62, 503, + /* 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 */ 211, 292, 481, 524, 542, 573, 109, 416, 541, 452, - /* 190 */ 331, 317, 408, 21, 240, 340, 409, 522, 317, 68, - /* 200 */ 362, 70, 154, 572, 571, 519, 492, 426, 432, 149, - /* 210 */ 150, 380, 419, 415, 42, 412, 151, 533, 202, 490, - /* 220 */ 415, 50, 532, 421, 292, 61, 60, 297, 436, 437, - /* 230 */ 433, 433, 63, 63, 62, 62, 62, 62, 388, 64, - /* 240 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 211, - /* 250 */ 426, 432, 416, 333, 216, 423, 423, 423, 66, 66, - /* 260 */ 66, 67, 211, 491, 568, 212, 308, 292, 61, 60, - /* 270 */ 297, 436, 437, 433, 433, 63, 63, 62, 62, 62, - /* 280 */ 62, 397, 64, 64, 64, 64, 65, 65, 66, 66, - /* 290 */ 66, 67, 211, 426, 432, 182, 300, 410, 345, 348, - /* 300 */ 349, 531, 506, 252, 68, 519, 70, 154, 530, 350, - /* 310 */ 231, 61, 60, 297, 436, 437, 433, 433, 63, 63, - /* 320 */ 62, 62, 62, 62, 575, 64, 64, 64, 64, 65, - /* 330 */ 65, 66, 66, 66, 67, 211, 525, 317, 303, 78, - /* 340 */ 292, 238, 300, 511, 485, 153, 398, 399, 182, 494, - /* 350 */ 495, 345, 348, 349, 320, 152, 439, 439, 339, 415, - /* 360 */ 28, 328, 350, 512, 222, 370, 426, 432, 547, 495, - /* 370 */ 164, 114, 244, 343, 249, 344, 176, 583, 291, 416, - /* 380 */ 415, 3, 81, 253, 61, 60, 297, 436, 437, 433, - /* 390 */ 433, 63, 63, 62, 62, 62, 62, 174, 64, 64, - /* 400 */ 64, 64, 65, 65, 66, 66, 66, 67, 211, 292, - /* 410 */ 222, 587, 894, 488, 894, 302, 573, 114, 244, 343, - /* 420 */ 249, 344, 176, 182, 317, 397, 345, 348, 349, 253, - /* 430 */ 224, 416, 155, 549, 572, 426, 432, 350, 68, 463, - /* 440 */ 70, 154, 397, 175, 160, 397, 415, 35, 338, 587, - /* 450 */ 893, 584, 893, 61, 60, 297, 436, 437, 433, 433, - /* 460 */ 63, 63, 62, 62, 62, 62, 416, 64, 64, 64, - /* 470 */ 64, 65, 65, 66, 66, 66, 67, 211, 292, 550, - /* 480 */ 448, 213, 505, 373, 270, 269, 171, 160, 331, 584, - /* 490 */ 398, 399, 317, 330, 209, 383, 212, 159, 427, 428, - /* 500 */ 569, 570, 483, 524, 426, 432, 336, 398, 399, 230, - /* 510 */ 398, 399, 534, 21, 415, 42, 239, 549, 479, 430, - /* 520 */ 431, 475, 61, 60, 297, 436, 437, 433, 433, 63, - /* 530 */ 63, 62, 62, 62, 62, 264, 64, 64, 64, 64, - /* 540 */ 65, 65, 66, 66, 66, 67, 211, 292, 429, 287, - /* 550 */ 457, 256, 450, 523, 168, 215, 197, 295, 317, 353, - /* 560 */ 242, 317, 458, 298, 443, 444, 468, 373, 270, 269, - /* 570 */ 322, 443, 444, 426, 432, 459, 558, 496, 209, 299, - /* 580 */ 415, 35, 544, 415, 50, 1, 177, 497, 479, 397, - /* 590 */ 416, 61, 60, 297, 436, 437, 433, 433, 63, 63, - /* 600 */ 62, 62, 62, 62, 484, 64, 64, 64, 64, 65, - /* 610 */ 65, 66, 66, 66, 67, 211, 292, 317, 524, 375, - /* 620 */ 457, 94, 335, 590, 392, 389, 212, 580, 21, 309, - /* 630 */ 10, 363, 458, 212, 397, 209, 366, 391, 2, 415, - /* 640 */ 29, 294, 426, 432, 195, 459, 253, 327, 372, 361, - /* 650 */ 440, 450, 323, 168, 398, 399, 252, 147, 546, 292, - /* 660 */ 61, 60, 297, 436, 437, 433, 433, 63, 63, 62, - /* 670 */ 62, 62, 62, 317, 64, 64, 64, 64, 65, 65, - /* 680 */ 66, 66, 66, 67, 211, 426, 432, 210, 318, 453, - /* 690 */ 320, 223, 439, 439, 56, 415, 24, 826, 252, 398, - /* 700 */ 399, 193, 292, 61, 60, 297, 436, 437, 433, 433, - /* 710 */ 63, 63, 62, 62, 62, 62, 226, 64, 64, 64, - /* 720 */ 64, 65, 65, 66, 66, 66, 67, 211, 426, 432, - /* 730 */ 311, 119, 264, 304, 396, 416, 320, 19, 439, 439, - /* 740 */ 400, 401, 402, 85, 274, 292, 61, 71, 297, 436, - /* 750 */ 437, 433, 433, 63, 63, 62, 62, 62, 62, 371, - /* 760 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67, - /* 770 */ 211, 426, 432, 385, 115, 320, 18, 439, 439, 446, - /* 780 */ 446, 374, 277, 5, 275, 264, 8, 252, 292, 341, - /* 790 */ 60, 297, 436, 437, 433, 433, 63, 63, 62, 62, - /* 800 */ 62, 62, 397, 64, 64, 64, 64, 65, 65, 66, - /* 810 */ 66, 66, 67, 211, 426, 432, 414, 397, 422, 470, - /* 820 */ 413, 22, 305, 387, 252, 419, 560, 193, 414, 264, - /* 830 */ 264, 370, 413, 190, 297, 436, 437, 433, 433, 63, - /* 840 */ 63, 62, 62, 62, 62, 479, 64, 64, 64, 64, - /* 850 */ 65, 65, 66, 66, 66, 67, 211, 73, 324, 306, - /* 860 */ 4, 416, 264, 276, 296, 449, 177, 398, 399, 317, - /* 870 */ 561, 562, 321, 73, 324, 317, 4, 540, 360, 540, - /* 880 */ 296, 329, 398, 399, 461, 371, 158, 317, 321, 326, - /* 890 */ 419, 415, 33, 471, 317, 165, 225, 415, 54, 452, - /* 900 */ 317, 264, 317, 278, 317, 326, 307, 367, 472, 415, - /* 910 */ 53, 470, 178, 179, 180, 452, 415, 99, 317, 76, - /* 920 */ 75, 294, 415, 97, 415, 102, 415, 103, 74, 315, - /* 930 */ 316, 319, 264, 421, 469, 76, 75, 482, 317, 382, - /* 940 */ 415, 108, 379, 474, 74, 315, 316, 73, 324, 421, - /* 950 */ 4, 209, 317, 156, 296, 317, 184, 465, 209, 187, - /* 960 */ 415, 110, 321, 258, 466, 423, 423, 423, 424, 425, - /* 970 */ 12, 381, 478, 280, 415, 17, 250, 415, 100, 326, - /* 980 */ 507, 423, 423, 423, 424, 425, 12, 416, 624, 452, - /* 990 */ 416, 162, 508, 416, 317, 513, 227, 228, 229, 105, - /* 1000 */ 514, 262, 317, 260, 20, 317, 144, 434, 317, 76, - /* 1010 */ 75, 77, 206, 79, 282, 317, 415, 34, 74, 315, - /* 1020 */ 316, 283, 317, 421, 415, 98, 251, 415, 25, 526, - /* 1030 */ 415, 55, 441, 204, 23, 549, 257, 415, 111, 203, - /* 1040 */ 317, 477, 205, 173, 415, 112, 317, 259, 317, 515, - /* 1050 */ 317, 181, 317, 261, 245, 423, 423, 423, 424, 425, - /* 1060 */ 12, 263, 415, 113, 357, 246, 317, 268, 415, 26, - /* 1070 */ 415, 37, 415, 38, 415, 27, 317, 500, 501, 510, - /* 1080 */ 509, 317, 365, 317, 368, 378, 279, 269, 415, 39, - /* 1090 */ 369, 293, 317, 255, 317, 181, 209, 271, 415, 40, - /* 1100 */ 317, 272, 317, 415, 41, 415, 43, 352, 317, 181, - /* 1110 */ 317, 273, 557, 317, 415, 44, 415, 45, 317, 545, - /* 1120 */ 384, 181, 415, 30, 415, 31, 317, 585, 567, 317, - /* 1130 */ 415, 46, 415, 47, 317, 415, 48, 317, 281, 284, - /* 1140 */ 415, 49, 553, 554, 173, 92, 285, 579, 415, 32, - /* 1150 */ 406, 415, 11, 565, 420, 92, 415, 51, 146, 415, - /* 1160 */ 52, 582, 232, 290, 325, 517, 586, 445, 447, 464, - /* 1170 */ 467, 506, 520, 163, 247, 516, 395, 518, 552, 347, - /* 1180 */ 403, 404, 405, 564, 7, 314, 85, 334, 332, 233, - /* 1190 */ 84, 234, 80, 170, 58, 214, 417, 462, 121, 86, - /* 1200 */ 337, 342, 499, 493, 235, 301, 236, 503, 418, 498, - /* 1210 */ 248, 124, 504, 502, 220, 354, 288, 241, 527, 476, - /* 1220 */ 243, 528, 480, 521, 529, 289, 185, 358, 535, 186, - /* 1230 */ 89, 356, 189, 188, 117, 537, 364, 191, 548, 194, - /* 1240 */ 219, 132, 142, 221, 376, 377, 555, 133, 134, 310, - /* 1250 */ 135, 136, 266, 563, 538, 581, 576, 141, 93, 393, - /* 1260 */ 96, 138, 407, 577, 578, 107, 218, 101, 104, 118, - /* 1270 */ 312, 625, 626, 166, 435, 167, 438, 442, 72, 454, - /* 1280 */ 451, 143, 157, 169, 455, 456, 460, 6, 14, 82, - /* 1290 */ 473, 13, 122, 161, 123, 486, 487, 217, 87, 346, - /* 1300 */ 125, 126, 116, 254, 88, 127, 183, 246, 355, 145, - /* 1310 */ 536, 128, 173, 359, 192, 351, 267, 130, 9, 551, - /* 1320 */ 131, 196, 90, 539, 91, 129, 15, 198, 556, 543, - /* 1330 */ 199, 559, 200, 137, 139, 566, 16, 140, 106, 574, - /* 1340 */ 207, 148, 286, 390, 386, 588, + /* 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, }; static const YYCODETYPE yy_lookahead[] = { - /* 0 */ 16, 139, 140, 141, 142, 21, 23, 23, 69, 70, + /* 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, /* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - /* 40 */ 78, 79, 23, 58, 60, 61, 62, 63, 64, 65, - /* 50 */ 66, 67, 68, 69, 70, 71, 72, 147, 74, 75, + /* 40 */ 58, 162, 163, 164, 60, 61, 62, 63, 64, 65, + /* 50 */ 66, 67, 68, 69, 70, 71, 72, 148, 74, 75, /* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16, - /* 70 */ 147, 88, 88, 88, 84, 22, 217, 92, 219, 220, + /* 70 */ 88, 88, 88, 84, 92, 22, 219, 220, 221, 222, /* 80 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 90 */ 84, 169, 169, 170, 22, 42, 43, 78, 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, + /* 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, /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, - /* 140 */ 44, 143, 144, 161, 221, 21, 148, 23, 169, 170, - /* 150 */ 19, 83, 84, 155, 23, 161, 60, 61, 62, 63, - /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 97, + /* 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, /* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - /* 180 */ 84, 16, 200, 147, 25, 147, 21, 189, 29, 58, - /* 190 */ 211, 147, 156, 157, 200, 216, 167, 168, 147, 217, - /* 200 */ 41, 219, 220, 165, 166, 176, 160, 42, 43, 78, - /* 210 */ 79, 213, 88, 169, 170, 169, 180, 181, 155, 88, - /* 220 */ 169, 170, 181, 92, 16, 60, 61, 62, 63, 64, - /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 240, 74, + /* 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, /* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - /* 250 */ 42, 43, 189, 209, 210, 124, 125, 126, 80, 81, - /* 260 */ 82, 83, 84, 169, 226, 227, 215, 16, 60, 61, + /* 250 */ 42, 43, 78, 0, 1, 2, 125, 126, 127, 226, + /* 260 */ 11, 162, 88, 89, 231, 228, 229, 16, 60, 61, /* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - /* 280 */ 72, 23, 74, 75, 76, 77, 78, 79, 80, 81, - /* 290 */ 82, 83, 84, 42, 43, 90, 16, 168, 93, 94, - /* 300 */ 95, 176, 177, 147, 217, 176, 219, 220, 183, 104, - /* 310 */ 190, 60, 61, 62, 63, 64, 65, 66, 67, 68, - /* 320 */ 69, 70, 71, 72, 237, 74, 75, 76, 77, 78, - /* 330 */ 79, 80, 81, 82, 83, 84, 181, 147, 182, 131, - /* 340 */ 16, 147, 16, 30, 20, 155, 88, 89, 90, 185, - /* 350 */ 186, 93, 94, 95, 106, 22, 108, 109, 147, 169, - /* 360 */ 170, 186, 104, 50, 84, 147, 42, 43, 185, 186, - /* 370 */ 90, 91, 92, 93, 94, 95, 96, 243, 244, 189, - /* 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, 19, 20, 20, 22, 102, 147, 91, 92, 93, - /* 420 */ 94, 95, 96, 90, 147, 23, 93, 94, 95, 103, - /* 430 */ 212, 189, 155, 49, 165, 42, 43, 104, 217, 218, - /* 440 */ 219, 220, 23, 201, 202, 23, 169, 170, 206, 19, - /* 450 */ 20, 59, 22, 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, 11, - /* 480 */ 78, 79, 20, 99, 100, 101, 201, 202, 211, 59, - /* 490 */ 88, 89, 147, 216, 110, 226, 227, 147, 42, 43, - /* 500 */ 98, 99, 80, 147, 42, 43, 147, 88, 89, 153, - /* 510 */ 88, 89, 156, 157, 169, 170, 147, 49, 147, 63, - /* 520 */ 64, 161, 60, 61, 62, 63, 64, 65, 66, 67, - /* 530 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77, - /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 92, 158, - /* 550 */ 12, 20, 161, 162, 163, 210, 155, 150, 147, 16, - /* 560 */ 200, 147, 24, 164, 165, 166, 22, 99, 100, 101, - /* 570 */ 164, 165, 166, 42, 43, 37, 188, 39, 110, 208, - /* 580 */ 169, 170, 18, 169, 170, 19, 43, 49, 147, 23, - /* 590 */ 189, 60, 61, 62, 63, 64, 65, 66, 67, 68, - /* 600 */ 69, 70, 71, 72, 20, 74, 75, 76, 77, 78, - /* 610 */ 79, 80, 81, 82, 83, 84, 16, 147, 147, 55, - /* 620 */ 12, 21, 211, 0, 1, 2, 227, 156, 157, 215, - /* 630 */ 19, 224, 24, 227, 23, 110, 229, 141, 142, 169, - /* 640 */ 170, 98, 42, 43, 22, 37, 103, 39, 123, 208, - /* 650 */ 20, 161, 162, 163, 88, 89, 147, 113, 94, 16, - /* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - /* 670 */ 70, 71, 72, 147, 74, 75, 76, 77, 78, 79, - /* 680 */ 80, 81, 82, 83, 84, 42, 43, 192, 147, 20, - /* 690 */ 106, 182, 108, 109, 199, 169, 170, 133, 147, 88, - /* 700 */ 89, 155, 16, 60, 61, 62, 63, 64, 65, 66, - /* 710 */ 67, 68, 69, 70, 71, 72, 145, 74, 75, 76, - /* 720 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, - /* 730 */ 241, 242, 147, 182, 147, 189, 106, 19, 108, 109, - /* 740 */ 7, 8, 9, 121, 14, 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, 147, 106, 230, 108, 109, 124, - /* 780 */ 125, 235, 52, 191, 54, 147, 68, 147, 16, 80, - /* 790 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - /* 800 */ 71, 72, 23, 74, 75, 76, 77, 78, 79, 80, - /* 810 */ 81, 82, 83, 84, 42, 43, 107, 23, 147, 22, - /* 820 */ 111, 19, 182, 238, 147, 23, 188, 155, 107, 147, - /* 830 */ 147, 147, 111, 231, 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, 182, - /* 860 */ 19, 189, 147, 133, 23, 161, 43, 88, 89, 147, - /* 870 */ 188, 188, 31, 16, 17, 147, 19, 99, 100, 101, - /* 880 */ 23, 147, 88, 89, 147, 213, 89, 147, 31, 48, - /* 890 */ 88, 169, 170, 114, 147, 19, 212, 169, 170, 58, - /* 900 */ 147, 147, 147, 188, 147, 48, 208, 235, 114, 169, - /* 910 */ 170, 114, 99, 100, 101, 58, 169, 170, 147, 78, - /* 920 */ 79, 98, 169, 170, 169, 170, 169, 170, 87, 88, - /* 930 */ 89, 16, 147, 92, 203, 78, 79, 80, 147, 91, - /* 940 */ 169, 170, 188, 147, 87, 88, 89, 16, 17, 92, - /* 950 */ 19, 110, 147, 155, 23, 147, 155, 27, 110, 155, - /* 960 */ 169, 170, 31, 14, 34, 124, 125, 126, 127, 128, - /* 970 */ 129, 123, 147, 188, 169, 170, 147, 169, 170, 48, - /* 980 */ 147, 124, 125, 126, 127, 128, 129, 189, 112, 58, - /* 990 */ 189, 5, 178, 189, 147, 178, 10, 11, 12, 13, - /* 1000 */ 178, 52, 147, 54, 19, 147, 21, 92, 147, 78, - /* 1010 */ 79, 130, 26, 132, 28, 147, 169, 170, 87, 88, - /* 1020 */ 89, 35, 147, 92, 169, 170, 147, 169, 170, 147, - /* 1030 */ 169, 170, 20, 47, 22, 49, 147, 169, 170, 53, - /* 1040 */ 147, 20, 56, 22, 169, 170, 147, 147, 147, 20, - /* 1050 */ 147, 22, 147, 147, 92, 124, 125, 126, 127, 128, - /* 1060 */ 129, 147, 169, 170, 232, 103, 147, 147, 169, 170, - /* 1070 */ 169, 170, 169, 170, 169, 170, 147, 7, 8, 91, - /* 1080 */ 92, 147, 147, 147, 147, 99, 100, 101, 169, 170, - /* 1090 */ 147, 105, 147, 20, 147, 22, 110, 147, 169, 170, - /* 1100 */ 147, 147, 147, 169, 170, 169, 170, 20, 147, 22, - /* 1110 */ 147, 147, 147, 147, 169, 170, 169, 170, 147, 20, - /* 1120 */ 134, 22, 169, 170, 169, 170, 147, 20, 147, 147, - /* 1130 */ 169, 170, 169, 170, 147, 169, 170, 147, 147, 147, - /* 1140 */ 169, 170, 20, 20, 22, 22, 147, 147, 169, 170, - /* 1150 */ 149, 169, 170, 20, 161, 22, 169, 170, 191, 169, - /* 1160 */ 170, 20, 193, 22, 223, 161, 59, 228, 228, 172, - /* 1170 */ 172, 177, 161, 6, 172, 172, 146, 172, 194, 173, - /* 1180 */ 146, 146, 146, 194, 22, 154, 121, 118, 116, 194, - /* 1190 */ 119, 195, 130, 112, 120, 222, 189, 152, 152, 98, - /* 1200 */ 115, 98, 179, 171, 196, 40, 197, 97, 198, 171, - /* 1210 */ 171, 19, 171, 173, 84, 15, 174, 204, 171, 205, - /* 1220 */ 204, 171, 205, 179, 171, 174, 151, 38, 152, 151, - /* 1230 */ 130, 152, 152, 151, 60, 152, 152, 151, 184, 184, - /* 1240 */ 225, 19, 214, 225, 152, 15, 194, 187, 187, 152, - /* 1250 */ 187, 187, 233, 194, 234, 137, 33, 214, 236, 1, - /* 1260 */ 236, 184, 20, 152, 152, 239, 175, 159, 175, 242, - /* 1270 */ 245, 112, 112, 112, 92, 112, 107, 20, 19, 11, - /* 1280 */ 20, 19, 19, 22, 20, 20, 20, 117, 117, 22, - /* 1290 */ 114, 22, 19, 112, 20, 20, 20, 44, 19, 44, - /* 1300 */ 19, 19, 32, 20, 19, 19, 96, 103, 16, 21, - /* 1310 */ 17, 98, 22, 36, 98, 44, 133, 19, 5, 1, - /* 1320 */ 102, 122, 68, 51, 68, 45, 19, 113, 1, 45, - /* 1330 */ 14, 17, 115, 113, 102, 123, 19, 122, 14, 20, - /* 1340 */ 135, 19, 136, 3, 57, 4, + /* 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, }; #define YY_SHIFT_USE_DFLT (-99) -#define YY_SHIFT_MAX 390 +#define YY_SHIFT_MAX 396 static const short yy_shift_ofst[] = { - /* 0 */ 23, 841, 986, -16, 841, 931, 931, 258, 402, 384, - /* 10 */ -98, 96, 931, 931, 931, 931, 931, -45, 468, 19, - /* 20 */ 419, -17, -38, -38, 53, 165, 208, 251, 324, 393, - /* 30 */ 462, 531, 600, 643, 686, 643, 643, 643, 643, 643, - /* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, - /* 50 */ 643, 643, 643, 729, 772, 772, 857, 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, 931, -61, -61, 6, - /* 100 */ 6, 280, 22, 178, 543, 564, 419, 419, 68, -17, - /* 110 */ -10, -99, -99, -99, 131, 326, 538, 538, 392, 430, - /* 120 */ 623, 124, 419, 124, 419, 419, 419, 419, 419, 419, - /* 130 */ 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, - /* 140 */ 419, 848, 525, -98, -98, -98, -99, -99, -99, -15, - /* 150 */ -15, 333, 205, 584, 566, 630, 669, 608, 779, 794, - /* 160 */ 611, 422, 733, 419, 419, 709, 419, 419, 802, 419, - /* 170 */ 419, 797, 419, 419, 248, 797, 419, 419, 313, 313, - /* 180 */ 313, 419, 419, 419, 248, 419, 419, 248, 419, 159, - /* 190 */ 778, 419, 419, 248, 419, 419, 419, 248, 419, 419, - /* 200 */ 419, 248, 248, 419, 419, 419, 419, 419, 985, 721, - /* 210 */ 544, -17, 655, 655, 881, 930, 930, 930, 823, 930, - /* 220 */ -17, 930, -17, 72, 622, 622, 1167, 1167, 1167, 1167, - /* 230 */ 1162, -98, 1065, 1069, 1071, 1072, 1074, 1062, 1081, 1081, - /* 240 */ 1101, 1085, 1101, 1085, 1103, 1103, 1165, 1103, 1110, 1103, - /* 250 */ 1192, 1130, 1130, 1165, 1103, 1103, 1103, 1192, 1200, 1081, - /* 260 */ 1200, 1081, 1200, 1081, 1081, 1189, 1100, 1200, 1081, 1174, - /* 270 */ 1174, 1222, 1065, 1081, 1230, 1230, 1230, 1230, 1065, 1174, - /* 280 */ 1222, 1081, 1223, 1223, 1081, 1081, 1118, -99, -99, -99, - /* 290 */ -99, -99, 456, 730, 813, 949, 876, 915, 1012, 1021, - /* 300 */ 962, 1070, 988, 1029, 1073, 1087, 1099, 1122, 1123, 1133, - /* 310 */ 718, 1141, 1107, 1258, 1242, 1159, 1160, 1161, 1163, 1182, - /* 320 */ 1169, 1259, 1257, 1260, 1262, 1268, 1263, 1264, 1261, 1265, - /* 330 */ 1266, 1267, 1170, 1269, 1171, 1267, 1176, 1273, 1274, 1181, - /* 340 */ 1275, 1276, 1270, 1253, 1279, 1255, 1281, 1283, 1282, 1285, - /* 350 */ 1271, 1286, 1210, 1204, 1292, 1293, 1288, 1213, 1277, 1272, - /* 360 */ 1280, 1290, 1284, 1183, 1216, 1298, 1313, 1318, 1218, 1254, - /* 370 */ 1256, 1199, 1307, 1214, 1327, 1316, 1217, 1314, 1220, 1232, - /* 380 */ 1215, 1317, 1212, 1319, 1324, 1287, 1205, 1206, 1322, 1340, - /* 390 */ 1341, + /* 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, }; -#define YY_REDUCE_USE_DFLT (-142) -#define YY_REDUCE_MAX 291 +#define YY_REDUCE_USE_DFLT (-144) +#define YY_REDUCE_MAX 295 static const short yy_reduce_ofst[] = { - /* 0 */ -138, 277, -2, -18, 190, -21, 44, 36, 38, 546, - /* 10 */ 242, 87, -77, 345, 411, 51, 414, 221, 672, 269, - /* 20 */ 356, 391, 399, 406, -141, -141, -141, -141, -141, -141, - /* 30 */ -141, -141, -141, -141, -141, -141, -141, -141, -141, -141, - /* 40 */ -141, -141, -141, -141, -141, -141, -141, -141, -141, -141, - /* 50 */ -141, -141, -141, -141, -141, -141, 211, 470, 526, 722, - /* 60 */ 728, 740, 747, 753, 755, 757, 771, 791, 805, 808, - /* 70 */ 847, 855, 858, 861, 868, 875, 893, 899, 901, 903, - /* 80 */ 905, 919, 929, 934, 936, 945, 947, 953, 955, 961, - /* 90 */ 963, 966, 971, 979, 982, 987, 990, -141, -141, -141, - /* 100 */ -141, 29, -141, -141, 125, 407, 585, 471, -141, 490, - /* 110 */ -141, -141, -141, -141, 46, 129, 164, 183, 134, 134, - /* 120 */ 496, -6, 371, 360, 156, 509, 551, 640, -90, 441, - /* 130 */ 677, 218, 698, 388, 638, 682, 683, 715, 754, 684, - /* 140 */ 785, 63, 401, 798, 801, 804, 495, 285, 489, -78, - /* 150 */ 94, 41, 155, 120, 194, 120, 120, 175, 350, 359, - /* 160 */ 369, 541, 571, 587, 627, 592, 541, 671, 704, 734, - /* 170 */ 737, 731, 796, 825, 120, 731, 829, 833, 814, 817, - /* 180 */ 822, 879, 882, 889, 120, 900, 906, 120, 914, 602, - /* 190 */ 832, 920, 935, 120, 937, 943, 950, 120, 954, 964, - /* 200 */ 965, 120, 120, 981, 991, 992, 999, 1000, 1001, 967, - /* 210 */ 969, 993, 939, 940, 941, 997, 998, 1002, 994, 1003, - /* 220 */ 1004, 1005, 1011, 1006, 984, 989, 1030, 1034, 1035, 1036, - /* 230 */ 1031, 1007, 995, 996, 1008, 1009, 1010, 973, 1045, 1046, - /* 240 */ 1013, 1014, 1016, 1017, 1032, 1038, 1023, 1039, 1040, 1041, - /* 250 */ 1042, 1015, 1018, 1044, 1047, 1050, 1053, 1051, 1075, 1076, - /* 260 */ 1078, 1079, 1082, 1080, 1083, 1019, 1020, 1086, 1084, 1054, - /* 270 */ 1055, 1028, 1052, 1092, 1060, 1061, 1063, 1064, 1059, 1077, - /* 280 */ 1043, 1097, 1022, 1024, 1111, 1112, 1026, 1108, 1091, 1093, - /* 290 */ 1027, 1025, + /* 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, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 595, 821, 902, 711, 902, 821, 902, 902, 848, 902, - /* 10 */ 715, 877, 819, 902, 902, 902, 902, 793, 902, 848, - /* 20 */ 902, 627, 848, 848, 744, 902, 902, 902, 902, 902, - /* 30 */ 902, 902, 902, 745, 902, 823, 818, 814, 816, 815, - /* 40 */ 822, 746, 735, 742, 749, 727, 861, 751, 752, 758, - /* 50 */ 759, 878, 876, 781, 780, 799, 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, 902, 783, 805, 782, - /* 100 */ 792, 620, 784, 785, 680, 615, 902, 902, 786, 902, - /* 110 */ 787, 800, 801, 802, 902, 902, 902, 902, 902, 902, - /* 120 */ 595, 711, 902, 711, 902, 902, 902, 902, 902, 902, - /* 130 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, - /* 140 */ 902, 902, 902, 902, 902, 902, 705, 715, 895, 902, - /* 150 */ 902, 671, 902, 902, 902, 902, 902, 902, 902, 902, - /* 160 */ 902, 902, 603, 601, 902, 703, 902, 902, 629, 902, - /* 170 */ 902, 713, 902, 902, 718, 719, 902, 902, 902, 902, - /* 180 */ 902, 902, 902, 902, 617, 902, 902, 692, 902, 854, - /* 190 */ 902, 902, 902, 868, 902, 902, 902, 866, 902, 902, - /* 200 */ 902, 694, 754, 834, 902, 881, 883, 902, 902, 703, - /* 210 */ 712, 902, 902, 902, 817, 738, 738, 738, 650, 738, - /* 220 */ 902, 738, 902, 653, 748, 748, 600, 600, 600, 600, - /* 230 */ 670, 902, 748, 739, 741, 731, 743, 902, 720, 720, - /* 240 */ 728, 730, 728, 730, 682, 682, 667, 682, 653, 682, - /* 250 */ 827, 831, 831, 667, 682, 682, 682, 827, 612, 720, - /* 260 */ 612, 720, 612, 720, 720, 858, 860, 612, 720, 684, - /* 270 */ 684, 760, 748, 720, 691, 691, 691, 691, 748, 684, - /* 280 */ 760, 720, 880, 880, 720, 720, 888, 637, 655, 655, - /* 290 */ 895, 900, 902, 902, 902, 902, 767, 902, 902, 902, - /* 300 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, - /* 310 */ 841, 902, 902, 902, 902, 772, 768, 902, 769, 902, - /* 320 */ 697, 902, 902, 902, 902, 902, 902, 902, 902, 902, - /* 330 */ 902, 820, 902, 732, 902, 740, 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, 902, 887, 902, 902, 890, 596, - /* 390 */ 902, 591, 593, 594, 598, 599, 602, 624, 625, 626, - /* 400 */ 604, 605, 606, 607, 608, 609, 610, 616, 618, 636, - /* 410 */ 638, 622, 640, 701, 702, 764, 695, 696, 700, 623, - /* 420 */ 775, 766, 770, 771, 773, 774, 788, 789, 791, 797, - /* 430 */ 804, 807, 790, 795, 796, 798, 803, 806, 698, 699, - /* 440 */ 810, 630, 631, 634, 635, 844, 846, 845, 847, 633, - /* 450 */ 632, 776, 779, 812, 813, 869, 870, 871, 872, 873, - /* 460 */ 808, 721, 811, 794, 733, 736, 737, 734, 704, 714, - /* 470 */ 723, 724, 725, 726, 709, 710, 716, 729, 762, 763, - /* 480 */ 717, 706, 707, 708, 809, 765, 777, 778, 641, 642, - /* 490 */ 772, 643, 644, 645, 683, 686, 687, 688, 646, 665, - /* 500 */ 668, 669, 647, 654, 648, 649, 656, 657, 658, 661, - /* 510 */ 662, 663, 664, 659, 660, 828, 829, 832, 830, 651, - /* 520 */ 652, 666, 639, 628, 621, 672, 675, 676, 677, 678, - /* 530 */ 679, 681, 673, 674, 619, 611, 613, 722, 850, 859, - /* 540 */ 855, 851, 852, 853, 614, 824, 825, 685, 756, 757, - /* 550 */ 849, 862, 864, 761, 865, 867, 863, 892, 689, 690, - /* 560 */ 693, 833, 874, 747, 750, 753, 755, 835, 836, 837, - /* 570 */ 838, 839, 842, 843, 840, 875, 879, 882, 884, 885, - /* 580 */ 886, 889, 891, 896, 897, 898, 901, 899, 597, 592, + /* 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, }; #define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0])) @@ -79139,9 +80446,10 @@ 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 */ @@ -79267,40 +80575,40 @@ static const char *const yyTokenName[] = { "UPDATE", "INSERT", "SET", "DEFERRABLE", "FOREIGN", "DROP", "UNION", "ALL", "EXCEPT", "INTERSECT", "SELECT", "DISTINCT", - "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", "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", - "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", "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", }; #endif /* NDEBUG */ @@ -79434,7 +80742,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 on_opt using_opt", + /* 126 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt 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", @@ -79447,179 +80755,182 @@ static const char *const yyRuleName[] = { /* 136 */ "joinop ::= JOIN_KW nm nm JOIN", /* 137 */ "on_opt ::= ON expr", /* 138 */ "on_opt ::=", - /* 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 nm collate sortorder", - /* 240 */ "idxlist ::= nm collate sortorder", - /* 241 */ "collate ::=", - /* 242 */ "collate ::= COLLATE ids", - /* 243 */ "cmd ::= DROP INDEX ifexists fullname", - /* 244 */ "cmd ::= VACUUM", - /* 245 */ "cmd ::= VACUUM nm", - /* 246 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 247 */ "cmd ::= PRAGMA nm dbnm EQ ON", - /* 248 */ "cmd ::= PRAGMA nm dbnm EQ DELETE", - /* 249 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 250 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 251 */ "cmd ::= PRAGMA nm dbnm", - /* 252 */ "nmnum ::= plus_num", - /* 253 */ "nmnum ::= nm", - /* 254 */ "plus_num ::= plus_opt number", - /* 255 */ "minus_num ::= MINUS number", - /* 256 */ "number ::= INTEGER|FLOAT", - /* 257 */ "plus_opt ::= PLUS", - /* 258 */ "plus_opt ::=", - /* 259 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", - /* 260 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 261 */ "trigger_time ::= BEFORE", - /* 262 */ "trigger_time ::= AFTER", - /* 263 */ "trigger_time ::= INSTEAD OF", - /* 264 */ "trigger_time ::=", - /* 265 */ "trigger_event ::= DELETE|INSERT", - /* 266 */ "trigger_event ::= UPDATE", - /* 267 */ "trigger_event ::= UPDATE OF inscollist", - /* 268 */ "foreach_clause ::=", - /* 269 */ "foreach_clause ::= FOR EACH ROW", - /* 270 */ "when_clause ::=", - /* 271 */ "when_clause ::= WHEN expr", - /* 272 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 273 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", - /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", - /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", - /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt", - /* 278 */ "trigger_cmd ::= select", - /* 279 */ "expr ::= RAISE LP IGNORE RP", - /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 281 */ "raisetype ::= ROLLBACK", - /* 282 */ "raisetype ::= ABORT", - /* 283 */ "raisetype ::= FAIL", - /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 286 */ "cmd ::= DETACH database_kw_opt expr", - /* 287 */ "key_opt ::=", - /* 288 */ "key_opt ::= KEY expr", - /* 289 */ "database_kw_opt ::= DATABASE", - /* 290 */ "database_kw_opt ::=", - /* 291 */ "cmd ::= REINDEX", - /* 292 */ "cmd ::= REINDEX nm dbnm", - /* 293 */ "cmd ::= ANALYZE", - /* 294 */ "cmd ::= ANALYZE nm dbnm", - /* 295 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 296 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 297 */ "add_column_fullname ::= fullname", - /* 298 */ "kwcolumn_opt ::=", - /* 299 */ "kwcolumn_opt ::= COLUMNKW", - /* 300 */ "cmd ::= create_vtab", - /* 301 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 302 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm", - /* 303 */ "vtabarglist ::= vtabarg", - /* 304 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 305 */ "vtabarg ::=", - /* 306 */ "vtabarg ::= vtabarg vtabargtoken", - /* 307 */ "vtabargtoken ::= ANY", - /* 308 */ "vtabargtoken ::= lp anylist RP", - /* 309 */ "lp ::= LP", - /* 310 */ "anylist ::=", - /* 311 */ "anylist ::= anylist ANY", + /* 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", }; #endif /* NDEBUG */ @@ -79668,6 +80979,8 @@ SQLITE_PRIVATE void *sqlite3ParserAlloc(void *(*mallocProc)(size_t)){ pParser->yyidxMax = 0; #endif #if YYSTACKDEPTH<=0 + pParser->yystack = NULL; + pParser->yystksz = 0; yyGrowStack(pParser); #endif } @@ -79696,68 +81009,68 @@ static void yy_destructor( ** which appear on the RHS of the rule, but which are not used ** inside the C code. */ - case 155: /* select */ - case 189: /* oneselect */ - case 206: /* seltablist_paren */ + case 156: /* select */ + case 190: /* oneselect */ + case 208: /* seltablist_paren */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy375)); +sqlite3SelectDelete(pParse->db, (yypminor->yy43)); } break; - 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 234: /* when_clause */ - case 237: /* key_opt */ + 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 */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy62)); +sqlite3ExprDelete(pParse->db, (yypminor->yy450)); } break; - 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 */ + 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 */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy418)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy242)); } break; - case 188: /* fullname */ - case 193: /* from */ - case 201: /* seltablist */ - case 202: /* stl_prefix */ + case 189: /* fullname */ + case 194: /* from */ + case 202: /* seltablist */ + case 203: /* stl_prefix */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy151)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy419)); } break; - case 205: /* using_opt */ - case 208: /* inscollist */ - case 214: /* inscollist_opt */ + case 207: /* using_opt */ + case 210: /* inscollist */ + case 216: /* inscollist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy240)); +sqlite3IdListDelete(pParse->db, (yypminor->yy352)); } break; - case 230: /* trigger_cmd_list */ - case 235: /* trigger_cmd */ + case 232: /* trigger_cmd_list */ + case 237: /* trigger_cmd */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy360)); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy75)); } break; - case 232: /* trigger_event */ + case 234: /* trigger_event */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy30).b); +sqlite3IdListDelete(pParse->db, (yypminor->yy354).b); } break; default: break; /* If no destructor action specified: do nothing */ @@ -79989,318 +81302,321 @@ 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 }, - { 141, 3 }, - { 142, 0 }, { 142, 1 }, { 142, 3 }, + { 143, 0 }, { 143, 1 }, - { 144, 3 }, + { 143, 3 }, + { 144, 1 }, + { 145, 3 }, + { 147, 0 }, + { 147, 1 }, + { 147, 2 }, { 146, 0 }, { 146, 1 }, - { 146, 2 }, - { 145, 0 }, - { 145, 1 }, - { 145, 1 }, - { 145, 1 }, - { 144, 2 }, - { 144, 2 }, - { 144, 2 }, - { 144, 2 }, - { 148, 6 }, + { 146, 1 }, + { 146, 1 }, + { 145, 2 }, + { 145, 2 }, + { 145, 2 }, + { 145, 2 }, + { 149, 6 }, + { 152, 0 }, + { 152, 3 }, + { 151, 1 }, { 151, 0 }, - { 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 }, + { 150, 4 }, + { 150, 2 }, + { 154, 3 }, + { 154, 1 }, + { 157, 3 }, { 158, 1 }, + { 161, 1 }, { 162, 1 }, - { 162, 4 }, - { 162, 6 }, + { 148, 1 }, + { 148, 1 }, + { 148, 1 }, + { 159, 0 }, + { 159, 1 }, { 163, 1 }, - { 163, 2 }, - { 164, 1 }, + { 163, 4 }, + { 163, 6 }, { 164, 1 }, - { 159, 2 }, - { 159, 0 }, - { 167, 3 }, - { 167, 1 }, - { 168, 2 }, - { 168, 4 }, + { 164, 2 }, + { 165, 1 }, + { 165, 1 }, + { 160, 2 }, + { 160, 0 }, { 168, 3 }, - { 168, 3 }, - { 168, 2 }, - { 168, 2 }, - { 168, 3 }, - { 168, 5 }, - { 168, 2 }, - { 168, 4 }, - { 168, 4 }, { 168, 1 }, - { 168, 2 }, - { 173, 0 }, - { 173, 1 }, - { 175, 0 }, - { 175, 2 }, - { 177, 2 }, - { 177, 3 }, - { 177, 3 }, - { 177, 3 }, - { 178, 2 }, - { 178, 2 }, - { 178, 1 }, - { 178, 1 }, - { 176, 3 }, + { 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 }, - { 179, 0 }, + { 178, 2 }, + { 178, 3 }, + { 178, 3 }, + { 178, 3 }, { 179, 2 }, { 179, 2 }, - { 154, 0 }, - { 154, 2 }, - { 180, 3 }, + { 179, 1 }, + { 179, 1 }, + { 177, 3 }, + { 177, 2 }, + { 180, 0 }, { 180, 2 }, - { 180, 1 }, + { 180, 2 }, + { 155, 0 }, + { 155, 2 }, + { 181, 3 }, { 181, 2 }, - { 181, 7 }, - { 181, 5 }, - { 181, 5 }, - { 181, 10 }, - { 183, 0 }, - { 183, 1 }, - { 171, 0 }, - { 171, 3 }, + { 181, 1 }, + { 182, 2 }, + { 182, 7 }, + { 182, 5 }, + { 182, 5 }, + { 182, 10 }, { 184, 0 }, - { 184, 2 }, - { 185, 1 }, - { 185, 1 }, - { 185, 1 }, - { 144, 4 }, - { 187, 2 }, - { 187, 0 }, - { 144, 8 }, - { 144, 4 }, - { 144, 1 }, - { 155, 1 }, - { 155, 3 }, - { 190, 1 }, - { 190, 2 }, - { 190, 1 }, - { 189, 9 }, + { 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 }, { 191, 1 }, + { 191, 2 }, { 191, 1 }, - { 191, 0 }, - { 199, 2 }, - { 199, 0 }, - { 192, 3 }, - { 192, 2 }, - { 192, 4 }, + { 190, 9 }, + { 192, 1 }, + { 192, 1 }, + { 192, 0 }, { 200, 2 }, - { 200, 1 }, { 200, 0 }, - { 193, 0 }, + { 193, 3 }, { 193, 2 }, - { 202, 2 }, - { 202, 0 }, - { 201, 6 }, - { 201, 7 }, - { 206, 1 }, - { 206, 1 }, - { 152, 0 }, - { 152, 2 }, - { 188, 2 }, - { 203, 1 }, + { 193, 4 }, + { 201, 2 }, + { 201, 1 }, + { 201, 0 }, + { 194, 0 }, + { 194, 2 }, { 203, 2 }, - { 203, 3 }, - { 203, 4 }, + { 203, 0 }, + { 202, 7 }, + { 202, 7 }, + { 208, 1 }, + { 208, 1 }, + { 153, 0 }, + { 153, 2 }, + { 189, 2 }, + { 204, 1 }, { 204, 2 }, - { 204, 0 }, - { 205, 4 }, + { 204, 3 }, + { 204, 4 }, + { 206, 2 }, + { 206, 0 }, { 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, 3 }, - { 209, 4 }, - { 209, 2 }, - { 210, 1 }, - { 172, 1 }, - { 172, 1 }, - { 172, 0 }, + { 197, 2 }, + { 199, 0 }, + { 199, 2 }, + { 199, 4 }, + { 199, 4 }, + { 145, 5 }, { 195, 0 }, - { 195, 3 }, - { 196, 0 }, - { 196, 2 }, - { 198, 0 }, - { 198, 2 }, - { 198, 4 }, - { 198, 4 }, - { 144, 4 }, - { 194, 0 }, - { 194, 2 }, - { 144, 6 }, - { 212, 5 }, - { 212, 3 }, - { 144, 8 }, - { 144, 5 }, - { 144, 6 }, - { 213, 2 }, - { 213, 1 }, - { 215, 3 }, - { 215, 1 }, - { 214, 0 }, + { 195, 2 }, + { 145, 7 }, + { 214, 5 }, { 214, 3 }, - { 208, 3 }, - { 208, 1 }, - { 170, 1 }, - { 170, 3 }, - { 169, 1 }, + { 145, 8 }, + { 145, 5 }, + { 145, 6 }, + { 215, 2 }, + { 215, 1 }, + { 217, 3 }, + { 217, 1 }, + { 216, 0 }, + { 216, 3 }, + { 210, 3 }, + { 210, 1 }, + { 171, 1 }, + { 171, 3 }, { 170, 1 }, + { 171, 1 }, + { 171, 1 }, + { 171, 3 }, + { 171, 5 }, { 170, 1 }, - { 170, 3 }, - { 170, 5 }, - { 169, 1 }, - { 169, 1 }, { 170, 1 }, + { 171, 1 }, + { 171, 1 }, + { 171, 3 }, + { 171, 6 }, + { 171, 5 }, + { 171, 4 }, { 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 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 171, 3 }, + { 219, 1 }, + { 219, 2 }, { 219, 1 }, { 219, 2 }, - { 170, 5 }, - { 220, 1 }, { 220, 2 }, - { 170, 5 }, - { 170, 3 }, - { 170, 5 }, - { 170, 4 }, - { 170, 4 }, - { 170, 5 }, - { 222, 5 }, - { 222, 4 }, - { 223, 2 }, - { 223, 0 }, + { 220, 0 }, + { 171, 4 }, + { 171, 2 }, + { 171, 3 }, + { 171, 3 }, + { 171, 4 }, + { 171, 2 }, + { 171, 2 }, + { 171, 2 }, + { 171, 2 }, { 221, 1 }, - { 221, 0 }, - { 216, 1 }, - { 216, 0 }, - { 211, 3 }, - { 211, 1 }, - { 144, 11 }, - { 224, 1 }, - { 224, 0 }, - { 174, 0 }, - { 174, 3 }, - { 182, 5 }, - { 182, 3 }, - { 225, 0 }, + { 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 }, - { 144, 4 }, - { 144, 1 }, - { 144, 2 }, - { 144, 5 }, - { 144, 5 }, - { 144, 5 }, - { 144, 5 }, - { 144, 6 }, - { 144, 3 }, - { 226, 1 }, + { 225, 0 }, + { 223, 1 }, + { 223, 0 }, + { 218, 1 }, + { 218, 0 }, + { 213, 3 }, + { 213, 1 }, + { 145, 11 }, { 226, 1 }, - { 165, 2 }, - { 166, 2 }, - { 228, 1 }, - { 227, 1 }, + { 226, 0 }, + { 175, 0 }, + { 175, 3 }, + { 183, 5 }, + { 183, 3 }, { 227, 0 }, - { 144, 5 }, - { 229, 11 }, - { 231, 1 }, - { 231, 1 }, - { 231, 2 }, - { 231, 0 }, - { 232, 1 }, - { 232, 1 }, - { 232, 3 }, + { 227, 2 }, + { 145, 4 }, + { 145, 1 }, + { 145, 2 }, + { 145, 5 }, + { 145, 5 }, + { 145, 5 }, + { 145, 5 }, + { 145, 6 }, + { 145, 3 }, + { 228, 1 }, + { 228, 1 }, + { 166, 2 }, + { 167, 2 }, + { 230, 1 }, + { 229, 1 }, + { 229, 0 }, + { 145, 5 }, + { 231, 11 }, + { 233, 1 }, + { 233, 1 }, + { 233, 2 }, { 233, 0 }, - { 233, 3 }, - { 234, 0 }, - { 234, 2 }, - { 230, 3 }, - { 230, 2 }, - { 235, 6 }, - { 235, 8 }, - { 235, 5 }, - { 235, 4 }, - { 235, 1 }, - { 170, 4 }, - { 170, 6 }, - { 186, 1 }, - { 186, 1 }, - { 186, 1 }, - { 144, 4 }, - { 144, 6 }, - { 144, 3 }, - { 237, 0 }, - { 237, 2 }, - { 236, 1 }, + { 234, 1 }, + { 234, 1 }, + { 234, 3 }, + { 235, 0 }, + { 235, 3 }, { 236, 0 }, - { 144, 1 }, - { 144, 3 }, - { 144, 1 }, - { 144, 3 }, - { 144, 6 }, - { 144, 6 }, - { 238, 1 }, + { 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, 1 }, - { 144, 1 }, - { 144, 4 }, - { 240, 7 }, + { 239, 2 }, + { 238, 1 }, + { 238, 0 }, + { 145, 1 }, + { 145, 3 }, + { 145, 1 }, + { 145, 3 }, + { 145, 6 }, + { 145, 6 }, + { 240, 1 }, + { 241, 0 }, { 241, 1 }, - { 241, 3 }, - { 242, 0 }, - { 242, 2 }, + { 145, 1 }, + { 145, 4 }, + { 242, 7 }, { 243, 1 }, { 243, 3 }, - { 244, 1 }, - { 245, 0 }, - { 245, 2 }, + { 244, 0 }, + { 244, 2 }, + { 245, 1 }, + { 245, 3 }, + { 246, 1 }, + { 247, 0 }, + { 247, 2 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -80378,18 +81694,18 @@ static void yy_reduce( case 83: /* conslist ::= conslist tcons */ case 84: /* conslist ::= tcons */ case 85: /* tcons ::= CONSTRAINT nm */ - case 257: /* plus_opt ::= PLUS */ - case 258: /* plus_opt ::= */ - case 268: /* foreach_clause ::= */ - case 269: /* foreach_clause ::= FOR EACH ROW */ - case 289: /* database_kw_opt ::= DATABASE */ - case 290: /* database_kw_opt ::= */ - case 298: /* kwcolumn_opt ::= */ - case 299: /* kwcolumn_opt ::= COLUMNKW */ - case 303: /* vtabarglist ::= vtabarg */ - case 304: /* vtabarglist ::= vtabarglist COMMA vtabarg */ - case 306: /* vtabarg ::= vtabarg vtabargtoken */ - case 310: /* anylist ::= */ + 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 ::= */ { } break; @@ -80406,17 +81722,17 @@ static void yy_reduce( { sqlite3FinishCoding(pParse); } break; case 9: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy280);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy316);} break; case 13: /* transtype ::= */ -{yygotominor.yy280 = TK_DEFERRED;} +{yygotominor.yy316 = 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.yy280 = yymsp[0].major;} +{yygotominor.yy316 = yymsp[0].major;} break; case 17: /* cmd ::= COMMIT trans_opt */ case 18: /* cmd ::= END trans_opt */ @@ -80427,7 +81743,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.yy280,0,0,yymsp[-2].minor.yy280); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy316,0,0,yymsp[-2].minor.yy316); } break; case 22: /* ifnotexists ::= */ @@ -80439,9 +81755,9 @@ static void yy_reduce( case 101: /* ifexists ::= */ case 112: /* distinct ::= ALL */ case 113: /* distinct ::= */ - case 213: /* between_op ::= BETWEEN */ - case 216: /* in_op ::= IN */ -{yygotominor.yy280 = 0;} + case 216: /* between_op ::= BETWEEN */ + case 219: /* in_op ::= IN */ +{yygotominor.yy316 = 0;} break; case 23: /* ifnotexists ::= IF NOT EXISTS */ case 24: /* temp ::= TEMP */ @@ -80449,9 +81765,9 @@ static void yy_reduce( case 78: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ case 100: /* ifexists ::= IF EXISTS */ case 111: /* distinct ::= DISTINCT */ - case 214: /* between_op ::= NOT BETWEEN */ - case 217: /* in_op ::= NOT IN */ -{yygotominor.yy280 = 1;} + case 217: /* between_op ::= NOT BETWEEN */ + case 220: /* in_op ::= NOT IN */ +{yygotominor.yy316 = 1;} break; case 26: /* create_table_args ::= LP columnlist conslist_opt RP */ { @@ -80460,8 +81776,8 @@ static void yy_reduce( break; case 27: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy375); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy375); + sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy43); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43); } break; case 30: /* column ::= columnid type carglist */ @@ -80486,12 +81802,13 @@ static void yy_reduce( case 119: /* as ::= AS nm */ case 120: /* as ::= ids */ case 131: /* dbnm ::= DOT nm */ - case 242: /* collate ::= COLLATE ids */ - case 252: /* nmnum ::= plus_num */ - case 253: /* nmnum ::= nm */ - case 254: /* plus_num ::= plus_opt number */ - case 255: /* minus_num ::= MINUS number */ - case 256: /* number ::= INTEGER|FLOAT */ + 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 */ {yygotominor.yy0 = yymsp[0].minor.yy0;} break; case 38: /* type ::= typetoken */ @@ -80514,14 +81831,15 @@ static void yy_reduce( break; case 50: /* ccons ::= DEFAULT term */ case 52: /* ccons ::= DEFAULT PLUS term */ -{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy62);} +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy450);} break; case 51: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy62);} +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy450);} break; case 53: /* ccons ::= DEFAULT MINUS term */ { - Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy62, 0, 0); + Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy450, 0, 0); + sqlite3ExprSpan(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span); sqlite3AddDefaultValue(pParse,p); } break; @@ -80532,55 +81850,55 @@ static void yy_reduce( } break; case 56: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy280);} +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy316);} break; case 57: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy280,yymsp[0].minor.yy280,yymsp[-2].minor.yy280);} +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy316,yymsp[0].minor.yy316,yymsp[-2].minor.yy316);} break; case 58: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy280,0,0,0,0);} +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy316,0,0,0,0);} break; case 59: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy62);} +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy450);} break; case 60: /* ccons ::= REFERENCES nm idxlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy418,yymsp[0].minor.yy280);} +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy242,yymsp[0].minor.yy316);} break; case 61: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy280);} +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy316);} break; case 62: /* ccons ::= COLLATE ids */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; case 65: /* refargs ::= */ -{ yygotominor.yy280 = OE_Restrict * 0x010101; } +{ yygotominor.yy316 = OE_Restrict * 0x010101; } break; case 66: /* refargs ::= refargs refarg */ -{ yygotominor.yy280 = (yymsp[-1].minor.yy280 & yymsp[0].minor.yy359.mask) | yymsp[0].minor.yy359.value; } +{ yygotominor.yy316 = (yymsp[-1].minor.yy316 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; } break; case 67: /* refarg ::= MATCH nm */ -{ yygotominor.yy359.value = 0; yygotominor.yy359.mask = 0x000000; } +{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; } break; case 68: /* refarg ::= ON DELETE refact */ -{ yygotominor.yy359.value = yymsp[0].minor.yy280; yygotominor.yy359.mask = 0x0000ff; } +{ yygotominor.yy207.value = yymsp[0].minor.yy316; yygotominor.yy207.mask = 0x0000ff; } break; case 69: /* refarg ::= ON UPDATE refact */ -{ yygotominor.yy359.value = yymsp[0].minor.yy280<<8; yygotominor.yy359.mask = 0x00ff00; } +{ yygotominor.yy207.value = yymsp[0].minor.yy316<<8; yygotominor.yy207.mask = 0x00ff00; } break; case 70: /* refarg ::= ON INSERT refact */ -{ yygotominor.yy359.value = yymsp[0].minor.yy280<<16; yygotominor.yy359.mask = 0xff0000; } +{ yygotominor.yy207.value = yymsp[0].minor.yy316<<16; yygotominor.yy207.mask = 0xff0000; } break; case 71: /* refact ::= SET NULL */ -{ yygotominor.yy280 = OE_SetNull; } +{ yygotominor.yy316 = OE_SetNull; } break; case 72: /* refact ::= SET DEFAULT */ -{ yygotominor.yy280 = OE_SetDflt; } +{ yygotominor.yy316 = OE_SetDflt; } break; case 73: /* refact ::= CASCADE */ -{ yygotominor.yy280 = OE_Cascade; } +{ yygotominor.yy316 = OE_Cascade; } break; case 74: /* refact ::= RESTRICT */ -{ yygotominor.yy280 = OE_Restrict; } +{ yygotominor.yy316 = OE_Restrict; } break; case 75: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ case 76: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ @@ -80588,8 +81906,8 @@ static void yy_reduce( case 93: /* onconf ::= ON CONFLICT resolvetype */ case 95: /* orconf ::= OR resolvetype */ case 96: /* resolvetype ::= raisetype */ - case 166: /* insert_cmd ::= INSERT orconf */ -{yygotominor.yy280 = yymsp[0].minor.yy280;} + case 169: /* insert_cmd ::= INSERT orconf */ +{yygotominor.yy316 = yymsp[0].minor.yy316;} break; case 80: /* conslist_opt ::= */ {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;} @@ -80598,96 +81916,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.yy418,yymsp[0].minor.yy280,yymsp[-2].minor.yy280,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy242,yymsp[0].minor.yy316,yymsp[-2].minor.yy316,0);} break; case 87: /* tcons ::= UNIQUE LP idxlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy418,yymsp[0].minor.yy280,0,0,0,0);} +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy242,yymsp[0].minor.yy316,0,0,0,0);} break; case 88: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy62);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy450);} break; case 89: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy418, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy418, yymsp[-1].minor.yy280); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy280); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy242, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[-1].minor.yy316); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy316); } break; case 92: /* onconf ::= */ case 94: /* orconf ::= */ -{yygotominor.yy280 = OE_Default;} +{yygotominor.yy316 = OE_Default;} break; case 97: /* resolvetype ::= IGNORE */ -{yygotominor.yy280 = OE_Ignore;} +{yygotominor.yy316 = OE_Ignore;} break; case 98: /* resolvetype ::= REPLACE */ - case 167: /* insert_cmd ::= REPLACE */ -{yygotominor.yy280 = OE_Replace;} + case 170: /* insert_cmd ::= REPLACE */ +{yygotominor.yy316 = OE_Replace;} break; case 99: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy151, 0, yymsp[-1].minor.yy280); + sqlite3DropTable(pParse, yymsp[0].minor.yy419, 0, yymsp[-1].minor.yy316); } 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.yy375, yymsp[-6].minor.yy280, yymsp[-4].minor.yy280); + 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); } break; case 103: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy151, 1, yymsp[-1].minor.yy280); + sqlite3DropTable(pParse, yymsp[0].minor.yy419, 1, yymsp[-1].minor.yy316); } break; case 104: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy375, &dest); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy375); + sqlite3Select(pParse, yymsp[0].minor.yy43, &dest); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43); } break; case 105: /* select ::= oneselect */ case 128: /* seltablist_paren ::= select */ -{yygotominor.yy375 = yymsp[0].minor.yy375;} +{yygotominor.yy43 = yymsp[0].minor.yy43;} break; case 106: /* select ::= select multiselect_op oneselect */ { - if( yymsp[0].minor.yy375 ){ - yymsp[0].minor.yy375->op = yymsp[-1].minor.yy280; - yymsp[0].minor.yy375->pPrior = yymsp[-2].minor.yy375; + if( yymsp[0].minor.yy43 ){ + yymsp[0].minor.yy43->op = yymsp[-1].minor.yy316; + yymsp[0].minor.yy43->pPrior = yymsp[-2].minor.yy43; }else{ - sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy375); + sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy43); } - yygotominor.yy375 = yymsp[0].minor.yy375; + yygotominor.yy43 = yymsp[0].minor.yy43; } break; case 108: /* multiselect_op ::= UNION ALL */ -{yygotominor.yy280 = TK_ALL;} +{yygotominor.yy316 = TK_ALL;} break; case 110: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yygotominor.yy375 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy418,yymsp[-5].minor.yy151,yymsp[-4].minor.yy62,yymsp[-3].minor.yy418,yymsp[-2].minor.yy62,yymsp[-1].minor.yy418,yymsp[-7].minor.yy280,yymsp[0].minor.yy220.pLimit,yymsp[0].minor.yy220.pOffset); + 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); } break; case 114: /* sclp ::= selcollist COMMA */ - case 238: /* idxlist_opt ::= LP idxlist RP */ -{yygotominor.yy418 = yymsp[-1].minor.yy418;} + case 241: /* idxlist_opt ::= LP idxlist RP */ +{yygotominor.yy242 = yymsp[-1].minor.yy242;} break; case 115: /* sclp ::= */ - case 141: /* orderby_opt ::= */ - case 149: /* groupby_opt ::= */ - case 231: /* exprlist ::= */ - case 237: /* idxlist_opt ::= */ -{yygotominor.yy418 = 0;} + case 144: /* orderby_opt ::= */ + case 152: /* groupby_opt ::= */ + case 234: /* exprlist ::= */ + case 240: /* idxlist_opt ::= */ +{yygotominor.yy242 = 0;} break; case 116: /* selcollist ::= sclp expr as */ { - yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy418,yymsp[-1].minor.yy62,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0); + yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[-1].minor.yy450,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.yy418 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy418, p, 0); + yygotominor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy242, p, 0); } break; case 118: /* selcollist ::= sclp nm DOT STAR */ @@ -80695,644 +82013,653 @@ 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.yy418 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy418, pDot, 0); + yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242, pDot, 0); } break; case 121: /* as ::= */ {yygotominor.yy0.n = 0;} break; case 122: /* from ::= */ -{yygotominor.yy151 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy151));} +{yygotominor.yy419 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy419));} break; case 123: /* from ::= FROM seltablist */ { - yygotominor.yy151 = yymsp[0].minor.yy151; - sqlite3SrcListShiftJoinType(yygotominor.yy151); + yygotominor.yy419 = yymsp[0].minor.yy419; + sqlite3SrcListShiftJoinType(yygotominor.yy419); } break; case 124: /* stl_prefix ::= seltablist joinop */ { - yygotominor.yy151 = yymsp[-1].minor.yy151; - if( yygotominor.yy151 && yygotominor.yy151->nSrc>0 ) yygotominor.yy151->a[yygotominor.yy151->nSrc-1].jointype = yymsp[0].minor.yy280; + 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; } break; case 125: /* stl_prefix ::= */ -{yygotominor.yy151 = 0;} +{yygotominor.yy419 = 0;} break; - case 126: /* seltablist ::= stl_prefix nm dbnm as on_opt using_opt */ + case 126: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { - yygotominor.yy151 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy151,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy62,yymsp[0].minor.yy240); + 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); } break; case 127: /* seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt */ { - yygotominor.yy151 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy151,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy375,yymsp[-1].minor.yy62,yymsp[0].minor.yy240); + 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); } break; case 129: /* seltablist_paren ::= seltablist */ { - sqlite3SrcListShiftJoinType(yymsp[0].minor.yy151); - yygotominor.yy375 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy151,0,0,0,0,0,0,0); + sqlite3SrcListShiftJoinType(yymsp[0].minor.yy419); + yygotominor.yy43 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy419,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.yy151 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} +{yygotominor.yy419 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} break; case 133: /* joinop ::= COMMA|JOIN */ -{ yygotominor.yy280 = JT_INNER; } +{ yygotominor.yy316 = JT_INNER; } break; case 134: /* joinop ::= JOIN_KW JOIN */ -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } +{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } break; case 135: /* joinop ::= JOIN_KW nm JOIN */ -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } +{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } break; case 136: /* joinop ::= JOIN_KW nm nm JOIN */ -{ yygotominor.yy280 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } +{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } break; case 137: /* on_opt ::= ON expr */ - 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.yy62 = yymsp[0].minor.yy62;} + 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;} break; case 138: /* on_opt ::= */ - case 151: /* having_opt ::= */ - case 158: /* where_opt ::= */ - case 203: /* escape ::= */ - case 227: /* case_else ::= */ - case 229: /* case_operand ::= */ -{yygotominor.yy62 = 0;} + 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;} break; - case 139: /* using_opt ::= USING LP inscollist RP */ - case 171: /* inscollist_opt ::= LP inscollist RP */ -{yygotominor.yy240 = yymsp[-1].minor.yy240;} + case 142: /* using_opt ::= USING LP inscollist RP */ + case 174: /* inscollist_opt ::= LP inscollist RP */ +{yygotominor.yy352 = yymsp[-1].minor.yy352;} break; - case 140: /* using_opt ::= */ - case 170: /* inscollist_opt ::= */ -{yygotominor.yy240 = 0;} + case 143: /* using_opt ::= */ + case 173: /* inscollist_opt ::= */ +{yygotominor.yy352 = 0;} break; - case 142: /* orderby_opt ::= ORDER BY sortlist */ - case 150: /* groupby_opt ::= GROUP BY nexprlist */ - case 230: /* exprlist ::= nexprlist */ -{yygotominor.yy418 = yymsp[0].minor.yy418;} + case 145: /* orderby_opt ::= ORDER BY sortlist */ + case 153: /* groupby_opt ::= GROUP BY nexprlist */ + case 233: /* exprlist ::= nexprlist */ +{yygotominor.yy242 = yymsp[0].minor.yy242;} break; - case 143: /* sortlist ::= sortlist COMMA sortitem sortorder */ + case 146: /* sortlist ::= sortlist COMMA sortitem sortorder */ { - yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy418,yymsp[-1].minor.yy62,0); - if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280; + 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; } break; - case 144: /* sortlist ::= sortitem sortorder */ + case 147: /* sortlist ::= sortitem sortorder */ { - yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy62,0); - if( yygotominor.yy418 && yygotominor.yy418->a ) yygotominor.yy418->a[0].sortOrder = yymsp[0].minor.yy280; + 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; } break; - case 146: /* sortorder ::= ASC */ - case 148: /* sortorder ::= */ -{yygotominor.yy280 = SQLITE_SO_ASC;} + case 149: /* sortorder ::= ASC */ + case 151: /* sortorder ::= */ +{yygotominor.yy316 = SQLITE_SO_ASC;} break; - case 147: /* sortorder ::= DESC */ -{yygotominor.yy280 = SQLITE_SO_DESC;} + case 150: /* sortorder ::= DESC */ +{yygotominor.yy316 = SQLITE_SO_DESC;} break; - case 153: /* limit_opt ::= */ -{yygotominor.yy220.pLimit = 0; yygotominor.yy220.pOffset = 0;} + case 156: /* limit_opt ::= */ +{yygotominor.yy84.pLimit = 0; yygotominor.yy84.pOffset = 0;} break; - case 154: /* limit_opt ::= LIMIT expr */ -{yygotominor.yy220.pLimit = yymsp[0].minor.yy62; yygotominor.yy220.pOffset = 0;} + case 157: /* limit_opt ::= LIMIT expr */ +{yygotominor.yy84.pLimit = yymsp[0].minor.yy450; yygotominor.yy84.pOffset = 0;} break; - case 155: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yygotominor.yy220.pLimit = yymsp[-2].minor.yy62; yygotominor.yy220.pOffset = yymsp[0].minor.yy62;} + case 158: /* limit_opt ::= LIMIT expr OFFSET expr */ +{yygotominor.yy84.pLimit = yymsp[-2].minor.yy450; yygotominor.yy84.pOffset = yymsp[0].minor.yy450;} break; - case 156: /* limit_opt ::= LIMIT expr COMMA expr */ -{yygotominor.yy220.pOffset = yymsp[-2].minor.yy62; yygotominor.yy220.pLimit = yymsp[0].minor.yy62;} + case 159: /* limit_opt ::= LIMIT expr COMMA expr */ +{yygotominor.yy84.pOffset = yymsp[-2].minor.yy450; yygotominor.yy84.pLimit = yymsp[0].minor.yy450;} break; - case 157: /* cmd ::= DELETE FROM fullname where_opt */ -{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy151,yymsp[0].minor.yy62);} + 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); +} break; - case 160: /* cmd ::= UPDATE orconf fullname SET setlist where_opt */ + case 163: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */ { - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy418,"set list"); - sqlite3Update(pParse,yymsp[-3].minor.yy151,yymsp[-1].minor.yy418,yymsp[0].minor.yy62,yymsp[-4].minor.yy280); + 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); } break; - case 161: /* setlist ::= setlist COMMA nm EQ expr */ -{yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418,yymsp[0].minor.yy62,&yymsp[-2].minor.yy0);} + case 164: /* setlist ::= setlist COMMA nm EQ expr */ +{yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242,yymsp[0].minor.yy450,&yymsp[-2].minor.yy0);} break; - case 162: /* setlist ::= nm EQ expr */ -{yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy62,&yymsp[-2].minor.yy0);} + case 165: /* setlist ::= nm EQ expr */ +{yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy450,&yymsp[-2].minor.yy0);} break; - case 163: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */ -{sqlite3Insert(pParse, yymsp[-5].minor.yy151, yymsp[-1].minor.yy418, 0, yymsp[-4].minor.yy240, yymsp[-7].minor.yy280);} + 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);} break; - case 164: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */ -{sqlite3Insert(pParse, yymsp[-2].minor.yy151, 0, yymsp[0].minor.yy375, yymsp[-1].minor.yy240, yymsp[-4].minor.yy280);} + 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);} break; - case 165: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */ -{sqlite3Insert(pParse, yymsp[-3].minor.yy151, 0, 0, yymsp[-2].minor.yy240, yymsp[-5].minor.yy280);} + 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);} break; - case 168: /* itemlist ::= itemlist COMMA expr */ - case 232: /* nexprlist ::= nexprlist COMMA expr */ -{yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy418,yymsp[0].minor.yy62,0);} + 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);} break; - case 169: /* itemlist ::= expr */ - case 233: /* nexprlist ::= expr */ -{yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy62,0);} + case 172: /* itemlist ::= expr */ + case 236: /* nexprlist ::= expr */ +{yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy450,0);} break; - case 172: /* inscollist ::= inscollist COMMA nm */ -{yygotominor.yy240 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy240,&yymsp[0].minor.yy0);} + case 175: /* inscollist ::= inscollist COMMA nm */ +{yygotominor.yy352 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy352,&yymsp[0].minor.yy0);} break; - case 173: /* inscollist ::= nm */ -{yygotominor.yy240 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} + case 176: /* inscollist ::= nm */ +{yygotominor.yy352 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} break; - case 175: /* expr ::= LP expr RP */ -{yygotominor.yy62 = yymsp[-1].minor.yy62; sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } + case 178: /* expr ::= LP expr RP */ +{yygotominor.yy450 = yymsp[-1].minor.yy450; sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } break; - case 176: /* term ::= NULL */ - case 181: /* term ::= INTEGER|FLOAT|BLOB */ - case 182: /* term ::= STRING */ -{yygotominor.yy62 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} + 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);} break; - case 177: /* expr ::= ID */ - case 178: /* expr ::= JOIN_KW */ -{yygotominor.yy62 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);} + case 180: /* expr ::= ID */ + case 181: /* expr ::= JOIN_KW */ +{yygotominor.yy450 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);} break; - case 179: /* expr ::= nm DOT nm */ + case 182: /* 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.yy62 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + yygotominor.yy450 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); } break; - case 180: /* expr ::= nm DOT nm DOT nm */ + case 183: /* 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.yy62 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + yygotominor.yy450 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); } break; - case 183: /* expr ::= REGISTER */ -{yygotominor.yy62 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} + case 186: /* expr ::= REGISTER */ +{yygotominor.yy450 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} break; - case 184: /* expr ::= VARIABLE */ + case 187: /* expr ::= VARIABLE */ { Token *pToken = &yymsp[0].minor.yy0; - Expr *pExpr = yygotominor.yy62 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken); + Expr *pExpr = yygotominor.yy450 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } break; - case 185: /* expr ::= expr COLLATE ids */ + case 188: /* expr ::= expr COLLATE ids */ { - yygotominor.yy62 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy62, &yymsp[0].minor.yy0); + yygotominor.yy450 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy450, &yymsp[0].minor.yy0); } break; - case 186: /* expr ::= CAST LP expr AS typetoken RP */ + case 189: /* expr ::= CAST LP expr AS typetoken RP */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy62, 0, &yymsp[-1].minor.yy0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); + 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); } break; - case 187: /* expr ::= ID LP distinct exprlist RP */ + case 190: /* expr ::= ID LP distinct exprlist RP */ { - if( yymsp[-1].minor.yy418 && yymsp[-1].minor.yy418->nExpr>SQLITE_MAX_FUNCTION_ARG ){ + if( yymsp[-1].minor.yy242 && yymsp[-1].minor.yy242->nExpr>SQLITE_MAX_FUNCTION_ARG ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); } - yygotominor.yy62 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy418, &yymsp[-4].minor.yy0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy280 && yygotominor.yy62 ){ - yygotominor.yy62->flags |= EP_Distinct; + 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; } } break; - case 188: /* expr ::= ID LP STAR RP */ + case 191: /* expr ::= ID LP STAR RP */ { - yygotominor.yy62 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy450 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); + sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } break; - case 189: /* term ::= CTIME_KW */ + case 192: /* term ::= CTIME_KW */ { /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are ** treated as functions that return constants */ - yygotominor.yy62 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0); - if( yygotominor.yy62 ){ - yygotominor.yy62->op = TK_CONST_FUNC; - yygotominor.yy62->span = yymsp[0].minor.yy0; + 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; } } break; - 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.yy62 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy62,yymsp[0].minor.yy62,0);} + 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);} break; - case 198: /* likeop ::= LIKE_KW */ - case 200: /* likeop ::= MATCH */ -{yygotominor.yy222.eOperator = yymsp[0].minor.yy0; yygotominor.yy222.not = 0;} + case 201: /* likeop ::= LIKE_KW */ + case 203: /* likeop ::= MATCH */ +{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 0;} break; - case 199: /* likeop ::= NOT LIKE_KW */ - case 201: /* likeop ::= NOT MATCH */ -{yygotominor.yy222.eOperator = yymsp[0].minor.yy0; yygotominor.yy222.not = 1;} + case 202: /* likeop ::= NOT LIKE_KW */ + case 204: /* likeop ::= NOT MATCH */ +{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 1;} break; - case 204: /* expr ::= expr likeop expr escape */ + case 207: /* expr ::= expr likeop expr escape */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy62, 0); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy62, 0); - if( yymsp[0].minor.yy62 ){ - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy62, 0); + 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); } - yygotominor.yy62 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy222.eOperator); - if( yymsp[-2].minor.yy222.not ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy62->span, &yymsp[-1].minor.yy62->span); - if( yygotominor.yy62 ) yygotominor.yy62->flags |= EP_InfixFunc; + 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; } break; - case 205: /* expr ::= expr ISNULL|NOTNULL */ + case 208: /* expr ::= expr ISNULL|NOTNULL */ { - yygotominor.yy62 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy62->span,&yymsp[0].minor.yy0); + 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); } break; - case 206: /* expr ::= expr IS NULL */ + case 209: /* expr ::= expr IS NULL */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->span,&yymsp[0].minor.yy0); + yygotominor.yy450 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy450, 0, 0); + sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0); } break; - case 207: /* expr ::= expr NOT NULL */ + case 210: /* expr ::= expr NOT NULL */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->span,&yymsp[0].minor.yy0); + yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy450, 0, 0); + sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0); } break; - case 208: /* expr ::= expr IS NOT NULL */ + case 211: /* expr ::= expr IS NOT NULL */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,&yymsp[0].minor.yy0); + yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy450, 0, 0); + sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,&yymsp[0].minor.yy0); } break; - case 209: /* expr ::= NOT expr */ - case 210: /* expr ::= BITNOT expr */ + case 212: /* expr ::= NOT expr */ + case 213: /* expr ::= BITNOT expr */ { - yygotominor.yy62 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); + 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); } break; - case 211: /* expr ::= MINUS expr */ + case 214: /* expr ::= MINUS expr */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); + yygotominor.yy450 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy450, 0, 0); + sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span); } break; - case 212: /* expr ::= PLUS expr */ + case 215: /* expr ::= PLUS expr */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span); + yygotominor.yy450 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy450, 0, 0); + sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span); } break; - case 215: /* expr ::= expr between_op expr AND expr */ + case 218: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62, 0); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy62, 0); - yygotominor.yy62 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = pList; + 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; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy62->span); + 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); } break; - case 218: /* expr ::= expr in_op LP exprlist RP */ + case 221: /* expr ::= expr in_op LP exprlist RP */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = yymsp[-1].minor.yy418; - sqlite3ExprSetHeight(pParse, yygotominor.yy62); + 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); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy418); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0); + 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); } break; - case 219: /* expr ::= LP select RP */ + case 222: /* expr ::= LP select RP */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = yymsp[-1].minor.yy375; - sqlite3ExprSetHeight(pParse, yygotominor.yy62); + yygotominor.yy450 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( yygotominor.yy450 ){ + yygotominor.yy450->pSelect = yymsp[-1].minor.yy43; + sqlite3ExprSetHeight(pParse, yygotominor.yy450); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43); } - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } break; - case 220: /* expr ::= expr in_op LP select RP */ + case 223: /* expr ::= expr in_op LP select RP */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = yymsp[-1].minor.yy375; - sqlite3ExprSetHeight(pParse, yygotominor.yy62); + 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); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43); } - if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0); + 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); } break; - case 221: /* expr ::= expr in_op nm dbnm */ + case 224: /* expr ::= expr in_op nm dbnm */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); - yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy62, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - sqlite3ExprSetHeight(pParse, yygotominor.yy62); + 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); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } - if( yymsp[-2].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0); - sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0); + 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); } break; - case 222: /* expr ::= EXISTS LP select RP */ + case 225: /* expr ::= EXISTS LP select RP */ { - Expr *p = yygotominor.yy62 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + Expr *p = yygotominor.yy450 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ - p->pSelect = yymsp[-1].minor.yy375; + p->pSelect = yymsp[-1].minor.yy43; sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); - sqlite3ExprSetHeight(pParse, yygotominor.yy62); + sqlite3ExprSetHeight(pParse, yygotominor.yy450); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43); } } break; - case 223: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 226: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->pList = yymsp[-2].minor.yy418; - sqlite3ExprSetHeight(pParse, yygotominor.yy62); + 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); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy418); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy242); } - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); + sqlite3ExprSpan(yygotominor.yy450, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); } break; - case 224: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 227: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418, yymsp[-2].minor.yy62, 0); - yygotominor.yy418 = sqlite3ExprListAppend(pParse,yygotominor.yy418, yymsp[0].minor.yy62, 0); + yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[-2].minor.yy450, 0); + yygotominor.yy242 = sqlite3ExprListAppend(pParse,yygotominor.yy242, yymsp[0].minor.yy450, 0); } break; - case 225: /* case_exprlist ::= WHEN expr THEN expr */ + case 228: /* case_exprlist ::= WHEN expr THEN expr */ { - yygotominor.yy418 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62, 0); - yygotominor.yy418 = sqlite3ExprListAppend(pParse,yygotominor.yy418, yymsp[0].minor.yy62, 0); + yygotominor.yy242 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy450, 0); + yygotominor.yy242 = sqlite3ExprListAppend(pParse,yygotominor.yy242, yymsp[0].minor.yy450, 0); } break; - case 234: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */ + case 237: /* 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.yy418, yymsp[-9].minor.yy280, - &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy280); + 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); } break; - case 235: /* uniqueflag ::= UNIQUE */ - case 282: /* raisetype ::= ABORT */ -{yygotominor.yy280 = OE_Abort;} + case 238: /* uniqueflag ::= UNIQUE */ + case 285: /* raisetype ::= ABORT */ +{yygotominor.yy316 = OE_Abort;} break; - case 236: /* uniqueflag ::= */ -{yygotominor.yy280 = OE_None;} + case 239: /* uniqueflag ::= */ +{yygotominor.yy316 = OE_None;} break; - case 239: /* idxlist ::= idxlist COMMA nm collate sortorder */ + case 242: /* idxlist ::= idxlist COMMA nm 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.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418, p, &yymsp[-2].minor.yy0); - sqlite3ExprListCheckLength(pParse, yygotominor.yy418, "index"); - if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280; + 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; } break; - case 240: /* idxlist ::= nm collate sortorder */ + case 243: /* idxlist ::= nm 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.yy418 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0); - sqlite3ExprListCheckLength(pParse, yygotominor.yy418, "index"); - if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280; + 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; } break; - case 241: /* collate ::= */ + case 244: /* collate ::= */ {yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;} break; - case 243: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy151, yymsp[-1].minor.yy280);} + case 246: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy419, yymsp[-1].minor.yy316);} break; - case 244: /* cmd ::= VACUUM */ - case 245: /* cmd ::= VACUUM nm */ + case 247: /* cmd ::= VACUUM */ + case 248: /* cmd ::= VACUUM nm */ {sqlite3Vacuum(pParse);} break; - case 246: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ - case 247: /* cmd ::= PRAGMA nm dbnm EQ ON */ - case 248: /* cmd ::= PRAGMA nm dbnm EQ DELETE */ + case 249: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 250: /* cmd ::= PRAGMA nm dbnm EQ ON */ + case 251: /* cmd ::= PRAGMA nm dbnm EQ DELETE */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 249: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 252: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ { sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1); } break; - case 250: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 251: /* cmd ::= PRAGMA nm dbnm */ + case 254: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 259: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */ + case 262: /* 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.yy360, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy75, &all); } break; - case 260: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 263: /* 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.yy280, yymsp[-4].minor.yy30.a, yymsp[-4].minor.yy30.b, yymsp[-2].minor.yy151, yymsp[0].minor.yy62, yymsp[-10].minor.yy280, yymsp[-8].minor.yy280); + 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); yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); } break; - case 261: /* trigger_time ::= BEFORE */ - case 264: /* trigger_time ::= */ -{ yygotominor.yy280 = TK_BEFORE; } + case 264: /* trigger_time ::= BEFORE */ + case 267: /* trigger_time ::= */ +{ yygotominor.yy316 = TK_BEFORE; } break; - case 262: /* trigger_time ::= AFTER */ -{ yygotominor.yy280 = TK_AFTER; } + case 265: /* trigger_time ::= AFTER */ +{ yygotominor.yy316 = TK_AFTER; } break; - case 263: /* trigger_time ::= INSTEAD OF */ -{ yygotominor.yy280 = TK_INSTEAD;} + case 266: /* trigger_time ::= INSTEAD OF */ +{ yygotominor.yy316 = TK_INSTEAD;} break; - case 265: /* trigger_event ::= DELETE|INSERT */ - case 266: /* trigger_event ::= UPDATE */ -{yygotominor.yy30.a = yymsp[0].major; yygotominor.yy30.b = 0;} + case 268: /* trigger_event ::= DELETE|INSERT */ + case 269: /* trigger_event ::= UPDATE */ +{yygotominor.yy354.a = yymsp[0].major; yygotominor.yy354.b = 0;} break; - case 267: /* trigger_event ::= UPDATE OF inscollist */ -{yygotominor.yy30.a = TK_UPDATE; yygotominor.yy30.b = yymsp[0].minor.yy240;} + case 270: /* trigger_event ::= UPDATE OF inscollist */ +{yygotominor.yy354.a = TK_UPDATE; yygotominor.yy354.b = yymsp[0].minor.yy352;} break; - case 270: /* when_clause ::= */ - case 287: /* key_opt ::= */ -{ yygotominor.yy62 = 0; } + case 273: /* when_clause ::= */ + case 290: /* key_opt ::= */ +{ yygotominor.yy450 = 0; } break; - case 271: /* when_clause ::= WHEN expr */ - case 288: /* key_opt ::= KEY expr */ -{ yygotominor.yy62 = yymsp[0].minor.yy62; } + case 274: /* when_clause ::= WHEN expr */ + case 291: /* key_opt ::= KEY expr */ +{ yygotominor.yy450 = yymsp[0].minor.yy450; } break; - case 272: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 275: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { /* - if( yymsp[-2].minor.yy360 ){ - yymsp[-2].minor.yy360->pLast->pNext = yymsp[-1].minor.yy360; + if( yymsp[-2].minor.yy75 ){ + yymsp[-2].minor.yy75->pLast->pNext = yymsp[-1].minor.yy75; }else{ - yymsp[-2].minor.yy360 = yymsp[-1].minor.yy360; + yymsp[-2].minor.yy75 = yymsp[-1].minor.yy75; } */ - assert( yymsp[-2].minor.yy360!=0 ); - yymsp[-2].minor.yy360->pLast->pNext = yymsp[-1].minor.yy360; - yymsp[-2].minor.yy360->pLast = yymsp[-1].minor.yy360; - yygotominor.yy360 = yymsp[-2].minor.yy360; + 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; } break; - case 273: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 276: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - /* if( yymsp[-1].minor.yy360 ) */ - assert( yymsp[-1].minor.yy360!=0 ); - yymsp[-1].minor.yy360->pLast = yymsp[-1].minor.yy360; - yygotominor.yy360 = yymsp[-1].minor.yy360; + /* 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; } break; - case 274: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */ -{ yygotominor.yy360 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy418, yymsp[0].minor.yy62, yymsp[-4].minor.yy280); } + 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); } break; - case 275: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */ -{yygotominor.yy360 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy240, yymsp[-1].minor.yy418, 0, yymsp[-7].minor.yy280);} + 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);} break; - case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */ -{yygotominor.yy360 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy240, 0, yymsp[0].minor.yy375, yymsp[-4].minor.yy280);} + 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);} break; - case 277: /* trigger_cmd ::= DELETE FROM nm where_opt */ -{yygotominor.yy360 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy62);} + case 280: /* trigger_cmd ::= DELETE FROM nm where_opt */ +{yygotominor.yy75 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy450);} break; - case 278: /* trigger_cmd ::= select */ -{yygotominor.yy360 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy375); } + case 281: /* trigger_cmd ::= select */ +{yygotominor.yy75 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy43); } break; - case 279: /* expr ::= RAISE LP IGNORE RP */ + case 282: /* expr ::= RAISE LP IGNORE RP */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); - if( yygotominor.yy62 ){ - yygotominor.yy62->iColumn = OE_Ignore; - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); + 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); } } break; - case 280: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 283: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - yygotominor.yy62 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); - if( yygotominor.yy62 ) { - yygotominor.yy62->iColumn = yymsp[-3].minor.yy280; - sqlite3ExprSpan(yygotominor.yy62, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); + 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); } } break; - case 281: /* raisetype ::= ROLLBACK */ -{yygotominor.yy280 = OE_Rollback;} + case 284: /* raisetype ::= ROLLBACK */ +{yygotominor.yy316 = OE_Rollback;} break; - case 283: /* raisetype ::= FAIL */ -{yygotominor.yy280 = OE_Fail;} + case 286: /* raisetype ::= FAIL */ +{yygotominor.yy316 = OE_Fail;} break; - case 284: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 287: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy151,yymsp[-1].minor.yy280); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy419,yymsp[-1].minor.yy316); } break; - case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 288: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, yymsp[0].minor.yy62); + sqlite3Attach(pParse, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, yymsp[0].minor.yy450); } break; - case 286: /* cmd ::= DETACH database_kw_opt expr */ + case 289: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy62); + sqlite3Detach(pParse, yymsp[0].minor.yy450); } break; - case 291: /* cmd ::= REINDEX */ + case 294: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 292: /* cmd ::= REINDEX nm dbnm */ + case 295: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 293: /* cmd ::= ANALYZE */ + case 296: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 294: /* cmd ::= ANALYZE nm dbnm */ + case 297: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 295: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 298: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy151,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy419,&yymsp[0].minor.yy0); } break; - case 296: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ + case 299: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ { sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); } break; - case 297: /* add_column_fullname ::= fullname */ + case 300: /* add_column_fullname ::= fullname */ { - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy151); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy419); } break; - case 300: /* cmd ::= create_vtab */ + case 303: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 301: /* cmd ::= create_vtab LP vtabarglist RP */ + case 304: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 302: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */ + case 305: /* 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 305: /* vtabarg ::= */ + case 308: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 307: /* vtabargtoken ::= ANY */ - case 308: /* vtabargtoken ::= lp anylist RP */ - case 309: /* lp ::= LP */ - case 311: /* anylist ::= anylist ANY */ + case 310: /* vtabargtoken ::= ANY */ + case 311: /* vtabargtoken ::= lp anylist RP */ + case 312: /* lp ::= LP */ + case 314: /* anylist ::= anylist ANY */ {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; }; @@ -81646,7 +82973,7 @@ const unsigned char ebcdicToAscii[] = { ** ** The code in this file has been automatically generated by ** -** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.31 2007/07/30 18:26:20 rse Exp $ +** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.32 2008/10/06 05:32:19 danielk1977 Exp $ ** ** The code in this file implements a function that determines whether ** or not a given identifier is really an SQL keyword. The same thing @@ -81655,89 +82982,89 @@ const unsigned char ebcdicToAscii[] = { ** is substantially reduced. This is important for embedded applications ** on platforms with limited memory. */ -/* Hash score: 165 */ +/* Hash score: 167 */ static int keywordCode(const char *z, int n){ - /* zText[] encodes 775 bytes of keywords in 526 bytes */ - static const char zText[526] = - "BEFOREIGNOREGEXPLAINSTEADDESCAPEACHECKEYCONSTRAINTERSECTABLEFT" - "HENDATABASELECTRANSACTIONATURALTERAISELSEXCEPTRIGGEREFERENCES" - "UNIQUERYATTACHAVINGROUPDATEMPORARYBEGINNEREINDEXCLUSIVEXISTSBETWEEN" - "OTNULLIKECASCADEFERRABLECASECOLLATECREATECURRENT_DATEDELETEDETACH" - "IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN" - "WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICT" - "CROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOB" - "YIFINTOFFSETISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUM" + /* zText[] encodes 783 bytes of keywords in 528 bytes */ + static const char zText[528] = + "REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECTABLE" + "FTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTSCONSTRAINT" + "ERSECTRIGGEREFERENCESUNIQUERYATTACHAVINGROUPDATEMPORARYBEGINNER" + "ENAMEBETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATE" + "DETACHIMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMIT" + "WHENWHEREPLACEAFTERESTRICTANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT" + "CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROM" + "FULLGLOBYIFINTOFFSETISNULLORDERIGHTOUTEROLLBACKROWUNIONUSINGVACUUM" "VIEWINITIALLY"; static const unsigned char aHash[127] = { - 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, + 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, }; - 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 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 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 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 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 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 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, + 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, }; int h, i; if( n<2 ) return TK_ID; @@ -82503,7 +83830,7 @@ SQLITE_API int sqlite3_complete16(const void *zSql){ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.500 2008/09/08 08:08:09 danielk1977 Exp $ +** $Id: main.c,v 1.514 2008/11/19 09:05:27 danielk1977 Exp $ */ #ifdef SQLITE_ENABLE_FTS3 @@ -82710,6 +84037,8 @@ SQLITE_API int sqlite3_initialize(void){ rc = SQLITE_NOMEM; } } + } + if( rc==SQLITE_OK ){ sqlite3GlobalConfig.nRefInitMutex++; } sqlite3_mutex_leave(pMaster); @@ -82789,12 +84118,8 @@ SQLITE_API int sqlite3_shutdown(void){ if( sqlite3GlobalConfig.isInit ){ sqlite3_os_end(); } - if( sqlite3GlobalConfig.m.xShutdown ){ - sqlite3MallocEnd(); - } - if( sqlite3GlobalConfig.mutex.xMutexEnd ){ - sqlite3MutexEnd(); - } + sqlite3MallocEnd(); + sqlite3MutexEnd(); sqlite3GlobalConfig.isInit = 0; return SQLITE_OK; } @@ -82818,6 +84143,11 @@ SQLITE_API int sqlite3_config(int op, ...){ 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; @@ -82837,6 +84167,19 @@ SQLITE_API int sqlite3_config(int op, ...){ sqlite3GlobalConfig.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*); @@ -82848,16 +84191,6 @@ SQLITE_API int sqlite3_config(int op, ...){ *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; 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; - } case SQLITE_CONFIG_MEMSTATUS: { /* Enable or disable the malloc status collection */ sqlite3GlobalConfig.bMemstat = va_arg(ap, int); @@ -82878,6 +84211,20 @@ SQLITE_API int sqlite3_config(int op, ...){ 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; + break; + } + #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) case SQLITE_CONFIG_HEAP: { /* Designate a buffer for heap memory space */ @@ -82909,14 +84256,6 @@ SQLITE_API int sqlite3_config(int op, ...){ } #endif -#if defined(SQLITE_ENABLE_MEMSYS6) - case SQLITE_CONFIG_CHUNKALLOC: { - sqlite3GlobalConfig.nSmall = va_arg(ap, int); - sqlite3GlobalConfig.m = *sqlite3MemGetMemsys6(); - break; - } -#endif - case SQLITE_CONFIG_LOOKASIDE: { sqlite3GlobalConfig.szLookaside = va_arg(ap, int); sqlite3GlobalConfig.nLookaside = va_arg(ap, int); @@ -82985,6 +84324,13 @@ 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, ...){ @@ -83071,6 +84417,7 @@ static int nocaseCollatingFunc( ){ int r = sqlite3StrNICmp( (const char *)pKey1, (const char *)pKey2, (nKey1mutex); 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); } @@ -83834,6 +85182,15 @@ 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 @@ -83948,8 +85305,8 @@ 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>127 -# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127 +#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>1000 +# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 1000 #endif #if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>30 # error SQLITE_MAX_ATTACHED must be between 0 and 30 @@ -84065,9 +85422,9 @@ static int openDatabase( | SQLITE_LoadExtension #endif ; - sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&db->aCollSeq, 0); #ifndef SQLITE_OMIT_VIRTUALTABLE - sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&db->aModule, 0); #endif db->pVfs = sqlite3_vfs_find(zVfs); @@ -84107,6 +85464,9 @@ 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); goto opendb_out; } @@ -84189,7 +85549,8 @@ static int openDatabase( #endif /* Enable the lookaside-malloc subsystem */ - setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, sqlite3GlobalConfig.nLookaside); + setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, + sqlite3GlobalConfig.nLookaside); opendb_out: if( db ){ @@ -84366,6 +85727,7 @@ 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. @@ -84374,6 +85736,7 @@ SQLITE_API int sqlite3_global_recover(void){ return SQLITE_OK; } #endif +#endif /* ** Test to see whether or not the database connection is in autocommit @@ -84398,6 +85761,7 @@ 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. @@ -84407,6 +85771,7 @@ SQLITE_PRIVATE int sqlite3Corrupt(void){ */ SQLITE_API void sqlite3_thread_cleanup(void){ } +#endif /* ** Return meta information about a specific column of a database table. @@ -92464,6 +93829,13 @@ 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 ){ @@ -92478,14 +93850,6 @@ 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); } @@ -93749,7 +95113,7 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule( ** This file contains code for implementations of the r-tree and r*-tree ** algorithms packaged as an SQLite virtual table module. ** -** $Id: rtree.c,v 1.9 2008/09/08 11:07:03 danielk1977 Exp $ +** $Id: rtree.c,v 1.11 2008/11/12 15:24:27 drh Exp $ */ #if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE) @@ -93794,10 +95158,8 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule( #ifndef SQLITE_CORE - #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #else - #include "sqlite3.h" #endif @@ -93961,8 +95323,12 @@ struct RtreeCell { RtreeCoord aCoord[RTREE_MAX_DIMENSIONS*2]; }; -#define MAX(x,y) ((x) < (y) ? (y) : (x)) -#define MIN(x,y) ((x) > (y) ? (y) : (x)) +#ifndef MAX +# define MAX(x,y) ((x) < (y) ? (y) : (x)) +#endif +#ifndef MIN +# define MIN(x,y) ((x) > (y) ? (y) : (x)) +#endif /* ** Functions to deserialize a 16 bit integer, 32 bit real number and @@ -94335,7 +95701,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, int + sqlite3 *, void *, int, const char *const*, sqlite3_vtab **, char **, int ); /* @@ -94348,7 +95714,7 @@ static int rtreeCreate( sqlite3_vtab **ppVtab, char **pzErr ){ - return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1, (int)pAux); + return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 1); } /* @@ -94361,7 +95727,7 @@ static int rtreeConnect( sqlite3_vtab **ppVtab, char **pzErr ){ - return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0, (int)pAux); + return rtreeInit(db, pAux, argc, argv, ppVtab, pzErr, 0); } /* @@ -96386,18 +97752,18 @@ static int getPageSize(sqlite3 *db, const char *zDb, int *piPageSize){ */ static int rtreeInit( sqlite3 *db, /* Database connection */ - void *pAux, /* Pointer to head of rtree list */ + void *pAux, /* One of the RTREE_COORD_* constants */ 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 eCoordType /* One of the RTREE_COORD_* constants */ + int isCreate /* True for xCreate, false for xConnect */ ){ 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 */ @@ -96630,10 +97996,8 @@ SQLITE_API int sqlite3_extension_init( #ifndef SQLITE_CORE - #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #else - #include "sqlite3.h" #endif /* @@ -97090,3 +98454,261 @@ 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: fts3_icu.c,v 1.3 2008/09/01 18:34:20 danielk1977 Exp $ +*/ + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) +#ifdef SQLITE_ENABLE_ICU + + +#include +#include + +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( iInputpIter = 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( iStartaChar, 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 ********************************************/