/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.2. By combining all the individual C code files into this
+** version 3.6.5. 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
** 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
-** 6312 lines past this header comment.) Additional code files may be
+** 6569 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-08-30 16:23:32 UTC.
+** This amalgamation was generated on 2008-11-12 15:36:10 UTC.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#endif
#endif
+/*
+** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
+** It determines whether or not the features related to
+** SQLITE_CONFIG_MEMSTATUS are availabe by default or not. This value can
+** be overridden at runtime using the sqlite3_config() API.
+*/
+#if !defined(SQLITE_DEFAULT_MEMSTATUS)
+# define SQLITE_DEFAULT_MEMSTATUS 1
+#endif
+
/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+defined(SQLITE_POW2_MEMORY_SIZE)>1
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
+ defined(SQLITE_POW2_MEMORY_SIZE)>1
# error "At most one of the following compile-time configuration options\
is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\
SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE"
#endif
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+defined(SQLITE_POW2_MEMORY_SIZE)==0
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+\
+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+\
+ defined(SQLITE_POW2_MEMORY_SIZE)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif
#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.
** 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.2"
-#define SQLITE_VERSION_NUMBER 3006002
+#define SQLITE_VERSION "3.6.5"
+#define SQLITE_VERSION_NUMBER 3006005
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
** CAPI3REF: Test To See If The Library Is Threadsafe {H10100} <S60100>
**
** SQLite can be compiled with or without mutexes. When
-** the [SQLITE_THREADSAFE] C preprocessor macro is true, mutexes
-** are enabled and SQLite is threadsafe. When that macro is false,
+** the [SQLITE_THREADSAFE] C preprocessor macro 1 or 2, mutexes
+** are enabled and SQLite is threadsafe. When the
+** [SQLITE_THREADSAFE] macro is 0,
** the mutexes are omitted. Without the mutexes, it is not safe
** to use SQLite concurrently from more than one thread.
**
** only the default compile-time setting, not any run-time changes
** to that setting.
**
+** See the [threading mode] documentation for additional information.
+**
** INVARIANTS:
**
-** {H10101} The [sqlite3_threadsafe()] function shall return nonzero if
-** SQLite was compiled with the its mutexes enabled by default
-** or zero if SQLite was compiled such that mutexes are
-** permanently disabled.
+** {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);
** 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
** *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.
**
** 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
**
** 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.
**
** 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 {
** 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
** 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);
SQLITE_API int sqlite3_os_end(void);
/*
-** CAPI3REF: Configuring The SQLite Library {H10145} <S20000><S30200>
+** CAPI3REF: Configuring The SQLite Library {H14100} <S20000><S30200>
** EXPERIMENTAL
**
** The sqlite3_config() interface is used to make global configuration
** 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} <S20000>
+** CAPI3REF: Configure database connections {H14200} <S20000>
** EXPERIMENTAL
**
** The sqlite3_db_config() interface is used to make configuration
** 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, ...);
** The application is responsible for serializing access to
** [database connections] and [prepared statements]. But other mutexes
** are enabled so that SQLite will be safe to use in a multi-threaded
-** environment.</dd>
+** environment as long as no two threads attempt to use the same
+** [database connection] at the same time. See the [threading mode]
+** documentation for additional information.</dd>
**
** <dt>SQLITE_CONFIG_SERIALIZED</dt>
** <dd>There are no arguments to this option. This option enables
** to [database connections] and [prepared statements] so that the
** application is free to use the same [database connection] or the
** same [prepared statement] in different threads at the same time.
-**
-** <p>This configuration option merely sets the default mutex
-** behavior to serialize access to [database connections]. Individual
-** [database connections] can override this setting
-** using the [SQLITE_OPEN_NOMUTEX] flag to [sqlite3_open_v2()].</p></dd>
+** See the [threading mode] documentation for additional information.</dd>
**
** <dt>SQLITE_CONFIG_MALLOC</dt>
** <dd>This option takes a single argument which is a pointer to an
#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 */
/*
** 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
** 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
** 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.
**
** 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:
**
** 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.
**
** previously set handler. Note that calling [sqlite3_busy_timeout()]
** will also set or clear the busy handler.
**
+** The busy callback should not take any actions which modify the
+** database connection that invoked the busy handler. Any such actions
+** result in undefined behavior.
+**
** INVARIANTS:
**
** {H12311} The [sqlite3_busy_handler(D,C,A)] function shall replace
** 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
** previous call. Disable the authorizer by installing a NULL callback.
** The authorizer is disabled by default.
**
+** The authorizer callback must not do anything that will modify
+** the database connection that invoked the authorizer callback.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** When [sqlite3_prepare_v2()] is used to prepare a statement, the
** statement might be reprepared during [sqlite3_step()] due to a
** schema change. Hence, the application should ensure that the
#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 */
/*
**
** If the progress callback returns non-zero, the operation is
** interrupted. This feature can be used to implement a
-** "Cancel" button on a GUI dialog box.
+** "Cancel" button on a GUI progress dialog box.
+**
+** The progress handler must not do anything that will modify
+** the database connection that invoked the progress handler.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
**
** INVARIANTS:
**
** except that it accepts two additional parameters for additional control
** over the new database connection. The flags parameter can take one of
** the following three values, optionally combined with the
-** [SQLITE_OPEN_NOMUTEX] flag:
+** [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags:
**
** <dl>
** <dt>[SQLITE_OPEN_READONLY]</dt>
**
** If the 3rd parameter to sqlite3_open_v2() is not one of the
** combinations shown above or one of the combinations shown above combined
-** with the [SQLITE_OPEN_NOMUTEX] flag, then the behavior is undefined.
+** with the [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags,
+** then the behavior is undefined.
**
-** If the [SQLITE_OPEN_NOMUTEX] flag is set, then mutexes on the
-** opened [database connection] are disabled and the appliation must
-** insure that access to the [database connection] and its associated
-** [prepared statements] is serialized. The [SQLITE_OPEN_NOMUTEX] flag
-** is the default behavior is SQLite is configured using the
-** [SQLITE_CONFIG_MULTITHREAD] or [SQLITE_CONFIG_SINGLETHREAD] options
-** to [sqlite3_config()]. The [SQLITE_OPEN_NOMUTEX] flag only makes a
-** difference when SQLite is in its default [SQLITE_CONFIG_SERIALIZED] mode.
+** If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
+** opens in the multi-thread [threading mode] as long as the single-thread
+** mode has not been set at compile-time or start-time. If the
+** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
+** in the serialized [threading mode] unless single-thread was
+** previously selected at compile-time or start-time.
**
** If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection. This in-memory database will vanish when
** [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.
** 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.
** [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,
** {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*);
);
/*
-** CAPIREF: Retrieving Statement SQL {H13100} <H13000>
+** CAPI3REF: Retrieving Statement SQL {H13100} <H13000>
**
** This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
** characters. Any attempt to create a function with a longer name
** will result in [SQLITE_ERROR] being returned.
**
-** The third parameter is the number of arguments that the SQL function or
+** The third parameter (nArg)
+** is the number of arguments that the SQL function or
** aggregate takes. If this parameter is negative, then the SQL function or
** aggregate may take any number of arguments.
**
** functions with the same name but with either differing numbers of
** arguments or differing preferred text encodings. SQLite will use
** the implementation most closely matches the way in which the
-** SQL function is used.
+** SQL function is used. A function implementation with a non-negative
+** nArg parameter is a better match than a function implementation with
+** a negative nArg. A function where the preferred text encoding
+** matches the database encoding is a better
+** match than a function where the encoding is different.
+** A function where the encoding difference is between UTF16le and UTF16be
+** is a closer match than a function where the encoding difference is
+** between UTF8 and UTF16.
+**
+** Built-in functions may be overloaded by new application-defined functions.
+** The first application-defined function with a given name overrides all
+** built-in functions in the same [database connection] with the same name.
+** Subsequent application-defined functions of the same name only override
+** prior application-defined functions that are an exact match for the
+** number of parameters and preferred encoding.
+**
+** An application-defined function is permitted to call other
+** SQLite interfaces. However, such calls must not
+** close the database connection nor finalize or reset the prepared
+** statement in which the function is running.
**
** INVARIANTS:
**
-** {H16103} The [sqlite3_create_function16()] interface behaves exactly
-** like [sqlite3_create_function()] in every way except that it
-** interprets the zFunctionName argument as zero-terminated UTF-16
+** {H16103} The [sqlite3_create_function16(D,X,...)] interface shall behave
+** as [sqlite3_create_function(D,X,...)] in every way except that it
+** interprets the X argument as zero-terminated UTF-16
** native byte order instead of as zero-terminated UTF-8.
**
-** {H16106} A successful invocation of
-** the [sqlite3_create_function(D,X,N,E,...)] interface registers
+** {H16106} A successful invocation of the
+** [sqlite3_create_function(D,X,N,E,...)] interface shall register
** or replaces callback functions in the [database connection] D
** used to implement the SQL function named X with N parameters
** and having a preferred text encoding of E.
**
** {H16109} A successful call to [sqlite3_create_function(D,X,N,E,P,F,S,L)]
-** replaces the P, F, S, and L values from any prior calls with
+** shall replace the P, F, S, and L values from any prior calls with
** the same D, X, N, and E values.
**
-** {H16112} The [sqlite3_create_function(D,X,...)] interface fails with
-** a return code of [SQLITE_ERROR] if the SQL function name X is
+** {H16112} The [sqlite3_create_function(D,X,...)] interface shall fail
+** if the SQL function name X is
** longer than 255 bytes exclusive of the zero terminator.
**
-** {H16118} Either F must be NULL and S and L are non-NULL or else F
-** is non-NULL and S and L are NULL, otherwise
-** [sqlite3_create_function(D,X,N,E,P,F,S,L)] returns [SQLITE_ERROR].
+** {H16118} The [sqlite3_create_function(D,X,N,E,P,F,S,L)] interface
+** shall fail unless either F is NULL and S and L are non-NULL or
+*** F is non-NULL and S and L are NULL.
**
-** {H16121} The [sqlite3_create_function(D,...)] interface fails with an
+** {H16121} The [sqlite3_create_function(D,...)] interface shall fails with an
** error code of [SQLITE_BUSY] if there exist [prepared statements]
** associated with the [database connection] D.
**
-** {H16124} The [sqlite3_create_function(D,X,N,...)] interface fails with an
-** error code of [SQLITE_ERROR] if parameter N (specifying the number
-** of arguments to the SQL function being registered) is less
+** {H16124} The [sqlite3_create_function(D,X,N,...)] interface shall fail with
+** an error code of [SQLITE_ERROR] if parameter N is less
** than -1 or greater than 127.
**
** {H16127} When N is non-negative, the [sqlite3_create_function(D,X,N,...)]
-** interface causes callbacks to be invoked for the SQL function
+** interface shall register callbacks to be invoked for the
+** SQL function
** named X when the number of arguments to the SQL function is
** exactly N.
**
** {H16130} When N is -1, the [sqlite3_create_function(D,X,N,...)]
-** interface causes callbacks to be invoked for the SQL function
-** named X with any number of arguments.
+** interface shall register callbacks to be invoked for the SQL
+** function named X with any number of arguments.
**
** {H16133} When calls to [sqlite3_create_function(D,X,N,...)]
** specify multiple implementations of the same function X
** and when one implementation has N>=0 and the other has N=(-1)
-** the implementation with a non-zero N is preferred.
+** the implementation with a non-zero N shall be preferred.
**
** {H16136} When calls to [sqlite3_create_function(D,X,N,E,...)]
** specify multiple implementations of the same function X with
** the same number of arguments N but with different
** encodings E, then the implementation where E matches the
-** database encoding is preferred.
+** database encoding shall preferred.
**
** {H16139} For an aggregate SQL function created using
** [sqlite3_create_function(D,X,N,E,P,0,S,L)] the finalizer
-** function L will always be invoked exactly once if the
+** function L shall always be invoked exactly once if the
** step function S is called one or more times.
**
** {H16142} When SQLite invokes either the xFunc or xStep function of
** an application-defined SQL function or aggregate created
** by [sqlite3_create_function()] or [sqlite3_create_function16()],
** then the array of [sqlite3_value] objects passed as the
-** third parameter are always [protected sqlite3_value] objects.
+** third parameter shall be [protected sqlite3_value] objects.
*/
SQLITE_API int sqlite3_create_function(
sqlite3 *db,
** 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} <S20200>
** If another function was previously registered, its
** pArg value is returned. Otherwise NULL is returned.
**
+** The callback implementation must not do anything that will modify
+** the database connection that invoked the callback. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the commit
+** or rollback hook in the first place.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** Registering a NULL function disables the callback.
**
** For the purposes of this API, a transaction is said to have been
** The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).
**
+** The update hook implementation must not do anything that will modify
+** the database connection that invoked the update hook. Any actions
+** to modify the database connection must be deferred until after the
+** completion of the [sqlite3_step()] call that triggered the update hook.
+** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
+** database connections for the meaning of "modify" in this paragraph.
+**
** If another function was previously registered, its pArg value
** is returned. Otherwise NULL is returned.
**
**
** {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.
**
**
** {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.
**
** {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.
*/
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */
+/*
+** CAPI3REF: Retrieve the mutex for a database connection {H17002} <H17000>
+**
+** This interface returns a pointer the [sqlite3_mutex] object that
+** serializes access to the [database connection] given in the argument
+** when the [threading mode] is Serialized.
+** If the [threading mode] is Single-thread or Multi-thread then this
+** routine returns a NULL pointer.
+*/
+SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
+
/*
** CAPI3REF: Low-Level Control Of Database Files {H11300} <S30800>
**
*/
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
-/*
-** CAPI3REF: Database Connection Status {H17201} <S60200>
-** EXPERIMENTAL
-**
-** This interface is used to retrieve runtime status information
-** about a single [database connection]. The first argument is the
-** database connection object to be interrogated. The second argument
-** is the parameter to interrogate. Currently, the only allowed value
-** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
-** Additional options will likely appear in future releases of SQLite.
-**
-** The current value of the request parameter is written into *pCur
-** and the highest instantaneous value is written into *pHiwtr. If
-** the resetFlg is true, then the highest instantaneous value is
-** reset back down to the current value.
-**
-** See also: [sqlite3_status()].
-*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters {H17250} <H17200>
#define SQLITE_STATUS_SCRATCH_SIZE 8
/*
-** CAPI3REF: Status Parameters for database connections {H17275} <H17200>
+** CAPI3REF: Database Connection Status {H17500} <S60200>
+** EXPERIMENTAL
+**
+** This interface is used to retrieve runtime status information
+** about a single [database connection]. The first argument is the
+** database connection object to be interrogated. The second argument
+** is the parameter to interrogate. Currently, the only allowed value
+** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
+** Additional options will likely appear in future releases of SQLite.
+**
+** The current value of the requested parameter is written into *pCur
+** and the highest instantaneous value is written into *pHiwtr. If
+** the resetFlg is true, then the highest instantaneous value is
+** reset back down to the current value.
+**
+** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+
+/*
+** CAPI3REF: Status Parameters for database connections {H17520} <H17500>
** EXPERIMENTAL
**
** Status verbs for [sqlite3_db_status()].
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
+
+/*
+** CAPI3REF: Prepared Statement Status {H17550} <S60200>
+** EXPERIMENTAL
+**
+** Each prepared statement maintains various
+** [SQLITE_STMTSTATUS_SORT | counters] that measure the number
+** of times it has performed specific operations. These counters can
+** be used to monitor the performance characteristics of the prepared
+** statements. For example, if the number of table steps greatly exceeds
+** the number of table searches or result rows, that would tend to indicate
+** that the prepared statement is using a full table scan rather than
+** an index.
+**
+** This interface is used to retrieve and reset counter values from
+** a [prepared statement]. The first argument is the prepared statement
+** object to be interrogated. The second argument
+** is an integer code for a specific [SQLITE_STMTSTATUS_SORT | counter]
+** to be interrogated.
+** The current value of the requested counter is returned.
+** If the resetFlg is true, then the counter is reset to zero after this
+** interface call returns.
+**
+** See also: [sqlite3_status()] and [sqlite3_db_status()].
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+
+/*
+** CAPI3REF: Status Parameters for prepared statements {H17570} <H17550>
+** EXPERIMENTAL
+**
+** These preprocessor macros define integer codes that name counter
+** values associated with the [sqlite3_stmt_status()] interface.
+** The meanings of the various counters are as follows:
+**
+** <dl>
+** <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
+** <dd>This is the number of times that SQLite has stepped forward in
+** a table as part of a full table scan. Large numbers for this counter
+** may indicate opportunities for performance improvement through
+** careful use of indices.</dd>
+**
+** <dt>SQLITE_STMTSTATUS_SORT</dt>
+** <dd>This is the number of sort operations that have occurred.
+** A non-zero value in this counter may indicate an opportunity to
+** improvement performance through careful use of indices.</dd>
+**
+** </dl>
+*/
+#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
+#define SQLITE_STMTSTATUS_SORT 2
+
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
** 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;
};
void *pKey; int nKey; /* Key associated with this element */
};
-/*
-** 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);
#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 ******************/
#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
*/
#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree)
+/*
+** When SQLITE_OMIT_WSD is defined, it means that the target platform does
+** not support Writable Static Data (WSD) such as global and static variables.
+** All variables must either be on the stack or dynamically allocated from
+** the heap. When WSD is unsupported, the variable declarations scattered
+** throughout the SQLite code must become constants instead. The SQLITE_WSD
+** macro is used for this purpose. And instead of referencing the variable
+** directly, we use its constant as a key to lookup the run-time allocated
+** buffer that holds real variable. The constant is also the initializer
+** for the run-time allocated buffer.
+**
+** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL
+** macros become no-ops and have zero performance impact.
+*/
+#ifdef SQLITE_OMIT_WSD
+ #define SQLITE_WSD const
+ #define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
+ #define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
+SQLITE_API int sqlite3_wsd_init(int N, int J);
+SQLITE_API void *sqlite3_wsd_find(void *K, int L);
+#else
+ #define SQLITE_WSD
+ #define GLOBAL(t,v) v
+ #define sqlite3GlobalConfig sqlite3Config
+#endif
+
/*
** Forward references to structures
*/
#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);
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);
#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 */
#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
#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 */
#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
#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
#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
#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
/* 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 ***********************/
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);
#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 int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
-SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int));
+SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*));
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*);
SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
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*);
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
-SQLITE_PRIVATE void sqlite3PagerAlwaysRollback(Pager *pPager);
#ifdef SQLITE_HAS_CODEC
SQLITE_PRIVATE void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
*/
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
/* Bit values for PgHdr.flags */
#define PGHDR_IN_JOURNAL 0x001 /* Page is in rollback journal */
-#define PGHDR_IN_STMTJRNL 0x002 /* Page is in the statement journal */
-#define PGHDR_DIRTY 0x004 /* Page has changed */
-#define PGHDR_NEED_SYNC 0x008 /* Peed to fsync this page */
-#define PGHDR_NEED_READ 0x020 /* Content is unread */
-#define PGHDR_IS_INIT 0x040 /* pData is initialized */
-#define PGHDR_REUSE_UNLIKELY 0x080 /* Hint: Reuse is unlikely */
-#define PGHDR_DONT_WRITE 0x100 /* Do not write content to disk */
+#define PGHDR_DIRTY 0x002 /* Page has changed */
+#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before
+ ** writing this page to the database */
+#define PGHDR_NEED_READ 0x008 /* Content is unread */
+#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */
+#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
/* Initialize and shutdown the page cache subsystem */
SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
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 */
/* 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); /* Rollback to preserved copy */
-
/* Get a list of all dirty pages in the cache, sorted by page number */
SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*);
/* Reset and close the cache object */
SQLITE_PRIVATE void sqlite3PcacheClose(PCache*);
-/* Set flags on all pages in the page cache */
-SQLITE_PRIVATE void sqlite3PcacheSetFlags(PCache*, int andMask, int orMask);
+/* Clear flags from pages of the page cache */
+SQLITE_PRIVATE void sqlite3PcacheClearFlags(PCache*, int mask);
/* Assert flags settings on all pages. Debugging only */
-SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask);
+#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*);
/* Increment the reference count of an existing page */
SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*);
+SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*);
+
/* Return the total number of pages stored in the cache */
SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*);
+#ifdef SQLITE_CHECK_PAGES
/* Iterate through all 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 *));
+#endif
/* Set and get the suggested cache-size for the specified pager-cache.
**
SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *);
SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int);
+#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
#endif /* _PCACHE_H_ */
*/
-#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.
**
**
** 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.
*/
#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 ******************/
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 */
char *zErrMsg; /* Most recent error message (UTF-8 encoded) */
char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */
union {
- int isInterrupted; /* True if sqlite3_interrupt has been called */
+ volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
double notUsed1; /* Spacer */
} u1;
Lookaside lookaside; /* Lookaside malloc configuration */
** 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 */
/*
** 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
** 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}
+#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
+ {nArg, SQLITE_UTF8, bNC*8, pArg, 0, xFunc, 0, 0, #zName}
#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}
#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}
/*
char **azModuleArg; /* Text of all module args. [0] is module name */
#endif
Schema *pSchema; /* Schema that contains this table */
+ Table *pNextZombie; /* Next on the Parse.pZombieTab list */
};
/*
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N or pTab is used */
+ u8 notIndexed; /* True if there is a NOT INDEXED clause */
+ char *zIndex; /* Identifier from "INDEXED BY <zIndex>" clause */
+ Index *pIndex; /* Index structure corresponding to zIndex, if any */
} a[1]; /* One entry for each identifier on the list */
};
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 {
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#endif
int nHeight; /* Expression tree height of current sub-select */
+ Table *pZombieTab; /* List of Table objects to delete after code gen */
};
#ifdef SQLITE_OMIT_VIRTUALTABLE
int szPage; /* Size of each page in pPage[] */
int nPage; /* Number of pages in pPage[] */
int isInit; /* True after initialization has finished */
+ int inProgress; /* True while initialization in progress */
int isMallocInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
- int nSmall; /* alloc size threshold used by mem6.c */
int mxParserStack; /* maximum depth of the parser stack */
+ int sharedCacheEnabled; /* true if shared-cache mode enabled */
};
/*
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 const sqlite3_mem_methods *sqlite3MemGetMemsys5(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
+#ifndef SQLITE_MUTEX_OMIT
SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void);
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int);
SQLITE_PRIVATE int sqlite3MutexInit(void);
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*);
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*);
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);
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
+
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
+#endif
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
-SQLITE_PRIVATE struct Sqlite3Config sqlite3Config;
-SQLITE_PRIVATE FuncDefHash sqlite3GlobalFunctions;
+SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
+SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
#endif
SQLITE_PRIVATE void sqlite3RootPageMoved(Db*, int, int);
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, 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*);
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 *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
+SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
#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 *);
** The following singleton contains the global configuration for
** the SQLite library.
*/
-SQLITE_PRIVATE struct Sqlite3Config sqlite3Config = {
- 1, /* bMemstat */
- 1, /* bCoreMutex */
- 1, /* bFullMutex */
- 0x7ffffffe, /* mxStrlen */
- 100, /* szLookaside */
- 500, /* nLookaside */
+SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
+ SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
+ 1, /* bCoreMutex */
+ SQLITE_THREADSAFE==1, /* bFullMutex */
+ 0x7ffffffe, /* mxStrlen */
+ 100, /* szLookaside */
+ 500, /* nLookaside */
/* Other fields all default to zero */
};
** database connections. After initialization, this table is
** read-only.
*/
-SQLITE_PRIVATE FuncDefHash sqlite3GlobalFunctions;
+SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
/************** End of global.c **********************************************/
/************** Begin file status.c ******************************************/
/*
** Variables in which to record status information.
*/
-static struct {
+typedef struct sqlite3StatType sqlite3StatType;
+static SQLITE_WSD struct sqlite3StatType {
int nowValue[9]; /* Current value */
int mxValue[9]; /* Maximum value */
-} sqlite3Stat;
+} sqlite3Stat = { {0,}, {0,} };
+/* The "wsdStat" macro will resolve to the status information
+** state vector. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdStat can refer directly
+** to the "sqlite3Stat" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
+# define wsdStat x[0]
+#else
+# define wsdStatInit
+# define wsdStat sqlite3Stat
+#endif
+
/*
** Return the current value of a status parameter.
*/
SQLITE_PRIVATE int sqlite3StatusValue(int op){
- assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
- return sqlite3Stat.nowValue[op];
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ return wsdStat.nowValue[op];
}
/*
** caller holds appropriate locks.
*/
SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
- assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
- sqlite3Stat.nowValue[op] += N;
- if( sqlite3Stat.nowValue[op]>sqlite3Stat.mxValue[op] ){
- sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ wsdStat.nowValue[op] += N;
+ if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
}
** Set the value of a status to X.
*/
SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
- assert( op>=0 && op<ArraySize(sqlite3Stat.nowValue) );
- sqlite3Stat.nowValue[op] = X;
- if( sqlite3Stat.nowValue[op]>sqlite3Stat.mxValue[op] ){
- sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
+ wsdStatInit;
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ wsdStat.nowValue[op] = X;
+ if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
}
** then this routine is not threadsafe.
*/
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
- if( op<0 || op>=ArraySize(sqlite3Stat.nowValue) ){
+ wsdStatInit;
+ if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
return SQLITE_MISUSE;
}
- *pCurrent = sqlite3Stat.nowValue[op];
- *pHighwater = sqlite3Stat.mxValue[op];
+ *pCurrent = wsdStat.nowValue[op];
+ *pHighwater = wsdStat.mxValue[op];
if( resetFlag ){
- sqlite3Stat.mxValue[op] = sqlite3Stat.nowValue[op];
+ wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
return SQLITE_OK;
}
}
#ifndef SQLITE_OMIT_LOCALTIME
else if( strcmp(z, "utc")==0 ){
- double c1;
+ int c1;
computeJD(p);
c1 = localtimeOffset(p);
p->iJD -= c1;
** external linkage.
*/
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
- static FuncDef aDateTimeFuncs[] = {
+ static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
FUNCTION(julianday, -1, 0, 0, juliandayFunc ),
FUNCTION(date, -1, 0, 0, dateFunc ),
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;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
for(i=0; i<ArraySize(aDateTimeFuncs); i++){
- sqlite3FuncDefInsert(&sqlite3GlobalFunctions, &aDateTimeFuncs[i]);
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
}
** 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; \
/*
** The list of all registered VFS implementations.
*/
-static sqlite3_vfs *vfsList = 0;
+static sqlite3_vfs * SQLITE_WSD vfsList = 0;
+#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
/*
** Locate a VFS by name. If no name is given, simply return the
*/
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);
** 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);
/*
** Global variables.
*/
-static struct BenignMallocHooks {
+typedef struct BenignMallocHooks BenignMallocHooks;
+static SQLITE_WSD struct BenignMallocHooks {
void (*xBenignBegin)(void);
void (*xBenignEnd)(void);
-} hooks;
+} sqlite3Hooks = { 0, 0 };
+
+/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
+** structure. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdHooks can refer directly
+** to the "sqlite3Hooks" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdHooksInit \
+ BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
+# define wsdHooks x[0]
+#else
+# define wsdHooksInit
+# define wsdHooks sqlite3Hooks
+#endif
+
/*
** Register hooks to call when sqlite3BeginBenignMalloc() and
void (*xBenignBegin)(void),
void (*xBenignEnd)(void)
){
- hooks.xBenignBegin = xBenignBegin;
- hooks.xBenignEnd = xBenignEnd;
+ wsdHooksInit;
+ wsdHooks.xBenignBegin = xBenignBegin;
+ wsdHooks.xBenignEnd = xBenignEnd;
}
/*
** indicates that subsequent malloc failures are non-benign.
*/
SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
- if( hooks.xBenignBegin ){
- hooks.xBenignBegin();
+ wsdHooksInit;
+ if( wsdHooks.xBenignBegin ){
+ wsdHooks.xBenignBegin();
}
}
SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
- if( hooks.xBenignEnd ){
- hooks.xBenignEnd();
+ wsdHooksInit;
+ if( wsdHooks.xBenignEnd ){
+ wsdHooks.xBenignEnd();
}
}
#endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
/************** End of fault.c ***********************************************/
+/************** Begin file mem0.c ********************************************/
+/*
+** 2008 October 28
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains a no-op memory allocation drivers for use when
+** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented
+** here always fail. SQLite will not operate with these drivers. These
+** are merely placeholders. Real drivers must be substituted using
+** sqlite3_config() before SQLite will operate.
+**
+** $Id$
+*/
+
+/*
+** This version of the memory allocator is the default. It is
+** used when no other memory allocator is specified using compile-time
+** macros.
+*/
+#ifdef SQLITE_ZERO_MALLOC
+
+/*
+** No-op versions of all memory allocation routines
+*/
+static void *sqlite3MemMalloc(int nByte){ return 0; }
+static void sqlite3MemFree(void *pPrior){ return; }
+static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
+static int sqlite3MemSize(void *pPrior){ return 0; }
+static int sqlite3MemRoundup(int n){ return n; }
+static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
+static void sqlite3MemShutdown(void *NotUsed){ return; }
+
+/*
+** This routine is the only routine in this file with external linkage.
+**
+** Populate the low-level memory allocation function pointers in
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
+*/
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+ static const sqlite3_mem_methods defaultMethods = {
+ sqlite3MemMalloc,
+ sqlite3MemFree,
+ sqlite3MemRealloc,
+ sqlite3MemSize,
+ sqlite3MemRoundup,
+ sqlite3MemInit,
+ sqlite3MemShutdown,
+ 0
+ };
+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+}
+
+#endif /* SQLITE_ZERO_MALLOC */
+
+/************** End of mem0.c ************************************************/
/************** Begin file mem1.c ********************************************/
/*
** 2007 August 14
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,
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
-** sqlite3Config.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 */
** Initialize the memory allocation subsystem.
*/
static int sqlite3MemInit(void *NotUsed){
- if( !sqlite3Config.bMemstat ){
+ if( !sqlite3GlobalConfig.bMemstat ){
/* If memory status is enabled, then the malloc.c wrapper will already
** hold the STATIC_MEM mutex when the routines here are invoked. */
mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
struct MemBlockHdr *pHdr;
void **pBt;
char *z;
- assert( sqlite3Config.bMemstat || mem.mutex!=0 );
+ assert( sqlite3GlobalConfig.bMemstat || mem.mutex!=0 );
pHdr = sqlite3MemsysGetHeader(pPrior);
pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
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,
sqlite3MemShutdown,
0
};
- return &defaultMethods;
-}
-
-/*
-** Populate the low-level memory allocation function pointers in
-** sqlite3Config.m with pointers to the routines in this file.
-*/
-SQLITE_PRIVATE void sqlite3MemSetDefault(void){
- sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetDefault());
+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
}
/*
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
-static struct {
+static SQLITE_WSD struct Mem3Global {
+ /*
+ ** Memory available for allocation. nPool is the size of the array
+ ** (in Mem3Blocks) pointed to by aPool less 2.
+ */
+ u32 nPool;
+ Mem3Block *aPool;
+
/*
** True if we are evaluating an out-of-memory callback.
*/
*/
u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
+} mem3 = { 97535575 };
- /*
- ** Memory available for allocation. nPool is the size of the array
- ** (in Mem3Blocks) pointed to by aPool less 2.
- */
- u32 nPool;
- Mem3Block *aPool;
-} mem3;
+#define mem3 GLOBAL(struct Mem3Global, mem3)
/*
** Unlink the chunk at mem3.aPool[i] from list it is currently
/*
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
** will already be held (obtained by code in malloc.c) if
-** sqlite3Config.bMemStat is true.
+** sqlite3GlobalConfig.bMemStat is true.
*/
static void memsys3Enter(void){
- if( sqlite3Config.bMemstat==0 && mem3.mutex==0 ){
+ if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
sqlite3_mutex_enter(mem3.mutex);
** Initialize this module.
*/
static int memsys3Init(void *NotUsed){
- if( !sqlite3Config.pHeap ){
+ if( !sqlite3GlobalConfig.pHeap ){
return SQLITE_ERROR;
}
/* Store a pointer to the memory block in global structure mem3. */
assert( sizeof(Mem3Block)==8 );
- mem3.aPool = (Mem3Block *)sqlite3Config.pHeap;
- mem3.nPool = (sqlite3Config.nHeap / sizeof(Mem3Block)) - 2;
+ mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
+ mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
/* Initialize the master block. */
mem3.szMaster = mem3.nPool;
** Open the file indicated and write a log of all unfreed memory
** allocations into that log.
*/
-#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
+#ifdef SQLITE_DEBUG
FILE *out;
int i, j;
u32 size;
}else{
fclose(out);
}
-}
#endif
+}
/*
** This routine is the only routine in this file with external
** linkage.
**
** Populate the low-level memory allocation function pointers in
-** sqlite3Config.m with pointers to the routines in this file. The
+** sqlite3GlobalConfig.m with pointers to the routines in this file. The
** arguments specify the block of memory to manage.
**
** This routine is only called by sqlite3_config(), and therefore
/*
** 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)<<SQLITE_POW2_LOGMAX)
-
-/*
-** Number of distinct allocation sizes.
-*/
-#define NSIZE (SQLITE_POW2_LOGMAX - SQLITE_POW2_LOGMIN + 1)
-
/*
** A minimum allocation is an instance of the following structure.
** Larger allocations are an array of these structures where the
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
-static struct {
+static SQLITE_WSD struct Mem5Global {
/*
- ** The alarm callback and its arguments. The mem5.mutex lock will
- ** be held while the callback is running. Recursive calls into
- ** the memory subsystem are allowed, but no new callbacks will be
- ** issued. The alarmBusy variable is set to prevent recursive
- ** callbacks.
+ ** Memory available for allocation
*/
- sqlite3_int64 alarmThreshold;
- void (*alarmCallback)(void*, sqlite3_int64,int);
- void *alarmArg;
- int alarmBusy;
+ int nAtom; /* Smallest possible allocation in bytes */
+ int nBlock; /* Number of nAtom sized blocks in zPool */
+ u8 *zPool;
/*
** Mutex to control access to the memory allocation subsystem.
*/
u8 *aCtrl;
- /*
- ** Memory available for allocation
- */
- int nAtom; /* Smallest possible allocation in bytes */
- int nBlock; /* Number of nAtom sized blocks in zPool */
- u8 *zPool;
-} mem5;
+} mem5 = { 19804167 };
+
+#define mem5 GLOBAL(struct Mem5Global, mem5)
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.nAtom]))
/*
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
** will already be held (obtained by code in malloc.c) if
-** sqlite3Config.bMemStat is true.
+** sqlite3GlobalConfig.bMemStat is true.
*/
static void memsys5Enter(void){
- if( sqlite3Config.bMemstat==0 && mem5.mutex==0 ){
+ if( sqlite3GlobalConfig.bMemstat==0 && mem5.mutex==0 ){
mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
sqlite3_mutex_enter(mem5.mutex);
*/
static int memsys5Init(void *NotUsed){
int ii;
- int nByte = sqlite3Config.nHeap;
- u8 *zByte = (u8 *)sqlite3Config.pHeap;
+ int nByte = sqlite3GlobalConfig.nHeap;
+ u8 *zByte = (u8 *)sqlite3GlobalConfig.pHeap;
int nMinLog; /* Log of minimum allocation size in bytes*/
int iOffset;
return SQLITE_ERROR;
}
- nMinLog = memsys5Log(sqlite3Config.mnReq);
+ nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
mem5.nAtom = (1<<nMinLog);
while( sizeof(Mem5Link)>mem5.nAtom ){
mem5.nAtom = mem5.nAtom << 1;
#endif /* SQLITE_ENABLE_MEMSYS5 */
/************** End of mem5.c ************************************************/
-/************** Begin file mem6.c ********************************************/
-/*
-** 2008 July 24
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file contains an alternative memory allocation system for SQLite.
-** This system is implemented as a wrapper around the system provided
-** by the operating system - vanilla malloc(), realloc() and free().
-**
-** This system differentiates between requests for "small" allocations
-** (by default those of 128 bytes or less) and "large" allocations (all
-** others). The 256 byte threshhold is configurable at runtime.
-**
-** All requests for large allocations are passed through to the
-** default system.
-**
-** Requests for small allocations are met by allocating space within
-** one or more larger "chunks" of memory obtained from the default
-** memory allocation system. Chunks of memory are usually 64KB or
-** larger. The algorithm used to manage space within each chunk is
-** the same as that used by mem5.c.
-**
-** This strategy is designed to prevent the default memory allocation
-** system (usually the system malloc) from suffering from heap
-** fragmentation. On some systems, heap fragmentation can cause a
-** significant real-time slowdown.
-**
-** $Id$
-*/
-
-#ifdef SQLITE_ENABLE_MEMSYS6
-
-
-/*
-** Maximum size of any "small" allocation is ((1<<LOGMAX)*Mem6Chunk.nAtom).
-** Mem6Chunk.nAtom is always at least 8, so this is not a practical
-** limitation
-*/
-#define LOGMAX 30
-
-/*
-** Default value for the "small" allocation size threshold.
-*/
-#define SMALL_MALLOC_DEFAULT_THRESHOLD 256
-
-/*
-** Minimum size for a memory chunk.
-*/
-#define MIN_CHUNKSIZE (1<<16)
-
-#define LOG2_MINALLOC 4
-
-
-typedef struct Mem6Chunk Mem6Chunk;
-typedef struct Mem6Link Mem6Link;
-
-/*
-** A minimum allocation is an instance of the following structure.
-** Larger allocations are an array of these structures where the
-** size of the array is a power of 2.
-*/
-struct Mem6Link {
- int next; /* Index of next free chunk */
- int prev; /* Index of previous free chunk */
-};
-
-/*
-** Masks used for mem5.aCtrl[] elements.
-*/
-#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block relative to POW2_MIN */
-#define CTRL_FREE 0x20 /* True if not checked out */
-
-struct Mem6Chunk {
- Mem6Chunk *pNext;
-
- /*
- ** Lists of free blocks of various sizes.
- */
- int aiFreelist[LOGMAX+1];
-
- int nCheckedOut; /* Number of currently outstanding allocations */
-
- /*
- ** Space for tracking which blocks are checked out and the size
- ** of each block. One byte per block.
- */
- u8 *aCtrl;
-
- /*
- ** Memory available for allocation
- */
- int nAtom; /* Smallest possible allocation in bytes */
- int nBlock; /* Number of nAtom sized blocks in zPool */
- u8 *zPool; /* Pointer to memory chunk from which allocations are made */
-};
-
-#define MEM6LINK(idx) ((Mem6Link *)(&pChunk->zPool[(idx)*pChunk->nAtom]))
-
-struct Mem6Global {
- int nMinAlloc; /* Minimum allowed allocation size */
- int nThreshold; /* Allocs larger than this go to malloc() */
- int nLogThreshold; /* log2 of (nThreshold/nMinAlloc) */
- sqlite3_mutex *mutex;
- Mem6Chunk *pChunk; /* Singly linked list of all memory chunks */
-} mem6;
-
-/*
-** Unlink the chunk at pChunk->aPool[i] from list it is currently
-** on. It should be found on pChunk->aiFreelist[iLogsize].
-*/
-static void memsys6Unlink(Mem6Chunk *pChunk, int i, int iLogsize){
- int next, prev;
- assert( i>=0 && i<pChunk->nBlock );
- assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold );
- assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
-
- next = MEM6LINK(i)->next;
- prev = MEM6LINK(i)->prev;
- if( prev<0 ){
- pChunk->aiFreelist[iLogsize] = next;
- }else{
- MEM6LINK(prev)->next = next;
- }
- if( next>=0 ){
- MEM6LINK(next)->prev = prev;
- }
-}
-
-/*
-** Link the chunk at mem5.aPool[i] so that is on the iLogsize
-** free list.
-*/
-static void memsys6Link(Mem6Chunk *pChunk, int i, int iLogsize){
- int x;
- assert( i>=0 && i<pChunk->nBlock );
- assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold );
- assert( (pChunk->aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
-
- x = MEM6LINK(i)->next = pChunk->aiFreelist[iLogsize];
- MEM6LINK(i)->prev = -1;
- if( x>=0 ){
- assert( x<pChunk->nBlock );
- MEM6LINK(x)->prev = i;
- }
- pChunk->aiFreelist[iLogsize] = i;
-}
-
-
-/*
-** Find the first entry on the freelist iLogsize. Unlink that
-** entry and return its index.
-*/
-static int memsys6UnlinkFirst(Mem6Chunk *pChunk, int iLogsize){
- int i;
- int iFirst;
-
- assert( iLogsize>=0 && iLogsize<=mem6.nLogThreshold );
- i = iFirst = pChunk->aiFreelist[iLogsize];
- assert( iFirst>=0 );
- memsys6Unlink(pChunk, iFirst, iLogsize);
- return iFirst;
-}
-
-static int roundupLog2(int n){
- static const char LogTable256[256] = {
- 0, /* 1 */
- 1, /* 2 */
- 2, 2, /* 3..4 */
- 3, 3, 3, 3, /* 5..8 */
- 4, 4, 4, 4, 4, 4, 4, 4, /* 9..16 */
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, /* 17..32 */
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, /* 33..64 */
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* 65..128 */
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* 129..256 */
- };
-
- assert(n<=(1<<16) && n>0);
- if( n<=256 ) return LogTable256[n-1];
- return LogTable256[(n>>8) - ((n&0xFF)?0:1)] + 8;
-}
-
-/*
-** Allocate and return a block of (pChunk->nAtom << iLogsize) bytes from chunk
-** pChunk. If the allocation request cannot be satisfied, return 0.
-*/
-static void *chunkMalloc(Mem6Chunk *pChunk, int iLogsize){
- int i; /* Index of a mem5.aPool[] slot */
- int iBin; /* Index into mem5.aiFreelist[] */
-
- /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
- ** block. If not, then split a block of the next larger power of
- ** two in order to create a new free block of size iLogsize.
- */
- for(iBin=iLogsize; pChunk->aiFreelist[iBin]<0 && iBin<=mem6.nLogThreshold; iBin++){}
- if( iBin>mem6.nLogThreshold ) return 0;
- i = memsys6UnlinkFirst(pChunk, iBin);
- while( iBin>iLogsize ){
- int newSize;
- iBin--;
- newSize = 1 << iBin;
- pChunk->aCtrl[i+newSize] = CTRL_FREE | iBin;
- memsys6Link(pChunk, i+newSize, iBin);
- }
- pChunk->aCtrl[i] = iLogsize;
-
- /* Return a pointer to the allocated memory. */
- pChunk->nCheckedOut++;
- return (void*)&pChunk->zPool[i*pChunk->nAtom];
-}
-
-/*
-** Free the allocation pointed to by p, which is guaranteed to be non-zero
-** and a part of chunk object pChunk.
-*/
-static void chunkFree(Mem6Chunk *pChunk, void *pOld){
- u32 size, iLogsize;
- int iBlock;
-
- /* Set iBlock to the index of the block pointed to by pOld in
- ** the array of pChunk->nAtom byte blocks pointed to by pChunk->zPool.
- */
- iBlock = ((u8 *)pOld-pChunk->zPool)/pChunk->nAtom;
-
- /* Check that the pointer pOld points to a valid, non-free block. */
- assert( iBlock>=0 && iBlock<pChunk->nBlock );
- assert( ((u8 *)pOld-pChunk->zPool)%pChunk->nAtom==0 );
- assert( (pChunk->aCtrl[iBlock] & CTRL_FREE)==0 );
-
- iLogsize = pChunk->aCtrl[iBlock] & CTRL_LOGSIZE;
- size = 1<<iLogsize;
- assert( iBlock+size-1<pChunk->nBlock );
-
- pChunk->aCtrl[iBlock] |= CTRL_FREE;
- pChunk->aCtrl[iBlock+size-1] |= CTRL_FREE;
-
- pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize;
- while( iLogsize<mem6.nLogThreshold ){
- int iBuddy;
- if( (iBlock>>iLogsize) & 1 ){
- iBuddy = iBlock - size;
- }else{
- iBuddy = iBlock + size;
- }
- assert( iBuddy>=0 );
- if( (iBuddy+(1<<iLogsize))>pChunk->nBlock ) break;
- if( pChunk->aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
- memsys6Unlink(pChunk, iBuddy, iLogsize);
- iLogsize++;
- if( iBuddy<iBlock ){
- pChunk->aCtrl[iBuddy] = CTRL_FREE | iLogsize;
- pChunk->aCtrl[iBlock] = 0;
- iBlock = iBuddy;
- }else{
- pChunk->aCtrl[iBlock] = CTRL_FREE | iLogsize;
- pChunk->aCtrl[iBuddy] = 0;
- }
- size *= 2;
- }
- pChunk->nCheckedOut--;
- memsys6Link(pChunk, iBlock, iLogsize);
-}
-
-/*
-** Return the actual size of the block pointed to by p, which is guaranteed
-** to have been allocated from chunk pChunk.
-*/
-static int chunkSize(Mem6Chunk *pChunk, void *p){
- int iSize = 0;
- if( p ){
- int i = ((u8 *)p-pChunk->zPool)/pChunk->nAtom;
- assert( i>=0 && i<pChunk->nBlock );
- iSize = pChunk->nAtom * (1 << (pChunk->aCtrl[i]&CTRL_LOGSIZE));
- }
- return iSize;
-}
-
-/*
-** Return true if there are currently no outstanding allocations.
-*/
-static int chunkIsEmpty(Mem6Chunk *pChunk){
- return (pChunk->nCheckedOut==0);
-}
-
-/*
-** Initialize the buffer zChunk, which is nChunk bytes in size, as
-** an Mem6Chunk object. Return a copy of the zChunk pointer.
-*/
-static Mem6Chunk *chunkInit(u8 *zChunk, int nChunk, int nMinAlloc){
- int ii;
- int iOffset;
- Mem6Chunk *pChunk = (Mem6Chunk *)zChunk;
-
- assert( nChunk>sizeof(Mem6Chunk) );
- assert( nMinAlloc>sizeof(Mem6Link) );
-
- memset(pChunk, 0, sizeof(Mem6Chunk));
- pChunk->nAtom = nMinAlloc;
- pChunk->nBlock = ((nChunk-sizeof(Mem6Chunk)) / (pChunk->nAtom+sizeof(u8)));
-
- pChunk->zPool = (u8 *)&pChunk[1];
- pChunk->aCtrl = &pChunk->zPool[pChunk->nBlock*pChunk->nAtom];
-
- for(ii=0; ii<=mem6.nLogThreshold; ii++){
- pChunk->aiFreelist[ii] = -1;
- }
-
- iOffset = 0;
- for(ii=mem6.nLogThreshold; ii>=0; ii--){
- int nAlloc = (1<<ii);
- while( (iOffset+nAlloc)<=pChunk->nBlock ){
- pChunk->aCtrl[iOffset] = ii | CTRL_FREE;
- memsys6Link(pChunk, iOffset, ii);
- iOffset += nAlloc;
- }
- }
-
- return pChunk;
-}
-
-
-static void mem6Enter(void){
- sqlite3_mutex_enter(mem6.mutex);
-}
-
-static void mem6Leave(void){
- sqlite3_mutex_leave(mem6.mutex);
-}
-
-/*
-** Based on the number and size of the currently allocated chunks, return
-** the size of the next chunk to allocate, in bytes.
-*/
-static int nextChunkSize(void){
- int iTotal = MIN_CHUNKSIZE;
- Mem6Chunk *p;
- for(p=mem6.pChunk; p; p=p->pNext){
- iTotal = iTotal*2;
- }
- return iTotal;
-}
-
-static void freeChunk(Mem6Chunk *pChunk){
- Mem6Chunk **pp = &mem6.pChunk;
- for( pp=&mem6.pChunk; *pp!=pChunk; pp = &(*pp)->pNext );
- *pp = (*pp)->pNext;
- free(pChunk);
-}
-
-static void *memsys6Malloc(int nByte){
- Mem6Chunk *pChunk;
- void *p = 0;
- int nTotal = nByte+8;
- int iOffset = 0;
-
- if( nTotal>mem6.nThreshold ){
- p = malloc(nTotal);
- }else{
- int iLogsize = 0;
- if( nTotal>(1<<LOG2_MINALLOC) ){
- iLogsize = roundupLog2(nTotal) - LOG2_MINALLOC;
- }
- mem6Enter();
- for(pChunk=mem6.pChunk; pChunk; pChunk=pChunk->pNext){
- p = chunkMalloc(pChunk, iLogsize);
- if( p ){
- break;
- }
- }
- if( !p ){
- int iSize = nextChunkSize();
- p = malloc(iSize);
- if( p ){
- pChunk = chunkInit((u8 *)p, iSize, mem6.nMinAlloc);
- pChunk->pNext = mem6.pChunk;
- mem6.pChunk = pChunk;
- p = chunkMalloc(pChunk, iLogsize);
- assert(p);
- }
- }
- iOffset = ((u8*)p - (u8*)pChunk);
- mem6Leave();
- }
-
- if( !p ){
- return 0;
- }
- ((u32 *)p)[0] = iOffset;
- ((u32 *)p)[1] = nByte;
- return &((u32 *)p)[2];
-}
-
-static int memsys6Size(void *pPrior){
- if( pPrior==0 ) return 0;
- return ((u32*)pPrior)[-1];
-}
-
-static void memsys6Free(void *pPrior){
- int iSlot;
- void *p = &((u32 *)pPrior)[-2];
- iSlot = ((u32 *)p)[0];
- if( iSlot ){
- Mem6Chunk *pChunk;
- mem6Enter();
- pChunk = (Mem6Chunk *)(&((u8 *)p)[-1 * iSlot]);
- chunkFree(pChunk, p);
- if( chunkIsEmpty(pChunk) ){
- freeChunk(pChunk);
- }
- mem6Leave();
- }else{
- free(p);
- }
-}
-
-static void *memsys6Realloc(void *p, int nByte){
- void *p2;
-
- if( p && nByte<=memsys6Size(p) ){
- p2 = p;
- }else{
- p2 = memsys6Malloc(nByte);
- if( p && p2 ){
- memcpy(p2, p, memsys6Size(p));
- memsys6Free(p);
- }
- }
-
- return p2;
-}
-
-static int memsys6Roundup(int n){
- if( n>mem6.nThreshold ){
- return n;
- }else{
- return (1<<roundupLog2(n));
- }
-}
-
-static int memsys6Init(void *pCtx){
- u8 bMemstat = sqlite3Config.bMemstat;
- mem6.nMinAlloc = (1 << LOG2_MINALLOC);
- mem6.pChunk = 0;
- mem6.nThreshold = sqlite3Config.nSmall;
- if( mem6.nThreshold<=0 ){
- mem6.nThreshold = SMALL_MALLOC_DEFAULT_THRESHOLD;
- }
- mem6.nLogThreshold = roundupLog2(mem6.nThreshold) - LOG2_MINALLOC;
- if( !bMemstat ){
- mem6.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
- }
- return SQLITE_OK;
-}
-
-static void memsys6Shutdown(void *pCtx){
- memset(&mem6, 0, sizeof(mem6));
-}
-
-/*
-** This routine is the only routine in this file with external
-** linkage. It returns a pointer to a static sqlite3_mem_methods
-** struct populated with the memsys6 methods.
-*/
-SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys6(void){
- static const sqlite3_mem_methods memsys6Methods = {
- memsys6Malloc,
- memsys6Free,
- memsys6Realloc,
- memsys6Size,
- memsys6Roundup,
- memsys6Init,
- memsys6Shutdown,
- 0
- };
- return &memsys6Methods;
-}
-
-#endif
-
-/************** End of mem6.c ************************************************/
/************** Begin file mutex.c *******************************************/
/*
** 2007 August 14
*************************************************************************
** This file contains the C functions that implement mutexes.
**
-** The implementation in this file does not provide any mutual
-** exclusion and is thus suitable for use only in applications
-** that use SQLite in a single thread. But this implementation
-** does do a lot of error checking on mutexes to make sure they
-** are called correctly and at appropriate times. Hence, this
-** implementation is suitable for testing.
-** debugging purposes
+** This file contains code that is common across all mutex implementations.
+
**
** $Id$
*/
-#ifndef SQLITE_MUTEX_NOOP
+#ifndef SQLITE_MUTEX_OMIT
/*
** Initialize the mutex system.
*/
SQLITE_PRIVATE int sqlite3MutexInit(void){
int rc = SQLITE_OK;
- if( sqlite3Config.bCoreMutex ){
- if( !sqlite3Config.mutex.xMutexAlloc ){
+ if( sqlite3GlobalConfig.bCoreMutex ){
+ if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
/* If the xMutexAlloc method has not been set, then the user did not
** install a mutex implementation via sqlite3_config() prior to
** sqlite3_initialize() being called. This block copies pointers to
- ** the default implementation into the sqlite3Config structure.
+ ** the default implementation into the sqlite3GlobalConfig structure.
**
** The danger is that although sqlite3_config() is not a threadsafe
** API, sqlite3_initialize() is, and so multiple threads may be
** attempting to run this function simultaneously. To guard write
- ** access to the sqlite3Config structure, the 'MASTER' static mutex
+ ** access to the sqlite3GlobalConfig structure, the 'MASTER' static mutex
** is obtained before modifying it.
*/
sqlite3_mutex_methods *p = sqlite3DefaultMutex();
pMaster = p->xMutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
assert(pMaster);
p->xMutexEnter(pMaster);
- assert( sqlite3Config.mutex.xMutexAlloc==0
- || sqlite3Config.mutex.xMutexAlloc==p->xMutexAlloc
+ assert( sqlite3GlobalConfig.mutex.xMutexAlloc==0
+ || sqlite3GlobalConfig.mutex.xMutexAlloc==p->xMutexAlloc
);
- if( !sqlite3Config.mutex.xMutexAlloc ){
- sqlite3Config.mutex = *p;
+ if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
+ sqlite3GlobalConfig.mutex = *p;
}
p->xMutexLeave(pMaster);
}
}else{
- rc = sqlite3Config.mutex.xMutexInit();
+ rc = sqlite3GlobalConfig.mutex.xMutexInit();
}
}
*/
SQLITE_PRIVATE int sqlite3MutexEnd(void){
int rc = SQLITE_OK;
- rc = sqlite3Config.mutex.xMutexEnd();
+ rc = sqlite3GlobalConfig.mutex.xMutexEnd();
return rc;
}
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
- return sqlite3Config.mutex.xMutexAlloc(id);
+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
}
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
- if( !sqlite3Config.bCoreMutex ){
+ if( !sqlite3GlobalConfig.bCoreMutex ){
return 0;
}
- return sqlite3Config.mutex.xMutexAlloc(id);
+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
}
/*
*/
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexFree(p);
+ sqlite3GlobalConfig.mutex.xMutexFree(p);
}
}
*/
SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexEnter(p);
+ sqlite3GlobalConfig.mutex.xMutexEnter(p);
}
}
SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
int rc = SQLITE_OK;
if( p ){
- return sqlite3Config.mutex.xMutexTry(p);
+ return sqlite3GlobalConfig.mutex.xMutexTry(p);
}
return rc;
}
*/
SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexLeave(p);
+ sqlite3GlobalConfig.mutex.xMutexLeave(p);
}
}
** intended for use inside assert() statements.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
- return p==0 || sqlite3Config.mutex.xMutexHeld(p);
+ return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
- return p==0 || sqlite3Config.mutex.xMutexNotheld(p);
+ return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
#endif
-#endif
+#endif /* SQLITE_OMIT_MUTEX */
+
+/************** End of mutex.c ***********************************************/
+/************** Begin file mutex_noop.c **************************************/
+/*
+** 2008 October 07
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement mutexes.
+**
+** This implementation in this file does not provide any mutual
+** exclusion and is thus suitable for use only in applications
+** that use SQLite in a single thread. The routines defined
+** here are place-holders. Applications can substitute working
+** mutex routines at start-time using the
+**
+** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
+**
+** interface.
+**
+** If compiled with SQLITE_DEBUG, then additional logic is inserted
+** that does error checking on mutexes to make sure they are being
+** called correctly.
+**
+** $Id$
+*/
+
+
+#if defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG)
+/*
+** Stub routines for all mutex methods.
+**
+** This routines provide no mutual exclusion or error checking.
+*/
+static int noopMutexHeld(sqlite3_mutex *p){ return 1; }
+static int noopMutexNotheld(sqlite3_mutex *p){ return 1; }
+static int noopMutexInit(void){ return SQLITE_OK; }
+static int noopMutexEnd(void){ return SQLITE_OK; }
+static sqlite3_mutex *noopMutexAlloc(int id){ return (sqlite3_mutex*)8; }
+static void noopMutexFree(sqlite3_mutex *p){ return; }
+static void noopMutexEnter(sqlite3_mutex *p){ return; }
+static int noopMutexTry(sqlite3_mutex *p){ return SQLITE_OK; }
+static void noopMutexLeave(sqlite3_mutex *p){ return; }
-#ifdef SQLITE_MUTEX_NOOP_DEBUG
+SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
+ static sqlite3_mutex_methods sMutex = {
+ noopMutexInit,
+ noopMutexEnd,
+ noopMutexAlloc,
+ noopMutexFree,
+ noopMutexEnter,
+ noopMutexTry,
+ noopMutexLeave,
+
+ noopMutexHeld,
+ noopMutexNotheld
+ };
+
+ return &sMutex;
+}
+#endif /* defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG) */
+
+#if defined(SQLITE_MUTEX_NOOP) && defined(SQLITE_DEBUG)
/*
-** In this implementation, mutexes do not provide any mutual exclusion.
-** But the error checking is provided. This implementation is useful
-** for test purposes.
+** In this implementation, error checking is provided for testing
+** and debugging purposes. The mutexes still do not provide any
+** mutual exclusion.
*/
/*
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
*/
-static int noopMutexHeld(sqlite3_mutex *p){
+static int debugMutexHeld(sqlite3_mutex *p){
return p==0 || p->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 ){
/*
** 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);
** 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;
}
** 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
** 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
return osType==2;
}
#endif /* SQLITE_OS_WINCE */
-
+#endif
#ifdef SQLITE_DEBUG
/*
}
sqlite3_initialize();
if( iLimit>0 ){
- sqlite3_memory_alarm(softHeapLimitEnforcer, 0, iLimit);
+ sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, iLimit);
}else{
- sqlite3_memory_alarm(0, 0, 0);
+ sqlite3MemoryAlarm(0, 0, 0);
}
overage = sqlite3_memory_used() - n;
if( overage>0 ){
/*
** State information local to the memory allocation subsystem.
*/
-static struct {
+static SQLITE_WSD struct Mem0Global {
+ /* Number of free pages for scratch and page-cache memory */
+ u32 nScratchFree;
+ u32 nPageFree;
+
sqlite3_mutex *mutex; /* Mutex to serialize access */
/*
int alarmBusy;
/*
- ** Pointers to the end of sqlite3Config.pScratch and
- ** sqlite3Config.pPage to a block of memory that records
+ ** Pointers to the end of sqlite3GlobalConfig.pScratch and
+ ** sqlite3GlobalConfig.pPage to a block of memory that records
** which pages are available.
*/
u32 *aScratchFree;
u32 *aPageFree;
+} mem0 = { 62560955 };
- /* Number of free pages for scratch and page-cache memory */
- u32 nScratchFree;
- u32 nPageFree;
-} mem0;
+#define mem0 GLOBAL(struct Mem0Global, mem0)
/*
** Initialize the memory allocation subsystem.
*/
SQLITE_PRIVATE int sqlite3MallocInit(void){
- if( sqlite3Config.m.xMalloc==0 ){
+ if( sqlite3GlobalConfig.m.xMalloc==0 ){
sqlite3MemSetDefault();
}
memset(&mem0, 0, sizeof(mem0));
- if( sqlite3Config.bCoreMutex ){
+ if( sqlite3GlobalConfig.bCoreMutex ){
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
}
- if( sqlite3Config.pScratch && sqlite3Config.szScratch>=100
- && sqlite3Config.nScratch>=0 ){
+ if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
+ && sqlite3GlobalConfig.nScratch>=0 ){
int i;
- sqlite3Config.szScratch -= 4;
- mem0.aScratchFree = (u32*)&((char*)sqlite3Config.pScratch)
- [sqlite3Config.szScratch*sqlite3Config.nScratch];
- for(i=0; i<sqlite3Config.nScratch; i++){ mem0.aScratchFree[i] = i; }
- mem0.nScratchFree = sqlite3Config.nScratch;
+ sqlite3GlobalConfig.szScratch -= 4;
+ mem0.aScratchFree = (u32*)&((char*)sqlite3GlobalConfig.pScratch)
+ [sqlite3GlobalConfig.szScratch*sqlite3GlobalConfig.nScratch];
+ for(i=0; i<sqlite3GlobalConfig.nScratch; i++){ mem0.aScratchFree[i] = i; }
+ mem0.nScratchFree = sqlite3GlobalConfig.nScratch;
}else{
- sqlite3Config.pScratch = 0;
- sqlite3Config.szScratch = 0;
+ sqlite3GlobalConfig.pScratch = 0;
+ sqlite3GlobalConfig.szScratch = 0;
}
- if( sqlite3Config.pPage && sqlite3Config.szPage>=512
- && sqlite3Config.nPage>=1 ){
+ if( sqlite3GlobalConfig.pPage && sqlite3GlobalConfig.szPage>=512
+ && sqlite3GlobalConfig.nPage>=1 ){
int i;
int overhead;
- int sz = sqlite3Config.szPage;
- int n = sqlite3Config.nPage;
+ int sz = sqlite3GlobalConfig.szPage;
+ int n = sqlite3GlobalConfig.nPage;
overhead = (4*n + sz - 1)/sz;
- sqlite3Config.nPage -= overhead;
- mem0.aPageFree = (u32*)&((char*)sqlite3Config.pPage)
- [sqlite3Config.szPage*sqlite3Config.nPage];
- for(i=0; i<sqlite3Config.nPage; i++){ mem0.aPageFree[i] = i; }
- mem0.nPageFree = sqlite3Config.nPage;
+ sqlite3GlobalConfig.nPage -= overhead;
+ mem0.aPageFree = (u32*)&((char*)sqlite3GlobalConfig.pPage)
+ [sqlite3GlobalConfig.szPage*sqlite3GlobalConfig.nPage];
+ for(i=0; i<sqlite3GlobalConfig.nPage; i++){ mem0.aPageFree[i] = i; }
+ mem0.nPageFree = sqlite3GlobalConfig.nPage;
}else{
- sqlite3Config.pPage = 0;
- sqlite3Config.szPage = 0;
+ sqlite3GlobalConfig.pPage = 0;
+ sqlite3GlobalConfig.szPage = 0;
}
- return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
+ return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
}
/*
** Deinitialize the memory allocation subsystem.
*/
SQLITE_PRIVATE void sqlite3MallocEnd(void){
- sqlite3Config.m.xShutdown(sqlite3Config.m.pAppData);
+ sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
memset(&mem0, 0, sizeof(mem0));
}
/*
** Change the alarm callback
*/
-SQLITE_API int sqlite3_memory_alarm(
+SQLITE_PRIVATE int sqlite3MemoryAlarm(
void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
void *pArg,
sqlite3_int64 iThreshold
return SQLITE_OK;
}
+#ifndef SQLITE_OMIT_DEPRECATED
+/*
+** Deprecated external interface. Internal/core SQLite code
+** should call sqlite3MemoryAlarm.
+*/
+SQLITE_API int sqlite3_memory_alarm(
+ void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
+ void *pArg,
+ sqlite3_int64 iThreshold
+){
+ return sqlite3MemoryAlarm(xCallback, pArg, iThreshold);
+}
+#endif
+
/*
** Trigger the alarm
*/
int nFull;
void *p;
assert( sqlite3_mutex_held(mem0.mutex) );
- nFull = sqlite3Config.m.xRoundup(n);
+ nFull = sqlite3GlobalConfig.m.xRoundup(n);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmCallback!=0 ){
int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
sqlite3MallocAlarm(nFull);
}
}
- p = sqlite3Config.m.xMalloc(nFull);
+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
if( p==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nFull);
- p = sqlite3Config.m.xMalloc(nFull);
+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
}
if( p ){
nFull = sqlite3MallocSize(p);
void *p;
if( n<=0 ){
p = 0;
- }else if( sqlite3Config.bMemstat ){
+ }else if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
mallocWithAlarm(n, &p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3Config.m.xMalloc(n);
+ p = sqlite3GlobalConfig.m.xMalloc(n);
}
return p;
}
assert( scratchAllocOut==0 );
#endif
- if( sqlite3Config.szScratch<n ){
+ if( sqlite3GlobalConfig.szScratch<n ){
goto scratch_overflow;
}else{
sqlite3_mutex_enter(mem0.mutex);
}else{
int i;
i = mem0.aScratchFree[--mem0.nScratchFree];
- i *= sqlite3Config.szScratch;
+ i *= sqlite3GlobalConfig.szScratch;
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
sqlite3_mutex_leave(mem0.mutex);
- p = (void*)&((char*)sqlite3Config.pScratch)[i];
+ p = (void*)&((char*)sqlite3GlobalConfig.pScratch)[i];
}
}
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
return p;
scratch_overflow:
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
n = mallocWithAlarm(n, &p);
if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3Config.m.xMalloc(n);
+ p = sqlite3GlobalConfig.m.xMalloc(n);
}
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
scratchAllocOut = p!=0;
scratchAllocOut = 0;
#endif
- if( sqlite3Config.pScratch==0
- || p<sqlite3Config.pScratch
+ if( sqlite3GlobalConfig.pScratch==0
+ || p<sqlite3GlobalConfig.pScratch
|| p>=(void*)mem0.aScratchFree ){
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
}
}else{
int i;
- i = (u8 *)p - (u8 *)sqlite3Config.pScratch;
- i /= sqlite3Config.szScratch;
- assert( i>=0 && i<sqlite3Config.nScratch );
+ i = (u8 *)p - (u8 *)sqlite3GlobalConfig.pScratch;
+ i /= sqlite3GlobalConfig.szScratch;
+ assert( i>=0 && i<sqlite3GlobalConfig.nScratch );
sqlite3_mutex_enter(mem0.mutex);
- assert( mem0.nScratchFree<sqlite3Config.nScratch );
+ assert( mem0.nScratchFree<sqlite3GlobalConfig.nScratch );
mem0.aScratchFree[mem0.nScratchFree++] = i;
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
sqlite3_mutex_leave(mem0.mutex);
assert( (n & (n-1))==0 );
assert( n>=512 && n<=32768 );
- if( sqlite3Config.szPage<n ){
+ if( sqlite3GlobalConfig.szPage<n ){
goto page_overflow;
}else{
sqlite3_mutex_enter(mem0.mutex);
int i;
i = mem0.aPageFree[--mem0.nPageFree];
sqlite3_mutex_leave(mem0.mutex);
- i *= sqlite3Config.szPage;
+ i *= sqlite3GlobalConfig.szPage;
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, n);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
- p = (void*)&((char*)sqlite3Config.pPage)[i];
+ p = (void*)&((char*)sqlite3GlobalConfig.pPage)[i];
}
}
return p;
page_overflow:
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, n);
n = mallocWithAlarm(n, &p);
if( p ) sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, n);
sqlite3_mutex_leave(mem0.mutex);
}else{
- p = sqlite3Config.m.xMalloc(n);
+ p = sqlite3GlobalConfig.m.xMalloc(n);
}
return p;
}
SQLITE_PRIVATE void sqlite3PageFree(void *p){
if( p ){
- if( sqlite3Config.pPage==0
- || p<sqlite3Config.pPage
+ if( sqlite3GlobalConfig.pPage==0
+ || p<sqlite3GlobalConfig.pPage
|| p>=(void*)mem0.aPageFree ){
/* In this case, the page allocation was obtained from a regular
** call to sqlite3_mem_methods.xMalloc() (a page-cache-memory
** "overflow"). Free the block with sqlite3_mem_methods.xFree().
*/
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
}
}else{
- /* The page allocation was allocated from the sqlite3Config.pPage
+ /* The page allocation was allocated from the sqlite3GlobalConfig.pPage
** buffer. In this case all that is add the index of the page in
- ** the sqlite3Config.pPage array to the set of free indexes stored
+ ** the sqlite3GlobalConfig.pPage array to the set of free indexes stored
** in the mem0.aPageFree[] array.
*/
int i;
- i = (u8 *)p - (u8 *)sqlite3Config.pPage;
- i /= sqlite3Config.szPage;
- assert( i>=0 && i<sqlite3Config.nPage );
+ i = (u8 *)p - (u8 *)sqlite3GlobalConfig.pPage;
+ i /= sqlite3GlobalConfig.szPage;
+ assert( i>=0 && i<sqlite3GlobalConfig.nPage );
sqlite3_mutex_enter(mem0.mutex);
- assert( mem0.nPageFree<sqlite3Config.nPage );
+ assert( mem0.nPageFree<sqlite3GlobalConfig.nPage );
mem0.aPageFree[mem0.nPageFree++] = i;
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
sqlite3_mutex_leave(mem0.mutex);
/*
** TRUE if p is a lookaside memory allocation from db
*/
+#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, void *p){
return db && p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
}
+#else
+#define isLookaside(A,B) 0
+#endif
/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
SQLITE_PRIVATE int sqlite3MallocSize(void *p){
- return sqlite3Config.m.xSize(p);
+ return sqlite3GlobalConfig.m.xSize(p);
}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
- return sqlite3Config.m.xSize(p);
+ return sqlite3GlobalConfig.m.xSize(p);
}
}
*/
SQLITE_API void sqlite3_free(void *p){
if( p==0 ) return;
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
- sqlite3Config.m.xFree(p);
+ sqlite3GlobalConfig.m.xFree(p);
}
}
return 0;
}
nOld = sqlite3MallocSize(pOld);
- if( sqlite3Config.bMemstat ){
+ if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, nBytes);
- nNew = sqlite3Config.m.xRoundup(nBytes);
+ nNew = sqlite3GlobalConfig.m.xRoundup(nBytes);
if( nOld==nNew ){
pNew = pOld;
}else{
mem0.alarmThreshold ){
sqlite3MallocAlarm(nNew-nOld);
}
- pNew = sqlite3Config.m.xRealloc(pOld, nNew);
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
if( pNew==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nBytes);
- pNew = sqlite3Config.m.xRealloc(pOld, nNew);
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
}
if( pNew ){
nNew = sqlite3MallocSize(pNew);
}
sqlite3_mutex_leave(mem0.mutex);
}else{
- pNew = sqlite3Config.m.xRealloc(pOld, nBytes);
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nBytes);
}
return pNew;
}
/*
** 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 ){
return (void*)pBuf;
}
}
+#else
+ if( db && db->mallocFailed ){
+ return 0;
+ }
+#endif
p = sqlite3Malloc(n);
if( !p && db ){
db->mallocFailed = 1;
** 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;
/* All threads share a single random number generator.
** This structure is the current state of the generator.
*/
-static struct sqlite3PrngType {
+static SQLITE_WSD struct sqlite3PrngType {
unsigned char isInit; /* True if initialized */
unsigned char i, j; /* State variables */
unsigned char s[256]; /* State variables */
-} sqlite3Prng;
+} sqlite3Prng = { 0, };
/*
** Get a single 8-bit random value from the RC4 PRNG. The Mutex
unsigned char t;
+ /* The "wsdPrng" macro will resolve to the pseudo-random number generator
+ ** state vector. If writable static data is unsupported on the target,
+ ** we have to locate the state vector at run-time. In the more common
+ ** case where writable static data is supported, wsdPrng can refer directly
+ ** to the "sqlite3Prng" state vector declared above.
+ */
+#ifdef SQLITE_OMIT_WSD
+ struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
+# define wsdPrng p[0]
+#else
+# define wsdPrng sqlite3Prng
+#endif
+
+
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device.
*/
- if( !sqlite3Prng.isInit ){
+ if( !wsdPrng.isInit ){
int i;
char k[256];
- sqlite3Prng.j = 0;
- sqlite3Prng.i = 0;
+ wsdPrng.j = 0;
+ wsdPrng.i = 0;
sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
for(i=0; i<256; i++){
- sqlite3Prng.s[i] = i;
+ wsdPrng.s[i] = i;
}
for(i=0; i<256; i++){
- sqlite3Prng.j += sqlite3Prng.s[i] + k[i];
- t = sqlite3Prng.s[sqlite3Prng.j];
- sqlite3Prng.s[sqlite3Prng.j] = sqlite3Prng.s[i];
- sqlite3Prng.s[i] = t;
+ wsdPrng.j += wsdPrng.s[i] + k[i];
+ t = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
+ wsdPrng.s[i] = t;
}
- sqlite3Prng.isInit = 1;
+ wsdPrng.isInit = 1;
}
/* Generate and return single random byte
*/
- sqlite3Prng.i++;
- t = sqlite3Prng.s[sqlite3Prng.i];
- sqlite3Prng.j += t;
- sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j];
- sqlite3Prng.s[sqlite3Prng.j] = t;
- t += sqlite3Prng.s[sqlite3Prng.i];
- return sqlite3Prng.s[t];
+ wsdPrng.i++;
+ t = wsdPrng.s[wsdPrng.i];
+ wsdPrng.j += t;
+ wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = t;
+ t += wsdPrng.s[wsdPrng.i];
+ return wsdPrng.s[t];
}
/*
*/
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);
#ifndef SQLITE_OMIT_BUILTIN_TEST
/*
** For testing purposes, we sometimes want to preserve the state of
-** PRNG and restore the PRNG to its saved state at a later time.
+** PRNG and restore the PRNG to its saved state at a later time, or
+** to reset the PRNG to its initial state. These routines accomplish
+** those tasks.
+**
** The sqlite3_test_control() interface calls these routines to
** control the PRNG.
*/
-static struct sqlite3PrngType sqlite3SavedPrng;
+static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng = { 0, };
SQLITE_PRIVATE void sqlite3PrngSaveState(void){
- memcpy(&sqlite3SavedPrng, &sqlite3Prng, sizeof(sqlite3Prng));
+ memcpy(
+ &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
+ &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
+ sizeof(sqlite3Prng)
+ );
}
SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
- memcpy(&sqlite3Prng, &sqlite3SavedPrng, sizeof(sqlite3Prng));
+ memcpy(
+ &GLOBAL(struct sqlite3PrngType, sqlite3Prng),
+ &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
+ sizeof(sqlite3Prng)
+ );
}
SQLITE_PRIVATE void sqlite3PrngResetState(void){
- sqlite3Prng.isInit = 0;
+ GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
}
#endif /* SQLITE_OMIT_BUILTIN_TEST */
** 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 */
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
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 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 */
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
/*
** 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
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*);
return SQLITE_NOMEM;
}
zIn = (u8*)pMem->z;
- zTerm = &zIn[pMem->n];
+ zTerm = &zIn[pMem->n&~1];
while( zIn<zTerm ){
temp = *zIn;
*zIn = *(zIn+1);
** A single byte is required for the output string
** nul-terminator.
*/
+ pMem->n &= ~1;
len = pMem->n * 2 + 1;
}else{
/* When converting from UTF-8 to UTF-16 the maximum growth is caused
** 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;
pH->count = 0;
}
-#if 0 /* NOT USED */
-/*
-** Hash and comparison functions when the mode is SQLITE_HASH_INT
-*/
-static int intHash(const void *pKey, int nKey){
- return nKey ^ (nKey<<8) ^ (nKey>>8);
-}
-static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- return n2 - n1;
-}
-#endif
-
-#if 0 /* NOT USED */
-/*
-** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
-*/
-static int ptrHash(const void *pKey, int nKey){
- uptr x = Addr(pKey);
- return x ^ (x<<8) ^ (x>>8);
-}
-static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( pKey1==pKey2 ) return 0;
- if( pKey1<pKey2 ) return -1;
- return 1;
-}
-#endif
-
/*
** Hash and comparison functions when the mode is SQLITE_HASH_STRING
*/
return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
}
-/*
-** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
-*/
-static int binHash(const void *pKey, int nKey){
- int h = 0;
- const char *z = (const char *)pKey;
- while( nKey-- > 0 ){
- h = (h<<3) ^ h ^ *(z++);
- }
- return h & 0x7fffffff;
-}
-static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
- if( n1!=n2 ) return 1;
- return memcmp(pKey1,pKey2,n1);
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** The C syntax in this function definition may be unfamilar to some
-** programmers, so we provide the following additional explanation:
-**
-** The name of the function is "hashFunction". The function takes a
-** single parameter "keyClass". The return value of hashFunction()
-** is a pointer to another function. Specifically, the return value
-** of hashFunction() is a pointer to a function that takes two parameters
-** with types "const void*" and "int" and returns an "int".
-*/
-static int (*hashFunction(int keyClass))(const void*,int){
-#if 0 /* HASH_INT and HASH_POINTER are never used */
- switch( keyClass ){
- case SQLITE_HASH_INT: return &intHash;
- case SQLITE_HASH_POINTER: return &ptrHash;
- case SQLITE_HASH_STRING: return &strHash;
- case SQLITE_HASH_BINARY: return &binHash;;
- default: break;
- }
- return 0;
-#else
- if( keyClass==SQLITE_HASH_STRING ){
- return &strHash;
- }else{
- assert( keyClass==SQLITE_HASH_BINARY );
- return &binHash;
- }
-#endif
-}
-
-/*
-** Return a pointer to the appropriate hash function given the key class.
-**
-** For help in interpreted the obscure C code in the function definition,
-** see the header comment on the previous function.
-*/
-static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
-#if 0 /* HASH_INT and HASH_POINTER are never used */
- switch( keyClass ){
- case SQLITE_HASH_INT: return &intCompare;
- case SQLITE_HASH_POINTER: return &ptrCompare;
- case SQLITE_HASH_STRING: return &strCompare;
- case SQLITE_HASH_BINARY: return &binCompare;
- default: break;
- }
- return 0;
-#else
- if( keyClass==SQLITE_HASH_STRING ){
- return &strCompare;
- }else{
- assert( keyClass==SQLITE_HASH_BINARY );
- return &binCompare;
- }
-#endif
-}
/* Link an element into the hash table
*/
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 ){
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);
}
){
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;
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;
}
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);
/* 122 */ "VUpdate",
/* 123 */ "IfZero",
/* 124 */ "VCreate",
- /* 125 */ "Real",
- /* 126 */ "Found",
+ /* 125 */ "Found",
+ /* 126 */ "Real",
/* 127 */ "IfPos",
/* 128 */ "NullRow",
/* 129 */ "Jump",
/* 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];
}
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;
}
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
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;
}
}
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;
}
/*
#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).
+**
+** 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
/*
** These #defines should enable >2GB file support on Posix if the
#include <sys/time.h>
#include <errno.h>
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_ENABLE_LOCKING_STYLE
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/mount.h>
#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 */
/*
** 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));
}
#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;
}
*/
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 */
/*
}
}
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#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.
const char *filePath,
int fd
){
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_ENABLE_LOCKING_STYLE
struct Mapping {
const char *zFilesystem;
int eLockingStyle;
}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;
}
|| (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);
/* something went terribly awry, unless during file system support
* introspection, in which it actually means what it says */
#endif
+#ifdef ENOTSUP
case ENOTSUP:
/* invalid fd, unless during file system support introspection, in which
* it actually means what it says */
+#endif
case EIO:
case EBADF:
case EINVAL:
pLock->locktype = NO_LOCK;
}else{
int tErrno = errno;
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){
pFile->lastErrno = tErrno;
}
}
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_ENABLE_LOCKING_STYLE
#pragma mark AFP Support
/*
static int flockLock(sqlite3_file *id, int locktype) {
int rc = SQLITE_OK;
- int lrc;
unixFile *pFile = (unixFile*)id;
assert( pFile );
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)
,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
break;
}
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_ENABLE_LOCKING_STYLE
case LOCKING_STYLE_AFP: {
/* AFP locking uses the file path so it needs to be included in
** the afpLockingContext.
int rc = SQLITE_OK;
SimulateIOError(return SQLITE_IOERR_DELETE);
unlink(zPath);
+#ifndef SQLITE_DISABLE_DIRSYNC
if( dirSync ){
int fd;
rc = openDirectory(zPath, &fd);
close(fd);
}
}
+#endif
return rc;
}
memcpy(zBuf, &t, sizeof(t));
pid = getpid();
memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
+ assert( sizeof(t)+sizeof(pid)<=nBuf );
+ nBuf = sizeof(t) + sizeof(pid);
}else{
- read(fd, zBuf, nBuf);
+ nBuf = read(fd, zBuf, nBuf);
close(fd);
}
}
#endif
- return SQLITE_OK;
+ return nBuf;
}
}
static sqlite3_vfs unixVfs = UNIXVFS("unix", 0);
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
-#if 0
+#if SQLITE_ENABLE_LOCKING_STYLE
int i;
static sqlite3_vfs aVfs[] = {
UNIXVFS("unix-posix", LOCKING_STYLE_POSIX),
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
sqlite3_vfs_register(&aVfs[i], 0);
}
-#endif
#endif
sqlite3_vfs_register(&unixVfs, 1);
return SQLITE_OK;
/************** End of os_common.h *******************************************/
/************** Continuing where we left off in os_win.c *********************/
+/*
+** Some microsoft compilers lack this definition.
+*/
+#ifndef INVALID_FILE_ATTRIBUTES
+# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+#endif
+
/*
** Determine if we are dealing with WindowsCE - which has a much
** reduced API.
*/
-#if defined(SQLITE_OS_WINCE)
+#if SQLITE_OS_WINCE
# define AreFileApisANSI() 1
#endif
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);
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;
}
** 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
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;
}
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;
}
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;
}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];
}else{
return SQLITE_NOMEM;
}
+#endif
}
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
zTempPath[i] = 0;
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 */
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,
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,
dwFlagsAndAttributes,
NULL
);
+#endif
}
if( h==INVALID_HANDLE_VALUE ){
free(zConverted);
int syncDir /* Not used on win32 */
){
int cnt = 0;
- int rc;
+ DWORD rc;
DWORD error;
void *zConverted = convertUtf8Filename(zFilename);
if( zConverted==0 ){
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;
}
}
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 ){
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;
free(zConverted);
zOut = mbcsToUtf8(zTemp);
free(zTemp);
+#endif
}
if( zOut ){
sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut);
}
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;
** 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.
**
/*
** 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;
}
p->nSet++;
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);
sqlite3BitvecClear(p->u.apSub[bin], i);
}
}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);
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
if( p==0 ) return;
if( p->iDivisor ){
- int i;
+ unsigned int i;
for(i=0; i<BITVEC_NPTR; i++){
sqlite3BitvecDestroy(p->u.apSub[i]);
}
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 */
/**********************************************************************
/*
** Global data for the page cache.
*/
-static struct PCacheGlobal {
+static SQLITE_WSD struct PCacheGlobal {
int isInit; /* True when initialized */
sqlite3_mutex *mutex; /* static mutex MUTEX_STATIC_LRU */
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
** 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.mutex)
-#define pcacheExitMutex() sqlite3_mutex_leave(pcache.mutex)
-#define pcacheMutexHeld() sqlite3_mutex_held(pcache.mutex)
+#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
** Remove a page from the global LRU list
*/
static void pcacheRemoveFromLruList(PgHdr *pPage){
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
assert( (pPage->flags&PGHDR_DIRTY)==0 );
if( pPage->pCache->bPurgeable==0 ) return;
if( pPage->pNextLru ){
- assert( pcache.pLruTail!=pPage );
+ assert( pcache_g.pLruTail!=pPage );
pPage->pNextLru->pPrevLru = pPage->pPrevLru;
}else{
- assert( pcache.pLruTail==pPage );
- pcache.pLruTail = pPage->pPrevLru;
+ assert( pcache_g.pLruTail==pPage );
+ pcache_g.pLruTail = pPage->pPrevLru;
}
if( pPage->pPrevLru ){
- assert( pcache.pLruHead!=pPage );
+ assert( pcache_g.pLruHead!=pPage );
pPage->pPrevLru->pNextLru = pPage->pNextLru;
}else{
- assert( pcache.pLruHead==pPage );
- pcache.pLruHead = pPage->pNextLru;
+ assert( pcache_g.pLruHead==pPage );
+ pcache_g.pLruHead = pPage->pNextLru;
}
}
** 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.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
assert( (pPage->flags&PGHDR_DIRTY)==0 );
if( pPage->pCache->bPurgeable==0 ) return;
- if( pcache.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
+ 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.pLruHead );
+ assert( pcache_g.pLruHead );
pPage->pNextLru = 0;
- pPage->pPrevLru = pcache.pLruTail;
- pcache.pLruTail->pNextLru = pPage;
- pcache.pLruTail = pPage;
+ 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.pLruHead ){
- pcache.pLruHead->pPrevLru = pPage;
+ if( pcache_g.pLruHead ){
+ pcache_g.pLruHead->pPrevLru = pPage;
}
- pPage->pNextLru = pcache.pLruHead;
- pcache.pLruHead = pPage;
+ pPage->pNextLru = pcache_g.pLruHead;
+ pcache_g.pLruHead = pPage;
pPage->pPrevLru = 0;
- if( pcache.pLruTail==0 ){
- pcache.pLruTail = pPage;
+ if( pcache_g.pLruTail==0 ){
+ pcache_g.pLruTail = pPage;
}
}
}
SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
PgFreeslot *p;
sz &= ~7;
- pcache.szSlot = sz;
- pcache.pStart = pBuf;
- pcache.pFree = 0;
+ pcache_g.szSlot = sz;
+ pcache_g.pStart = pBuf;
+ pcache_g.pFree = 0;
while( n-- ){
p = (PgFreeslot*)pBuf;
- p->pNext = pcache.pFree;
- pcache.pFree = p;
+ p->pNext = pcache_g.pFree;
+ pcache_g.pFree = p;
pBuf = (void*)&((char*)pBuf)[sz];
}
- pcache.pEnd = pBuf;
+ pcache_g.pEnd = pBuf;
}
/*
** 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.
*/
-void *pcacheMalloc(int sz, PCache *pCache){
- assert( sqlite3_mutex_held(pcache.mutex) );
- if( sz<=pcache.szSlot && pcache.pFree ){
- PgFreeslot *p = pcache.pFree;
- pcache.pFree = p->pNext;
+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;
return p;
}
}
-SQLITE_PRIVATE void *sqlite3PageMalloc(sz){
+SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
void *p;
pcacheEnterMutex();
p = pcacheMalloc(sz, 0);
/*
** Release a pager memory allocation
*/
-void pcacheFree(void *p){
- assert( sqlite3_mutex_held(pcache.mutex) );
+static void pcacheFree(void *p){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
if( p==0 ) return;
- if( p>=pcache.pStart && p<pcache.pEnd ){
+ if( p>=pcache_g.pStart && p<pcache_g.pEnd ){
PgFreeslot *pSlot;
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
pSlot = (PgFreeslot*)p;
- pSlot->pNext = pcache.pFree;
- pcache.pFree = pSlot;
+ pSlot->pNext = pcache_g.pFree;
+ pcache_g.pFree = pSlot;
}else{
int iSize = sqlite3MallocSize(p);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
static PgHdr *pcachePageAlloc(PCache *pCache){
PgHdr *p;
int sz = sizeof(*p) + pCache->szPage + pCache->szExtra;
- assert( sqlite3_mutex_held(pcache.mutex) );
+ 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.nCurrentPage++;
+ pcache_g.nCurrentPage++;
}
return p;
}
** Deallocate a page
*/
static void pcachePageFree(PgHdr *p){
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
if( p->pCache->bPurgeable ){
- pcache.nCurrentPage--;
+ pcache_g.nCurrentPage--;
}
- pcacheFree(p->apSave[0]);
- pcacheFree(p->apSave[1]);
pcacheFree(p);
}
** the argument is passed to pcachePageFree().
*/
static int pcachePageSize(PgHdr *p){
- assert( sqlite3_mutex_held(pcache.mutex) );
- assert( !pcache.pStart );
- assert( p->apSave[0]==0 );
- assert( p->apSave[1]==0 );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ assert( !pcache_g.pStart );
assert( p && p->pCache );
return sqlite3MallocSize(p);
}
** A pointer to the recycled page is returned, or NULL if no page is
** eligible for recycling.
*/
-static PgHdr *pcacheRecyclePage(){
+static PgHdr *pcacheRecyclePage(void){
PgHdr *p = 0;
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
- if( (p=pcache.pLruTail) ){
+ if( (p=pcache_g.pLruTail)!=0 ){
assert( (p->flags&PGHDR_DIRTY)==0 );
pcacheRemoveFromLruList(p);
pcacheRemoveFromHash(p);
int szPage = pCache->szPage;
int szExtra = pCache->szExtra;
- assert( pcache.isInit );
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( pcache_g.isInit );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
*ppPage = 0;
- /* If we have reached the limit for pinned/dirty pages, and there is at
- ** least one dirty page, invoke the xStress callback to cause a page to
- ** become clean.
+ /* 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.nMaxPage+pCache->nMin-pcache.nMinPage)
+ && (pCache->nPinned>=(pcache_g.nMaxPage+pCache->nMin-pcache_g.nMinPage)
+ || pCache->nPinned>=pCache->nMax)
){
PgHdr *pPg;
assert(pCache->pDirtyTail);
}
}
- /* If the global page limit has been reached, try to recycle a page. */
- if( pCache->bPurgeable && pcache.nCurrentPage>=pcache.nMaxPage ){
+ /* 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();
}
** functions are threadsafe.
*/
SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
- assert( pcache.isInit==0 );
- memset(&pcache, 0, sizeof(pcache));
- if( sqlite3Config.bCoreMutex ){
+ 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.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
+ pcache_g.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
}
- pcache.isInit = 1;
+ pcache_g.isInit = 1;
return SQLITE_OK;
}
SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
- memset(&pcache, 0, sizeof(pcache));
+ memset(&pcache_g, 0, sizeof(pcache));
}
/*
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.isInit );
+ 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;
pcacheEnterMutex();
if( bPurgeable ){
- pcache.nMaxPage += p->nMax;
- pcache.nMinPage += p->nMin;
+ pcache_g.nMaxPage += p->nMax;
+ pcache_g.nMinPage += p->nMin;
}
pcacheExitMutex();
int rc = SQLITE_OK;
PgHdr *pPage = 0;
- assert( pcache.isInit );
+ assert( pcache_g.isInit );
assert( pCache!=0 );
assert( pgno>0 );
expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
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.nCurrentPage>pcache.nMaxPage ){
+ if( pcache_g.nCurrentPage>pcache_g.nMaxPage ){
pcacheRemoveFromList(&pCache->pClean, p);
pcacheRemoveFromHash(p);
pcachePageFree(p);
p->flags |= PGHDR_DIRTY;
}
-void pcacheMakeClean(PgHdr *p){
+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);
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);
pcacheRemoveFromHash(p);
p->pgno = newPgno;
if( newPgno==0 ){
- p->flags |= PGHDR_REUSE_UNLIKELY;
- 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;
}
pcacheAddToHash(p);
pcacheExitMutex();
/*
** Remove all content from a page cache
*/
-void pcacheClear(PCache *pCache){
+static void pcacheClear(PCache *pCache){
PgHdr *p, *pNext;
- assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
for(p=pCache->pClean; p; p=pNext){
pNext = p->pNext;
pcacheRemoveFromLruList(p);
** 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(){
+static void pcacheEnforceMaxPage(void){
PgHdr *p;
- assert( sqlite3_mutex_held(pcache.mutex) );
- while( pcache.nCurrentPage>pcache.nMaxPage && (p = pcacheRecyclePage()) ){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ while( pcache_g.nCurrentPage>pcache_g.nMaxPage
+ && (p = pcacheRecyclePage())!=0 ){
pcachePageFree(p);
}
}
/* Free all the pages used by this pager and remove them from the LRU list. */
pcacheClear(pCache);
if( pCache->bPurgeable ){
- pcache.nMaxPage -= pCache->nMax;
- pcache.nMinPage -= pCache->nMin;
+ 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;
- 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;
- }
- }
- pcacheExitMutex();
-}
-
-/*
-** Rollback a change previously preserved.
-*/
-SQLITE_PRIVATE void sqlite3PcacheRollback(PCache *pCache, int idJournal){
- PgHdr *p;
- int sz;
- 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;
- }
- }
- pcacheExitMutex();
-}
+#ifndef NDEBUG
/*
** Assert flags settings on all pages. Debugging only.
*/
assert( (p->flags&falseMask)==0 );
}
}
+#endif
/*
** Discard the contents of the cache.
return pCache->nRef;
}
+SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
+ return p->nRef;
+}
+
/*
** Return the total number of pages in the cache.
*/
/*
** Set flags on all pages in the page cache
*/
-SQLITE_PRIVATE void sqlite3PcacheSetFlags(PCache *pCache, int andMask, int orMask){
+SQLITE_PRIVATE void sqlite3PcacheClearFlags(PCache *pCache, int mask){
PgHdr *p;
- assert( (orMask&PGHDR_NEED_SYNC)==0 );
-
/* 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 = (p->flags&andMask)|orMask;
+ p->flags &= mask;
}
for(p=pCache->pClean; p; p=p->pNext){
- p->flags = (p->flags&andMask)|orMask;
+ p->flags &= mask;
}
- if( 0==(andMask&PGHDR_NEED_SYNC) ){
+ if( 0==(mask&PGHDR_NEED_SYNC) ){
pCache->pSynced = pCache->pDirtyTail;
assert( !pCache->pSynced || (pCache->pSynced->flags&PGHDR_NEED_SYNC)==0 );
}
}
if( pCache->bPurgeable ){
pcacheEnterMutex();
- pcache.nMaxPage -= pCache->nMax;
- pcache.nMaxPage += mxPage;
+ pcache_g.nMaxPage -= pCache->nMax;
+ pcache_g.nMaxPage += mxPage;
pcacheEnforceMaxPage();
pcacheExitMutex();
}
*/
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
int nFree = 0;
- if( pcache.pStart==0 ){
+ if( pcache_g.pStart==0 ){
PgHdr *p;
pcacheEnterMutex();
while( (nReq<0 || nFree<nReq) && (p=pcacheRecyclePage()) ){
){
PgHdr *p;
int nRecyclable = 0;
- for(p=pcache.pLruHead; p; p=p->pNextLru){
+ for(p=pcache_g.pLruHead; p; p=p->pNextLru){
nRecyclable++;
}
- *pnCurrent = pcache.nCurrentPage;
- *pnMax = pcache.nMaxPage;
- *pnMin = pcache.nMinPage;
+ *pnCurrent = pcache_g.nCurrentPage;
+ *pnMax = pcache_g.nMaxPage;
+ *pnMin = pcache_g.nMinPage;
*pnRecyclable = nRecyclable;
}
#endif
-
/************** End of pcache.c **********************************************/
/************** Begin file pager.c *******************************************/
/*
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 */
#endif
- void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */
- void (*xReiniter)(DbPage*,int); /* Call this routine when reloading pages */
+ void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
#ifdef SQLITE_HAS_CODEC
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
void *pCodecArg; /* First argument to xCodec() */
*/
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);
}
/*
#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) );
}
*/
static int zeroJournalHdr(Pager *pPager, int doTruncate){
int rc = SQLITE_OK;
- static const char zeroHdr[28];
+ static const char zeroHdr[28] = {0};
if( pPager->journalOff ){
i64 iLimit = pPager->journalSizeLimit;
** 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);
** 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;
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);
*/
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))
+ 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;
- }
+ /* 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;
}
}
static int pager_end_transaction(Pager *pPager, int hasMaster){
int rc = SQLITE_OK;
int rc2 = SQLITE_OK;
- assert( !MEMDB );
if( pPager->state<PAGER_RESERVED ){
return SQLITE_OK;
}
pPager->stmtOpen = 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);
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 ){
#ifdef SQLITE_CHECK_PAGES
sqlite3PcacheIterate(pPager->pPCache, pager_set_pagehash);
#endif
- sqlite3PcacheSetFlags(pPager->pPCache,
- ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
+ sqlite3PcacheClearFlags(pPager->pPCache,
+ PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC
);
pPager->dirtyCache = 0;
pPager->nRec = 0;
pPager->setMaster = 0;
pPager->needSync = 0;
/* lruListSetFirstSynced(pPager); */
- pPager->dbSize = -1;
+ if( !MEMDB ){
+ pPager->dbSize = -1;
+ }
pPager->dbModified = 0;
return (rc==SQLITE_OK?rc2:rc);
pData = pPg->pData;
memcpy(pData, aData, pPager->pageSize);
if( pPager->xReiniter ){
- pPager->xReiniter(pPg, pPager->pageSize);
+ pPager->xReiniter(pPg);
}
if( isMainJrnl ) makeClean(pPg);
#ifdef SQLITE_CHECK_PAGES
pPager->journalOff = szJ;
break;
}else{
+ /* If we are unable to rollback, then the database is probably
+ ** going to end up being corrupt. It is corrupt to us, anyhow.
+ ** Perhaps the next process to come along can fix it....
+ */
+ rc = SQLITE_CORRUPT_BKPT;
goto end_playback;
}
}
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.
*/
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() */
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;
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 ){
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;
}
}
}
- }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;
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);
}
/* pPager->journalOpen = 0; */
- pPager->useJournal = useJournal && !memDb;
+ pPager->useJournal = useJournal;
pPager->noReadlock = noReadlock && readOnly;
/* pPager->stmtOpen = 0; */
/* pPager->stmtInUse = 0; */
/* 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; */
/* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */
** an opportunity to restore the EXTRA section to agree with the restored
** page data.
*/
-SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){
+SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*)){
pPager->xReiniter = xReinit;
}
** value before returning.
*/
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){
- int rc = SQLITE_OK;
- u16 pageSize = *pPageSize;
- assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
- if( pageSize && pageSize!=pPager->pageSize
- && (pPager->memDb==0 || pPager->dbSize==0)
- && sqlite3PcacheRefCount(pPager->pPCache)==0
- ){
- char *pNew = (char *)sqlite3PageMalloc(pageSize);
- if( !pNew ){
- rc = SQLITE_NOMEM;
- }else{
- pager_reset(pPager);
- pPager->pageSize = pageSize;
- if( !pPager->memDb ) setSectorSize(pPager);
- sqlite3PageFree(pPager->pTmpSpace);
- pPager->pTmpSpace = pNew;
- sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
+ int rc = pPager->errCode;
+ if( rc==SQLITE_OK ){
+ u16 pageSize = *pPageSize;
+ assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
+ if( pageSize && pageSize!=pPager->pageSize
+ && (pPager->memDb==0 || pPager->dbSize==0)
+ && sqlite3PcacheRefCount(pPager->pPCache)==0
+ ){
+ char *pNew = (char *)sqlite3PageMalloc(pageSize);
+ if( !pNew ){
+ rc = SQLITE_NOMEM;
+ }else{
+ pager_reset(pPager);
+ pPager->pageSize = pageSize;
+ if( !pPager->memDb ) setSectorSize(pPager);
+ sqlite3PageFree(pPager->pTmpSpace);
+ pPager->pTmpSpace = pNew;
+ sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
+ }
}
+ *pPageSize = pPager->pageSize;
}
- *pPageSize = pPager->pageSize;
return rc;
}
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);
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->dbSize<0 );
if( pPager->state>=locktype ){
rc = SQLITE_OK;
*/
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);
- }
+ 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);
}
}
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));
** (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 );
/* Erase the needSync flag from every page.
*/
- sqlite3PcacheSetFlags(pPager->pPCache, ~PGHDR_NEED_SYNC, 0);
- /* lruListSetFirstSynced(pPager); */
+ sqlite3PcacheClearFlags(pPager->pPCache, PGHDR_NEED_SYNC);
}
#ifndef NDEBUG
*/
else{
sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_NEED_SYNC);
- /* assert( pPager->lru.pFirstSynced==pPager->lru.pFirst ); */
}
#endif
#ifdef SQLITE_CHECK_PAGES
pList->pageHash = pager_pagehash(pList);
#endif
- /* makeClean(pList); */
pList = pList->pDirty;
}
- /* sqlite3PcacheCleanAll(pPager->pPCache); */
return SQLITE_OK;
}
if( pPg->flags&PGHDR_NEED_SYNC ){
rc = syncJournal(pPager);
if( rc==SQLITE_OK && pPager->fullSync &&
+ !(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) &&
!(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
){
pPager->nRec = 0;
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->state<EXCLUSIVE_LOCK ){
+ rc = sqlite3OsLock(pPager->fd, 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->state<EXCLUSIVE_LOCK ){
- rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
- if( rc!=SQLITE_OK ){
- rc = pager_error(pPager, rc);
- goto failed;
- }
- pPager->state = PAGER_EXCLUSIVE;
- }
- /* Open the journal for read/write access. This is because in
- ** exclusive-access mode the file descriptor will be kept open and
- ** possibly used for a transaction later on. On some systems, the
- ** OsTruncate() call used in exclusive-access mode also requires
- ** a read/write file handle.
- */
- if( !isErrorReset && pPager->journalOpen==0 ){
- int res;
- rc = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS,&res);
- if( rc==SQLITE_OK ){
- if( res ){
- int fout = 0;
- int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
- assert( !pPager->tempFile );
- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
- assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
- if( 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));
+ 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 );
** called again with noContent==0, that means that the content is needed
** and the disk read should occur at that point.
*/
-static int pagerAcquire(
+SQLITE_PRIVATE int sqlite3PagerAcquire(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
DbPage **ppPage, /* Write a pointer to the page here */
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
return SQLITE_OK;
}
-SQLITE_PRIVATE int sqlite3PagerAcquire(
- Pager *pPager, /* The pager open on the database file */
- Pgno pgno, /* Page number to fetch */
- DbPage **ppPage, /* Write a pointer to the page here */
- int noContent /* Do not bother reading content from disk if true */
-){
- int rc;
- rc = pagerAcquire(pPager, pgno, ppPage, noContent);
- return rc;
-}
-
-
/*
** Acquire a page if it is already in the in-memory cache. Do
** not read the page from disk. Return a pointer to the page,
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 );
}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;
assert( pPager->state!=PAGER_UNLOCK );
if( pPager->state==PAGER_SHARED ){
assert( pPager->pInJournal==0 );
+ assert( !MEMDB );
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);
+ 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
** 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( !(pPg->flags&PGHDR_IN_JOURNAL) && pPager->journalOpen ){
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;
- }
+ 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 ){
&& !pageInStatement(pPg)
&& (int)pPg->pgno<=pPager->stmtSize
){
+ i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
+ char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
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);
+ 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);
}
}
assert( pPager->state>=PAGER_SHARED );
if( pPager->dbSize<(int)pPg->pgno ){
pPager->dbSize = pPg->pgno;
- if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
+ if( pPager->dbSize==PENDING_BYTE/pPager->pageSize ){
pPager->dbSize++;
}
}
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 */
/* 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;
** before any of them can be written out to the database file.
*/
if( needSync ){
+ assert( !MEMDB && pPager->noSync==0 );
for(ii=0; ii<nPage && needSync; ii++){
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
if( pPage ) pPage->flags |= PGHDR_NEED_SYNC;
/*
** 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
Pager *pPager = pPg->pPager;
int rc;
- if( MEMDB || pPg->pgno>pPager->origDbSize ){
+ if( pPg->pgno>pPager->origDbSize ){
return SQLITE_OK;
}
if( pPager->pAlwaysRollback==0 ){
){
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 the optimization can be used, then the journal file will never
** be created for this transaction.
*/
+ int useAtomicWrite;
pPg = sqlite3PcacheDirtyList(pPager->pPCache);
- int useAtomicWrite = (
+ useAtomicWrite = (
!zMaster &&
pPager->journalOpen &&
pPager->journalOff==jrnlBufferSize(pPager) &&
return SQLITE_OK;
}
PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
- if( MEMDB ){
- sqlite3PcacheCommit(pPager->pPCache, 0);
- sqlite3PcacheCleanAll(pPager->pPCache);
- sqlite3PcacheSetFlags(pPager->pPCache,
- ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
- );
- 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;
}
SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
int rc = SQLITE_OK;
PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
- if( MEMDB ){
- sqlite3PcacheRollback(pPager->pPCache, 1);
- sqlite3PcacheRollback(pPager->pPCache, 0);
- sqlite3PcacheCleanAll(pPager->pPCache);
- sqlite3PcacheSetFlags(pPager->pPCache,
- ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
- );
- 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 ){
rc = pager_playback(pPager, 0);
}
- pPager->dbSize = -1;
+ if( !MEMDB ){
+ pPager->dbSize = -1;
+ }
/* If an error occurs during a ROLLBACK, we can no longer trust the pager
** cache. So call pager_error() on the way out to make any error
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.
assert( pPager->state>=PAGER_SHARED );
assert( pPager->dbSize>=0 );
PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager));
- if( MEMDB ){
- pPager->stmtInUse = 1;
- pPager->stmtSize = pPager->dbSize;
- return SQLITE_OK;
- }
if( !pPager->journalOpen ){
pPager->stmtAutoopen = 1;
return SQLITE_OK;
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;
SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager *pPager){
if( pPager->stmtInUse ){
PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
- if( !MEMDB ){
- /* sqlite3OsTruncate(pPager->stfd, 0); */
- 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;
int rc;
if( pPager->stmtInUse ){
PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
- if( MEMDB ){
- sqlite3PcacheRollback(pPager->pPCache, 1);
- 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;
**
** There must be no references to the page previously located at
** pgno (which we call pPgOld) though that page is allowed to be
-** in cache. If the page previous located at pgno is not already
+** in cache. If the page previously located at pgno is not already
** in the rollback journal, it is not put there by by this routine.
**
** References to the page pPg remain valid. Updating any
return rc;
}
pPager->needSync = 1;
+ assert( pPager->noSync==0 && !MEMDB );
pPgHdr->flags |= PGHDR_NEED_SYNC;
pPgHdr->flags |= PGHDR_IN_JOURNAL;
makeDirty(pPgHdr);
** 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;
}
}
/*
-** 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;
}
*/
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 */
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 */
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 */
};
/*
u16 nSize; /* Size of the cell content on the main b-tree page */
};
+/*
+** 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.
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 */
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] */
};
/*
** 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 ********************************************/
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.
pLater->locked = 1;
}
}
-#endif /* SQLITE_MUTEX_NOOP */
}
/*
# define TRACE(X)
#endif
+/*
+** Sometimes we need a small amount of code such as a variable initialization
+** to setup for a later assert() statement. We do not want this code to
+** appear when assert() is disabled. The following macro is therefore
+** used to contain that setup code. The "VVA" acronym stands for
+** "Verification, Validation, and Accreditation". In other words, the
+** code within VVA_ONLY() will only run during verification processes.
+*/
+#ifndef NDEBUG
+# define VVA_ONLY(X) X
+#else
+# define VVA_ONLY(X)
+#endif
+
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
-** A flag to indicate whether or not shared cache is enabled. Also,
-** a list of BtShared objects that are eligible for participation
-** in shared cache. The variables have file scope during normal builds,
-** but the test harness needs to access these variables so we make them
-** global for test builds.
+** A list of BtShared objects that are eligible for participation
+** in shared cache. This variable has file scope during normal builds,
+** but the test harness needs to access it so we make it global for
+** test builds.
*/
#ifdef SQLITE_TEST
-SQLITE_PRIVATE BtShared *sqlite3SharedCacheList = 0;
-SQLITE_PRIVATE int sqlite3SharedCacheEnabled = 0;
+SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
#else
-static BtShared *sqlite3SharedCacheList = 0;
-static int sqlite3SharedCacheEnabled = 0;
+static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
#endif
#endif /* SQLITE_OMIT_SHARED_CACHE */
** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2().
*/
SQLITE_API int sqlite3_enable_shared_cache(int enable){
- sqlite3SharedCacheEnabled = enable;
+ sqlite3GlobalConfig.sharedCacheEnabled = enable;
return SQLITE_OK;
}
#endif
** 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);
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;
}
/*
** 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;
/*
** 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
** 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 */
u8 *pAddr; /* The i-th cell pointer */
pAddr = &data[cellOffset + i*2];
pc = get2byte(pAddr);
- assert( pc<pPage->pBt->usableSize );
+ if (pc >= pPage->pBt->usableSize) {
+ return SQLITE_CORRUPT_BKPT;
+ }
size = cellSizePtr(pPage, &temp[pc]);
cbrk -= size;
+ if ((cbrk < cellOffset+2*nCell) || (cbrk+size>pPage->pBt->usableSize)) {
+ return SQLITE_CORRUPT_BKPT;
+ }
memcpy(&data[cbrk], &temp[pc], size);
put2byte(pAddr, cbrk);
}
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;
}
/*
/*
** 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!=pParent && (pPage->pParent!=0 || pPage->isInit) ){
- /* The parent page should never change unless the file is corrupt */
- return SQLITE_CORRUPT_BKPT;
- }
- if( pPage->isInit ) return SQLITE_OK;
- if( pPage->pParent==0 && pParent!=0 ){
- pPage->pParent = pParent;
- sqlite3PagerRef(pParent->pDbPage);
- }
- hdr = pPage->hdrOffset;
- data = pPage->aData;
- if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
- assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
- pPage->maskPage = pBt->pageSize - 1;
- pPage->nOverflow = 0;
- pPage->idxShift = 0;
- usableSize = pBt->usableSize;
- pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
- top = get2byte(&data[hdr+5]);
- pPage->nCell = get2byte(&data[hdr+3]);
- if( pPage->nCell>MX_CELL(pBt) ){
- /* To many cells for a single page. The page must be corrupt */
- return SQLITE_CORRUPT_BKPT;
- }
- if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){
- /* All pages must have at least one cell, except for root pages */
- return SQLITE_CORRUPT_BKPT;
- }
- /* Compute the total free space on the page */
- pc = get2byte(&data[hdr+1]);
- nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
- while( pc>0 ){
- int next, size;
- if( pc>usableSize-4 ){
- /* Free block is off the page */
- return SQLITE_CORRUPT_BKPT;
+ if( !pPage->isInit ){
+ int pc; /* Address of a freeblock within pPage->aData[] */
+ int hdr; /* Offset to beginning of page header */
+ u8 *data; /* Equal to pPage->aData */
+ BtShared *pBt; /* The main btree structure */
+ int usableSize; /* Amount of usable space on each page */
+ int cellOffset; /* Offset from start of page to first cell pointer */
+ int nFree; /* Number of unused bytes on the page */
+ int top; /* First byte of the cell content area */
+
+ pBt = pPage->pBt;
+
+ hdr = pPage->hdrOffset;
+ data = pPage->aData;
+ if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
+ assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
+ pPage->maskPage = pBt->pageSize - 1;
+ pPage->nOverflow = 0;
+ usableSize = pBt->usableSize;
+ pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
+ top = get2byte(&data[hdr+5]);
+ pPage->nCell = get2byte(&data[hdr+3]);
+ if( pPage->nCell>MX_CELL(pBt) ){
+ /* To many cells for a single page. The page must be corrupt */
+ return SQLITE_CORRUPT_BKPT;
+ }
+
+ /* Compute the total free space on the page */
+ pc = get2byte(&data[hdr+1]);
+ nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
+ while( pc>0 ){
+ int next, size;
+ if( pc>usableSize-4 ){
+ /* Free block is off the page */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ next = get2byte(&data[pc]);
+ size = get2byte(&data[pc+2]);
+ if( next>0 && next<=pc+size+3 ){
+ /* Free blocks must be in accending order */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nFree += size;
+ pc = next;
}
- next = get2byte(&data[pc]);
- size = get2byte(&data[pc+2]);
- if( next>0 && next<=pc+size+3 ){
- /* Free blocks must be in accending order */
+ pPage->nFree = nFree;
+ if( nFree>=usableSize ){
+ /* Free space cannot exceed total page size */
return SQLITE_CORRUPT_BKPT;
}
- nFree += size;
- pc = next;
- }
- pPage->nFree = nFree;
- if( nFree>=usableSize ){
- /* Free space cannot exceed total page size */
- return SQLITE_CORRUPT_BKPT;
- }
#if 0
/* Check that all the offsets in the cell offset array are within range.
}
#endif
- pPage->isInit = 1;
+ pPage->isInit = 1;
+ }
return SQLITE_OK;
}
pPage->nOverflow = 0;
assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
pPage->maskPage = pBt->pageSize - 1;
- pPage->idxShift = 0;
pPage->nCell = 0;
pPage->isInit = 1;
}
+
+/*
+** Convert a DbPage obtained from the pager into a MemPage used by
+** the btree layer.
+*/
+static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
+ MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
+ pPage->aData = sqlite3PagerGetData(pDbPage);
+ pPage->pDbPage = pDbPage;
+ pPage->pBt = pBt;
+ pPage->pgno = pgno;
+ pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
+ return pPage;
+}
+
/*
** Get a page from the pager. Initialize the MemPage.pBt and
** MemPage.aData elements if needed.
int noContent /* Do not load page content if true */
){
int rc;
- MemPage *pPage;
DbPage *pDbPage;
assert( sqlite3_mutex_held(pBt->mutex) );
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
if( rc ) return rc;
- pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage);
- pPage->aData = sqlite3PagerGetData(pDbPage);
- pPage->pDbPage = pDbPage;
- pPage->pBt = pBt;
- pPage->pgno = pgno;
- pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
- *ppPage = pPage;
+ *ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
return SQLITE_OK;
}
+/*
+** Return the size of the database file in pages. Or return -1 if
+** there is any kind of error.
+*/
+static int pagerPagecount(Pager *pPager){
+ int rc;
+ int nPage;
+ rc = sqlite3PagerPagecount(pPager, &nPage);
+ return (rc==SQLITE_OK?nPage:-1);
+}
+
/*
** Get a page from the pager and initialize it. This routine
** is just a convenience wrapper around separate calls to
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) );
if( pgno==0 ){
return SQLITE_CORRUPT_BKPT;
}
- rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
- if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
- rc = sqlite3BtreeInitPage(*ppPage, pParent);
- if( rc!=SQLITE_OK ){
- releasePage(*ppPage);
- *ppPage = 0;
+
+ /* It is often the case that the page we want is already in cache.
+ ** If so, get it directly. This saves us from having to call
+ ** pagerPagecount() to make sure pgno is within limits, which results
+ ** in a measureable performance improvements.
+ */
+ pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
+ if( pDbPage ){
+ /* Page is already in cache */
+ *ppPage = pPage = btreePageFromDbPage(pDbPage, pgno, pBt);
+ rc = SQLITE_OK;
+ }else{
+ /* Page not in cache. Acquire it. */
+ if( pgno>pagerPagecount(pBt->pPager) ){
+ return SQLITE_CORRUPT_BKPT;
}
+ rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0);
+ if( rc ) return rc;
+ pPage = *ppPage;
+ }
+ if( !pPage->isInit ){
+ rc = sqlite3BtreeInitPage(pPage);
+ }
+ if( rc!=SQLITE_OK ){
+ releasePage(pPage);
+ *ppPage = 0;
}
return rc;
}
}
}
-/*
-** 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==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
- if( pPage->pParent ){
- MemPage *pParent = pPage->pParent;
- assert( pParent->pBt==pPage->pBt );
- pPage->pParent = 0;
- releasePage(pParent);
- }
- pPage->isInit = 0;
- }
-}
-
/*
** During a rollback, when the pager reloads information into the cache
** so that the cache is restored to its original state at the start of
** This routine needs to reset the extra data section at the end of the
** page to agree with the restored data.
*/
-static void pageReinit(DbPage *pData, int pageSize){
+static void pageReinit(DbPage *pData){
MemPage *pPage;
- assert( (pageSize & 7)==0 );
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
if( pPage->isInit ){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
pPage->isInit = 0;
- sqlite3BtreeInitPage(pPage, pPage->pParent);
+ if( sqlite3PagerPageRefcount(pData)>0 ){
+ sqlite3BtreeInitPage(pPage);
+ }
}
}
&& (db->flags & SQLITE_Vtab)==0
&& zFilename && zFilename[0]
){
- if( sqlite3SharedCacheEnabled ){
+ if( sqlite3GlobalConfig.sharedCacheEnabled ){
int nFullPathname = pVfs->mxPathname+1;
char *zFullPathname = sqlite3Malloc(nFullPathname);
sqlite3_mutex *mutexShared;
sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(mutexShared);
- for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
+ for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
assert( pBt->nRef>0 );
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
}
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);
sqlite3_mutex *mutexShared;
pBt->nRef = 1;
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
- if( SQLITE_THREADSAFE && sqlite3Config.bCoreMutex ){
+ if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
rc = SQLITE_NOMEM;
}
}
sqlite3_mutex_enter(mutexShared);
- pBt->pNext = sqlite3SharedCacheList;
- sqlite3SharedCacheList = pBt;
+ pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList);
+ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt;
sqlite3_mutex_leave(mutexShared);
}
#endif
sqlite3_mutex_enter(pMaster);
pBt->nRef--;
if( pBt->nRef<=0 ){
- if( sqlite3SharedCacheList==pBt ){
- sqlite3SharedCacheList = pBt->pNext;
+ if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
+ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;
}else{
- pList = sqlite3SharedCacheList;
+ pList = GLOBAL(BtShared*,sqlite3SharedCacheList);
while( ALWAYS(pList) && pList->pNext!=pBt ){
pList=pList->pNext;
}
return rc;
}
-/*
-** Return the size of the database file in pages. Or return -1 if
-** there is any kind of error.
-*/
-static int pagerPagecount(Pager *pPager){
- int rc;
- int nPage;
- rc = sqlite3PagerPagecount(pPager, &nPage);
- return (rc==SQLITE_OK?nPage:-1);
-}
-
-
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
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;
}
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;
}
}
int i;
int nCell;
- sqlite3BtreeInitPage(pPage, 0);
+ sqlite3BtreeInitPage(pPage);
nCell = pPage->nCell;
for(i=0; i<nCell; i++){
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);
return rc;
}
-#endif
+#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */
/*
** This routine does the first phase of a two-phase commit. This routine
BtCursor *p;
sqlite3BtreeEnter(pBtree);
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- clearCursorPosition(p);
+ sqlite3BtreeClearCursor(p);
p->eState = CURSOR_FAULT;
p->skip = errCode;
}
** 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 */
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;
}
return SQLITE_OK;
create_cursor_exception:
- releasePage(pCur->pPage);
+ releasePage(pCur->apPage[0]);
unlockBtreeIfUnused(pBt);
return rc;
}
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{
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); */
** 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);
}
}
** 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);
}
}
#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
/* 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);
}
#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 */
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; /* Btree this cursor belongs to */
assert( pPage );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
+ assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
assert( offset>=0 );
assert( cursorHoldsMutex(pCur) );
}
if( offset+amt > nKey+pCur->info.nData ){
/* Trying to read or write past the end of the data is an error */
- return SQLITE_ERROR;
+ return SQLITE_CORRUPT_BKPT;
}
/* Check if data must be read/written to/from the btree page itself. */
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->idx<pCur->pPage->nCell );
+ assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0);
}
return rc;
rc = restoreCursorPosition(pCur);
if( rc==SQLITE_OK ){
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->pPage!=0 );
- assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
+ assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
+ assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
rc = accessPayload(pCur, offset, amt, pBuf, 1, 0);
}
return rc;
u32 nKey;
int 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->idx<pPage->nCell );
+ pPage = pCur->apPage[pCur->iPage];
+ assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
getCellInfo(pCur);
aPayload = pCur->info.pCell;
aPayload += pCur->info.nHeader;
*/
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->iPage<BTCURSOR_MAX_DEPTH );
+ if( pCur->iPage>=(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 ){
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.
** 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;
}
/*
if( pCur->eState==CURSOR_FAULT ){
return pCur->skip;
}
- clearCursorPosition(pCur);
+ sqlite3BtreeClearCursor(pCur);
}
- pRoot = pCur->pPage;
- if( pRoot && pRoot->pgno==pCur->pgnoRoot ){
- assert( pRoot->isInit );
+
+ 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;
}
- 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 );
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;
}
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
- while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){
- assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
- pgno = get4byte(findCell(pPage, pCur->idx));
+ while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
+ assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
+ pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
rc = moveToChild(pCur, pgno);
}
return rc;
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;
}
- return SQLITE_OK;
+ return rc;
}
/* Move the cursor to the first entry in the table. Return SQLITE_OK
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);
}
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 );
/* 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;
}
}
-
rc = moveToRoot(pCur);
if( rc ){
return rc;
}
- assert( pCur->pPage );
- assert( pCur->pPage->isInit );
+ 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;
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);
if( c==0 ){
pCur->info.nKey = nCellKey;
if( pPage->intKey && !pPage->leaf ){
- lwr = pCur->idx;
+ lwr = idx;
upr = lwr - 1;
break;
}else{
}
}
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 );
chldPg = get4byte(findCell(pPage, lwr));
}
if( chldPg==0 ){
- assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
+ assert( pCur->aiIdx[pCur->iPage]<pCur->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);
*/
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
int rc;
+ int idx;
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
return rc;
}
assert( pRes!=0 );
- pPage = pCur->pPage;
if( CURSOR_INVALID==pCur->eState ){
*pRes = 1;
return SQLITE_OK;
}
pCur->skip = 0;
+ pPage = pCur->apPage[pCur->iPage];
+ idx = ++pCur->aiIdx[pCur->iPage];
assert( pPage->isInit );
- assert( pCur->idx<pPage->nCell );
+ 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;
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);
*/
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int rc;
- Pgno pgno;
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
}
pCur->skip = 0;
- pPage = pCur->pPage;
+ pPage = pCur->apPage[pCur->iPage];
assert( pPage->isInit );
- assert( pCur->idx>=0 );
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{
end_allocate_page:
releasePage(pTrunk);
releasePage(pPrevTrunk);
+ if( rc==SQLITE_OK && sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
+ releasePage(*ppPage);
+ return SQLITE_CORRUPT_BKPT;
+ }
return rc;
}
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);
return SQLITE_OK;
}
-
-/*
-** Change the MemPage.pParent pointer on the page whose number is
-** given in the second argument so that MemPage.pParent holds the
-** pointer in the third argument.
-**
-** If the final argument, updatePtrmap, is non-zero and the database
-** is an auto-vacuum database, then the pointer-map entry for pgno
-** is updated.
-*/
-static int reparentPage(
- BtShared *pBt, /* B-Tree structure */
- Pgno pgno, /* Page number of child being adopted */
- MemPage *pNewParent, /* New parent of pgno */
- int idx, /* Index of child page pgno in pNewParent */
- int updatePtrmap /* If true, update pointer-map for pgno */
-){
- MemPage *pThis;
- DbPage *pDbPage;
-
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( pNewParent!=0 );
- if( pgno==0 ) return SQLITE_OK;
- assert( pBt->pPager!=0 );
- pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
- if( pDbPage ){
- pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage);
- if( pThis->isInit ){
- assert( pThis->aData==sqlite3PagerGetData(pDbPage) );
- if( pThis->pParent!=pNewParent ){
- if( pThis->pParent ) sqlite3PagerUnref(pThis->pParent->pDbPage);
- pThis->pParent = pNewParent;
- sqlite3PagerRef(pNewParent->pDbPage);
- }
- pThis->idxParent = idx;
- }
- sqlite3PagerUnref(pDbPage);
- }
-
- if( ISAUTOVACUUM && updatePtrmap ){
- return ptrmapPut(pBt, pgno, PTRMAP_BTREE, pNewParent->pgno);
- }
-
-#ifndef NDEBUG
- /* If the updatePtrmap flag was clear, assert that the entry in the
- ** pointer-map is already correct.
- */
- if( ISAUTOVACUUM ){
- pDbPage = sqlite3PagerLookup(pBt->pPager,PTRMAP_PAGENO(pBt,pgno));
- if( pDbPage ){
- u8 eType;
- Pgno ii;
- int rc = ptrmapGet(pBt, pgno, &eType, &ii);
- assert( rc==SQLITE_OK && ii==pNewParent->pgno && eType==PTRMAP_BTREE );
- sqlite3PagerUnref(pDbPage);
- }
- }
-#endif
-
- return SQLITE_OK;
-}
-
-
-
-/*
-** Change the pParent pointer of all children of pPage to point back
-** to pPage.
-**
-** In other words, for every child of pPage, invoke reparentPage()
-** to make sure that each child knows that pPage is its parent.
-**
-** This routine gets called after you memcpy() one page into
-** another.
-**
-** If updatePtrmap is true, then the pointer-map entries for all child
-** pages of pPage are updated.
-*/
-static int reparentChildPages(MemPage *pPage, int updatePtrmap){
- int rc = SQLITE_OK;
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- if( !pPage->leaf ){
- int i;
- BtShared *pBt = pPage->pBt;
- Pgno iRight = get4byte(&pPage->aData[pPage->hdrOffset+8]);
-
- for(i=0; i<pPage->nCell; i++){
- u8 *pCell = findCell(pPage, i);
- rc = reparentPage(pBt, get4byte(pCell), pPage, i, updatePtrmap);
- if( rc!=SQLITE_OK ) return rc;
- }
- rc = reparentPage(pBt, iRight, pPage, i, updatePtrmap);
- pPage->idxShift = 0;
- }
- return rc;
-}
-
/*
** Remove the i-th cell from pPage. This routine effects pPage only.
** The cell content is not freed or deallocated. It is assumed that
**
** "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 */
data = pPage->aData;
ptr = &data[pPage->cellOffset + 2*idx];
pc = get2byte(ptr);
- assert( pc>10 && pc+sz<=pPage->pBt->usableSize );
+ if ( pc<=10 || pc+sz>pPage->pBt->usableSize ) {
+ return SQLITE_CORRUPT_BKPT;
+ }
freeSpace(pPage, pc, sz);
for(i=idx+1; i<pPage->nCell; i++, ptr+=2){
ptr[0] = ptr[2];
pPage->nCell--;
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
pPage->nFree += 2;
- pPage->idxShift = 1;
+ return SQLITE_OK;
}
/*
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);
}
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
#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
/*
** 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;
+ 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 */
** into it. Then remove the overflow cell from pPage.
*/
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pCell = pPage->aOvfl[0].pCell;
- szCell = cellSizePtr(pPage, pCell);
- zeroPage(pNew, pPage->aData[0]);
- assemblePage(pNew, 1, &pCell, &szCell);
- pPage->nOverflow = 0;
+ if( rc==SQLITE_OK ){
+ pCell = pPage->aOvfl[0].pCell;
+ szCell = cellSizePtr(pPage, pCell);
+ zeroPage(pNew, pPage->aData[0]);
+ assemblePage(pNew, 1, &pCell, &szCell);
+ pPage->nOverflow = 0;
+
+ /* pPage is currently the right-child of pParent. Change this
+ ** so that the right-child is the new page allocated above and
+ ** pPage is the next-to-right child.
+ **
+ ** Ignore the return value of the call to fillInCell(). fillInCell()
+ ** may only return other than SQLITE_OK if it is required to allocate
+ ** one or more overflow pages. Since an internal table B-Tree cell
+ ** may never spill over onto an overflow page (it is a maximum of
+ ** 13 bytes in size), it is not neccessary to check the return code.
+ **
+ ** Similarly, the insertCell() function cannot fail if the page
+ ** being inserted into is already writable and the cell does not
+ ** contain an overflow pointer. So ignore this return code too.
+ */
+ assert( pPage->nCell>0 );
+ pCell = findCell(pPage, pPage->nCell-1);
+ sqlite3BtreeParseCellPtr(pPage, pCell, &info);
+ fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize);
+ assert( parentSize<64 );
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
+ put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
+ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
+
+ /* If this is an auto-vacuum database, update the pointer map
+ ** with entries for the new page, and any pointer from the
+ ** cell on the page to an overflow page.
+ */
+ if( ISAUTOVACUUM ){
+ rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
+ if( rc==SQLITE_OK ){
+ rc = ptrmapPutOvfl(pNew, 0);
+ }
+ }
- /* Set the parent of the newly allocated page to pParent. */
- pNew->pParent = pParent;
- sqlite3PagerRef(pParent->pDbPage);
+ /* Release the reference to the new page. */
+ releasePage(pNew);
+ }
- /* pPage is currently the right-child of pParent. Change this
- ** so that the right-child is the new page allocated above and
- ** pPage is the next-to-right child.
- **
- ** Ignore the return value of the call to fillInCell(). fillInCell()
- ** may only return other than SQLITE_OK if it is required to allocate
- ** one or more overflow pages. Since an internal table B-Tree cell
- ** may never spill over onto an overflow page (it is a maximum of
- ** 13 bytes in size), it is not neccessary to check the return code.
+ /* At this point the pPage->nFree variable is not set correctly with
+ ** respect to the content of the page (because it was set to 0 by
+ ** insertCell). So call sqlite3BtreeInitPage() to make sure it is
+ ** correct.
**
- ** Similarly, the insertCell() function cannot fail if the page
- ** being inserted into is already writable and the cell does not
- ** contain an overflow pointer. So ignore this return code too.
+ ** This has to be done even if an error will be returned. Normally, if
+ ** an error occurs during tree balancing, the contents of MemPage are
+ ** not important, as they will be recalculated when the page is rolled
+ ** back. But here, in balance_quick(), it is possible that pPage has
+ ** not yet been marked dirty or written into the journal file. Therefore
+ ** it will not be rolled back and so it is important to make sure that
+ ** the page data and contents of MemPage are consistent.
*/
- assert( pPage->nCell>0 );
- pCell = findCell(pPage, pPage->nCell-1);
- sqlite3BtreeParseCellPtr(pPage, pCell, &info);
- fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize);
- assert( parentSize<64 );
- assert( sqlite3PagerIswriteable(pParent->pDbPage) );
- insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
- put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
- put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
+ pPage->isInit = 0;
+ sqlite3BtreeInitPage(pPage);
- /* If this is an auto-vacuum database, update the pointer map
- ** with entries for the new page, and any pointer from the
- ** cell on the page to an overflow page.
+ /* If everything else succeeded, balance the parent page, in
+ ** case the divider cell inserted caused it to become overfull.
*/
- if( ISAUTOVACUUM ){
- rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
- if( rc==SQLITE_OK ){
- rc = ptrmapPutOvfl(pNew, 0);
- }
- if( rc!=SQLITE_OK ){
- releasePage(pNew);
- return rc;
- }
+ if( rc==SQLITE_OK ){
+ releasePage(pPage);
+ pCur->iPage--;
+ rc = balance(pCur, 0);
}
-
- /* Release the reference to the new page and balance the parent page,
- ** in case the divider cell inserted caused it to become overfull.
- */
- releasePage(pNew);
- return balance(pParent, 0);
+ return rc;
}
#endif /* SQLITE_OMIT_QUICKBALANCE */
** 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[] */
u8 *aSpace2 = 0; /* Space for overflow dividers cells after balance */
u8 *aFrom = 0;
+ pPage = pCur->apPage[pCur->iPage];
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ VVA_ONLY( pCur->pagesShuffled = 1 );
/*
** Find the parent page.
*/
+ assert( pCur->iPage>0 );
assert( pPage->isInit );
assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 );
pBt = pPage->pBt;
- pParent = pPage->pParent;
+ pParent = pCur->apPage[pCur->iPage-1];
assert( pParent );
if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){
return rc;
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 );
** 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
** 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; idx<pParent->nCell; idx++){
- if( get4byte(findCell(pParent, idx))==pgno ){
- break;
- }
- }
- assert( idx<pParent->nCell
- || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno );
- }else{
- idx = pPage->idxParent;
- }
+ 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
}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++;
put4byte(findOverflowCell(pParent, nxDiv), pgnoNew[nNew-1]);
}
- /*
- ** Reparent children of all cells.
- */
- for(i=0; i<nNew; i++){
- rc = reparentChildPages(apNew[i], 0);
- if( rc!=SQLITE_OK ) goto balance_cleanup;
- }
- rc = reparentChildPages(pParent, 0);
- if( rc!=SQLITE_OK ) goto balance_cleanup;
-
/*
** Balance the parent page. Note that the current page (pPage) might
** have been added to the freelist so it might no longer be initialized.
assert( pParent->isInit );
sqlite3ScratchFree(apCell);
apCell = 0;
- rc = balance(pParent, 0);
+ releasePage(pPage);
+ pCur->iPage--;
+ rc = balance(pCur, 0);
/*
** Cleanup before returning.
for(i=0; i<nNew; i++){
releasePage(apNew[i]);
}
- releasePage(pParent);
+
+ /* releasePage(pParent); */
TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n",
pPage->pgno, nOld, nNew, nCell));
+
return rc;
}
** 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 */
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;
** 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) );
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 ){
}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; i<pPage->nCell; i++){
- rc = ptrmapPutOvfl(pPage, i);
- if( rc!=SQLITE_OK ){
- goto end_shallow_balance;
- }
- }
+ rc = setChildPtrmaps(pPage);
}
+#endif
releasePage(pChild);
}
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 */
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);
cdata = pChild->aData;
memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
- if( pChild->isInit ) return SQLITE_CORRUPT;
- rc = sqlite3BtreeInitPage(pChild, pPage);
- if( rc ) goto balancedeeper_out;
- memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0]));
- pChild->nOverflow = pPage->nOverflow;
- if( pChild->nOverflow ){
- pChild->nFree = 0;
- }
- assert( pChild->nCell==pPage->nCell );
- zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF);
- put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild);
- TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno));
- if( ISAUTOVACUUM ){
- int i;
- rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno);
- if( rc ) goto balancedeeper_out;
- for(i=0; i<pChild->nCell; i++){
- rc = ptrmapPutOvfl(pChild, i);
- if( rc!=SQLITE_OK ){
- goto balancedeeper_out;
+
+ 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;
int rc;
int loc;
int szNew;
+ int idx;
MemPage *pPage;
Btree *p = pCur->pBtree;
BtShared *pBt = p->pBt;
}
/* 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))
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",
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->idx<pPage->nCell );
+ assert( idx<pPage->nCell );
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);
}
/*
** 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;
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 ){
** 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);
}
** to be a leaf so we can use it.
*/
BtCursor leafCur;
+ MemPage *pLeafPage;
+
unsigned char *pNext;
int notUsed;
unsigned char *tempCell = 0;
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;
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->nFree<pBt->usableSize*2/3
+ && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
+ testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3
+ && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
+ testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3+1
+ && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
+ testcase( pPage->nOverflow>0 && pPage->nFree<=pBt->usableSize*2/3
+ && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
+ testcase( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3))
+ && pLeafPage->nFree+2+szNext == pBt->usableSize*2/3 );
+
+
+ if( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3)) &&
+ (pLeafPage->nFree+2+szNext > pBt->usableSize*2/3)
+ ){
+ /* This branch is taken if the internal node is now either overflowing
+ ** or underfull and the leaf node will be underfull after the just cell
+ ** copied to the internal node is deleted from it. This is a special
+ ** case because the call to balance() to correct the internal node
+ ** may change the tree structure and invalidate the contents of
+ ** the leafCur.apPage[] and leafCur.aiIdx[] arrays, which will be
+ ** used by the balance() required to correct the underfull leaf
+ ** node.
+ **
+ ** The formula used in the expression above are based on facets of
+ ** the SQLite file-format that do not change over time.
+ */
+ testcase( pPage->nFree==pBt->usableSize*2/3+1 );
+ testcase( pLeafPage->nFree+2+szNext==pBt->usableSize*2/3+1 );
+ leafCursorInvalid = 1;
+ }
+
if( rc==SQLITE_OK ){
- put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild);
- rc = balance(pPage, 0);
+ 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 ){
- 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);
+ dropCell(pPage, idx, cellSizePtr(pPage, pCell));
+ rc = balance(pCur, 0);
}
if( rc==SQLITE_OK ){
moveToRoot(pCur);
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;
return SQLITE_CORRUPT_BKPT;
}
- rc = getAndInitPage(pBt, pgno, &pPage, pParent);
+ rc = getAndInitPage(pBt, pgno, &pPage);
if( rc ) goto cleardatabasepage_out;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
if( !pPage->leaf ){
- rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1);
+ rc = clearDatabasePage(pBt, get4byte(pCell), pPage, 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->pParent, 1);
+ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage, 1, pnChange);
if( rc ) goto cleardatabasepage_out;
+ }else if( pnChange ){
+ assert( pPage->intKey );
+ *pnChange += pPage->nCell;
}
if( freePageFlag ){
rc = freePage(pPage);
** 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);
}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, 0, pnChange);
}
sqlite3BtreeLeave(p);
return rc;
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;
}
assert( idx>=0 && idx<=15 );
- rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage);
- if( rc ){
- sqlite3BtreeLeave(p);
- return rc;
+ if( pBt->pPage1 ){
+ /* The b-tree is already holding a reference to page 1 of the database
+ ** file. In this case the required meta-data value can be read directly
+ ** from the page data of this reference. This is slightly faster than
+ ** requesting a new reference from the pager layer.
+ */
+ pP1 = (unsigned char *)pBt->pPage1->aData;
+ }else{
+ /* The b-tree does not have a reference to page 1 of the database file.
+ ** Obtain one from the pager layer.
+ */
+ rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage);
+ if( rc ){
+ sqlite3BtreeLeave(p);
+ return rc;
+ }
+ pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage);
}
- pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage);
*pMeta = get4byte(&pP1[36 + idx*4]);
- sqlite3PagerUnref(pDbPage);
+
+ /* If the b-tree is not holding a reference to page 1, then one was
+ ** requested from the pager layer in the above block. Release it now.
+ */
+ if( !pBt->pPage1 ){
+ sqlite3PagerUnref(pDbPage);
+ }
/* If autovacuumed is disabled in this build but we are trying to
** access an autovacuumed database, then make the database readonly.
*/
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;
BtShared *pBt;
int usableSize;
char zContext[100];
- char *hit;
+ char *hit = 0;
sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
"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);
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; i<nCell; i++){
cnt, data[hdr+7], iPage);
}
}
- sqlite3PageFree(hit);
+check_page_abort:
+ if (hit) sqlite3PageFree(hit);
releasePage(pPage);
return depth+1;
}
memcpy(zTo, zFrom, nCopy);
- sqlite3PagerUnref(pFromPage);
+ sqlite3PagerUnref(pFromPage);
}
}
- if( pToPage ) sqlite3PagerUnref(pToPage);
+ if( pToPage ){
+ MemPage *p = (MemPage *)sqlite3PagerGetExtra(pToPage);
+ p->isInit = 0;
+ sqlite3PagerUnref(pToPage);
+ }
}
}
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;
}
if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
if( preserve && pMem->z==pMem->zMalloc ){
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
- if( !pMem->z ){
- pMem->flags = MEM_Null;
- }
preserve = 0;
}else{
sqlite3DbFree(pMem->db, pMem->zMalloc);
}
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);
}
}
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
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
+ if( nByte>iLimit ){
+ return SQLITE_TOOBIG;
+ }
if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){
return SQLITE_NOMEM;
}
pMem->xDel = xDel;
flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
}
+ if( nByte>iLimit ){
+ return SQLITE_TOOBIG;
+ }
pMem->n = nByte;
pMem->flags = flags;
** comparison function directly */
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
}else{
- u8 origEnc = pMem1->enc;
const void *v1, *v2;
int n1, n2;
- /* Convert the strings into the encoding that the comparison
- ** function expects */
- v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc);
- n1 = v1==0 ? 0 : pMem1->n;
- assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) );
- v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc);
- n2 = v2==0 ? 0 : pMem2->n;
- assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) );
- /* Do the comparison */
+ Mem c1;
+ Mem c2;
+ memset(&c1, 0, sizeof(c1));
+ memset(&c2, 0, sizeof(c2));
+ sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
+ sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
+ v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
+ n1 = v1==0 ? 0 : c1.n;
+ v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
+ n2 = v2==0 ? 0 : c2.n;
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
- /* Convert the strings back into the database encoding */
- sqlite3ValueText((sqlite3_value*)pMem1, origEnc);
- sqlite3ValueText((sqlite3_value*)pMem2, origEnc);
+ sqlite3VdbeMemRelease(&c1);
+ sqlite3VdbeMemRelease(&c2);
return rc;
}
}
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,
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;
}
}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;
** 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;
*/
static void releaseMemArray(Mem *p, int N){
if( p && N ){
+ Mem *pEnd;
sqlite3 *db = p->db;
int malloc_failed = db->mallocFailed;
- while( N-->0 ){
- assert( N<2 || p[0].db==p[1].db );
- sqlite3VdbeMemRelease(p);
+ for(pEnd=&p[N]; p<pEnd; p++){
+ assert( (&p[1])==pEnd || p[0].db==p[1].db );
+
+ /* This block is really an inlined version of sqlite3VdbeMemRelease()
+ ** that takes advantage of the fact that the memory cell value is
+ ** being set to NULL after releasing any dynamic resources.
+ **
+ ** The justification for duplicating code is that according to
+ ** callgrind, this causes a certain test case to hit the CPU 4.7
+ ** percent less (x86 linux, gcc version 4.1.2, -O6) than if
+ ** sqlite3MemRelease() were called from here. With -O2, this jumps
+ ** to 6.6 percent. The test case is inserting 1000 rows into a table
+ ** with no indexes using a single prepared INSERT statement, bind()
+ ** and reset(). Inserts are grouped into a transaction.
+ */
+ if( p->flags&(MEM_Agg|MEM_Dyn) ){
+ sqlite3VdbeMemRelease(p);
+ }else if( p->zMalloc ){
+ sqlite3DbFree(db, p->zMalloc);
+ p->zMalloc = 0;
+ }
+
p->flags = MEM_Null;
- p++;
}
db->mallocFailed = malloc_failed;
}
pMem->z = pOp->zComment;
pMem->n = strlen(pMem->z);
pMem->enc = SQLITE_UTF8;
+ pMem->type = SQLITE_TEXT;
}else
#endif
{
/* 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.
**
/*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 */
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; n<nVar; n++){
p->aVar[n].flags = MEM_Null;
** 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;
}
int i;
if( p->apCsr==0 ) return;
for(i=0; i<p->nCursor; i++){
- Cursor *pC = p->apCsr[i];
+ VdbeCursor *pC = p->apCsr[i];
if( pC && (!p->inVtabMethod || !pC->pVtabCursor) ){
sqlite3VdbeFreeCursor(p, pC);
p->apCsr[i] = 0;
**
** 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( idx<p->nResColumn );
assert( var<COLNAME_N );
- if( p->db->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;
}
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)
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
if( isSpecialError ){
- /* This loop does static analysis of the query to see which of the
- ** following three categories it falls into:
- **
- ** Read-only
- ** Query with statement journal
- ** Query without statement journal
- **
- ** We could do something more elegant than this static analysis (i.e.
- ** store the type of query as part of the compliation phase), but
- ** handling malloc() or IO failure is a fairly obscure edge case so
- ** this is probably easier. Todo: Might be an opportunity to reduce
- ** code size a very small amount though...
- */
- int notReadOnly = 0;
- int isStatement = 0;
- assert(p->aOp || p->nOp==0);
- for(i=0; i<p->nOp; i++){
- switch( p->aOp[i].opcode ){
- case OP_Transaction:
- notReadOnly |= p->aOp[i].p2;
- break;
- case OP_Statement:
- isStatement = 1;
- break;
- }
- }
-
-
/* If the query was read-only, we need do no rollback at all. Otherwise,
** proceed with the special handling.
*/
- if( 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
** 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( 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
/* 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);
*/
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;
** 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
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;
** 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 */
){
#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
Vdbe *p = (Vdbe*)pStmt;
return p==0 || p->expired;
}
+#endif
/*
** The following routine destroys a virtual machine that is created by
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);
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);
#endif
db->activeVdbeCnt++;
+ if( p->readOnly==0 ) db->writeVdbeCnt++;
p->pc = 0;
stmtLruRemove(p);
}
}
}
+#ifndef SQLITE_OMIT_DEPRECATED
/*
** Return the number of times the Step function of a aggregate has been
** called.
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.
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){
** 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--;
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;
}
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){
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(
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;
}
** If the two statements contain a different number of bindings, then
** an SQLITE_ERROR is returned.
*/
-SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
+SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
int i, rc = SQLITE_OK;
return rc;
}
+#ifndef SQLITE_OMIT_DEPRECATED
+/*
+** Deprecated external interface. Internal/core SQLite code
+** should call sqlite3TransferBindings.
+*/
+SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
+ return sqlite3TransferBindings(pFromStmt, pToStmt);
+}
+#endif
+
/*
** Return the sqlite3* database handle to which the prepared statement given
** in the argument belongs. This is the same database handle that was
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 ********************************************/
/*
# define UPDATE_MAX_BLOBSIZE(P)
#endif
-/*
-** Release the memory associated with a register. This
-** leaves the Mem.flags field in an inconsistent state.
-*/
-#define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); }
-
/*
** Convert the given register into a string if it isn't one
** already. Return non-zero if a malloc() fails.
** from the comments following the "case OP_xxxx:" statements in
** this file.
*/
-static unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
+static const unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
/*
** Return true if an opcode has any of the OPFLG_xxx properties
}
/*
-** 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
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);
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;
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 );
**
** 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.
u32 payloadSize; /* Number of bytes in the record */
int p1 = pOp->p1; /* P1 value of the opcode */
int p2 = pOp->p2; /* column number to retrieve */
- 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 */
** 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 );
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
- if( zIdx>zEndHdr || offset>payloadSize || (zIdx==zEndHdr && offset!=payloadSize) ){
+ if( zIdx>zEndHdr || offset>payloadSize
+ || (zIdx==zEndHdr && offset!=payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
** 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;
}
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"));
int iDb = pOp->p3;
int wrFlag;
Btree *pX;
- Cursor *pCur;
+ VdbeCursor *pCur;
Db *pDb;
assert( iDb>=0 && iDb<db->nDb );
*/
case OP_OpenEphemeral: {
int i = pOp->p1;
- Cursor *pCx;
+ VdbeCursor *pCx;
static const int openFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
*/
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;
case OP_MoveGe: /* jump, in3 */
case OP_MoveGt: { /* jump, in3 */
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
case OP_Found: { /* jump, in3 */
int i = pOp->p1;
int alreadyExists = 0;
- Cursor *pC;
+ VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pC = p->apCsr[i])->pCursor!=0 ){
*/
case OP_IsUnique: { /* jump, in3 */
int i = pOp->p1;
- Cursor *pCx;
+ VdbeCursor *pCx;
BtCursor *pCrsr;
Mem *pK;
i64 R;
*/
case OP_NotExists: { /* jump, in3 */
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
BtCursor *pCrsr;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
case OP_NewRowid: { /* out2-prerelease */
int i = pOp->p1;
i64 v = 0;
- Cursor *pC;
+ VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pC = p->apCsr[i])->pCursor==0 ){
i64 iKey; /* The integer ROWID or key for the record to be inserted */
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
assert( pC!=0 );
case OP_Delete: {
int i = pOp->p1;
i64 iKey;
- Cursor *pC;
+ VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
case OP_RowKey:
case OP_RowData: {
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
*/
case OP_Rowid: { /* out2-prerelease */
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
i64 v;
assert( i>=0 && i<p->nCursor );
*/
case OP_NullRow: {
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
pC = p->apCsr[i];
assert( pC!=0 );
pC->nullRow = 1;
pC->rowidIsValid = 0;
+ if( pC->pCursor ){
+ sqlite3BtreeClearCursor(pC->pCursor);
+ }
break;
}
*/
case OP_Last: { /* jump */
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
BtCursor *pCrsr;
int res;
sqlite3_sort_count++;
sqlite3_search_count--;
#endif
+ p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
/* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
*/
case OP_Rewind: { /* jump */
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
BtCursor *pCrsr;
int res;
*/
case OP_Prev: /* jump */
case OP_Next: { /* jump */
- Cursor *pC;
+ VdbeCursor *pC;
BtCursor *pCrsr;
int res;
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
*/
case OP_IdxInsert: { /* in2 */
int i = pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
BtCursor *pCrsr;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
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
*/
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 );
case OP_IdxRowid: { /* out2-prerelease */
int i = pOp->p1;
BtCursor *pCrsr;
- Cursor *pC;
+ VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
case OP_IdxLT: /* jump, in3 */
case OP_IdxGE: { /* jump, in3 */
int i= pOp->p1;
- Cursor *pC;
+ VdbeCursor *pC;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
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
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
+** If the P3 value is non-zero, then the table refered to must be an
+** intkey table (an SQL table, not an index). In this case the row change
+** count is incremented by the number of rows in the table being cleared.
+** If P3 is greater than zero, then the value stored in register P3 is
+** also incremented by the number of rows in the table being cleared.
+**
** See also: Destroy
*/
case OP_Clear: {
+ int nChange = 0;
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
- rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
+ 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;
}
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 );
** 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;
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 );
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 ){
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];
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;
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
#endif
/************** End of journal.c *********************************************/
+/************** Begin file memjournal.c **************************************/
+/*
+** 2008 October 7
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code use to implement an in-memory rollback journal.
+** The in-memory rollback journal is used to journal transactions for
+** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
+**
+** @(#) $Id$
+*/
+
+/* Forward references to internal structures */
+typedef struct MemJournal MemJournal;
+typedef struct FilePoint FilePoint;
+typedef struct FileChunk FileChunk;
+
+/* Space to hold the rollback journal is allocated in increments of
+** this many bytes.
+*/
+#define JOURNAL_CHUNKSIZE 1024
+
+/* Macro to find the minimum of two numeric values.
+*/
+#ifndef MIN
+# define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+/*
+** The rollback journal is composed of a linked list of these structures.
+*/
+struct FileChunk {
+ FileChunk *pNext; /* Next chunk in the journal */
+ u8 zChunk[JOURNAL_CHUNKSIZE]; /* Content of this chunk */
+};
+
+/*
+** An instance of this object serves as a cursor into the rollback journal.
+** The cursor can be either for reading or writing.
+*/
+struct FilePoint {
+ sqlite3_int64 iOffset; /* Offset from the beginning of the file */
+ FileChunk *pChunk; /* Specific chunk into which cursor points */
+};
+
+/*
+** This subclass is a subclass of sqlite3_file. Each open memory-journal
+** is an instance of this class.
+*/
+struct MemJournal {
+ sqlite3_io_methods *pMethod; /* Parent class. MUST BE FIRST */
+ FileChunk *pFirst; /* Head of in-memory chunk-list */
+ FilePoint endpoint; /* Pointer to the end of the file */
+ FilePoint readpoint; /* Pointer to the end of the last xRead() */
+};
+
+/*
+** Read data from the file.
+*/
+static int memjrnlRead(
+ sqlite3_file *pJfd, /* The journal file from which to read */
+ void *zBuf, /* Put the results here */
+ int iAmt, /* Number of bytes to read */
+ sqlite_int64 iOfst /* Begin reading at this offset */
+){
+ MemJournal *p = (MemJournal *)pJfd;
+ u8 *zOut = zBuf;
+ int nRead = iAmt;
+ int iChunkOffset;
+ FileChunk *pChunk;
+
+ assert( iOfst+iAmt<=p->endpoint.iOffset );
+
+ if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
+ sqlite3_int64 iOff = 0;
+ for(pChunk=p->pFirst;
+ pChunk && (iOff+JOURNAL_CHUNKSIZE)<=iOfst;
+ pChunk=pChunk->pNext
+ ){
+ iOff += JOURNAL_CHUNKSIZE;
+ }
+ }else{
+ pChunk = p->readpoint.pChunk;
+ }
+
+ iChunkOffset = (iOfst%JOURNAL_CHUNKSIZE);
+ do {
+ int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset;
+ int nCopy = MIN(nRead, (JOURNAL_CHUNKSIZE - iChunkOffset));
+ memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy);
+ zOut += nCopy;
+ nRead -= iSpace;
+ iChunkOffset = 0;
+ } while( nRead>=0 && (pChunk=pChunk->pNext) && nRead>0 );
+ p->readpoint.iOffset = iOfst+iAmt;
+ p->readpoint.pChunk = pChunk;
+
+ return SQLITE_OK;
+}
+
+/*
+** Write data to the file.
+*/
+static int memjrnlWrite(
+ sqlite3_file *pJfd, /* The journal file into which to write */
+ const void *zBuf, /* Take data to be written from here */
+ int iAmt, /* Number of bytes to write */
+ sqlite_int64 iOfst /* Begin writing at this offset into the file */
+){
+ MemJournal *p = (MemJournal *)pJfd;
+ int nWrite = iAmt;
+ u8 *zWrite = (u8 *)zBuf;
+
+ /* An in-memory journal file should only ever be appended to. Random
+ ** access writes are not required by sqlite.
+ */
+ assert(iOfst==p->endpoint.iOffset);
+
+ 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);
+ 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 *pJfd, int flags){
+ 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
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);
}
if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
sqlite3DbFree(db, zCol);
pExpr->op = TK_STRING;
+ pExpr->pTab = 0;
return 0;
}
}
#endif
switch( pExpr->op ){
+
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
+ /* The special operator TK_ROW means use the rowid for the first
+ ** column in the FROM clause. This is used by the LIMIT and ORDER BY
+ ** clause processing on UPDATE and DELETE statements.
+ */
+ case TK_ROW: {
+ SrcList *pSrcList = pNC->pSrcList;
+ struct SrcList_item *pItem;
+ assert( pSrcList && pSrcList->nSrc==1 );
+ pItem = pSrcList->a;
+ pExpr->op = TK_COLUMN;
+ pExpr->pTab = pItem->pTab;
+ pExpr->iTable = pItem->iCursor;
+ pExpr->iColumn = -1;
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ break;
+ }
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
+
/* A lone identifier is the name of a column.
*/
case TK_ID: {
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;
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;
}
/*
-** 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);
}
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++;
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;
}
**
** The pExpr parameter describes the expression that contains the IN
** operator or subquery.
+**
+** If parameter isRowid is non-zero, then expression pExpr is guaranteed
+** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
+** to some integer key column of a table B-Tree. In this case, use an
+** intkey B-Tree to store the set of IN(...) values instead of the usual
+** (slower) variable length keys B-Tree.
*/
#ifndef SQLITE_OMIT_SUBQUERY
-SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHaveNull){
+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;
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(<exprlist>)'
** expression it is handled the same way. A virtual table is
** 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;
SelectDest dest;
ExprList *pEList;
+ assert( !isRowid );
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.affinity = (int)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
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;
}
** 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 ){
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;
}
break;
}
case TK_AS: {
- inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft);
+ inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft, target);
break;
}
#ifndef SQLITE_OMIT_CAST
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);
if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){
constMask |= (1<<i);
}
- if( pDef->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);
}
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;
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);
Parse *pParse, /* Parsing context */
ExprList *pList, /* The expression list to be coded */
int target, /* Where to write results */
- int doHardCopy /* Call sqlite3ExprHardCopy on each element if true */
+ int doHardCopy /* Make a hard copy of every element */
){
struct ExprList_item *pItem;
int i, n;
n = pList->nExpr;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
if( pItem->iAlias ){
- 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);
}
- if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n);
+ if( doHardCopy ){
+ sqlite3ExprHardCopy(pParse, target, n);
+ }
}
return n;
}
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;
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 */
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 */
int rc;
NameContext sName;
Vdbe *v;
- FuncDef *pFunc;
sqlite3* db = pParse->db;
int regArgs;
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
** 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);
}
/*
** 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.
}
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 );
return -1;
}
+/*
+** Expand the space allocated for the given SrcList object by
+** creating nExtra new slots beginning at iStart. iStart is zero based.
+** New slots are zeroed.
+**
+** For example, suppose a SrcList initially contains two entries: A,B.
+** To append 3 new entries onto the end, do this:
+**
+** sqlite3SrcListEnlarge(db, pSrclist, 3, 2);
+**
+** After the call above it would contain: A, B, nil, nil, nil.
+** If the iStart argument had been 1 instead of 2, then the result
+** would have been: A, nil, nil, nil, B. To prepend the new slots,
+** the iStart value would be 0. The result then would
+** be: nil, nil, nil, A, B.
+**
+** If a memory allocation fails the SrcList is unchanged. The
+** db->mallocFailed flag will be set to true.
+*/
+SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(
+ sqlite3 *db, /* Database connection to notify of OOM errors */
+ SrcList *pSrc, /* The SrcList to be enlarged */
+ int nExtra, /* Number of new slots to add to pSrc->a[] */
+ int iStart /* Index in pSrc->a[] of first new slot */
+){
+ int i;
+
+ /* Sanity checking on calling parameters */
+ assert( iStart>=0 );
+ assert( nExtra>=1 );
+ if( pSrc==0 || iStart>pSrc->nSrc ){
+ assert( db->mallocFailed );
+ return pSrc;
+ }
+
+ /* Allocate additional space if needed */
+ if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
+ SrcList *pNew;
+ int nAlloc = pSrc->nSrc+nExtra;
+ pNew = sqlite3DbRealloc(db, pSrc,
+ sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
+ if( pNew==0 ){
+ assert( db->mallocFailed );
+ return pSrc;
+ }
+ pSrc = pNew;
+ pSrc->nAlloc = nAlloc;
+ }
+
+ /* Move existing slots that come after the newly inserted slots
+ ** out of the way */
+ for(i=pSrc->nSrc-1; i>=iStart; i--){
+ pSrc->a[i+nExtra] = pSrc->a[i];
+ }
+ pSrc->nSrc += nExtra;
+
+ /* Zero the newly allocated slots */
+ memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
+ for(i=iStart; i<iStart+nExtra; i++){
+ pSrc->a[i].iCursor = -1;
+ }
+
+ /* Return a pointer to the enlarged SrcList */
+ return pSrc;
+}
+
+
/*
** Append a new table name to the given SrcList. Create a new SrcList if
** need be. A new entry is created in the SrcList even if pToken is NULL.
**
-** A 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
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;
}
}
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;
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);
return p;
}
+/*
+** 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
if( nArg<-1 ) nArg = -1;
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
-
+ /* First search for a match amongst the application-defined functions.
+ */
p = functionSearch(&db->aFunc, h, zName, nName);
while( p ){
int score = matchQuality(p, nArg, enc);
p = p->pNext;
}
- /* If the createFlag parameter is false and no match was found amongst
- ** the custom functions stored in sqlite3.aFunc, try to find a built-in
- ** function to use.
+ /* If no match is found, search the built-in functions.
+ **
+ ** Except, if createFlag is true, that means that we are trying to
+ ** install a new function. Whatever FuncDef structure is returned will
+ ** have fields overwritten with new information appropriate for the
+ ** new function. But the FuncDefs for built-in functions are read-only.
+ ** So we must not search for built-ins when creating a new function.
*/
if( !createFlag && !pBest ){
- p = functionSearch(&sqlite3GlobalFunctions, h, zName, nName);
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ p = functionSearch(pHash, h, zName, nName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){
}
}
- /* If the createFlag parameter is true, and the seach did not reveal an
+ /* If the createFlag parameter is true and the search did not reveal an
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
- if( createFlag && bestScore<6 &&
+ if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
pBest->zName = (char *)&pBest[1];
pBest->nArg = nArg;
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);
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;
** 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; i<pSrc->nSrc; 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;
}
}
#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.
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 */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb<db->nDb );
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.
*/
/* If we are trying to delete from a view, realize that view into
** a ephemeral table.
*/
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
}
+#endif
/* Resolve the column names in the WHERE clause.
*/
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
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:
assert( zIn==sqlite3_value_text(argv[0]) );
if( argc==1 ){
static const unsigned char lenOne[] = { 1 };
- static const unsigned char *azOne[] = { (u8*)" " };
+ static unsigned char * const azOne[] = { (u8*)" " };
nChar = 1;
aLen = (u8*)lenOne;
azChar = (unsigned char **)azOne;
sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
}
+
#ifdef SQLITE_SOUNDEX
/*
** Compute the soundex encoding of a word.
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);
return 1;
}
-/*
-** The following array holds FuncDef structures for all of the functions
-** defined in this file.
-**
-** The array cannot be constant since changes are made to the
-** FuncDef.pHash elements at start-time. The elements of this array
-** are read-only after initialization is complete.
-*/
-static FuncDef aBuiltinFunc[] = {
- FUNCTION(ltrim, 1, 1, 0, trimFunc ),
- FUNCTION(ltrim, 2, 1, 0, trimFunc ),
- FUNCTION(rtrim, 1, 2, 0, trimFunc ),
- FUNCTION(rtrim, 2, 2, 0, trimFunc ),
- FUNCTION(trim, 1, 3, 0, trimFunc ),
- FUNCTION(trim, 2, 3, 0, trimFunc ),
- FUNCTION(min, -1, 0, 1, minmaxFunc ),
- FUNCTION(min, 0, 0, 1, 0 ),
- AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
- FUNCTION(max, -1, 1, 1, minmaxFunc ),
- FUNCTION(max, 0, 1, 1, 0 ),
- AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
- FUNCTION(typeof, 1, 0, 0, typeofFunc ),
- FUNCTION(length, 1, 0, 0, lengthFunc ),
- FUNCTION(substr, 2, 0, 0, substrFunc ),
- FUNCTION(substr, 3, 0, 0, substrFunc ),
- FUNCTION(abs, 1, 0, 0, absFunc ),
- FUNCTION(round, 1, 0, 0, roundFunc ),
- FUNCTION(round, 2, 0, 0, roundFunc ),
- FUNCTION(upper, 1, 0, 0, upperFunc ),
- FUNCTION(lower, 1, 0, 0, lowerFunc ),
- FUNCTION(coalesce, 1, 0, 0, 0 ),
- FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
- FUNCTION(coalesce, 0, 0, 0, 0 ),
- FUNCTION(hex, 1, 0, 0, hexFunc ),
- FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
- FUNCTION(random, -1, 0, 0, randomFunc ),
- FUNCTION(randomblob, 1, 0, 0, randomBlob ),
- FUNCTION(nullif, 2, 0, 1, nullifFunc ),
- FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
- FUNCTION(quote, 1, 0, 0, quoteFunc ),
- FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
- FUNCTION(changes, 0, 0, 0, changes ),
- FUNCTION(total_changes, 0, 0, 0, total_changes ),
- FUNCTION(replace, 3, 0, 0, replaceFunc ),
- FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
-#ifdef SQLITE_SOUNDEX
- FUNCTION(soundex, 1, 0, 0, soundexFunc ),
-#endif
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- FUNCTION(load_extension, 1, 0, 0, loadExt ),
- FUNCTION(load_extension, 2, 0, 0, loadExt ),
-#endif
- AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
- AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
- AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
- AGGREGATE(count, 0, 0, 0, countStep, countFinalize ),
- AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
- AGGREGATE(group_concat, -1, 0, 0, groupConcatStep, groupConcatFinalize),
-
- LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
-#ifdef SQLITE_CASE_SENSITIVE_LIKE
- LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
- LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
-#else
- LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
- LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
-#endif
-};
-
/*
** All all of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
** After this routine runs
*/
SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
+ /*
+ ** The following array holds FuncDef structures for all of the functions
+ ** defined in this file.
+ **
+ ** The array cannot be constant since changes are made to the
+ ** FuncDef.pHash elements at start-time. The elements of this array
+ ** are read-only after initialization is complete.
+ */
+ static SQLITE_WSD FuncDef aBuiltinFunc[] = {
+ FUNCTION(ltrim, 1, 1, 0, trimFunc ),
+ FUNCTION(ltrim, 2, 1, 0, trimFunc ),
+ FUNCTION(rtrim, 1, 2, 0, trimFunc ),
+ FUNCTION(rtrim, 2, 2, 0, trimFunc ),
+ FUNCTION(trim, 1, 3, 0, trimFunc ),
+ FUNCTION(trim, 2, 3, 0, trimFunc ),
+ FUNCTION(min, -1, 0, 1, minmaxFunc ),
+ FUNCTION(min, 0, 0, 1, 0 ),
+ AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(max, -1, 1, 1, minmaxFunc ),
+ FUNCTION(max, 0, 1, 1, 0 ),
+ AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(typeof, 1, 0, 0, typeofFunc ),
+ FUNCTION(length, 1, 0, 0, lengthFunc ),
+ FUNCTION(substr, 2, 0, 0, substrFunc ),
+ FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(abs, 1, 0, 0, absFunc ),
+ FUNCTION(round, 1, 0, 0, roundFunc ),
+ FUNCTION(round, 2, 0, 0, roundFunc ),
+ FUNCTION(upper, 1, 0, 0, upperFunc ),
+ FUNCTION(lower, 1, 0, 0, lowerFunc ),
+ FUNCTION(coalesce, 1, 0, 0, 0 ),
+ FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
+ FUNCTION(coalesce, 0, 0, 0, 0 ),
+ FUNCTION(hex, 1, 0, 0, hexFunc ),
+ FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
+ FUNCTION(random, -1, 0, 0, randomFunc ),
+ FUNCTION(randomblob, 1, 0, 0, randomBlob ),
+ FUNCTION(nullif, 2, 0, 1, nullifFunc ),
+ FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
+ FUNCTION(quote, 1, 0, 0, quoteFunc ),
+ FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
+ FUNCTION(changes, 0, 0, 0, changes ),
+ FUNCTION(total_changes, 0, 0, 0, total_changes ),
+ FUNCTION(replace, 3, 0, 0, replaceFunc ),
+ FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
+ #ifdef SQLITE_SOUNDEX
+ FUNCTION(soundex, 1, 0, 0, soundexFunc ),
+ #endif
+ #ifndef SQLITE_OMIT_LOAD_EXTENSION
+ FUNCTION(load_extension, 1, 0, 0, loadExt ),
+ FUNCTION(load_extension, 2, 0, 0, loadExt ),
+ #endif
+ AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
+ AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
+ AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
+ AGGREGATE(count, 0, 0, 0, countStep, countFinalize ),
+ AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
+ AGGREGATE(group_concat, -1, 0, 0, groupConcatStep, groupConcatFinalize),
+
+ LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ #ifdef SQLITE_CASE_SENSITIVE_LIKE
+ LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ #else
+ LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ #endif
+ };
+
int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);
+
for(i=0; i<ArraySize(aBuiltinFunc); i++){
- sqlite3FuncDefInsert(&sqlite3GlobalFunctions, &aBuiltinFunc[i]);
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
}
sqlite3RegisterDateTimeFunctions();
}
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:
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;
*/
#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
#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
#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
*/
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,
sqlite3_errmsg,
sqlite3_errmsg16,
sqlite3_exec,
+#ifndef SQLITE_OMIT_DEPRECATED
sqlite3_expired,
+#else
+ 0,
+#endif
sqlite3_finalize,
sqlite3_free,
sqlite3_free_table,
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,
sqlite3_file_control,
sqlite3_memory_highwater,
sqlite3_memory_used,
-#ifdef SQLITE_MUTEX_NOOP
+#ifdef SQLITE_MUTEX_OMIT
0,
0,
0,
** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER
** mutex must be held while accessing this list.
*/
-static struct {
+typedef struct sqlite3ExtType sqlite3ExtType;
+static SQLITE_WSD struct sqlite3ExtType {
int nExt; /* Number of entries in aExt[] */
void **aExt; /* Pointers to the extension init functions */
-} autoext = { 0, 0 };
+} sqlite3Autoext = { 0, 0 };
+
+/* The "wsdAutoext" macro will resolve to the autoextension
+** state vector. If writable static data is unsupported on the target,
+** we have to locate the state vector at run-time. In the more common
+** case where writable static data is supported, wsdStat can refer directly
+** to the "sqlite3Autoext" state vector declared above.
+*/
+#ifdef SQLITE_OMIT_WSD
+# define wsdAutoextInit \
+ sqlite3ExtType *x = &GLOBAL(sqlite3ExtType,sqlite3Autoext)
+# define wsdAutoext x[0]
+#else
+# define wsdAutoextInit
+# define wsdAutoext sqlite3Autoext
+#endif
/*
#endif
{
int i;
-#ifndef SQLITE_MUTEX_NOOP
+#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
+ wsdAutoextInit;
sqlite3_mutex_enter(mutex);
- for(i=0; i<autoext.nExt; i++){
- if( autoext.aExt[i]==xInit ) break;
+ for(i=0; i<wsdAutoext.nExt; i++){
+ if( wsdAutoext.aExt[i]==xInit ) break;
}
- if( i==autoext.nExt ){
- int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);
+ if( i==wsdAutoext.nExt ){
+ int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
void **aNew;
- aNew = sqlite3_realloc(autoext.aExt, nByte);
+ aNew = sqlite3_realloc(wsdAutoext.aExt, nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
- autoext.aExt = aNew;
- autoext.aExt[autoext.nExt] = xInit;
- autoext.nExt++;
+ wsdAutoext.aExt = aNew;
+ wsdAutoext.aExt[wsdAutoext.nExt] = xInit;
+ wsdAutoext.nExt++;
}
}
sqlite3_mutex_leave(mutex);
if( sqlite3_initialize()==SQLITE_OK )
#endif
{
-#ifndef SQLITE_MUTEX_NOOP
+#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
+ wsdAutoextInit;
sqlite3_mutex_enter(mutex);
- sqlite3_free(autoext.aExt);
- autoext.aExt = 0;
- autoext.nExt = 0;
+ sqlite3_free(wsdAutoext.aExt);
+ wsdAutoext.aExt = 0;
+ wsdAutoext.nExt = 0;
sqlite3_mutex_leave(mutex);
}
}
int rc = SQLITE_OK;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
- if( autoext.nExt==0 ){
+ wsdAutoextInit;
+ if( wsdAutoext.nExt==0 ){
/* Common case: early out without every having to acquire a mutex */
return SQLITE_OK;
}
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);
- if( i>=autoext.nExt ){
+ if( i>=wsdAutoext.nExt ){
xInit = 0;
go = 0;
}else{
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
- autoext.aExt[i];
+ wsdAutoext.aExt[i];
}
sqlite3_mutex_leave(mutex);
if( xInit && xInit(db, &zErrmsg, &sqlite3Apis) ){
sqlite3VdbeAddOp2(v, OP_Integer, value, mem);
if( pParse->explain==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);
}
}
#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.
**
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);
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
/*
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 const char *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--;
}
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);
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);
}
}else{
+#ifndef SQLITE_OMIT_WSD
if( zRight[0] ){
+ int rc;
int res;
- sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
- if( res==0 ){
+ rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
+ if( rc!=SQLITE_OK || res==0 ){
sqlite3ErrorMsg(pParse, "not a writable directory");
goto pragma_out;
}
}else{
sqlite3_temp_directory = 0;
}
+#endif /* SQLITE_OMIT_WSD */
}
}else
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; i<pTab->nCol; i++, pCol++){
const Token *pDflt;
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{
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; i<pIdx->nColumn; i++){
int cnum = pIdx->aiColumn[i];
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
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);
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; i<db->nDb; i++){
if( db->aDb[i].pBt==0 ) continue;
assert( db->aDb[i].zName!=0 );
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);
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; j<pFK->nCol; j++){
char *zCol = pFK->aCol[j].zCol;
+ char *zOnUpdate = (char *)actionName(pFK->updateConf);
+ char *zOnDelete = (char *)actionName(pFK->deleteConf);
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
sqlite3VdbeAddOp2(v, OP_Integer, j, 2);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0);
sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0,
pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
sqlite3VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0);
- 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;
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;
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) ){
|| sqlite3StrICmp(zLeft, "user_version")==0
|| sqlite3StrICmp(zLeft, "freelist_count")==0
){
-
int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
switch( zLeft[0] ){
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 */
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; i<db->nDb; i++){
Btree *pBt;
Pager *pPager;
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
+
}else
#endif
}
assert( argc==3 );
+ assert( iDb>=0 && iDb<db->nDb );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 ){
corruptSchema(pData, argv[0], 0);
- return 1;
- }
- assert( iDb>=0 && iDb<db->nDb );
- if( argv[2] && argv[2][0] ){
+ }else if( argv[2] && argv[2][0] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
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
assert( pNew!=0 );
}
sqlite3VdbeSwap((Vdbe*)pNew, p);
- sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p);
+ sqlite3TransferBindings(pNew, (sqlite3_stmt*)p);
sqlite3VdbeResetStepResult((Vdbe*)pNew);
sqlite3VdbeFinalize((Vdbe*)pNew);
return 1;
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));
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;
*/
static void setQuotedToken(Parse *pParse, Token *p, const char *z){
- /* Check if the string contains any " characters. If it does, then
- ** this function will malloc space to create a quoted version of
- ** the string in. Otherwise, save a call to sqlite3MPrintf() by
- ** just copying the pointer to the string.
+ /* Check if the string appears to be quoted using "..." or `...`
+ ** or [...] or '...' or if the string contains any " characters.
+ ** If it does, then record a version of the string with the special
+ ** characters escaped.
*/
const char *z2 = z;
- while( *z2 ){
- if( *z2=='"' ) break;
- z2++;
+ if( *z2!='[' && *z2!='`' && *z2!='\'' ){
+ while( *z2 ){
+ if( *z2=='"' ) break;
+ z2++;
+ }
}
if( *z2 ){
** 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 */
}
if( p==0 ) continue;
if( pEList->a[i].zName ){
char *zName = pEList->a[i].zName;
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName));
- }else if( p->op==TK_COLUMN && pTabList ){
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
+ }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){
Table *pTab;
char *zCol;
int iCol = p->iColumn;
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;
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);
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 */
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;
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,
int iTable, /* Table to be replaced */
ExprList *pEList /* Substitute values */
){
+ SrcList *pSrc;
+ struct SrcList_item *pItem;
+ int i;
if( !p ) return;
substExprList(db, p->pEList, iTable, pEList);
substExprList(db, p->pGroupBy, iTable, pEList);
substExpr(db, p->pHaving, iTable, pEList);
substExpr(db, p->pWhere, iTable, pEList);
substSelect(db, p->pPrior, iTable, pEList);
+ pSrc = p->pSrc;
+ if( pSrc ){
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+ substSelect(db, pItem->pSelect, iTable, pEList);
+ }
+ }
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/* Check to see if flattening is permitted. Return 0 if not.
*/
+ assert( p!=0 );
if( p==0 ) return 0;
+ assert( p->pPrior==0 ); /* Unable to flatten compound queries */
pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
pSubitem = &pSrc->a[iFrom];
** SELECT <expr-list> FROM (<sub-query>) <where-clause>
**
** 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 ){
- pSubitem = &pSrc->a[iFrom];
- nSubSrc = pSubSrc->nSrc;
+ assert( pParent==p ); /* First time through the loop */
jointype = pSubitem->jointype;
- sqlite3DeleteTable(pSubitem->pTab);
- sqlite3DbFree(db, pSubitem->zDatabase);
- sqlite3DbFree(db, pSubitem->zName);
- sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->pTab = 0;
- pSubitem->zDatabase = 0;
- pSubitem->zName = 0;
- pSubitem->zAlias = 0;
- }
- if( nSubSrc!=1 || !pSrc ){
- int extra = nSubSrc - 1;
- for(i=(pSrc?1:0); i<nSubSrc; i++){
- pSrc = sqlite3SrcListAppend(db, pSrc, 0, 0);
- if( pSrc==0 ){
- pParent->pSrc = 0;
- return 1;
- }
+ }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;
}
- 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; i<nSubSrc; i++){
pSrc->a[i+iFrom] = pSubSrc->a[i];
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
return WHERE_ORDERBY_NORMAL;
}
+/*
+** 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:
}
#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.
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 && j<nArg; j++, pItem++){
pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
}
** processed */
int iAbortFlag; /* Mem address which causes query abort if positive */
int groupBySort; /* Rows come from source in GROUP BY order */
+ int addrEnd; /* End of processing for this SELECT */
+ /* Remove any and all aliases between the result set and the
+ ** GROUP BY clause.
+ */
+ if( pGroupBy ){
+ int i; /* Loop counter */
+ struct ExprList_item *pItem; /* For looping over expression in a list */
- /* The following variables hold addresses or labels for parts of the
- ** virtual machine program we are putting together */
- int addrOutputRow; /* Start of subroutine that outputs a result row */
- int regOutputRow; /* Return address register for output subroutine */
- int addrSetAbort; /* Set the abort flag and return */
- int addrInitializeLoop; /* Start of code that initializes the input loop */
- int addrTopOfLoop; /* Top of the input loop */
- int addrEnd; /* End of all processing */
- int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
- int addrReset; /* Subroutine for resetting the accumulator */
- int regReset; /* Return address register for reset subroutine */
+ for(i=p->pEList->nExpr, pItem=p->pEList->a; i>0; i--, pItem++){
+ pItem->iAlias = 0;
+ }
+ for(i=pGroupBy->nExpr, pItem=pGroupBy->a; i>0; i--, pItem++){
+ pItem->iAlias = 0;
+ }
+ }
+
+ /* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(v);
/* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
*/
if( pGroupBy ){
KeyInfo *pKeyInfo; /* Keying information for the group by clause */
- int j1;
-
- /* Create labels that we will be needing
- */
- addrInitializeLoop = sqlite3VdbeMakeLabel(v);
+ int j1; /* A-vs-B comparision jump */
+ int addrOutputRow; /* Start of subroutine that outputs a result row */
+ int regOutputRow; /* Return address register for output subroutine */
+ int addrSetAbort; /* Set the abort flag and return */
+ int addrTopOfLoop; /* Top of the input loop */
+ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
+ int addrReset; /* Subroutine for resetting the accumulator */
+ int regReset; /* Return address register for reset subroutine */
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
*/
iUseFlag = ++pParse->nMem;
iAbortFlag = ++pParse->nMem;
+ regOutputRow = ++pParse->nMem;
+ addrOutputRow = sqlite3VdbeMakeLabel(v);
+ regReset = ++pParse->nMem;
+ addrReset = sqlite3VdbeMakeLabel(v);
iAMem = pParse->nMem + 1;
pParse->nMem += pGroupBy->nExpr;
iBMem = pParse->nMem + 1;
VdbeComment((v, "clear abort flag"));
sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
VdbeComment((v, "indicate accumulator empty"));
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrInitializeLoop);
-
- /* Generate a subroutine that outputs a single row of the result
- ** set. This subroutine first looks at the iUseFlag. If iUseFlag
- ** is less than or equal to zero, the subroutine is a no-op. If
- ** the processing calls for the query to abort, this subroutine
- ** increments the iAbortFlag memory location before returning in
- ** order to signal the caller to abort.
- */
- addrSetAbort = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
- VdbeComment((v, "set abort flag"));
- regOutputRow = ++pParse->nMem;
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- addrOutputRow = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
- VdbeComment((v, "Groupby result generator entry point"));
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- finalizeAggFunctions(pParse, &sAggInfo);
- if( pHaving ){
- sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
- }
- selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
- distinct, pDest,
- addrOutputRow+1, addrSetAbort);
- sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
- VdbeComment((v, "end groupby result generator"));
-
- /* Generate a subroutine that will reset the group-by accumulator
- */
- addrReset = sqlite3VdbeCurrentAddr(v);
- regReset = ++pParse->nMem;
- resetAccumulator(pParse, &sAggInfo);
- sqlite3VdbeAddOp1(v, OP_Return, regReset);
/* Begin a loop that will extract all source rows in GROUP BY order.
** This might involve two separate loops with an OP_Sort in between, or
** it might be a single loop that uses an index to extract information
** in the right order to begin with.
*/
- sqlite3VdbeResolveLabel(v, addrInitializeLoop);
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0);
if( pWInfo==0 ) goto select_end;
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
VdbeComment((v, "output final row"));
-
+
+ /* Jump over the subroutines
+ */
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd);
+
+ /* Generate a subroutine that outputs a single row of the result
+ ** set. This subroutine first looks at the iUseFlag. If iUseFlag
+ ** is less than or equal to zero, the subroutine is a no-op. If
+ ** the processing calls for the query to abort, this subroutine
+ ** increments the iAbortFlag memory location before returning in
+ ** order to signal the caller to abort.
+ */
+ addrSetAbort = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
+ VdbeComment((v, "set abort flag"));
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ sqlite3VdbeResolveLabel(v, addrOutputRow);
+ addrOutputRow = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
+ VdbeComment((v, "Groupby result generator entry point"));
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ finalizeAggFunctions(pParse, &sAggInfo);
+ if( pHaving ){
+ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
+ }
+ selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
+ distinct, pDest,
+ addrOutputRow+1, addrSetAbort);
+ sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
+ VdbeComment((v, "end groupby result generator"));
+
+ /* Generate a subroutine that will reset the group-by accumulator
+ */
+ sqlite3VdbeResolveLabel(v, addrReset);
+ resetAccumulator(pParse, &sAggInfo);
+ sqlite3VdbeAddOp1(v, OP_Return, regReset);
+
} /* endif pGroupBy */
else {
ExprList *pMinMax = 0;
/* If we are trying to update a view, realize that view into
** a ephemeral table.
*/
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
if( isView ){
sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
}
+#endif
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
if( chngRowid ){
sqlite3ExprCodeAndCache(pParse, pRowidExpr, regRowid);
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
}else{
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regRowid);
}
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:
** * 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 */
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
return 0.0;
}
- /* Check for a rowid=EXPR or rowid IN (...) constraints
+ /* Check for a rowid=EXPR or rowid IN (...) constraints. If there was
+ ** an INDEXED BY clause attached to this table, skip this step.
*/
- pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
- if( pTerm ){
- Expr *pExpr;
- *ppIndex = 0;
- bestFlags = WHERE_ROWID_EQ;
- if( pTerm->eOperator & WO_EQ ){
- /* Rowid== is always the best pick. Look no further. Because only
- ** a single row is generated, output is always in sorted order */
- *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
- *pnEq = 1;
- WHERETRACE(("... best is rowid\n"));
- return 0.0;
- }else if( (pExpr = pTerm->pExpr)->pList!=0 ){
- /* Rowid IN (LIST): cost is NlogN where N is the number of list
- ** elements. */
- lowestCost = pExpr->pList->nExpr;
- lowestCost *= estLog(lowestCost);
- }else{
- /* Rowid IN (SELECT): cost is NlogN where N is the number of rows
- ** in the result of the inner select. We have no way to estimate
- ** that value so make a wild guess. */
- lowestCost = 200;
- }
- WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost));
- }
-
- /* Estimate the cost of a table scan. If we do not know how many
- ** entries are in the table, use 1 million as a guess.
- */
- cost = pProbe ? pProbe->aiRowEst[0] : 1000000;
- WHERETRACE(("... table scan base cost: %.9g\n", cost));
- flags = WHERE_ROWID_RANGE;
-
- /* Check for constraints on a range of rowids in a table scan.
- */
- pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0);
- if( pTerm ){
- if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){
- flags |= WHERE_TOP_LIMIT;
- cost /= 3; /* Guess that rowid<EXPR eliminates two-thirds or rows */
- }
- if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
- flags |= WHERE_BTM_LIMIT;
- cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */
+ 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 rowid<EXPR eliminates two-thirds or rows */
}
+ if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
+ flags |= WHERE_BTM_LIMIT;
+ cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */
+ }
+ WHERETRACE(("... rowid range reduces cost to %.9g\n", cost));
}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( cost<lowestCost ){
+ lowestCost = cost;
+ bestFlags = flags;
}
- }
- if( cost<lowestCost ){
- lowestCost = cost;
- bestFlags = flags;
}
/* If the pSrc table is the right table of a LEFT JOIN then we may not
/* Look at each index.
*/
- for(; pProbe; pProbe=pProbe->pNext){
+ if( pSrc->pIndex ){
+ pProbe = pSrc->pIndex;
+ }
+ for(; pProbe; pProbe=(pSrc->pIndex ? 0 : pProbe->pNext)){
int i; /* Loop counter */
double inMultiplier = 1;
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 ){
/*
** 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; i<pWInfo->nLevel; i++){
sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
if( pInfo ){
pWInfo = sqlite3DbMallocZero(db,
sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
if( db->mallocFailed ){
- goto whereBeginNoMem;
+ goto whereBeginError;
}
pWInfo->nLevel = pTabList->nSrc;
pWInfo->pParse = pParse;
*/
exprAnalyzeAll(pTabList, &wc);
if( db->mallocFailed ){
- goto whereBeginNoMem;
+ goto whereBeginError;
}
/* Chose the best index to use for each table in the FROM clause.
** 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
**
}
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"));
*/
notReady = ~(Bitmask)0;
for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; 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 */
** 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, rtmp);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
}else if( pLevel->flags & WHERE_ROWID_RANGE ){
}
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);
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 );
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;
}
return pWInfo;
/* Jump here if malloc fails */
-whereBeginNoMem:
+whereBeginError:
whereClauseClear(&wc);
- whereInfoFree(pWInfo);
+ whereInfoFree(db, pWInfo);
return 0;
}
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;
/* Final cleanup
*/
- whereInfoFree(pWInfo);
+ whereInfoFree(db, pWInfo);
return;
}
** 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
#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)
** 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]))
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 */
"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 */
/* 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",
/* 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 */
** 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 */
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 },
+ { 163, 4 },
+ { 163, 6 },
{ 164, 1 },
- { 164, 1 },
- { 159, 2 },
- { 159, 0 },
- { 167, 3 },
- { 167, 1 },
- { 168, 2 },
- { 168, 4 },
- { 168, 3 },
+ { 164, 2 },
+ { 165, 1 },
+ { 165, 1 },
+ { 160, 2 },
+ { 160, 0 },
{ 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 */
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;
{ 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 */
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 ::= */
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 */
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 */
{
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 */
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 */
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;
}
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 */
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;}
{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 */
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;
};
** 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;
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->apVarExpr);
sqlite3DbFree(db, pParse->aAlias);
+ while( pParse->pZombieTab ){
+ Table *p = pParse->pZombieTab;
+ pParse->pZombieTab = p->pNextZombie;
+ sqlite3DeleteTable(p);
+ }
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}
/************** End of rtree.h ***********************************************/
/************** Continuing where we left off in main.c ***********************/
#endif
+#ifdef SQLITE_ENABLE_ICU
+/************** Include sqliteicu.h in the middle of main.c ******************/
+/************** Begin file sqliteicu.h ***************************************/
+/*
+** 2008 May 26
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This header file is used by programs that want to link against the
+** ICU extension. All it does is declare the sqlite3IcuInit() interface.
+*/
+
+#if 0
+extern "C" {
+#endif /* __cplusplus */
+
+SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db);
+
+#if 0
+} /* extern "C" */
+#endif /* __cplusplus */
+
+
+/************** End of sqliteicu.h *******************************************/
+/************** Continuing where we left off in main.c ***********************/
+#endif
/*
** The version of the library
** without blocking.
*/
SQLITE_API int sqlite3_initialize(void){
- static int inProgress = 0; /* Prevent recursion */
- sqlite3_mutex *pMaster; /* The main static mutex */
- int rc; /* Result code */
+ sqlite3_mutex *pMaster; /* The main static mutex */
+ int rc; /* Result code */
+
+#ifdef SQLITE_OMIT_WSD
+ rc = sqlite3_wsd_init(4096, 24);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+#endif
/* If SQLite is already completely initialized, then this call
** to sqlite3_initialize() should be a no-op. But the initialization
** must be complete. So isInit must not be set until the very end
** of this routine.
*/
- if( sqlite3Config.isInit ) return SQLITE_OK;
+ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
/* Make sure the mutex subsystem is initialized. If unable to
** initialize the mutex subsystem, return early with the error.
*/
pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(pMaster);
- if( !sqlite3Config.isMallocInit ){
+ if( !sqlite3GlobalConfig.isMallocInit ){
rc = sqlite3MallocInit();
}
if( rc==SQLITE_OK ){
- sqlite3Config.isMallocInit = 1;
- if( !sqlite3Config.pInitMutex ){
- sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
- if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
+ sqlite3GlobalConfig.isMallocInit = 1;
+ if( !sqlite3GlobalConfig.pInitMutex ){
+ sqlite3GlobalConfig.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
+ if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){
rc = SQLITE_NOMEM;
}
}
- sqlite3Config.nRefInitMutex++;
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3GlobalConfig.nRefInitMutex++;
}
sqlite3_mutex_leave(pMaster);
** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
** recursive calls might also be possible.
*/
- sqlite3_mutex_enter(sqlite3Config.pInitMutex);
- if( sqlite3Config.isInit==0 && inProgress==0 ){
- inProgress = 1;
- memset(&sqlite3GlobalFunctions, 0, sizeof(sqlite3GlobalFunctions));
+ sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex);
+ if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ sqlite3GlobalConfig.inProgress = 1;
+ memset(pHash, 0, sizeof(sqlite3GlobalFunctions));
sqlite3RegisterGlobalFunctions();
rc = sqlite3_os_init();
if( rc==SQLITE_OK ){
rc = sqlite3PcacheInitialize();
- sqlite3PCacheBufferSetup(sqlite3Config.pPage, sqlite3Config.szPage,
- sqlite3Config.nPage);
+ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
+ sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
}
- inProgress = 0;
- sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
+ sqlite3GlobalConfig.inProgress = 0;
+ sqlite3GlobalConfig.isInit = (rc==SQLITE_OK ? 1 : 0);
}
- sqlite3_mutex_leave(sqlite3Config.pInitMutex);
+ sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);
/* Go back under the static mutex and clean up the recursive
** mutex to prevent a resource leak.
*/
sqlite3_mutex_enter(pMaster);
- sqlite3Config.nRefInitMutex--;
- if( sqlite3Config.nRefInitMutex<=0 ){
- assert( sqlite3Config.nRefInitMutex==0 );
- sqlite3_mutex_free(sqlite3Config.pInitMutex);
- sqlite3Config.pInitMutex = 0;
+ sqlite3GlobalConfig.nRefInitMutex--;
+ if( sqlite3GlobalConfig.nRefInitMutex<=0 ){
+ assert( sqlite3GlobalConfig.nRefInitMutex==0 );
+ sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
+ sqlite3GlobalConfig.pInitMutex = 0;
}
sqlite3_mutex_leave(pMaster);
** routine is not threadsafe. Not by a long shot.
*/
SQLITE_API int sqlite3_shutdown(void){
- sqlite3Config.isMallocInit = 0;
+ sqlite3GlobalConfig.isMallocInit = 0;
sqlite3PcacheShutdown();
- if( sqlite3Config.isInit ){
+ if( sqlite3GlobalConfig.isInit ){
sqlite3_os_end();
}
- if( sqlite3Config.m.xShutdown ){
- sqlite3MallocEnd();
- }
- if( sqlite3Config.mutex.xMutexEnd ){
- sqlite3MutexEnd();
- }
- sqlite3Config.isInit = 0;
+ sqlite3MallocEnd();
+ sqlite3MutexEnd();
+ sqlite3GlobalConfig.isInit = 0;
return SQLITE_OK;
}
/* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while
** the SQLite library is in use. */
- if( sqlite3Config.isInit ) return SQLITE_MISUSE;
+ if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE;
va_start(ap, op);
switch( op ){
+
+ /* Mutex configuration options are only available in a threadsafe
+ ** compile.
+ */
+#if SQLITE_THREADSAFE
case SQLITE_CONFIG_SINGLETHREAD: {
/* Disable all mutexing */
- sqlite3Config.bCoreMutex = 0;
- sqlite3Config.bFullMutex = 0;
+ sqlite3GlobalConfig.bCoreMutex = 0;
+ sqlite3GlobalConfig.bFullMutex = 0;
break;
}
case SQLITE_CONFIG_MULTITHREAD: {
/* Disable mutexing of database connections */
/* Enable mutexing of core data structures */
- sqlite3Config.bCoreMutex = 1;
- sqlite3Config.bFullMutex = 0;
+ sqlite3GlobalConfig.bCoreMutex = 1;
+ sqlite3GlobalConfig.bFullMutex = 0;
break;
}
case SQLITE_CONFIG_SERIALIZED: {
/* Enable all mutexing */
- sqlite3Config.bCoreMutex = 1;
- sqlite3Config.bFullMutex = 1;
- break;
- }
- case SQLITE_CONFIG_MALLOC: {
- /* Specify an alternative malloc implementation */
- sqlite3Config.m = *va_arg(ap, sqlite3_mem_methods*);
- break;
- }
- case SQLITE_CONFIG_GETMALLOC: {
- /* Retrieve the current malloc() implementation */
- if( sqlite3Config.m.xMalloc==0 ) sqlite3MemSetDefault();
- *va_arg(ap, sqlite3_mem_methods*) = sqlite3Config.m;
+ sqlite3GlobalConfig.bCoreMutex = 1;
+ sqlite3GlobalConfig.bFullMutex = 1;
break;
}
case SQLITE_CONFIG_MUTEX: {
/* Specify an alternative mutex implementation */
- sqlite3Config.mutex = *va_arg(ap, sqlite3_mutex_methods*);
+ sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
break;
}
case SQLITE_CONFIG_GETMUTEX: {
/* Retrieve the current mutex implementation */
- *va_arg(ap, sqlite3_mutex_methods*) = sqlite3Config.mutex;
+ *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*);
+ break;
+ }
+ case SQLITE_CONFIG_GETMALLOC: {
+ /* Retrieve the current malloc() implementation */
+ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault();
+ *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m;
break;
}
case SQLITE_CONFIG_MEMSTATUS: {
/* Enable or disable the malloc status collection */
- sqlite3Config.bMemstat = va_arg(ap, int);
+ sqlite3GlobalConfig.bMemstat = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_SCRATCH: {
/* Designate a buffer for scratch memory space */
- sqlite3Config.pScratch = va_arg(ap, void*);
- sqlite3Config.szScratch = va_arg(ap, int);
- sqlite3Config.nScratch = va_arg(ap, int);
+ sqlite3GlobalConfig.pScratch = va_arg(ap, void*);
+ sqlite3GlobalConfig.szScratch = va_arg(ap, int);
+ sqlite3GlobalConfig.nScratch = va_arg(ap, int);
break;
}
case SQLITE_CONFIG_PAGECACHE: {
/* Designate a buffer for scratch memory space */
- sqlite3Config.pPage = va_arg(ap, void*);
- sqlite3Config.szPage = va_arg(ap, int);
- sqlite3Config.nPage = va_arg(ap, int);
+ sqlite3GlobalConfig.pPage = va_arg(ap, void*);
+ sqlite3GlobalConfig.szPage = va_arg(ap, int);
+ sqlite3GlobalConfig.nPage = va_arg(ap, int);
break;
}
#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5)
case SQLITE_CONFIG_HEAP: {
/* Designate a buffer for heap memory space */
- sqlite3Config.pHeap = va_arg(ap, void*);
- sqlite3Config.nHeap = va_arg(ap, int);
- sqlite3Config.mnReq = va_arg(ap, int);
+ sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
+ sqlite3GlobalConfig.nHeap = va_arg(ap, int);
+ sqlite3GlobalConfig.mnReq = va_arg(ap, int);
- if( sqlite3Config.pHeap==0 ){
+ if( sqlite3GlobalConfig.pHeap==0 ){
/* If the heap pointer is NULL, then restore the malloc implementation
** back to NULL pointers too. This will cause the malloc to go
** back to its default implementation when sqlite3_initialize() is
** run.
*/
- memset(&sqlite3Config.m, 0, sizeof(sqlite3Config.m));
+ memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
}else{
/* The heap pointer is not NULL, then install one of the
** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
** the default case and return an error.
*/
#ifdef SQLITE_ENABLE_MEMSYS3
- sqlite3Config.m = *sqlite3MemGetMemsys3();
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
#endif
#ifdef SQLITE_ENABLE_MEMSYS5
- sqlite3Config.m = *sqlite3MemGetMemsys5();
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5();
#endif
}
break;
}
#endif
-#if defined(SQLITE_ENABLE_MEMSYS6)
- case SQLITE_CONFIG_CHUNKALLOC: {
- sqlite3Config.nSmall = va_arg(ap, int);
- sqlite3Config.m = *sqlite3MemGetMemsys6();
- break;
- }
-#endif
-
case SQLITE_CONFIG_LOOKASIDE: {
- sqlite3Config.szLookaside = va_arg(ap, int);
- sqlite3Config.nLookaside = va_arg(ap, int);
+ sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
+ sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
break;
}
return SQLITE_OK;
}
+/*
+** 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
*/
sqlite3_mutex_leave(db->mutex);
db->magic = SQLITE_MAGIC_CLOSED;
sqlite3_mutex_free(db->mutex);
+ assert( db->lookaside.nOut==0 ); /* Fails on a lookaside memory leak */
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
}
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
#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
sqlite3 *db;
int rc;
CollSeq *pColl;
- int isThreadsafe = 1;
+ int isThreadsafe;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ) return rc;
#endif
- if( flags&SQLITE_OPEN_NOMUTEX ){
+ if( sqlite3GlobalConfig.bCoreMutex==0 ){
isThreadsafe = 0;
+ }else if( flags & SQLITE_OPEN_NOMUTEX ){
+ isThreadsafe = 0;
+ }else if( flags & SQLITE_OPEN_FULLMUTEX ){
+ isThreadsafe = 1;
+ }else{
+ isThreadsafe = sqlite3GlobalConfig.bFullMutex;
}
/* Remove harmful bits from the flags parameter */
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_MASTER_JOURNAL |
- SQLITE_OPEN_NOMUTEX
+ SQLITE_OPEN_NOMUTEX |
+ SQLITE_OPEN_FULLMUTEX
);
/* Allocate the sqlite data structure */
db = sqlite3MallocZero( sizeof(sqlite3) );
if( db==0 ) goto opendb_out;
- if( sqlite3Config.bFullMutex && isThreadsafe ){
+ if( isThreadsafe ){
db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
if( db->mutex==0 ){
sqlite3_free(db);
| 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);
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;
}
#ifdef SQLITE_ENABLE_ICU
if( !db->mallocFailed && rc==SQLITE_OK ){
- extern int sqlite3IcuInit(sqlite3*);
rc = sqlite3IcuInit(db);
}
#endif
#endif
/* Enable the lookaside-malloc subsystem */
- setupLookaside(db, 0, sqlite3Config.szLookaside, sqlite3Config.nLookaside);
+ setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
+ sqlite3GlobalConfig.nLookaside);
opendb_out:
if( db ){
- assert( db->mutex!=0 || isThreadsafe==0 || sqlite3Config.bFullMutex==0 );
+ assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
sqlite3_mutex_leave(db->mutex);
}
rc = sqlite3_errcode(db);
#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.
return SQLITE_OK;
}
#endif
+#endif
/*
** Test to see whether or not the database connection is in autocommit
}
#endif
+#ifndef SQLITE_OMIT_DEPRECATED
/*
** This is a convenience routine that makes sure that all thread-specific
** data for this thread has been deallocated.
*/
SQLITE_API void sqlite3_thread_cleanup(void){
}
+#endif
/*
** Return meta information about a specific column of a database table.
short int nPhrase; /* How many following terms are part of the same phrase */
short int iPhrase; /* This is the i-th term of a phrase. */
short int iColumn; /* Column of the index that must match this term */
- signed char nNear; /* term followed by a NEAR operator with span=(nNear-1) */
+ short int nNear; /* term followed by a NEAR operator with span=(nNear-1) */
signed char isOr; /* this term is preceded by "OR" */
signed char isNot; /* this term is preceded by "-" */
signed char isPrefix; /* this term is followed by "*" */
}
/*
-** Parse the text at pSegment[0..nSegment-1]. Add additional terms
+** Parse the text at zSegment[0..nSegment-1]. Add additional terms
** to the query being assemblied in pQuery.
**
-** inPhrase is true if pSegment[0..nSegement-1] is contained within
+** inPhrase is true if zSegment[0..nSegement-1] is contained within
** double-quotes. If inPhrase is true, then the first term
** is marked with the number of terms in the phrase less one and
** OR and "-" syntax is ignored. If inPhrase is false, then every
*/
static int tokenizeSegment(
sqlite3_tokenizer *pTokenizer, /* The tokenizer to use */
- const char *pSegment, int nSegment, /* Query expression being parsed */
+ const char *zSegment, int nSegment, /* Query expression being parsed */
int inPhrase, /* True if within "..." */
Query *pQuery /* Append results here */
){
int iCol;
int nTerm = 1;
- int rc = pModule->xOpen(pTokenizer, pSegment, nSegment, &pCursor);
+ int rc = pModule->xOpen(pTokenizer, zSegment, nSegment, &pCursor);
if( rc!=SQLITE_OK ) return rc;
pCursor->pTokenizer = pTokenizer;
while( 1 ){
- const char *pToken;
+ const char *zToken;
int nToken, iBegin, iEnd, iPos;
rc = pModule->xNext(pCursor,
- &pToken, &nToken,
+ &zToken, &nToken,
&iBegin, &iEnd, &iPos);
if( rc!=SQLITE_OK ) break;
if( !inPhrase &&
- pSegment[iEnd]==':' &&
- (iCol = checkColumnSpecifier(pQuery->pFts, pToken, nToken))>=0 ){
+ zSegment[iEnd]==':' &&
+ (iCol = checkColumnSpecifier(pQuery->pFts, zToken, nToken))>=0 ){
pQuery->nextColumn = iCol;
continue;
}
if( !inPhrase && pQuery->nTerms>0 && nToken==2
- && pSegment[iBegin+0]=='O'
- && pSegment[iBegin+1]=='R'
+ && zSegment[iBegin+0]=='O'
+ && zSegment[iBegin+1]=='R'
){
pQuery->nextIsOr = 1;
continue;
}
if( !inPhrase && pQuery->nTerms>0 && !pQuery->nextIsOr && nToken==4
- && pSegment[iBegin+0]=='N'
- && pSegment[iBegin+1]=='E'
- && pSegment[iBegin+2]=='A'
- && pSegment[iBegin+3]=='R'
+ && memcmp(&zSegment[iBegin], "NEAR", 4)==0
){
QueryTerm *pTerm = &pQuery->pTerms[pQuery->nTerms-1];
if( (iBegin+6)<nSegment
- && pSegment[iBegin+4] == '/'
- && pSegment[iBegin+5]>='0' && pSegment[iBegin+5]<='9'
+ && zSegment[iBegin+4] == '/'
+ && isdigit(zSegment[iBegin+5])
){
- pTerm->nNear = (pSegment[iBegin+5] - '0');
- nToken += 2;
- if( pSegment[iBegin+6]>='0' && pSegment[iBegin+6]<=9 ){
- pTerm->nNear = pTerm->nNear * 10 + (pSegment[iBegin+6] - '0');
- iEnd++;
+ int k;
+ pTerm->nNear = 0;
+ for(k=5; (iBegin+k)<=nSegment && isdigit(zSegment[iBegin+k]); k++){
+ pTerm->nNear = pTerm->nNear*10 + (zSegment[iBegin+k] - '0');
}
- pModule->xNext(pCursor, &pToken, &nToken, &iBegin, &iEnd, &iPos);
+ pModule->xNext(pCursor, &zToken, &nToken, &iBegin, &iEnd, &iPos);
} else {
pTerm->nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM;
}
continue;
}
- queryAdd(pQuery, pToken, nToken);
- if( !inPhrase && iBegin>0 && pSegment[iBegin-1]=='-' ){
+ queryAdd(pQuery, zToken, nToken);
+ if( !inPhrase && iBegin>0 && zSegment[iBegin-1]=='-' ){
pQuery->pTerms[pQuery->nTerms-1].isNot = 1;
}
- if( iEnd<nSegment && pSegment[iEnd]=='*' ){
+ if( iEnd<nSegment && zSegment[iEnd]=='*' ){
pQuery->pTerms[pQuery->nTerms-1].isPrefix = 1;
}
pQuery->pTerms[pQuery->nTerms-1].iPhrase = nTerm;
#ifndef SQLITE_CORE
- #include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#else
- #include "sqlite3.h"
#endif
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
** 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
);
/*
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);
}
/*
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);
}
/*
pIdxInfo->idxNum = 1;
pIdxInfo->aConstraintUsage[ii].argvIndex = 1;
pIdxInfo->aConstraintUsage[jj].omit = 1;
+
+ /* This strategy involves a two rowid lookups on an B-Tree structures
+ ** and then a linear search of an R-Tree node. This should be
+ ** considered almost as quick as a direct rowid lookup (for which
+ ** sqlite uses an internal cost of 0.0).
+ */
+ pIdxInfo->estimatedCost = 10.0;
return SQLITE_OK;
}
if( iIdx>0 && 0==(pIdxInfo->idxStr = sqlite3_mprintf("%s", zIdxStr)) ){
return SQLITE_NOMEM;
}
+ assert( iIdx>=0 );
+ pIdxInfo->estimatedCost = (2000000.0 / (double)(iIdx + 1));
return rc;
}
}
}
+/*
+** Return true if the area covered by p2 is a subset of the area covered
+** by p1. False otherwise.
+*/
+static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){
+ int ii;
+ int isInt = (pRtree->eCoordType==RTREE_COORD_INT32);
+ for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ RtreeCoord *a1 = &p1->aCoord[ii];
+ RtreeCoord *a2 = &p2->aCoord[ii];
+ if( (!isInt && (a2[0].f<a1[0].f || a2[1].f>a1[1].f))
+ || ( isInt && (a2[0].i<a1[0].i || a2[1].i>a1[1].i))
+ ){
+ return 0;
+ }
+ }
+ return 1;
+}
+
/*
** Return the amount cell p would grow by if it were unioned with pCell.
*/
int iCell = nodeParentIndex(pRtree, p);
nodeGetCell(pRtree, pParent, iCell, &cell);
- if( cellGrowth(pRtree, &cell, pCell)>0.0 ){
+ if( !cellContains(pRtree, &cell, pCell) ){
cellUnion(pRtree, &cell, pCell);
nodeOverwriteCell(pRtree, pParent, &cell, iCell);
}
*/
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 */
#ifndef SQLITE_CORE
- #include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#else
- #include "sqlite3.h"
#endif
/*
#endif
/************** End of icu.c *************************************************/
+/************** Begin file fts3_icu.c ****************************************/
+/*
+** 2007 June 22
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements a tokenizer for fts3 based on the ICU library.
+**
+** $Id$
+*/
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+#ifdef SQLITE_ENABLE_ICU
+
+
+#include <unicode/ubrk.h>
+#include <unicode/utf16.h>
+
+typedef struct IcuTokenizer IcuTokenizer;
+typedef struct IcuCursor IcuCursor;
+
+struct IcuTokenizer {
+ sqlite3_tokenizer base;
+ char *zLocale;
+};
+
+struct IcuCursor {
+ sqlite3_tokenizer_cursor base;
+
+ UBreakIterator *pIter; /* ICU break-iterator object */
+ int nChar; /* Number of UChar elements in pInput */
+ UChar *aChar; /* Copy of input using utf-16 encoding */
+ int *aOffset; /* Offsets of each character in utf-8 input */
+ int nBuffer;
+ char *zBuffer;
+
+ int iToken;
+};
+
+/*
+** Create a new tokenizer instance.
+*/
+static int icuCreate(
+ int argc, /* Number of entries in argv[] */
+ const char * const *argv, /* Tokenizer creation arguments */
+ sqlite3_tokenizer **ppTokenizer /* OUT: Created tokenizer */
+){
+ IcuTokenizer *p;
+ int n = 0;
+
+ if( argc>0 ){
+ n = strlen(argv[0])+1;
+ }
+ p = (IcuTokenizer *)sqlite3_malloc(sizeof(IcuTokenizer)+n);
+ if( !p ){
+ return SQLITE_NOMEM;
+ }
+ memset(p, 0, sizeof(IcuTokenizer));
+
+ if( n ){
+ p->zLocale = (char *)&p[1];
+ memcpy(p->zLocale, argv[0], n);
+ }
+
+ *ppTokenizer = (sqlite3_tokenizer *)p;
+
+ return SQLITE_OK;
+}
+
+/*
+** Destroy a tokenizer
+*/
+static int icuDestroy(sqlite3_tokenizer *pTokenizer){
+ IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
+ sqlite3_free(p);
+ return SQLITE_OK;
+}
+
+/*
+** Prepare to begin tokenizing a particular string. The input
+** string to be tokenized is pInput[0..nBytes-1]. A cursor
+** used to incrementally tokenize this string is returned in
+** *ppCursor.
+*/
+static int icuOpen(
+ sqlite3_tokenizer *pTokenizer, /* The tokenizer */
+ const char *zInput, /* Input string */
+ int nInput, /* Length of zInput in bytes */
+ sqlite3_tokenizer_cursor **ppCursor /* OUT: Tokenization cursor */
+){
+ IcuTokenizer *p = (IcuTokenizer *)pTokenizer;
+ IcuCursor *pCsr;
+
+ const int32_t opt = U_FOLD_CASE_DEFAULT;
+ UErrorCode status = U_ZERO_ERROR;
+ int nChar;
+
+ UChar32 c;
+ int iInput = 0;
+ int iOut = 0;
+
+ *ppCursor = 0;
+
+ if( nInput<0 ){
+ nInput = strlen(zInput);
+ }
+ nChar = nInput+1;
+ pCsr = (IcuCursor *)sqlite3_malloc(
+ sizeof(IcuCursor) + /* IcuCursor */
+ nChar * sizeof(UChar) + /* IcuCursor.aChar[] */
+ (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
+ );
+ if( !pCsr ){
+ return SQLITE_NOMEM;
+ }
+ memset(pCsr, 0, sizeof(IcuCursor));
+ pCsr->aChar = (UChar *)&pCsr[1];
+ pCsr->aOffset = (int *)&pCsr->aChar[nChar];
+
+ pCsr->aOffset[iOut] = iInput;
+ U8_NEXT(zInput, iInput, nInput, c);
+ while( c>0 ){
+ int isError = 0;
+ c = u_foldCase(c, opt);
+ U16_APPEND(pCsr->aChar, iOut, nChar, c, isError);
+ if( isError ){
+ sqlite3_free(pCsr);
+ return SQLITE_ERROR;
+ }
+ pCsr->aOffset[iOut] = iInput;
+
+ if( iInput<nInput ){
+ U8_NEXT(zInput, iInput, nInput, c);
+ }else{
+ c = 0;
+ }
+ }
+
+ pCsr->pIter = ubrk_open(UBRK_WORD, p->zLocale, pCsr->aChar, iOut, &status);
+ if( !U_SUCCESS(status) ){
+ sqlite3_free(pCsr);
+ return SQLITE_ERROR;
+ }
+ pCsr->nChar = iOut;
+
+ ubrk_first(pCsr->pIter);
+ *ppCursor = (sqlite3_tokenizer_cursor *)pCsr;
+ return SQLITE_OK;
+}
+
+/*
+** Close a tokenization cursor previously opened by a call to icuOpen().
+*/
+static int icuClose(sqlite3_tokenizer_cursor *pCursor){
+ IcuCursor *pCsr = (IcuCursor *)pCursor;
+ ubrk_close(pCsr->pIter);
+ sqlite3_free(pCsr->zBuffer);
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+/*
+** Extract the next token from a tokenization cursor.
+*/
+static int icuNext(
+ sqlite3_tokenizer_cursor *pCursor, /* Cursor returned by simpleOpen */
+ const char **ppToken, /* OUT: *ppToken is the token text */
+ int *pnBytes, /* OUT: Number of bytes in token */
+ int *piStartOffset, /* OUT: Starting offset of token */
+ int *piEndOffset, /* OUT: Ending offset of token */
+ int *piPosition /* OUT: Position integer of token */
+){
+ IcuCursor *pCsr = (IcuCursor *)pCursor;
+
+ int iStart = 0;
+ int iEnd = 0;
+ int nByte = 0;
+
+ while( iStart==iEnd ){
+ UChar32 c;
+
+ iStart = ubrk_current(pCsr->pIter);
+ iEnd = ubrk_next(pCsr->pIter);
+ if( iEnd==UBRK_DONE ){
+ return SQLITE_DONE;
+ }
+
+ while( iStart<iEnd ){
+ int iWhite = iStart;
+ U8_NEXT(pCsr->aChar, iWhite, pCsr->nChar, c);
+ if( u_isspace(c) ){
+ iStart = iWhite;
+ }else{
+ break;
+ }
+ }
+ assert(iStart<=iEnd);
+ }
+
+ do {
+ UErrorCode status = U_ZERO_ERROR;
+ if( nByte ){
+ char *zNew = sqlite3_realloc(pCsr->zBuffer, nByte);
+ if( !zNew ){
+ return SQLITE_NOMEM;
+ }
+ pCsr->zBuffer = zNew;
+ pCsr->nBuffer = nByte;
+ }
+
+ u_strToUTF8(
+ pCsr->zBuffer, pCsr->nBuffer, &nByte, /* Output vars */
+ &pCsr->aChar[iStart], iEnd-iStart, /* Input vars */
+ &status /* Output success/failure */
+ );
+ } while( nByte>pCsr->nBuffer );
+
+ *ppToken = pCsr->zBuffer;
+ *pnBytes = nByte;
+ *piStartOffset = pCsr->aOffset[iStart];
+ *piEndOffset = pCsr->aOffset[iEnd];
+ *piPosition = pCsr->iToken++;
+
+ return SQLITE_OK;
+}
+
+/*
+** The set of routines that implement the simple tokenizer
+*/
+static const sqlite3_tokenizer_module icuTokenizerModule = {
+ 0, /* iVersion */
+ icuCreate, /* xCreate */
+ icuDestroy, /* xCreate */
+ icuOpen, /* xOpen */
+ icuClose, /* xClose */
+ icuNext, /* xNext */
+};
+
+/*
+** Set *ppModule to point at the implementation of the ICU tokenizer.
+*/
+SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(
+ sqlite3_tokenizer_module const**ppModule
+){
+ *ppModule = &icuTokenizerModule;
+}
+
+#endif /* defined(SQLITE_ENABLE_ICU) */
+#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
+
+/************** End of fts3_icu.c ********************************************/
#if defined(_MSC_VER) && _MSC_VER < 1300
#pragma optimize("", on)
#endif
+