@@ -1,7 +1,7 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.0. By combining all the individual C code files into this
+** version 3.6.4. 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
** of 5% are more are commonly seen when SQLite is compiled as a single
@@ -10,15 +10,15 @@
** This file is all you need to compile SQLite. To use SQLite in other
** 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
-** 6137 lines past this header comment.) Additional code files may be
+** 6542 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-07-15 15:32:57 UTC.
+** This amalgamation was generated on 2008-11-01 20:35:33 UTC.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
@@ -40,9 +40,9 @@
**
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.742 2008/07/12 14:52:20 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.787 2008/10/28 18:58:20 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -252,9 +252,11 @@
#pragma warn -spa /* Suspicous pointer arithmetic */
#endif
/* Needed for various definitions... */
-#define _GNU_SOURCE
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
/*
** Include standard header files as necessary
*/
@@ -372,8 +374,18 @@
#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.
**
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
@@ -422,8 +434,11 @@
#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE
# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */
#endif
+/*
+** The TCL headers are only needed when compiling the TCL bindings.
+*/
#if defined(SQLITE_TCL) || defined(TCLSH)
# include <tcl.h>
#endif
@@ -471,9 +486,9 @@
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
-** @(#) $Id: sqlite.h.in,v 1.371 2008/07/14 18:38:17 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.406 2008/10/30 15:03:16 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h> /* Needed for the definition of va_list */
@@ -493,8 +508,24 @@
# define SQLITE_EXTERN extern
#endif
/*
+** These no-op macros are used in front of interfaces to mark those
+** interfaces as either deprecated or experimental. New applications
+** should not use deprecated intrfaces - they are support for backwards
+** compatibility only. Application writers should be aware that
+** experimental interfaces are subject to change in point releases.
+**
+** These macros used to resolve to various kinds of compiler magic that
+** would generate warning messages when they were used. But that
+** compiler magic ended up generating such a flurry of bug reports
+** that we have taken it all out and gone back to using simple
+** noop macros.
+*/
+#define SQLITE_DEPRECATED
+#define SQLITE_EXPERIMENTAL
+
+/*
** Ensure these symbols were not defined by some previous header file.
*/
#ifdef SQLITE_VERSION
# undef SQLITE_VERSION
@@ -503,9 +534,9 @@
# undef SQLITE_VERSION_NUMBER
#endif
/*
-** CAPI3REF: Compile-Time Library Version Numbers {F10010}
+** CAPI3REF: Compile-Time Library Version Numbers {H10010} <S60100>
**
** The SQLITE_VERSION and SQLITE_VERSION_NUMBER #defines in
** the sqlite3.h file specify the version of SQLite with which
** that header file is associated.
@@ -524,21 +555,21 @@
** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()].
**
** INVARIANTS:
**
-** {F10011} The SQLITE_VERSION #define in the sqlite3.h header file shall
+** {H10011} The SQLITE_VERSION #define in the sqlite3.h header file shall
** evaluate to a string literal that is the SQLite version
** with which the header file is associated.
**
-** {F10014} The SQLITE_VERSION_NUMBER #define shall resolve to an integer
+** {H10014} The SQLITE_VERSION_NUMBER #define shall resolve to an integer
** 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.0"
-#define SQLITE_VERSION_NUMBER 3006000
-
-/*
-** CAPI3REF: Run-Time Library Version Numbers {F10020}
+#define SQLITE_VERSION "3.6.4"
+#define SQLITE_VERSION_NUMBER 3006004
+
+/*
+** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
** KEYWORDS: sqlite3_version
**
** These features provide the same information as the [SQLITE_VERSION]
** and [SQLITE_VERSION_NUMBER] #defines in the header, but are associated
@@ -553,27 +584,28 @@
** constants within the DLL.
**
** INVARIANTS:
**
-** {F10021} The [sqlite3_libversion_number()] interface shall return
+** {H10021} The [sqlite3_libversion_number()] interface shall return
** an integer equal to [SQLITE_VERSION_NUMBER].
**
-** {F10022} The [sqlite3_version] string constant shall contain
+** {H10022} The [sqlite3_version] string constant shall contain
** the text of the [SQLITE_VERSION] string.
**
-** {F10023} The [sqlite3_libversion()] function shall return
+** {H10023} The [sqlite3_libversion()] function shall return
** a pointer to the [sqlite3_version] string constant.
*/
SQLITE_API const char sqlite3_version[];
SQLITE_API const char *sqlite3_libversion(void);
SQLITE_API int sqlite3_libversion_number(void);
/*
-** CAPI3REF: Test To See If The Library Is Threadsafe {F10100}
+** 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.
**
** Enabling mutexes incurs a measurable performance penalty.
@@ -593,26 +625,22 @@
** or [SQLITE_CONFIG_MUTEX]. The return value of this function shows
** only the default compile-time setting, not any run-time changes
** to that setting.
**
-** INVARIANTS:
-**
-** {F10101} 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.
-**
-** {F10102} 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.
+** See the [threading mode] documentation for additional information.
+**
+** INVARIANTS:
+**
+** {H10101} The [sqlite3_threadsafe()] function shall return zero if
+** and only if SQLite was compiled with mutexing code omitted.
+**
+** {H10102} The value returned by the [sqlite3_threadsafe()] function
+** shall remain the same across calls to [sqlite3_config()].
*/
SQLITE_API int sqlite3_threadsafe(void);
/*
-** CAPI3REF: Database Connection Handle {F12000}
+** CAPI3REF: Database Connection Handle {H12000} <S40200>
** KEYWORDS: {database connection} {database connections}
**
** Each open SQLite database is represented by a pointer to an instance of
** the opaque structure named "sqlite3". It is useful to think of an sqlite3
@@ -625,9 +653,9 @@
*/
typedef struct sqlite3 sqlite3;
/*
-** CAPI3REF: 64-Bit Integer Types {F10200}
+** CAPI3REF: 64-Bit Integer Types {H10200} <S10110>
** KEYWORDS: sqlite_int64 sqlite_uint64
**
** Because there is no cross-platform way to specify 64-bit integer types
** SQLite includes typedefs for 64-bit signed and unsigned integers.
@@ -637,12 +665,12 @@
** compatibility only.
**
** INVARIANTS:
**
-** {F10201} The [sqlite_int64] and [sqlite3_int64] type shall specify
+** {H10201} The [sqlite_int64] and [sqlite3_int64] type shall specify
** a 64-bit signed integer.
**
-** {F10202} The [sqlite_uint64] and [sqlite3_uint64] type shall specify
+** {H10202} The [sqlite_uint64] and [sqlite3_uint64] type shall specify
** a 64-bit unsigned integer.
*/
#ifdef SQLITE_INT64_TYPE
typedef SQLITE_INT64_TYPE sqlite_int64;
@@ -665,9 +693,9 @@
# define double sqlite3_int64
#endif
/*
-** CAPI3REF: Closing A Database Connection {F12010}
+** CAPI3REF: Closing A Database Connection {H12010} <S30100><S40200>
**
** This routine is the destructor for the [sqlite3] object.
**
** Applications should [sqlite3_finalize | finalize] all [prepared statements]
@@ -688,32 +716,32 @@
** the transaction is automatically rolled back.
**
** INVARIANTS:
**
-** {F12011} A successful call to [sqlite3_close(C)] shall destroy the
+** {H12011} A successful call to [sqlite3_close(C)] shall destroy the
** [database connection] object C.
**
-** {F12012} A successful call to [sqlite3_close(C)] shall return SQLITE_OK.
-**
-** {F12013} A successful call to [sqlite3_close(C)] shall release all
+** {H12012} A successful call to [sqlite3_close(C)] shall return SQLITE_OK.
+**
+** {H12013} A successful call to [sqlite3_close(C)] shall release all
** memory and system resources associated with [database connection]
** C.
**
-** {F12014} A call to [sqlite3_close(C)] on a [database connection] C that
+** {H12014} A call to [sqlite3_close(C)] on a [database connection] C that
** has one or more open [prepared statements] shall fail with
** an [SQLITE_BUSY] error code.
**
-** {F12015} A call to [sqlite3_close(C)] where C is a NULL pointer shall
-** return SQLITE_OK.
-**
-** {F12019} When [sqlite3_close(C)] is invoked on a [database connection] C
+** {H12015} A call to [sqlite3_close(C)] where C is a NULL pointer shall
+** 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
** rolled back.
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A12016} The C parameter to [sqlite3_close(C)] must be either a NULL
-** pointer or an [sqlite3] object pointer previously obtained
+** pointer or an [sqlite3] object pointer obtained
** from [sqlite3_open()], [sqlite3_open16()], or
** [sqlite3_open_v2()], and not previously closed.
*/
SQLITE_API int sqlite3_close(sqlite3 *);
@@ -725,9 +753,9 @@
*/
typedef int (*sqlite3_callback)(void*,int,char**, char**);
/*
-** CAPI3REF: One-Step Query Execution Interface {F12100}
+** CAPI3REF: One-Step Query Execution Interface {H12100} <S10000>
**
** The sqlite3_exec() interface is a convenient way of running one or more
** SQL statements without having to write a lot of C code. The UTF-8 encoded
** SQL statements are passed in as the second parameter to sqlite3_exec().
@@ -753,71 +781,73 @@
** by [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()].
**
** INVARIANTS:
**
-** {F12101} A successful invocation of [sqlite3_exec(D,S,C,A,E)]
+** {H12101} A successful invocation of [sqlite3_exec(D,S,C,A,E)]
** shall sequentially evaluate all of the UTF-8 encoded,
** semicolon-separated SQL statements in the zero-terminated
** string S within the context of the [database connection] D.
**
-** {F12102} If the S parameter to [sqlite3_exec(D,S,C,A,E)] is NULL then
+** {H12102} If the S parameter to [sqlite3_exec(D,S,C,A,E)] is NULL then
** the actions of the interface shall be the same as if the
** S parameter were an empty string.
**
-** {F12104} The return value of [sqlite3_exec()] shall be [SQLITE_OK] if all
+** {H12104} The return value of [sqlite3_exec()] shall be [SQLITE_OK] if all
** SQL statements run successfully and to completion.
**
-** {F12105} The return value of [sqlite3_exec()] shall be an appropriate
+** {H12105} The return value of [sqlite3_exec()] shall be an appropriate
** non-zero [error code] if any SQL statement fails.
**
-** {F12107} If one or more of the SQL statements handed to [sqlite3_exec()]
+** {H12107} If one or more of the SQL statements handed to [sqlite3_exec()]
** return results and the 3rd parameter is not NULL, then
** the callback function specified by the 3rd parameter shall be
** invoked once for each row of result.
**
-** {F12110} If the callback returns a non-zero value then [sqlite3_exec()]
+** {H12110} If the callback returns a non-zero value then [sqlite3_exec()]
** shall abort the SQL statement it is currently evaluating,
** skip all subsequent SQL statements, and return [SQLITE_ABORT].
**
-** {F12113} The [sqlite3_exec()] routine shall pass its 4th parameter through
+** {H12113} The [sqlite3_exec()] routine shall pass its 4th parameter through
** as the 1st parameter of the callback.
**
-** {F12116} The [sqlite3_exec()] routine shall set the 2nd parameter of its
+** {H12116} The [sqlite3_exec()] routine shall set the 2nd parameter of its
** callback to be the number of columns in the current row of
** result.
**
-** {F12119} The [sqlite3_exec()] routine shall set the 3rd parameter of its
+** {H12119} The [sqlite3_exec()] routine shall set the 3rd parameter of its
** callback to be an array of pointers to strings holding the
** values for each column in the current result set row as
** obtained from [sqlite3_column_text()].
**
-** {F12122} The [sqlite3_exec()] routine shall set the 4th parameter of its
+** {H12122} The [sqlite3_exec()] routine shall set the 4th parameter of its
** callback to be an array of pointers to strings holding the
** names of result columns as obtained from [sqlite3_column_name()].
**
-** {F12125} If the 3rd parameter to [sqlite3_exec()] is NULL then
+** {H12125} If the 3rd parameter to [sqlite3_exec()] is NULL then
** [sqlite3_exec()] shall silently discard query results.
**
-** {F12131} If an error occurs while parsing or evaluating any of the SQL
+** {H12131} If an error occurs while parsing or evaluating any of the SQL
** statements in the S parameter of [sqlite3_exec(D,S,C,A,E)] and if
** the E parameter is not NULL, then [sqlite3_exec()] shall store
** in *E an appropriate error message written into memory obtained
** from [sqlite3_malloc()].
**
-** {F12134} The [sqlite3_exec(D,S,C,A,E)] routine shall set the value of
+** {H12134} The [sqlite3_exec(D,S,C,A,E)] routine shall set the value of
** *E to NULL if E is not NULL and there are no errors.
**
-** {F12137} The [sqlite3_exec(D,S,C,A,E)] function shall set the [error code]
+** {H12137} The [sqlite3_exec(D,S,C,A,E)] function shall set the [error code]
** and message accessible via [sqlite3_errcode()],
+** [sqlite3_extended_errcode()],
** [sqlite3_errmsg()], and [sqlite3_errmsg16()].
**
-** {F12138} If the S parameter to [sqlite3_exec(D,S,C,A,E)] is NULL or an
+** {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.
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A12141} The first parameter to [sqlite3_exec()] must be an valid and open
** [database connection].
**
@@ -839,9 +869,9 @@
char **errmsg /* Error msg written here */
);
/*
-** CAPI3REF: Result Codes {F10210}
+** CAPI3REF: Result Codes {H10210} <S10700>
** KEYWORDS: SQLITE_OK {error code} {error codes}
** KEYWORDS: {result code} {result codes}
**
** Many SQLite functions return an integer result code from the set shown
@@ -883,9 +913,9 @@
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
/* end-of-error-codes */
/*
-** CAPI3REF: Extended Result Codes {F10220}
+** CAPI3REF: Extended Result Codes {H10220} <S10700>
** KEYWORDS: {extended error code} {extended error codes}
** KEYWORDS: {extended result code} {extended result codes}
**
** In its default configuration, SQLite API routines return one of 26 integer
@@ -907,16 +937,16 @@
** be exactly zero.
**
** INVARIANTS:
**
-** {F10223} The symbolic name for an extended result code shall contains
+** {H10223} The symbolic name for an extended result code shall contains
** a related primary result code as a prefix.
**
-** {F10224} Primary result code names shall contain a single "_" character.
-**
-** {F10225} Extended result code names shall contain two or more "_" characters.
-**
-** {F10226} The numeric value of an extended result code shall contain the
+** {H10224} Primary result code names shall contain a single "_" character.
+**
+** {H10225} Extended result code names shall contain two or more "_" characters.
+**
+** {H10226} The numeric value of an extended result code shall contain the
** numeric value of its corresponding primary result code in
** its least significant 8 bits.
*/
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
@@ -932,11 +962,12 @@
#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8))
#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8))
#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8))
#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
-
-/*
-** CAPI3REF: Flags For File Open Operations {F10230}
+#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
+
+/*
+** CAPI3REF: Flags For File Open Operations {H10230} <H11120> <H12700>
**
** These bit values are intended for use in the
** 3rd parameter to the [sqlite3_open_v2()] interface and
** in the 4th parameter to the xOpen method of the
@@ -954,11 +985,12 @@
#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000
#define SQLITE_OPEN_SUBJOURNAL 0x00002000
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000
#define SQLITE_OPEN_NOMUTEX 0x00008000
-
-/*
-** CAPI3REF: Device Characteristics {F10240}
+#define SQLITE_OPEN_FULLMUTEX 0x00010000
+
+/*
+** CAPI3REF: Device Characteristics {H10240} <H11120>
**
** The xDeviceCapabilities method of the [sqlite3_io_methods]
** object returns an integer which is a vector of the these
** bit values expressing I/O characteristics of the mass storage
@@ -988,9 +1020,9 @@
#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
/*
-** CAPI3REF: File Locking Levels {F10250}
+** CAPI3REF: File Locking Levels {H10250} <H11120> <H11310>
**
** SQLite uses one of these integer values as the second
** argument to calls it makes to the xLock() and xUnlock() methods
** of an [sqlite3_io_methods] object.
@@ -1001,9 +1033,9 @@
#define SQLITE_LOCK_PENDING 3
#define SQLITE_LOCK_EXCLUSIVE 4
/*
-** CAPI3REF: Synchronization Type Flags {F10260}
+** CAPI3REF: Synchronization Type Flags {H10260} <H11120>
**
** When SQLite invokes the xSync() method of an
** [sqlite3_io_methods] object it uses a combination of
** these integer values as the second argument.
@@ -1018,9 +1050,9 @@
#define SQLITE_SYNC_FULL 0x00003
#define SQLITE_SYNC_DATAONLY 0x00010
/*
-** CAPI3REF: OS Interface Open File Handle {F11110}
+** CAPI3REF: OS Interface Open File Handle {H11110} <S20110>
**
** An [sqlite3_file] object represents an open file in the OS
** interface layer. Individual OS interface implementations will
** want to subclass this object by appending additional fields
@@ -1033,9 +1065,9 @@
const struct sqlite3_io_methods *pMethods; /* Methods for an open file */
};
/*
-** CAPI3REF: OS Interface File Virtual Methods Object {F11120}
+** CAPI3REF: OS Interface File Virtual Methods Object {H11120} <S20110>
**
** Every file opened by the [sqlite3_vfs] xOpen method populates an
** [sqlite3_file] object (or, more commonly, a subclass of the
** [sqlite3_file] object) with a pointer to an instance of this object.
@@ -1126,9 +1158,9 @@
/* Additional methods may be added in future releases */
};
/*
-** CAPI3REF: Standard File Control Opcodes {F11310}
+** CAPI3REF: Standard File Control Opcodes {H11310} <S30800>
**
** These integer constants are opcodes for the xFileControl method
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
** interface.
@@ -1143,9 +1175,9 @@
*/
#define SQLITE_FCNTL_LOCKSTATE 1
/*
-** CAPI3REF: Mutex Handle {F17110}
+** CAPI3REF: Mutex Handle {H17110} <S20130>
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object. The SQLite core never looks
** at the internal representation of an [sqlite3_mutex]. It only
@@ -1155,9 +1187,9 @@
*/
typedef struct sqlite3_mutex sqlite3_mutex;
/*
-** CAPI3REF: OS Interface Object {F11140}
+** CAPI3REF: OS Interface Object {H11140} <S20100>
**
** An instance of the sqlite3_vfs object defines the interface between
** the SQLite core and the underlying operating system. The "vfs"
** in the name of the object stands for "virtual file system".
@@ -1188,28 +1220,28 @@
**
** The zName field holds the name of the VFS module. The name must
** be unique across all VFS modules.
**
-** {F11141} SQLite will guarantee that the zFilename parameter to xOpen
+** {H11141} SQLite will guarantee that the zFilename parameter to xOpen
** is either a NULL pointer or string obtained
** from xFullPathname(). SQLite further guarantees that
** the string will be valid and unchanged until xClose() is
-** called. {END} Becasue of the previous sentense,
+** called. {END} Because of the previous sentense,
** the [sqlite3_file] can safely store a pointer to the
** filename if it needs to remember the filename for some reason.
** If the zFilename parameter is xOpen is a NULL pointer then xOpen
** must invite its own temporary name for the file. Whenever the
** xFilename parameter is NULL it will also be the case that the
** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
**
-** {F11142} The flags argument to xOpen() includes all bits set in
+** {H11142} The flags argument to xOpen() includes all bits set in
** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
** or [sqlite3_open16()] is used, then flags includes at least
** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END}
** If xOpen() opens a file read-only then it sets *pOutFlags to
** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
**
-** {F11143} SQLite will also add one of the following flags to the xOpen()
+** {H11143} SQLite will also add one of the following flags to the xOpen()
** call, depending on the object being opened:
**
** <ul>
** <li> [SQLITE_OPEN_MAIN_DB]
@@ -1236,29 +1268,29 @@
** <li> [SQLITE_OPEN_DELETEONCLOSE]
** <li> [SQLITE_OPEN_EXCLUSIVE]
** </ul>
**
-** {F11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
-** deleted when it is closed. {F11146} The [SQLITE_OPEN_DELETEONCLOSE]
+** {H11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
+** deleted when it is closed. {H11146} The [SQLITE_OPEN_DELETEONCLOSE]
** will be set for TEMP databases, journals and for subjournals.
**
-** {F11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened
+** {H11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened
** for exclusive access. This flag is set for all files except
** for the main database file.
**
-** {F11148} At least szOsFile bytes of memory are allocated by SQLite
+** {H11148} At least szOsFile bytes of memory are allocated by SQLite
** to hold the [sqlite3_file] structure passed as the third
** argument to xOpen. {END} The xOpen method does not have to
** allocate the structure; it should just fill it in.
**
-** {F11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
+** {H11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
** to test whether a file is at least readable. {END} The file can be a
** directory.
**
-** {F11150} SQLite will always allocate at least mxPathname+1 bytes for the
-** output buffer xFullPathname. {F11151} The exact size of the output buffer
+** {H11150} SQLite will always allocate at least mxPathname+1 bytes for the
+** output buffer xFullPathname. {H11151} The exact size of the output buffer
** is also passed as a parameter to both methods. {END} If the output buffer
** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is
** handled as a fatal error by SQLite, vfs implementations should endeavor
** to prevent this by setting mxPathname to a sufficiently large value.
@@ -1298,26 +1330,26 @@
** value will increment whenever this happens. */
};
/*
-** CAPI3REF: Flags for the xAccess VFS method {F11190}
-**
-** {F11191} These integer constants can be used as the third parameter to
+** CAPI3REF: Flags for the xAccess VFS method {H11190} <H11140>
+**
+** {H11191} These integer constants can be used as the third parameter to
** the xAccess method of an [sqlite3_vfs] object. {END} They determine
** what kind of permissions the xAccess method is looking for.
-** {F11192} With SQLITE_ACCESS_EXISTS, the xAccess method
+** {H11192} With SQLITE_ACCESS_EXISTS, the xAccess method
** simply checks whether the file exists.
-** {F11193} With SQLITE_ACCESS_READWRITE, the xAccess method
+** {H11193} With SQLITE_ACCESS_READWRITE, the xAccess method
** checks whether the file is both readable and writable.
-** {F11194} With SQLITE_ACCESS_READ, the xAccess method
+** {H11194} With SQLITE_ACCESS_READ, the xAccess method
** checks whether the file is readable.
*/
#define SQLITE_ACCESS_EXISTS 0
#define SQLITE_ACCESS_READWRITE 1
#define SQLITE_ACCESS_READ 2
/*
-** CAPI3REF: Initialize The SQLite Library {F10130}
+** CAPI3REF: Initialize The SQLite Library {H10130} <S20000><S30100>
**
** The sqlite3_initialize() routine initializes the
** SQLite library. The sqlite3_shutdown() routine
** deallocates any resources that were allocated by sqlite3_initialize().
@@ -1332,26 +1364,26 @@
** Among other things, sqlite3_initialize() shall invoke
** 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
** initialization of the SQLite library. The sqlite3_os_end()
@@ -1367,13 +1399,13 @@
** interface is called automatically by sqlite3_initialize() and
** 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_shutdown(void);
@@ -1380,9 +1412,10 @@
SQLITE_API int sqlite3_os_init(void);
SQLITE_API int sqlite3_os_end(void);
/*
-** CAPI3REF: Configuring The SQLite Library {F10145}
+** CAPI3REF: Configuring The SQLite Library {H14100} <S20000><S30200>
+** EXPERIMENTAL
**
** The sqlite3_config() interface is used to make global configuration
** changes to SQLite in order to tune SQLite to the specific needs of
** the application. The default configuration is recommended for most
@@ -1402,16 +1435,159 @@
** what property of SQLite is to be configured. Subsequent arguments
** 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].
-*/
-SQLITE_API int sqlite3_config(int, ...);
-
-/*
-** CAPI3REF: Memory Allocation Routines {F10155}
+**
+** INVARIANTS:
+**
+** {H14103} A successful invocation of [sqlite3_config()] shall return
+** [SQLITE_OK].
+**
+** {H14106} The [sqlite3_config()] interface shall return [SQLITE_MISUSE]
+** if it is invoked in between calls to [sqlite3_initialize()] and
+** [sqlite3_shutdown()].
+**
+** {H14120} A successful call to [sqlite3_config]([SQLITE_CONFIG_SINGLETHREAD])
+** shall set the default [threading mode] to Single-thread.
+**
+** {H14123} A successful call to [sqlite3_config]([SQLITE_CONFIG_MULTITHREAD])
+** shall set the default [threading mode] to Multi-thread.
+**
+** {H14126} A successful call to [sqlite3_config]([SQLITE_CONFIG_SERIALIZED])
+** shall set the default [threading mode] to Serialized.
+**
+** {H14129} A successful call to [sqlite3_config]([SQLITE_CONFIG_MUTEX],X)
+** where X is a pointer to an initialized [sqlite3_mutex_methods]
+** object shall cause all subsequent mutex operations performed
+** by SQLite to use the mutex methods that were present in X
+** during the call to [sqlite3_config()].
+**
+** {H14132} A successful call to [sqlite3_config]([SQLITE_CONFIG_GETMUTEX],X)
+** where X is a pointer to an [sqlite3_mutex_methods] object
+** shall overwrite the content of [sqlite3_mutex_methods] object
+** with the mutex methods currently in use by SQLite.
+**
+** {H14135} A successful call to [sqlite3_config]([SQLITE_CONFIG_MALLOC],M)
+** where M is a pointer to an initialized [sqlite3_mem_methods]
+** object shall cause all subsequent memory allocation operations
+** performed by SQLite to use the methods that were present in
+** M during the call to [sqlite3_config()].
+**
+** {H14138} A successful call to [sqlite3_config]([SQLITE_CONFIG_GETMALLOC],M)
+** where M is a pointer to an [sqlite3_mem_methods] object shall
+** overwrite the content of [sqlite3_mem_methods] object with
+** the memory allocation methods currently in use by
+** SQLite.
+**
+** {H14141} A successful call to [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],1)
+** shall enable the memory allocation status collection logic.
+**
+** {H14144} A successful call to [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],0)
+** shall disable the memory allocation status collection logic.
+**
+** {H14147} The memory allocation status collection logic shall be
+** enabled by default.
+**
+** {H14150} A successful call to [sqlite3_config]([SQLITE_CONFIG_SCRATCH],S,Z,N)
+** where Z and N are non-negative integers and
+** S is a pointer to an aligned memory buffer not less than
+** Z*N bytes in size shall cause S to be used by the
+** [scratch memory allocator] for as many as N simulataneous
+** allocations each of size Z.
+**
+** {H14153} A successful call to [sqlite3_config]([SQLITE_CONFIG_SCRATCH],S,Z,N)
+** where S is a NULL pointer shall disable the
+** [scratch memory allocator].
+**
+** {H14156} A successful call to
+** [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],S,Z,N)
+** where Z and N are non-negative integers and
+** S is a pointer to an aligned memory buffer not less than
+** Z*N bytes in size shall cause S to be used by the
+** [pagecache memory allocator] for as many as N simulataneous
+** allocations each of size Z.
+**
+** {H14159} A successful call to
+** [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],S,Z,N)
+** where S is a NULL pointer shall disable the
+** [pagecache memory allocator].
+**
+** {H14162} A successful call to [sqlite3_config]([SQLITE_CONFIG_HEAP],H,Z,N)
+** where Z and N are non-negative integers and
+** H is a pointer to an aligned memory buffer not less than
+** Z bytes in size shall enable the [memsys5] memory allocator
+** and cause it to use buffer S as its memory source and to use
+** a minimum allocation size of N.
+**
+** {H14165} A successful call to [sqlite3_config]([SQLITE_CONFIG_HEAP],H,Z,N)
+** where H is a NULL pointer shall disable the
+** [memsys5] memory allocator.
+**
+** {H14168} A successful call to [sqlite3_config]([SQLITE_CONFIG_LOOKASIDE],Z,N)
+** shall cause the default [lookaside memory allocator] configuration
+** for new [database connections] to be N slots of Z bytes each.
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
+
+/*
+** CAPI3REF: Configure database connections {H14200} <S20000>
+** EXPERIMENTAL
+**
+** The sqlite3_db_config() interface is used to make configuration
+** changes to a [database connection]. The interface is similar to
+** [sqlite3_config()] except that the changes apply to a single
+** [database connection] (specified in the first argument). The
+** sqlite3_db_config() interface can only be used immediately after
+** the database connection is created using [sqlite3_open()],
+** [sqlite3_open16()], or [sqlite3_open_v2()].
+**
+** The second argument to sqlite3_db_config(D,V,...) is the
+** configuration verb - an integer code that indicates what
+** aspect of the [database connection] is being configured.
+** 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, ...);
+
+/*
+** CAPI3REF: Memory Allocation Routines {H10155} <S20120>
+** EXPERIMENTAL
**
** An instance of this object defines the interface between SQLite
** and low-level memory allocation routines.
**
@@ -1463,12 +1639,20 @@
void *pAppData; /* Argument to xInit() and xShutdown() */
};
/*
-** CAPI3REF: Configuration Options {F10160}
+** CAPI3REF: Configuration Options {H10160} <S20000>
+** EXPERIMENTAL
**
** These constants are the available integer configuration options that
** can be passed as the first argument to the [sqlite3_config()] interface.
+**
+** New configuration options may be added in future releases of SQLite.
+** Existing configuration options might be discontinued. Applications
+** should check the return code from [sqlite3_config()] to make sure that
+** the call worked. The [sqlite3_config()] interface will return a
+** non-zero [error code] if a discontinued or unsupported configuration option
+** is invoked.
**
** <dl>
** <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
** <dd>There are no arguments to this option. This option disables
@@ -1480,9 +1664,11 @@
** mutexing on [database connection] and [prepared statement] objects.
** 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
** all mutexes including the recursive
@@ -1491,13 +1677,9 @@
** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access
** 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
** instance of the [sqlite3_mem_methods] structure. The argument specifies
@@ -1512,25 +1694,28 @@
** routines with a wrapper that simulations memory allocation failure or
** tracks memory usage, for example.</dd>
**
** <dt>SQLITE_CONFIG_MEMSTATUS</dt>
-** <dd>This option takes single boolean argument which enables or disables
-** the collection of memory allocation statistics. When disabled, the
-** following SQLite interfaces become non-operational:
+** <dd>This option takes single argument of type int, interpreted as a
+** boolean, which enables or disables the collection of memory allocation
+** statistics. When disabled, the following SQLite interfaces become
+** non-operational:
** <ul>
** <li> [sqlite3_memory_used()]
** <li> [sqlite3_memory_highwater()]
** <li> [sqlite3_soft_heap_limit()]
-** <li> sqlite3_memory_status()
+** <li> [sqlite3_status()]
** </ul>
** </dd>
**
** <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd>This option specifies a static memory buffer that SQLite can use for
** scratch memory. There are three arguments: A pointer to the memory, the
** size of each scratch buffer (sz), and the number of buffers (N). The sz
-** argument must be a multiple of 16. The first
-** argument should point to an allocation of at least (sz+4)*N bytes of memory.
+** argument must be a multiple of 16. The sz parameter should be a few bytes
+** larger than the actual scratch space required due internal overhead.
+** The first
+** argument should point to an allocation of at least sz*N bytes of memory.
** SQLite will use no more than one scratch buffer at once per thread, so
** N should be set to the expected maximum number of threads. The sz
** parameter should be 6 times the size of the largest database page size.
** Scratch buffers are used as part of the btree balance operation. If
@@ -1542,13 +1727,15 @@
** <dd>This option specifies a static memory buffer that SQLite can use for
** the database page cache. There are three arguments: A pointer to the
** memory, the size of each page buffer (sz), and the number of pages (N).
** The sz argument must be a power of two between 512 and 32768. The first
-** argument should point to an allocation of at least (sz+4)*N bytes of memory.
+** argument should point to an allocation of at least sz*N bytes of memory.
** SQLite will use the memory provided by the first argument to satisfy its
** memory needs for the first N pages that it adds to cache. If additional
** page cache memory is needed beyond what is provided by this option, then
-** SQLite goes to [sqlite3_malloc()] for the additional storage space.</dd>
+** SQLite goes to [sqlite3_malloc()] for the additional storage space.
+** The implementation might use one or more of the N buffers to hold
+** memory accounting information. </dd>
**
** <dt>SQLITE_CONFIG_HEAP</dt>
** <dd>This option specifies a static memory buffer that SQLite will use
** for all of its dynamic memory allocation needs beyond those provided
@@ -1575,8 +1762,16 @@
** structure is filled with the currently defined mutex routines.
** This option can be used to overload the default mutex allocation
** routines with a wrapper used to track mutex usage for performance
** profiling or testing, for example.</dd>
+**
+** <dt>SQLITE_CONFIG_LOOKASIDE</dt>
+** <dd>This option takes two arguments that determine the default
+** memory allcation lookaside optimization. The first argument is the
+** size of each lookaside buffer slot and the second is the number of
+** slots allocated to each database connection.</dd>
+**
+** </dl>
*/
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
@@ -1587,30 +1782,62 @@
#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
-
-
-/*
-** CAPI3REF: Enable Or Disable Extended Result Codes {F12200}
+#define SQLITE_CONFIG_CHUNKALLOC 12 /* int threshold */
+#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
+
+/*
+** CAPI3REF: Configuration Options {H10170} <S20000>
+** EXPERIMENTAL
+**
+** These constants are the available integer configuration options that
+** can be passed as the second argument to the [sqlite3_db_config()] interface.
+**
+** New configuration options may be added in future releases of SQLite.
+** Existing configuration options might be discontinued. Applications
+** should check the return code from [sqlite3_db_config()] to make sure that
+** the call worked. The [sqlite3_db_config()] interface will return a
+** non-zero [error code] if a discontinued or unsupported configuration option
+** is invoked.
+**
+** <dl>
+** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
+** <dd>This option takes three additional arguments that determine the
+** [lookaside memory allocator] configuration for the [database connection].
+** The first argument (the third parameter to [sqlite3_db_config()] is a
+** pointer to a memory buffer to use for lookaside memory. The first
+** argument may be NULL in which case SQLite will allocate the lookaside
+** buffer itself using [sqlite3_malloc()]. The second argument is the
+** size of each lookaside buffer slot and the third argument is the number of
+** slots. The size of the buffer in the first argument must be greater than
+** or equal to the product of the second and third arguments.</dd>
+**
+** </dl>
+*/
+#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
+
+
+/*
+** CAPI3REF: Enable Or Disable Extended Result Codes {H12200} <S10700>
**
** The sqlite3_extended_result_codes() routine enables or disables the
** [extended result codes] feature of SQLite. The extended result
** codes are disabled by default for historical compatibility considerations.
**
** INVARIANTS:
**
-** {F12201} Each new [database connection] shall have the
+** {H12201} Each new [database connection] shall have the
** [extended result codes] feature disabled by default.
**
-** {F12202} The [sqlite3_extended_result_codes(D,F)] interface shall enable
+** {H12202} The [sqlite3_extended_result_codes(D,F)] interface shall enable
** [extended result codes] for the [database connection] D
** if the F parameter is true, or disable them if F is false.
*/
SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
/*
-** CAPI3REF: Last Insert Rowid {F12220}
+** CAPI3REF: Last Insert Rowid {H12220} <S10700>
**
** Each entry in an SQLite table has a unique 64-bit signed
** integer key called the "rowid". The rowid is always available
** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
@@ -1618,19 +1845,19 @@
** the table has a column of type INTEGER PRIMARY KEY then that column
** 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
** encounters a constraint violation, it does not fail. The
@@ -1637,25 +1864,26 @@
** INSERT continues to completion after deleting rows that caused
** 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:
**
-** {F12221} 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.
-**
-** {F12223} The [sqlite3_last_insert_rowid()] function returns the
+** trigger context, or zero if there have been no qualifying
+** [INSERT] statements.
+**
+** {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.
-**
-** LIMITATIONS:
-**
-** {A12232} If a separate thread performs a new INSERT on the same
+** immediately before and after a [ROLLBACK].
+**
+** ASSUMPTIONS:
+**
+** {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
** unpredictable and might not equal either the old or the new
@@ -1663,15 +1891,15 @@
*/
SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
/*
-** CAPI3REF: Count The Number Of Rows Modified {F12240}
+** CAPI3REF: Count The Number Of Rows Modified {H12240} <S10600>
**
** 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.
**
** A "row change" is a change to a single row of a single table
@@ -1703,30 +1931,32 @@
** However, the number returned does not include changes
** 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.
-**
-** INVARIANTS:
-**
-** {F12241} The [sqlite3_changes()] function shall return the number of
+** "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:
+**
+** {H12241} The [sqlite3_changes()] function shall return the number of
** row changes caused by the most recent INSERT, UPDATE,
** or DELETE statement on the same database connection and
** within the same or higher trigger context, or zero if there have
** not been any qualifying row changes.
**
-** {F12243} Statements of the form "DELETE FROM tablename" with no
+** {H12243} Statements of the form "DELETE FROM tablename" with no
** WHERE clause shall cause subsequent calls to
** [sqlite3_changes()] to return zero, regardless of the
** number of rows originally in the table.
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A12252} If a separate thread makes changes on the same database connection
** while [sqlite3_changes()] is running then the value returned
** is unpredictable and not meaningful.
@@ -1733,9 +1963,9 @@
*/
SQLITE_API int sqlite3_changes(sqlite3*);
/*
-** CAPI3REF: Total Number Of Rows Modified {F12260}
+** CAPI3REF: Total Number Of Rows Modified {H12260} <S10600>
**
** This function returns the number of row changes caused by INSERT,
** UPDATE or DELETE statements since the [database connection] was opened.
** The count includes all changes from all trigger contexts. However,
@@ -1751,24 +1981,26 @@
** 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.
**
** See also the [sqlite3_changes()] interface.
**
** INVARIANTS:
**
-** {F12261} The [sqlite3_total_changes()] returns the total number
+** {H12261} The [sqlite3_total_changes()] returns the total number
** of row changes caused by INSERT, UPDATE, and/or DELETE
** statements on the same [database connection], in any
** trigger context, since the database connection was created.
**
-** {F12263} Statements of the form "DELETE FROM tablename" with no
+** {H12263} Statements of the form "DELETE FROM tablename" with no
** WHERE clause shall not change the value returned
** by [sqlite3_total_changes()].
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A12264} If a separate thread makes changes on the same database connection
** while [sqlite3_total_changes()] is running then the value
** returned is unpredictable and not meaningful.
@@ -1775,9 +2007,9 @@
*/
SQLITE_API int sqlite3_total_changes(sqlite3*);
/*
-** CAPI3REF: Interrupt A Long-Running Query {F12270}
+** CAPI3REF: Interrupt A Long-Running Query {H12270} <S30500>
**
** This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically
** called in response to a user action such as pressing "Cancel"
@@ -1802,24 +2034,24 @@
** that are started after sqlite3_interrupt() returns.
**
** INVARIANTS:
**
-** {F12271} The [sqlite3_interrupt()] interface will force all running
+** {H12271} The [sqlite3_interrupt()] interface will force all running
** SQL statements associated with the same database connection
** to halt after processing at most one additional row of data.
**
-** {F12272} Any SQL statement that is interrupted by [sqlite3_interrupt()]
+** {H12272} Any SQL statement that is interrupted by [sqlite3_interrupt()]
** will return [SQLITE_INTERRUPT].
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A12279} If the database connection closes while [sqlite3_interrupt()]
** is running then bad things will likely happen.
*/
SQLITE_API void sqlite3_interrupt(sqlite3*);
/*
-** CAPI3REF: Determine If An SQL Statement Is Complete {F10510}
+** CAPI3REF: Determine If An SQL Statement Is Complete {H10510} <S70200>
**
** These routines are useful for command-line input to determine if the
** currently entered text seems to form complete a SQL statement or
** if additional input is needed before sending the text into
@@ -1835,19 +2067,19 @@
** will not detect syntactically incorrect SQL.
**
** INVARIANTS:
**
-** {F10511} A successful evaluation of [sqlite3_complete()] or
+** {H10511} A successful evaluation of [sqlite3_complete()] or
** [sqlite3_complete16()] functions shall
** return a numeric 1 if and only if the last non-whitespace
** token in their input is a semicolon that is not in between
** the BEGIN and END of a CREATE TRIGGER statement.
**
-** {F10512} If a memory allocation error occurs during an invocation
+** {H10512} If a memory allocation error occurs during an invocation
** of [sqlite3_complete()] or [sqlite3_complete16()] then the
** routine shall return [SQLITE_NOMEM].
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A10512} The input to [sqlite3_complete()] must be a zero-terminated
** UTF-8 string.
**
@@ -1857,9 +2089,9 @@
SQLITE_API int sqlite3_complete(const char *sql);
SQLITE_API int sqlite3_complete16(const void *sql);
/*
-** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {F12310}
+** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors {H12310} <S40400>
**
** This routine sets a callback function that might be invoked whenever
** an attempt is made to open a database table that another thread
** or process has locked.
@@ -1913,44 +2145,48 @@
** [database connection]. Setting a new busy handler clears any
** previously set handler. Note that calling [sqlite3_busy_timeout()]
** will also set or clear the busy handler.
**
-** INVARIANTS:
-**
-** {F12311} The [sqlite3_busy_handler(D,C,A)] function shall replace
+** 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
** busy callback in the [database connection] D with a new
** a new busy handler C and application data pointer A.
**
-** {F12312} Newly created [database connections] shall have a busy
+** {H12312} Newly created [database connections] shall have a busy
** handler of NULL.
**
-** {F12314} When two or more [database connections] share a
+** {H12314} When two or more [database connections] share a
** [sqlite3_enable_shared_cache | common cache],
** the busy handler for the database connection currently using
** the cache shall be invoked when the cache encounters a lock.
**
-** {F12316} If a busy handler callback returns zero, then the SQLite interface
+** {H12316} If a busy handler callback returns zero, then the SQLite interface
** that provoked the locking event shall return [SQLITE_BUSY].
**
-** {F12318} SQLite shall invokes the busy handler with two arguments which
+** {H12318} SQLite shall invokes the busy handler with two arguments which
** are a copy of the pointer supplied by the 3rd parameter to
** [sqlite3_busy_handler()] and a count of the number of prior
** invocations of the busy handler for the same locking event.
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A12319} A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
/*
-** CAPI3REF: Set A Busy Timeout {F12340}
+** CAPI3REF: Set A Busy Timeout {H12340} <S40410>
**
** This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked. The handler
** will sleep multiple times until at least "ms" milliseconds of sleeping
-** have accumulated. {F12343} After "ms" milliseconds of sleeping,
+** have accumulated. {H12343} After "ms" milliseconds of sleeping,
** the handler returns 0 which causes [sqlite3_step()] to return
** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
**
** Calling this routine with an argument less than or equal to zero
@@ -1962,17 +2198,17 @@
** this routine, that other busy handler is cleared.
**
** INVARIANTS:
**
-** {F12341} The [sqlite3_busy_timeout()] function shall override any prior
+** {H12341} The [sqlite3_busy_timeout()] function shall override any prior
** [sqlite3_busy_timeout()] or [sqlite3_busy_handler()] setting
** on the same [database connection].
**
-** {F12343} If the 2nd parameter to [sqlite3_busy_timeout()] is less than
+** {H12343} If the 2nd parameter to [sqlite3_busy_timeout()] is less than
** or equal to zero, then the busy handler shall be cleared so that
** all subsequent locking events immediately return [SQLITE_BUSY].
**
-** {F12344} If the 2nd parameter to [sqlite3_busy_timeout()] is a positive
+** {H12344} If the 2nd parameter to [sqlite3_busy_timeout()] is a positive
** number N, then a busy handler shall be set that repeatedly calls
** the xSleep() method in the [sqlite3_vfs | VFS interface] until
** either the lock clears or until the cumulative sleep time
** reported back by xSleep() exceeds N milliseconds.
@@ -1979,9 +2215,9 @@
*/
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
/*
-** CAPI3REF: Convenience Routines For Running Queries {F12370}
+** CAPI3REF: Convenience Routines For Running Queries {H12370} <S10000>
**
** Definition: A <b>result table</b> is memory data structure created by the
** [sqlite3_get_table()] interface. A result table records the
** complete query results from one or more queries.
@@ -2048,34 +2284,34 @@
** reflected in subsequent calls to [sqlite3_errcode()] or [sqlite3_errmsg()].
**
** INVARIANTS:
**
-** {F12371} If a [sqlite3_get_table()] fails a memory allocation, then
+** {H12371} If a [sqlite3_get_table()] fails a memory allocation, then
** it shall free the result table under construction, abort the
** query in process, skip any subsequent queries, set the
** *pazResult output pointer to NULL and return [SQLITE_NOMEM].
**
-** {F12373} If the pnColumn parameter to [sqlite3_get_table()] is not NULL
+** {H12373} If the pnColumn parameter to [sqlite3_get_table()] is not NULL
** then a successful invocation of [sqlite3_get_table()] shall
** write the number of columns in the
** result set of the query into *pnColumn.
**
-** {F12374} If the pnRow parameter to [sqlite3_get_table()] is not NULL
+** {H12374} If the pnRow parameter to [sqlite3_get_table()] is not NULL
** then a successful invocation of [sqlite3_get_table()] shall
** writes the number of rows in the
** result set of the query into *pnRow.
**
-** {F12376} A successful invocation of [sqlite3_get_table()] that computes
+** {H12376} A successful invocation of [sqlite3_get_table()] that computes
** N rows of result with C columns per row shall make *pazResult
** point to an array of pointers to (N+1)*C strings where the first
** C strings are column names as obtained from
** [sqlite3_column_name()] and the rest are column result values
** obtained from [sqlite3_column_text()].
**
-** {F12379} The values in the pazResult array returned by [sqlite3_get_table()]
+** {H12379} The values in the pazResult array returned by [sqlite3_get_table()]
** shall remain valid until cleared by [sqlite3_free_table()].
**
-** {F12382} When an error occurs during evaluation of [sqlite3_get_table()]
+** {H12382} When an error occurs during evaluation of [sqlite3_get_table()]
** the function shall set *pazResult to NULL, write an error message
** into memory obtained from [sqlite3_malloc()], make
** **pzErrmsg point to that error message, and return a
** appropriate [error code].
@@ -2090,9 +2326,9 @@
);
SQLITE_API void sqlite3_free_table(char **result);
/*
-** CAPI3REF: Formatted String Printing Functions {F17400}
+** CAPI3REF: Formatted String Printing Functions {H17400} <S70000><S20000>
**
** These routines are workalikes of the "printf()" family of functions
** from the standard C library.
**
@@ -2183,18 +2419,18 @@
** the result, [sqlite3_free()] is called on the input string. {END}
**
** INVARIANTS:
**
-** {F17403} The [sqlite3_mprintf()] and [sqlite3_vmprintf()] interfaces
+** {H17403} The [sqlite3_mprintf()] and [sqlite3_vmprintf()] interfaces
** return either pointers to zero-terminated UTF-8 strings held in
** memory obtained from [sqlite3_malloc()] or NULL pointers if
** a call to [sqlite3_malloc()] fails.
**
-** {F17406} The [sqlite3_snprintf()] interface writes a zero-terminated
+** {H17406} The [sqlite3_snprintf()] interface writes a zero-terminated
** UTF-8 string into the buffer pointed to by the second parameter
** provided that the first parameter is greater than zero.
**
-** {F17407} The [sqlite3_snprintf()] interface does not write slots of
+** {H17407} The [sqlite3_snprintf()] interface does not write slots of
** its output buffer (the second parameter) outside the range
** of 0 through N-1 (where N is the first parameter)
** regardless of the length of the string
** requested by the format specification.
@@ -2203,9 +2439,9 @@
SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
/*
-** CAPI3REF: Memory Allocation Subsystem {F17300}
+** CAPI3REF: Memory Allocation Subsystem {H17300} <S20000>
**
** The SQLite core uses these three routines for all of its own
** internal memory allocation needs. "Core" in the previous sentence
** does not include operating-system specific VFS implementation. The
@@ -2226,9 +2462,9 @@
** should neither be read nor written. Even reading previously freed
** 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
** second parameter. The memory allocation to be resized is the first
@@ -2250,9 +2486,9 @@
** is always aligned to at least an 8 byte boundary. {END}
**
** The default implementation of the memory allocation subsystem uses
** the malloc(), realloc() and free() provided by the standard C library.
-** {F17382} However, if SQLite is compiled with the
+** {H17382} However, if SQLite is compiled with the
** SQLITE_MEMORY_SIZE=<i>NNN</i> C preprocessor macro (where <i>NNN</i>
** is an integer), then SQLite create a static array of at least
** <i>NNN</i> bytes in size and uses that array for all of its dynamic
** memory allocation needs. {END} Additional memory allocator options
@@ -2272,48 +2508,48 @@
** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
**
** INVARIANTS:
**
-** {F17303} The [sqlite3_malloc(N)] interface returns either a pointer to
+** {H17303} The [sqlite3_malloc(N)] interface returns either a pointer to
** a newly checked-out block of at least N bytes of memory
** that is 8-byte aligned, or it returns NULL if it is unable
** to fulfill the request.
**
-** {F17304} The [sqlite3_malloc(N)] interface returns a NULL pointer if
+** {H17304} The [sqlite3_malloc(N)] interface returns a NULL pointer if
** N is less than or equal to zero.
**
-** {F17305} The [sqlite3_free(P)] interface releases memory previously
+** {H17305} The [sqlite3_free(P)] interface releases memory previously
** returned from [sqlite3_malloc()] or [sqlite3_realloc()],
** making it available for reuse.
**
-** {F17306} A call to [sqlite3_free(NULL)] is a harmless no-op.
-**
-** {F17310} A call to [sqlite3_realloc(0,N)] is equivalent to a call
+** {H17306} A call to [sqlite3_free(NULL)] is a harmless no-op.
+**
+** {H17310} A call to [sqlite3_realloc(0,N)] is equivalent to a call
** to [sqlite3_malloc(N)].
**
-** {F17312} A call to [sqlite3_realloc(P,0)] is equivalent to a call
+** {H17312} A call to [sqlite3_realloc(P,0)] is equivalent to a call
** to [sqlite3_free(P)].
**
-** {F17315} The SQLite core uses [sqlite3_malloc()], [sqlite3_realloc()],
+** {H17315} The SQLite core uses [sqlite3_malloc()], [sqlite3_realloc()],
** and [sqlite3_free()] for all of its memory allocation and
** deallocation needs.
**
-** {F17318} The [sqlite3_realloc(P,N)] interface returns either a pointer
+** {H17318} The [sqlite3_realloc(P,N)] interface returns either a pointer
** to a block of checked-out memory of at least N bytes in size
** that is 8-byte aligned, or a NULL pointer.
**
-** {F17321} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first
+** {H17321} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first
** copies the first K bytes of content from P into the newly
** allocated block, where K is the lesser of N and the size of
** the buffer P.
**
-** {F17322} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first
+** {H17322} When [sqlite3_realloc(P,N)] returns a non-NULL pointer, it first
** releases the buffer P.
**
-** {F17323} When [sqlite3_realloc(P,N)] returns NULL, the buffer P is
+** {H17323} When [sqlite3_realloc(P,N)] returns NULL, the buffer P is
** not modified or released.
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A17350} The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
** must be either NULL or else pointers obtained from a prior
** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
@@ -2327,30 +2563,30 @@
SQLITE_API void *sqlite3_realloc(void*, int);
SQLITE_API void sqlite3_free(void*);
/*
-** CAPI3REF: Memory Allocator Statistics {F17370}
+** CAPI3REF: Memory Allocator Statistics {H17370} <S30210>
**
** SQLite provides these two interfaces for reporting on the status
** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()]
** routines, which form the built-in memory allocation subsystem.
**
** INVARIANTS:
**
-** {F17371} The [sqlite3_memory_used()] routine returns the number of bytes
+** {H17371} The [sqlite3_memory_used()] routine returns the number of bytes
** of memory currently outstanding (malloced but not freed).
**
-** {F17373} The [sqlite3_memory_highwater()] routine returns the maximum
+** {H17373} The [sqlite3_memory_highwater()] routine returns the maximum
** value of [sqlite3_memory_used()] since the high-water mark
** was last reset.
**
-** {F17374} The values returned by [sqlite3_memory_used()] and
+** {H17374} The values returned by [sqlite3_memory_used()] and
** [sqlite3_memory_highwater()] include any overhead
** added by SQLite in its implementation of [sqlite3_malloc()],
** but not overhead added by the any underlying system library
** routines that [sqlite3_malloc()] may call.
**
-** {F17375} The memory high-water mark is reset to the current value of
+** {H17375} The memory high-water mark is reset to the current value of
** [sqlite3_memory_used()] if and only if the parameter to
** [sqlite3_memory_highwater()] is true. The value returned
** by [sqlite3_memory_highwater(1)] is the high-water mark
** prior to the reset.
@@ -2358,9 +2594,9 @@
SQLITE_API sqlite3_int64 sqlite3_memory_used(void);
SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
/*
-** CAPI3REF: Pseudo-Random Number Generator {F17390}
+** CAPI3REF: Pseudo-Random Number Generator {H17390} <S20000>
**
** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
** select random ROWIDs when inserting new records into a table that
** already uses the largest possible ROWID. The PRNG is also used for
@@ -2377,15 +2613,15 @@
** method.
**
** INVARIANTS:
**
-** {F17392} The [sqlite3_randomness(N,P)] interface writes N bytes of
+** {H17392} The [sqlite3_randomness(N,P)] interface writes N bytes of
** high-quality pseudo-randomness into buffer P.
*/
SQLITE_API void sqlite3_randomness(int N, void *P);
/*
-** CAPI3REF: Compile-Time Authorization Callbacks {F12500}
+** CAPI3REF: Compile-Time Authorization Callbacks {H12500} <S70100>
**
** This routine registers a authorizer callback with a particular
** [database connection], supplied in the first argument.
** The authorizer callback is invoked as SQL statements are being compiled
@@ -2441,63 +2677,73 @@
** at a time. Each call to sqlite3_set_authorizer overrides 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
+** correct authorizer callback remains in place during the [sqlite3_step()].
+**
** Note that the authorizer callback is invoked only during
** [sqlite3_prepare()] or its variants. Authorization is not
** performed during statement evaluation in [sqlite3_step()].
**
** INVARIANTS:
**
-** {F12501} The [sqlite3_set_authorizer(D,...)] interface registers a
+** {H12501} The [sqlite3_set_authorizer(D,...)] interface registers a
** authorizer callback with database connection D.
**
-** {F12502} The authorizer callback is invoked as SQL statements are
-** being compiled.
-**
-** {F12503} If the authorizer callback returns any value other than
+** {H12502} The authorizer callback is invoked as SQL statements are
+** being parseed and compiled.
+**
+** {H12503} If the authorizer callback returns any value other than
** [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY], then
-** the [sqlite3_prepare_v2()] or equivalent call that caused
+** the application interface call that caused
** the authorizer callback to run shall fail with an
** [SQLITE_ERROR] error code and an appropriate error message.
**
-** {F12504} When the authorizer callback returns [SQLITE_OK], the operation
+** {H12504} When the authorizer callback returns [SQLITE_OK], the operation
** described is processed normally.
**
-** {F12505} When the authorizer callback returns [SQLITE_DENY], the
-** [sqlite3_prepare_v2()] or equivalent call that caused the
+** {H12505} When the authorizer callback returns [SQLITE_DENY], the
+** application interface call that caused the
** authorizer callback to run shall fail
** with an [SQLITE_ERROR] error code and an error message
** explaining that access is denied.
**
-** {F12506} If the authorizer code (the 2nd parameter to the authorizer
+** {H12506} If the authorizer code (the 2nd parameter to the authorizer
** callback) is [SQLITE_READ] and the authorizer callback returns
** [SQLITE_IGNORE], then the prepared statement is constructed to
** insert a NULL value in place of the table column that would have
** been read if [SQLITE_OK] had been returned.
**
-** {F12507} If the authorizer code (the 2nd parameter to the authorizer
+** {H12507} If the authorizer code (the 2nd parameter to the authorizer
** callback) is anything other than [SQLITE_READ], then
** a return of [SQLITE_IGNORE] has the same effect as [SQLITE_DENY].
**
-** {F12510} The first parameter to the authorizer callback is a copy of
+** {H12510} The first parameter to the authorizer callback is a copy of
** the third parameter to the [sqlite3_set_authorizer()] interface.
**
-** {F12511} The second parameter to the callback is an integer
+** {H12511} The second parameter to the callback is an integer
** [SQLITE_COPY | action code] that specifies the particular action
** to be authorized.
**
-** {F12512} The third through sixth parameters to the callback are
+** {H12512} The third through sixth parameters to the callback are
** zero-terminated strings that contain
** additional details about the action to be authorized.
**
-** {F12520} Each call to [sqlite3_set_authorizer()] overrides
+** {H12520} Each call to [sqlite3_set_authorizer()] overrides
** any previously installed authorizer.
**
-** {F12521} A NULL authorizer means that no authorization
+** {H12521} A NULL authorizer means that no authorization
** callback is invoked.
**
-** {F12522} The default authorizer is NULL.
+** {H12522} The default authorizer is NULL.
*/
SQLITE_API int sqlite3_set_authorizer(
sqlite3*,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
@@ -2504,9 +2750,9 @@
void *pUserData
);
/*
-** CAPI3REF: Authorizer Return Codes {F12590}
+** CAPI3REF: Authorizer Return Codes {H12590} <H12500>
**
** The [sqlite3_set_authorizer | authorizer callback function] must
** return either [SQLITE_OK] or one of these two constants in order
** to signal SQLite whether or not the action is permitted. See the
@@ -2516,9 +2762,9 @@
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
/*
-** CAPI3REF: Authorizer Action Codes {F12550}
+** CAPI3REF: Authorizer Action Codes {H12550} <H12500>
**
** The [sqlite3_set_authorizer()] interface registers a callback function
** that is invoked to authorize certain SQL statement actions. The
** second parameter to the callback is an integer code that specifies
@@ -2536,24 +2782,24 @@
** top-level SQL code.
**
** INVARIANTS:
**
-** {F12551} The second parameter to an
-** [sqlite3_set_authorizer | authorizer callback] is always an integer
+** {H12551} The second parameter to an
+** [sqlite3_set_authorizer | authorizer callback] shall be an integer
** [SQLITE_COPY | authorizer code] that specifies what action
** is being authorized.
**
-** {F12552} The 3rd and 4th parameters to the
+** {H12552} The 3rd and 4th parameters to the
** [sqlite3_set_authorizer | authorization callback]
-** will be parameters or NULL depending on which
+** shall be parameters or NULL depending on which
** [SQLITE_COPY | authorizer code] is used as the second parameter.
**
-** {F12553} The 5th parameter to the
-** [sqlite3_set_authorizer | authorizer callback] is the name
+** {H12553} The 5th parameter to the
+** [sqlite3_set_authorizer | authorizer callback] shall be the name
** of the database (example: "main", "temp", etc.) if applicable.
**
-** {F12554} The 6th parameter to the
-** [sqlite3_set_authorizer | authorizer callback] is the name
+** {H12554} The 6th parameter to the
+** [sqlite3_set_authorizer | authorizer callback] shall be the name
** of the inner-most trigger or view that is responsible for
** the access attempt or NULL if this access attempt is directly from
** top-level SQL code.
*/
@@ -2591,9 +2837,10 @@
#define SQLITE_FUNCTION 31 /* Function Name NULL */
#define SQLITE_COPY 0 /* No longer used */
/*
-** CAPI3REF: Tracing And Profiling Functions {F12280}
+** CAPI3REF: Tracing And Profiling Functions {H12280} <S60400>
+** EXPERIMENTAL
**
** These routines register callback functions that can be used for
** tracing and profiling the execution of SQL statements.
**
@@ -2608,57 +2855,50 @@
** as each SQL statement finishes. The profile callback contains
** the original statement text and an estimate of wall-clock time
** of how long that statement took to run.
**
-** The sqlite3_profile() API is currently considered experimental and
-** is subject to change or removal in a future release.
-**
-** The trigger reporting feature of the trace callback is considered
-** experimental and is subject to change or removal in future releases.
-** Future versions of SQLite might also add new trace callback
-** invocations.
-**
-** INVARIANTS:
-**
-** {F12281} The callback function registered by [sqlite3_trace()] is
+** INVARIANTS:
+**
+** {H12281} The callback function registered by [sqlite3_trace()]
+** shall be invoked
** whenever an SQL statement first begins to execute and
** whenever a trigger subprogram first begins to run.
**
-** {F12282} Each call to [sqlite3_trace()] overrides the previously
+** {H12282} Each call to [sqlite3_trace()] shall override the previously
** registered trace callback.
**
-** {F12283} A NULL trace callback disables tracing.
-**
-** {F12284} The first argument to the trace callback is a copy of
+** {H12283} A NULL trace callback shall disable tracing.
+**
+** {H12284} The first argument to the trace callback shall be a copy of
** the pointer which was the 3rd argument to [sqlite3_trace()].
**
-** {F12285} The second argument to the trace callback is a
+** {H12285} The second argument to the trace callback is a
** zero-terminated UTF-8 string containing the original text
** of the SQL statement as it was passed into [sqlite3_prepare_v2()]
** or the equivalent, or an SQL comment indicating the beginning
** of a trigger subprogram.
**
-** {F12287} The callback function registered by [sqlite3_profile()] is invoked
+** {H12287} The callback function registered by [sqlite3_profile()] is invoked
** as each SQL statement finishes.
**
-** {F12288} The first parameter to the profile callback is a copy of
+** {H12288} The first parameter to the profile callback is a copy of
** the 3rd parameter to [sqlite3_profile()].
**
-** {F12289} The second parameter to the profile callback is a
+** {H12289} The second parameter to the profile callback is a
** zero-terminated UTF-8 string that contains the complete text of
** the SQL statement as it was processed by [sqlite3_prepare_v2()]
** or the equivalent.
**
-** {F12290} The third parameter to the profile callback is an estimate
+** {H12290} The third parameter to the profile callback is an estimate
** of the number of nanoseconds of wall-clock time required to
** run the SQL statement from start to finish.
*/
-SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
-SQLITE_API void *sqlite3_profile(sqlite3*,
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
/*
-** CAPI3REF: Query Progress Callbacks {F12910}
+** CAPI3REF: Query Progress Callbacks {H12910} <S60400>
**
** This routine configures a callback function - the
** progress callback - that is invoked periodically during long
** running calls to [sqlite3_exec()], [sqlite3_step()] and
@@ -2666,45 +2906,51 @@
** interface is to keep a GUI updated during a large query.
**
** 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.
-**
-** INVARIANTS:
-**
-** {F12911} The callback function registered by sqlite3_progress_handler()
+** "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:
+**
+** {H12911} The callback function registered by sqlite3_progress_handler()
** is invoked periodically during long running calls to
** [sqlite3_step()].
**
-** {F12912} The progress callback is invoked once for every N virtual
+** {H12912} The progress callback is invoked once for every N virtual
** machine opcodes, where N is the second argument to
** the [sqlite3_progress_handler()] call that registered
** the callback. If N is less than 1, sqlite3_progress_handler()
** acts as if a NULL progress handler had been specified.
**
-** {F12913} The progress callback itself is identified by the third
+** {H12913} The progress callback itself is identified by the third
** argument to sqlite3_progress_handler().
**
-** {F12914} The fourth argument to sqlite3_progress_handler() is a
+** {H12914} The fourth argument to sqlite3_progress_handler() is a
** void pointer passed to the progress callback
** function each time it is invoked.
**
-** {F12915} If a call to [sqlite3_step()] results in fewer than N opcodes
+** {H12915} If a call to [sqlite3_step()] results in fewer than N opcodes
** being executed, then the progress callback is never invoked.
**
-** {F12916} Every call to [sqlite3_progress_handler()]
+** {H12916} Every call to [sqlite3_progress_handler()]
** overwrites any previously registered progress handler.
**
-** {F12917} If the progress handler callback is NULL then no progress
+** {H12917} If the progress handler callback is NULL then no progress
** handler is invoked.
**
-** {F12918} If the progress callback returns a result other than 0, then
+** {H12918} If the progress callback returns a result other than 0, then
** the behavior is a if [sqlite3_interrupt()] had been called.
+** <S30500>
*/
SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
/*
-** CAPI3REF: Opening A New Database Connection {F12700}
+** CAPI3REF: Opening A New Database Connection {H12700} <S40200>
**
** These routines open an SQLite database file whose name is given by the
** filename argument. The filename argument is interpreted as UTF-8 for
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
@@ -2728,9 +2974,9 @@
** The sqlite3_open_v2() interface works like sqlite3_open()
** 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>
** <dd>The database is opened in read-only mode. If the database does not
@@ -2748,18 +2994,17 @@
** </dl>
**
** 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.
-**
-** 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.
+** with the [SQLITE_OPEN_NOMUTEX] or [SQLITE_OPEN_FULLMUTEX] flags,
+** then the behavior is undefined.
+**
+** If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
+** opens in the multi-thread [threading mode] as long as the single-thread
+** mode has not been set at compile-time or start-time. If the
+** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
+** in the serialized [threading mode] unless single-thread was
+** previously selected at compile-time or start-time.
**
** If the filename is ":memory:", then a private, temporary in-memory database
** is created for the connection. This in-memory database will vanish when
** the database connection is closed. Future versions of SQLite might
@@ -2784,69 +3029,69 @@
** sqlite3_open() or sqlite3_open_v2().
**
** INVARIANTS:
**
-** {F12701} The [sqlite3_open()], [sqlite3_open16()], and
+** {H12701} The [sqlite3_open()], [sqlite3_open16()], and
** [sqlite3_open_v2()] interfaces create a new
** [database connection] associated with
** the database file given in their first parameter.
**
-** {F12702} The filename argument is interpreted as UTF-8
+** {H12702} The filename argument is interpreted as UTF-8
** for [sqlite3_open()] and [sqlite3_open_v2()] and as UTF-16
** in the native byte order for [sqlite3_open16()].
**
-** {F12703} A successful invocation of [sqlite3_open()], [sqlite3_open16()],
+** {H12703} A successful invocation of [sqlite3_open()], [sqlite3_open16()],
** or [sqlite3_open_v2()] writes a pointer to a new
** [database connection] into *ppDb.
**
-** {F12704} The [sqlite3_open()], [sqlite3_open16()], and
+** {H12704} The [sqlite3_open()], [sqlite3_open16()], and
** [sqlite3_open_v2()] interfaces return [SQLITE_OK] upon success,
** or an appropriate [error code] on failure.
**
-** {F12706} The default text encoding for a new database created using
+** {H12706} The default text encoding for a new database created using
** [sqlite3_open()] or [sqlite3_open_v2()] will be UTF-8.
**
-** {F12707} The default text encoding for a new database created using
+** {H12707} The default text encoding for a new database created using
** [sqlite3_open16()] will be UTF-16.
**
-** {F12709} The [sqlite3_open(F,D)] interface is equivalent to
+** {H12709} The [sqlite3_open(F,D)] interface is equivalent to
** [sqlite3_open_v2(F,D,G,0)] where the G parameter is
** [SQLITE_OPEN_READWRITE]|[SQLITE_OPEN_CREATE].
**
-** {F12711} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
+** {H12711} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
** bit value [SQLITE_OPEN_READONLY] then the database is opened
** for reading only.
**
-** {F12712} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
+** {H12712} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
** bit value [SQLITE_OPEN_READWRITE] then the database is opened
** reading and writing if possible, or for reading only if the
** file is write protected by the operating system.
**
-** {F12713} If the G parameter to [sqlite3_open(v2(F,D,G,V)] omits the
+** {H12713} If the G parameter to [sqlite3_open_v2(F,D,G,V)] omits the
** bit value [SQLITE_OPEN_CREATE] and the database does not
** previously exist, an error is returned.
**
-** {F12714} If the G parameter to [sqlite3_open(v2(F,D,G,V)] contains the
+** {H12714} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
** bit value [SQLITE_OPEN_CREATE] and the database does not
** previously exist, then an attempt is made to create and
** initialize the database.
**
-** {F12717} If the filename argument to [sqlite3_open()], [sqlite3_open16()],
+** {H12717} If the filename argument to [sqlite3_open()], [sqlite3_open16()],
** or [sqlite3_open_v2()] is ":memory:", then an private,
** ephemeral, in-memory database is created for the connection.
** <todo>Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required
** in sqlite3_open_v2()?</todo>
**
-** {F12719} If the filename is NULL or an empty string, then a private,
+** {H12719} If the filename is NULL or an empty string, then a private,
** ephemeral on-disk database will be created.
** <todo>Is SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE required
** in sqlite3_open_v2()?</todo>
**
-** {F12721} The [database connection] created by [sqlite3_open_v2(F,D,G,V)]
+** {H12721} The [database connection] created by [sqlite3_open_v2(F,D,G,V)]
** will use the [sqlite3_vfs] object identified by the V parameter,
** or the default [sqlite3_vfs] object if V is a NULL pointer.
**
-** {F12723} Two [database connections] will share a common cache if both were
+** {H12723} Two [database connections] will share a common cache if both were
** opened with the same VFS while [shared cache mode] was enabled and
** if both filenames compare equal using memcmp() after having been
** processed by the [sqlite3_vfs | xFullPathname] method of the VFS.
*/
@@ -2865,15 +3110,18 @@
const char *zVfs /* Name of VFS module to use */
);
/*
-** CAPI3REF: Error Codes And Messages {F12800}
+** CAPI3REF: Error Codes And Messages {H12800} <S60200>
**
** The sqlite3_errcode() interface returns the numeric [result code] or
** [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.
** Memory to hold the error message string is managed internally.
@@ -2886,37 +3134,44 @@
** error code and message may or may not be set.
**
** INVARIANTS:
**
-** {F12801} The [sqlite3_errcode(D)] interface returns the numeric
+** {H12801} The [sqlite3_errcode(D)] interface returns the numeric
** [result code] or [extended result code] for the most recently
** failed interface call associated with the [database connection] D.
**
-** {F12803} The [sqlite3_errmsg(D)] and [sqlite3_errmsg16(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,
** encoded as either UTF-8 or UTF-16 respectively.
**
-** {F12807} The strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]
+** {H12807} The strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]
** are valid until the next SQLite interface call.
**
-** {F12808} Calls to API routines that do not return an error code
+** {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()].
-**
-** {F12809} Interfaces that are not associated with a specific
+** [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*);
/*
-** CAPI3REF: SQL Statement Object {F13000}
+** CAPI3REF: SQL Statement Object {H13000} <H13010>
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement.
** This object is variously known as a "prepared statement" or a
@@ -2940,9 +3195,9 @@
*/
typedef struct sqlite3_stmt sqlite3_stmt;
/*
-** CAPI3REF: Run-time Limits {F12760}
+** CAPI3REF: Run-time Limits {H12760} <S20600>
**
** This interface allows the size of various constructs to be limited
** on a connection by connection basis. The first parameter is the
** [database connection] whose limit is to be set or queried. The
@@ -2969,29 +3224,28 @@
** interface to further control untrusted SQL. The size of the database
** created by an untrusted script can be contained using the
** [max_page_count] [PRAGMA].
**
-** This interface is currently considered experimental and is subject
-** to change or removal without prior notice.
-**
-** INVARIANTS:
-**
-** {F12762} A successful call to [sqlite3_limit(D,C,V)] where V is
+** New run-time limit categories may be added in future releases.
+**
+** INVARIANTS:
+**
+** {H12762} A successful call to [sqlite3_limit(D,C,V)] where V is
** positive changes the limit on the size of construct C in the
** [database connection] D to the lesser of V and the hard upper
** bound on the size of C that is set at compile-time.
**
-** {F12766} A successful call to [sqlite3_limit(D,C,V)] where V is negative
+** {H12766} A successful call to [sqlite3_limit(D,C,V)] where V is negative
** leaves the state of the [database connection] D unchanged.
**
-** {F12769} A successful call to [sqlite3_limit(D,C,V)] returns the
+** {H12769} A successful call to [sqlite3_limit(D,C,V)] returns the
** value of the limit on the size of construct C in the
** [database connection] D as it was prior to the call.
*/
SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
/*
-** CAPI3REF: Run-Time Limit Categories {F12790}
+** CAPI3REF: Run-Time Limit Categories {H12790} <H12760>
** KEYWORDS: {limit category} {limit categories}
**
** These constants define various aspects of a [database connection]
** that can be limited in size by calls to [sqlite3_limit()].
@@ -3045,9 +3299,9 @@
#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
#define SQLITE_LIMIT_VARIABLE_NUMBER 9
/*
-** CAPI3REF: Compiling An SQL Statement {F13010}
+** CAPI3REF: Compiling An SQL Statement {H13010} <S10000>
** KEYWORDS: {SQL statement compiler}
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
@@ -3115,39 +3369,39 @@
** </ol>
**
** INVARIANTS:
**
-** {F13011} The [sqlite3_prepare(db,zSql,...)] and
+** {H13011} The [sqlite3_prepare(db,zSql,...)] and
** [sqlite3_prepare_v2(db,zSql,...)] interfaces interpret the
** text in their zSql parameter as UTF-8.
**
-** {F13012} The [sqlite3_prepare16(db,zSql,...)] and
+** {H13012} The [sqlite3_prepare16(db,zSql,...)] and
** [sqlite3_prepare16_v2(db,zSql,...)] interfaces interpret the
** text in their zSql parameter as UTF-16 in the native byte order.
**
-** {F13013} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)]
+** {H13013} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)]
** and its variants is less than zero, the SQL text is
** read from zSql is read up to the first zero terminator.
**
-** {F13014} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)]
+** {H13014} If the nByte argument to [sqlite3_prepare_v2(db,zSql,nByte,...)]
** and its variants is non-negative, then at most nBytes bytes of
** SQL text is read from zSql.
**
-** {F13015} In [sqlite3_prepare_v2(db,zSql,N,P,pzTail)] and its variants
+** {H13015} In [sqlite3_prepare_v2(db,zSql,N,P,pzTail)] and its variants
** if the zSql input text contains more than one SQL statement
** and pzTail is not NULL, then *pzTail is made to point to the
** first byte past the end of the first SQL statement in zSql.
** <todo>What does *pzTail point to if there is one statement?</todo>
**
-** {F13016} A successful call to [sqlite3_prepare_v2(db,zSql,N,ppStmt,...)]
+** {H13016} A successful call to [sqlite3_prepare_v2(db,zSql,N,ppStmt,...)]
** or one of its variants writes into *ppStmt a pointer to a new
** [prepared statement] or a pointer to NULL if zSql contains
** nothing other than whitespace or comments.
**
-** {F13019} The [sqlite3_prepare_v2()] interface and its variants return
+** {H13019} The [sqlite3_prepare_v2()] interface and its variants return
** [SQLITE_OK] or an appropriate [error code] upon failure.
**
-** {F13021} Before [sqlite3_prepare(db,zSql,nByte,ppStmt,pzTail)] or its
+** {H13021} Before [sqlite3_prepare(db,zSql,nByte,ppStmt,pzTail)] or its
** variants returns an error (any value other than [SQLITE_OK]),
** they first set *ppStmt to NULL.
*/
SQLITE_API int sqlite3_prepare(
@@ -3179,33 +3433,33 @@
const void **pzTail /* OUT: Pointer to unused portion of zSql */
);
/*
-** CAPIREF: Retrieving Statement SQL {F13100}
+** 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
** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
**
** INVARIANTS:
**
-** {F13101} If the [prepared statement] passed as the argument to
+** {H13101} If the [prepared statement] passed as the argument to
** [sqlite3_sql()] was compiled using either [sqlite3_prepare_v2()] or
** [sqlite3_prepare16_v2()], then [sqlite3_sql()] returns
** a pointer to a zero-terminated string containing a UTF-8 rendering
** of the original SQL statement.
**
-** {F13102} If the [prepared statement] passed as the argument to
+** {H13102} If the [prepared statement] passed as the argument to
** [sqlite3_sql()] was compiled using either [sqlite3_prepare()] or
** [sqlite3_prepare16()], then [sqlite3_sql()] returns a NULL pointer.
**
-** {F13103} The string returned by [sqlite3_sql(S)] is valid until the
+** {H13103} The string returned by [sqlite3_sql(S)] is valid until the
** [prepared statement] S is deleted using [sqlite3_finalize(S)].
*/
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
/*
-** CAPI3REF: Dynamically Typed Value Object {F15000}
+** CAPI3REF: Dynamically Typed Value Object {H15000} <S20200>
** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
**
** SQLite uses the sqlite3_value object to represent all values
** that can be stored in a database table. SQLite uses dynamic typing
@@ -3242,9 +3496,9 @@
*/
typedef struct Mem sqlite3_value;
/*
-** CAPI3REF: SQL Function Context Object {F16001}
+** CAPI3REF: SQL Function Context Object {H16001} <S20200>
**
** The context in which an SQL function executes is stored in an
** sqlite3_context object. A pointer to an sqlite3_context object
** is always first parameter to [application-defined SQL functions].
@@ -3256,9 +3510,9 @@
*/
typedef struct sqlite3_context sqlite3_context;
/*
-** CAPI3REF: Binding Values To Prepared Statements {F13500}
+** CAPI3REF: Binding Values To Prepared Statements {H13500} <S70300>
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
**
** In the SQL strings input to [sqlite3_prepare_v2()] and its variants,
@@ -3336,77 +3590,77 @@
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
**
** INVARIANTS:
**
-** {F13506} The [SQL statement compiler] recognizes tokens of the forms
+** {H13506} The [SQL statement compiler] recognizes tokens of the forms
** "?", "?NNN", "$VVV", ":VVV", and "@VVV" as SQL parameters,
** where NNN is any sequence of one or more digits
** and where VVV is any sequence of one or more alphanumeric
** characters or "::" optionally followed by a string containing
** no spaces and contained within parentheses.
**
-** {F13509} The initial value of an SQL parameter is NULL.
-**
-** {F13512} The index of an "?" SQL parameter is one larger than the
+** {H13509} The initial value of an SQL parameter is NULL.
+**
+** {H13512} The index of an "?" SQL parameter is one larger than the
** largest index of SQL parameter to the left, or 1 if
** the "?" is the leftmost SQL parameter.
**
-** {F13515} The index of an "?NNN" SQL parameter is the integer NNN.
-**
-** {F13518} The index of an ":VVV", "$VVV", or "@VVV" SQL parameter is
+** {H13515} The index of an "?NNN" SQL parameter is the integer NNN.
+**
+** {H13518} The index of an ":VVV", "$VVV", or "@VVV" SQL parameter is
** the same as the index of leftmost occurrences of the same
** parameter, or one more than the largest index over all
** parameters to the left if this is the first occurrence
** of this parameter, or 1 if this is the leftmost parameter.
**
-** {F13521} The [SQL statement compiler] fails with an [SQLITE_RANGE]
+** {H13521} The [SQL statement compiler] fails with an [SQLITE_RANGE]
** error if the index of an SQL parameter is less than 1
** or greater than the compile-time SQLITE_MAX_VARIABLE_NUMBER
** parameter.
**
-** {F13524} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,V,...)]
+** {H13524} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,V,...)]
** associate the value V with all SQL parameters having an
** index of N in the [prepared statement] S.
**
-** {F13527} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,...)]
+** {H13527} Calls to [sqlite3_bind_text | sqlite3_bind(S,N,...)]
** override prior calls with the same values of S and N.
**
-** {F13530} Bindings established by [sqlite3_bind_text | sqlite3_bind(S,...)]
+** {H13530} Bindings established by [sqlite3_bind_text | sqlite3_bind(S,...)]
** persist across calls to [sqlite3_reset(S)].
**
-** {F13533} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
+** {H13533} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
** [sqlite3_bind_text(S,N,V,L,D)], or
** [sqlite3_bind_text16(S,N,V,L,D)] SQLite binds the first L
** bytes of the BLOB or string pointed to by V, when L
** is non-negative.
**
-** {F13536} In calls to [sqlite3_bind_text(S,N,V,L,D)] or
+** {H13536} In calls to [sqlite3_bind_text(S,N,V,L,D)] or
** [sqlite3_bind_text16(S,N,V,L,D)] SQLite binds characters
** from V through the first zero character when L is negative.
**
-** {F13539} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
+** {H13539} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
** [sqlite3_bind_text(S,N,V,L,D)], or
** [sqlite3_bind_text16(S,N,V,L,D)] when D is the special
** constant [SQLITE_STATIC], SQLite assumes that the value V
** is held in static unmanaged space that will not change
** during the lifetime of the binding.
**
-** {F13542} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
+** {H13542} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
** [sqlite3_bind_text(S,N,V,L,D)], or
** [sqlite3_bind_text16(S,N,V,L,D)] when D is the special
** constant [SQLITE_TRANSIENT], the routine makes a
** private copy of the value V before it returns.
**
-** {F13545} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
+** {H13545} In calls to [sqlite3_bind_blob(S,N,V,L,D)],
** [sqlite3_bind_text(S,N,V,L,D)], or
** [sqlite3_bind_text16(S,N,V,L,D)] when D is a pointer to
** a function, SQLite invokes that function to destroy the
** value V after it has finished using the value V.
**
-** {F13548} In calls to [sqlite3_bind_zeroblob(S,N,V,L)] the value bound
+** {H13548} In calls to [sqlite3_bind_zeroblob(S,N,V,L)] the value bound
** is a BLOB of L bytes, or a zero-length BLOB if L is negative.
**
-** {F13551} In calls to [sqlite3_bind_value(S,N,V)] the V argument may
+** {H13551} In calls to [sqlite3_bind_value(S,N,V)] the V argument may
** be either a [protected sqlite3_value] object or an
** [unprotected sqlite3_value] object.
*/
SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
@@ -3419,9 +3673,9 @@
SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
/*
-** CAPI3REF: Number Of SQL Parameters {F13600}
+** CAPI3REF: Number Of SQL Parameters {H13600} <S70300>
**
** This routine can be used to find the number of [SQL parameters]
** in a [prepared statement]. SQL parameters are tokens of the
** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as
@@ -3438,16 +3692,16 @@
** [sqlite3_bind_parameter_index()].
**
** INVARIANTS:
**
-** {F13601} The [sqlite3_bind_parameter_count(S)] interface returns
+** {H13601} The [sqlite3_bind_parameter_count(S)] interface returns
** the largest index of all SQL parameters in the
** [prepared statement] S, or 0 if S contains no SQL parameters.
*/
SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
/*
-** CAPI3REF: Name Of A Host Parameter {F13620}
+** CAPI3REF: Name Of A Host Parameter {H13620} <S70300>
**
** This routine returns a pointer to the name of the n-th
** [SQL parameter] in a [prepared statement].
** SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA"
@@ -3471,9 +3725,9 @@
** [sqlite3_bind_parameter_index()].
**
** INVARIANTS:
**
-** {F13621} The [sqlite3_bind_parameter_name(S,N)] interface returns
+** {H13621} The [sqlite3_bind_parameter_name(S,N)] interface returns
** a UTF-8 rendering of the name of the SQL parameter in
** the [prepared statement] S having index N, or
** NULL if there is no SQL parameter with index N or if the
** parameter with index N is an anonymous parameter "?".
@@ -3480,9 +3734,9 @@
*/
SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
/*
-** CAPI3REF: Index Of A Parameter With A Given Name {F13640}
+** CAPI3REF: Index Of A Parameter With A Given Name {H13640} <S70300>
**
** Return the index of an SQL parameter given its name. The
** index value returned is suitable for use as the second
** parameter to [sqlite3_bind_blob|sqlite3_bind()]. A zero
@@ -3495,46 +3749,46 @@
** [sqlite3_bind_parameter_index()].
**
** INVARIANTS:
**
-** {F13641} The [sqlite3_bind_parameter_index(S,N)] interface returns
+** {H13641} The [sqlite3_bind_parameter_index(S,N)] interface returns
** the index of SQL parameter in the [prepared statement]
** S whose name matches the UTF-8 string N, or 0 if there is
** no match.
*/
SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
/*
-** CAPI3REF: Reset All Bindings On A Prepared Statement {F13660}
+** CAPI3REF: Reset All Bindings On A Prepared Statement {H13660} <S70300>
**
** Contrary to the intuition of many, [sqlite3_reset()] does not reset
** the [sqlite3_bind_blob | bindings] on a [prepared statement].
** Use this routine to reset all host parameters to NULL.
**
** INVARIANTS:
**
-** {F13661} The [sqlite3_clear_bindings(S)] interface resets all SQL
+** {H13661} The [sqlite3_clear_bindings(S)] interface resets all SQL
** parameter bindings in the [prepared statement] S back to NULL.
*/
SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
/*
-** CAPI3REF: Number Of Columns In A Result Set {F13710}
+** CAPI3REF: Number Of Columns In A Result Set {H13710} <S10700>
**
** Return the number of columns in the result set returned by the
** [prepared statement]. This routine returns 0 if pStmt is an SQL
** statement that does not return data (for example an [UPDATE]).
**
** INVARIANTS:
**
-** {F13711} The [sqlite3_column_count(S)] interface returns the number of
+** {H13711} The [sqlite3_column_count(S)] interface returns the number of
** columns in the result set generated by the [prepared statement] S,
** or 0 if S does not generate a result set.
*/
SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
/*
-** CAPI3REF: Column Names In A Result Set {F13720}
+** CAPI3REF: Column Names In A Result Set {H13720} <S10700>
**
** These routines return the name assigned to a particular column
** in the result set of a [SELECT] statement. The sqlite3_column_name()
** interface returns a pointer to a zero-terminated UTF-8 string
@@ -3557,41 +3811,41 @@
** one release of SQLite to the next.
**
** INVARIANTS:
**
-** {F13721} A successful invocation of the [sqlite3_column_name(S,N)]
+** {H13721} A successful invocation of the [sqlite3_column_name(S,N)]
** interface returns the name of the Nth column (where 0 is
** the leftmost column) for the result set of the
** [prepared statement] S as a zero-terminated UTF-8 string.
**
-** {F13723} A successful invocation of the [sqlite3_column_name16(S,N)]
+** {H13723} A successful invocation of the [sqlite3_column_name16(S,N)]
** interface returns the name of the Nth column (where 0 is
** the leftmost column) for the result set of the
** [prepared statement] S as a zero-terminated UTF-16 string
** in the native byte order.
**
-** {F13724} The [sqlite3_column_name()] and [sqlite3_column_name16()]
+** {H13724} The [sqlite3_column_name()] and [sqlite3_column_name16()]
** interfaces return a NULL pointer if they are unable to
** allocate memory to hold their normal return strings.
**
-** {F13725} If the N parameter to [sqlite3_column_name(S,N)] or
+** {H13725} If the N parameter to [sqlite3_column_name(S,N)] or
** [sqlite3_column_name16(S,N)] is out of range, then the
** interfaces return a NULL pointer.
**
-** {F13726} The strings returned by [sqlite3_column_name(S,N)] and
+** {H13726} The strings returned by [sqlite3_column_name(S,N)] and
** [sqlite3_column_name16(S,N)] are valid until the next
** call to either routine with the same S and N parameters
** or until [sqlite3_finalize(S)] is called.
**
-** {F13727} When a result column of a [SELECT] statement contains
+** {H13727} When a result column of a [SELECT] statement contains
** an AS clause, the name of that column is the identifier
** to the right of the AS keyword.
*/
SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
/*
-** CAPI3REF: Source Of Data In A Query Result {F13740}
+** CAPI3REF: Source Of Data In A Query Result {H13740} <S10700>
**
** These routines provide a means to determine what column of what
** table in which database a result of a [SELECT] statement comes from.
** The name of the database or table or column can be returned as
@@ -3627,52 +3881,52 @@
** undefined.
**
** INVARIANTS:
**
-** {F13741} The [sqlite3_column_database_name(S,N)] interface returns either
+** {H13741} The [sqlite3_column_database_name(S,N)] interface returns either
** the UTF-8 zero-terminated name of the database from which the
** Nth result column of the [prepared statement] S is extracted,
** or NULL if the Nth column of S is a general expression
** or if unable to allocate memory to store the name.
**
-** {F13742} The [sqlite3_column_database_name16(S,N)] interface returns either
+** {H13742} The [sqlite3_column_database_name16(S,N)] interface returns either
** the UTF-16 native byte order zero-terminated name of the database
** from which the Nth result column of the [prepared statement] S is
** extracted, or NULL if the Nth column of S is a general expression
** or if unable to allocate memory to store the name.
**
-** {F13743} The [sqlite3_column_table_name(S,N)] interface returns either
+** {H13743} The [sqlite3_column_table_name(S,N)] interface returns either
** the UTF-8 zero-terminated name of the table from which the
** Nth result column of the [prepared statement] S is extracted,
** or NULL if the Nth column of S is a general expression
** or if unable to allocate memory to store the name.
**
-** {F13744} The [sqlite3_column_table_name16(S,N)] interface returns either
+** {H13744} The [sqlite3_column_table_name16(S,N)] interface returns either
** the UTF-16 native byte order zero-terminated name of the table
** from which the Nth result column of the [prepared statement] S is
** extracted, or NULL if the Nth column of S is a general expression
** or if unable to allocate memory to store the name.
**
-** {F13745} The [sqlite3_column_origin_name(S,N)] interface returns either
+** {H13745} The [sqlite3_column_origin_name(S,N)] interface returns either
** the UTF-8 zero-terminated name of the table column from which the
** Nth result column of the [prepared statement] S is extracted,
** or NULL if the Nth column of S is a general expression
** or if unable to allocate memory to store the name.
**
-** {F13746} The [sqlite3_column_origin_name16(S,N)] interface returns either
+** {H13746} The [sqlite3_column_origin_name16(S,N)] interface returns either
** the UTF-16 native byte order zero-terminated name of the table
** column from which the Nth result column of the
** [prepared statement] S is extracted, or NULL if the Nth column
** of S is a general expression or if unable to allocate memory
** to store the name.
**
-** {F13748} The return values from
+** {H13748} The return values from
** [sqlite3_column_database_name | column metadata interfaces]
** are valid for the lifetime of the [prepared statement]
** or until the encoding is changed by another metadata
** interface call for the same prepared statement and column.
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A13751} If two or more threads call one or more
** [sqlite3_column_database_name | column metadata interfaces]
** for the same [prepared statement] and result column
@@ -3685,9 +3939,9 @@
SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
/*
-** CAPI3REF: Declared Datatype Of A Query Result {F13760}
+** CAPI3REF: Declared Datatype Of A Query Result {H13760} <S10700>
**
** The first parameter is a [prepared statement].
** If this statement is a [SELECT] statement and the Nth column of the
** returned result set of that [SELECT] is a table column (not an
@@ -3715,20 +3969,20 @@
** used to hold those values.
**
** INVARIANTS:
**
-** {F13761} A successful call to [sqlite3_column_decltype(S,N)] returns a
+** {H13761} A successful call to [sqlite3_column_decltype(S,N)] returns a
** zero-terminated UTF-8 string containing the declared datatype
** of the table column that appears as the Nth column (numbered
** from 0) of the result set to the [prepared statement] S.
**
-** {F13762} A successful call to [sqlite3_column_decltype16(S,N)]
+** {H13762} A successful call to [sqlite3_column_decltype16(S,N)]
** returns a zero-terminated UTF-16 native byte order string
** containing the declared datatype of the table column that appears
** as the Nth column (numbered from 0) of the result set to the
** [prepared statement] S.
**
-** {F13763} If N is less than 0 or N is greater than or equal to
+** {H13763} If N is less than 0 or N is greater than or equal to
** the number of columns in the [prepared statement] S,
** or if the Nth column of S is an expression or subquery rather
** than a table column, or if a memory allocation failure
** occurs during encoding conversions, then
@@ -3738,9 +3992,9 @@
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
/*
-** CAPI3REF: Evaluate An SQL Statement {F13200}
+** CAPI3REF: Evaluate An SQL Statement {H13200} <S10000>
**
** After a [prepared statement] has been prepared using either
** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function
@@ -3804,26 +4058,26 @@
** by sqlite3_step(). The use of the "v2" interface is recommended.
**
** INVARIANTS:
**
-** {F13202} If the [prepared statement] S is ready to be run, then
+** {H13202} If the [prepared statement] S is ready to be run, then
** [sqlite3_step(S)] advances that prepared statement until
** completion or until it is ready to return another row of the
** result set, or until an [sqlite3_interrupt | interrupt]
** or a run-time error occurs.
**
-** {F15304} When a call to [sqlite3_step(S)] causes the [prepared statement]
+** {H15304} When a call to [sqlite3_step(S)] causes the [prepared statement]
** S to run to completion, the function returns [SQLITE_DONE].
**
-** {F15306} When a call to [sqlite3_step(S)] stops because it is ready to
+** {H15306} When a call to [sqlite3_step(S)] stops because it is ready to
** return another row of the result set, it returns [SQLITE_ROW].
**
-** {F15308} If a call to [sqlite3_step(S)] encounters an
+** {H15308} If a call to [sqlite3_step(S)] encounters an
** [sqlite3_interrupt | interrupt] or a run-time error,
** it returns an appropriate error code that is not one of
** [SQLITE_OK], [SQLITE_ROW], or [SQLITE_DONE].
**
-** {F15310} If an [sqlite3_interrupt | interrupt] or a run-time error
+** {H15310} If an [sqlite3_interrupt | interrupt] or a run-time error
** occurs during a call to [sqlite3_step(S)]
** for a [prepared statement] S created using
** legacy interfaces [sqlite3_prepare()] or
** [sqlite3_prepare16()], then the function returns either
@@ -3831,19 +4085,19 @@
*/
SQLITE_API int sqlite3_step(sqlite3_stmt*);
/*
-** CAPI3REF: Number of columns in a result set {F13770}
+** CAPI3REF: Number of columns in a result set {H13770} <S10700>
**
** Returns the number of values in the current row of the result set.
**
** INVARIANTS:
**
-** {F13771} After a call to [sqlite3_step(S)] that returns [SQLITE_ROW],
+** {H13771} After a call to [sqlite3_step(S)] that returns [SQLITE_ROW],
** the [sqlite3_data_count(S)] routine will return the same value
** as the [sqlite3_column_count(S)] function.
**
-** {F13772} After [sqlite3_step(S)] has returned any value other than
+** {H13772} After [sqlite3_step(S)] has returned any value other than
** [SQLITE_ROW] or before [sqlite3_step(S)] has been called on the
** [prepared statement] for the first time since it was
** [sqlite3_prepare | prepared] or [sqlite3_reset | reset],
** the [sqlite3_data_count(S)] routine returns zero.
@@ -3850,12 +4104,12 @@
*/
SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
/*
-** CAPI3REF: Fundamental Datatypes {F10265}
+** CAPI3REF: Fundamental Datatypes {H10265} <S10110><S10120>
** KEYWORDS: SQLITE_TEXT
**
-** {F10266} Every value in SQLite has one of five fundamental datatypes:
+** {H10266} Every value in SQLite has one of five fundamental datatypes:
**
** <ul>
** <li> 64-bit signed integer
** <li> 64-bit IEEE floating point number
@@ -3882,9 +4136,9 @@
#endif
#define SQLITE3_TEXT 3
/*
-** CAPI3REF: Result Values From A Query {F13800}
+** CAPI3REF: Result Values From A Query {H13800} <S10700>
** KEYWORDS: {column access functions}
**
** These routines form the "result set query" interface.
**
@@ -4035,57 +4289,57 @@
** [SQLITE_NOMEM].
**
** INVARIANTS:
**
-** {F13803} The [sqlite3_column_blob(S,N)] interface converts the
+** {H13803} The [sqlite3_column_blob(S,N)] interface converts the
** Nth column in the current row of the result set for
** the [prepared statement] S into a BLOB and then returns a
** pointer to the converted value.
**
-** {F13806} The [sqlite3_column_bytes(S,N)] interface returns the
+** {H13806} The [sqlite3_column_bytes(S,N)] interface returns the
** number of bytes in the BLOB or string (exclusive of the
** zero terminator on the string) that was returned by the
** most recent call to [sqlite3_column_blob(S,N)] or
** [sqlite3_column_text(S,N)].
**
-** {F13809} The [sqlite3_column_bytes16(S,N)] interface returns the
+** {H13809} The [sqlite3_column_bytes16(S,N)] interface returns the
** number of bytes in the string (exclusive of the
** zero terminator on the string) that was returned by the
** most recent call to [sqlite3_column_text16(S,N)].
**
-** {F13812} The [sqlite3_column_double(S,N)] interface converts the
+** {H13812} The [sqlite3_column_double(S,N)] interface converts the
** Nth column in the current row of the result set for the
** [prepared statement] S into a floating point value and
** returns a copy of that value.
**
-** {F13815} The [sqlite3_column_int(S,N)] interface converts the
+** {H13815} The [sqlite3_column_int(S,N)] interface converts the
** Nth column in the current row of the result set for the
** [prepared statement] S into a 64-bit signed integer and
** returns the lower 32 bits of that integer.
**
-** {F13818} The [sqlite3_column_int64(S,N)] interface converts the
+** {H13818} The [sqlite3_column_int64(S,N)] interface converts the
** Nth column in the current row of the result set for the
** [prepared statement] S into a 64-bit signed integer and
** returns a copy of that integer.
**
-** {F13821} The [sqlite3_column_text(S,N)] interface converts the
+** {H13821} The [sqlite3_column_text(S,N)] interface converts the
** Nth column in the current row of the result set for
** the [prepared statement] S into a zero-terminated UTF-8
** string and returns a pointer to that string.
**
-** {F13824} The [sqlite3_column_text16(S,N)] interface converts the
+** {H13824} The [sqlite3_column_text16(S,N)] interface converts the
** Nth column in the current row of the result set for the
** [prepared statement] S into a zero-terminated 2-byte
** aligned UTF-16 native byte order string and returns
** a pointer to that string.
**
-** {F13827} The [sqlite3_column_type(S,N)] interface returns
+** {H13827} The [sqlite3_column_type(S,N)] interface returns
** one of [SQLITE_NULL], [SQLITE_INTEGER], [SQLITE_FLOAT],
** [SQLITE_TEXT], or [SQLITE_BLOB] as appropriate for
** the Nth column in the current row of the result set for
** the [prepared statement] S.
**
-** {F13830} The [sqlite3_column_value(S,N)] interface returns a
+** {H13830} The [sqlite3_column_value(S,N)] interface returns a
** pointer to an [unprotected sqlite3_value] object for the
** Nth column in the current row of the result set for
** the [prepared statement] S.
*/
@@ -4100,9 +4354,9 @@
SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
/*
-** CAPI3REF: Destroy A Prepared Statement Object {F13300}
+** CAPI3REF: Destroy A Prepared Statement Object {H13300} <S70300><S30100>
**
** The sqlite3_finalize() function is called to delete a [prepared statement].
** If the statement was executed successfully or not executed at all, then
** SQLITE_OK is returned. If execution of the statement failed then an
@@ -4117,46 +4371,46 @@
** [error code] returned will be [SQLITE_ABORT].
**
** INVARIANTS:
**
-** {F11302} The [sqlite3_finalize(S)] interface destroys the
+** {H11302} The [sqlite3_finalize(S)] interface destroys the
** [prepared statement] S and releases all
** memory and file resources held by that object.
**
-** {F11304} If the most recent call to [sqlite3_step(S)] for the
+** {H11304} If the most recent call to [sqlite3_step(S)] for the
** [prepared statement] S returned an error,
** then [sqlite3_finalize(S)] returns that same error.
*/
SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
/*
-** CAPI3REF: Reset A Prepared Statement Object {F13330}
+** CAPI3REF: Reset A Prepared Statement Object {H13330} <S70300>
**
** The sqlite3_reset() function is called to reset a [prepared statement]
** object back to its initial state, ready to be re-executed.
** Any SQL statement variables that had values bound to them using
** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values.
** Use [sqlite3_clear_bindings()] to reset the bindings.
**
-** {F11332} The [sqlite3_reset(S)] interface resets the [prepared statement] S
+** {H11332} The [sqlite3_reset(S)] interface resets the [prepared statement] S
** back to the beginning of its program.
**
-** {F11334} If the most recent call to [sqlite3_step(S)] for the
+** {H11334} If the most recent call to [sqlite3_step(S)] for the
** [prepared statement] S returned [SQLITE_ROW] or [SQLITE_DONE],
** or if [sqlite3_step(S)] has never before been called on S,
** then [sqlite3_reset(S)] returns [SQLITE_OK].
**
-** {F11336} If the most recent call to [sqlite3_step(S)] for the
+** {H11336} If the most recent call to [sqlite3_step(S)] for the
** [prepared statement] S indicated an error, then
** [sqlite3_reset(S)] returns an appropriate [error code].
**
-** {F11338} The [sqlite3_reset(S)] interface does not change the values
+** {H11338} The [sqlite3_reset(S)] interface does not change the values
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
*/
SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
/*
-** CAPI3REF: Create Or Redefine SQL Functions {F16100}
+** CAPI3REF: Create Or Redefine SQL Functions {H16100} <S20200>
** KEYWORDS: {function creation routines}
** KEYWORDS: {application-defined SQL function}
** KEYWORDS: {application-defined SQL functions}
**
@@ -4177,9 +4431,10 @@
** the zero-terminator. Note that the name length limit is in bytes, not
** 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.
**
** The fourth parameter, eTextRep, specifies what
@@ -4208,74 +4463,93 @@
** It is permitted to register multiple implementations of the same
** 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.
-**
-** INVARIANTS:
-**
-** {F16103} 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
+** 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(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.
**
-** {F16106} 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.
**
-** {F16109} 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
+** {H16109} A successful call to [sqlite3_create_function(D,X,N,E,P,F,S,L)]
+** shall replace the P, F, S, and L values from any prior calls with
** the same D, X, N, and E values.
**
-** {F16112} 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.
**
-** {F16118} 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].
-**
-** {F16121} The [sqlite3_create_function(D,...)] interface fails with an
+** {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 shall fails with an
** error code of [SQLITE_BUSY] if there exist [prepared statements]
** associated with the [database connection] D.
**
-** {F16124} 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.
**
-** {F16127} When N is non-negative, the [sqlite3_create_function(D,X,N,...)]
-** interface causes callbacks to be invoked for the SQL function
+** {H16127} When N is non-negative, the [sqlite3_create_function(D,X,N,...)]
+** 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.
**
-** {F16130} 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.
-**
-** {F16133} When calls to [sqlite3_create_function(D,X,N,...)]
+** {H16130} When N is -1, the [sqlite3_create_function(D,X,N,...)]
+** interface shall register callbacks to be invoked for the SQL
+** function named X with any number of arguments.
+**
+** {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.
-**
-** {F16136} When calls to [sqlite3_create_function(D,X,N,E,...)]
+** 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.
-**
-** {F16139} For an aggregate SQL function created using
+** 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.
**
-** {F16142} When SQLite invokes either the xFunc or xStep function of
+** {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,
const char *zFunctionName,
@@ -4297,9 +4571,9 @@
void (*xFinal)(sqlite3_context*)
);
/*
-** CAPI3REF: Text Encodings {F10267}
+** CAPI3REF: Text Encodings {H10267} <S50200> <H16100>
**
** These constant define integer codes that represent the various
** text encodings supported by SQLite.
*/
@@ -4310,25 +4584,28 @@
#define SQLITE_ANY 5 /* sqlite3_create_function only */
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
/*
-** CAPI3REF: Obsolete Functions
-**
-** These functions are all now obsolete. In order to maintain
-** backwards compatibility with older code, we continue to support
-** these functions. However, new development projects should avoid
+** CAPI3REF: Deprecated Functions
+** DEPRECATED
+**
+** These functions are [deprecated]. In order to maintain
+** 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.
*/
-SQLITE_API int sqlite3_aggregate_count(sqlite3_context*);
-SQLITE_API int sqlite3_expired(sqlite3_stmt*);
-SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
-SQLITE_API int sqlite3_global_recover(void);
-SQLITE_API void sqlite3_thread_cleanup(void);
-SQLITE_API int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
-
-/*
-** CAPI3REF: Obtaining SQL Function Parameter Values {F15100}
+#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>
**
** The C-language implementation of SQL functions and aggregates uses
** this set of interface routines to access the parameter values on
** the function or aggregate.
@@ -4372,61 +4649,61 @@
** the SQL function that supplied the [sqlite3_value*] parameters.
**
** INVARIANTS:
**
-** {F15103} The [sqlite3_value_blob(V)] interface converts the
+** {H15103} The [sqlite3_value_blob(V)] interface converts the
** [protected sqlite3_value] object V into a BLOB and then
** returns a pointer to the converted value.
**
-** {F15106} The [sqlite3_value_bytes(V)] interface returns the
+** {H15106} The [sqlite3_value_bytes(V)] interface returns the
** number of bytes in the BLOB or string (exclusive of the
** zero terminator on the string) that was returned by the
** most recent call to [sqlite3_value_blob(V)] or
** [sqlite3_value_text(V)].
**
-** {F15109} The [sqlite3_value_bytes16(V)] interface returns the
+** {H15109} The [sqlite3_value_bytes16(V)] interface returns the
** number of bytes in the string (exclusive of the
** zero terminator on the string) that was returned by the
** most recent call to [sqlite3_value_text16(V)],
** [sqlite3_value_text16be(V)], or [sqlite3_value_text16le(V)].
**
-** {F15112} The [sqlite3_value_double(V)] interface converts the
+** {H15112} The [sqlite3_value_double(V)] interface converts the
** [protected sqlite3_value] object V into a floating point value and
** returns a copy of that value.
**
-** {F15115} The [sqlite3_value_int(V)] interface converts the
+** {H15115} The [sqlite3_value_int(V)] interface converts the
** [protected sqlite3_value] object V into a 64-bit signed integer and
** returns the lower 32 bits of that integer.
**
-** {F15118} The [sqlite3_value_int64(V)] interface converts the
+** {H15118} The [sqlite3_value_int64(V)] interface converts the
** [protected sqlite3_value] object V into a 64-bit signed integer and
** returns a copy of that integer.
**
-** {F15121} The [sqlite3_value_text(V)] interface converts the
+** {H15121} The [sqlite3_value_text(V)] interface converts the
** [protected sqlite3_value] object V into a zero-terminated UTF-8
** string and returns a pointer to that string.
**
-** {F15124} The [sqlite3_value_text16(V)] interface converts the
+** {H15124} The [sqlite3_value_text16(V)] interface converts the
** [protected sqlite3_value] object V into a zero-terminated 2-byte
** aligned UTF-16 native byte order
** string and returns a pointer to that string.
**
-** {F15127} The [sqlite3_value_text16be(V)] interface converts the
+** {H15127} The [sqlite3_value_text16be(V)] interface converts the
** [protected sqlite3_value] object V into a zero-terminated 2-byte
** aligned UTF-16 big-endian
** string and returns a pointer to that string.
**
-** {F15130} The [sqlite3_value_text16le(V)] interface converts the
+** {H15130} The [sqlite3_value_text16le(V)] interface converts the
** [protected sqlite3_value] object V into a zero-terminated 2-byte
** aligned UTF-16 little-endian
** string and returns a pointer to that string.
**
-** {F15133} The [sqlite3_value_type(V)] interface returns
+** {H15133} The [sqlite3_value_type(V)] interface returns
** one of [SQLITE_NULL], [SQLITE_INTEGER], [SQLITE_FLOAT],
** [SQLITE_TEXT], or [SQLITE_BLOB] as appropriate for
** the [sqlite3_value] object V.
**
-** {F15136} The [sqlite3_value_numeric_type(V)] interface converts
+** {H15136} The [sqlite3_value_numeric_type(V)] interface converts
** the [protected sqlite3_value] object V into either an integer or
** a floating point value if it can do so without loss of
** information, and returns one of [SQLITE_NULL],
** [SQLITE_INTEGER], [SQLITE_FLOAT], [SQLITE_TEXT], or
@@ -4446,9 +4723,9 @@
SQLITE_API int sqlite3_value_type(sqlite3_value*);
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
/*
-** CAPI3REF: Obtain Aggregate Function Context {F16210}
+** CAPI3REF: Obtain Aggregate Function Context {H16210} <S20200>
**
** The implementation of aggregate SQL functions use this routine to allocate
** a structure for storing their state.
**
@@ -4470,30 +4747,30 @@
** the aggregate SQL function is running.
**
** INVARIANTS:
**
-** {F16211} The first invocation of [sqlite3_aggregate_context(C,N)] for
+** {H16211} The first invocation of [sqlite3_aggregate_context(C,N)] for
** a particular instance of an aggregate function (for a particular
** context C) causes SQLite to allocate N bytes of memory,
** zero that memory, and return a pointer to the allocated memory.
**
-** {F16213} If a memory allocation error occurs during
+** {H16213} If a memory allocation error occurs during
** [sqlite3_aggregate_context(C,N)] then the function returns 0.
**
-** {F16215} Second and subsequent invocations of
+** {H16215} Second and subsequent invocations of
** [sqlite3_aggregate_context(C,N)] for the same context pointer C
** ignore the N parameter and return a pointer to the same
** block of memory returned by the first invocation.
**
-** {F16217} The memory allocated by [sqlite3_aggregate_context(C,N)] is
+** {H16217} The memory allocated by [sqlite3_aggregate_context(C,N)] is
** automatically freed on the next call to [sqlite3_reset()]
** or [sqlite3_finalize()] for the [prepared statement] containing
** the aggregate function associated with context C.
*/
SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
/*
-** CAPI3REF: User Data For Functions {F16240}
+** CAPI3REF: User Data For Functions {H16240} <S20200>
**
** The sqlite3_user_data() interface returns a copy of
** the pointer that was the pUserData parameter (the 5th parameter)
** of the [sqlite3_create_function()]
@@ -4504,17 +4781,17 @@
** the application-defined function is running.
**
** INVARIANTS:
**
-** {F16243} The [sqlite3_user_data(C)] interface returns a copy of the
+** {H16243} The [sqlite3_user_data(C)] interface returns a copy of the
** P pointer from the [sqlite3_create_function(D,X,N,E,P,F,S,L)]
** or [sqlite3_create_function16(D,X,N,E,P,F,S,L)] call that
** registered the SQL function associated with [sqlite3_context] C.
*/
SQLITE_API void *sqlite3_user_data(sqlite3_context*);
/*
-** CAPI3REF: Database Connection For Functions {F16250}
+** CAPI3REF: Database Connection For Functions {H16250} <S60600><S20200>
**
** The sqlite3_context_db_handle() interface returns a copy of
** the pointer to the [database connection] (the 1st parameter)
** of the [sqlite3_create_function()]
@@ -4522,17 +4799,17 @@
** registered the application defined function.
**
** INVARIANTS:
**
-** {F16253} The [sqlite3_context_db_handle(C)] interface returns a copy of the
+** {H16253} The [sqlite3_context_db_handle(C)] interface returns a copy of the
** D pointer from the [sqlite3_create_function(D,X,N,E,P,F,S,L)]
** or [sqlite3_create_function16(D,X,N,E,P,F,S,L)] call that
** registered the SQL function associated with [sqlite3_context] C.
*/
SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
/*
-** CAPI3REF: Function Auxiliary Data {F16270}
+** CAPI3REF: Function Auxiliary Data {H16270} <S20200>
**
** The following two functions may be used by scalar SQL functions to
** associate metadata with argument values. If the same value is passed to
** multiple invocations of the same SQL function during query execution, under
@@ -4573,29 +4850,29 @@
** the SQL function is running.
**
** INVARIANTS:
**
-** {F16272} The [sqlite3_get_auxdata(C,N)] interface returns a pointer
+** {H16272} The [sqlite3_get_auxdata(C,N)] interface returns a pointer
** to metadata associated with the Nth parameter of the SQL function
** whose context is C, or NULL if there is no metadata associated
** with that parameter.
**
-** {F16274} The [sqlite3_set_auxdata(C,N,P,D)] interface assigns a metadata
+** {H16274} The [sqlite3_set_auxdata(C,N,P,D)] interface assigns a metadata
** pointer P to the Nth parameter of the SQL function with context C.
**
-** {F16276} SQLite will invoke the destructor D with a single argument
+** {H16276} SQLite will invoke the destructor D with a single argument
** which is the metadata pointer P following a call to
** [sqlite3_set_auxdata(C,N,P,D)] when SQLite ceases to hold
** the metadata.
**
-** {F16277} SQLite ceases to hold metadata for an SQL function parameter
+** {H16277} SQLite ceases to hold metadata for an SQL function parameter
** when the value of that parameter changes.
**
-** {F16278} When [sqlite3_set_auxdata(C,N,P,D)] is invoked, the destructor
+** {H16278} When [sqlite3_set_auxdata(C,N,P,D)] is invoked, the destructor
** is called for any prior metadata associated with the same function
** context C and parameter N.
**
-** {F16279} SQLite will call destructors for any metadata it is holding
+** {H16279} SQLite will call destructors for any metadata it is holding
** in a particular [prepared statement] S when either
** [sqlite3_reset(S)] or [sqlite3_finalize(S)] is called.
*/
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
@@ -4602,9 +4879,9 @@
SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
/*
-** CAPI3REF: Constants Defining Special Destructor Behavior {F10280}
+** CAPI3REF: Constants Defining Special Destructor Behavior {H10280} <S30100>
**
** These are special values for the destructor that is passed in as the
** final argument to routines like [sqlite3_result_blob()]. If the destructor
** argument is SQLITE_STATIC, it means that the content pointer is constant
@@ -4620,9 +4897,9 @@
#define SQLITE_STATIC ((sqlite3_destructor_type)0)
#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
/*
-** CAPI3REF: Setting The Result Of An SQL Function {F16400}
+** CAPI3REF: Setting The Result Of An SQL Function {H16400} <S20200>
**
** These routines are used by the xFunc or xFinal callbacks that
** implement SQL functions and aggregates. See
** [sqlite3_create_function()] and [sqlite3_create_function16()]
@@ -4725,95 +5002,95 @@
** the [sqlite3_context] pointer, the results are undefined.
**
** INVARIANTS:
**
-** {F16403} The default return value from any SQL function is NULL.
-**
-** {F16406} The [sqlite3_result_blob(C,V,N,D)] interface changes the
+** {H16403} The default return value from any SQL function is NULL.
+**
+** {H16406} The [sqlite3_result_blob(C,V,N,D)] interface changes the
** return value of function C to be a BLOB that is N bytes
** in length and with content pointed to by V.
**
-** {F16409} The [sqlite3_result_double(C,V)] interface changes the
+** {H16409} The [sqlite3_result_double(C,V)] interface changes the
** return value of function C to be the floating point value V.
**
-** {F16412} The [sqlite3_result_error(C,V,N)] interface changes the return
+** {H16412} The [sqlite3_result_error(C,V,N)] interface changes the return
** value of function C to be an exception with error code
** [SQLITE_ERROR] and a UTF-8 error message copied from V up to the
** first zero byte or until N bytes are read if N is positive.
**
-** {F16415} The [sqlite3_result_error16(C,V,N)] interface changes the return
+** {H16415} The [sqlite3_result_error16(C,V,N)] interface changes the return
** value of function C to be an exception with error code
** [SQLITE_ERROR] and a UTF-16 native byte order error message
** copied from V up to the first zero terminator or until N bytes
** are read if N is positive.
**
-** {F16418} The [sqlite3_result_error_toobig(C)] interface changes the return
+** {H16418} The [sqlite3_result_error_toobig(C)] interface changes the return
** value of the function C to be an exception with error code
** [SQLITE_TOOBIG] and an appropriate error message.
**
-** {F16421} The [sqlite3_result_error_nomem(C)] interface changes the return
+** {H16421} The [sqlite3_result_error_nomem(C)] interface changes the return
** value of the function C to be an exception with error code
** [SQLITE_NOMEM] and an appropriate error message.
**
-** {F16424} The [sqlite3_result_error_code(C,E)] interface changes the return
+** {H16424} The [sqlite3_result_error_code(C,E)] interface changes the return
** value of the function C to be an exception with error code E.
** The error message text is unchanged.
**
-** {F16427} The [sqlite3_result_int(C,V)] interface changes the
+** {H16427} The [sqlite3_result_int(C,V)] interface changes the
** return value of function C to be the 32-bit integer value V.
**
-** {F16430} The [sqlite3_result_int64(C,V)] interface changes the
+** {H16430} The [sqlite3_result_int64(C,V)] interface changes the
** return value of function C to be the 64-bit integer value V.
**
-** {F16433} The [sqlite3_result_null(C)] interface changes the
+** {H16433} The [sqlite3_result_null(C)] interface changes the
** return value of function C to be NULL.
**
-** {F16436} The [sqlite3_result_text(C,V,N,D)] interface changes the
+** {H16436} The [sqlite3_result_text(C,V,N,D)] interface changes the
** return value of function C to be the UTF-8 string
** V up to the first zero if N is negative
** or the first N bytes of V if N is non-negative.
**
-** {F16439} The [sqlite3_result_text16(C,V,N,D)] interface changes the
+** {H16439} The [sqlite3_result_text16(C,V,N,D)] interface changes the
** return value of function C to be the UTF-16 native byte order
** string V up to the first zero if N is negative
** or the first N bytes of V if N is non-negative.
**
-** {F16442} The [sqlite3_result_text16be(C,V,N,D)] interface changes the
+** {H16442} The [sqlite3_result_text16be(C,V,N,D)] interface changes the
** return value of function C to be the UTF-16 big-endian
** string V up to the first zero if N is negative
** or the first N bytes or V if N is non-negative.
**
-** {F16445} The [sqlite3_result_text16le(C,V,N,D)] interface changes the
+** {H16445} The [sqlite3_result_text16le(C,V,N,D)] interface changes the
** return value of function C to be the UTF-16 little-endian
** string V up to the first zero if N is negative
** or the first N bytes of V if N is non-negative.
**
-** {F16448} The [sqlite3_result_value(C,V)] interface changes the
+** {H16448} The [sqlite3_result_value(C,V)] interface changes the
** return value of function C to be the [unprotected sqlite3_value]
** object V.
**
-** {F16451} The [sqlite3_result_zeroblob(C,N)] interface changes the
+** {H16451} The [sqlite3_result_zeroblob(C,N)] interface changes the
** return value of function C to be an N-byte BLOB of all zeros.
**
-** {F16454} The [sqlite3_result_error()] and [sqlite3_result_error16()]
+** {H16454} The [sqlite3_result_error()] and [sqlite3_result_error16()]
** interfaces make a copy of their error message strings before
** returning.
**
-** {F16457} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** {H16457} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
** [sqlite3_result_text16be(C,V,N,D)], or
** [sqlite3_result_text16le(C,V,N,D)] is the constant [SQLITE_STATIC]
** then no destructor is ever called on the pointer V and SQLite
** assumes that V is immutable.
**
-** {F16460} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** {H16460} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
** [sqlite3_result_text16be(C,V,N,D)], or
** [sqlite3_result_text16le(C,V,N,D)] is the constant
** [SQLITE_TRANSIENT] then the interfaces makes a copy of the
** content of V and retains the copy.
**
-** {F16463} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
+** {H16463} If the D destructor parameter to [sqlite3_result_blob(C,V,N,D)],
** [sqlite3_result_text(C,V,N,D)], [sqlite3_result_text16(C,V,N,D)],
** [sqlite3_result_text16be(C,V,N,D)], or
** [sqlite3_result_text16le(C,V,N,D)] is some value other than
** the constants [SQLITE_STATIC] and [SQLITE_TRANSIENT] then
@@ -4837,9 +5114,9 @@
SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
/*
-** CAPI3REF: Define New Collating Sequences {F16600}
+** CAPI3REF: Define New Collating Sequences {H16600} <S20300>
**
** These functions are used to add new collation sequences to the
** [database connection] specified as the first argument.
**
@@ -4880,51 +5157,51 @@
** using [sqlite3_close()].
**
** INVARIANTS:
**
-** {F16603} A successful call to the
+** {H16603} A successful call to the
** [sqlite3_create_collation_v2(B,X,E,P,F,D)] interface
** registers function F as the comparison function used to
** implement collation X on the [database connection] B for
** databases having encoding E.
**
-** {F16604} SQLite understands the X parameter to
+** {H16604} SQLite understands the X parameter to
** [sqlite3_create_collation_v2(B,X,E,P,F,D)] as a zero-terminated
** UTF-8 string in which case is ignored for ASCII characters and
** is significant for non-ASCII characters.
**
-** {F16606} Successive calls to [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** {H16606} Successive calls to [sqlite3_create_collation_v2(B,X,E,P,F,D)]
** with the same values for B, X, and E, override prior values
** of P, F, and D.
**
-** {F16609} If the destructor D in [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** {H16609} If the destructor D in [sqlite3_create_collation_v2(B,X,E,P,F,D)]
** is not NULL then it is called with argument P when the
** collating function is dropped by SQLite.
**
-** {F16612} A collating function is dropped when it is overloaded.
-**
-** {F16615} A collating function is dropped when the database connection
+** {H16612} A collating function is dropped when it is overloaded.
+**
+** {H16615} A collating function is dropped when the database connection
** is closed using [sqlite3_close()].
**
-** {F16618} The pointer P in [sqlite3_create_collation_v2(B,X,E,P,F,D)]
+** {H16618} The pointer P in [sqlite3_create_collation_v2(B,X,E,P,F,D)]
** is passed through as the first parameter to the comparison
** function F for all subsequent invocations of F.
**
-** {F16621} A call to [sqlite3_create_collation(B,X,E,P,F)] is exactly
+** {H16621} A call to [sqlite3_create_collation(B,X,E,P,F)] is exactly
** the same as a call to [sqlite3_create_collation_v2()] with
** the same parameters and a NULL destructor.
**
-** {F16624} Following a [sqlite3_create_collation_v2(B,X,E,P,F,D)],
+** {H16624} Following a [sqlite3_create_collation_v2(B,X,E,P,F,D)],
** SQLite uses the comparison function F for all text comparison
** operations on the [database connection] B on text values that
** use the collating sequence named X.
**
-** {F16627} The [sqlite3_create_collation16(B,X,E,P,F)] works the same
+** {H16627} The [sqlite3_create_collation16(B,X,E,P,F)] works the same
** as [sqlite3_create_collation(B,X,E,P,F)] except that the
** collation name X is understood as UTF-16 in native byte order
** instead of UTF-8.
**
-** {F16630} When multiple comparison functions are available for the same
+** {H16630} When multiple comparison functions are available for the same
** collating sequence, SQLite chooses the one whose text encoding
** requires the least amount of conversion from the default
** text encoding of the database.
*/
@@ -4951,9 +5228,9 @@
int(*xCompare)(void*,int,const void*,int,const void*)
);
/*
-** CAPI3REF: Collation Needed Callbacks {F16700}
+** CAPI3REF: Collation Needed Callbacks {H16700} <S20300>
**
** To avoid having to register all collation sequences before a database
** can be used, a single callback function may be registered with the
** [database connection] to be called whenever an undefined collation
@@ -4960,9 +5237,9 @@
** sequence is required.
**
** If the function is registered using the sqlite3_collation_needed() API,
** then it is passed the names of undefined collation sequences as strings
-** encoded in UTF-8. {F16703} If sqlite3_collation_needed16() is used,
+** encoded in UTF-8. {H16703} If sqlite3_collation_needed16() is used,
** the names are passed as UTF-16 in machine native byte order.
** A call to either function replaces any existing callback.
**
** When the callback is invoked, the first argument passed is a copy
@@ -4978,20 +5255,20 @@
** [sqlite3_create_collation_v2()].
**
** INVARIANTS:
**
-** {F16702} A successful call to [sqlite3_collation_needed(D,P,F)]
+** {H16702} A successful call to [sqlite3_collation_needed(D,P,F)]
** or [sqlite3_collation_needed16(D,P,F)] causes
** the [database connection] D to invoke callback F with first
** parameter P whenever it needs a comparison function for a
** collating sequence that it does not know about.
**
-** {F16704} Each successful call to [sqlite3_collation_needed()] or
+** {H16704} Each successful call to [sqlite3_collation_needed()] or
** [sqlite3_collation_needed16()] overrides the callback registered
** on the same [database connection] by prior calls to either
** interface.
**
-** {F16706} The name of the requested collating function passed in the
+** {H16706} The name of the requested collating function passed in the
** 4th parameter to the callback is in UTF-8 if the callback
** was registered using [sqlite3_collation_needed()] and
** is in UTF-16 native byte order if the callback was
** registered using [sqlite3_collation_needed16()].
@@ -5032,9 +5309,9 @@
const void *pKey, int nKey /* The new key */
);
/*
-** CAPI3REF: Suspend Execution For A Short Time {F10530}
+** CAPI3REF: Suspend Execution For A Short Time {H10530} <S40410>
**
** The sqlite3_sleep() function causes the current thread to suspend execution
** for at least a number of milliseconds specified in its parameter.
**
@@ -5047,21 +5324,21 @@
** method of the default [sqlite3_vfs] object.
**
** INVARIANTS:
**
-** {F10533} The [sqlite3_sleep(M)] interface invokes the xSleep
+** {H10533} The [sqlite3_sleep(M)] interface invokes the xSleep
** method of the default [sqlite3_vfs|VFS] in order to
** suspend execution of the current thread for at least
** M milliseconds.
**
-** {F10536} The [sqlite3_sleep(M)] interface returns the number of
+** {H10536} The [sqlite3_sleep(M)] interface returns the number of
** milliseconds of sleep actually requested of the operating
** system, which might be larger than the parameter M.
*/
SQLITE_API int sqlite3_sleep(int);
/*
-** CAPI3REF: Name Of The Folder Holding Temporary Files {F10310}
+** CAPI3REF: Name Of The Folder Holding Temporary Files {H10310} <S20000>
**
** If this global variable is made to point to a string which is
** the name of a folder (a.k.a. directory), then all temporary files
** created by SQLite will be placed in that directory. If this variable
@@ -5075,9 +5352,9 @@
*/
SQLITE_API char *sqlite3_temp_directory;
/*
-** CAPI3REF: Test To See If The Database Is In Auto-Commit Mode {F12930}
+** CAPI3REF: Test For Auto-Commit Mode {H12930} <S60200>
** KEYWORDS: {autocommit mode}
**
** The sqlite3_get_autocommit() interface returns non-zero or
** zero if the given database connection is or is not in autocommit mode,
@@ -5093,20 +5370,20 @@
** an error is to use this function.
**
** INVARIANTS:
**
-** {F12931} The [sqlite3_get_autocommit(D)] interface returns non-zero or
+** {H12931} The [sqlite3_get_autocommit(D)] interface returns non-zero or
** zero if the [database connection] D is or is not in autocommit
** mode, respectively.
**
-** {F12932} Autocommit mode is on by default.
-**
-** {F12933} Autocommit mode is disabled by a successful [BEGIN] statement.
-**
-** {F12934} Autocommit mode is enabled by a successful [COMMIT] or [ROLLBACK]
+** {H12932} Autocommit mode is on by default.
+**
+** {H12933} Autocommit mode is disabled by a successful [BEGIN] statement.
+**
+** {H12934} Autocommit mode is enabled by a successful [COMMIT] or [ROLLBACK]
** statement.
**
-** LIMITATIONS:
+** ASSUMPTIONS:
**
** {A12936} If another thread changes the autocommit status of the database
** connection while this routine is running, then the return value
** is undefined.
@@ -5113,9 +5390,9 @@
*/
SQLITE_API int sqlite3_get_autocommit(sqlite3*);
/*
-** CAPI3REF: Find The Database Handle Of A Prepared Statement {F13120}
+** CAPI3REF: Find The Database Handle Of A Prepared Statement {H13120} <S60600>
**
** The sqlite3_db_handle interface returns the [database connection] handle
** to which a [prepared statement] belongs. The database handle returned by
** sqlite3_db_handle is the same database handle that was the first argument
@@ -5123,16 +5400,16 @@
** create the statement in the first place.
**
** INVARIANTS:
**
-** {F13123} The [sqlite3_db_handle(S)] interface returns a pointer
+** {H13123} The [sqlite3_db_handle(S)] interface returns a pointer
** to the [database connection] associated with the
** [prepared statement] S.
*/
SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
/*
-** CAPI3REF: Find the next prepared statement {F13140}
+** CAPI3REF: Find the next prepared statement {H13140} <S60600>
**
** This interface returns a pointer to the next [prepared statement] after
** pStmt associated with the [database connection] pDb. If pStmt is NULL
** then this interface returns a pointer to the first prepared statement
@@ -5140,30 +5417,36 @@
** satisfies the conditions of this routine, it returns NULL.
**
** INVARIANTS:
**
-** {F13143} If D is a [database connection] that holds one or more
+** {H13143} If D is a [database connection] that holds one or more
** unfinalized [prepared statements] and S is a NULL pointer,
** then [sqlite3_next_stmt(D, S)] routine shall return a pointer
** to one of the prepared statements associated with D.
**
-** {F13146} If D is a [database connection] that holds no unfinalized
+** {H13146} If D is a [database connection] that holds no unfinalized
** [prepared statements] and S is a NULL pointer, then
** [sqlite3_next_stmt(D, S)] routine shall return a NULL pointer.
**
-** {F13149} If S is a [prepared statement] in the [database connection] D
+** {H13149} If S is a [prepared statement] in the [database connection] D
** and S is not the last prepared statement in D, then
** [sqlite3_next_stmt(D, S)] routine shall return a pointer
** to the next prepared statement in D after S.
**
-** {F13152} If S is the last [prepared statement] in the
+** {H13152} If S is the last [prepared statement] in the
** [database connection] D then the [sqlite3_next_stmt(D, S)]
** routine shall return a NULL pointer.
+**
+** ASSUMPTIONS:
+**
+** {A13154} The [database connection] pointer D in a call to
+** [sqlite3_next_stmt(D,S)] must refer to an open database
+** connection and in particular must not be a NULL pointer.
*/
SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
/*
-** CAPI3REF: Commit And Rollback Notification Callbacks {F12950}
+** CAPI3REF: Commit And Rollback Notification Callbacks {H12950} <S60400>
**
** The sqlite3_commit_hook() interface registers a callback
** function to be invoked whenever a transaction is committed.
** Any callback set by a previous call to sqlite3_commit_hook()
@@ -5178,8 +5461,16 @@
**
** 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
** rolled back if an explicit "ROLLBACK" statement is executed, or
@@ -5189,51 +5480,49 @@
** The rollback callback is not invoked if a transaction is
** rolled back because a commit callback returned non-zero.
** <todo> Check on this </todo>
**
-** These are experimental interfaces and are subject to change.
-**
** INVARIANTS:
**
-** {F12951} The [sqlite3_commit_hook(D,F,P)] interface registers the
+** {H12951} The [sqlite3_commit_hook(D,F,P)] interface registers the
** callback function F to be invoked with argument P whenever
** a transaction commits on the [database connection] D.
**
-** {F12952} The [sqlite3_commit_hook(D,F,P)] interface returns the P argument
+** {H12952} The [sqlite3_commit_hook(D,F,P)] interface returns the P argument
** from the previous call with the same [database connection] D,
** or NULL on the first call for a particular database connection D.
**
-** {F12953} Each call to [sqlite3_commit_hook()] overwrites the callback
+** {H12953} Each call to [sqlite3_commit_hook()] overwrites the callback
** registered by prior calls.
**
-** {F12954} If the F argument to [sqlite3_commit_hook(D,F,P)] is NULL
+** {H12954} If the F argument to [sqlite3_commit_hook(D,F,P)] is NULL
** then the commit hook callback is canceled and no callback
** is invoked when a transaction commits.
**
-** {F12955} If the commit callback returns non-zero then the commit is
+** {H12955} If the commit callback returns non-zero then the commit is
** converted into a rollback.
**
-** {F12961} The [sqlite3_rollback_hook(D,F,P)] interface registers the
+** {H12961} The [sqlite3_rollback_hook(D,F,P)] interface registers the
** callback function F to be invoked with argument P whenever
** a transaction rolls back on the [database connection] D.
**
-** {F12962} The [sqlite3_rollback_hook(D,F,P)] interface returns the P
+** {H12962} The [sqlite3_rollback_hook(D,F,P)] interface returns the P
** argument from the previous call with the same
** [database connection] D, or NULL on the first call
** for a particular database connection D.
**
-** {F12963} Each call to [sqlite3_rollback_hook()] overwrites the callback
+** {H12963} Each call to [sqlite3_rollback_hook()] overwrites the callback
** registered by prior calls.
**
-** {F12964} If the F argument to [sqlite3_rollback_hook(D,F,P)] is NULL
+** {H12964} If the F argument to [sqlite3_rollback_hook(D,F,P)] is NULL
** then the rollback hook callback is canceled and no callback
** is invoked when a transaction rolls back.
*/
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
-** CAPI3REF: Data Change Notification Callbacks {F12970}
+** CAPI3REF: Data Change Notification Callbacks {H12970} <S60400>
**
** The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
** to be invoked whenever a row is updated, inserted or deleted.
@@ -5254,40 +5543,47 @@
**
** 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.
**
** INVARIANTS:
**
-** {F12971} The [sqlite3_update_hook(D,F,P)] interface causes the callback
+** {H12971} The [sqlite3_update_hook(D,F,P)] interface causes the callback
** function F to be invoked with first parameter P whenever
** a table row is modified, inserted, or deleted on
** the [database connection] D.
**
-** {F12973} The [sqlite3_update_hook(D,F,P)] interface returns the value
+** {H12973} The [sqlite3_update_hook(D,F,P)] interface returns the value
** of P for the previous call on the same [database connection] D,
** or NULL for the first call.
**
-** {F12975} If the update hook callback F in [sqlite3_update_hook(D,F,P)]
+** {H12975} If the update hook callback F in [sqlite3_update_hook(D,F,P)]
** is NULL then the no update callbacks are made.
**
-** {F12977} Each call to [sqlite3_update_hook(D,F,P)] overrides prior calls
+** {H12977} Each call to [sqlite3_update_hook(D,F,P)] overrides prior calls
** to the same interface on the same [database connection] D.
**
-** {F12979} The update hook callback is not invoked when internal system
+** {H12979} The update hook callback is not invoked when internal system
** tables such as sqlite_master and sqlite_sequence are modified.
**
-** {F12981} The second parameter to the update callback
+** {H12981} The second parameter to the update callback
** is one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
** depending on the operation that caused the callback to be invoked.
**
-** {F12983} The third and fourth arguments to the callback contain pointers
+** {H12983} The third and fourth arguments to the callback contain pointers
** to zero-terminated UTF-8 strings which are the names of the
** database and table that is being updated.
-** {F12985} The final callback parameter is the rowid of the row after
+** {H12985} The final callback parameter is the rowid of the row after
** the change occurs.
*/
SQLITE_API void *sqlite3_update_hook(
sqlite3*,
@@ -5295,9 +5591,9 @@
void*
);
/*
-** CAPI3REF: Enable Or Disable Shared Pager Cache {F10330}
+** CAPI3REF: Enable Or Disable Shared Pager Cache {H10330} <S30900>
** KEYWORDS: {shared cache} {shared cache mode}
**
** This routine enables or disables the sharing of the database cache
** and schema data structures between [database connection | connections]
@@ -5325,24 +5621,24 @@
** cache setting should set it explicitly.
**
** INVARIANTS:
**
-** {F10331} A successful invocation of [sqlite3_enable_shared_cache(B)]
+** {H10331} A successful invocation of [sqlite3_enable_shared_cache(B)]
** will enable or disable shared cache mode for any subsequently
** created [database connection] in the same process.
**
-** {F10336} When shared cache is enabled, the [sqlite3_create_module()]
+** {H10336} When shared cache is enabled, the [sqlite3_create_module()]
** interface will always return an error.
**
-** {F10337} The [sqlite3_enable_shared_cache(B)] interface returns
+** {H10337} The [sqlite3_enable_shared_cache(B)] interface returns
** [SQLITE_OK] if shared cache was enabled or disabled successfully.
**
-** {F10339} Shared cache is disabled by default.
+** {H10339} Shared cache is disabled by default.
*/
SQLITE_API int sqlite3_enable_shared_cache(int);
/*
-** CAPI3REF: Attempt To Free Heap Memory {F17340}
+** CAPI3REF: Attempt To Free Heap Memory {H17340} <S30220>
**
** The sqlite3_release_memory() interface attempts to free N bytes
** of heap memory by deallocating non-essential memory allocations
** held by the database library. {END} Memory used to cache database
@@ -5351,20 +5647,20 @@
** which might be more or less than the amount requested.
**
** INVARIANTS:
**
-** {F17341} The [sqlite3_release_memory(N)] interface attempts to
+** {H17341} The [sqlite3_release_memory(N)] interface attempts to
** free N bytes of heap memory by deallocating non-essential
** memory allocations held by the database library.
**
-** {F16342} The [sqlite3_release_memory(N)] returns the number
+** {H16342} The [sqlite3_release_memory(N)] returns the number
** of bytes actually freed, which might be more or less
** than the amount requested.
*/
SQLITE_API int sqlite3_release_memory(int);
/*
-** CAPI3REF: Impose A Limit On Heap Size {F17350}
+** CAPI3REF: Impose A Limit On Heap Size {H17350} <S30220>
**
** The sqlite3_soft_heap_limit() interface places a "soft" limit
** on the amount of heap memory that may be allocated by SQLite.
** If an internal allocation is requested that would exceed the
@@ -5393,38 +5689,38 @@
** individual threads.
**
** INVARIANTS:
**
-** {F16351} The [sqlite3_soft_heap_limit(N)] interface places a soft limit
+** {H16351} The [sqlite3_soft_heap_limit(N)] interface places a soft limit
** of N bytes on the amount of heap memory that may be allocated
** using [sqlite3_malloc()] or [sqlite3_realloc()] at any point
** in time.
**
-** {F16352} If a call to [sqlite3_malloc()] or [sqlite3_realloc()] would
+** {H16352} If a call to [sqlite3_malloc()] or [sqlite3_realloc()] would
** cause the total amount of allocated memory to exceed the
** soft heap limit, then [sqlite3_release_memory()] is invoked
** in an attempt to reduce the memory usage prior to proceeding
** with the memory allocation attempt.
**
-** {F16353} Calls to [sqlite3_malloc()] or [sqlite3_realloc()] that trigger
+** {H16353} Calls to [sqlite3_malloc()] or [sqlite3_realloc()] that trigger
** attempts to reduce memory usage through the soft heap limit
** mechanism continue even if the attempt to reduce memory
** usage is unsuccessful.
**
-** {F16354} A negative or zero value for N in a call to
+** {H16354} A negative or zero value for N in a call to
** [sqlite3_soft_heap_limit(N)] means that there is no soft
** heap limit and [sqlite3_release_memory()] will only be
** called when memory is completely exhausted.
**
-** {F16355} The default value for the soft heap limit is zero.
-**
-** {F16358} Each call to [sqlite3_soft_heap_limit(N)] overrides the
+** {H16355} The default value for the soft heap limit is zero.
+**
+** {H16358} Each call to [sqlite3_soft_heap_limit(N)] overrides the
** values set by all prior calls.
*/
SQLITE_API void sqlite3_soft_heap_limit(int);
/*
-** CAPI3REF: Extract Metadata About A Column Of A Table {F12850}
+** CAPI3REF: Extract Metadata About A Column Of A Table {H12850} <S60300>
**
** This routine returns metadata about a specific column of a specific
** database table accessible using the [database connection] handle
** passed as the first function argument.
@@ -5496,30 +5792,30 @@
int *pAutoinc /* OUTPUT: True if column is auto-increment */
);
/*
-** CAPI3REF: Load An Extension {F12600}
+** CAPI3REF: Load An Extension {H12600} <S20500>
**
** This interface loads an SQLite extension library from the named file.
**
-** {F12601} The sqlite3_load_extension() interface attempts to load an
+** {H12601} The sqlite3_load_extension() interface attempts to load an
** SQLite extension library contained in the file zFile.
**
-** {F12602} The entry point is zProc.
-**
-** {F12603} zProc may be 0, in which case the name of the entry point
+** {H12602} The entry point is zProc.
+**
+** {H12603} zProc may be 0, in which case the name of the entry point
** defaults to "sqlite3_extension_init".
**
-** {F12604} The sqlite3_load_extension() interface shall return
+** {H12604} The sqlite3_load_extension() interface shall return
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
**
-** {F12605} If an error occurs and pzErrMsg is not 0, then the
+** {H12605} If an error occurs and pzErrMsg is not 0, then the
** [sqlite3_load_extension()] interface shall attempt to
** fill *pzErrMsg with error message text stored in memory
** obtained from [sqlite3_malloc()]. {END} The calling function
** should free this memory by calling [sqlite3_free()].
**
-** {F12606} Extension loading must be enabled using
+** {H12606} Extension loading must be enabled using
** [sqlite3_enable_load_extension()] prior to calling this API,
** otherwise an error will be returned.
*/
SQLITE_API int sqlite3_load_extension(
@@ -5529,9 +5825,9 @@
char **pzErrMsg /* Put error message here if not 0 */
);
/*
-** CAPI3REF: Enable Or Disable Extension Loading {F12620}
+** CAPI3REF: Enable Or Disable Extension Loading {H12620} <S20500>
**
** So as not to open security holes in older applications that are
** unprepared to deal with extension loading, and as a means of disabling
** extension loading while evaluating user-entered SQL, the following API
@@ -5538,18 +5834,18 @@
** is provided to turn the [sqlite3_load_extension()] mechanism on and off.
**
** Extension loading is off by default. See ticket #1863.
**
-** {F12621} Call the sqlite3_enable_load_extension() routine with onoff==1
+** {H12621} Call the sqlite3_enable_load_extension() routine with onoff==1
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
**
-** {F12622} Extension loading is off by default.
+** {H12622} Extension loading is off by default.
*/
SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
/*
-** CAPI3REF: Make Arrangements To Automatically Load An Extension {F12640}
+** CAPI3REF: Automatically Load An Extensions {H12640} <S20500>
**
** This API can be invoked at program startup in order to register
** one or more statically linked extensions that will be available
** to all new [database connections]. {END}
@@ -5558,40 +5854,34 @@
** obtained from [sqlite3_malloc()]. If you run a memory leak checker
** on your program and it reports a leak because of this array, invoke
** [sqlite3_reset_auto_extension()] prior to shutdown to free the memory.
**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
-**
-** {F12641} This function registers an extension entry point that is
+** {H12641} This function registers an extension entry point that is
** automatically invoked whenever a new [database connection]
** is opened using [sqlite3_open()], [sqlite3_open16()],
** or [sqlite3_open_v2()].
**
-** {F12642} Duplicate extensions are detected so calling this routine
+** {H12642} Duplicate extensions are detected so calling this routine
** multiple times with the same extension is harmless.
**
-** {F12643} This routine stores a pointer to the extension in an array
+** {H12643} This routine stores a pointer to the extension in an array
** that is obtained from [sqlite3_malloc()].
**
-** {F12644} Automatic extensions apply across all threads.
+** {H12644} Automatic extensions apply across all threads.
*/
SQLITE_API int sqlite3_auto_extension(void *xEntryPoint);
/*
-** CAPI3REF: Reset Automatic Extension Loading {F12660}
+** CAPI3REF: Reset Automatic Extension Loading {H12660} <S20500>
**
** This function disables all previously registered automatic
** extensions. {END} It undoes the effect of all prior
** [sqlite3_auto_extension()] calls.
**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
-**
-** {F12661} This function disables all previously registered
+** {H12661} This function disables all previously registered
** automatic extensions.
**
-** {F12662} This function disables automatic extensions in all threads.
+** {H12662} This function disables automatic extensions in all threads.
*/
SQLITE_API void sqlite3_reset_auto_extension(void);
/*
@@ -5613,10 +5903,11 @@
typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
typedef struct sqlite3_module sqlite3_module;
/*
-** CAPI3REF: Virtual Table Object {F18000}
+** CAPI3REF: Virtual Table Object {H18000} <S20400>
** KEYWORDS: sqlite3_module
+** EXPERIMENTAL
**
** A module is a class of virtual tables. Each module is defined
** by an instance of the following structure. This structure consists
** mostly of methods for the module.
@@ -5650,15 +5941,15 @@
int (*xRollback)(sqlite3_vtab *pVTab);
int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
void **ppArg);
-
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
};
/*
-** CAPI3REF: Virtual Table Indexing Information {F18100}
+** CAPI3REF: Virtual Table Indexing Information {H18100} <S20400>
** KEYWORDS: sqlite3_index_info
+** EXPERIMENTAL
**
** The sqlite3_index_info structure and its substructures is used to
** pass information into and receive the reply from the xBestIndex
** method of an sqlite3_module. The fields under **Inputs** are the
@@ -5719,9 +6010,8 @@
struct sqlite3_index_orderby {
int iColumn; /* Column number */
unsigned char desc; /* True for DESC. False for ASC. */
} *aOrderBy; /* The ORDER BY clause */
-
/* Outputs */
struct sqlite3_index_constraint_usage {
int argvIndex; /* if >0, constraint is part of argv to xFilter */
unsigned char omit; /* Do not code a test for this constraint */
@@ -5739,9 +6029,10 @@
#define SQLITE_INDEX_CONSTRAINT_GE 32
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
/*
-** CAPI3REF: Register A Virtual Table Implementation {F18200}
+** CAPI3REF: Register A Virtual Table Implementation {H18200} <S20400>
+** EXPERIMENTAL
**
** This routine is used to register a new module name with a
** [database connection]. Module names must be registered before
** creating new virtual tables on the module, or before using
@@ -5749,23 +6040,24 @@
**
** This interface is experimental and is subject to change or
** removal in future releases of SQLite.
*/
-SQLITE_API int sqlite3_create_module(
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *, /* Methods for the module */
void * /* Client data for xCreate/xConnect */
);
/*
-** CAPI3REF: Register A Virtual Table Implementation {F18210}
+** CAPI3REF: Register A Virtual Table Implementation {H18210} <S20400>
+** EXPERIMENTAL
**
** This routine is identical to the [sqlite3_create_module()] method above,
** except that it allows a destructor function to be specified. It is
** even more experimental than the rest of the virtual tables API.
*/
-SQLITE_API int sqlite3_create_module_v2(
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_create_module_v2(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *, /* Methods for the module */
void *, /* Client data for xCreate/xConnect */
@@ -5772,10 +6064,11 @@
void(*xDestroy)(void*) /* Module destructor function */
);
/*
-** CAPI3REF: Virtual Table Instance Object {F18010}
+** CAPI3REF: Virtual Table Instance Object {H18010} <S20400>
** KEYWORDS: sqlite3_vtab
+** EXPERIMENTAL
**
** Every module implementation uses a subclass of the following structure
** to describe a particular instance of the module. Each subclass will
** be tailored to the specific needs of the module implementation.
@@ -5802,10 +6095,11 @@
/* Virtual table implementations will typically add additional fields */
};
/*
-** CAPI3REF: Virtual Table Cursor Object {F18020}
+** CAPI3REF: Virtual Table Cursor Object {H18020} <S20400>
** KEYWORDS: sqlite3_vtab_cursor
+** EXPERIMENTAL
**
** Every module implementation uses a subclass of the following structure
** to describe cursors that point into the virtual table and are used
** to loop through the virtual table. Cursors are created using the
@@ -5823,9 +6117,10 @@
/* Virtual table implementations will typically add additional fields */
};
/*
-** CAPI3REF: Declare The Schema Of A Virtual Table {F18280}
+** CAPI3REF: Declare The Schema Of A Virtual Table {H18280} <S20400>
+** EXPERIMENTAL
**
** The xCreate and xConnect methods of a module use the following API
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
@@ -5832,12 +6127,13 @@
**
** This interface is experimental and is subject to change or
** removal in future releases of SQLite.
*/
-SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
-
-/*
-** CAPI3REF: Overload A Function For A Virtual Table {F18300}
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
+
+/*
+** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400>
+** EXPERIMENTAL
**
** Virtual tables can provide alternative implementations of functions
** using the xFindFunction method. But global versions of those functions
** must exist in order to be overloaded.
@@ -5852,9 +6148,9 @@
**
** This API should be considered part of the virtual table interface,
** which is experimental and subject to change.
*/
-SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
/*
** The interface to the virtual-table mechanism defined above (back up
** to a comment remarkably similar to this one) is currently considered
@@ -5867,9 +6163,9 @@
****** EXPERIMENTAL - subject to change without notice **************
*/
/*
-** CAPI3REF: A Handle To An Open BLOB {F17800}
+** CAPI3REF: A Handle To An Open BLOB {H17800} <S30230>
** KEYWORDS: {BLOB handle} {BLOB handles}
**
** An instance of this object represents an open BLOB on which
** [sqlite3_blob_open | incremental BLOB I/O] can be performed.
@@ -5881,9 +6177,9 @@
*/
typedef struct sqlite3_blob sqlite3_blob;
/*
-** CAPI3REF: Open A BLOB For Incremental I/O {F17810}
+** CAPI3REF: Open A BLOB For Incremental I/O {H17810} <S30230>
**
** This interfaces opens a [BLOB handle | handle] to the BLOB located
** in row iRow, column zColumn, table zTable in database zDb;
** in other words, the same BLOB that would be selected by:
@@ -5919,30 +6215,31 @@
** commit if the transaction continues to completion.
**
** INVARIANTS:
**
-** {F17813} A successful invocation of the [sqlite3_blob_open(D,B,T,C,R,F,P)]
+** {H17813} A successful invocation of the [sqlite3_blob_open(D,B,T,C,R,F,P)]
** interface shall open an [sqlite3_blob] object P on the BLOB
** in column C of the table T in the database B on
** the [database connection] D.
**
-** {F17814} A successful invocation of [sqlite3_blob_open(D,...)] shall start
+** {H17814} A successful invocation of [sqlite3_blob_open(D,...)] shall start
** a new transaction on the [database connection] D if that
** connection is not already in a transaction.
**
-** {F17816} The [sqlite3_blob_open(D,B,T,C,R,F,P)] interface shall open
+** {H17816} The [sqlite3_blob_open(D,B,T,C,R,F,P)] interface shall open
** the BLOB for read and write access if and only if the F
** parameter is non-zero.
**
-** {F17819} The [sqlite3_blob_open()] interface shall return [SQLITE_OK] on
+** {H17819} The [sqlite3_blob_open()] interface shall return [SQLITE_OK] on
** success and an appropriate [error code] on failure.
**
-** {F17821} If an error occurs during evaluation of [sqlite3_blob_open(D,...)]
+** {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.
**
-** {F17824} If any column in the row that a [sqlite3_blob] has open is
+** {H17824} If any column in the row that a [sqlite3_blob] has open is
** changed by a separate [UPDATE] or [DELETE] statement or by
** an [ON CONFLICT] side effect, then the [sqlite3_blob] shall
** be marked as invalid.
*/
@@ -5956,9 +6253,9 @@
sqlite3_blob **ppBlob
);
/*
-** CAPI3REF: Close A BLOB Handle {F17830}
+** CAPI3REF: Close A BLOB Handle {H17830} <S30230>
**
** Closes an open [BLOB handle].
**
** Closing a BLOB shall cause the current transaction to commit
@@ -5968,47 +6265,47 @@
** until the close operation if they will fit. {END}
**
** Closing the BLOB often forces the changes
** out to disk and so if any I/O errors occur, they will likely occur
-** at the time when the BLOB is closed. {F17833} Any errors that occur during
+** at the time when the BLOB is closed. {H17833} Any errors that occur during
** closing are reported as a non-zero return value.
**
** The BLOB is closed unconditionally. Even if this routine returns
** an error code, the BLOB is still closed.
**
** INVARIANTS:
**
-** {F17833} The [sqlite3_blob_close(P)] interface closes an [sqlite3_blob]
+** {H17833} The [sqlite3_blob_close(P)] interface closes an [sqlite3_blob]
** object P previously opened using [sqlite3_blob_open()].
**
-** {F17836} Closing an [sqlite3_blob] object using
+** {H17836} Closing an [sqlite3_blob] object using
** [sqlite3_blob_close()] shall cause the current transaction to
** commit if there are no other open [sqlite3_blob] objects
** or [prepared statements] on the same [database connection] and
** the database connection is in [autocommit mode].
**
-** {F17839} The [sqlite3_blob_close(P)] interfaces shall close the
+** {H17839} The [sqlite3_blob_close(P)] interfaces shall close the
** [sqlite3_blob] object P unconditionally, even if
** [sqlite3_blob_close(P)] returns something other than [SQLITE_OK].
*/
SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
/*
-** CAPI3REF: Return The Size Of An Open BLOB {F17840}
+** CAPI3REF: Return The Size Of An Open BLOB {H17840} <S30230>
**
** Returns the size in bytes of the BLOB accessible via the open
** []BLOB handle] in its only argument.
**
** INVARIANTS:
**
-** {F17843} The [sqlite3_blob_bytes(P)] interface returns the size
+** {H17843} The [sqlite3_blob_bytes(P)] interface returns the size
** in bytes of the BLOB that the [sqlite3_blob] object P
** refers to.
*/
SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
/*
-** CAPI3REF: Read Data From A BLOB Incrementally {F17850}
+** CAPI3REF: Read Data From A BLOB Incrementally {H17850} <S30230>
**
** This function is used to read data from an open [BLOB handle] into a
** caller-supplied buffer. N bytes of data are copied into buffer Z
** from the open BLOB, starting at offset iOffset.
@@ -6024,42 +6321,43 @@
** Otherwise, an [error code] or an [extended error code] is returned.
**
** INVARIANTS:
**
-** {F17853} A successful invocation of [sqlite3_blob_read(P,Z,N,X)]
+** {H17853} A successful invocation of [sqlite3_blob_read(P,Z,N,X)]
** shall reads N bytes of data out of the BLOB referenced by
** [BLOB handle] P beginning at offset X and store those bytes
** into buffer Z.
**
-** {F17856} In [sqlite3_blob_read(P,Z,N,X)] if the size of the BLOB
+** {H17856} In [sqlite3_blob_read(P,Z,N,X)] if the size of the BLOB
** is less than N+X bytes, then the function shall leave the
** Z buffer unchanged and return [SQLITE_ERROR].
**
-** {F17859} In [sqlite3_blob_read(P,Z,N,X)] if X or N is less than zero
+** {H17859} In [sqlite3_blob_read(P,Z,N,X)] if X or N is less than zero
** then the function shall leave the Z buffer unchanged
** and return [SQLITE_ERROR].
**
-** {F17862} The [sqlite3_blob_read(P,Z,N,X)] interface shall return [SQLITE_OK]
+** {H17862} The [sqlite3_blob_read(P,Z,N,X)] interface shall return [SQLITE_OK]
** if N bytes are successfully read into buffer Z.
**
-** {F17863} If the [BLOB handle] P is expired and X and N are within bounds
+** {H17863} If the [BLOB handle] P is expired and X and N are within bounds
** then [sqlite3_blob_read(P,Z,N,X)] shall leave the Z buffer
** unchanged and return [SQLITE_ABORT].
**
-** {F17865} If the requested read could not be completed,
+** {H17865} If the requested read could not be completed,
** the [sqlite3_blob_read(P,Z,N,X)] interface shall return an
** appropriate [error code] or [extended error code].
**
-** {F17868} If an error occurs during evaluation of [sqlite3_blob_read(P,...)]
+** {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.
*/
SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
/*
-** CAPI3REF: Write Data Into A BLOB Incrementally {F17870}
+** CAPI3REF: Write Data Into A BLOB Incrementally {H17870} <S30230>
**
** This function is used to write data into an open [BLOB handle] from a
** caller-supplied buffer. N bytes of data are copied from the buffer Z
** into the open BLOB, starting at offset iOffset.
@@ -6085,49 +6383,50 @@
** Otherwise, an [error code] or an [extended error code] is returned.
**
** INVARIANTS:
**
-** {F17873} A successful invocation of [sqlite3_blob_write(P,Z,N,X)]
+** {H17873} A successful invocation of [sqlite3_blob_write(P,Z,N,X)]
** shall write N bytes of data from buffer Z into the BLOB
** referenced by [BLOB handle] P beginning at offset X into
** the BLOB.
**
-** {F17874} In the absence of other overridding changes, the changes
+** {H17874} In the absence of other overridding changes, the changes
** written to a BLOB by [sqlite3_blob_write()] shall
** remain in effect after the associated [BLOB handle] expires.
**
-** {F17875} If the [BLOB handle] P was opened for reading only then
+** {H17875} If the [BLOB handle] P was opened for reading only then
** an invocation of [sqlite3_blob_write(P,Z,N,X)] shall leave
** the referenced BLOB unchanged and return [SQLITE_READONLY].
**
-** {F17876} If the size of the BLOB referenced by [BLOB handle] P is
+** {H17876} If the size of the BLOB referenced by [BLOB handle] P is
** less than N+X bytes then [sqlite3_blob_write(P,Z,N,X)] shall
** leave the BLOB unchanged and return [SQLITE_ERROR].
**
-** {F17877} If the [BLOB handle] P is expired and X and N are within bounds
+** {H17877} If the [BLOB handle] P is expired and X and N are within bounds
** then [sqlite3_blob_read(P,Z,N,X)] shall leave the BLOB
** unchanged and return [SQLITE_ABORT].
**
-** {F17879} If X or N are less than zero then [sqlite3_blob_write(P,Z,N,X)]
+** {H17879} If X or N are less than zero then [sqlite3_blob_write(P,Z,N,X)]
** shall leave the BLOB referenced by [BLOB handle] P unchanged
** and return [SQLITE_ERROR].
**
-** {F17882} The [sqlite3_blob_write(P,Z,N,X)] interface shall return
+** {H17882} The [sqlite3_blob_write(P,Z,N,X)] interface shall return
** [SQLITE_OK] if N bytes where successfully written into the BLOB.
**
-** {F17885} If the requested write could not be completed,
+** {H17885} If the requested write could not be completed,
** the [sqlite3_blob_write(P,Z,N,X)] interface shall return an
** appropriate [error code] or [extended error code].
**
-** {F17888} If an error occurs during evaluation of [sqlite3_blob_write(D,...)]
+** {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.
*/
SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
/*
-** CAPI3REF: Virtual File System Objects {F11200}
+** CAPI3REF: Virtual File System Objects {H11200} <S20100>
**
** A virtual filesystem (VFS) is an [sqlite3_vfs] object
** that SQLite uses to interact
** with the underlying operating system. Most SQLite builds come with a
@@ -6155,29 +6454,29 @@
** the default. The choice for the new VFS is arbitrary.
**
** INVARIANTS:
**
-** {F11203} The [sqlite3_vfs_find(N)] interface returns a pointer to the
+** {H11203} The [sqlite3_vfs_find(N)] interface returns a pointer to the
** registered [sqlite3_vfs] object whose name exactly matches
** the zero-terminated UTF-8 string N, or it returns NULL if
** there is no match.
**
-** {F11206} If the N parameter to [sqlite3_vfs_find(N)] is NULL then
+** {H11206} If the N parameter to [sqlite3_vfs_find(N)] is NULL then
** the function returns a pointer to the default [sqlite3_vfs]
** object if there is one, or NULL if there is no default
** [sqlite3_vfs] object.
**
-** {F11209} The [sqlite3_vfs_register(P,F)] interface registers the
+** {H11209} The [sqlite3_vfs_register(P,F)] interface registers the
** well-formed [sqlite3_vfs] object P using the name given
** by the zName field of the object.
**
-** {F11212} Using the [sqlite3_vfs_register(P,F)] interface to register
+** {H11212} Using the [sqlite3_vfs_register(P,F)] interface to register
** the same [sqlite3_vfs] object multiple times is a harmless no-op.
**
-** {F11215} The [sqlite3_vfs_register(P,F)] interface makes the [sqlite3_vfs]
+** {H11215} The [sqlite3_vfs_register(P,F)] interface makes the [sqlite3_vfs]
** object P the default [sqlite3_vfs] object if F is non-zero.
**
-** {F11218} The [sqlite3_vfs_unregister(P)] interface unregisters the
+** {H11218} The [sqlite3_vfs_unregister(P)] interface unregisters the
** [sqlite3_vfs] object P so that it is no longer returned by
** subsequent calls to [sqlite3_vfs_find()].
*/
SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
@@ -6184,9 +6483,9 @@
SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
/*
-** CAPI3REF: Mutexes {F17000}
+** CAPI3REF: Mutexes {H17000} <S20000>
**
** The SQLite core uses these routines for thread
** synchronization. Though they are intended for internal
** use by SQLite, code that links against SQLite is
@@ -6217,12 +6516,12 @@
** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
** before calling sqlite3_initialize() or any other public sqlite3_
** function that calls sqlite3_initialize().
**
-** {F17011} The sqlite3_mutex_alloc() routine allocates a new
-** mutex and returns a pointer to it. {F17012} If it returns NULL
-** that means that a mutex could not be allocated. {F17013} SQLite
-** will unwind its stack and return an error. {F17014} The argument
+** {H17011} The sqlite3_mutex_alloc() routine allocates a new
+** mutex and returns a pointer to it. {H17012} If it returns NULL
+** that means that a mutex could not be allocated. {H17013} SQLite
+** will unwind its stack and return an error. {H17014} The argument
** to sqlite3_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li> SQLITE_MUTEX_FAST
@@ -6234,61 +6533,61 @@
** <li> SQLITE_MUTEX_STATIC_LRU
** <li> SQLITE_MUTEX_STATIC_LRU2
** </ul>
**
-** {F17015} The first two constants cause sqlite3_mutex_alloc() to create
+** {H17015} The first two constants cause sqlite3_mutex_alloc() to create
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE_MUTEX_FAST is used. {END}
** The mutex implementation does not need to make a distinction
** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
-** not want to. {F17016} But SQLite will only request a recursive mutex in
+** not want to. {H17016} But SQLite will only request a recursive mutex in
** cases where it really needs one. {END} If a faster non-recursive mutex
** implementation is available on the host platform, the mutex subsystem
** might return such a mutex in response to SQLITE_MUTEX_FAST.
**
-** {F17017} The other allowed parameters to sqlite3_mutex_alloc() each return
+** {H17017} The other allowed parameters to sqlite3_mutex_alloc() each return
** a pointer to a static preexisting mutex. {END} Four static mutexes are
** used by the current version of SQLite. Future versions of SQLite
** may add additional static mutexes. Static mutexes are for internal
** use by SQLite only. Applications that use SQLite mutexes should
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
** SQLITE_MUTEX_RECURSIVE.
**
-** {F17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
+** {H17018} Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
-** returns a different mutex on every call. {F17034} But for the static
+** returns a different mutex on every call. {H17034} But for the static
** mutex types, the same mutex is returned on every call that has
** the same type number.
**
-** {F17019} The sqlite3_mutex_free() routine deallocates a previously
-** allocated dynamic mutex. {F17020} SQLite is careful to deallocate every
+** {H17019} The sqlite3_mutex_free() routine deallocates a previously
+** allocated dynamic mutex. {H17020} SQLite is careful to deallocate every
** dynamic mutex that it allocates. {A17021} The dynamic mutexes must not be in
** use when they are deallocated. {A17022} Attempting to deallocate a static
-** mutex results in undefined behavior. {F17023} SQLite never deallocates
+** mutex results in undefined behavior. {H17023} SQLite never deallocates
** a static mutex. {END}
**
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
-** to enter a mutex. {F17024} If another thread is already within the mutex,
+** to enter a mutex. {H17024} If another thread is already within the mutex,
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
-** SQLITE_BUSY. {F17025} The sqlite3_mutex_try() interface returns [SQLITE_OK]
-** upon successful entry. {F17026} Mutexes created using
+** SQLITE_BUSY. {H17025} The sqlite3_mutex_try() interface returns [SQLITE_OK]
+** upon successful entry. {H17026} Mutexes created using
** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread.
-** {F17027} In such cases the,
+** {H17027} In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter. {A17028} If the same thread tries to enter any other
** kind of mutex more than once, the behavior is undefined.
-** {F17029} SQLite will never exhibit
+** {H17029} SQLite will never exhibit
** such behavior in its own use of mutexes.
**
** Some systems (for example, Windows 95) do not support the operation
** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
-** will always return SQLITE_BUSY. {F17030} The SQLite core only ever uses
+** will always return SQLITE_BUSY. {H17030} The SQLite core only ever uses
** sqlite3_mutex_try() as an optimization so this is acceptable behavior.
**
-** {F17031} The sqlite3_mutex_leave() routine exits a mutex that was
+** {H17031} The sqlite3_mutex_leave() routine exits a mutex that was
** previously entered by the same thread. {A17032} The behavior
** is undefined if the mutex is not currently entered by the
-** calling thread or is not currently allocated. {F17033} SQLite will
+** calling thread or is not currently allocated. {H17033} SQLite will
** never do either. {END}
**
** If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(), or
** sqlite3_mutex_leave() is a NULL pointer, then all three routines
@@ -6302,9 +6601,10 @@
SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
/*
-** CAPI3REF: Mutex Methods Object {F17120}
+** CAPI3REF: Mutex Methods Object {H17120} <S20130>
+** EXPERIMENTAL
**
** An instance of this structure defines the low-level routines
** used to allocate and use mutexes.
**
@@ -6319,16 +6619,16 @@
** implementation, using the [SQLITE_CONFIG_GETMUTEX] option.
**
** The xMutexInit method defined by this structure is invoked as
** part of system initialization by the sqlite3_initialize() function.
-** {F17001} The xMutexInit routine shall be called by SQLite once for each
+** {H17001} The xMutexInit routine shall be called by SQLite once for each
** effective call to [sqlite3_initialize()].
**
** The xMutexEnd method defined by this structure is invoked as
** part of system shutdown by the sqlite3_shutdown() function. The
** implementation of this method is expected to release all outstanding
** resources obtained by the mutex methods implementation, especially
-** those obtained by the xMutexInit method. {F17003} The xMutexEnd()
+** those obtained by the xMutexInit method. {H17003} The xMutexEnd()
** interface shall be invoked once for each call to [sqlite3_shutdown()].
**
** The remaining seven methods defined by this structure (xMutexAlloc,
** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and
@@ -6365,44 +6665,48 @@
int (*xMutexNotheld)(sqlite3_mutex *);
};
/*
-** CAPI3REF: Mutex Verification Routines {F17080}
+** CAPI3REF: Mutex Verification Routines {H17080} <S20130> <S30800>
**
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines
-** are intended for use inside assert() statements. {F17081} The SQLite core
+** are intended for use inside assert() statements. {H17081} The SQLite core
** never uses these routines except inside an assert() and applications
-** are advised to follow the lead of the core. {F17082} The core only
+** are advised to follow the lead of the core. {H17082} The core only
** provides implementations for these routines when it is compiled
** with the SQLITE_DEBUG flag. {A17087} External mutex implementations
** are only required to provide these routines if SQLITE_DEBUG is
** defined and if NDEBUG is not defined.
**
-** {F17083} These routines should return true if the mutex in their argument
+** {H17083} These routines should return true if the mutex in their argument
** is held or not held, respectively, by the calling thread.
**
** {X17084} The implementation is not required to provided versions of these
** routines that actually work. If the implementation does not provide working
** versions of these routines, it should at least provide stubs that always
** return true so that one does not get spurious assertion failures.
**
-** {F17085} If the argument to sqlite3_mutex_held() is a NULL pointer then
+** {H17085} If the argument to sqlite3_mutex_held() is a NULL pointer then
** the routine should return 1. {END} This seems counter-intuitive since
** clearly the mutex cannot be held if it does not exist. But the
** the reason the mutex does not exist is because the build is not
** using mutexes. And we do not want the assert() containing the
** call to sqlite3_mutex_held() to fail, so a non-zero return is
-** the appropriate thing to do. {F17086} The sqlite3_mutex_notheld()
+** the appropriate thing to do. {H17086} The sqlite3_mutex_notheld()
** interface should also return 1 when given a NULL pointer.
*/
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
/*
-** CAPI3REF: Mutex Types {F17001}
-**
-** {F17002} The [sqlite3_mutex_alloc()] interface takes a single argument
+** CAPI3REF: Mutex Types {H17001} <H17000>
+**
+** The [sqlite3_mutex_alloc()] interface takes a single argument
** which is one of these integer constants.
+**
+** The set of static mutexes may change from one SQLite release to the
+** next. Applications that override the built-in mutex logic must be
+** prepared to accommodate additional static mutexes.
*/
#define SQLITE_MUTEX_FAST 0
#define SQLITE_MUTEX_RECURSIVE 1
#define SQLITE_MUTEX_STATIC_MASTER 2
@@ -6412,23 +6716,23 @@
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* lru page list */
/*
-** CAPI3REF: Low-Level Control Of Database Files {F11300}
-**
-** {F11301} The [sqlite3_file_control()] interface makes a direct call to the
+** CAPI3REF: Low-Level Control Of Database Files {H11300} <S30800>
+**
+** {H11301} The [sqlite3_file_control()] interface makes a direct call to the
** xFileControl method for the [sqlite3_io_methods] object associated
-** with a particular database identified by the second argument. {F11302} The
+** with a particular database identified by the second argument. {H11302} The
** name of the database is the name assigned to the database by the
** <a href="lang_attach.html">ATTACH</a> SQL command that opened the
-** database. {F11303} To control the main database file, use the name "main"
-** or a NULL pointer. {F11304} The third and fourth parameters to this routine
+** database. {H11303} To control the main database file, use the name "main"
+** or a NULL pointer. {H11304} The third and fourth parameters to this routine
** are passed directly through to the second and third parameters of
-** the xFileControl method. {F11305} The return value of the xFileControl
+** the xFileControl method. {H11305} The return value of the xFileControl
** method becomes the return value of this routine.
**
-** {F11306} If the second parameter (zDbName) does not match the name of any
-** open database file, then SQLITE_ERROR is returned. {F11307} This error
+** {H11306} If the second parameter (zDbName) does not match the name of any
+** open database file, then SQLITE_ERROR is returned. {H11307} This error
** code is not remembered and will not be recalled by [sqlite3_errcode()]
** or [sqlite3_errmsg()]. {A11308} The underlying xFileControl method might
** also return SQLITE_ERROR. {A11309} There is no way to distinguish between
** an incorrect zDbName and an SQLITE_ERROR return from the underlying
@@ -6438,9 +6742,9 @@
*/
SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
/*
-** CAPI3REF: Testing Interface {F11400}
+** CAPI3REF: Testing Interface {H11400} <S30800>
**
** The sqlite3_test_control() interface is used to read out internal
** state of SQLite and to inject faults into SQLite for testing
** purposes. The first parameter is an operation code that determines
@@ -6457,9 +6761,9 @@
*/
SQLITE_API int sqlite3_test_control(int op, ...);
/*
-** CAPI3REF: Testing Interface Operation Codes {F11410}
+** CAPI3REF: Testing Interface Operation Codes {H11410} <H11400>
**
** These constants are the valid operation code parameters used
** as the first argument to [sqlite3_test_control()].
**
@@ -6475,9 +6779,10 @@
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
/*
-** CAPI3REF: SQLite Runtime Status {F17200}
+** CAPI3REF: SQLite Runtime Status {H17200} <S60200>
+** EXPERIMENTAL
**
** This interface is used to retrieve runtime status information
** about the preformance of SQLite, and optionally to reset various
** highwater marks. The first argument is an integer code for
@@ -6501,15 +6806,16 @@
** *pHighwater reflect the status of SQLite at different points in time
** and it is possible that another thread might change the parameter
** in between the times when *pCurrent and *pHighwater are written.
**
-** This interface is experimental and is subject to change or
-** removal in future releases of SQLite.
-*/
-SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
-
-/*
-** CAPI3REF: Status Parameters {F17250}
+** See also: [sqlite3_db_status()]
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+
+
+/*
+** CAPI3REF: Status Parameters {H17250} <H17200>
+** EXPERIMENTAL
**
** These integer constants designate various run-time status parameters
** that can be returned by [sqlite3_status()].
**
@@ -6523,37 +6829,63 @@
** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
** this parameter. The amount returned is the sum of the allocation
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>
**
+** <dt>SQLITE_STATUS_MALLOC_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
+** internal equivalents). Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>
+**
** <dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
-** page cache buffer configured using [SQLITE_CONFIG_PAGECACHE]. The
+** [pagecache memory allocator] that was configured using
+** [SQLITE_CONFIG_PAGECACHE]. The
** value returned is in pages, not in bytes.</dd>
**
** <dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of page cache
** allocation which could not be statisfied by the [SQLITE_CONFIG_PAGECACHE]
-** buffer and where forced to overflow to [sqlite3_malloc()].</dd>
+** buffer and where forced to overflow to [sqlite3_malloc()]. The
+** returned value includes allocations that overflowed because they
+** where too large (they were larger than the "sz" parameter to
+** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
+** no space was left in the page cache.</dd>
+**
+** <dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
+** <dd>This parameter records the largest memory allocation request
+** handed to [pagecache memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>
**
** <dt>SQLITE_STATUS_SCRATCH_USED</dt>
** <dd>This parameter returns the number of allocations used out of the
-** scratch allocation lookaside buffer configured using
+** [scratch memory allocator] configured using
** [SQLITE_CONFIG_SCRATCH]. The value returned is in allocations, not
-** in bytes. Since a single thread may only have one allocation
+** in bytes. Since a single thread may only have one scratch allocation
** outstanding at time, this parameter also reports the number of threads
** using scratch memory at the same time.</dd>
**
** <dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
** <dd>This parameter returns the number of bytes of scratch memory
** allocation which could not be statisfied by the [SQLITE_CONFIG_SCRATCH]
-** buffer and where forced to overflow to [sqlite3_malloc()].</dd>
-**
-** <dt>SQLITE_STATUS_MALLOC_SIZE</dt>
+** buffer and where forced to overflow to [sqlite3_malloc()]. The values
+** returned include overflows because the requested allocation was too
+** larger (that is, because the requested allocation was larger than the
+** "sz" parameter to [SQLITE_CONFIG_SCRATCH]) and because no scratch buffer
+** slots were available.
+** </dd>
+**
+** <dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
-** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
-** internal equivalents). The value of interest is return in the
-** *pHighwater parameter to [sqlite3_status()]. The value written
-** into the *pCurrent parameter is undefined.</dd>
+** handed to [scratch memory allocator]. Only the value returned in the
+** *pHighwater parameter to [sqlite3_status()] is of interest.
+** The value written into the *pCurrent parameter is undefined.</dd>
+**
+** <dt>SQLITE_STATUS_PARSER_STACK</dt>
+** <dd>This parameter records the deepest parser stack. It is only
+** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>
** </dl>
**
** New status parameters may be added from time to time.
*/
@@ -6562,9 +6894,97 @@
#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
#define SQLITE_STATUS_SCRATCH_USED 3
#define SQLITE_STATUS_SCRATCH_OVERFLOW 4
#define SQLITE_STATUS_MALLOC_SIZE 5
-
+#define SQLITE_STATUS_PARSER_STACK 6
+#define SQLITE_STATUS_PAGECACHE_SIZE 7
+#define SQLITE_STATUS_SCRATCH_SIZE 8
+
+/*
+** CAPI3REF: Database Connection Status {H17500} <S60200>
+** EXPERIMENTAL
+**
+** This interface is used to retrieve runtime status information
+** about a single [database connection]. The first argument is the
+** database connection object to be interrogated. The second argument
+** is the parameter to interrogate. Currently, the only allowed value
+** for the second parameter is [SQLITE_DBSTATUS_LOOKASIDE_USED].
+** Additional options will likely appear in future releases of SQLite.
+**
+** The current value of the requested parameter is written into *pCur
+** and the highest instantaneous value is written into *pHiwtr. If
+** the resetFlg is true, then the highest instantaneous value is
+** reset back down to the current value.
+**
+** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
+*/
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+
+/*
+** CAPI3REF: Status Parameters for database connections {H17520} <H17500>
+** EXPERIMENTAL
+**
+** Status verbs for [sqlite3_db_status()].
+**
+** <dl>
+** <dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
+** <dd>This parameter returns the number of lookaside memory slots currently
+** checked out.</dd>
+** </dl>
+*/
+#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.
@@ -6595,9 +7015,9 @@
*************************************************************************
** This is the header file for the generic hash-table implemenation
** used in SQLite.
**
-** $Id: hash.h,v 1.11 2007/09/04 14:31:47 danielk1977 Exp $
+** $Id: hash.h,v 1.12 2008/10/10 17:41:29 drh Exp $
*/
#ifndef _SQLITE_HASH_H_
#define _SQLITE_HASH_H_
@@ -6613,16 +7033,15 @@
** accessing this structure are really macros, so we can't really make
** 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;
};
/* Each element in the hash table is an instance of the following
@@ -6637,33 +7056,11 @@
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);
SQLITE_PRIVATE void sqlite3HashClear(Hash*);
@@ -6810,41 +7207,41 @@
#define TK_DISTINCT 111
#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_COMMENT 147
+#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
@@ -6988,9 +7385,9 @@
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
-typedef UINT8_TYPE i8; /* 1-byte signed integer */
+typedef INT8_TYPE i8; /* 1-byte signed integer */
/*
** Macros to determine whether the machine is big or little endian,
** evaluated at runtime.
@@ -6999,9 +7396,10 @@
SQLITE_PRIVATE const int sqlite3one;
#else
SQLITE_PRIVATE const int sqlite3one;
#endif
-#if defined(i386) || defined(__i386__) || defined(_M_IX86)
+#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
+ || defined(__x86_64) || defined(__x86_64__)
# define SQLITE_BIGENDIAN 0
# define SQLITE_LITTLEENDIAN 1
# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
#else
@@ -7058,8 +7456,40 @@
*/
#define ArraySize(X) (sizeof(X)/sizeof(X[0]))
/*
+** The following value as a destructor means to use sqlite3DbFree().
+** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT.
+*/
+#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 usually 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
*/
typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
@@ -7071,12 +7501,15 @@
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct FKey FKey;
typedef struct FuncDef FuncDef;
+typedef struct FuncDefHash FuncDefHash;
typedef struct IdList IdList;
typedef struct Index Index;
typedef struct KeyClass KeyClass;
typedef struct KeyInfo KeyInfo;
+typedef struct Lookaside Lookaside;
+typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct Select Select;
@@ -7087,8 +7520,10 @@
typedef struct Token Token;
typedef struct TriggerStack TriggerStack;
typedef struct TriggerStep TriggerStep;
typedef struct Trigger Trigger;
+typedef struct UnpackedRecord UnpackedRecord;
+typedef struct Walker Walker;
typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;
/*
@@ -7112,9 +7547,9 @@
** This header file defines the interface that the sqlite B-Tree file
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
-** @(#) $Id: btree.h,v 1.102 2008/07/11 21:02:54 drh Exp $
+** @(#) $Id: btree.h,v 1.105 2008/10/27 13:59:34 danielk1977 Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
@@ -7216,14 +7651,12 @@
#define BTREE_ZERODATA 2 /* Table has keys only - no data */
#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);
-
-struct UnpackedRecord; /* Forward declaration. Definition in vdbeaux.c. */
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
@@ -7236,10 +7669,16 @@
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeMoveto(
BtCursor*,
const void *pKey,
- struct UnpackedRecord *pUnKey,
i64 nKey,
+ int bias,
+ int *pRes
+);
+SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
+ BtCursor*,
+ UnpackedRecord *pUnKey,
+ i64 intKey,
int bias,
int *pRes
);
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
@@ -7265,8 +7704,9 @@
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
SQLITE_PRIVATE void sqlite3BtreeCacheOverflow(BtCursor *);
+SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
#ifdef SQLITE_TEST
SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
@@ -7338,9 +7778,9 @@
** This header defines the interface to the virtual database engine
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.134 2008/06/25 00:12:41 drh Exp $
+** $Id: vdbe.h,v 1.139 2008/10/31 10:53:23 danielk1977 Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@@ -7356,9 +7796,8 @@
** for the VdbeOp definition.
*/
typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
-typedef struct UnpackedRecord UnpackedRecord;
/*
** A single instruction of the virtual machine has an opcode
** and as many as three operands. The instruction is recorded
@@ -7471,143 +7910,143 @@
/************** Include opcodes.h in the middle of vdbe.h ********************/
/************** Begin file opcodes.h *****************************************/
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
-#define OP_VNext 1
-#define OP_Affinity 2
-#define OP_Column 3
-#define OP_SetCookie 4
-#define OP_Real 125 /* same as TK_FLOAT */
-#define OP_Sequence 5
-#define OP_MoveGt 6
+#define OP_ReadCookie 1
+#define OP_AutoCommit 2
+#define OP_Found 3
+#define OP_NullRow 4
+#define OP_Lt 71 /* same as TK_LT */
+#define OP_MoveLe 5
+#define OP_Variable 6
+#define OP_RealAffinity 7
+#define OP_Sort 8
+#define OP_Affinity 9
+#define OP_IfNot 10
+#define OP_Gosub 11
+#define OP_Add 78 /* same as TK_PLUS */
+#define OP_NotFound 12
+#define OP_ResultRow 13
+#define OP_IsNull 65 /* same as TK_ISNULL */
+#define OP_MoveLt 14
+#define OP_Rowid 15
+#define OP_CreateIndex 17
+#define OP_Explain 18
+#define OP_Statement 19
+#define OP_DropIndex 20
+#define OP_Null 21
+#define OP_ToInt 142 /* same as TK_TO_INT */
+#define OP_Int64 22
+#define OP_LoadAnalysis 23
+#define OP_IdxInsert 24
+#define OP_VUpdate 25
+#define OP_Next 26
+#define OP_SetNumColumns 27
+#define OP_ToNumeric 141 /* same as TK_TO_NUMERIC*/
#define OP_Ge 72 /* same as TK_GE */
-#define OP_RowKey 7
-#define OP_SCopy 8
-#define OP_Eq 68 /* same as TK_EQ */
-#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_String8 88 /* same as TK_STRING */
-#define OP_VRowid 11
-#define OP_CollSeq 12
-#define OP_OpenRead 13
-#define OP_Expire 14
-#define OP_AutoCommit 15
-#define OP_Gt 69 /* same as TK_GT */
-#define OP_Pagecount 17
-#define OP_IntegrityCk 18
-#define OP_Sort 19
-#define OP_Copy 20
-#define OP_Trace 21
-#define OP_Function 22
-#define OP_IfNeg 23
-#define OP_And 61 /* same as TK_AND */
-#define OP_Subtract 79 /* same as TK_MINUS */
-#define OP_Noop 24
-#define OP_Return 25
-#define OP_Remainder 82 /* same as TK_REM */
-#define OP_NewRowid 26
+#define OP_BitNot 87 /* same as TK_BITNOT */
+#define OP_Rewind 28
#define OP_Multiply 80 /* same as TK_STAR */
-#define OP_Variable 27
-#define OP_String 28
-#define OP_RealAffinity 29
-#define OP_VRename 30
-#define OP_ParseSchema 31
-#define OP_VOpen 32
-#define OP_Close 33
-#define OP_CreateIndex 34
-#define OP_IsUnique 35
-#define OP_NotFound 36
-#define OP_Int64 37
-#define OP_MustBeInt 38
-#define OP_Halt 39
-#define OP_Rowid 40
-#define OP_IdxLT 41
-#define OP_AddImm 42
-#define OP_Statement 43
-#define OP_RowData 44
-#define OP_MemMax 45
-#define OP_Or 60 /* same as TK_OR */
-#define OP_NotExists 46
-#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_Prev 49
-#define OP_Concat 83 /* same as TK_CONCAT */
+#define OP_ToReal 143 /* same as TK_TO_REAL */
+#define OP_Gt 69 /* same as TK_GT */
+#define OP_Last 29
+#define OP_MustBeInt 30
+#define OP_Ne 67 /* same as TK_NE */
+#define OP_MoveGe 31
+#define OP_IncrVacuum 32
+#define OP_String 33
+#define OP_VFilter 34
+#define OP_ForceInt 35
+#define OP_Close 36
+#define OP_AggFinal 37
+#define OP_RowData 38
+#define OP_IdxRowid 39
+#define OP_Pagecount 40
+#define OP_BitOr 75 /* same as TK_BITOR */
+#define OP_NotNull 66 /* same as TK_NOTNULL */
+#define OP_MoveGt 41
+#define OP_Not 16 /* same as TK_NOT */
+#define OP_OpenPseudo 42
+#define OP_Halt 43
+#define OP_Compare 44
+#define OP_NewRowid 45
+#define OP_Real 126 /* same as TK_FLOAT */
+#define OP_IdxLT 46
+#define OP_MemMax 47
+#define OP_Function 48
+#define OP_IntegrityCk 49
+#define OP_Remainder 82 /* same as TK_REM */
+#define OP_SCopy 50
+#define OP_ShiftLeft 76 /* same as TK_LSHIFT */
+#define OP_IfNeg 51
+#define OP_FifoWrite 52
#define OP_BitAnd 74 /* same as TK_BITAND */
-#define OP_VColumn 50
-#define OP_CreateTable 51
-#define OP_Last 52
-#define OP_IsNull 65 /* same as TK_ISNULL */
-#define OP_IncrVacuum 53
-#define OP_IdxRowid 54
-#define OP_ShiftRight 77 /* same as TK_RSHIFT */
-#define OP_ResetCount 55
-#define OP_FifoWrite 56
-#define OP_ContextPush 57
-#define OP_Yield 58
-#define OP_DropTrigger 59
-#define OP_DropIndex 62
-#define OP_IdxGE 63
-#define OP_IdxDelete 64
-#define OP_Vacuum 73
-#define OP_MoveLe 84
-#define OP_IfNot 85
-#define OP_DropTable 86
-#define OP_MakeRecord 89
-#define OP_ToBlob 139 /* same as TK_TO_BLOB */
-#define OP_ResultRow 90
-#define OP_Delete 91
-#define OP_AggFinal 92
-#define OP_Compare 93
-#define OP_ShiftLeft 76 /* same as TK_LSHIFT */
-#define OP_Goto 94
-#define OP_TableLock 95
-#define OP_FifoRead 96
-#define OP_Clear 97
-#define OP_MoveLt 98
-#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_Not 16 /* same as TK_NOT */
-#define OP_ToReal 142 /* same as TK_TO_REAL */
-#define OP_SetNumColumns 101
+#define OP_Or 60 /* same as TK_OR */
+#define OP_NotExists 53
+#define OP_VDestroy 54
+#define OP_IdxDelete 55
+#define OP_Vacuum 56
+#define OP_Copy 57
+#define OP_If 58
+#define OP_Jump 59
+#define OP_Destroy 62
+#define OP_AggStep 63
+#define OP_Insert 64
+#define OP_Clear 73
+#define OP_Permutation 84
+#define OP_VBegin 85
+#define OP_OpenEphemeral 86
+#define OP_IdxGE 89
+#define OP_Trace 90
+#define OP_Divide 81 /* same as TK_SLASH */
+#define OP_String8 88 /* same as TK_STRING */
+#define OP_Concat 83 /* same as TK_CONCAT */
+#define OP_VRowid 91
+#define OP_MakeRecord 92
+#define OP_Yield 93
+#define OP_SetCookie 94
+#define OP_Prev 95
+#define OP_ContextPush 96
+#define OP_DropTrigger 97
+#define OP_And 61 /* same as TK_AND */
+#define OP_VColumn 98
+#define OP_Return 99
+#define OP_OpenWrite 100
+#define OP_Integer 101
#define OP_Transaction 102
-#define OP_VFilter 103
-#define OP_Ne 67 /* same as TK_NE */
-#define OP_VDestroy 104
-#define OP_ContextPop 105
-#define OP_BitOr 75 /* same as TK_BITOR */
-#define OP_Next 106
-#define OP_IdxInsert 107
-#define OP_Lt 71 /* same as TK_LT */
-#define OP_Insert 108
-#define OP_Destroy 109
-#define OP_ReadCookie 110
-#define OP_ForceInt 111
-#define OP_LoadAnalysis 112
-#define OP_Explain 113
-#define OP_OpenPseudo 114
-#define OP_OpenEphemeral 115
-#define OP_Null 116
-#define OP_Move 117
-#define OP_Blob 118
-#define OP_Add 78 /* same as TK_PLUS */
-#define OP_Rewind 119
-#define OP_MoveGe 120
-#define OP_VBegin 121
-#define OP_VUpdate 122
-#define OP_IfZero 123
-#define OP_BitNot 87 /* same as TK_BITNOT */
-#define OP_VCreate 124
-#define OP_Found 126
-#define OP_IfPos 127
-#define OP_NullRow 128
-#define OP_Jump 129
-#define OP_Permutation 130
+#define OP_IfPos 103
+#define OP_CollSeq 104
+#define OP_VRename 105
+#define OP_ToBlob 140 /* same as TK_TO_BLOB */
+#define OP_Sequence 106
+#define OP_ContextPop 107
+#define OP_ShiftRight 77 /* same as TK_RSHIFT */
+#define OP_VCreate 108
+#define OP_CreateTable 109
+#define OP_AddImm 110
+#define OP_ToText 139 /* same as TK_TO_TEXT */
+#define OP_DropTable 111
+#define OP_IsUnique 112
+#define OP_VOpen 113
+#define OP_IfZero 114
+#define OP_Noop 115
+#define OP_RowKey 116
+#define OP_Expire 117
+#define OP_FifoRead 118
+#define OP_Delete 119
+#define OP_Subtract 79 /* same as TK_MINUS */
+#define OP_Blob 120
+#define OP_Move 121
+#define OP_Goto 122
+#define OP_ParseSchema 123
+#define OP_Eq 68 /* same as TK_EQ */
+#define OP_VNext 124
+#define OP_Le 70 /* same as TK_LE */
+#define OP_TableLock 125
+#define OP_VerifyCookie 127
+#define OP_Column 128
+#define OP_OpenRead 129
+#define OP_ResetCount 130
/* The following opcode values are never used */
#define OP_NotUsed_131 131
#define OP_NotUsed_132 132
@@ -7615,8 +8054,9 @@
#define OP_NotUsed_134 134
#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
** comments following the "case" for each opcode in the vdbe.c
@@ -7628,26 +8068,27 @@
#define OPFLG_IN2 0x0008 /* in2: P2 is an input */
#define OPFLG_IN3 0x0010 /* in3: P3 is an input */
#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
-/* 0 */ 0x00, 0x01, 0x00, 0x00, 0x10, 0x02, 0x11, 0x00,\
-/* 8 */ 0x00, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00,\
-/* 16 */ 0x04, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05,\
-/* 24 */ 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00,\
-/* 32 */ 0x00, 0x00, 0x02, 0x11, 0x11, 0x02, 0x05, 0x00,\
-/* 40 */ 0x02, 0x11, 0x04, 0x00, 0x00, 0x0c, 0x11, 0x01,\
-/* 48 */ 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
-/* 56 */ 0x04, 0x00, 0x00, 0x00, 0x2c, 0x2c, 0x00, 0x11,\
+/* 0 */ 0x00, 0x02, 0x00, 0x11, 0x00, 0x11, 0x02, 0x04,\
+/* 8 */ 0x01, 0x00, 0x05, 0x01, 0x11, 0x00, 0x11, 0x02,\
+/* 16 */ 0x04, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00,\
+/* 24 */ 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, 0x05, 0x11,\
+/* 32 */ 0x01, 0x02, 0x01, 0x05, 0x00, 0x00, 0x00, 0x02,\
+/* 40 */ 0x02, 0x11, 0x00, 0x00, 0x00, 0x02, 0x11, 0x0c,\
+/* 48 */ 0x00, 0x00, 0x00, 0x05, 0x04, 0x11, 0x00, 0x00,\
+/* 56 */ 0x00, 0x00, 0x05, 0x01, 0x2c, 0x2c, 0x02, 0x00,\
/* 64 */ 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
/* 72 */ 0x15, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\
-/* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x11, 0x05, 0x00, 0x04,\
-/* 88 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,\
-/* 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,\
-/* 128 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,}
+/* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x00, 0x00, 0x04,\
+/* 88 */ 0x02, 0x11, 0x00, 0x02, 0x00, 0x00, 0x10, 0x01,\
+/* 96 */ 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x05,\
+/* 104 */ 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x04, 0x00,\
+/* 112 */ 0x11, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00,\
+/* 120 */ 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00,\
+/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 136 */ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,\
+}
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -7680,11 +8121,11 @@
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3VdbeTrace(Vdbe*,FILE*);
#endif
SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*);
-SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*, int);
+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);
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
@@ -7691,9 +8132,10 @@
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int);
#endif
-SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int);
+SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,
+ UnpackedRecord*,int);
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
@@ -7727,9 +8169,9 @@
** This header file defines the interface that the sqlite page cache
** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
-** @(#) $Id: pager.h,v 1.76 2008/06/07 08:58:22 danielk1977 Exp $
+** @(#) $Id: pager.h,v 1.86 2008/10/17 18:51:53 danielk1977 Exp $
*/
#ifndef _PAGER_H_
#define _PAGER_H_
@@ -7779,17 +8221,18 @@
#define PAGER_JOURNALMODE_QUERY -1
#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
+#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
+#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
/*
** See source code comments for a detailed description of the following
** routines:
*/
SQLITE_PRIVATE int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, int,int,int);
SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler);
-SQLITE_PRIVATE void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int));
-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 void sqlite3PagerSetCachesize(Pager*, int);
@@ -7796,8 +8239,9 @@
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager);
SQLITE_PRIVATE int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0)
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
+SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*);
SQLITE_PRIVATE int sqlite3PagerRef(DbPage*);
SQLITE_PRIVATE int sqlite3PagerUnref(DbPage*);
SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
SQLITE_PRIVATE int sqlite3PagerPagecount(Pager*, int*);
@@ -7810,9 +8254,9 @@
SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager*);
SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager*);
SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager*);
SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage*);
-SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*);
+SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage*);
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int);
SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*);
SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*);
@@ -7819,20 +8263,16 @@
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
SQLITE_PRIVATE const char *sqlite3PagerDirname(Pager*);
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
-SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno);
+SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *);
SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
SQLITE_PRIVATE int sqlite3PagerJournalMode(Pager *, int);
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager);
-
-#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
-SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int);
-#endif
#ifdef SQLITE_HAS_CODEC
SQLITE_PRIVATE void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
#endif
@@ -7858,8 +8298,184 @@
#endif /* _PAGER_H_ */
/************** End of pager.h ***********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include pcache.h in the middle of sqliteInt.h ****************/
+/************** Begin file pcache.h ******************************************/
+/*
+** 2008 August 05
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the sqlite page cache
+** subsystem.
+**
+** @(#) $Id: pcache.h,v 1.14 2008/10/17 18:51:53 danielk1977 Exp $
+*/
+
+#ifndef _PCACHE_H_
+
+typedef struct PgHdr PgHdr;
+typedef struct PCache PCache;
+
+/*
+** Every page in the cache is controlled by an instance of the following
+** structure.
+*/
+struct PgHdr {
+ void *pData; /* Content of this page */
+ void *pExtra; /* Extra content */
+ PgHdr *pDirty; /* Transient list of dirty pages */
+ Pgno pgno; /* Page number for this page */
+ Pager *pPager; /* The pager this page is part of */
+#ifdef SQLITE_CHECK_PAGES
+ u32 pageHash; /* Hash of page content */
+#endif
+ u16 flags; /* PGHDR flags defined below */
+ /**********************************************************************
+ ** Elements above are public. All that follows is private to pcache.c
+ ** and should not be accessed by other modules.
+ */
+ i16 nRef; /* Number of users of this page */
+ PCache *pCache; /* Cache that owns this page */
+
+ /**********************************************************************
+ ** Elements above are accessible at any time by the owner of the cache
+ ** without the need for a mutex. The elements that follow can only be
+ ** accessed while holding the SQLITE_MUTEX_STATIC_LRU mutex.
+ */
+ PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */
+ PgHdr *pNext, *pPrev; /* List of clean or dirty pages */
+ PgHdr *pNextLru, *pPrevLru; /* Part of global LRU list */
+};
+
+/* Bit values for PgHdr.flags */
+#define PGHDR_IN_JOURNAL 0x001 /* Page is in rollback journal */
+#define PGHDR_DIRTY 0x002 /* Page has changed */
+#define PGHDR_NEED_SYNC 0x004 /* Fsync the rollback journal before
+ ** writing this page to the database */
+#define PGHDR_NEED_READ 0x008 /* Content is unread */
+#define PGHDR_REUSE_UNLIKELY 0x010 /* A hint that reuse is unlikely */
+#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
+
+/* Initialize and shutdown the page cache subsystem */
+SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
+SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
+
+/* Page cache buffer management:
+** These routines implement SQLITE_CONFIG_PAGECACHE.
+*/
+SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n);
+SQLITE_PRIVATE void *sqlite3PCacheMalloc(int sz);
+SQLITE_PRIVATE void sqlite3PCacheFree(void*);
+
+/* Create a new pager cache.
+** Under memory stress, invoke xStress to try to make pages clean.
+** Only clean and unpinned pages can be reclaimed.
+*/
+SQLITE_PRIVATE void sqlite3PcacheOpen(
+ int szPage, /* Size of every page */
+ int szExtra, /* Extra space associated with each page */
+ int bPurgeable, /* True if pages are on backing store */
+ int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */
+ void *pStress, /* Argument to xStress */
+ PCache *pToInit /* Preallocated space for the PCache */
+);
+
+/* Modify the page-size after the cache has been created. */
+SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *, int);
+
+/* Return the size in bytes of a PCache object. Used to preallocate
+** storage space.
+*/
+SQLITE_PRIVATE int sqlite3PcacheSize(void);
+
+/* One release per successful fetch. Page is pinned until released.
+** Reference counted.
+*/
+SQLITE_PRIVATE int sqlite3PcacheFetch(PCache*, Pgno, int createFlag, PgHdr**);
+SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*);
+
+SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
+SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
+SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
+SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
+
+/* Change a page number. Used by incr-vacuum. */
+SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno);
+
+/* Remove all pages with pgno>x. Reset the cache if x==0 */
+SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x);
+
+/* Get a list of all dirty pages in the cache, sorted by page number */
+SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*);
+
+/* Reset and close the cache object */
+SQLITE_PRIVATE void sqlite3PcacheClose(PCache*);
+
+/* Clear flags from pages of the page cache */
+SQLITE_PRIVATE void sqlite3PcacheClearFlags(PCache*, int mask);
+
+/* Assert flags settings on all pages. Debugging only */
+#ifndef NDEBUG
+SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask);
+#else
+# define sqlite3PcacheAssertFlags(A,B,C)
+#endif
+
+/* Return true if the number of dirty pages is 0 or 1 */
+SQLITE_PRIVATE int sqlite3PcacheZeroOrOneDirtyPages(PCache*);
+
+/* Discard the contents of the cache */
+SQLITE_PRIVATE int sqlite3PcacheClear(PCache*);
+
+/* Return the total number of outstanding page references */
+SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache*);
+
+/* Increment the reference count of an existing page */
+SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*);
+
+SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr*);
+
+/* Return the total number of pages stored in the cache */
+SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*);
+
+#ifdef SQLITE_CHECK_PAGES
+/* Iterate through all 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.
+**
+** If no global maximum is configured, then the system attempts to limit
+** the total number of pages cached by purgeable pager-caches to the sum
+** of the suggested cache-sizes.
+*/
+SQLITE_PRIVATE 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_ */
+
+/************** End of pcache.h **********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include os.h in the middle of sqliteInt.h ********************/
/************** Begin file os.h **********************************************/
@@ -8163,56 +8779,46 @@
** NOTE: source files should *not* #include this header file directly.
** Source files should #include the sqliteInt.h file and let that file
** include this one indirectly.
**
-** $Id: mutex.h,v 1.8 2008/06/26 10:41:19 danielk1977 Exp $
-*/
-
-
-#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
+** $Id: mutex.h,v 1.9 2008/10/07 15:25:48 drh Exp $
+*/
+
+
/*
** 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_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_OMIT No mutex logic. Not even stubs. The
+** mutexes implemention cannot be overridden
+** at start-time.
+**
+** 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_W32 For multi-threaded applications on Win32.
**
** 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
-#endif
-
-#ifdef SQLITE_MUTEX_NOOP
+#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_OMIT
/*
** If this is a no-op implementation, implement everything as macros.
*/
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
@@ -8224,11 +8830,9 @@
#define sqlite3_mutex_notheld(X) 1
#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 ******************/
@@ -8304,8 +8908,45 @@
** The number of different kinds of things that can be limited
** using the sqlite3_limit() interface.
*/
#define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1)
+
+/*
+** Lookaside malloc is a set of fixed-size buffers that can be used
+** to satisify small transient memory allocation requests for objects
+** associated with a particular database connection. The use of
+** lookaside malloc provides a significant performance enhancement
+** (approx 10%) by avoiding numerous malloc/free requests while parsing
+** SQL statements.
+**
+** The Lookaside structure holds configuration information about the
+** lookaside malloc subsystem. Each available memory allocation in
+** the lookaside subsystem is stored on a linked list of LookasideSlot
+** objects.
+*/
+struct Lookaside {
+ u16 sz; /* Size of each buffer in bytes */
+ u8 bEnabled; /* True if use lookaside. False to ignore it */
+ u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
+ int nOut; /* Number of buffers currently checked out */
+ int mxOut; /* Highwater mark for nOut */
+ LookasideSlot *pFree; /* List of available buffers */
+ void *pStart; /* First byte of available memory space */
+ void *pEnd; /* First byte past end of available space */
+};
+struct LookasideSlot {
+ LookasideSlot *pNext; /* Next buffer in the list of free buffers */
+};
+
+/*
+** A hash table for function definitions.
+**
+** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
+** Collisions are on the FuncDef.pHash chain.
+*/
+struct FuncDefHash {
+ FuncDef *a[23]; /* Hash table for functions */
+};
/*
** Each database is an instance of the following structure.
**
@@ -8381,11 +9022,12 @@
sqlite3_value *pErr; /* Most recent error message */
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 */
#ifndef SQLITE_OMIT_AUTHORIZATION
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
/* Access authorization function */
void *pAuthArg; /* 1st argument to the access auth function */
@@ -8400,9 +9042,9 @@
Table *pVTab; /* vtab with active Connect/Create method */
sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */
int nVTrans; /* Allocated size of aVTrans */
#endif
- Hash aFunc; /* All functions that can be in SQL exprs */
+ FuncDefHash aFunc; /* Hash table of connection functions */
Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */
int busyTimeout; /* Busy handler timeout, in msec */
Db aDbStatic[2]; /* Static space for the 2 default backends */
@@ -8467,17 +9109,60 @@
*/
struct FuncDef {
i16 nArg; /* Number of arguments. -1 means unlimited */
u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */
- u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */
u8 flags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */
- char zName[1]; /* SQL name of the function. MUST BE LAST */
-};
+ char *zName; /* SQL name of the function. */
+ FuncDef *pHash; /* Next with a different name but the same hash */
+};
+
+/*
+** Possible values for FuncDef.flags
+*/
+#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
+#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
+#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
+
+/*
+** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
+** used to create the initializers for the FuncDef structures.
+**
+** FUNCTION(zName, nArg, iArg, bNC, xFunc)
+** Used to create a scalar function definition of a function zName
+** implemented by C function xFunc that accepts nArg arguments. The
+** value passed as iArg is cast to a (void*) and made available
+** as the user-data (sqlite3_user_data()) for the function. If
+** argument bNC is true, then the FuncDef.needCollate flag is set.
+**
+** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
+** Used to create an aggregate function definition implemented by
+** the C functions xStep and xFinal. The first four parameters
+** are interpreted in the same way as the first 4 parameters to
+** FUNCTION().
+**
+** LIKEFUNC(zName, nArg, pArg, flags)
+** Used to create a scalar function definition of a function zName
+** that accepts nArg arguments and is implemented by a call to C
+** function likeFunc. Argument pArg is cast to a (void *) and made
+** available as the function user-data (sqlite3_user_data()). The
+** FuncDef.flags variable is set to the value passed as the flags
+** parameter.
+*/
+#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
+ {nArg, SQLITE_UTF8, bNC*8, SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName}
+#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, flags, (void *)arg, 0, likeFunc, 0, 0, #zName}
+#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
+ {nArg, SQLITE_UTF8, nc*8, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal, #zName}
+
/*
** Each SQLite module (virtual table definition) is defined by an
** instance of the following structure, stored in the sqlite3.aModule
@@ -8488,15 +9173,8 @@
const char *zName; /* Name passed to create_module() */
void *pAux; /* pAux passed to create_module() */
void (*xDestroy)(void *); /* Module destructor function */
};
-
-/*
-** Possible values for FuncDef.flags
-*/
-#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
-#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
-#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
/*
** information about each column of an SQL table is held in an instance
** of this structure.
@@ -8544,9 +9222,9 @@
void (*xDel)(void*); /* Destructor for pUser */
};
/*
-** Allowed values of CollSeq flags:
+** Allowed values of CollSeq.type:
*/
#define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */
#define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */
#define SQLITE_COLL_REVERSE 3 /* The built-in REVERSE collating sequence */
@@ -8562,9 +9240,9 @@
** Column affinity types.
**
** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
-** the speed a little by number the values consecutively.
+** the speed a little by numbering the values consecutively.
**
** But rather than start with 0 or 1, we begin with 'a'. That way,
** when multiple affinity types are concatenated into a string and
** used as the P4 operand, they will be more readable.
@@ -8608,63 +9286,72 @@
** the column that is that key. Otherwise Table.iPKey is negative. Note
** that the datatype of the PRIMARY KEY must be INTEGER for this field to
** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
-** is generated for each row of the table. Table.hasPrimKey is true if
+** is generated for each row of the table. TF_HasPrimaryKey is set if
** the table has any PRIMARY KEY, INTEGER or otherwise.
**
** Table.tnum is the page number for the root BTree page of the table in the
** database file. If Table.iDb is the index of the database table backend
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
-** holds temporary tables and indices. If Table.isEphem
-** is true, then the table is stored in a file that is automatically deleted
+** holds temporary tables and indices. If TF_Ephemeral is set
+** then the table is stored in a file that is automatically deleted
** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
** page number. Transient tables are used to hold the results of a
** sub-query that appears instead of a real table name in the FROM clause
** of a SELECT statement.
*/
struct Table {
- char *zName; /* Name of the table */
- int nCol; /* Number of columns in this table */
- Column *aCol; /* Information about each column */
- int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */
- Index *pIndex; /* List of SQL indexes on this table. */
- int tnum; /* Root BTree node for this table (see note above) */
- Select *pSelect; /* NULL for tables. Points to definition if a view. */
- int nRef; /* Number of pointers to this Table */
- Trigger *pTrigger; /* List of SQL triggers on this table */
- FKey *pFKey; /* Linked list of all foreign keys in this table */
- char *zColAff; /* String defining the affinity of each column */
+ sqlite3 *db; /* Associated database connection. Might be NULL. */
+ char *zName; /* Name of the table or view */
+ int iPKey; /* If not negative, use aCol[iPKey] as the primary key */
+ int nCol; /* Number of columns in this table */
+ Column *aCol; /* Information about each column */
+ Index *pIndex; /* List of SQL indexes on this table. */
+ int tnum; /* Root BTree node for this table (see note above) */
+ Select *pSelect; /* NULL for tables. Points to definition if a view. */
+ u16 nRef; /* Number of pointers to this Table */
+ u8 tabFlags; /* Mask of TF_* values */
+ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
+ Trigger *pTrigger; /* List of SQL triggers on this table */
+ FKey *pFKey; /* Linked list of all foreign keys in this table */
+ char *zColAff; /* String defining the affinity of each column */
#ifndef SQLITE_OMIT_CHECK
- Expr *pCheck; /* The AND of all CHECK constraints */
+ Expr *pCheck; /* The AND of all CHECK constraints */
#endif
#ifndef SQLITE_OMIT_ALTERTABLE
- int addColOffset; /* Offset in CREATE TABLE statement to add a new column */
-#endif
- u8 readOnly; /* True if this table should not be written by the user */
- u8 isEphem; /* True if created using OP_OpenEphermeral */
- u8 hasPrimKey; /* True if there exists a primary key */
- u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
- u8 autoInc; /* True if the integer primary key is autoincrement */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- u8 isVirtual; /* True if this is a virtual table */
- u8 isCommit; /* True once the CREATE TABLE has been committed */
- Module *pMod; /* Pointer to the implementation of the module */
- sqlite3_vtab *pVtab; /* Pointer to the module instance */
- int nModuleArg; /* Number of arguments to the module */
- char **azModuleArg; /* Text of all module args. [0] is module name */
-#endif
- Schema *pSchema; /* Schema that contains this table */
-};
+ int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ Module *pMod; /* Pointer to the implementation of the module */
+ sqlite3_vtab *pVtab; /* Pointer to the module instance */
+ int nModuleArg; /* Number of arguments to the module */
+ char **azModuleArg; /* Text of all module args. [0] is module name */
+#endif
+ Schema *pSchema; /* Schema that contains this table */
+ Table *pNextZombie; /* Next on the Parse.pZombieTab list */
+};
+
+/*
+** Allowed values for Tabe.tabFlags.
+*/
+#define TF_Readonly 0x01 /* Read-only system table */
+#define TF_Ephemeral 0x02 /* An emphermal table */
+#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
+#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
+#define TF_Virtual 0x10 /* Is a virtual table */
+#define TF_NeedMetadata 0x20 /* aCol[].zType and aCol[].pColl missing */
+
+
/*
** Test to see whether or not a table is a virtual table. This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
-# define IsVirtual(X) ((X)->isVirtual)
+# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
# define IsHiddenColumn(X) ((X)->isHidden)
#else
# define IsVirtual(X) 0
# define IsHiddenColumn(X) 0
@@ -8754,22 +9441,46 @@
/*
** An instance of the following structure is passed as the first
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
-**
-** If the KeyInfo.incrKey value is true and the comparison would
-** otherwise be equal, then return a result as if the second key
-** were larger.
*/
struct KeyInfo {
sqlite3 *db; /* The database connection */
u8 enc; /* Text encoding - one of the TEXT_Utf* values */
- u8 incrKey; /* Increase 2nd key by epsilon before comparison */
- u8 prefixIsEqual; /* Treat a prefix as equal */
- int nField; /* Number of entries in aColl[] */
+ u16 nField; /* Number of entries in aColl[] */
u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
};
+
+/*
+** An instance of the following structure holds information about a
+** single index record that has already been parsed out into individual
+** values.
+**
+** A record is an object that contains one or more fields of data.
+** Records are used to store the content of a table row and to store
+** the key of an index. A blob encoding of a record is created by
+** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
+** OP_Column opcode.
+**
+** This structure holds a record that has already been disassembled
+** into its constitutent fields.
+*/
+struct UnpackedRecord {
+ KeyInfo *pKeyInfo; /* Collation and sort-order information */
+ u16 nField; /* Number of entries in apMem[] */
+ u16 flags; /* Boolean settings. UNPACKED_... below */
+ Mem *aMem; /* Values */
+};
+
+/*
+** Allowed values of UnpackedRecord.flags
+*/
+#define UNPACKED_NEED_FREE 0x0001 /* Memory is from sqlite3Malloc() */
+#define UNPACKED_NEED_DESTROY 0x0002 /* apMem[]s should all be destroyed */
+#define UNPACKED_IGNORE_ROWID 0x0004 /* Ignore trailing rowid on key1 */
+#define UNPACKED_INCRKEY 0x0008 /* Make this key an epsilon larger */
+#define UNPACKED_PREFIX_MATCH 0x0010 /* A prefix match is considered OK */
/*
** Each SQL index is represented in memory by an
** instance of the following structure.
@@ -8932,9 +9643,9 @@
int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
Select *pSelect; /* When the expression is a sub-select. Also the
** right side of "<expr> IN (<select>)" */
- Table *pTab; /* Table for OP_Column expressions. */
+ Table *pTab; /* Table for TK_COLUMN expressions. */
#if SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Height of the tree headed by this node */
#endif
};
@@ -8978,10 +9689,11 @@
struct ExprList_item {
Expr *pExpr; /* The list of expressions */
char *zName; /* Token associated with this expression */
u8 sortOrder; /* 1 for DESC or 0 for ASC */
- u8 isAgg; /* True if this is an aggregate like count(*) */
u8 done; /* A flag to indicate when processing is finished */
+ u16 iCol; /* For ORDER BY, column number in result set */
+ u16 iAlias; /* Index into Parse.aAlias[] for zName */
} *a; /* One entry for each expression */
};
/*
@@ -9047,8 +9759,11 @@
int iCursor; /* The VDBE cursor number used to access this table */
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 */
};
/*
@@ -9092,9 +9807,9 @@
int brk; /* Jump here to break out of the loop */
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 {
int iCur; /* The VDBE cursor used by this IN operator */
@@ -9193,14 +9908,10 @@
*/
struct Select {
ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
- u8 isDistinct; /* True if the DISTINCT keyword is present */
- u8 isResolved; /* True once sqlite3SelectResolve() has run. */
- u8 isAgg; /* True if this is an aggregate query */
- u8 usesEphm; /* True if uses an OpenEphemeral opcode */
- u8 disallowOrderBy; /* Do not allow an ORDER BY to be attached if TRUE */
char affinity; /* MakeRecord with this affinity for SRT_Set */
+ u16 selFlags; /* Various SF_* values */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
Expr *pHaving; /* The HAVING clause */
@@ -9214,9 +9925,22 @@
int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
};
/*
-** The results of a select can be distributed in several ways.
+** Allowed values for Select.selFlags. The "SF" prefix stands for
+** "Select Flag".
+*/
+#define SF_Distinct 0x0001 /* Output should be DISTINCT */
+#define SF_Resolved 0x0002 /* Identifiers have been resolved */
+#define SF_Aggregate 0x0004 /* Contains aggregate functions */
+#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
+#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
+
+
+/*
+** The results of a select can be distributed in several ways. The
+** "SRT" prefix means "SELECT Result Type".
*/
#define SRT_Union 1 /* Store result as keys in an index */
#define SRT_Except 2 /* Remove result from a UNION index */
#define SRT_Exists 3 /* Store 1 if the result is not empty */
@@ -9224,9 +9948,9 @@
/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)
-#define SRT_Callback 5 /* Invoke a callback with each row of result */
+#define SRT_Output 5 /* Output each row of result */
#define SRT_Mem 6 /* Store result in a memory cell */
#define SRT_Set 7 /* Store results as keys in an index */
#define SRT_Table 8 /* Store result as data with an automatic rowid */
#define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */
@@ -9307,8 +10031,10 @@
int nVar; /* Number of '?' variables seen in the SQL so far */
int nVarExpr; /* Number of used slots in apVarExpr[] */
int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */
Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */
+ int nAlias; /* Number of aliased result set columns */
+ int *aAlias; /* Register used to hold aliased result */
u8 explain; /* True if the EXPLAIN flag is found on the query */
Token sErrToken; /* The token at which the error occurred */
Token sNameToken; /* Token with unqualified schema object name */
Token sLastToken; /* The last token parsed */
@@ -9324,8 +10050,9 @@
int nVtabLock; /* Number of virtual tables to lock */
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
#define IN_DECLARE_VTAB 0
@@ -9500,12 +10227,13 @@
** An objected used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end.
*/
struct StrAccum {
- char *zBase; /* A base allocation. Not from malloc. */
- char *zText; /* The string collected so far */
- int nChar; /* Length of the string so far */
- int nAlloc; /* Amount of space allocated in zText */
+ sqlite3 *db; /* Optional database for lookaside. Can be NULL */
+ char *zBase; /* A base allocation. Not from malloc. */
+ char *zText; /* The string collected so far */
+ int nChar; /* Length of the string so far */
+ int nAlloc; /* Amount of space allocated in zText */
int mxAlloc; /* Maximum allowed string length */
u8 mallocFailed; /* Becomes true if any memory allocation fails */
u8 useMalloc; /* True if zText is enlargable using realloc */
u8 tooBig; /* Becomes true if string size exceeds limits */
@@ -9531,8 +10259,10 @@
int bMemstat; /* True to enable memory status */
int bCoreMutex; /* True to enable core mutexing */
int bFullMutex; /* True to enable full mutexing */
int mxStrlen; /* Maximum string length */
+ int szLookaside; /* Default lookaside buffer size */
+ int nLookaside; /* Default lookaside buffer count */
sqlite3_mem_methods m; /* Low-level memory allocation interface */
sqlite3_mutex_methods mutex; /* Low-level mutex interface */
void *pHeap; /* Heap storage space */
int nHeap; /* Size of pHeap[] */
@@ -9543,11 +10273,44 @@
void *pPage; /* Page cache memory */
int szPage; /* Size of each page in pPage[] */
int nPage; /* Number of pages in pPage[] */
int isInit; /* True after initialization has finished */
+ int inProgress; /* True while initialization in progress */
int isMallocInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
-};
+ int nRefInitMutex; /* Number of users of pInitMutex */
+ int nSmall; /* alloc size threshold used by mem6.c */
+ int mxParserStack; /* maximum depth of the parser stack */
+ int sharedCacheEnabled; /* true if shared-cache mode enabled */
+};
+
+/*
+** Context pointer passed down through the tree-walk.
+*/
+struct Walker {
+ int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
+ int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
+ Parse *pParse; /* Parser context. */
+ union { /* Extra data for callback */
+ NameContext *pNC; /* Naming context */
+ int i; /* Integer value */
+ } u;
+};
+
+/* Forward declarations */
+SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
+SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
+SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
+SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
+SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
+
+/*
+** Return code from the parse-tree walking primitives and their
+** callbacks.
+*/
+#define WRC_Continue 0
+#define WRC_Prune 1
+#define WRC_Abort 2
/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
@@ -9584,33 +10347,33 @@
SQLITE_PRIVATE void *sqlite3Malloc(int);
SQLITE_PRIVATE void *sqlite3MallocZero(int);
SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, int);
SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, int);
-SQLITE_PRIVATE char *sqlite3StrDup(const char*);
-SQLITE_PRIVATE char *sqlite3StrNDup(const char*, int);
SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*);
SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, int);
SQLITE_PRIVATE void *sqlite3Realloc(void*, int);
SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, int);
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, int);
-SQLITE_PRIVATE int sqlite3MallocSize(void *);
+SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
+SQLITE_PRIVATE int sqlite3MallocSize(void*);
+SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*);
SQLITE_PRIVATE void *sqlite3ScratchMalloc(int);
SQLITE_PRIVATE void sqlite3ScratchFree(void*);
SQLITE_PRIVATE void *sqlite3PageMalloc(int);
SQLITE_PRIVATE void sqlite3PageFree(void*);
SQLITE_PRIVATE void sqlite3MemSetDefault(void);
-SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
+SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
-
-#ifndef SQLITE_MUTEX_NOOP
+SQLITE_PRIVATE int sqlite3MemoryAlarm(void (*)(void*, sqlite3_int64, int), void*, sqlite3_int64);
+
+#ifndef SQLITE_MUTEX_OMIT
SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void);
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int);
SQLITE_PRIVATE int sqlite3MutexInit(void);
SQLITE_PRIVATE int sqlite3MutexEnd(void);
#endif
-SQLITE_PRIVATE void sqlite3StatusReset(void);
SQLITE_PRIVATE int sqlite3StatusValue(int);
SQLITE_PRIVATE void sqlite3StatusAdd(int, int);
SQLITE_PRIVATE void sqlite3StatusSet(int, int);
@@ -9618,8 +10381,9 @@
SQLITE_PRIVATE void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
+SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE_TEST)
@@ -9643,18 +10407,19 @@
SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
SQLITE_PRIVATE void sqlite3ExprSpan(Expr*,Token*,Token*);
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*);
-SQLITE_PRIVATE void sqlite3ExprDelete(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(ExprList*);
+SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3*, int);
SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,char*,Select*);
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token*);
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
@@ -9686,24 +10451,29 @@
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 *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(IdList*);
-SQLITE_PRIVATE void sqlite3SrcListDelete(SrcList*);
+SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
+SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Token*, int, int);
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
-SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*);
+SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,int,Expr*,Expr*);
-SQLITE_PRIVATE void sqlite3SelectDelete(Select*);
+SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
+SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
+#endif
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
@@ -9730,9 +10500,8 @@
SQLITE_PRIVATE void sqlite3Vacuum(Parse*);
SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*);
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, Token*);
SQLITE_PRIVATE int sqlite3ExprCompare(Expr*, Expr*);
-SQLITE_PRIVATE int sqlite3ExprResolveNames(NameContext *, Expr *);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
SQLITE_PRIVATE Expr *sqlite3CreateIdExpr(Parse *, const char*);
@@ -9762,11 +10531,14 @@
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*);
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*);
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*);
+SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*);
-SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(sqlite3*);
+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void);
+SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void);
+SQLITE_PRIVATE int sqlite3GetBuiltinFunction(const char *, int, FuncDef **);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlite3SafetyOn(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3*);
#else
@@ -9775,9 +10547,12 @@
#endif
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
-SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Select*, Expr*, 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*,
Expr*,int, int);
@@ -9787,19 +10562,19 @@
SQLITE_PRIVATE int sqlite3TriggersExist(Parse*, Table*, int, ExprList*);
SQLITE_PRIVATE int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int,
int, int, u32*, u32*);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
-SQLITE_PRIVATE void sqlite3DeleteTriggerStep(TriggerStep*);
+SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
ExprList*,Select*,int);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, int);
SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
-SQLITE_PRIVATE void sqlite3DeleteTrigger(Trigger*);
+SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
#else
# define sqlite3TriggersExist(A,B,C,D,E,F) 0
-# define sqlite3DeleteTrigger(A)
+# define sqlite3DeleteTrigger(A,B)
# define sqlite3DropTriggerPtr(A,B)
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I,J,K) 0
#endif
@@ -9828,9 +10603,8 @@
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
SQLITE_PRIVATE int sqlite3FixExprList(DbFixer*, ExprList*);
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*);
-SQLITE_API char *sqlite3_snprintf(int,char*,const char*,...);
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3FitsIn64Bits(const char *, int);
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
@@ -9901,9 +10675,10 @@
SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
-SQLITE_PRIVATE struct Sqlite3Config sqlite3Config;
+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 void sqlite3AlterFunctions(sqlite3*);
@@ -9910,10 +10685,13 @@
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
-SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *, Expr *, int);
-SQLITE_PRIVATE int sqlite3SelectResolve(Parse *, Select *, NameContext *);
+SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *, Expr *, int, int);
+SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
+SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(sqlite3*, CollSeq *, const char *, int);
@@ -9924,9 +10702,8 @@
SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*);
SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3*, int);
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
-SQLITE_PRIVATE void sqlite3AttachFunctions(sqlite3 *);
SQLITE_PRIVATE void sqlite3MinimumFileFormat(Parse*, int, int);
SQLITE_PRIVATE void sqlite3SchemaFree(void *);
SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
@@ -9948,8 +10725,11 @@
*/
SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(size_t));
SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
SQLITE_PRIVATE void sqlite3Parser(void*, int, Token, Parse*);
+#ifdef YYTRACKMAXSTACKDEPTH
+SQLITE_PRIVATE int sqlite3ParserStackPeak(void*);
+#endif
SQLITE_PRIVATE int sqlite3AutoLoadExtensions(sqlite3*);
#ifndef SQLITE_OMIT_LOAD_EXTENSION
SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*);
@@ -9968,14 +10748,14 @@
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
# define sqlite3VtabClear(X)
-# define sqlite3VtabSync(X,Y) (Y)
+# define sqlite3VtabSync(X,Y) SQLITE_OK
# define sqlite3VtabRollback(X)
# define sqlite3VtabCommit(X)
#else
SQLITE_PRIVATE void sqlite3VtabClear(Table*);
-SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, int rc);
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **);
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
#endif
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
@@ -9990,8 +10770,9 @@
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
SQLITE_PRIVATE void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
+SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
@@ -10027,14 +10808,20 @@
#else
#define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
#endif
+SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
+SQLITE_PRIVATE int sqlite3MemJournalSize();
+SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *);
+
#if SQLITE_MAX_EXPR_DEPTH>0
SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *);
+SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int);
#else
#define sqlite3ExprSetHeight(x,y)
#define sqlite3SelectExprHeight(x) 0
+ #define sqlite3ExprCheckHeight(x,y)
#endif
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32);
@@ -10078,9 +10865,9 @@
*************************************************************************
**
** This file contains definitions of global variables and contants.
**
-** $Id: global.c,v 1.3 2008/07/08 14:52:10 drh Exp $
+** $Id: global.c,v 1.8 2008/09/04 17:17:39 danielk1977 Exp $
*/
/* An array to map all upper-case characters into their corresponding
@@ -10131,9 +10918,25 @@
/*
** The following singleton contains the global configuration for
** the SQLite library.
*/
-SQLITE_PRIVATE struct Sqlite3Config sqlite3Config = { 1, 1, 1, 0x7ffffffe };
+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 */
+};
+
+
+/*
+** Hash table for global functions - functions common to all
+** database connections. After initialization, this table is
+** read-only.
+*/
+SQLITE_PRIVATE SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
/************** End of global.c **********************************************/
/************** Begin file status.c ******************************************/
/*
@@ -10150,56 +10953,66 @@
**
** This module implements the sqlite3_status() interface and related
** functionality.
**
-** $Id: status.c,v 1.3 2008/07/11 16:15:18 drh Exp $
+** $Id: status.c,v 1.9 2008/09/02 00:52:52 drh Exp $
*/
/*
** Variables in which to record status information.
*/
-static struct {
- int nowValue[6]; /* Current value */
- int mxValue[6]; /* Maximum value */
-} sqlite3Stat;
-
-
-/*
-** Reset the status records. This routine is called by
-** sqlite3_initialize().
-*/
-SQLITE_PRIVATE void sqlite3StatusReset(void){
- memset(&sqlite3Stat, 0, sizeof(sqlite3Stat));
-}
+typedef struct sqlite3StatType sqlite3StatType;
+static SQLITE_WSD struct sqlite3StatType {
+ int nowValue[9]; /* Current value */
+ int mxValue[9]; /* Maximum value */
+} 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];
}
/*
** Add N to the value of a status record. It is assumed that the
** 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];
}
}
/*
@@ -10209,15 +11022,42 @@
** 32-bit integer is an atomic operation. If that assumption is not true,
** 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) ){
- return SQLITE_MISUSE;
- }
- *pCurrent = sqlite3Stat.nowValue[op];
- *pHighwater = sqlite3Stat.mxValue[op];
+ wsdStatInit;
+ if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
+ return SQLITE_MISUSE;
+ }
+ *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;
+}
+
+/*
+** Query status information for a single database connection
+*/
+SQLITE_API int sqlite3_db_status(
+ sqlite3 *db, /* The database connection whose status is desired */
+ int op, /* Status verb */
+ int *pCurrent, /* Write current value here */
+ int *pHighwater, /* Write high-water mark here */
+ int resetFlag /* Reset high-water mark if true */
+){
+ switch( op ){
+ case SQLITE_DBSTATUS_LOOKASIDE_USED: {
+ *pCurrent = db->lookaside.nOut;
+ *pHighwater = db->lookaside.mxOut;
+ if( resetFlag ){
+ db->lookaside.mxOut = db->lookaside.nOut;
+ }
+ break;
+ }
+ default: {
+ return SQLITE_ERROR;
+ }
}
return SQLITE_OK;
}
@@ -10240,9 +11080,9 @@
** There is only one exported symbol in this file - the function
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: date.c,v 1.85 2008/06/18 17:09:10 danielk1977 Exp $
+** $Id: date.c,v 1.92 2008/10/13 15:35:09 drh Exp $
**
** SQLite processes all times and dates as Julian Day numbers. The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
@@ -10774,17 +11614,20 @@
if( strcmp(z, "unixepoch")==0 && p->validJD ){
p->iJD = p->iJD/86400.0 + 2440587.5*86400000.0;
clearYMD_HMS_TZ(p);
rc = 0;
- }else if( strcmp(z, "utc")==0 ){
- double c1;
+ }
+#ifndef SQLITE_OMIT_LOCALTIME
+ else if( strcmp(z, "utc")==0 ){
+ int c1;
computeJD(p);
c1 = localtimeOffset(p);
p->iJD -= c1;
clearYMD_HMS_TZ(p);
p->iJD += c1 - localtimeOffset(p);
rc = 0;
}
+#endif
break;
}
case 'w': {
/*
@@ -11067,11 +11910,13 @@
DateTime x;
u64 n;
int i, j;
char *z;
+ sqlite3 *db;
const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
char zBuf[100];
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
+ db = sqlite3_context_db_handle(context);
for(i=0, n=1; zFmt[i]; i++, n++){
if( zFmt[i]=='%' ){
switch( zFmt[i+1] ){
case 'd':
@@ -11105,13 +11950,13 @@
}
}
if( n<sizeof(zBuf) ){
z = zBuf;
- }else if( n>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
+ }else if( n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
return;
}else{
- z = sqlite3Malloc( n );
+ z = sqlite3DbMallocRaw(db, n);
if( z==0 ){
sqlite3_result_error_nomem(context);
return;
}
@@ -11174,9 +12019,9 @@
}
}
z[j] = 0;
sqlite3_result_text(context, z, -1,
- z==zBuf ? SQLITE_TRANSIENT : sqlite3_free);
+ z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
}
/*
** current_time()
@@ -11268,46 +12113,32 @@
** This function registered all of the above C functions as SQL
** functions. This should be the only routine in this file with
** external linkage.
*/
-SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
+SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
+ static SQLITE_WSD FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
- static const struct {
- char *zName;
- int nArg;
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
- } aFuncs[] = {
- { "julianday", -1, juliandayFunc },
- { "date", -1, dateFunc },
- { "time", -1, timeFunc },
- { "datetime", -1, datetimeFunc },
- { "strftime", -1, strftimeFunc },
- { "current_time", 0, ctimeFunc },
- { "current_timestamp", 0, ctimestampFunc },
- { "current_date", 0, cdateFunc },
- };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
- SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
- }
-#else
- static const struct {
- char *zName;
- char *zFormat;
- } aFuncs[] = {
- { "current_time", "%H:%M:%S" },
- { "current_date", "%Y-%m-%d" },
- { "current_timestamp", "%Y-%m-%d %H:%M:%S" }
- };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8,
- aFuncs[i].zFormat, currentTimeFunc, 0, 0);
- }
-#endif
+ FUNCTION(julianday, -1, 0, 0, juliandayFunc ),
+ FUNCTION(date, -1, 0, 0, dateFunc ),
+ FUNCTION(time, -1, 0, 0, timeFunc ),
+ FUNCTION(datetime, -1, 0, 0, datetimeFunc ),
+ FUNCTION(strftime, -1, 0, 0, strftimeFunc ),
+ FUNCTION(current_time, 0, 0, 0, ctimeFunc ),
+ FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
+ FUNCTION(current_date, 0, 0, 0, cdateFunc ),
+#else
+ STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
+ STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc),
+ STR_FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
+#endif
+ };
+ int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aDateTimeFuncs);
+
+ for(i=0; i<ArraySize(aDateTimeFuncs); i++){
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
+ }
}
/************** End of date.c ************************************************/
/************** Begin file os.c **********************************************/
@@ -11325,9 +12156,9 @@
**
** This file contains OS interface code that is common to all
** architectures.
**
-** $Id: os.c,v 1.119 2008/06/26 18:16:06 drh Exp $
+** $Id: os.c,v 1.124 2008/10/07 15:25:48 drh Exp $
*/
#define _SQLITE_OS_C_ 1
#undef _SQLITE_OS_C_
@@ -11501,24 +12332,25 @@
/*
** 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
** first VFS on the list.
*/
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);
for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
@@ -11578,9 +12410,9 @@
/*
** 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);
vfsUnlink(pVfs);
@@ -11601,9 +12433,9 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
**
-** $Id: fault.c,v 1.10 2008/06/22 12:37:58 drh Exp $
+** $Id: fault.c,v 1.11 2008/09/02 00:52:52 drh Exp $
*/
/*
** This file contains code to support the concept of "benign"
@@ -11625,12 +12457,29 @@
/*
** 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
** sqlite3EndBenignMalloc() are called, respectively.
@@ -11638,10 +12487,11 @@
SQLITE_PRIVATE void sqlite3BenignMallocHooks(
void (*xBenignBegin)(void),
void (*xBenignEnd)(void)
){
- hooks.xBenignBegin = xBenignBegin;
- hooks.xBenignEnd = xBenignEnd;
+ wsdHooksInit;
+ wsdHooks.xBenignBegin = xBenignBegin;
+ wsdHooks.xBenignEnd = xBenignEnd;
}
/*
** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
@@ -11648,21 +12498,86 @@
** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
** 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: mem0.c,v 1.1 2008/10/28 18:58:20 drh Exp $
+*/
+
+/*
+** This version of the memory allocator is the default. It is
+** used when no other memory allocator is specified using compile-time
+** macros.
+*/
+#ifdef SQLITE_ZERO_MALLOC
+
+/*
+** No-op versions of all memory allocation routines
+*/
+static void *sqlite3MemMalloc(int nByte){ return 0; }
+static void sqlite3MemFree(void *pPrior){ return; }
+static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
+static int sqlite3MemSize(void *pPrior){ return 0; }
+static int sqlite3MemRoundup(int n){ return n; }
+static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
+static void sqlite3MemShutdown(void *NotUsed){ return; }
+
+/*
+** This routine is the only routine in this file with external linkage.
+**
+** Populate the low-level memory allocation function pointers in
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
+*/
+SQLITE_PRIVATE void sqlite3MemSetDefault(void){
+ static const sqlite3_mem_methods defaultMethods = {
+ sqlite3MemMalloc,
+ sqlite3MemFree,
+ sqlite3MemRealloc,
+ sqlite3MemSize,
+ sqlite3MemRoundup,
+ sqlite3MemInit,
+ sqlite3MemShutdown,
+ 0
+ };
+ sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
+}
+
+#endif /* SQLITE_ZERO_MALLOC */
+
+/************** End of mem0.c ************************************************/
/************** Begin file mem1.c ********************************************/
/*
** 2007 August 14
**
@@ -11681,9 +12596,9 @@
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
-** $Id: mem1.c,v 1.23 2008/06/23 15:10:25 danielk1977 Exp $
+** $Id: mem1.c,v 1.27 2008/10/28 18:58:20 drh Exp $
*/
/*
** This version of the memory allocator is the default. It is
@@ -11787,9 +12702,9 @@
/*
** 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.
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
*/
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
static const sqlite3_mem_methods defaultMethods = {
sqlite3MemMalloc,
@@ -11828,9 +12743,9 @@
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
-** $Id: mem2.c,v 1.34 2008/07/10 18:13:42 drh Exp $
+** $Id: mem2.c,v 1.40 2008/10/28 18:58:20 drh Exp $
*/
/*
** This version of the memory allocator is used only if the
@@ -11844,9 +12759,9 @@
#ifdef __GLIBC__
extern int backtrace(void**,int);
extern void backtrace_symbols_fd(void*const*,int,int);
#else
-# define backtrace(A,B) 0
+# define backtrace(A,B) 1
# define backtrace_symbols_fd(A,B,C)
#endif
/*
@@ -11920,15 +12835,38 @@
int disallow; /* Do not allow memory allocation */
/*
** Gather statistics on the sizes of memory allocations.
- ** sizeCnt[i] is the number of allocation attempts of i*8
+ ** nAlloc[i] is the number of allocation attempts of i*8
** bytes. i==NCSIZE is the number of allocation attempts for
** sizes more than NCSIZE*8 bytes.
*/
- int sizeCnt[NCSIZE];
+ int nAlloc[NCSIZE]; /* Total number of allocations */
+ int nCurrent[NCSIZE]; /* Current number of allocations */
+ int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */
} mem;
+
+
+/*
+** Adjust memory usage statistics
+*/
+static void adjustStats(int iSize, int increment){
+ int i = ((iSize+7)&~7)/8;
+ if( i>NCSIZE-1 ){
+ i = NCSIZE - 1;
+ }
+ if( increment>0 ){
+ mem.nAlloc[i]++;
+ mem.nCurrent[i]++;
+ if( mem.nCurrent[i]>mem.mxCurrent[i] ){
+ mem.mxCurrent[i] = mem.nCurrent[i];
+ }
+ }else{
+ mem.nCurrent[i]--;
+ assert( mem.nCurrent[i]>=0 );
+ }
+}
/*
** Given an allocation, find the MemBlockHdr for that allocation.
**
@@ -11969,9 +12907,9 @@
/*
** 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);
}
@@ -12005,13 +12943,8 @@
int nReserve;
sqlite3_mutex_enter(mem.mutex);
assert( mem.disallow==0 );
nReserve = (nByte+7)&~7;
- if( nReserve/8>NCSIZE-1 ){
- mem.sizeCnt[NCSIZE-1]++;
- }else{
- mem.sizeCnt[nReserve/8]++;
- }
totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
mem.nBacktrace*sizeof(void*) + mem.nTitle;
p = malloc(totalSize);
if( p ){
@@ -12042,8 +12975,9 @@
if( mem.nTitle ){
memcpy(z, mem.zTitle, mem.nTitle);
}
pHdr->iSize = nByte;
+ adjustStats(nByte, +1);
pInt = (int*)&pHdr[1];
pInt[nReserve/sizeof(int)] = REARGUARD;
memset(pInt, 0x65, nReserve);
p = (void*)pInt;
@@ -12058,9 +12992,9 @@
static void sqlite3MemFree(void *pPrior){
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;
sqlite3_mutex_enter(mem.mutex);
@@ -12079,8 +13013,9 @@
mem.pLast = pHdr->pPrev;
}
z = (char*)pBt;
z -= pHdr->nTitle;
+ adjustStats(pHdr->iSize, -1);
memset(z, 0x2b, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
pHdr->iSize + sizeof(int) + pHdr->nTitle);
free(z);
sqlite3_mutex_leave(mem.mutex);
@@ -12110,12 +13045,11 @@
}
return pNew;
}
-
/*
** Populate the low-level memory allocation function pointers in
-** sqlite3Config.m with pointers to the routines in this file.
+** sqlite3GlobalConfig.m with pointers to the routines in this file.
*/
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
static const sqlite3_mem_methods defaultMethods = {
sqlite3MemMalloc,
@@ -12197,14 +13131,17 @@
}
}
fprintf(out, "COUNTS:\n");
for(i=0; i<NCSIZE-1; i++){
- if( mem.sizeCnt[i] ){
- fprintf(out, " %3d: %d\n", i*8+8, mem.sizeCnt[i]);
- }
- }
- if( mem.sizeCnt[NCSIZE-1] ){
- fprintf(out, " >%3d: %d\n", NCSIZE*8, mem.sizeCnt[NCSIZE-1]);
+ if( mem.nAlloc[i] ){
+ fprintf(out, " %5d: %10d %10d %10d\n",
+ i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
+ }
+ }
+ if( mem.nAlloc[NCSIZE-1] ){
+ fprintf(out, " %5d: %10d %10d %10d\n",
+ NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
+ mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
}
fclose(out);
}
@@ -12214,9 +13151,9 @@
SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
int i;
int nTotal = 0;
for(i=0; i<NCSIZE; i++){
- nTotal += mem.sizeCnt[i];
+ nTotal += mem.nAlloc[i];
}
return nTotal;
}
@@ -12249,9 +13186,9 @@
**
** This version of the memory allocation subsystem is included
** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
**
-** $Id: mem3.c,v 1.18 2008/06/27 14:05:25 danielk1977 Exp $
+** $Id: mem3.c,v 1.23 2008/09/02 17:52:52 danielk1977 Exp $
*/
/*
** This version of the memory allocator is only built into the library
@@ -12324,9 +13261,16 @@
** into a single structure named "mem3". This is to keep 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 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.
*/
int alarmBusy;
@@ -12356,17 +13300,11 @@
** chunks.
*/
u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
-
- /*
- ** Memory available for allocation. nPool is the size of the array
- ** (in Mem3Blocks) pointed to by aPool less 2.
- */
- u32 nPool;
- Mem3Block *aPool;
- /* Mem3Block aPool[SQLITE_MEMORY_SIZE/sizeof(Mem3Block)+2]; */
-} mem3;
+} mem3 = { 97535575 };
+
+#define mem3 GLOBAL(struct Mem3Global, mem3)
/*
** Unlink the chunk at mem3.aPool[i] from list it is currently
** on. *pRoot is the list that i is a member of.
@@ -12443,12 +13381,12 @@
/*
** 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);
}
@@ -12696,8 +13634,32 @@
}
}
/*
+** Return the size of an outstanding allocation, in bytes. The
+** size returned omits the 8-byte header overhead. This only
+** works for chunks that are currently checked out.
+*/
+static int memsys3Size(void *p){
+ Mem3Block *pBlock;
+ if( p==0 ) return 0;
+ pBlock = (Mem3Block*)p;
+ assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
+ return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
+}
+
+/*
+** Round up a request size to the next valid allocation size.
+*/
+static int memsys3Roundup(int n){
+ if( n<=12 ){
+ return 12;
+ }else{
+ return ((n+11)&~7) - 4;
+ }
+}
+
+/*
** Allocate nBytes of memory.
*/
static void *memsys3Malloc(int nBytes){
sqlite3_int64 *p;
@@ -12715,20 +13677,8 @@
assert( pPrior );
memsys3Enter();
memsys3FreeUnsafe(pPrior);
memsys3Leave();
-}
-
-/*
-** Return the size of an outstanding allocation, in bytes. The
-** size returned omits the 8-byte header overhead. This only
-** works for chunks that are currently checked out.
-*/
-static int memsys3Size(void *p){
- Mem3Block *pBlock = (Mem3Block*)p;
- assert( pBlock );
- assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
- return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
}
/*
** Change the size of an existing memory allocation
@@ -12761,26 +13711,19 @@
return p;
}
/*
-** Round up a request size to the next valid allocation size.
-*/
-static int memsys3Roundup(int n){
- return (n+7) & ~7;
-}
-
-/*
** 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;
mem3.mnMaster = mem3.szMaster;
@@ -12804,10 +13747,10 @@
/*
** 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;
if( zFilename==0 || zFilename[0]==0 ){
@@ -12872,17 +13815,17 @@
fflush(stdout);
}else{
fclose(out);
}
-}
-#endif
+#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
** is not required to be threadsafe (it is not).
@@ -12929,38 +13872,16 @@
**
** This version of the memory allocation subsystem is included
** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
**
-** $Id: mem5.c,v 1.10 2008/06/27 14:05:25 danielk1977 Exp $
+** $Id: mem5.c,v 1.15 2008/10/28 18:58:20 drh Exp $
*/
/*
** This version of the memory allocator is used only when
-** SQLITE_POW2_MEMORY_SIZE is defined.
-*/
-#ifdef SQLITE_ENABLE_MEMSYS5
-
-/*
-** Log2 of the minimum size of an allocation. For example, if
-** 4 then all allocations will be rounded up to at least 16 bytes.
-** If 5 then all allocations will be rounded up to at least 32 bytes.
-*/
-#ifndef SQLITE_POW2_LOGMIN
-# define SQLITE_POW2_LOGMIN 6
-#endif
-
-/*
-** Log2 of the maximum size of an allocation.
-*/
-#ifndef SQLITE_POW2_LOGMAX
-# define SQLITE_POW2_LOGMAX 18
-#endif
-#define POW2_MAX (((unsigned int)1)<<SQLITE_POW2_LOGMAX)
-
-/*
-** Number of distinct allocation sizes.
-*/
-#define NSIZE (SQLITE_POW2_LOGMAX - SQLITE_POW2_LOGMIN + 1)
+** SQLITE_ENABLE_MEMSYS5 is defined.
+*/
+#ifdef SQLITE_ENABLE_MEMSYS5
/*
** A minimum allocation is an instance of the following structure.
** Larger allocations are an array of these structures where the
@@ -12990,20 +13911,15 @@
** into a single structure named "mem5". This is to keep the
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
-static struct {
- /*
- ** 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.
- */
- sqlite3_int64 alarmThreshold;
- void (*alarmCallback)(void*, sqlite3_int64,int);
- void *alarmArg;
- int alarmBusy;
+static SQLITE_WSD struct Mem5Global {
+ /*
+ ** Memory available for allocation
+ */
+ 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.
*/
@@ -13031,15 +13947,11 @@
** 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;
-} mem5;
+} mem5 = { 19804167 };
+
+#define mem5 GLOBAL(struct Mem5Global, mem5)
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.nAtom]))
/*
@@ -13086,12 +13998,12 @@
/*
** 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);
}
@@ -13311,18 +14223,18 @@
** Initialize this module.
*/
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;
if( !zByte ){
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;
}
@@ -13434,36 +14346,31 @@
**
*************************************************************************
** 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
-**
-** $Id: mutex.c,v 1.27 2008/06/19 08:51:24 danielk1977 Exp $
-*/
-
-#ifndef SQLITE_MUTEX_NOOP
+** This file contains code that is common across all mutex implementations.
+
+**
+** $Id: mutex.c,v 1.29 2008/10/07 15:25:48 drh Exp $
+*/
+
+#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();
sqlite3_mutex *pMaster = 0;
@@ -13472,18 +14379,18 @@
if( rc==SQLITE_OK ){
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();
}
}
return rc;
@@ -13494,9 +14401,9 @@
** sqlite3MutexInit().
*/
SQLITE_PRIVATE int sqlite3MutexEnd(void){
int rc = SQLITE_OK;
- rc = sqlite3Config.mutex.xMutexEnd();
+ rc = sqlite3GlobalConfig.mutex.xMutexEnd();
return rc;
}
/*
@@ -13505,24 +14412,24 @@
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
#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 ){
- return 0;
- }
- return sqlite3Config.mutex.xMutexAlloc(id);
+ if( !sqlite3GlobalConfig.bCoreMutex ){
+ return 0;
+ }
+ return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
}
/*
** Free a dynamic mutex.
*/
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexFree(p);
+ sqlite3GlobalConfig.mutex.xMutexFree(p);
}
}
/*
@@ -13530,9 +14437,9 @@
** until it can be obtained.
*/
SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexEnter(p);
+ sqlite3GlobalConfig.mutex.xMutexEnter(p);
}
}
/*
@@ -13541,9 +14448,9 @@
*/
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;
}
@@ -13554,9 +14461,9 @@
** this function is a no-op.
*/
SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
if( p ){
- sqlite3Config.mutex.xMutexLeave(p);
+ sqlite3GlobalConfig.mutex.xMutexLeave(p);
}
}
#ifndef NDEBUG
@@ -13564,22 +14471,89 @@
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** 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);
-}
-#endif
-
-#endif
-
-#ifdef SQLITE_MUTEX_NOOP_DEBUG
-/*
-** In this implementation, mutexes do not provide any mutual exclusion.
-** But the error checking is provided. This implementation is useful
-** for test purposes.
+ return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
+}
+#endif
+
+#endif /* SQLITE_OMIT_MUTEX */
+
+/************** End of mutex.c ***********************************************/
+/************** Begin file mutex_noop.c **************************************/
+/*
+** 2008 October 07
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains the C functions that implement mutexes.
+**
+** This implementation in this file does not provide any mutual
+** exclusion and is thus suitable for use only in applications
+** that use SQLite in a single thread. The routines defined
+** here are place-holders. Applications can substitute working
+** mutex routines at start-time using the
+**
+** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
+**
+** interface.
+**
+** If compiled with SQLITE_DEBUG, then additional logic is inserted
+** that does error checking on mutexes to make sure they are being
+** called correctly.
+**
+** $Id: mutex_noop.c,v 1.2 2008/10/15 19:03:03 drh Exp $
+*/
+
+
+#if defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG)
+/*
+** Stub routines for all mutex methods.
+**
+** This routines provide no mutual exclusion or error checking.
+*/
+static int noopMutexHeld(sqlite3_mutex *p){ return 1; }
+static int noopMutexNotheld(sqlite3_mutex *p){ return 1; }
+static int noopMutexInit(void){ return SQLITE_OK; }
+static int noopMutexEnd(void){ return SQLITE_OK; }
+static sqlite3_mutex *noopMutexAlloc(int id){ return (sqlite3_mutex*)8; }
+static void noopMutexFree(sqlite3_mutex *p){ return; }
+static void noopMutexEnter(sqlite3_mutex *p){ return; }
+static int noopMutexTry(sqlite3_mutex *p){ return SQLITE_OK; }
+static void noopMutexLeave(sqlite3_mutex *p){ return; }
+
+SQLITE_PRIVATE sqlite3_mutex_methods *sqlite3DefaultMutex(void){
+ static sqlite3_mutex_methods sMutex = {
+ noopMutexInit,
+ noopMutexEnd,
+ noopMutexAlloc,
+ noopMutexFree,
+ noopMutexEnter,
+ noopMutexTry,
+ noopMutexLeave,
+
+ noopMutexHeld,
+ noopMutexNotheld
+ };
+
+ return &sMutex;
+}
+#endif /* defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG) */
+
+#if defined(SQLITE_MUTEX_NOOP) && defined(SQLITE_DEBUG)
+/*
+** In this implementation, error checking is provided for testing
+** and debugging purposes. The mutexes still do not provide any
+** mutual exclusion.
*/
/*
** The mutex object
@@ -13592,27 +14566,27 @@
/*
** 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 ){
case SQLITE_MUTEX_FAST:
@@ -13637,9 +14611,9 @@
/*
** 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);
}
@@ -13654,14 +14628,14 @@
** mutex must be exited an equal number of times before another thread
** 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;
}
@@ -13670,33 +14644,33 @@
** previously entered by the same thread. The behavior
** 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 */
-
-/************** End of mutex.c ***********************************************/
+#endif /* defined(SQLITE_MUTEX_NOOP) && defined(SQLITE_DEBUG) */
+
+/************** End of mutex_noop.c ******************************************/
/************** Begin file mutex_os2.c ***************************************/
/*
** 2007 August 28
**
@@ -13984,9 +14958,9 @@
**
*************************************************************************
** This file contains the C functions that implement mutexes for pthreads
**
-** $Id: mutex_unix.c,v 1.12 2008/06/19 16:07:07 drh Exp $
+** $Id: mutex_unix.c,v 1.13 2008/07/16 12:33:24 drh Exp $
*/
/*
** The code in this file is only used if we are compiling threadsafe
@@ -14221,9 +15195,9 @@
pthread_t self = pthread_self();
if( p->nRef>0 && pthread_equal(p->owner, self) ){
p->nRef++;
rc = SQLITE_OK;
- }else if( pthread_mutex_lock(&p->mutex)==0 ){
+ }else if( pthread_mutex_trylock(&p->mutex)==0 ){
assert( p->nRef==0 );
p->owner = self;
p->nRef = 1;
rc = SQLITE_OK;
@@ -14558,9 +15532,9 @@
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
**
-** $Id: malloc.c,v 1.28 2008/07/14 12:38:21 drh Exp $
+** $Id: malloc.c,v 1.45 2008/10/12 00:27:53 shane Exp $
*/
/*
** This routine runs when the memory allocator sees that the
@@ -14588,11 +15562,11 @@
iLimit = n;
}
sqlite3_initialize();
if( iLimit>0 ){
- sqlite3_memory_alarm(softHeapLimitEnforcer, 0, iLimit);
- }else{
- sqlite3_memory_alarm(0, 0, 0);
+ sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, iLimit);
+ }else{
+ sqlite3MemoryAlarm(0, 0, 0);
}
overage = sqlite3_memory_used() - n;
if( overage>0 ){
sqlite3_release_memory(overage);
@@ -14605,10 +15579,13 @@
** cache database pages that are not currently in use.
*/
SQLITE_API int sqlite3_release_memory(int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- int nRet = sqlite3VdbeReleaseMemory(n);
- nRet += sqlite3PagerReleaseMemory(n-nRet);
+ int nRet = 0;
+#if 0
+ nRet += sqlite3VdbeReleaseMemory(n);
+#endif
+ nRet += sqlite3PcacheReleaseMemory(n-nRet);
return nRet;
#else
return SQLITE_OK;
#endif
@@ -14616,9 +15593,13 @@
/*
** 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 */
/*
** The alarm callback and its arguments. The mem0.mutex lock will
@@ -14632,61 +15613,65 @@
void *alarmArg;
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;
-
- /* Number of free pages for scratch and page-cache memory */
- u32 nScratchFree;
- u32 nPageFree;
-} mem0;
+} mem0 = { 62560955 };
+
+#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>=3000
- && sqlite3Config.nScratch>0 ){
- int i;
- mem0.aScratchFree = (u32*)&((char*)sqlite3Config.pScratch)
- [sqlite3Config.szScratch*sqlite3Config.nScratch];
- for(i=0; i<sqlite3Config.nScratch; i++){ mem0.aScratchFree[i] = i; }
- mem0.nScratchFree = sqlite3Config.nScratch;
- }else{
- sqlite3Config.pScratch = 0;
- sqlite3Config.szScratch = 0;
- }
- if( sqlite3Config.pPage && sqlite3Config.szPage>=512
- && sqlite3Config.nPage>0 ){
- int i;
- mem0.aPageFree = (u32*)&((char*)sqlite3Config.pPage)
- [sqlite3Config.szPage*sqlite3Config.nPage];
- for(i=0; i<sqlite3Config.nPage; i++){ mem0.aPageFree[i] = i; }
- mem0.nPageFree = sqlite3Config.nPage;
- }else{
- sqlite3Config.pPage = 0;
- sqlite3Config.szPage = 0;
- }
- return sqlite3Config.m.xInit(sqlite3Config.m.pAppData);
+ if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
+ && sqlite3GlobalConfig.nScratch>=0 ){
+ int i;
+ sqlite3GlobalConfig.szScratch -= 4;
+ mem0.aScratchFree = (u32*)&((char*)sqlite3GlobalConfig.pScratch)
+ [sqlite3GlobalConfig.szScratch*sqlite3GlobalConfig.nScratch];
+ for(i=0; i<sqlite3GlobalConfig.nScratch; i++){ mem0.aScratchFree[i] = i; }
+ mem0.nScratchFree = sqlite3GlobalConfig.nScratch;
+ }else{
+ sqlite3GlobalConfig.pScratch = 0;
+ sqlite3GlobalConfig.szScratch = 0;
+ }
+ if( sqlite3GlobalConfig.pPage && sqlite3GlobalConfig.szPage>=512
+ && sqlite3GlobalConfig.nPage>=1 ){
+ int i;
+ int overhead;
+ int sz = sqlite3GlobalConfig.szPage;
+ int n = sqlite3GlobalConfig.nPage;
+ overhead = (4*n + sz - 1)/sz;
+ sqlite3GlobalConfig.nPage -= overhead;
+ mem0.aPageFree = (u32*)&((char*)sqlite3GlobalConfig.pPage)
+ [sqlite3GlobalConfig.szPage*sqlite3GlobalConfig.nPage];
+ for(i=0; i<sqlite3GlobalConfig.nPage; i++){ mem0.aPageFree[i] = i; }
+ mem0.nPageFree = sqlite3GlobalConfig.nPage;
+ }else{
+ sqlite3GlobalConfig.pPage = 0;
+ sqlite3GlobalConfig.szPage = 0;
+ }
+ 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));
}
/*
@@ -14715,9 +15700,9 @@
/*
** 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
){
@@ -14727,8 +15712,22 @@
mem0.alarmThreshold = iThreshold;
sqlite3_mutex_leave(mem0.mutex);
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
*/
@@ -14754,22 +15753,25 @@
static int mallocWithAlarm(int n, void **pp){
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);
if( nUsed+nFull >= mem0.alarmThreshold ){
sqlite3MallocAlarm(nFull);
}
}
- p = sqlite3Config.m.xMalloc(nFull);
+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
if( p==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nFull);
- p = sqlite3Config.m.xMalloc(nFull);
- }
- if( p ) sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
+ p = sqlite3GlobalConfig.m.xMalloc(nFull);
+ }
+ if( p ){
+ nFull = sqlite3MallocSize(p);
+ sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
+ }
*pp = p;
return nFull;
}
@@ -14780,14 +15782,14 @@
SQLITE_PRIVATE void *sqlite3Malloc(int n){
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;
}
@@ -14833,9 +15835,9 @@
** would be much more complicated.) */
assert( scratchAllocOut==0 );
#endif
- if( sqlite3Config.szScratch<n ){
+ if( sqlite3GlobalConfig.szScratch<n ){
goto scratch_overflow;
}else{
sqlite3_mutex_enter(mem0.mutex);
if( mem0.nScratchFree==0 ){
@@ -14843,12 +15845,13 @@
goto scratch_overflow;
}else{
int i;
i = mem0.aScratchFree[--mem0.nScratchFree];
- sqlite3_mutex_leave(mem0.mutex);
- i *= sqlite3Config.szScratch;
+ i *= sqlite3GlobalConfig.szScratch;
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
- p = (void*)&((char*)sqlite3Config.pScratch)[i];
+ sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
+ sqlite3_mutex_leave(mem0.mutex);
+ p = (void*)&((char*)sqlite3GlobalConfig.pScratch)[i];
}
}
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
scratchAllocOut = p!=0;
@@ -14856,15 +15859,16 @@
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;
#endif
@@ -14881,28 +15885,28 @@
assert( scratchAllocOut==1 );
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);
- }
- }else{
- int i;
- i = (u8 *)p - (u8 *)sqlite3Config.pScratch;
- i /= sqlite3Config.szScratch;
- assert( i>=0 && i<sqlite3Config.nScratch );
+ sqlite3GlobalConfig.m.xFree(p);
+ }
+ }else{
+ int i;
+ 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);
}
@@ -14914,15 +15918,16 @@
** memory buffer provided by SQLITE_CONFIG_PAGECACHE if there is one
** and that memory is of the right size and is not completely
** consumed. Otherwise, failover to sqlite3Malloc().
*/
+#if 0
SQLITE_PRIVATE void *sqlite3PageMalloc(int n){
void *p;
assert( n>0 );
assert( (n & (n-1))==0 );
assert( n>=512 && n<=32768 );
- if( sqlite3Config.szPage<n ){
+ if( sqlite3GlobalConfig.szPage<n ){
goto page_overflow;
}else{
sqlite3_mutex_enter(mem0.mutex);
if( mem0.nPageFree==0 ){
@@ -14931,61 +15936,63 @@
}else{
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);
- }
- }else{
- /* The page allocation was allocated from the sqlite3Config.pPage
+ sqlite3GlobalConfig.m.xFree(p);
+ }
+ }else{
+ /* 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);
-#ifndef NDEBUG
+#if !defined(NDEBUG) && 0
/* Assert that a duplicate was not just inserted into aPageFree[]. */
for(i=0; i<mem0.nPageFree-1; i++){
assert( mem0.aPageFree[i]!=mem0.aPageFree[mem0.nPageFree-1] );
}
@@ -14992,29 +15999,63 @@
#endif
}
}
}
+#endif
+
+/*
+** TRUE if p is a lookaside memory allocation from db
+*/
+#ifndef SQLITE_OMIT_LOOKASIDE
+static int isLookaside(sqlite3 *db, void *p){
+ return db && p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
+}
+#else
+#define isLookaside(A,B) 0
+#endif
/*
** Return the size of a memory allocation previously obtained from
** sqlite3Malloc() or sqlite3_malloc().
*/
SQLITE_PRIVATE int sqlite3MallocSize(void *p){
- return 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 sqlite3GlobalConfig.m.xSize(p);
+ }
}
/*
** Free memory previously obtained from sqlite3Malloc().
*/
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);
+ }
+}
+
+/*
+** Free memory that might be associated with a particular database
+** connection.
+*/
+SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+ if( isLookaside(db, p) ){
+ LookasideSlot *pBuf = (LookasideSlot*)p;
+ pBuf->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = pBuf;
+ db->lookaside.nOut--;
+ }else{
+ sqlite3_free(p);
}
}
/*
@@ -15030,31 +16071,32 @@
sqlite3_free(pOld);
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{
if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >=
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);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
}
}
sqlite3_mutex_leave(mem0.mutex);
}else{
- pNew = sqlite3Config.m.xRealloc(pOld, nBytes);
+ pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nBytes);
}
return pNew;
}
@@ -15095,30 +16137,77 @@
/*
** 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 = 0;
- if( !db || db->mallocFailed==0 ){
- p = sqlite3Malloc(n);
- if( !p && db ){
- db->mallocFailed = 1;
- }
+ void *p;
+#ifndef SQLITE_OMIT_LOOKASIDE
+ if( db ){
+ LookasideSlot *pBuf;
+ if( db->mallocFailed ){
+ return 0;
+ }
+ if( db->lookaside.bEnabled && n<=db->lookaside.sz
+ && (pBuf = db->lookaside.pFree)!=0 ){
+ db->lookaside.pFree = pBuf->pNext;
+ db->lookaside.nOut++;
+ if( db->lookaside.nOut>db->lookaside.mxOut ){
+ db->lookaside.mxOut = db->lookaside.nOut;
+ }
+ return (void*)pBuf;
+ }
+ }
+#else
+ if( db && db->mallocFailed ){
+ return 0;
+ }
+#endif
+ p = sqlite3Malloc(n);
+ if( !p && db ){
+ db->mallocFailed = 1;
}
return p;
}
/*
** Resize the block of memory pointed to by p to n bytes. If the
-** resize fails, set the mallocFailed flag inthe connection object.
+** resize fails, set the mallocFailed flag in the connection object.
*/
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
void *pNew = 0;
if( db->mallocFailed==0 ){
- pNew = sqlite3_realloc(p, n);
- if( !pNew ){
- db->mallocFailed = 1;
+ if( p==0 ){
+ return sqlite3DbMallocRaw(db, n);
+ }
+ if( isLookaside(db, p) ){
+ if( n<=db->lookaside.sz ){
+ return p;
+ }
+ pNew = sqlite3DbMallocRaw(db, n);
+ if( pNew ){
+ memcpy(pNew, p, db->lookaside.sz);
+ sqlite3DbFree(db, p);
+ }
+ }else{
+ pNew = sqlite3_realloc(p, n);
+ if( !pNew ){
+ db->mallocFailed = 1;
+ }
}
}
return pNew;
}
@@ -15130,9 +16219,9 @@
SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, int n){
void *pNew;
pNew = sqlite3DbRealloc(db, p, n);
if( !pNew ){
- sqlite3_free(p);
+ sqlite3DbFree(db, p);
}
return pNew;
}
@@ -15142,39 +16231,32 @@
** is because when memory debugging is turned on, these two functions are
** called via macros that record the current file and line number in the
** ThreadData structure.
*/
-SQLITE_PRIVATE char *sqlite3StrDup(const char *z){
+SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
char *zNew;
- int n;
- if( z==0 ) return 0;
+ size_t n;
+ if( z==0 ){
+ return 0;
+ }
n = strlen(z)+1;
- zNew = sqlite3Malloc(n);
- if( zNew ) memcpy(zNew, z, n);
- return zNew;
-}
-SQLITE_PRIVATE char *sqlite3StrNDup(const char *z, int n){
- char *zNew;
- if( z==0 ) return 0;
- zNew = sqlite3Malloc(n+1);
+ assert( (n&0x7fffffff)==n );
+ zNew = sqlite3DbMallocRaw(db, (int)n);
if( zNew ){
memcpy(zNew, z, n);
- zNew[n] = 0;
- }
- return zNew;
-}
-
-SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
- char *zNew = sqlite3StrDup(z);
- if( z && !zNew ){
- db->mallocFailed = 1;
}
return zNew;
}
SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, int n){
- char *zNew = sqlite3StrNDup(z, n);
- if( z && !zNew ){
- db->mallocFailed = 1;
+ char *zNew;
+ if( z==0 ){
+ return 0;
+ }
+ assert( (n&0x7fffffff)==n );
+ zNew = sqlite3DbMallocRaw(db, n+1);
+ if( zNew ){
+ memcpy(zNew, z, n);
+ zNew[n] = 0;
}
return zNew;
}
@@ -15189,9 +16271,9 @@
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
- sqlite3_free(*pz);
+ sqlite3DbFree(db, *pz);
*pz = z;
}
@@ -15213,9 +16295,9 @@
** mutex here. Otherwise the read (and possible write) of db->mallocFailed
** 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;
}
@@ -15230,9 +16312,9 @@
** completeness. They are very out-of-date but might be useful as
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
-** $Id: printf.c,v 1.92 2008/07/15 00:27:35 drh Exp $
+** $Id: printf.c,v 1.94 2008/08/22 14:08:36 drh Exp $
**
**************************************************************************
**
** The following modules is an enhanced replacement for the "printf" subroutines
@@ -15470,9 +16552,8 @@
LONGDOUBLE_TYPE realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
- etByte errorflag = 0; /* True if an error is encountered */
etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
#ifndef SQLITE_OMIT_FLOATING_POINT
int exp, e2; /* exponent of real numbers */
@@ -15494,9 +16575,8 @@
sqlite3StrAccumAppend(pAccum, bufpt, amt);
if( c==0 ) break;
}
if( (c=(*++fmt))==0 ){
- errorflag = 1;
sqlite3StrAccumAppend(pAccum, "%", 1);
break;
}
/* Find out what flags are present */
@@ -15970,9 +17050,9 @@
return;
}else{
p->nAlloc = szNew;
}
- zNew = sqlite3Malloc( p->nAlloc );
+ zNew = sqlite3DbMallocRaw(p->db, p->nAlloc );
if( zNew ){
memcpy(zNew, p->zText, p->nChar);
sqlite3StrAccumReset(p);
p->zText = zNew;
@@ -15995,9 +17075,9 @@
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
p->zText[p->nChar] = 0;
if( p->useMalloc && p->zText==p->zBase ){
- p->zText = sqlite3Malloc( p->nChar+1 );
+ p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
p->mallocFailed = 1;
@@ -16011,9 +17091,9 @@
** Reset an StrAccum string. Reclaim all malloced memory.
*/
SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
if( p->zText!=p->zBase ){
- sqlite3_free(p->zText);
+ sqlite3DbFree(p->db, p->zText);
}
p->zText = 0;
}
@@ -16021,8 +17101,9 @@
** Initialize a string accumulator
*/
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
p->zText = p->zBase = zBase;
+ p->db = 0;
p->nChar = 0;
p->nAlloc = n;
p->mxAlloc = mx;
p->useMalloc = 1;
@@ -16039,8 +17120,9 @@
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
+ acc.db = db;
sqlite3VXPrintf(&acc, 1, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.mallocFailed && db ){
db->mallocFailed = 1;
@@ -16057,8 +17139,26 @@
char *z;
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
+ return z;
+}
+
+/*
+** Like sqlite3MPrintf(), but call sqlite3DbFree() on zStr after formatting
+** the string and before returnning. This routine is intended to be used
+** to modify an existing string. For example:
+**
+** x = sqlite3MPrintf(db, x, "prefix %s suffix", x);
+**
+*/
+SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zFormat, ...){
+ va_list ap;
+ char *z;
+ va_start(ap, zFormat);
+ z = sqlite3VMPrintf(db, zFormat, ap);
+ va_end(ap);
+ sqlite3DbFree(db, zStr);
return z;
}
/*
@@ -16156,20 +17256,20 @@
**
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
-** $Id: random.c,v 1.25 2008/06/19 01:03:18 drh Exp $
+** $Id: random.c,v 1.27 2008/10/07 15:25:48 drh Exp $
*/
/* 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
** must be held while executing this routine.
@@ -16189,8 +17289,22 @@
static int randomByte(void){
unsigned char t;
+ /* The "wsdPrng" macro will resolve to the pseudo-random number generator
+ ** state vector. If writable static data is unsupported on the target,
+ ** we have to locate the state vector at run-time. In the more common
+ ** case where writable static data is supported, wsdPrng can refer directly
+ ** to the "sqlite3Prng" state vector declared above.
+ */
+#ifdef SQLITE_OMIT_WSD
+ struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
+# define wsdPrng p[0]
+#else
+# define wsdPrng sqlite3Prng
+#endif
+
+
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
** trying to do secure encryption or anything like that...
@@ -16198,43 +17312,43 @@
** Nothing in this file or anywhere else in SQLite does any kind of
** 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;
- }
- sqlite3Prng.isInit = 1;
+ wsdPrng.j += wsdPrng.s[i] + k[i];
+ t = wsdPrng.s[wsdPrng.j];
+ wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
+ wsdPrng.s[i] = t;
+ }
+ 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];
}
/*
** Return N random bytes.
*/
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);
while( N-- ){
@@ -16245,21 +17359,32 @@
#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 */
/************** End of random.c **********************************************/
@@ -16277,9 +17402,9 @@
*************************************************************************
** This file contains routines used to translate between UTF-8,
** UTF-16, UTF-16BE, and UTF-16LE.
**
-** $Id: utf.c,v 1.62 2008/06/27 18:59:45 mihailim Exp $
+** $Id: utf.c,v 1.65 2008/08/12 15:04:59 danielk1977 Exp $
**
** Notes on UTF-8:
**
** Byte-0 Byte-1 Byte-2 Byte-3 Value
@@ -16319,9 +17444,9 @@
** source code file "vdbe.c". When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
**
-** $Id: vdbeInt.h,v 1.149 2008/06/25 00:12:41 drh Exp $
+** $Id: vdbeInt.h,v 1.155 2008/10/07 23:46:38 drh Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_
@@ -16375,15 +17500,13 @@
Bool ephemPseudoTable;
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
- u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
Btree *pBt; /* Separate file holding temporary table */
int nData; /* Number of bytes in pData */
char *pData; /* Data for a NEW or OLD pseudo-table */
i64 iKey; /* Key for the NEW or OLD pseudo-table row */
- u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int nField; /* Number of fields in the header */
i64 seqCount; /* Sequence counter */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
@@ -16549,8 +17672,9 @@
*/
typedef struct Fifo Fifo;
struct Fifo {
int nEntry; /* Total number of entries */
+ sqlite3 *db; /* The associated database connection */
FifoPage *pFirst; /* First page on the list */
FifoPage *pLast; /* Last page on the list */
};
@@ -16621,20 +17745,20 @@
char *zErrMsg; /* Error message written here */
Mem *pResultSet; /* Pointer to an array of results */
u8 explain; /* True if EXPLAIN present on SQL command */
u8 changeCntOn; /* True to update the change-counter */
- u8 aborted; /* True if ROLLBACK in another VM causes an abort */
u8 expired; /* True if the VM needs to be recompiled */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 inVtabMethod; /* See comments above */
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
int fetchId; /* Statement number used by sqlite3_fetch_statement */
@@ -16643,30 +17767,8 @@
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
Vdbe *pLruPrev;
Vdbe *pLruNext;
#endif
-};
-
-/*
-** An instance of the following structure holds information about a
-** single index record that has already been parsed out into individual
-** values.
-**
-** A record is an object that contains one or more fields of data.
-** Records are used to store the content of a table row and to store
-** the key of an index. A blob encoding of a record is created by
-** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
-** OP_Column opcode.
-**
-** This structure holds a record that has already been disassembled
-** into its constitutent fields.
-*/
-struct UnpackedRecord {
- KeyInfo *pKeyInfo; /* Collation and sort-order information */
- u16 nField; /* Number of entries in apMem[] */
- u8 needFree; /* True if memory obtained from sqlite3_malloc() */
- u8 needDestroy; /* True if apMem[]s should be destroyed on close */
- Mem *aMem; /* Values */
};
/*
** The following are allowed values for Vdbe.magic
@@ -16691,12 +17793,11 @@
SQLITE_PRIVATE int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
-SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*);
+SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord*,int*);
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
-SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
@@ -16710,9 +17811,8 @@
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
-SQLITE_PRIVATE int sqlite3VdbeMemDynamicify(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int);
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
@@ -16738,9 +17838,9 @@
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
#endif
SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
-SQLITE_PRIVATE void sqlite3VdbeFifoInit(Fifo*);
+SQLITE_PRIVATE void sqlite3VdbeFifoInit(Fifo*, sqlite3*);
SQLITE_PRIVATE int sqlite3VdbeFifoPush(Fifo*, i64);
SQLITE_PRIVATE int sqlite3VdbeFifoPop(Fifo*, i64*);
SQLITE_PRIVATE void sqlite3VdbeFifoClear(Fifo*);
@@ -16869,26 +17969,30 @@
** * This routine accepts an infinite number of different UTF8 encodings
** for unicode values 0x80 and greater. It do not change over-length
** encodings to 0xfffd as some systems recommend.
*/
+#define READ_UTF8(zIn, zTerm, c) \
+ c = *(zIn++); \
+ if( c>=0xc0 ){ \
+ c = sqlite3UtfTrans1[c-0xc0]; \
+ while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
+ c = (c<<6) + (0x3f & *(zIn++)); \
+ } \
+ if( c<0x80 \
+ || (c&0xFFFFF800)==0xD800 \
+ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
+ }
SQLITE_PRIVATE int sqlite3Utf8Read(
const unsigned char *z, /* First byte of UTF-8 character */
const unsigned char *zTerm, /* Pretend this byte is 0x00 */
const unsigned char **pzNext /* Write first byte past UTF-8 char here */
){
- int c = *(z++);
- if( c>=0xc0 ){
- c = sqlite3UtfTrans1[c-0xc0];
- while( z!=zTerm && (*z & 0xc0)==0x80 ){
- c = (c<<6) + (0x3f & *(z++));
- }
- if( c<0x80
- || (c&0xFFFFF800)==0xD800
- || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
- }
+ int c;
+ READ_UTF8(z, zTerm, c);
*pzNext = z;
return c;
}
+
/*
@@ -16983,16 +18087,18 @@
if( pMem->enc==SQLITE_UTF8 ){
if( desiredEnc==SQLITE_UTF16LE ){
/* UTF-8 -> UTF-16 Little-endian */
while( zIn<zTerm ){
- c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn);
+ /* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */
+ READ_UTF8(zIn, zTerm, c);
WRITE_UTF16LE(z, c);
}
}else{
assert( desiredEnc==SQLITE_UTF16BE );
/* UTF-8 -> UTF-16 Big-endian */
while( zIn<zTerm ){
- c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn);
+ /* c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn); */
+ READ_UTF8(zIn, zTerm, c);
WRITE_UTF16BE(z, c);
}
}
pMem->n = z - zOut;
@@ -17113,9 +18219,9 @@
*/
SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
unsigned char *zOut = zIn;
unsigned char *zStart = zIn;
- unsigned char *zTerm;
+ unsigned char *zTerm = &zIn[strlen((char *)zIn)];
u32 c;
while( zIn[0] ){
c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn);
@@ -17190,9 +18296,9 @@
** This routine is called from the TCL test function "translate_selftest".
** It checks that the primitives for serializing and deserializing
** characters in each encoding are inverses of each other.
*/
-SQLITE_PRIVATE void sqlite3UtfSelfTest(){
+SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
unsigned int i, t;
unsigned char zBuf[20];
unsigned char *z;
unsigned char *zTerm;
@@ -17256,14 +18362,14 @@
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.238 2008/07/11 16:19:10 drh Exp $
-*/
-
-
-/*
-** Return true if the floating point value is Not a Number.
+** $Id: util.c,v 1.241 2008/07/28 19:34:54 drh Exp $
+*/
+
+
+/*
+** Return true if the floating point value is Not a Number (NaN).
*/
SQLITE_PRIVATE int sqlite3IsNaN(double x){
/* This NaN test sometimes fails if compiled on GCC with -ffast-math.
** On the other hand, the use of -ffast-math comes with the following
@@ -17272,8 +18378,16 @@
** This option [-ffast-math] should never be turned on by any
** -O option since it can result in incorrect output for programs
** which depend on an exact implementation of IEEE or ISO
** rules/specifications for math functions.
+ **
+ ** Under MSVC, this NaN test may fail if compiled with a floating-
+ ** point precision mode other than /fp:precise. From the MSDN
+ ** documentation:
+ **
+ ** The compiler [with /fp:precise] will properly handle comparisons
+ ** involving NaN. For example, x != x evaluates to true if x is NaN
+ ** ...
*/
#ifdef __FAST_MATH__
# error SQLite will not work correctly with the -ffast-math option of GCC.
#endif
@@ -17287,13 +18401,17 @@
** to exceed the SQLITE_LIMIT_LENGTH setting.
*/
SQLITE_PRIVATE int sqlite3Strlen(sqlite3 *db, const char *z){
const char *z2 = z;
+ int len;
+ size_t x;
while( *z2 ){ z2++; }
- if( z2 > &z[db->aLimit[SQLITE_LIMIT_LENGTH]] ){
+ x = z2 - z;
+ len = 0x7fffffff & x;
+ if( len!=x || len > db->aLimit[SQLITE_LIMIT_LENGTH] ){
return db->aLimit[SQLITE_LIMIT_LENGTH];
}else{
- return (int)(z2 - z);
+ return len;
}
}
/*
@@ -17325,9 +18443,9 @@
va_list ap;
va_start(ap, zFormat);
z = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
- sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, sqlite3_free);
+ sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
}else{
sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
}
}
@@ -17351,12 +18469,13 @@
** (sqlite3_step() etc.).
*/
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
va_list ap;
+ sqlite3 *db = pParse->db;
pParse->nErr++;
- sqlite3_free(pParse->zErrMsg);
+ sqlite3DbFree(db, pParse->zErrMsg);
va_start(ap, zFormat);
- pParse->zErrMsg = sqlite3VMPrintf(pParse->db, zFormat, ap);
+ pParse->zErrMsg = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
if( pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
}
@@ -17365,9 +18484,9 @@
/*
** Clear the error message in pParse, if any
*/
SQLITE_PRIVATE void sqlite3ErrorClear(Parse *pParse){
- sqlite3_free(pParse->zErrMsg);
+ sqlite3DbFree(pParse->db, pParse->zErrMsg);
pParse->zErrMsg = 0;
pParse->nErr = 0;
}
@@ -18193,31 +19312,21 @@
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
**
-** $Id: hash.c,v 1.30 2008/06/20 14:59:51 danielk1977 Exp $
+** $Id: hash.c,v 1.31 2008/10/10 17:41:29 drh Exp $
*/
/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
-** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
-** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass
-** determines what kind of key the hash table will use. "copyKey" is
-** true if the hash table should make its own private copy of keys and
-** false if it should just use the supplied pointer. CopyKey only makes
-** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
-** for other key classes.
-*/
-SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
+** "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 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;
pNew->ht = 0;
@@ -18246,35 +19355,8 @@
}
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
*/
static int strHash(const void *pKey, int nKey){
@@ -18291,81 +19373,8 @@
if( n1!=n2 ) return 1;
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 insertElement(
@@ -18398,9 +19407,8 @@
*/
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 ){
new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
@@ -18420,11 +19428,10 @@
if( new_ht==0 ) return;
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);
}
}
@@ -18440,17 +19447,15 @@
int h /* The hash for this key. */
){
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;
}
@@ -18502,14 +19507,11 @@
*/
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;
}
@@ -18542,14 +19544,11 @@
int hraw; /* Raw hash value of the key */
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);
if( elem ){
@@ -18608,72 +19607,72 @@
/* See the mkopcodec.awk script for details. */
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
static const char *const azName[] = { "?",
- /* 1 */ "VNext",
- /* 2 */ "Affinity",
- /* 3 */ "Column",
- /* 4 */ "SetCookie",
- /* 5 */ "Sequence",
- /* 6 */ "MoveGt",
- /* 7 */ "RowKey",
- /* 8 */ "SCopy",
- /* 9 */ "OpenWrite",
- /* 10 */ "If",
- /* 11 */ "VRowid",
- /* 12 */ "CollSeq",
- /* 13 */ "OpenRead",
- /* 14 */ "Expire",
- /* 15 */ "AutoCommit",
+ /* 1 */ "ReadCookie",
+ /* 2 */ "AutoCommit",
+ /* 3 */ "Found",
+ /* 4 */ "NullRow",
+ /* 5 */ "MoveLe",
+ /* 6 */ "Variable",
+ /* 7 */ "RealAffinity",
+ /* 8 */ "Sort",
+ /* 9 */ "Affinity",
+ /* 10 */ "IfNot",
+ /* 11 */ "Gosub",
+ /* 12 */ "NotFound",
+ /* 13 */ "ResultRow",
+ /* 14 */ "MoveLt",
+ /* 15 */ "Rowid",
/* 16 */ "Not",
- /* 17 */ "Pagecount",
- /* 18 */ "IntegrityCk",
- /* 19 */ "Sort",
- /* 20 */ "Copy",
- /* 21 */ "Trace",
- /* 22 */ "Function",
- /* 23 */ "IfNeg",
- /* 24 */ "Noop",
- /* 25 */ "Return",
- /* 26 */ "NewRowid",
- /* 27 */ "Variable",
- /* 28 */ "String",
- /* 29 */ "RealAffinity",
- /* 30 */ "VRename",
- /* 31 */ "ParseSchema",
- /* 32 */ "VOpen",
- /* 33 */ "Close",
- /* 34 */ "CreateIndex",
- /* 35 */ "IsUnique",
- /* 36 */ "NotFound",
- /* 37 */ "Int64",
- /* 38 */ "MustBeInt",
- /* 39 */ "Halt",
- /* 40 */ "Rowid",
- /* 41 */ "IdxLT",
- /* 42 */ "AddImm",
- /* 43 */ "Statement",
- /* 44 */ "RowData",
- /* 45 */ "MemMax",
- /* 46 */ "NotExists",
- /* 47 */ "Gosub",
- /* 48 */ "Integer",
- /* 49 */ "Prev",
- /* 50 */ "VColumn",
- /* 51 */ "CreateTable",
- /* 52 */ "Last",
- /* 53 */ "IncrVacuum",
- /* 54 */ "IdxRowid",
- /* 55 */ "ResetCount",
- /* 56 */ "FifoWrite",
- /* 57 */ "ContextPush",
- /* 58 */ "Yield",
- /* 59 */ "DropTrigger",
+ /* 17 */ "CreateIndex",
+ /* 18 */ "Explain",
+ /* 19 */ "Statement",
+ /* 20 */ "DropIndex",
+ /* 21 */ "Null",
+ /* 22 */ "Int64",
+ /* 23 */ "LoadAnalysis",
+ /* 24 */ "IdxInsert",
+ /* 25 */ "VUpdate",
+ /* 26 */ "Next",
+ /* 27 */ "SetNumColumns",
+ /* 28 */ "Rewind",
+ /* 29 */ "Last",
+ /* 30 */ "MustBeInt",
+ /* 31 */ "MoveGe",
+ /* 32 */ "IncrVacuum",
+ /* 33 */ "String",
+ /* 34 */ "VFilter",
+ /* 35 */ "ForceInt",
+ /* 36 */ "Close",
+ /* 37 */ "AggFinal",
+ /* 38 */ "RowData",
+ /* 39 */ "IdxRowid",
+ /* 40 */ "Pagecount",
+ /* 41 */ "MoveGt",
+ /* 42 */ "OpenPseudo",
+ /* 43 */ "Halt",
+ /* 44 */ "Compare",
+ /* 45 */ "NewRowid",
+ /* 46 */ "IdxLT",
+ /* 47 */ "MemMax",
+ /* 48 */ "Function",
+ /* 49 */ "IntegrityCk",
+ /* 50 */ "SCopy",
+ /* 51 */ "IfNeg",
+ /* 52 */ "FifoWrite",
+ /* 53 */ "NotExists",
+ /* 54 */ "VDestroy",
+ /* 55 */ "IdxDelete",
+ /* 56 */ "Vacuum",
+ /* 57 */ "Copy",
+ /* 58 */ "If",
+ /* 59 */ "Jump",
/* 60 */ "Or",
/* 61 */ "And",
- /* 62 */ "DropIndex",
- /* 63 */ "IdxGE",
- /* 64 */ "IdxDelete",
+ /* 62 */ "Destroy",
+ /* 63 */ "AggStep",
+ /* 64 */ "Insert",
/* 65 */ "IsNull",
/* 66 */ "NotNull",
/* 67 */ "Ne",
/* 68 */ "Eq",
@@ -18680,9 +19679,9 @@
/* 69 */ "Gt",
/* 70 */ "Le",
/* 71 */ "Lt",
/* 72 */ "Ge",
- /* 73 */ "Vacuum",
+ /* 73 */ "Clear",
/* 74 */ "BitAnd",
/* 75 */ "BitOr",
/* 76 */ "ShiftLeft",
/* 77 */ "ShiftRight",
@@ -18691,67 +19690,68 @@
/* 80 */ "Multiply",
/* 81 */ "Divide",
/* 82 */ "Remainder",
/* 83 */ "Concat",
- /* 84 */ "MoveLe",
- /* 85 */ "IfNot",
- /* 86 */ "DropTable",
+ /* 84 */ "Permutation",
+ /* 85 */ "VBegin",
+ /* 86 */ "OpenEphemeral",
/* 87 */ "BitNot",
/* 88 */ "String8",
- /* 89 */ "MakeRecord",
- /* 90 */ "ResultRow",
- /* 91 */ "Delete",
- /* 92 */ "AggFinal",
- /* 93 */ "Compare",
- /* 94 */ "Goto",
- /* 95 */ "TableLock",
- /* 96 */ "FifoRead",
- /* 97 */ "Clear",
- /* 98 */ "MoveLt",
- /* 99 */ "VerifyCookie",
- /* 100 */ "AggStep",
- /* 101 */ "SetNumColumns",
+ /* 89 */ "IdxGE",
+ /* 90 */ "Trace",
+ /* 91 */ "VRowid",
+ /* 92 */ "MakeRecord",
+ /* 93 */ "Yield",
+ /* 94 */ "SetCookie",
+ /* 95 */ "Prev",
+ /* 96 */ "ContextPush",
+ /* 97 */ "DropTrigger",
+ /* 98 */ "VColumn",
+ /* 99 */ "Return",
+ /* 100 */ "OpenWrite",
+ /* 101 */ "Integer",
/* 102 */ "Transaction",
- /* 103 */ "VFilter",
- /* 104 */ "VDestroy",
- /* 105 */ "ContextPop",
- /* 106 */ "Next",
- /* 107 */ "IdxInsert",
- /* 108 */ "Insert",
- /* 109 */ "Destroy",
- /* 110 */ "ReadCookie",
- /* 111 */ "ForceInt",
- /* 112 */ "LoadAnalysis",
- /* 113 */ "Explain",
- /* 114 */ "OpenPseudo",
- /* 115 */ "OpenEphemeral",
- /* 116 */ "Null",
- /* 117 */ "Move",
- /* 118 */ "Blob",
- /* 119 */ "Rewind",
- /* 120 */ "MoveGe",
- /* 121 */ "VBegin",
- /* 122 */ "VUpdate",
- /* 123 */ "IfZero",
- /* 124 */ "VCreate",
- /* 125 */ "Real",
- /* 126 */ "Found",
- /* 127 */ "IfPos",
- /* 128 */ "NullRow",
- /* 129 */ "Jump",
- /* 130 */ "Permutation",
+ /* 103 */ "IfPos",
+ /* 104 */ "CollSeq",
+ /* 105 */ "VRename",
+ /* 106 */ "Sequence",
+ /* 107 */ "ContextPop",
+ /* 108 */ "VCreate",
+ /* 109 */ "CreateTable",
+ /* 110 */ "AddImm",
+ /* 111 */ "DropTable",
+ /* 112 */ "IsUnique",
+ /* 113 */ "VOpen",
+ /* 114 */ "IfZero",
+ /* 115 */ "Noop",
+ /* 116 */ "RowKey",
+ /* 117 */ "Expire",
+ /* 118 */ "FifoRead",
+ /* 119 */ "Delete",
+ /* 120 */ "Blob",
+ /* 121 */ "Move",
+ /* 122 */ "Goto",
+ /* 123 */ "ParseSchema",
+ /* 124 */ "VNext",
+ /* 125 */ "TableLock",
+ /* 126 */ "Real",
+ /* 127 */ "VerifyCookie",
+ /* 128 */ "Column",
+ /* 129 */ "OpenRead",
+ /* 130 */ "ResetCount",
/* 131 */ "NotUsed_131",
/* 132 */ "NotUsed_132",
/* 133 */ "NotUsed_133",
/* 134 */ "NotUsed_134",
/* 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];
}
#endif
@@ -18771,9 +19771,9 @@
******************************************************************************
**
** This file contains code that is specific to OS/2.
**
-** $Id: os_os2.c,v 1.49 2008/07/08 22:34:07 pweilbacher Exp $
+** $Id: os_os2.c,v 1.57 2008/10/13 21:46:47 pweilbacher Exp $
*/
#if SQLITE_OS_OS2
@@ -18905,9 +19905,9 @@
**
** This file contains inline asm code for retrieving "high-performance"
** counters for x86 class CPUs.
**
-** $Id: hwtime.h,v 1.2 2008/06/12 02:24:39 shane Exp $
+** $Id: hwtime.h,v 1.3 2008/08/01 14:33:15 shane Exp $
*/
#ifndef _HWTIME_H_
#define _HWTIME_H_
@@ -18944,8 +19944,23 @@
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
+ }
+
+#elif (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
}
#else
@@ -19146,9 +20161,9 @@
os2File *pFile = (os2File*)id;
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
/*
@@ -19181,15 +20196,15 @@
APIRET rc = NO_ERROR;
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;
}
}
/*
@@ -19522,34 +20537,59 @@
static int os2DeviceCharacteristics(sqlite3_file *id){
return 0;
}
+
+/*
+** Character set conversion objects used by conversion routines.
+*/
+static UconvObject ucUtf8 = NULL; /* convert between UTF-8 and UCS-2 */
+static UconvObject uclCp = NULL; /* convert between local codepage and UCS-2 */
+
+/*
+** Helper function to initialize the conversion objects from and to UTF-8.
+*/
+static void initUconvObjects( void ){
+ if( UniCreateUconvObject( UTF_8, &ucUtf8 ) != ULS_SUCCESS )
+ ucUtf8 = NULL;
+ if ( UniCreateUconvObject( (UniChar *)L"@path=yes", &uclCp ) != ULS_SUCCESS )
+ uclCp = NULL;
+}
+
+/*
+** Helper function to free the conversion objects from and to UTF-8.
+*/
+static void freeUconvObjects( void ){
+ if ( ucUtf8 )
+ UniFreeUconvObject( ucUtf8 );
+ if ( uclCp )
+ UniFreeUconvObject( uclCp );
+ ucUtf8 = NULL;
+ uclCp = NULL;
+}
+
/*
** Helper function to convert UTF-8 filenames to local OS/2 codepage.
** The two-step process: first convert the incoming UTF-8 string
** into UCS-2 and then from UCS-2 to the current codepage.
** The returned char pointer has to be freed.
*/
-static char *convertUtf8PathToCp(const char *in)
-{
- UconvObject uconv;
- UniChar ucsUtf8Cp[12],
- tempPath[CCHMAXPATH];
- char *out;
- int rc = 0;
-
- out = (char *)calloc(CCHMAXPATH, 1);
+static char *convertUtf8PathToCp( const char *in ){
+ UniChar tempPath[CCHMAXPATH];
+ char *out = (char *)calloc( CCHMAXPATH, 1 );
+
+ if( !out )
+ return NULL;
+
+ if( !ucUtf8 || !uclCp )
+ initUconvObjects();
/* determine string for the conversion of UTF-8 which is CP1208 */
- rc = UniMapCpToUcsCp(1208, ucsUtf8Cp, 12);
- rc = UniCreateUconvObject(ucsUtf8Cp, &uconv);
- rc = UniStrToUcs(uconv, tempPath, (char *)in, CCHMAXPATH);
- rc = UniFreeUconvObject(uconv);
+ if( UniStrToUcs( ucUtf8, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS )
+ return out; /* if conversion fails, return the empty string */
/* conversion for current codepage which can be used for paths */
- rc = UniCreateUconvObject((UniChar *)L"@path=yes", &uconv);
- rc = UniStrFromUcs(uconv, out, tempPath, CCHMAXPATH);
- rc = UniFreeUconvObject(uconv);
+ UniStrFromUcs( uclCp, out, tempPath, CCHMAXPATH );
return out;
}
@@ -19557,29 +20597,28 @@
** Helper function to convert filenames from local codepage to UTF-8.
** The two-step process: first convert the incoming codepage-specific
** string into UCS-2 and then from UCS-2 to the codepage of UTF-8.
** The returned char pointer has to be freed.
-*/
-static char *convertCpPathToUtf8(const char *in)
-{
- UconvObject uconv;
- UniChar ucsUtf8Cp[12],
- tempPath[CCHMAXPATH];
- char *out;
- int rc = 0;
-
- out = (char *)calloc(CCHMAXPATH, 1);
+**
+** This function is non-static to be able to use this in shell.c and
+** similar applications that take command line arguments.
+*/
+char *convertCpPathToUtf8( const char *in ){
+ UniChar tempPath[CCHMAXPATH];
+ char *out = (char *)calloc( CCHMAXPATH, 1 );
+
+ if( !out )
+ return NULL;
+
+ if( !ucUtf8 || !uclCp )
+ initUconvObjects();
/* conversion for current codepage which can be used for paths */
- rc = UniCreateUconvObject((UniChar *)L"@path=yes", &uconv);
- rc = UniStrToUcs(uconv, tempPath, (char *)in, CCHMAXPATH);
- rc = UniFreeUconvObject(uconv);
+ if( UniStrToUcs( uclCp, tempPath, (char *)in, CCHMAXPATH ) != ULS_SUCCESS )
+ return out; /* if conversion fails, return the empty string */
/* determine string for the conversion of UTF-8 which is CP1208 */
- rc = UniMapCpToUcsCp(1208, ucsUtf8Cp, 12);
- rc = UniCreateUconvObject(ucsUtf8Cp, &uconv);
- rc = UniStrFromUcs(uconv, out, tempPath, CCHMAXPATH);
- rc = UniFreeUconvObject(uconv);
+ UniStrFromUcs( ucUtf8, out, tempPath, CCHMAXPATH );
return out;
}
@@ -19626,11 +20665,11 @@
}else{
if( DosScanEnv( (PSZ)"TEMP", &zTempPath ) ){
if( DosScanEnv( (PSZ)"TMP", &zTempPath ) ){
if( DosScanEnv( (PSZ)"TMPDIR", &zTempPath ) ){
- ULONG ulDriveNum = 0, ulDriveMap = 0;
- DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
- sprintf( (char*)zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) );
+ ULONG ulDriveNum = 0, ulDriveMap = 0;
+ DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap );
+ sprintf( (char*)zTempPath, "%c:", (char)( 'A' + ulDriveNum - 1 ) );
}
}
}
}
@@ -19663,8 +20702,32 @@
}
/*
+** Turn a relative pathname into a full pathname. Write the full
+** pathname into zFull[]. zFull[] will be at least pVfs->mxPathname
+** bytes in size.
+*/
+static int os2FullPathname(
+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
+ const char *zRelative, /* Possibly relative input path */
+ int nFull, /* Size of output buffer in bytes */
+ char *zFull /* Output buffer */
+){
+ char *zRelativeCp = convertUtf8PathToCp( zRelative );
+ char zFullCp[CCHMAXPATH] = "\0";
+ char *zFullUTF;
+ APIRET rc = DosQueryPathInfo( zRelativeCp, FIL_QUERYFULLNAME, zFullCp,
+ CCHMAXPATH );
+ free( zRelativeCp );
+ zFullUTF = convertCpPathToUtf8( zFullCp );
+ sqlite3_snprintf( nFull, zFull, zFullUTF );
+ free( zFullUTF );
+ return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
+}
+
+
+/*
** Open a file.
*/
static int os2Open(
sqlite3_vfs *pVfs, /* Not used */
@@ -19673,9 +20736,9 @@
int flags, /* Open mode flags */
int *pOutFlags /* Status return flags */
){
HFILE h;
- ULONG ulFileAttribute = 0;
+ ULONG ulFileAttribute = FILE_NORMAL;
ULONG ulOpenFlags = 0;
ULONG ulOpenMode = 0;
os2File *pFile = (os2File*)id;
APIRET rc = NO_ERROR;
@@ -19698,9 +20761,8 @@
memset( pFile, 0, sizeof(*pFile) );
OSTRACE2( "OPEN want %d\n", flags );
- /*ulOpenMode = flags & SQLITE_OPEN_READWRITE ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY;*/
if( flags & SQLITE_OPEN_READWRITE ){
ulOpenMode |= OPEN_ACCESS_READWRITE;
OSTRACE1( "OPEN read/write\n" );
}else{
@@ -19707,9 +20769,8 @@
ulOpenMode |= OPEN_ACCESS_READONLY;
OSTRACE1( "OPEN read only\n" );
}
- /*ulOpenFlags = flags & SQLITE_OPEN_CREATE ? OPEN_ACTION_CREATE_IF_NEW : OPEN_ACTION_FAIL_IF_NEW;*/
if( flags & SQLITE_OPEN_CREATE ){
ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
OSTRACE1( "OPEN open new/create\n" );
}else{
@@ -19716,9 +20777,8 @@
ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
OSTRACE1( "OPEN open existing\n" );
}
- /*ulOpenMode |= flags & SQLITE_OPEN_MAIN_DB ? OPEN_SHARE_DENYNONE : OPEN_SHARE_DENYWRITE;*/
if( flags & SQLITE_OPEN_MAIN_DB ){
ulOpenMode |= OPEN_SHARE_DENYNONE;
OSTRACE1( "OPEN share read/write\n" );
}else{
@@ -19725,18 +20785,17 @@
ulOpenMode |= OPEN_SHARE_DENYWRITE;
OSTRACE1( "OPEN share read only\n" );
}
- if( flags & (SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TEMP_JOURNAL
- | SQLITE_OPEN_SUBJOURNAL) ){
+ if( flags & SQLITE_OPEN_DELETEONCLOSE ){
char pathUtf8[CCHMAXPATH];
- /*ulFileAttribute = FILE_HIDDEN; //for debugging, we want to make sure it is deleted*/
- ulFileAttribute = FILE_NORMAL;
- sqlite3OsFullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
+#ifdef NDEBUG /* when debugging we want to make sure it is deleted */
+ ulFileAttribute = FILE_HIDDEN;
+#endif
+ os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
OSTRACE1( "OPEN hidden/delete on close file attributes\n" );
}else{
- ulFileAttribute = FILE_ARCHIVED | FILE_NORMAL;
pFile->pathToDel = NULL;
OSTRACE1( "OPEN normal file attribute\n" );
}
@@ -19762,9 +20821,9 @@
free( pFile->pathToDel );
pFile->pathToDel = NULL;
if( flags & SQLITE_OPEN_READWRITE ){
OSTRACE2( "OPEN %d Invalid handle\n", ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) );
- return os2Open( 0, zName, id,
+ return os2Open( pVfs, zName, id,
((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE),
pOutFlags );
}else{
return SQLITE_CANTOPEN;
@@ -19795,9 +20854,9 @@
SimulateIOError( return SQLITE_IOERR_DELETE );
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;
}
/*
** Check the existance and status of a file.
@@ -19834,31 +20893,8 @@
*pOut = rc;
return SQLITE_OK;
}
-
-/*
-** Turn a relative pathname into a full pathname. Write the full
-** pathname into zFull[]. zFull[] will be at least pVfs->mxPathname
-** bytes in size.
-*/
-static int os2FullPathname(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- const char *zRelative, /* Possibly relative input path */
- int nFull, /* Size of output buffer in bytes */
- char *zFull /* Output buffer */
-){
- char *zRelativeCp = convertUtf8PathToCp( zRelative );
- char zFullCp[CCHMAXPATH];
- char *zFullUTF;
- APIRET rc = DosQueryPathInfo( zRelativeCp, FIL_QUERYFULLNAME, zFullCp,
- CCHMAXPATH );
- free( zRelativeCp );
- zFullUTF = convertCpPathToUtf8( zFullCp );
- sqlite3_snprintf( nFull, zFull, zFullUTF );
- free( zFullUTF );
- return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
-}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
@@ -20056,11 +21092,13 @@
os2CurrentTime, /* xCurrentTime */
os2GetLastError /* xGetLastError */
};
sqlite3_vfs_register(&os2Vfs, 1);
+ initUconvObjects();
return SQLITE_OK;
}
SQLITE_API int sqlite3_os_end(void){
+ freeUconvObjects();
return SQLITE_OK;
}
#endif /* SQLITE_OS_OS2 */
@@ -20080,23 +21118,32 @@
******************************************************************************
**
** This file contains code that is specific to Unix systems.
**
-** $Id: os_unix.c,v 1.193 2008/07/10 00:32:42 drh Exp $
+** $Id: os_unix.c,v 1.207 2008/10/16 13:27:41 danielk1977 Exp $
*/
#if SQLITE_OS_UNIX /* This file is used on unix only */
/*
-** If SQLITE_ENABLE_LOCKING_STYLE is defined, then several different
-** locking implementations are provided:
+** If SQLITE_ENABLE_LOCKING_STYLE is defined and is non-zero, then several
+** alternative locking implementations are provided:
**
** * POSIX locking (the default),
** * No locking,
** * Dot-file locking,
** * flock() locking,
** * AFP locking (OSX only).
-*/
-/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */
+**
+** SQLITE_ENABLE_LOCKING_STYLE only works on a Mac. It is turned on by
+** default on a Mac and disabled on all other posix platforms.
+*/
+#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
+# if defined(__DARWIN__)
+# define SQLITE_ENABLE_LOCKING_STYLE 1
+# else
+# define SQLITE_ENABLE_LOCKING_STYLE 0
+# endif
+#endif
/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it. If the OS lacks
@@ -20127,9 +21174,9 @@
#include <unistd.h>
#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 /* SQLITE_ENABLE_LOCKING_STYLE */
@@ -20169,9 +21216,9 @@
char aPadding[32];
#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 */
unsigned char locktype; /* The type of lock held on this fd */
@@ -20178,8 +21225,9 @@
int dirfd; /* File descriptor for the directory */
#if SQLITE_THREADSAFE
pthread_t tid; /* The thread that "owns" this unixFile */
#endif
+ int lastErrno; /* The unix errno from the last I/O error */
};
/*
** Include code that is common to all os_*.c files
@@ -20275,9 +21323,9 @@
**
** This file contains inline asm code for retrieving "high-performance"
** counters for x86 class CPUs.
**
-** $Id: hwtime.h,v 1.2 2008/06/12 02:24:39 shane Exp $
+** $Id: hwtime.h,v 1.3 2008/08/01 14:33:15 shane Exp $
*/
#ifndef _HWTIME_H_
#define _HWTIME_H_
@@ -20314,8 +21362,23 @@
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
+ }
+
+#elif (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
}
#else
@@ -20593,8 +21656,9 @@
struct lockKey key; /* The lookup key */
int cnt; /* Number of SHARED locks held */
int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
int nRef; /* Number of pointers to this structure */
+ struct lockInfo *pNext, *pPrev; /* List of all lockInfo objects */
};
/*
** An instance of the following structure serves as the key used
@@ -20618,17 +21682,19 @@
int nRef; /* Number of pointers to this structure */
int nLock; /* Number of outstanding locks */
int nPending; /* Number of pending close() operations */
int *aPending; /* Malloced space holding fd's awaiting a close() */
-};
-
-/*
-** These hash tables map inodes and file descriptors (really, lockKey and
-** openKey structures) into lockInfo and openCnt structures. Access to
-** these hash tables must be protected by a mutex.
-*/
-static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0};
-static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0, 0, 0};
+ struct openCnt *pNext, *pPrev; /* List of all openCnt objects */
+};
+
+/*
+** List of all lockInfo and openCnt objects. This used to be a hash
+** table. But the number of objects is rarely more than a dozen and
+** never exceeds a few thousand. And lookup is not on a critical
+** path oo a simple linked list will suffice.
+*/
+static struct lockInfo *lockList = 0;
+static struct openCnt *openList = 0;
/*
** The locking styles are associated with the different file locking
** capabilities supported by different file systems.
@@ -20644,20 +21710,26 @@
** UNSUPPORTED means that no locking will be attempted, this is only used for
** file systems that are known to be unsupported
*/
#define LOCKING_STYLE_POSIX 1
-#define LOCKING_STYLE_FLOCK 2
+#define LOCKING_STYLE_NONE 2
#define LOCKING_STYLE_DOTFILE 3
-#define LOCKING_STYLE_NONE 4
+#define LOCKING_STYLE_FLOCK 4
#define LOCKING_STYLE_AFP 5
+
+/*
+** Only set the lastErrno if the error code is a real error and not
+** a normal expected return code of SQLITE_BUSY or SQLITE_OK
+*/
+#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
/*
** Helper functions to obtain and relinquish the global mutex.
*/
-static void enterMutex(){
+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));
}
#if SQLITE_THREADSAFE
@@ -20805,9 +21877,19 @@
static void releaseLockInfo(struct lockInfo *pLock){
if( pLock ){
pLock->nRef--;
if( pLock->nRef==0 ){
- sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0);
+ if( pLock->pPrev ){
+ assert( pLock->pPrev->pNext==pLock );
+ pLock->pPrev->pNext = pLock->pNext;
+ }else{
+ assert( lockList==pLock );
+ lockList = pLock->pNext;
+ }
+ if( pLock->pNext ){
+ assert( pLock->pNext->pPrev==pLock );
+ pLock->pNext->pPrev = pLock->pPrev;
+ }
sqlite3_free(pLock);
}
}
}
@@ -20818,16 +21900,26 @@
static void releaseOpenCnt(struct openCnt *pOpen){
if( pOpen ){
pOpen->nRef--;
if( pOpen->nRef==0 ){
- sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0);
- free(pOpen->aPending);
+ if( pOpen->pPrev ){
+ assert( pOpen->pPrev->pNext==pOpen );
+ pOpen->pPrev->pNext = pOpen->pNext;
+ }else{
+ assert( openList==pOpen );
+ openList = pOpen->pNext;
+ }
+ if( pOpen->pNext ){
+ assert( pOpen->pNext->pPrev==pOpen );
+ pOpen->pNext->pPrev = pOpen->pPrev;
+ }
+ sqlite3_free(pOpen->aPending);
sqlite3_free(pOpen);
}
}
}
-#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.
*/
@@ -20867,17 +21959,21 @@
sqlite3_vfs *pVfs,
const char *filePath,
int fd
){
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_ENABLE_LOCKING_STYLE
struct Mapping {
const char *zFilesystem;
int eLockingStyle;
} aMap[] = {
{ "hfs", LOCKING_STYLE_POSIX },
{ "ufs", LOCKING_STYLE_POSIX },
{ "afpfs", LOCKING_STYLE_AFP },
+#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
+ { "smbfs", LOCKING_STYLE_AFP },
+#else
{ "smbfs", LOCKING_STYLE_FLOCK },
+#endif
{ "msdos", LOCKING_STYLE_DOTFILE },
{ "webdav", LOCKING_STYLE_NONE },
{ 0, 0 }
};
@@ -20887,9 +21983,9 @@
if( !filePath ){
return LOCKING_STYLE_NONE;
}
if( pVfs->pAppData ){
- return (int)pVfs->pAppData;
+ return SQLITE_PTR_TO_INT(pVfs->pAppData);
}
if( statfs(filePath, &fsInfo) != -1 ){
if( fsInfo.f_flags & MNT_RDONLY ){
@@ -20933,8 +22029,26 @@
#endif
return SQLITE_IOERR;
}
+ /* On OS X on an msdos filesystem, the inode number is reported
+ ** incorrectly for zero-size files. See ticket #3260. To work
+ ** around this problem (we consider it a bug in OS X, not SQLite)
+ ** we always increase the file size to 1 by writing a single byte
+ ** prior to accessing the inode number. The one byte written is
+ ** an ASCII 'S' character which also happens to be the first byte
+ ** in the header of every SQLite database. In this way, if there
+ ** is a race condition such that another thread has already populated
+ ** the first page of the database, no damage is done.
+ */
+ if( statbuf.st_size==0 ){
+ write(fd, "S", 1);
+ rc = fstat(fd, &statbuf);
+ if( rc!=0 ){
+ return SQLITE_IOERR;
+ }
+ }
+
memset(&key1, 0, sizeof(key1));
key1.dev = statbuf.st_dev;
key1.ino = statbuf.st_ino;
#if SQLITE_THREADSAFE
@@ -20945,11 +22059,13 @@
#endif
memset(&key2, 0, sizeof(key2));
key2.dev = statbuf.st_dev;
key2.ino = statbuf.st_ino;
- pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1));
- if( pLock==0 ){
- struct lockInfo *pOld;
+ pLock = lockList;
+ while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){
+ pLock = pLock->pNext;
+ }
+ if( pLock==0 ){
pLock = sqlite3_malloc( sizeof(*pLock) );
if( pLock==0 ){
rc = SQLITE_NOMEM;
goto exit_findlockinfo;
@@ -20957,23 +22073,22 @@
pLock->key = key1;
pLock->nRef = 1;
pLock->cnt = 0;
pLock->locktype = 0;
- pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock);
- if( pOld!=0 ){
- assert( pOld==pLock );
- sqlite3_free(pLock);
- rc = SQLITE_NOMEM;
- goto exit_findlockinfo;
- }
+ pLock->pNext = lockList;
+ pLock->pPrev = 0;
+ if( lockList ) lockList->pPrev = pLock;
+ lockList = pLock;
}else{
pLock->nRef++;
}
*ppLock = pLock;
if( ppOpen!=0 ){
- pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2));
- if( pOpen==0 ){
- struct openCnt *pOld;
+ pOpen = openList;
+ while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){
+ pOpen = pOpen->pNext;
+ }
+ if( pOpen==0 ){
pOpen = sqlite3_malloc( sizeof(*pOpen) );
if( pOpen==0 ){
releaseLockInfo(pLock);
rc = SQLITE_NOMEM;
@@ -20983,16 +22098,12 @@
pOpen->nRef = 1;
pOpen->nLock = 0;
pOpen->nPending = 0;
pOpen->aPending = 0;
- pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen);
- if( pOld!=0 ){
- assert( pOld==pOpen );
- sqlite3_free(pOpen);
- releaseLockInfo(pLock);
- rc = SQLITE_NOMEM;
- goto exit_findlockinfo;
- }
+ pOpen->pNext = openList;
+ pOpen->pPrev = 0;
+ if( openList ) openList->pPrev = pOpen;
+ openList = pOpen;
}else{
pOpen->nRef++;
}
*ppOpen = pOpen;
@@ -21295,8 +22406,13 @@
assert((flags&0x0F)==SQLITE_SYNC_NORMAL
|| (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);
SimulateIOError( rc=1 );
@@ -21354,19 +22470,95 @@
if( rc!=0 ){
return SQLITE_IOERR_FSTAT;
}
*pSize = buf.st_size;
- return SQLITE_OK;
+
+ /* When opening a zero-size database, the findLockInfo() procedure
+ ** writes a single byte into that file in order to work around a bug
+ ** in the OS-X msdos filesystem. In order to avoid problems with upper
+ ** layers, we need to report this file size as zero even though it is
+ ** really 1. Ticket #3260.
+ */
+ if( *pSize==1 ) *pSize = 0;
+
+
+ return SQLITE_OK;
+}
+
+/*
+** This routine translates a standard POSIX errno code into something
+** useful to the clients of the sqlite3 functions. Specifically, it is
+** intended to translate a variety of "try again" errors into SQLITE_BUSY
+** and a variety of "please close the file descriptor NOW" errors into
+** SQLITE_IOERR
+**
+** Errors during initialization of locks, or file system support for locks,
+** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
+*/
+static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
+ switch (posixError) {
+ case 0:
+ return SQLITE_OK;
+
+ case EAGAIN:
+ case ETIMEDOUT:
+ case EBUSY:
+ case EINTR:
+ case ENOLCK:
+ /* random NFS retry error, unless during file system support
+ * introspection, in which it actually means what it says */
+ return SQLITE_BUSY;
+
+ case EACCES:
+ /* EACCES is like EAGAIN during locking operations, but not any other time*/
+ if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
+ return SQLITE_BUSY;
+ }
+ /* else fall through */
+ case EPERM:
+ return SQLITE_PERM;
+
+ case EDEADLK:
+ return SQLITE_IOERR_BLOCKED;
+
+#if EOPNOTSUPP!=ENOTSUP
+ case EOPNOTSUPP:
+ /* something went terribly awry, unless during file system support
+ * introspection, in which it actually means what it says */
+#endif
+#ifdef ENOTSUP
+ case ENOTSUP:
+ /* invalid fd, unless during file system support introspection, in which
+ * it actually means what it says */
+#endif
+ case EIO:
+ case EBADF:
+ case EINVAL:
+ case ENOTCONN:
+ case ENODEV:
+ case ENXIO:
+ case ENOENT:
+ case ESTALE:
+ case ENOSYS:
+ /* these should force the client to close the file and reconnect */
+
+ default:
+ return sqliteIOErr;
+ }
}
/*
** This routine checks if there is a RESERVED lock held on the specified
-** file by this or any other process. If such a lock is held, return
-** non-zero. If the file is unlocked or holds only SHARED locks, then
-** return zero.
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
- int r = 0;
+ int rc = SQLITE_OK;
+ int reserved = 0;
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -21374,30 +22566,33 @@
enterMutex(); /* Because pFile->pLock is shared across threads */
/* Check if a thread in this process holds such a lock */
if( pFile->pLock->locktype>SHARED_LOCK ){
- r = 1;
+ reserved = 1;
}
/* Otherwise see if some other process holds it.
*/
- if( !r ){
+ if( !reserved ){
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = RESERVED_BYTE;
lock.l_len = 1;
lock.l_type = F_WRLCK;
- fcntl(pFile->h, F_GETLK, &lock);
- if( lock.l_type!=F_UNLCK ){
- r = 1;
+ if (-1 == fcntl(pFile->h, F_GETLK, &lock)) {
+ int tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
+ pFile->lastErrno = tErrno;
+ } else if( lock.l_type!=F_UNLCK ){
+ reserved = 1;
}
}
leaveMutex();
- OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
-
- *pResOut = r;
- return SQLITE_OK;
+ OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
+
+ *pResOut = reserved;
+ return rc;
}
/*
** Lock the file with the lock specified by parameter locktype - one
@@ -21541,9 +22736,13 @@
lock.l_type = (locktype==SHARED_LOCK?F_RDLCK:F_WRLCK);
lock.l_start = PENDING_BYTE;
s = fcntl(pFile->h, F_SETLK, &lock);
if( s==(-1) ){
- rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
+ int tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
goto end_lock;
}
}
@@ -21551,26 +22750,38 @@
/* If control gets to this point, then actually go ahead and make
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
+ int tErrno = 0;
assert( pLock->cnt==0 );
assert( pLock->locktype==0 );
/* Now get the read-lock */
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
- s = fcntl(pFile->h, F_SETLK, &lock);
-
+ if( (s = fcntl(pFile->h, F_SETLK, &lock))==(-1) ){
+ tErrno = errno;
+ }
/* Drop the temporary PENDING lock */
lock.l_start = PENDING_BYTE;
lock.l_len = 1L;
lock.l_type = F_UNLCK;
if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
- goto end_lock;
+ if( s != -1 ){
+ /* This could happen with a network mount */
+ tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ goto end_lock;
+ }
}
if( s==(-1) ){
- rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
}else{
pFile->locktype = SHARED_LOCK;
pFile->pOpen->nLock++;
pLock->cnt = 1;
@@ -21598,9 +22809,13 @@
assert(0);
}
s = fcntl(pFile->h, F_SETLK, &lock);
if( s==(-1) ){
- rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
+ int tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
}
}
if( rc==SQLITE_OK ){
@@ -21657,9 +22872,14 @@
lock.l_whence = SEEK_SET;
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
if( fcntl(h, F_SETLK, &lock)==(-1) ){
- rc = SQLITE_IOERR_RDLOCK;
+ int tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ goto end_unlock;
}
}
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
@@ -21667,9 +22887,14 @@
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = SHARED_LOCK;
}else{
- rc = SQLITE_IOERR_UNLOCK;
+ int tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ goto end_unlock;
}
}
if( locktype==NO_LOCK ){
struct openCnt *pOpen;
@@ -21688,10 +22913,15 @@
SimulateIOErrorBenign(0);
if( fcntl(h, F_SETLK, &lock)!=(-1) ){
pLock->locktype = NO_LOCK;
}else{
- rc = SQLITE_IOERR_UNLOCK;
+ int tErrno = errno;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
pLock->cnt = 1;
+ goto end_unlock;
}
}
/* Decrement the count of locks against this same file. When the
@@ -21706,14 +22936,16 @@
int i;
for(i=0; i<pOpen->nPending; i++){
close(pOpen->aPending[i]);
}
- free(pOpen->aPending);
+ sqlite3_free(pOpen->aPending);
pOpen->nPending = 0;
pOpen->aPending = 0;
}
}
}
+
+end_unlock:
leaveMutex();
if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
}
@@ -21755,9 +22987,9 @@
** the last lock is cleared.
*/
int *aNew;
struct openCnt *pOpen = pFile->pOpen;
- aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
+ aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
if( aNew==0 ){
/* If a malloc fails, just leak the file descriptor */
}else{
pOpen->aPending = aNew;
@@ -21774,9 +23006,9 @@
return SQLITE_OK;
}
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_ENABLE_LOCKING_STYLE
#pragma mark AFP Support
/*
** The afpLockingContext structure contains all afp lock specific state
@@ -21799,16 +23031,13 @@
#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
/*
-** Return 0 on success, 1 on failure. To match the behavior of the
-** normal posix file locking (used in unixLock for example), we should
-** provide 'richer' return codes - specifically to differentiate between
-** 'file busy' and 'file system error' results.
-*/
+ ** Return SQLITE_OK on success, SQLITE_BUSY on failure.
+ */
static int _AFPFSSetLock(
const char *path,
- int fd,
+ unixFile *pFile,
unsigned long long offset,
unsigned long long length,
int setLockFlag
){
@@ -21818,57 +23047,65 @@
pb.unLockFlag = setLockFlag ? 0 : 1;
pb.startEndFlag = 0;
pb.offset = offset;
pb.length = length;
- pb.fd = fd;
+ pb.fd = pFile->h;
OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n",
- (setLockFlag?"ON":"OFF"), fd, offset, length);
+ (setLockFlag?"ON":"OFF"), pFile->h, offset, length);
err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
if ( err==-1 ) {
- OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno,
- strerror(errno));
- return 1; /* error */
- } else {
- return 0;
- }
-}
-
-/*
- ** This routine checks if there is a RESERVED lock held on the specified
- ** file by this or any other process. If such a lock is held, return
- ** non-zero. If the file is unlocked or holds only SHARED locks, then
- ** return zero.
- */
+ int rc;
+ int tErrno = errno;
+ OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, tErrno, strerror(tErrno));
+ rc = sqliteErrorFromPosixError(tErrno, setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); /* error */
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ return rc;
+ } else {
+ return SQLITE_OK;
+ }
+}
+
+/* AFP-style reserved lock checking following the behavior of
+** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
- int r = 0;
+ int rc = SQLITE_OK;
+ int reserved = 0;
unixFile *pFile = (unixFile*)id;
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
/* Check if a thread in this process holds such a lock */
if( pFile->locktype>SHARED_LOCK ){
- r = 1;
+ reserved = 1;
}
/* Otherwise see if some other process holds it.
*/
- if ( !r ) {
- /* lock the byte */
- int failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
- if (failed) {
- /* if we failed to get the lock then someone else must have it */
- r = 1;
- } else {
+ if( !reserved ){
+ /* lock the RESERVED byte */
+ int lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);
+ if( SQLITE_OK==lrc ){
/* if we succeeded in taking the reserved lock, unlock it to restore
** the original state */
- _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0);
- }
- }
- OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
-
- *pResOut = r;
- return SQLITE_OK;
+ lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1, 0);
+ } else {
+ /* if we failed to get the lock then someone else must have it */
+ reserved = 1;
+ }
+ if( IS_LOCK_ERROR(lrc) ){
+ rc=lrc;
+ }
+ }
+
+ OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
+
+ *pResOut = reserved;
+ return rc;
}
/* AFP-style locking following the behavior of unixLock, see the unixLock
** function comments for details of lock management. */
@@ -21916,11 +23153,11 @@
if( locktype==SHARED_LOCK
|| (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
){
int failed;
- failed = _AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 1);
+ failed = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 1);
if (failed) {
- rc = SQLITE_BUSY;
+ rc = failed;
goto afp_end_lock;
}
}
@@ -21927,25 +23164,31 @@
/* If control gets to this point, then actually go ahead and make
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
- int lk, failed;
-
- /* Now get the read-lock */
+ int lk, lrc1, lrc2, lrc1Errno;
+
+ /* Now get the read-lock SHARED_LOCK */
/* note that the quality of the randomness doesn't matter that much */
lk = random();
context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
- failed = _AFPFSSetLock(context->filePath, pFile->h,
- SHARED_FIRST+context->sharedLockByte, 1, 1);
-
+ lrc1 = _AFPFSSetLock(context->filePath, pFile,
+ SHARED_FIRST+context->sharedLockByte, 1, 1);
+ if( IS_LOCK_ERROR(lrc1) ){
+ lrc1Errno = pFile->lastErrno;
+ }
/* Drop the temporary PENDING lock */
- if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)) {
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ lrc2 = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 0);
+
+ if( IS_LOCK_ERROR(lrc1) ) {
+ pFile->lastErrno = lrc1Errno;
+ rc = lrc1;
+ goto afp_end_lock;
+ } else if( IS_LOCK_ERROR(lrc2) ){
+ rc = lrc2;
goto afp_end_lock;
- }
-
- if( failed ){
- rc = SQLITE_BUSY;
+ } else if( lrc1 != SQLITE_OK ) {
+ rc = lrc1;
} else {
pFile->locktype = SHARED_LOCK;
}
}else{
@@ -21956,32 +23199,31 @@
int failed = 0;
assert( 0!=pFile->locktype );
if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
/* Acquire a RESERVED lock */
- failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
+ failed = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);
}
if (!failed && locktype == EXCLUSIVE_LOCK) {
/* Acquire an EXCLUSIVE lock */
/* Remove the shared lock before trying the range. we'll need to
** reestablish the shared lock if we can't get the afpUnlock
*/
- if (!_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST +
- context->sharedLockByte, 1, 0)) {
+ if (!(failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST +
+ context->sharedLockByte, 1, 0))) {
/* now attemmpt to get the exclusive lock range */
- failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST,
+ failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST,
SHARED_SIZE, 1);
- if (failed && _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST +
- context->sharedLockByte, 1, 1)) {
- rc = SQLITE_IOERR_RDLOCK; /* this should never happen */
+ if (failed && (failed = _AFPFSSetLock(context->filePath, pFile,
+ SHARED_FIRST + context->sharedLockByte, 1, 1))) {
+ rc = failed;
}
} else {
- /* */
- rc = SQLITE_IOERR_UNLOCK; /* this should never happen */
- }
- }
- if( failed && rc == SQLITE_OK){
- rc = SQLITE_BUSY;
+ rc = failed;
+ }
+ }
+ if( failed ){
+ rc = failed;
}
}
if( rc==SQLITE_OK ){
@@ -22020,47 +23262,48 @@
if( CHECK_THREADID(pFile) ){
return SQLITE_MISUSE;
}
enterMutex();
+ int failed = SQLITE_OK;
if( pFile->locktype>SHARED_LOCK ){
if( locktype==SHARED_LOCK ){
- int failed = 0;
/* unlock the exclusive range - then re-establish the shared lock */
if (pFile->locktype==EXCLUSIVE_LOCK) {
- failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST,
+ failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST,
SHARED_SIZE, 0);
if (!failed) {
/* successfully removed the exclusive lock */
- if (_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST+
- context->sharedLockByte, 1, 1)) {
+ if ((failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST+
+ context->sharedLockByte, 1, 1))) {
/* failed to re-establish our shared lock */
- rc = SQLITE_IOERR_RDLOCK; /* This should never happen */
+ rc = failed;
}
} else {
- /* This should never happen - failed to unlock the exclusive range */
- rc = SQLITE_IOERR_UNLOCK;
+ rc = failed;
}
}
}
if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) {
- if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)){
+ if ((failed = _AFPFSSetLock(context->filePath, pFile,
+ PENDING_BYTE, 1, 0))){
/* failed to release the pending lock */
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = failed;
}
}
if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) {
- if (_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0)) {
+ if ((failed = _AFPFSSetLock(context->filePath, pFile,
+ RESERVED_BYTE, 1, 0))) {
/* failed to release the reserved lock */
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = failed;
}
}
}
if( locktype==NO_LOCK ){
- int failed = _AFPFSSetLock(context->filePath, pFile->h,
+ int failed = _AFPFSSetLock(context->filePath, pFile,
SHARED_FIRST + context->sharedLockByte, 1, 0);
if (failed) {
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
+ rc = failed;
}
}
if (rc == SQLITE_OK)
pFile->locktype = locktype;
@@ -22087,28 +23330,62 @@
** The flockLockingContext is not used
*/
typedef void flockLockingContext;
+/* flock-style reserved lock checking following the behavior of
+ ** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int r = 1;
+ int rc = SQLITE_OK;
+ int reserved = 0;
unixFile *pFile = (unixFile*)id;
- if (pFile->locktype != RESERVED_LOCK) {
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( pFile );
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->locktype>SHARED_LOCK ){
+ reserved = 1;
+ }
+
+ /* Otherwise see if some other process holds it. */
+ if( !reserved ){
/* attempt to get the lock */
- int rc = flock(pFile->h, LOCK_EX | LOCK_NB);
- if (!rc) {
+ int lrc = flock(pFile->h, LOCK_EX | LOCK_NB);
+ if( !lrc ){
/* got the lock, unlock it */
- flock(pFile->h, LOCK_UN);
- r = 0; /* no one has it reserved */
- }
- }
-
- *pResOut = r;
- return SQLITE_OK;
+ lrc = flock(pFile->h, LOCK_UN);
+ if ( lrc ) {
+ int tErrno = errno;
+ /* unlock failed with an error */
+ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ if( IS_LOCK_ERROR(lrc) ){
+ pFile->lastErrno = tErrno;
+ rc = lrc;
+ }
+ }
+ } else {
+ int tErrno = errno;
+ reserved = 1;
+ /* someone else might have it reserved */
+ lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(lrc) ){
+ pFile->lastErrno = tErrno;
+ rc = lrc;
+ }
+ }
+ }
+ OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
+
+ *pResOut = reserved;
+ return rc;
}
static int flockLock(sqlite3_file *id, int locktype) {
+ int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
+
+ assert( pFile );
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (pFile->locktype > NO_LOCK) {
@@ -22116,22 +23393,31 @@
return SQLITE_OK;
}
/* grab an exclusive lock */
- int rc = flock(pFile->h, LOCK_EX | LOCK_NB);
- if (rc) {
+
+ if (flock(pFile->h, LOCK_EX | LOCK_NB)) {
+ int tErrno = errno;
/* didn't get, must be busy */
- return SQLITE_BUSY;
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
} else {
/* got it, set the type and return ok */
pFile->locktype = locktype;
- return SQLITE_OK;
- }
+ }
+ OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
+ rc==SQLITE_OK ? "ok" : "failed");
+ return rc;
}
static int flockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
+ assert( pFile );
+ OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
+ pFile->locktype, getpid());
assert( locktype<=SHARED_LOCK );
/* no-op if possible */
if( pFile->locktype==locktype ){
@@ -22145,11 +23431,16 @@
}
/* no, really, unlock. */
int rc = flock(pFile->h, LOCK_UN);
- if (rc)
- return SQLITE_IOERR_UNLOCK;
- else {
+ if (rc) {
+ int r, tErrno = errno;
+ r = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ if( IS_LOCK_ERROR(r) ){
+ pFile->lastErrno = tErrno;
+ }
+ return r;
+ } else {
pFile->locktype = NO_LOCK;
return SQLITE_OK;
}
}
@@ -22165,29 +23456,52 @@
}
#pragma mark Old-School .lock file based locking
+/* Dotlock-style reserved lock checking following the behavior of
+** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int r = 1;
+ int rc = SQLITE_OK;
+ int reserved = 0;
unixFile *pFile = (unixFile*)id;
- char *zLockFile = (char *)pFile->lockingContext;
-
- if (pFile->locktype != RESERVED_LOCK) {
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( pFile );
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->locktype>SHARED_LOCK ){
+ reserved = 1;
+ }
+
+ /* Otherwise see if some other process holds it. */
+ if( !reserved ){
+ char *zLockFile = (char *)pFile->lockingContext;
struct stat statBuf;
- if (lstat(zLockFile, &statBuf) != 0){
+
+ if( lstat(zLockFile, &statBuf)==0 ){
+ /* file exists, someone else has the lock */
+ reserved = 1;
+ }else{
/* file does not exist, we could have it if we want it */
- r = 0;
- }
- }
-
- *pResOut = r;
- return SQLITE_OK;
+ int tErrno = errno;
+ if( ENOENT != tErrno ){
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
+ pFile->lastErrno = tErrno;
+ }
+ }
+ }
+ OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
+
+ *pResOut = reserved;
+ return rc;
}
static int dotlockLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int fd;
char *zLockFile = (char *)pFile->lockingContext;
+ int rc=SQLITE_OK;
/* if we already have a lock, it is exclusive.
** Just adjust level and punt on outta here. */
if (pFile->locktype > NO_LOCK) {
@@ -22194,34 +23508,50 @@
pFile->locktype = locktype;
/* Always update the timestamp on the old file */
utimes(zLockFile, NULL);
- return SQLITE_OK;
+ rc = SQLITE_OK;
+ goto dotlock_end_lock;
}
/* check to see if lock file already exists */
struct stat statBuf;
if (lstat(zLockFile,&statBuf) == 0){
- return SQLITE_BUSY; /* it does, busy */
+ rc = SQLITE_BUSY; /* it does, busy */
+ goto dotlock_end_lock;
}
/* grab an exclusive lock */
fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
if( fd<0 ){
/* failed to open/create the file, someone else may have stolen the lock */
- return SQLITE_BUSY;
+ int tErrno = errno;
+ if( EEXIST == tErrno ){
+ rc = SQLITE_BUSY;
+ } else {
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ }
+ goto dotlock_end_lock;
}
close(fd);
/* got it, set the type and return ok */
pFile->locktype = locktype;
- return SQLITE_OK;
+
+ dotlock_end_lock:
+ return rc;
}
static int dotlockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
char *zLockFile = (char *)pFile->lockingContext;
+ assert( pFile );
+ OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
+ pFile->locktype, getpid());
assert( locktype<=SHARED_LOCK );
/* no-op if possible */
if( pFile->locktype==locktype ){
@@ -22234,9 +23564,18 @@
return SQLITE_OK;
}
/* no, really, unlock. */
- unlink(zLockFile);
+ if (unlink(zLockFile) ) {
+ int rc, tErrno = errno;
+ if( ENOENT != tErrno ){
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
+ }
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ return rc;
+ }
pFile->locktype = NO_LOCK;
return SQLITE_OK;
}
@@ -22252,9 +23591,9 @@
return closeUnixFile(id);
}
-#pragma mark No locking
+#endif /* SQLITE_ENABLE_LOCKING_STYLE */
/*
** The nolockLockingContext is void
*/
@@ -22278,10 +23617,8 @@
*/
static int nolockClose(sqlite3_file *id) {
return closeUnixFile(id);
}
-
-#endif /* SQLITE_ENABLE_LOCKING_STYLE */
/*
** Information and control of an open file handle.
@@ -22329,10 +23666,15 @@
sqlite3_vfs *pVfs, /* Pointer to vfs object */
int h, /* Open file descriptor of file being opened */
int dirfd, /* Directory file descriptor */
sqlite3_file *pId, /* Write to the unixFile structure here */
- const char *zFilename /* Name of the file being opened */
-){
+ const char *zFilename, /* Name of the file being opened */
+ int noLock /* Omit locking if true */
+){
+ int eLockingStyle;
+ unixFile *pNew = (unixFile *)pId;
+ int rc = SQLITE_OK;
+
/* Macro to define the static contents of an sqlite3_io_methods
** structure for a unix backend file. Different locking methods
** require different functions for the xClose, xLock, xUnlock and
** xCheckReservedLock methods.
@@ -22353,19 +23695,23 @@
unixDeviceCharacteristics /* xDeviceCapabilities */ \
}
static sqlite3_io_methods aIoMethod[] = {
IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock)
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
- ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
+ ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
+#if SQLITE_ENABLE_LOCKING_STYLE
,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock)
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
+ ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
#endif
};
-
- int eLockingStyle;
- unixFile *pNew = (unixFile *)pId;
- int rc = SQLITE_OK;
+ /* The order of the IOMETHODS macros above is important. It must be the
+ ** same order as the LOCKING_STYLE numbers
+ */
+ assert(LOCKING_STYLE_POSIX==1);
+ assert(LOCKING_STYLE_NONE==2);
+ assert(LOCKING_STYLE_DOTFILE==3);
+ assert(LOCKING_STYLE_FLOCK==4);
+ assert(LOCKING_STYLE_AFP==5);
assert( pNew->pLock==NULL );
assert( pNew->pOpen==NULL );
@@ -22373,14 +23719,13 @@
pNew->h = h;
pNew->dirfd = dirfd;
SET_THREADID(pNew);
- assert(LOCKING_STYLE_POSIX==1);
- assert(LOCKING_STYLE_FLOCK==2);
- assert(LOCKING_STYLE_DOTFILE==3);
- assert(LOCKING_STYLE_NONE==4);
- assert(LOCKING_STYLE_AFP==5);
- eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
+ if( noLock ){
+ eLockingStyle = LOCKING_STYLE_NONE;
+ }else{
+ eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
+ }
switch( eLockingStyle ){
case LOCKING_STYLE_POSIX: {
@@ -22389,9 +23734,9 @@
leaveMutex();
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.
*/
@@ -22431,8 +23776,9 @@
break;
#endif
}
+ pNew->lastErrno = 0;
if( rc!=SQLITE_OK ){
if( dirfd>=0 ) close(dirfd);
close(h);
}else{
@@ -22562,8 +23908,9 @@
int fd = 0; /* File descriptor returned by open() */
int dirfd = -1; /* Directory file descriptor */
int oflags = 0; /* Flags to pass to open() */
int eType = flags&0xFFFFFF00; /* Type of file to open */
+ int noLock; /* True to omit locking primitives */
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
@@ -22657,9 +24004,10 @@
#ifdef FD_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
- return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath);
+ noLock = eType!=SQLITE_OPEN_MAIN_DB;
+ return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock);
}
/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
@@ -22668,8 +24016,9 @@
static int unixDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
int rc = SQLITE_OK;
SimulateIOError(return SQLITE_IOERR_DELETE);
unlink(zPath);
+#ifndef SQLITE_DISABLE_DIRSYNC
if( dirSync ){
int fd;
rc = openDirectory(zPath, &fd);
if( rc==SQLITE_OK ){
@@ -22678,8 +24027,9 @@
}
close(fd);
}
}
+#endif
return rc;
}
/*
@@ -22852,15 +24202,17 @@
time(&t);
memcpy(zBuf, &t, sizeof(t));
pid = getpid();
memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
- }else{
- read(fd, zBuf, nBuf);
+ assert( sizeof(t)+sizeof(pid)<=nBuf );
+ nBuf = sizeof(t) + sizeof(pid);
+ }else{
+ nBuf = read(fd, zBuf, nBuf);
close(fd);
}
}
#endif
- return SQLITE_OK;
+ return nBuf;
}
/*
@@ -22947,10 +24299,9 @@
unixGetLastError /* xGetLastError */ \
}
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),
UNIXVFS("unix-afp", LOCKING_STYLE_AFP),
@@ -22960,9 +24311,8 @@
};
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;
}
@@ -22991,9 +24341,9 @@
******************************************************************************
**
** This file contains code that is specific to windows.
**
-** $Id: os_win.c,v 1.129 2008/06/26 10:41:19 danielk1977 Exp $
+** $Id: os_win.c,v 1.136 2008/10/22 16:55:47 shane Exp $
*/
#if SQLITE_OS_WIN /* This file is used for windows only */
@@ -23130,9 +24480,9 @@
**
** This file contains inline asm code for retrieving "high-performance"
** counters for x86 class CPUs.
**
-** $Id: hwtime.h,v 1.2 2008/06/12 02:24:39 shane Exp $
+** $Id: hwtime.h,v 1.3 2008/08/01 14:33:15 shane Exp $
*/
#ifndef _HWTIME_H_
#define _HWTIME_H_
@@ -23169,8 +24519,23 @@
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
+ }
+
+#elif (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
}
#else
@@ -23258,12 +24623,19 @@
/************** 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
/*
@@ -23797,9 +25169,9 @@
winFile *pFile = (winFile*)id;
OSTRACE2("CLOSE %d\n", pFile->h);
do{
rc = CloseHandle(pFile->h);
- }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
+ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
#if SQLITE_OS_WINCE
#define WINCE_DELETION_ATTEMPTS 3
winceDestroyLock(pFile);
if( pFile->zDeleteOnClose ){
@@ -23900,16 +25272,22 @@
/*
** 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
/*
@@ -23971,13 +25349,17 @@
ovlp.OffsetHigh = 0;
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;
}
@@ -23987,10 +25369,14 @@
static int unlockReadLock(winFile *pFile){
int res;
if( isNT() ){
res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+*/
+#if SQLITE_OS_WINCE==0
}else{
res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
+#endif
}
return res;
}
@@ -24261,10 +25647,14 @@
static void *convertUtf8Filename(const char *zFilename){
void *zConverted = 0;
if( isNT() ){
zConverted = utf8ToUnicode(zFilename);
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+*/
+#if SQLITE_OS_WINCE==0
}else{
zConverted = utf8ToMbcs(zFilename);
+#endif
}
/* caller will handle out of memory */
return zConverted;
}
@@ -24277,9 +25667,9 @@
static char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
- int i, j;
+ size_t i, j;
char zTempPath[MAX_PATH+1];
if( sqlite3_temp_directory ){
sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
}else if( isNT() ){
@@ -24292,8 +25682,13 @@
free(zMulti);
}else{
return SQLITE_NOMEM;
}
+/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
+** Since the ASCII version of these Windows API do not exist for WINCE,
+** it's important to not reference them for WINCE builds.
+*/
+#if SQLITE_OS_WINCE==0
}else{
char *zUtf8;
char zMbcsPath[MAX_PATH];
GetTempPathA(MAX_PATH-30, zMbcsPath);
@@ -24303,8 +25698,9 @@
free(zUtf8);
}else{
return SQLITE_NOMEM;
}
+#endif
}
for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
zTempPath[i] = 0;
sqlite3_snprintf(nBuf-30, zBuf,
@@ -24316,8 +25712,38 @@
}
zBuf[j] = 0;
OSTRACE2("TEMP FILENAME: %s\n", zBuf);
return SQLITE_OK;
+}
+
+/*
+** The return value of getLastErrorMsg
+** is zero if the error message fits in the buffer, or non-zero
+** otherwise (if the message was truncated).
+*/
+static int getLastErrorMsg(int nBuf, char *zBuf){
+ DWORD error = GetLastError();
+
+#if SQLITE_OS_WINCE
+ sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
+#else
+ /* FormatMessage returns 0 on failure. Otherwise it
+ ** returns the number of TCHARs written to the output
+ ** buffer, excluding the terminating null char.
+ */
+ if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ error,
+ 0,
+ zBuf,
+ nBuf-1,
+ 0))
+ {
+ sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
+ }
+#endif
+
+ return 0;
}
/*
@@ -24334,9 +25760,11 @@
DWORD dwDesiredAccess;
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 */
char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */
@@ -24375,21 +25803,22 @@
}
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;
+ }else{
+ dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
}
/* 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,
dwShareMode,
@@ -24397,12 +25826,14 @@
dwCreationDisposition,
dwFlagsAndAttributes,
NULL
);
- }else{
-#if SQLITE_OS_WINCE
- return SQLITE_NOMEM;
-#else
+/* 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,
dwShareMode,
NULL,
@@ -24456,9 +25887,9 @@
**
** Note that windows does not allow a file to be deleted if some other
** process has it open. Sometimes a virus scanner or indexing program
** will open a journal file shortly after it is created in order to do
-** whatever does. While this other process is holding the
+** whatever it does. While this other process is holding the
** file open, we will be unable to delete it. To work around this
** problem, we delay 100 milliseconds and try to delete again. Up
** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
** up and returning an error.
@@ -24469,9 +25900,10 @@
const char *zFilename, /* Name of file to delete */
int syncDir /* Not used on win32 */
){
int cnt = 0;
- int rc;
+ DWORD rc;
+ DWORD error;
void *zConverted = convertUtf8Filename(zFilename);
if( zConverted==0 ){
return SQLITE_NOMEM;
}
@@ -24478,23 +25910,30 @@
SimulateIOError(return SQLITE_IOERR_DELETE);
if( isNT() ){
do{
DeleteFileW(zConverted);
- }while( (rc = GetFileAttributesW(zConverted))!=0xffffffff
- && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) );
- }else{
-#if SQLITE_OS_WINCE
- return SQLITE_NOMEM;
-#else
+ }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
+ || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
+ && (++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))!=0xffffffff
- && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) );
+ }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
+ || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
+ && (++cnt < MX_DELETION_ATTEMPTS)
+ && (Sleep(100), 1) );
#endif
}
free(zConverted);
OSTRACE2("DELETE \"%s\"\n", zFilename);
- return rc==0xffffffff ? SQLITE_OK : SQLITE_IOERR_DELETE;
+ return ( (rc == INVALID_FILE_ATTRIBUTES)
+ && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
}
/*
** Check the existance and status of a file.
@@ -24512,20 +25951,22 @@
return SQLITE_NOMEM;
}
if( isNT() ){
attr = GetFileAttributesW((WCHAR*)zConverted);
- }else{
-#if SQLITE_OS_WINCE
- return SQLITE_NOMEM;
-#else
+/* 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 ){
case SQLITE_ACCESS_READ:
case SQLITE_ACCESS_EXISTS:
- rc = attr!=0xffffffff;
+ rc = attr!=INVALID_FILE_ATTRIBUTES;
break;
case SQLITE_ACCESS_READWRITE:
rc = (attr & FILE_ATTRIBUTE_READONLY)==0;
break;
@@ -24576,8 +26017,13 @@
GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0);
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;
zTemp = malloc( nByte*sizeof(zTemp[0]) );
@@ -24588,8 +26034,9 @@
GetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
free(zConverted);
zOut = mbcsToUtf8(zTemp);
free(zTemp);
+#endif
}
if( zOut ){
sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut);
free(zOut);
@@ -24616,37 +26063,22 @@
return 0;
}
if( isNT() ){
h = LoadLibraryW((WCHAR*)zConverted);
- }else{
-#if SQLITE_OS_WINCE
- return 0;
-#else
+/* 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;
}
static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
-#if SQLITE_OS_WINCE
- int error = GetLastError();
- if( error>0x7FFFFFF ){
- sqlite3_snprintf(nBuf, zBufOut, "OsError 0x%x", error);
- }else{
- sqlite3_snprintf(nBuf, zBufOut, "OsError %d", error);
- }
-#else
- FormatMessageA(
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- GetLastError(),
- 0,
- zBufOut,
- nBuf-1,
- 0
- );
-#endif
+ getLastErrorMsg(nBuf, zBufOut);
}
void *winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
#if SQLITE_OS_WINCE
/* The GetProcAddressA() routine is only available on wince. */
@@ -24728,9 +26160,12 @@
double now;
#if SQLITE_OS_WINCE
SYSTEMTIME time;
GetSystemTime(&time);
- SystemTimeToFileTime(&time,&ft);
+ /* if SystemTimeToFileTime() fails, it returns zero. */
+ if (!SystemTimeToFileTime(&time,&ft)){
+ return 1;
+ }
#else
GetSystemTimeAsFileTime( &ft );
#endif
now = ((double)ft.dwHighDateTime) * 4294967296.0;
@@ -24742,10 +26177,40 @@
#endif
return 0;
}
+/*
+** The idea is that this function works like a combination of
+** GetLastError() and FormatMessage() on windows (or errno and
+** strerror_r() on unix). After an error is returned by an OS
+** function, SQLite calls this function with zBuf pointing to
+** a buffer of nBuf bytes. The OS layer should populate the
+** buffer with a nul-terminated UTF-8 encoded error message
+** describing the last IO error to have occured within the calling
+** thread.
+**
+** If the error message is too large for the supplied buffer,
+** it should be truncated. The return value of xGetLastError
+** is zero if the error message fits in the buffer, or non-zero
+** otherwise (if the message was truncated). If non-zero is returned,
+** then it is not necessary to include the nul-terminator character
+** in the output buffer.
+**
+** Not supplying an error message will have no adverse effect
+** on SQLite. It is fine to have an implementation that never
+** returns an error message:
+**
+** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+** assert(zBuf[0]=='\0');
+** return 0;
+** }
+**
+** However if an error message is supplied, it will be incorporated
+** by sqlite into the error message available to the user using
+** sqlite3_errmsg(), possibly making IO errors easier to debug.
+*/
static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
- return 0;
+ return getLastErrorMsg(nBuf, zBuf);
}
/*
** Initialize and deinitialize the operating system interface.
@@ -25108,8 +26573,1219 @@
}
#endif /* SQLITE_OMIT_BUILTIN_TEST */
/************** End of bitvec.c **********************************************/
+/************** Begin file pcache.c ******************************************/
+/*
+** 2008 August 05
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements that page cache.
+**
+** @(#) $Id: pcache.c,v 1.34 2008/10/17 18:51:53 danielk1977 Exp $
+*/
+
+/*
+** A complete page cache is an instance of this structure.
+**
+** A cache may only be deleted by its owner and while holding the
+** SQLITE_MUTEX_STATUS_LRU mutex.
+*/
+struct PCache {
+ /*********************************************************************
+ ** The first group of elements may be read or written at any time by
+ ** the cache owner without holding the mutex. No thread other than the
+ ** cache owner is permitted to access these elements at any time.
+ */
+ PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
+ PgHdr *pSynced; /* Last synced page in dirty page list */
+ int nRef; /* Number of pinned pages */
+ int nPinned; /* Number of pinned and/or dirty pages */
+ int nMax; /* Configured cache size */
+ int nMin; /* Configured minimum cache size */
+ /**********************************************************************
+ ** The next group of elements are fixed when the cache is created and
+ ** may not be changed afterwards. These elements can read at any time by
+ ** the cache owner or by any thread holding the the mutex. Non-owner
+ ** threads must hold the mutex when reading these elements to prevent
+ ** the entire PCache object from being deleted during the read.
+ */
+ int szPage; /* Size of every page in this cache */
+ int szExtra; /* Size of extra space for each page */
+ int bPurgeable; /* True if pages are on backing store */
+ int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
+ void *pStress; /* Argument to xStress */
+ /**********************************************************************
+ ** The final group of elements can only be accessed while holding the
+ ** mutex. Both the cache owner and any other thread must hold the mutex
+ ** to read or write any of these elements.
+ */
+ int nPage; /* Total number of pages in apHash */
+ int nHash; /* Number of slots in apHash[] */
+ PgHdr **apHash; /* Hash table for fast lookup by pgno */
+ PgHdr *pClean; /* List of clean pages in use */
+};
+
+/*
+** Free slots in the page block allocator
+*/
+typedef struct PgFreeslot PgFreeslot;
+struct PgFreeslot {
+ PgFreeslot *pNext; /* Next free slot */
+};
+
+/*
+** Global data for the page cache.
+*/
+static SQLITE_WSD struct PCacheGlobal {
+ int isInit; /* True when initialized */
+ sqlite3_mutex *mutex; /* static mutex MUTEX_STATIC_LRU */
+
+ int nMaxPage; /* Sum of nMaxPage for purgeable caches */
+ int nMinPage; /* Sum of nMinPage for purgeable caches */
+ int nCurrentPage; /* Number of purgeable pages allocated */
+ PgHdr *pLruHead, *pLruTail; /* LRU list of unused clean pgs */
+
+ /* Variables related to SQLITE_CONFIG_PAGECACHE settings. */
+ int szSlot; /* Size of each free slot */
+ void *pStart, *pEnd; /* Bounds of pagecache malloc range */
+ PgFreeslot *pFree; /* Free page blocks */
+} pcache = {0};
+
+/*
+** All code in this file should access the global pcache structure via the
+** alias "pcache_g". This ensures that the WSD emulation is used when
+** compiling for systems that do not support real WSD.
+*/
+#define pcache_g (GLOBAL(struct PCacheGlobal, pcache))
+
+/*
+** All global variables used by this module (all of which are grouped
+** together in global structure "pcache" above) are protected by the static
+** SQLITE_MUTEX_STATIC_LRU mutex. A pointer to this mutex is stored in
+** variable "pcache.mutex".
+**
+** Some elements of the PCache and PgHdr structures are protected by the
+** SQLITE_MUTEX_STATUS_LRU mutex and other are not. The protected
+** elements are grouped at the end of the structures and are clearly
+** marked.
+**
+** Use the following macros must surround all access (read or write)
+** of protected elements. The mutex is not recursive and may not be
+** entered more than once. The pcacheMutexHeld() macro should only be
+** used within an assert() to verify that the mutex is being held.
+*/
+#define pcacheEnterMutex() sqlite3_mutex_enter(pcache_g.mutex)
+#define pcacheExitMutex() sqlite3_mutex_leave(pcache_g.mutex)
+#define pcacheMutexHeld() sqlite3_mutex_held(pcache_g.mutex)
+
+/*
+** Some of the assert() macros in this code are too expensive to run
+** even during normal debugging. Use them only rarely on long-running
+** tests. Enable the expensive asserts using the
+** -DSQLITE_ENABLE_EXPENSIVE_ASSERT=1 compile-time option.
+*/
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+# define expensive_assert(X) assert(X)
+#else
+# define expensive_assert(X)
+#endif
+
+/********************************** Linked List Management ********************/
+
+#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
+/*
+** This routine verifies that the number of entries in the hash table
+** is pCache->nPage. This routine is used within assert() statements
+** only and is therefore disabled during production builds.
+*/
+static int pcacheCheckHashCount(PCache *pCache){
+ int i;
+ int nPage = 0;
+ for(i=0; i<pCache->nHash; i++){
+ PgHdr *p;
+ for(p=pCache->apHash[i]; p; p=p->pNextHash){
+ nPage++;
+ }
+ }
+ assert( nPage==pCache->nPage );
+ return 1;
+}
+#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
+
+
+#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
+/*
+** Based on the current value of PCache.nRef and the contents of the
+** PCache.pDirty list, return the expected value of the PCache.nPinned
+** counter. This is only used in debugging builds, as follows:
+**
+** expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+*/
+static int pcachePinnedCount(PCache *pCache){
+ PgHdr *p;
+ int nPinned = pCache->nRef;
+ for(p=pCache->pDirty; p; p=p->pNext){
+ if( p->nRef==0 ){
+ nPinned++;
+ }
+ }
+ return nPinned;
+}
+#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
+
+
+#if !defined(NDEBUG) && defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
+/*
+** Check that the pCache->pSynced variable is set correctly. If it
+** is not, either fail an assert or return zero. Otherwise, return
+** non-zero. This is only used in debugging builds, as follows:
+**
+** expensive_assert( pcacheCheckSynced(pCache) );
+*/
+static int pcacheCheckSynced(PCache *pCache){
+ PgHdr *p = pCache->pDirtyTail;
+ for(p=pCache->pDirtyTail; p!=pCache->pSynced; p=p->pPrev){
+ assert( p->nRef || (p->flags&PGHDR_NEED_SYNC) );
+ }
+ return (p==0 || p->nRef || (p->flags&PGHDR_NEED_SYNC)==0);
+}
+#endif /* !NDEBUG && SQLITE_ENABLE_EXPENSIVE_ASSERT */
+
+
+
+/*
+** Remove a page from its hash table (PCache.apHash[]).
+*/
+static void pcacheRemoveFromHash(PgHdr *pPage){
+ assert( pcacheMutexHeld() );
+ if( pPage->pPrevHash ){
+ pPage->pPrevHash->pNextHash = pPage->pNextHash;
+ }else{
+ PCache *pCache = pPage->pCache;
+ u32 h = pPage->pgno % pCache->nHash;
+ assert( pCache->apHash[h]==pPage );
+ pCache->apHash[h] = pPage->pNextHash;
+ }
+ if( pPage->pNextHash ){
+ pPage->pNextHash->pPrevHash = pPage->pPrevHash;
+ }
+ pPage->pCache->nPage--;
+ expensive_assert( pcacheCheckHashCount(pPage->pCache) );
+}
+
+/*
+** Insert a page into the hash table
+**
+** The mutex must be held by the caller.
+*/
+static void pcacheAddToHash(PgHdr *pPage){
+ PCache *pCache = pPage->pCache;
+ u32 h = pPage->pgno % pCache->nHash;
+ assert( pcacheMutexHeld() );
+ pPage->pNextHash = pCache->apHash[h];
+ pPage->pPrevHash = 0;
+ if( pCache->apHash[h] ){
+ pCache->apHash[h]->pPrevHash = pPage;
+ }
+ pCache->apHash[h] = pPage;
+ pCache->nPage++;
+ expensive_assert( pcacheCheckHashCount(pCache) );
+}
+
+/*
+** Attempt to increase the size the hash table to contain
+** at least nHash buckets.
+*/
+static int pcacheResizeHash(PCache *pCache, int nHash){
+ PgHdr *p;
+ PgHdr **pNew;
+ assert( pcacheMutexHeld() );
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+ if( nHash*sizeof(PgHdr*)>SQLITE_MALLOC_SOFT_LIMIT ){
+ nHash = SQLITE_MALLOC_SOFT_LIMIT/sizeof(PgHdr *);
+ }
+#endif
+ pcacheExitMutex();
+ pNew = (PgHdr **)sqlite3Malloc(sizeof(PgHdr*)*nHash);
+ pcacheEnterMutex();
+ if( !pNew ){
+ return SQLITE_NOMEM;
+ }
+ memset(pNew, 0, sizeof(PgHdr *)*nHash);
+ sqlite3_free(pCache->apHash);
+ pCache->apHash = pNew;
+ pCache->nHash = nHash;
+ pCache->nPage = 0;
+
+ for(p=pCache->pClean; p; p=p->pNext){
+ pcacheAddToHash(p);
+ }
+ for(p=pCache->pDirty; p; p=p->pNext){
+ pcacheAddToHash(p);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Remove a page from a linked list that is headed by *ppHead.
+** *ppHead is either PCache.pClean or PCache.pDirty.
+*/
+static void pcacheRemoveFromList(PgHdr **ppHead, PgHdr *pPage){
+ int isDirtyList = (ppHead==&pPage->pCache->pDirty);
+ assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty );
+ assert( pcacheMutexHeld() || ppHead!=&pPage->pCache->pClean );
+
+ if( pPage->pPrev ){
+ pPage->pPrev->pNext = pPage->pNext;
+ }else{
+ assert( *ppHead==pPage );
+ *ppHead = pPage->pNext;
+ }
+ if( pPage->pNext ){
+ pPage->pNext->pPrev = pPage->pPrev;
+ }
+
+ if( isDirtyList ){
+ PCache *pCache = pPage->pCache;
+ assert( pPage->pNext || pCache->pDirtyTail==pPage );
+ if( !pPage->pNext ){
+ pCache->pDirtyTail = pPage->pPrev;
+ }
+ if( pCache->pSynced==pPage ){
+ PgHdr *pSynced = pPage->pPrev;
+ while( pSynced && (pSynced->flags&PGHDR_NEED_SYNC) ){
+ pSynced = pSynced->pPrev;
+ }
+ pCache->pSynced = pSynced;
+ }
+ }
+}
+
+/*
+** Add a page from a linked list that is headed by *ppHead.
+** *ppHead is either PCache.pClean or PCache.pDirty.
+*/
+static void pcacheAddToList(PgHdr **ppHead, PgHdr *pPage){
+ int isDirtyList = (ppHead==&pPage->pCache->pDirty);
+ assert( ppHead==&pPage->pCache->pClean || ppHead==&pPage->pCache->pDirty );
+
+ if( (*ppHead) ){
+ (*ppHead)->pPrev = pPage;
+ }
+ pPage->pNext = *ppHead;
+ pPage->pPrev = 0;
+ *ppHead = pPage;
+
+ if( isDirtyList ){
+ PCache *pCache = pPage->pCache;
+ if( !pCache->pDirtyTail ){
+ assert( pPage->pNext==0 );
+ pCache->pDirtyTail = pPage;
+ }
+ if( !pCache->pSynced && 0==(pPage->flags&PGHDR_NEED_SYNC) ){
+ pCache->pSynced = pPage;
+ }
+ }
+}
+
+/*
+** Remove a page from the global LRU list
+*/
+static void pcacheRemoveFromLruList(PgHdr *pPage){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ assert( (pPage->flags&PGHDR_DIRTY)==0 );
+ if( pPage->pCache->bPurgeable==0 ) return;
+ if( pPage->pNextLru ){
+ assert( pcache_g.pLruTail!=pPage );
+ pPage->pNextLru->pPrevLru = pPage->pPrevLru;
+ }else{
+ assert( pcache_g.pLruTail==pPage );
+ pcache_g.pLruTail = pPage->pPrevLru;
+ }
+ if( pPage->pPrevLru ){
+ assert( pcache_g.pLruHead!=pPage );
+ pPage->pPrevLru->pNextLru = pPage->pNextLru;
+ }else{
+ assert( pcache_g.pLruHead==pPage );
+ pcache_g.pLruHead = pPage->pNextLru;
+ }
+}
+
+/*
+** Add a page to the global LRU list. The page is normally added
+** to the front of the list so that it will be the last page recycled.
+** However, if the PGHDR_REUSE_UNLIKELY bit is set, the page is added
+** to the end of the LRU list so that it will be the next to be recycled.
+*/
+static void pcacheAddToLruList(PgHdr *pPage){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ assert( (pPage->flags&PGHDR_DIRTY)==0 );
+ if( pPage->pCache->bPurgeable==0 ) return;
+ if( pcache_g.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
+ /* If reuse is unlikely. Put the page at the end of the LRU list
+ ** where it will be recycled sooner rather than later.
+ */
+ assert( pcache_g.pLruHead );
+ pPage->pNextLru = 0;
+ pPage->pPrevLru = pcache_g.pLruTail;
+ pcache_g.pLruTail->pNextLru = pPage;
+ pcache_g.pLruTail = pPage;
+ pPage->flags &= ~PGHDR_REUSE_UNLIKELY;
+ }else{
+ /* If reuse is possible. the page goes at the beginning of the LRU
+ ** list so that it will be the last to be recycled.
+ */
+ if( pcache_g.pLruHead ){
+ pcache_g.pLruHead->pPrevLru = pPage;
+ }
+ pPage->pNextLru = pcache_g.pLruHead;
+ pcache_g.pLruHead = pPage;
+ pPage->pPrevLru = 0;
+ if( pcache_g.pLruTail==0 ){
+ pcache_g.pLruTail = pPage;
+ }
+ }
+}
+
+/*********************************************** Memory Allocation ***********
+**
+** Initialize the page cache memory pool.
+**
+** This must be called at start-time when no page cache lines are
+** checked out. This function is not threadsafe.
+*/
+SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
+ PgFreeslot *p;
+ sz &= ~7;
+ pcache_g.szSlot = sz;
+ pcache_g.pStart = pBuf;
+ pcache_g.pFree = 0;
+ while( n-- ){
+ p = (PgFreeslot*)pBuf;
+ p->pNext = pcache_g.pFree;
+ pcache_g.pFree = p;
+ pBuf = (void*)&((char*)pBuf)[sz];
+ }
+ pcache_g.pEnd = pBuf;
+}
+
+/*
+** Allocate a page cache line. Look in the page cache memory pool first
+** and use an element from it first if available. If nothing is available
+** in the page cache memory pool, go to the general purpose memory allocator.
+*/
+static void *pcacheMalloc(int sz, PCache *pCache){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ if( sz<=pcache_g.szSlot && pcache_g.pFree ){
+ PgFreeslot *p = pcache_g.pFree;
+ pcache_g.pFree = p->pNext;
+ sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, sz);
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
+ return (void*)p;
+ }else{
+ void *p;
+
+ /* Allocate a new buffer using sqlite3Malloc. Before doing so, exit the
+ ** global pcache mutex and unlock the pager-cache object pCache. This is
+ ** so that if the attempt to allocate a new buffer causes the the
+ ** configured soft-heap-limit to be breached, it will be possible to
+ ** reclaim memory from this pager-cache.
+ */
+ pcacheExitMutex();
+ p = sqlite3Malloc(sz);
+ pcacheEnterMutex();
+
+ if( p ){
+ sz = sqlite3MallocSize(p);
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
+ }
+ return p;
+ }
+}
+SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
+ void *p;
+ pcacheEnterMutex();
+ p = pcacheMalloc(sz, 0);
+ pcacheExitMutex();
+ return p;
+}
+
+/*
+** Release a pager memory allocation
+*/
+static void pcacheFree(void *p){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ if( p==0 ) return;
+ if( p>=pcache_g.pStart && p<pcache_g.pEnd ){
+ PgFreeslot *pSlot;
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
+ pSlot = (PgFreeslot*)p;
+ pSlot->pNext = pcache_g.pFree;
+ pcache_g.pFree = pSlot;
+ }else{
+ int iSize = sqlite3MallocSize(p);
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -iSize);
+ sqlite3_free(p);
+ }
+}
+SQLITE_PRIVATE void sqlite3PageFree(void *p){
+ pcacheEnterMutex();
+ pcacheFree(p);
+ pcacheExitMutex();
+}
+
+/*
+** Allocate a new page.
+*/
+static PgHdr *pcachePageAlloc(PCache *pCache){
+ PgHdr *p;
+ int sz = sizeof(*p) + pCache->szPage + pCache->szExtra;
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ p = pcacheMalloc(sz, pCache);
+ if( p==0 ) return 0;
+ memset(p, 0, sizeof(PgHdr));
+ p->pData = (void*)&p[1];
+ p->pExtra = (void*)&((char*)p->pData)[pCache->szPage];
+ if( pCache->bPurgeable ){
+ pcache_g.nCurrentPage++;
+ }
+ return p;
+}
+
+/*
+** Deallocate a page
+*/
+static void pcachePageFree(PgHdr *p){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ if( p->pCache->bPurgeable ){
+ pcache_g.nCurrentPage--;
+ }
+ pcacheFree(p);
+}
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+/*
+** Return the number of bytes that will be returned to the heap when
+** the argument is passed to pcachePageFree().
+*/
+static int pcachePageSize(PgHdr *p){
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ assert( !pcache_g.pStart );
+ assert( p->apSave[0]==0 );
+ assert( p->apSave[1]==0 );
+ assert( p && p->pCache );
+ return sqlite3MallocSize(p);
+}
+#endif
+
+/*
+** Attempt to 'recycle' a page from the global LRU list. Only clean,
+** unreferenced pages from purgeable caches are eligible for recycling.
+**
+** This function removes page pcache.pLruTail from the global LRU list,
+** and from the hash-table and PCache.pClean list of the owner pcache.
+** There should be no other references to the page.
+**
+** A pointer to the recycled page is returned, or NULL if no page is
+** eligible for recycling.
+*/
+static PgHdr *pcacheRecyclePage(void){
+ PgHdr *p = 0;
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+
+ if( (p=pcache_g.pLruTail) ){
+ assert( (p->flags&PGHDR_DIRTY)==0 );
+ pcacheRemoveFromLruList(p);
+ pcacheRemoveFromHash(p);
+ pcacheRemoveFromList(&p->pCache->pClean, p);
+ }
+
+ return p;
+}
+
+/*
+** Obtain space for a page. Try to recycle an old page if the limit on the
+** number of pages has been reached. If the limit has not been reached or
+** there are no pages eligible for recycling, allocate a new page.
+**
+** Return a pointer to the new page, or NULL if an OOM condition occurs.
+*/
+static int pcacheRecycleOrAlloc(PCache *pCache, PgHdr **ppPage){
+ PgHdr *p = 0;
+
+ int szPage = pCache->szPage;
+ int szExtra = pCache->szExtra;
+
+ assert( pcache_g.isInit );
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+
+ *ppPage = 0;
+
+ /* If we have reached either the global or the local limit for
+ ** pinned+dirty pages, and there is at least one dirty page,
+ ** invoke the xStress callback to cause a page to become clean.
+ */
+ expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+ expensive_assert( pcacheCheckSynced(pCache) );
+ if( pCache->xStress
+ && pCache->pDirty
+ && (pCache->nPinned>=(pcache_g.nMaxPage+pCache->nMin-pcache_g.nMinPage)
+ || pCache->nPinned>=pCache->nMax)
+ ){
+ PgHdr *pPg;
+ assert(pCache->pDirtyTail);
+
+ for(pPg=pCache->pSynced;
+ pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
+ pPg=pPg->pPrev
+ );
+ if( !pPg ){
+ for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pPrev);
+ }
+ if( pPg ){
+ int rc;
+ pcacheExitMutex();
+ rc = pCache->xStress(pCache->pStress, pPg);
+ pcacheEnterMutex();
+ if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+ }
+
+ /* If either the local or the global page limit has been reached,
+ ** try to recycle a page.
+ */
+ if( pCache->bPurgeable && (pCache->nPage>=pCache->nMax-1 ||
+ pcache_g.nCurrentPage>=pcache_g.nMaxPage) ){
+ p = pcacheRecyclePage();
+ }
+
+ /* If a page has been recycled but it is the wrong size, free it. */
+ if( p && (p->pCache->szPage!=szPage || p->pCache->szPage!=szExtra) ){
+ pcachePageFree(p);
+ p = 0;
+ }
+
+ if( !p ){
+ p = pcachePageAlloc(pCache);
+ }
+
+ *ppPage = p;
+ return (p?SQLITE_OK:SQLITE_NOMEM);
+}
+
+/*************************************************** General Interfaces ******
+**
+** Initialize and shutdown the page cache subsystem. Neither of these
+** functions are threadsafe.
+*/
+SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
+ assert( pcache_g.isInit==0 );
+ memset(&pcache_g, 0, sizeof(pcache));
+ if( sqlite3GlobalConfig.bCoreMutex ){
+ /* No need to check the return value of sqlite3_mutex_alloc().
+ ** Allocating a static mutex cannot fail.
+ */
+ pcache_g.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
+ }
+ pcache_g.isInit = 1;
+ return SQLITE_OK;
+}
+SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
+ memset(&pcache_g, 0, sizeof(pcache));
+}
+
+/*
+** Return the size in bytes of a PCache object.
+*/
+SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
+
+/*
+** Create a new PCache object. Storage space to hold the object
+** has already been allocated and is passed in as the p pointer.
+*/
+SQLITE_PRIVATE void sqlite3PcacheOpen(
+ int szPage, /* Size of every page */
+ int szExtra, /* Extra space associated with each page */
+ int bPurgeable, /* True if pages are on backing store */
+ int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
+ void *pStress, /* Argument to xStress */
+ PCache *p /* Preallocated space for the PCache */
+){
+ assert( pcache_g.isInit );
+ memset(p, 0, sizeof(PCache));
+ p->szPage = szPage;
+ p->szExtra = szExtra;
+ p->bPurgeable = bPurgeable;
+ p->xStress = xStress;
+ p->pStress = pStress;
+ p->nMax = 100;
+ p->nMin = 10;
+
+ pcacheEnterMutex();
+ if( bPurgeable ){
+ pcache_g.nMaxPage += p->nMax;
+ pcache_g.nMinPage += p->nMin;
+ }
+
+ pcacheExitMutex();
+}
+
+/*
+** Change the page size for PCache object. This can only happen
+** when the cache is empty.
+*/
+SQLITE_PRIVATE void sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
+ assert(pCache->nPage==0);
+ pCache->szPage = szPage;
+}
+
+/*
+** Try to obtain a page from the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcacheFetch(
+ PCache *pCache, /* Obtain the page from this cache */
+ Pgno pgno, /* Page number to obtain */
+ int createFlag, /* If true, create page if it does not exist already */
+ PgHdr **ppPage /* Write the page here */
+){
+ int rc = SQLITE_OK;
+ PgHdr *pPage = 0;
+
+ assert( pcache_g.isInit );
+ assert( pCache!=0 );
+ assert( pgno>0 );
+ expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+
+ pcacheEnterMutex();
+
+ /* Search the hash table for the requested page. Exit early if it is found. */
+ if( pCache->apHash ){
+ u32 h = pgno % pCache->nHash;
+ for(pPage=pCache->apHash[h]; pPage; pPage=pPage->pNextHash){
+ if( pPage->pgno==pgno ){
+ if( pPage->nRef==0 ){
+ if( 0==(pPage->flags&PGHDR_DIRTY) ){
+ pcacheRemoveFromLruList(pPage);
+ pCache->nPinned++;
+ }
+ pCache->nRef++;
+ }
+ pPage->nRef++;
+ break;
+ }
+ }
+ }
+
+ if( !pPage && createFlag ){
+ if( pCache->nHash<=pCache->nPage ){
+ rc = pcacheResizeHash(pCache, pCache->nHash<256 ? 256 : pCache->nHash*2);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pcacheRecycleOrAlloc(pCache, &pPage);
+ }
+ if( rc==SQLITE_OK ){
+ pPage->pPager = 0;
+ pPage->flags = 0;
+ pPage->pDirty = 0;
+ pPage->pgno = pgno;
+ pPage->pCache = pCache;
+ pPage->nRef = 1;
+ pCache->nRef++;
+ pCache->nPinned++;
+ pcacheAddToList(&pCache->pClean, pPage);
+ pcacheAddToHash(pPage);
+ }
+ }
+
+ pcacheExitMutex();
+
+ *ppPage = pPage;
+ expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+ assert( pPage || !createFlag || rc!=SQLITE_OK );
+ return rc;
+}
+
+/*
+** Dereference a page. When the reference count reaches zero,
+** move the page to the LRU list if it is clean.
+*/
+SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr *p){
+ assert( p->nRef>0 );
+ p->nRef--;
+ if( p->nRef==0 ){
+ PCache *pCache = p->pCache;
+ pCache->nRef--;
+ if( (p->flags&PGHDR_DIRTY)==0 ){
+ pCache->nPinned--;
+ pcacheEnterMutex();
+ if( pcache_g.nCurrentPage>pcache_g.nMaxPage ){
+ pcacheRemoveFromList(&pCache->pClean, p);
+ pcacheRemoveFromHash(p);
+ pcachePageFree(p);
+ }else{
+ pcacheAddToLruList(p);
+ }
+ pcacheExitMutex();
+ }else{
+ /* Move the page to the head of the caches dirty list. */
+ pcacheRemoveFromList(&pCache->pDirty, p);
+ pcacheAddToList(&pCache->pDirty, p);
+ }
+ }
+}
+
+SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
+ assert(p->nRef>0);
+ p->nRef++;
+}
+
+/*
+** Drop a page from the cache. There must be exactly one reference to the
+** page. This function deletes that reference, so after it returns the
+** page pointed to by p is invalid.
+*/
+SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
+ PCache *pCache;
+ assert( p->nRef==1 );
+ assert( 0==(p->flags&PGHDR_DIRTY) );
+ pCache = p->pCache;
+ pCache->nRef--;
+ pCache->nPinned--;
+ pcacheEnterMutex();
+ pcacheRemoveFromList(&pCache->pClean, p);
+ pcacheRemoveFromHash(p);
+ pcachePageFree(p);
+ pcacheExitMutex();
+}
+
+/*
+** Make sure the page is marked as dirty. If it isn't dirty already,
+** make it so.
+*/
+SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
+ PCache *pCache;
+ p->flags &= ~PGHDR_DONT_WRITE;
+ if( p->flags & PGHDR_DIRTY ) return;
+ assert( (p->flags & PGHDR_DIRTY)==0 );
+ assert( p->nRef>0 );
+ pCache = p->pCache;
+ pcacheEnterMutex();
+ pcacheRemoveFromList(&pCache->pClean, p);
+ pcacheAddToList(&pCache->pDirty, p);
+ pcacheExitMutex();
+ p->flags |= PGHDR_DIRTY;
+}
+
+static void pcacheMakeClean(PgHdr *p){
+ PCache *pCache = p->pCache;
+ assert( p->flags & PGHDR_DIRTY );
+ pcacheRemoveFromList(&pCache->pDirty, p);
+ pcacheAddToList(&pCache->pClean, p);
+ p->flags &= ~PGHDR_DIRTY;
+ if( p->nRef==0 ){
+ pcacheAddToLruList(p);
+ pCache->nPinned--;
+ }
+ expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+}
+
+/*
+** Make sure the page is marked as clean. If it isn't clean already,
+** make it so.
+*/
+SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
+ if( (p->flags & PGHDR_DIRTY) ){
+ pcacheEnterMutex();
+ pcacheMakeClean(p);
+ pcacheExitMutex();
+ }
+}
+
+/*
+** Make every page in the cache clean.
+*/
+SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
+ PgHdr *p;
+ pcacheEnterMutex();
+ while( (p = pCache->pDirty)!=0 ){
+ pcacheRemoveFromList(&pCache->pDirty, p);
+ p->flags &= ~PGHDR_DIRTY;
+ pcacheAddToList(&pCache->pClean, p);
+ if( p->nRef==0 ){
+ pcacheAddToLruList(p);
+ pCache->nPinned--;
+ }
+ }
+ sqlite3PcacheAssertFlags(pCache, 0, PGHDR_DIRTY);
+ expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+ pcacheExitMutex();
+}
+
+/*
+** Change the page number of page p to newPgno. If newPgno is 0, then the
+** page object is added to the clean-list and the PGHDR_REUSE_UNLIKELY
+** flag set.
+*/
+SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
+ assert( p->nRef>0 );
+ pcacheEnterMutex();
+ pcacheRemoveFromHash(p);
+ p->pgno = newPgno;
+ if( newPgno==0 ){
+ if( (p->flags & PGHDR_DIRTY) ){
+ pcacheMakeClean(p);
+ }
+ p->flags = PGHDR_REUSE_UNLIKELY;
+ }
+ pcacheAddToHash(p);
+ pcacheExitMutex();
+}
+
+/*
+** Remove all content from a page cache
+*/
+static void pcacheClear(PCache *pCache){
+ PgHdr *p, *pNext;
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ for(p=pCache->pClean; p; p=pNext){
+ pNext = p->pNext;
+ pcacheRemoveFromLruList(p);
+ pcachePageFree(p);
+ }
+ for(p=pCache->pDirty; p; p=pNext){
+ pNext = p->pNext;
+ pcachePageFree(p);
+ }
+ pCache->pClean = 0;
+ pCache->pDirty = 0;
+ pCache->pDirtyTail = 0;
+ pCache->nPage = 0;
+ pCache->nPinned = 0;
+ memset(pCache->apHash, 0, pCache->nHash*sizeof(pCache->apHash[0]));
+}
+
+
+/*
+** Drop every cache entry whose page number is greater than "pgno".
+*/
+SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
+ PgHdr *p, *pNext;
+ PgHdr *pDirty = pCache->pDirty;
+ pcacheEnterMutex();
+ for(p=pCache->pClean; p||pDirty; p=pNext){
+ if( !p ){
+ p = pDirty;
+ pDirty = 0;
+ }
+ pNext = p->pNext;
+ if( p->pgno>pgno ){
+ if( p->nRef==0 ){
+ pcacheRemoveFromHash(p);
+ if( p->flags&PGHDR_DIRTY ){
+ pcacheRemoveFromList(&pCache->pDirty, p);
+ pCache->nPinned--;
+ }else{
+ pcacheRemoveFromList(&pCache->pClean, p);
+ pcacheRemoveFromLruList(p);
+ }
+ pcachePageFree(p);
+ }else{
+ /* If there are references to the page, it cannot be freed. In this
+ ** case, zero the page content instead.
+ */
+ memset(p->pData, 0, pCache->szPage);
+ }
+ }
+ }
+ pcacheExitMutex();
+}
+
+/*
+** If there are currently more than pcache.nMaxPage pages allocated, try
+** to recycle pages to reduce the number allocated to pcache.nMaxPage.
+*/
+static void pcacheEnforceMaxPage(void){
+ PgHdr *p;
+ assert( sqlite3_mutex_held(pcache_g.mutex) );
+ while( pcache_g.nCurrentPage>pcache_g.nMaxPage && (p = pcacheRecyclePage()) ){
+ pcachePageFree(p);
+ }
+}
+
+/*
+** Close a cache.
+*/
+SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
+ pcacheEnterMutex();
+
+ /* Free all the pages used by this pager and remove them from the LRU list. */
+ pcacheClear(pCache);
+ if( pCache->bPurgeable ){
+ pcache_g.nMaxPage -= pCache->nMax;
+ pcache_g.nMinPage -= pCache->nMin;
+ pcacheEnforceMaxPage();
+ }
+ sqlite3_free(pCache->apHash);
+ pcacheExitMutex();
+}
+
+
+#ifndef NDEBUG
+/*
+** Assert flags settings on all pages. Debugging only.
+*/
+SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache *pCache, int trueMask, int falseMask){
+ PgHdr *p;
+ for(p=pCache->pDirty; p; p=p->pNext){
+ assert( (p->flags&trueMask)==trueMask );
+ assert( (p->flags&falseMask)==0 );
+ }
+ for(p=pCache->pClean; p; p=p->pNext){
+ assert( (p->flags&trueMask)==trueMask );
+ assert( (p->flags&falseMask)==0 );
+ }
+}
+#endif
+
+/*
+** Discard the contents of the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcacheClear(PCache *pCache){
+ assert(pCache->nRef==0);
+ pcacheEnterMutex();
+ pcacheClear(pCache);
+ pcacheExitMutex();
+ return SQLITE_OK;
+}
+
+/*
+** Merge two lists of pages connected by pDirty and in pgno order.
+** Do not both fixing the pPrevDirty pointers.
+*/
+static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
+ PgHdr result, *pTail;
+ pTail = &result;
+ while( pA && pB ){
+ if( pA->pgno<pB->pgno ){
+ pTail->pDirty = pA;
+ pTail = pA;
+ pA = pA->pDirty;
+ }else{
+ pTail->pDirty = pB;
+ pTail = pB;
+ pB = pB->pDirty;
+ }
+ }
+ if( pA ){
+ pTail->pDirty = pA;
+ }else if( pB ){
+ pTail->pDirty = pB;
+ }else{
+ pTail->pDirty = 0;
+ }
+ return result.pDirty;
+}
+
+/*
+** Sort the list of pages in accending order by pgno. Pages are
+** connected by pDirty pointers. The pPrevDirty pointers are
+** corrupted by this sort.
+*/
+#define N_SORT_BUCKET_ALLOC 25
+#define N_SORT_BUCKET 25
+#ifdef SQLITE_TEST
+ int sqlite3_pager_n_sort_bucket = 0;
+ #undef N_SORT_BUCKET
+ #define N_SORT_BUCKET \
+ (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
+#endif
+static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
+ PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
+ int i;
+ memset(a, 0, sizeof(a));
+ while( pIn ){
+ p = pIn;
+ pIn = p->pDirty;
+ p->pDirty = 0;
+ for(i=0; i<N_SORT_BUCKET-1; i++){
+ if( a[i]==0 ){
+ a[i] = p;
+ break;
+ }else{
+ p = pcacheMergeDirtyList(a[i], p);
+ a[i] = 0;
+ }
+ }
+ if( i==N_SORT_BUCKET-1 ){
+ /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET)
+ ** elements in the input list. This is possible, but impractical.
+ ** Testing this line is the point of global variable
+ ** sqlite3_pager_n_sort_bucket.
+ */
+ a[i] = pcacheMergeDirtyList(a[i], p);
+ }
+ }
+ p = a[0];
+ for(i=1; i<N_SORT_BUCKET; i++){
+ p = pcacheMergeDirtyList(p, a[i]);
+ }
+ return p;
+}
+
+/*
+** Return a list of all dirty pages in the cache, sorted by page number.
+*/
+SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
+ PgHdr *p;
+ for(p=pCache->pDirty; p; p=p->pNext){
+ p->pDirty = p->pNext;
+ }
+ return pcacheSortDirtyList(pCache->pDirty);
+}
+
+/*
+** Return the total number of outstanding page references.
+*/
+SQLITE_PRIVATE int sqlite3PcacheRefCount(PCache *pCache){
+ return pCache->nRef;
+}
+
+SQLITE_PRIVATE int sqlite3PcachePageRefcount(PgHdr *p){
+ return p->nRef;
+}
+
+/*
+** Return the total number of pages in the cache.
+*/
+SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
+ assert( pCache->nPage>=0 );
+ return pCache->nPage;
+}
+
+#ifdef SQLITE_CHECK_PAGES
+/*
+** This function is used by the pager.c module to iterate through all
+** pages in the cache. At present, this is only required if the
+** SQLITE_CHECK_PAGES macro (used for debugging) is specified.
+*/
+SQLITE_PRIVATE void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *)){
+ PgHdr *p;
+ for(p=pCache->pClean; p; p=p->pNext){
+ xIter(p);
+ }
+ for(p=pCache->pDirty; p; p=p->pNext){
+ xIter(p);
+ }
+}
+#endif
+
+/*
+** Set flags on all pages in the page cache
+*/
+SQLITE_PRIVATE void sqlite3PcacheClearFlags(PCache *pCache, int mask){
+ PgHdr *p;
+
+ /* Obtain the global mutex before modifying any PgHdr.flags variables
+ ** or traversing the LRU list.
+ */
+ pcacheEnterMutex();
+
+ mask = ~mask;
+ for(p=pCache->pDirty; p; p=p->pNext){
+ p->flags &= mask;
+ }
+ for(p=pCache->pClean; p; p=p->pNext){
+ p->flags &= mask;
+ }
+
+ if( 0==(mask&PGHDR_NEED_SYNC) ){
+ pCache->pSynced = pCache->pDirtyTail;
+ assert( !pCache->pSynced || (pCache->pSynced->flags&PGHDR_NEED_SYNC)==0 );
+ }
+
+ pcacheExitMutex();
+}
+
+/*
+** Set the suggested cache-size value.
+*/
+SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
+ return pCache->nMax;
+}
+
+/*
+** Set the suggested cache-size value.
+*/
+SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
+ if( mxPage<10 ){
+ mxPage = 10;
+ }
+ if( pCache->bPurgeable ){
+ pcacheEnterMutex();
+ pcache_g.nMaxPage -= pCache->nMax;
+ pcache_g.nMaxPage += mxPage;
+ pcacheEnforceMaxPage();
+ pcacheExitMutex();
+ }
+ pCache->nMax = mxPage;
+}
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+/*
+** This function is called to free superfluous dynamically allocated memory
+** held by the pager system. Memory in use by any SQLite pager allocated
+** by the current thread may be sqlite3_free()ed.
+**
+** nReq is the number of bytes of memory required. Once this much has
+** been released, the function returns. The return value is the total number
+** of bytes of memory released.
+*/
+SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
+ int nFree = 0;
+ if( pcache_g.pStart==0 ){
+ PgHdr *p;
+ pcacheEnterMutex();
+ while( (nReq<0 || nFree<nReq) && (p=pcacheRecyclePage()) ){
+ nFree += pcachePageSize(p);
+ pcachePageFree(p);
+ }
+ pcacheExitMutex();
+ }
+ return nFree;
+}
+#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE void sqlite3PcacheStats(
+ int *pnCurrent,
+ int *pnMax,
+ int *pnMin,
+ int *pnRecyclable
+){
+ PgHdr *p;
+ int nRecyclable = 0;
+ for(p=pcache_g.pLruHead; p; p=p->pNextLru){
+ nRecyclable++;
+ }
+
+ *pnCurrent = pcache_g.nCurrentPage;
+ *pnMax = pcache_g.nMaxPage;
+ *pnMin = pcache_g.nMinPage;
+ *pnRecyclable = nRecyclable;
+}
+#endif
+
+/************** End of pcache.c **********************************************/
/************** Begin file pager.c *******************************************/
/*
** 2001 September 15
**
@@ -25129,9 +27805,9 @@
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.465 2008/07/11 03:34:10 drh Exp $
+** @(#) $Id: pager.c,v 1.500 2008/10/29 07:01:57 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
/*
@@ -25239,175 +27915,8 @@
** is guaranteed to be an address that is aligned to an 8-byte boundary.
*/
#define FORCE_ALIGNMENT(X) (((X)+7)&~7)
-typedef struct PgHdr PgHdr;
-
-/*
-** Each pager stores all currently unreferenced pages in a list sorted
-** in least-recently-used (LRU) order (i.e. the first item on the list has
-** not been referenced in a long time, the last item has been recently
-** used). An instance of this structure is included as part of each
-** pager structure for this purpose (variable Pager.lru).
-**
-** Additionally, if memory-management is enabled, all unreferenced pages
-** are stored in a global LRU list (global variable sqlite3LruPageList).
-**
-** In both cases, the PagerLruList.pFirstSynced variable points to
-** the first page in the corresponding list that does not require an
-** fsync() operation before its memory can be reclaimed. If no such
-** page exists, PagerLruList.pFirstSynced is set to NULL.
-*/
-typedef struct PagerLruList PagerLruList;
-struct PagerLruList {
- PgHdr *pFirst; /* First page in LRU list */
- PgHdr *pLast; /* Last page in LRU list (the most recently used) */
- PgHdr *pFirstSynced; /* First page in list with PgHdr.needSync==0 */
-};
-
-/*
-** The following structure contains the next and previous pointers used
-** to link a PgHdr structure into a PagerLruList linked list.
-*/
-typedef struct PagerLruLink PagerLruLink;
-struct PagerLruLink {
- PgHdr *pNext;
- PgHdr *pPrev;
-};
-
-/*
-** Each in-memory image of a page begins with the following header.
-** This header is only visible to this pager module. The client
-** code that calls pager sees only the data that follows the header.
-**
-** Client code should call sqlite3PagerWrite() on a page prior to making
-** any modifications to that page. The first time sqlite3PagerWrite()
-** is called, the original page contents are written into the rollback
-** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once
-** the journal page has made it onto the disk surface, PgHdr.needSync
-** is cleared. The modified page cannot be written back into the original
-** database file until the journal pages has been synced to disk and the
-** PgHdr.needSync has been cleared.
-**
-** The PgHdr.dirty flag is set when sqlite3PagerWrite() is called and
-** is cleared again when the page content is written back to the original
-** database file.
-**
-** Details of important structure elements:
-**
-** needSync
-**
-** If this is true, this means that it is not safe to write the page
-** content to the database because the original content needed
-** for rollback has not by synced to the main rollback journal.
-** The original content may have been written to the rollback journal
-** but it has not yet been synced. So we cannot write to the database
-** file because power failure might cause the page in the journal file
-** to never reach the disk. It is as if the write to the journal file
-** does not occur until the journal file is synced.
-**
-** This flag is false if the page content exactly matches what
-** currently exists in the database file. The needSync flag is also
-** false if the original content has been written to the main rollback
-** journal and synced. If the page represents a new page that has
-** been added onto the end of the database during the current
-** transaction, the needSync flag is true until the original database
-** size in the journal header has been synced to disk.
-**
-** inJournal
-**
-** This is true if the original page has been written into the main
-** rollback journal. This is always false for new pages added to
-** the end of the database file during the current transaction.
-** And this flag says nothing about whether or not the journal
-** has been synced to disk. For pages that are in the original
-** database file, the following expression should always be true:
-**
-** inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno)
-**
-** The pPager->pInJournal object is only valid for the original
-** pages of the database, not new pages that are added to the end
-** of the database, so obviously the above expression cannot be
-** valid for new pages. For new pages inJournal is always 0.
-**
-** dirty
-**
-** When true, this means that the content of the page has been
-** modified and needs to be written back to the database file.
-** If false, it means that either the content of the page is
-** unchanged or else the content is unimportant and we do not
-** care whether or not it is preserved.
-**
-** alwaysRollback
-**
-** This means that the sqlite3PagerDontRollback() API should be
-** ignored for this page. The DontRollback() API attempts to say
-** that the content of the page on disk is unimportant (it is an
-** unused page on the freelist) so that it is unnecessary to
-** rollback changes to this page because the content of the page
-** can change without changing the meaning of the database. This
-** flag overrides any DontRollback() attempt. This flag is set
-** when a page that originally contained valid data is added to
-** the freelist. Later in the same transaction, this page might
-** be pulled from the freelist and reused for something different
-** and at that point the DontRollback() API will be called because
-** pages taken from the freelist do not need to be protected by
-** the rollback journal. But this flag says that the page was
-** not originally part of the freelist so that it still needs to
-** be rolled back in spite of any subsequent DontRollback() calls.
-**
-** needRead
-**
-** This flag means (when true) that the content of the page has
-** not yet been loaded from disk. The in-memory content is just
-** garbage. (Actually, we zero the content, but you should not
-** make any assumptions about the content nevertheless.) If the
-** content is needed in the future, it should be read from the
-** original database file.
-*/
-struct PgHdr {
- Pager *pPager; /* The pager to which this page belongs */
- Pgno pgno; /* The page number for this page */
- PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */
- PagerLruLink free; /* Next and previous free pages */
- PgHdr *pNextAll; /* A list of all pages */
- u8 inJournal; /* TRUE if has been written to journal */
- u8 dirty; /* TRUE if we need to write back changes */
- u8 needSync; /* Sync journal before writing this page */
- u8 alwaysRollback; /* Disable DontRollback() for this page */
- u8 needRead; /* Read content if PagerWrite() is called */
- short int nRef; /* Number of users of this page */
- PgHdr *pDirty, *pPrevDirty; /* Dirty pages */
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- PgHdr *pPrevAll; /* A list of all pages */
- PagerLruLink gfree; /* Global list of nRef==0 pages */
-#endif
-#ifdef SQLITE_CHECK_PAGES
- u32 pageHash;
-#endif
- void *pData; /* Page data */
- /* Pager.nExtra bytes of local data appended to this header */
-};
-
-/*
-** For an in-memory only database, some extra information is recorded about
-** each page so that changes can be rolled back. (Journal files are not
-** used for in-memory databases.) The following information is added to
-** the end of every EXTRA block for in-memory databases.
-**
-** This information could have been added directly to the PgHdr structure.
-** But then it would take up an extra 8 bytes of storage on every PgHdr
-** even for disk-based databases. Splitting it out saves 8 bytes. This
-** is only a savings of 0.8% but those percentages add up.
-*/
-typedef struct PgHistory PgHistory;
-struct PgHistory {
- u8 *pOrig; /* Original page text. Restore to this on a full rollback */
- u8 *pStmt; /* Text as it was at the beginning of the current statement */
- PgHdr *pNextStmt, *pPrevStmt; /* List of pages in the statement journal */
- u8 inStmt; /* TRUE if in the statement subjournal */
-};
-
/*
** A macro used for invoking the codec if there is one
*/
#ifdef SQLITE_HAS_CODEC
@@ -25416,17 +27925,8 @@
#else
# define CODEC1(P,D,N,X) /* NO-OP */
# define CODEC2(P,D,N,X) ((char*)D)
#endif
-
-/*
-** Convert a pointer to a PgHdr into a pointer to its data
-** and back again.
-*/
-#define PGHDR_TO_DATA(P) ((P)->pData)
-#define PGHDR_TO_EXTRA(G,P) ((void*)&((G)[1]))
-#define PGHDR_TO_HIST(P,PGR) \
- ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->nExtra])
/*
** A open page cache is an instance of the following structure.
**
@@ -25473,23 +27973,19 @@
int stmtNRec; /* Number of records in stmt subjournal */
int nExtra; /* Add this many bytes to each in-memory page */
int pageSize; /* Number of bytes in a page */
int nPage; /* Total number of in-memory pages */
- int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */
int mxPage; /* Maximum number of pages to hold in cache */
Pgno mxPgno; /* Maximum allowed size of the database */
Bitvec *pInJournal; /* One bit for each page in the database file */
Bitvec *pInStmt; /* One bit for each page in the database */
+ Bitvec *pAlwaysRollback; /* One bit for each page marked always-rollback */
char *zFilename; /* Name of the database file */
char *zJournal; /* Name of the journal file */
char *zDirectory; /* Directory hold database and journal files */
sqlite3_file *fd, *jfd; /* File descriptors for database and journal */
sqlite3_file *stfd; /* File descriptor for the statement subjournal*/
BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */
- PagerLruList lru; /* LRU list of free pages */
- PgHdr *pAll; /* List of all pages */
- PgHdr *pStmt; /* List of pages in the statement subjournal */
- PgHdr *pDirty; /* List of all dirty pages */
i64 journalOff; /* Current byte offset in the journal file */
i64 journalHdr; /* Byte offset to previous journal header */
i64 stmtHdrOff; /* First journal header written this statement */
i64 stmtCksum; /* cksumInit when statement was started */
@@ -25498,25 +27994,17 @@
#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() */
#endif
- int nHash; /* Size of the pager hash table */
- PgHdr **aHash; /* Hash table to map page number to PgHdr */
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- Pager *pNext; /* Doubly linked list of pagers on which */
- Pager *pPrev; /* sqlite3_release_memory() will work */
- volatile int iInUseMM; /* Non-zero if unavailable to MM */
- volatile int iInUseDB; /* Non-zero if in sqlite3_release_memory() */
-#endif
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
char dbFileVers[16]; /* Changes whenever database file changes */
i64 journalSizeLimit; /* Size limit for persistent journal files */
+ PCache *pPCache; /* Pointer to page cache object */
};
/*
** The following global variables hold counters used for
@@ -25526,24 +28014,13 @@
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */
SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */
SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */
-SQLITE_API int sqlite3_pager_pgfree_count = 0; /* Number of cache pages freed */
# define PAGER_INCR(v) v++
#else
# define PAGER_INCR(v)
#endif
-/*
-** The following variable points to the head of a double-linked list
-** of all pagers that are eligible for page stealing by the
-** sqlite3_release_memory() interface. Access to this list is
-** protected by the SQLITE_MUTEX_STATIC_MEM2 mutex.
-*/
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-static Pager *sqlite3PagerList = 0;
-static PagerLruList sqlite3LruPageList = {0, 0, 0};
-#endif
/*
** Journal files begin with the following magic string. The data
@@ -25612,218 +28089,15 @@
*/
#define PAGER_MAX_PGNO 2147483647
/*
-** The pagerEnter() and pagerLeave() routines acquire and release
-** a mutex on each pager. The mutex is recursive.
-**
-** This is a special-purpose mutex. It only provides mutual exclusion
-** between the Btree and the Memory Management sqlite3_release_memory()
-** function. It does not prevent, for example, two Btrees from accessing
-** the same pager at the same time. Other general-purpose mutexes in
-** the btree layer handle that chore.
-*/
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- static void pagerEnter(Pager *p){
- p->iInUseDB++;
- if( p->iInUseMM && p->iInUseDB==1 ){
-#ifndef SQLITE_MUTEX_NOOP
- sqlite3_mutex *mutex;
- mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
- p->iInUseDB = 0;
- sqlite3_mutex_enter(mutex);
- p->iInUseDB = 1;
- sqlite3_mutex_leave(mutex);
- }
- assert( p->iInUseMM==0 );
- }
- static void pagerLeave(Pager *p){
- p->iInUseDB--;
- assert( p->iInUseDB>=0 );
- }
-#else
-# define pagerEnter(X)
-# define pagerLeave(X)
-#endif
-
-/*
-** Add page pPg to the end of the linked list managed by structure
-** pList (pPg becomes the last entry in the list - the most recently
-** used). Argument pLink should point to either pPg->free or pPg->gfree,
-** depending on whether pPg is being added to the pager-specific or
-** global LRU list.
-*/
-static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){
- pLink->pNext = 0;
- pLink->pPrev = pList->pLast;
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- assert(pLink==&pPg->free || pLink==&pPg->gfree);
- assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
-#endif
-
- if( pList->pLast ){
- int iOff = (char *)pLink - (char *)pPg;
- PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)[iOff]);
- pLastLink->pNext = pPg;
- }else{
- assert(!pList->pFirst);
- pList->pFirst = pPg;
- }
-
- pList->pLast = pPg;
- if( !pList->pFirstSynced && pPg->needSync==0 ){
- pList->pFirstSynced = pPg;
- }
-}
-
-/*
-** Remove pPg from the list managed by the structure pointed to by pList.
-**
-** Argument pLink should point to either pPg->free or pPg->gfree, depending
-** on whether pPg is being added to the pager-specific or global LRU list.
-*/
-static void listRemove(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){
- int iOff = (char *)pLink - (char *)pPg;
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- assert(pLink==&pPg->free || pLink==&pPg->gfree);
- assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
-#endif
-
- if( pPg==pList->pFirst ){
- pList->pFirst = pLink->pNext;
- }
- if( pPg==pList->pLast ){
- pList->pLast = pLink->pPrev;
- }
- if( pLink->pPrev ){
- PagerLruLink *pPrevLink = (PagerLruLink *)(&((u8 *)pLink->pPrev)[iOff]);
- pPrevLink->pNext = pLink->pNext;
- }
- if( pLink->pNext ){
- PagerLruLink *pNextLink = (PagerLruLink *)(&((u8 *)pLink->pNext)[iOff]);
- pNextLink->pPrev = pLink->pPrev;
- }
- if( pPg==pList->pFirstSynced ){
- PgHdr *p = pLink->pNext;
- while( p && p->needSync ){
- PagerLruLink *pL = (PagerLruLink *)(&((u8 *)p)[iOff]);
- p = pL->pNext;
- }
- pList->pFirstSynced = p;
- }
-
- pLink->pNext = pLink->pPrev = 0;
-}
-
-/*
-** Add page pPg to the list of free pages for the pager. If
-** memory-management is enabled, also add the page to the global
-** list of free pages.
-*/
-static void lruListAdd(PgHdr *pPg){
- listAdd(&pPg->pPager->lru, &pPg->free, pPg);
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( !pPg->pPager->memDb ){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- listAdd(&sqlite3LruPageList, &pPg->gfree, pPg);
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- }
-#endif
-}
-
-/*
-** Remove page pPg from the list of free pages for the associated pager.
-** If memory-management is enabled, also remove pPg from the global list
-** of free pages.
-*/
-static void lruListRemove(PgHdr *pPg){
- listRemove(&pPg->pPager->lru, &pPg->free, pPg);
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( !pPg->pPager->memDb ){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- listRemove(&sqlite3LruPageList, &pPg->gfree, pPg);
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- }
-#endif
-}
-
-/*
-** This function is called just after the needSync flag has been cleared
-** from all pages managed by pPager (usually because the journal file
-** has just been synced). It updates the pPager->lru.pFirstSynced variable
-** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced
-** variable also.
-*/
-static void lruListSetFirstSynced(Pager *pPager){
- pPager->lru.pFirstSynced = pPager->lru.pFirst;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( !pPager->memDb ){
- PgHdr *p;
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext);
- assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced);
- sqlite3LruPageList.pFirstSynced = p;
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- }
-#endif
-}
-
-/*
** Return true if page *pPg has already been written to the statement
** journal (or statement snapshot has been created, if *pPg is part
** of an in-memory database).
*/
static int pageInStatement(PgHdr *pPg){
Pager *pPager = pPg->pPager;
- if( MEMDB ){
- return PGHDR_TO_HIST(pPg, pPager)->inStmt;
- }else{
- return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
- }
-}
-
-/*
-** Change the size of the pager hash table to N. N must be a power
-** of two.
-*/
-static void pager_resize_hash_table(Pager *pPager, int N){
- PgHdr **aHash, *pPg;
- assert( N>0 && (N&(N-1))==0 );
-#ifdef SQLITE_MALLOC_SOFT_LIMIT
- if( N*sizeof(aHash[0])>SQLITE_MALLOC_SOFT_LIMIT ){
- N = SQLITE_MALLOC_SOFT_LIMIT/sizeof(aHash[0]);
- }
- if( N==pPager->nHash ) return;
-#endif
- pagerLeave(pPager);
- if( pPager->aHash!=0 ) sqlite3BeginBenignMalloc();
- aHash = sqlite3MallocZero( sizeof(aHash[0])*N );
- if( pPager->aHash!=0 ) sqlite3EndBenignMalloc();
- pagerEnter(pPager);
- if( aHash==0 ){
- /* Failure to rehash is not an error. It is only a performance hit. */
- return;
- }
- sqlite3_free(pPager->aHash);
- pPager->nHash = N;
- pPager->aHash = aHash;
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- int h;
- if( pPg->pgno==0 ){
- assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
- continue;
- }
- h = pPg->pgno & (N-1);
- pPg->pNextHash = aHash[h];
- if( aHash[h] ){
- aHash[h]->pPrevHash = pPg;
- }
- aHash[h] = pPg;
- pPg->pPrevHash = 0;
- }
+ return sqlite3BitvecTest(pPager->pInStmt, pPg->pgno);
}
/*
** Read a 32-bit integer from the given file descriptor. Store the integer
@@ -25933,9 +28207,11 @@
rc2==SQLITE_IOERR ||
rc2==SQLITE_CORRUPT
){
pPager->errCode = rc;
- if( pPager->state==PAGER_UNLOCK && pPager->nRef==0 ){
+ if( pPager->state==PAGER_UNLOCK
+ && sqlite3PcacheRefCount(pPager->pPCache)==0
+ ){
/* If the pager is already unlocked, call pager_unlock() now to
** clear the error state and ensure that the pager-cache is
** completely empty.
*/
@@ -25962,10 +28238,12 @@
}
return hash;
}
static u32 pager_pagehash(PgHdr *pPage){
- return pager_datahash(pPage->pPager->pageSize,
- (unsigned char *)PGHDR_TO_DATA(pPage));
+ return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
+}
+static u32 pager_set_pagehash(PgHdr *pPage){
+ pPage->pageHash = pager_pagehash(pPage);
}
/*
** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
@@ -25974,17 +28252,17 @@
*/
#define CHECK_PAGE(x) checkPage(x)
static void checkPage(PgHdr *pPg){
Pager *pPager = pPg->pPager;
- assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty ||
- pPg->pageHash==pager_pagehash(pPg) );
+ assert( !pPg->pageHash || pPager->errCode
+ || (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
}
#else
#define pager_datahash(X,Y) 0
#define pager_pagehash(X) 0
#define CHECK_PAGE(x)
-#endif
+#endif /* SQLITE_CHECK_PAGES */
/*
** When this is called the journal file for pager pPager must be open.
** The master journal file name is read from the end of the file and
@@ -26004,9 +28282,9 @@
int rc;
u32 len;
i64 szJ;
u32 cksum;
- int i;
+ u32 u; /* Unsigned loop counter */
unsigned char aMagic[8]; /* A buffer to hold the magic header */
zMaster[0] = '\0';
@@ -26032,10 +28310,10 @@
}
zMaster[len] = '\0';
/* See if the checksum matches the master journal name */
- for(i=0; i<len; i++){
- cksum -= zMaster[i];
+ for(u=0; u<len; u++){
+ cksum -= zMaster[u];
}
if( cksum ){
/* If the checksum doesn't add up, then one or more of the disk sectors
** containing the master journal filename is corrupted. This means
@@ -26081,9 +28359,9 @@
** transaction.
*/
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;
@@ -26168,9 +28446,9 @@
** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
** 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);
}else{
@@ -26300,9 +28578,10 @@
i64 jrnlSize;
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);
for(i=0; i<len; i++){
@@ -26353,42 +28632,14 @@
return rc;
}
/*
-** Add or remove a page from the list of all pages that are in the
-** statement journal.
-**
-** The Pager keeps a separate list of pages that are currently in
-** the statement journal. This helps the sqlite3PagerStmtCommit()
-** routine run MUCH faster for the common case where there are many
-** pages in memory but only a few are in the statement journal.
-*/
-static void page_add_to_stmt_list(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- assert( MEMDB );
- if( !pHist->inStmt ){
- assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 );
- if( pPager->pStmt ){
- PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg;
- }
- pHist->pNextStmt = pPager->pStmt;
- pPager->pStmt = pPg;
- pHist->inStmt = 1;
- }
-}
-
-/*
** Find a page in the hash table given its page number. Return
** a pointer to the page or NULL if not found.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
PgHdr *p;
- if( pPager->aHash==0 ) return 0;
- p = pPager->aHash[pgno & (pPager->nHash-1)];
- while( p && p->pgno!=pgno ){
- p = p->pNextHash;
- }
+ sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &p);
return p;
}
/*
@@ -26397,29 +28648,10 @@
** opened. Any outstanding pages are invalidated and subsequent attempts
** to access those pages will likely result in a coredump.
*/
static void pager_reset(Pager *pPager){
- PgHdr *pPg, *pNext;
if( pPager->errCode ) return;
- for(pPg=pPager->pAll; pPg; pPg=pNext){
- IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
- PAGER_INCR(sqlite3_pager_pgfree_count);
- pNext = pPg->pNextAll;
- lruListRemove(pPg);
- sqlite3PageFree(pPg->pData);
- sqlite3_free(pPg);
- }
- assert(pPager->lru.pFirst==0);
- assert(pPager->lru.pFirstSynced==0);
- assert(pPager->lru.pLast==0);
- pPager->pStmt = 0;
- pPager->pAll = 0;
- pPager->pDirty = 0;
- pPager->nHash = 0;
- sqlite3_free(pPager->aHash);
- pPager->nPage = 0;
- pPager->aHash = 0;
- pPager->nRef = 0;
+ sqlite3PcacheClear(pPager->pPCache);
}
/*
** Unlock the database file.
@@ -26431,50 +28663,48 @@
** treated as a hot-journal and rolled back.
*/
static void pager_unlock(Pager *pPager){
if( !pPager->exclusiveMode ){
- if( !MEMDB ){
- int rc = osUnlock(pPager->fd, NO_LOCK);
- if( rc ) pPager->errCode = rc;
- pPager->dbSize = -1;
- IOTRACE(("UNLOCK %p\n", pPager))
-
- /* Always close the journal file when dropping the database lock.
- ** Otherwise, another connection with journal_mode=delete might
- ** delete the file out from under us.
- */
- if( pPager->journalOpen ){
- sqlite3OsClose(pPager->jfd);
- pPager->journalOpen = 0;
- sqlite3BitvecDestroy(pPager->pInJournal);
- pPager->pInJournal = 0;
- }
-
- /* 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;
- }
- }
-
- if( !MEMDB || pPager->errCode==SQLITE_OK ){
- pPager->state = PAGER_UNLOCK;
- pPager->changeCountDone = 0;
- }
+ 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;
+ }
+
+ pPager->state = PAGER_UNLOCK;
+ pPager->changeCountDone = 0;
}
}
/*
@@ -26482,19 +28712,14 @@
** database file. If the pager has already entered the error state,
** do not attempt the rollback.
*/
static void pagerUnlockAndRollback(Pager *p){
- /* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */
if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){
sqlite3BeginBenignMalloc();
sqlite3PagerRollback(p);
sqlite3EndBenignMalloc();
}
pager_unlock(p);
-#if 0
- assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );
- assert( p->errCode || !p->stmtOpen || p->exclusiveMode );
-#endif
}
/*
** This routine ends a transaction. A transaction is ended by either
@@ -26513,12 +28738,10 @@
** This might give a performance improvement on windows where opening
** a file is an expensive operation.
*/
static int pager_end_transaction(Pager *pPager, int hasMaster){
- PgHdr *pPg;
- int rc = SQLITE_OK;
- int rc2 = SQLITE_OK;
- assert( !MEMDB );
+ int rc = SQLITE_OK;
+ int rc2 = SQLITE_OK;
if( pPager->state<PAGER_RESERVED ){
return SQLITE_OK;
}
sqlite3PagerStmtCommit(pPager);
@@ -26526,16 +28749,28 @@
sqlite3OsClose(pPager->stfd);
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);
pager_error(pPager, rc);
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 ){
rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
@@ -26542,18 +28777,17 @@
}
}
sqlite3BitvecDestroy(pPager->pInJournal);
pPager->pInJournal = 0;
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- pPg->inJournal = 0;
- pPg->dirty = 0;
- pPg->needSync = 0;
- pPg->alwaysRollback = 0;
+ sqlite3BitvecDestroy(pPager->pAlwaysRollback);
+ pPager->pAlwaysRollback = 0;
+ sqlite3PcacheCleanAll(pPager->pPCache);
#ifdef SQLITE_CHECK_PAGES
- pPg->pageHash = pager_pagehash(pPg);
-#endif
- }
- pPager->pDirty = 0;
+ sqlite3PcacheIterate(pPager->pPCache, pager_set_pagehash);
+#endif
+ sqlite3PcacheClearFlags(pPager->pPCache,
+ PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC
+ );
pPager->dirtyCache = 0;
pPager->nRec = 0;
}else{
assert( pPager->pInJournal==0 );
@@ -26567,10 +28801,12 @@
}
pPager->origDbSize = 0;
pPager->setMaster = 0;
pPager->needSync = 0;
- lruListSetFirstSynced(pPager);
- pPager->dbSize = -1;
+ /* lruListSetFirstSynced(pPager); */
+ if( !MEMDB ){
+ pPager->dbSize = -1;
+ }
pPager->dbModified = 0;
return (rc==SQLITE_OK?rc2:rc);
}
@@ -26611,28 +28847,28 @@
/*
** Read a single page from the journal file opened on file descriptor
** jfd. Playback this one page.
**
-** If useCksum==0 it means this journal does not use checksums. Checksums
-** are not used in statement journals because statement journals do not
-** need to survive power failures.
+** The isMainJrnl flag is true if this is the main rollback journal and
+** false for the statement journal. The main rollback journal uses
+** checksums - the statement journal does not.
*/
static int pager_playback_one_page(
- Pager *pPager,
- sqlite3_file *jfd,
- i64 offset,
- int useCksum
+ Pager *pPager, /* The pager being played back */
+ sqlite3_file *jfd, /* The file that is the journal being rolled back */
+ i64 offset, /* Offset of the page within the journal */
+ int isMainJrnl /* True for main rollback journal. False for Stmt jrnl */
){
int rc;
PgHdr *pPg; /* An existing page in the cache */
Pgno pgno; /* The page number of a page in journal */
u32 cksum; /* Checksum used for sanity checking */
u8 *aData = (u8 *)pPager->pTmpSpace; /* Temp storage for a page */
- /* useCksum should be true for the main journal and false for
+ /* isMainJrnl should be true for the main journal and false for
** statement journals. Verify that this is always the case
*/
- assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) );
+ assert( jfd == (isMainJrnl ? pPager->jfd : pPager->stfd) );
assert( aData );
rc = read32bits(jfd, offset, &pgno);
if( rc!=SQLITE_OK ) return rc;
@@ -26650,9 +28886,9 @@
}
if( pgno>(unsigned)pPager->dbSize ){
return SQLITE_OK;
}
- if( useCksum ){
+ if( isMainJrnl ){
rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum);
if( rc ) return rc;
pPager->journalOff += 4;
if( pager_cksum(pPager, aData)!=cksum ){
@@ -26696,15 +28932,14 @@
*/
pPg = pager_lookup(pPager, pgno);
PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));
- if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0)
- && pPager->fd->pMethods ){
- i64 offset = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset);
- if( pPg ){
- makeClean(pPg);
- }
+ if( (pPager->state>=PAGER_EXCLUSIVE)
+ && (pPg==0 || 0==(pPg->flags&PGHDR_NEED_SYNC))
+ && (pPager->fd->pMethods)
+ ){
+ i64 ofst = (pgno-1)*(i64)pPager->pageSize;
+ rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
}
if( pPg ){
/* No page should ever be explicitly rolled back that is in use, except
** for page 1 which is held in use in order to keep the lock on the
@@ -26712,14 +28947,14 @@
** of an internal error resulting in an automatic call to
** sqlite3PagerRollback().
*/
void *pData;
- /* assert( pPg->nRef==0 || pPg->pgno==1 ); */
- pData = PGHDR_TO_DATA(pPg);
+ 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
pPg->pageHash = pager_pagehash(pPg);
#endif
/* If this was page 1, then restore the value of Pager.dbFileVers.
@@ -26729,8 +28964,9 @@
}
/* Decode the page just read from disk */
CODEC1(pPager, pData, pPg->pgno, 3);
+ sqlite3PcacheRelease(pPg);
}
return rc;
}
@@ -26956,9 +29192,9 @@
static int pager_playback(Pager *pPager, int isHot){
sqlite3_vfs *pVfs = pPager->pVfs;
i64 szJ; /* Size of the journal file in bytes */
u32 nRec; /* Number of Records in the journal */
- u32 i; /* Loop counter */
+ u32 u; /* Unsigned loop counter */
Pgno mxPg = 0; /* Size of the original file in pages */
int rc; /* Result code of a subroutine */
int res = 1; /* Value returned by sqlite3OsAccess() */
char *zMaster = 0; /* Name of master journal file if any */
@@ -27039,16 +29275,21 @@
}
/* Copy original pages out of the journal and back into the database file.
*/
- for(i=0; i<nRec; i++){
+ for(u=0; u<nRec; u++){
rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
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;
}
}
}
@@ -27063,9 +29304,9 @@
}
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.
*/
rc = pager_delmaster(pPager, zMaster);
@@ -27182,13 +29423,9 @@
/*
** Change the maximum number of in-memory pages that are allowed.
*/
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
- if( mxPage>10 ){
- pPager->mxPage = mxPage;
- }else{
- pPager->mxPage = 10;
- }
+ sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
}
/*
** Adjust the robustness of the database to damage due to OS crashes
@@ -27216,12 +29453,12 @@
** Numeric values associated with these states are OFF==1, NORMAL=2,
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int full_fsync){
+SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){
pPager->noSync = level==1 || pPager->tempFile;
pPager->fullSync = level==3 && !pPager->tempFile;
- pPager->sync_flags = (full_fsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
+ pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
if( pPager->noSync ) pPager->needSync = 0;
}
#endif
@@ -27258,8 +29495,10 @@
assert( rc!=SQLITE_OK || pFile->pMethods );
return rc;
}
+static int pagerStress(void *,PgHdr *);
+
/*
** Create a new page cache and put a pointer to the page cache in *ppPager.
** The file to be cached need not exist. The file is not locked until
** the first call to sqlite3PagerGet() and is only held open until the
@@ -27289,12 +29528,19 @@
int memDb = 0;
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;
@@ -27326,22 +29572,25 @@
/* Allocate memory for the pager structure */
pPager = sqlite3MallocZero(
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 ){
sqlite3_free(zPathname);
return SQLITE_NOMEM;
}
- pPtr = (u8 *)&pPager[1];
+ pPager->pPCache = (PCache *)&pPager[1];
+ 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;
if( zPathname ){
@@ -27389,12 +29638,16 @@
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
}
}
}
- }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;
}
@@ -27412,8 +29665,11 @@
sqlite3OsClose(pPager->fd);
sqlite3_free(pPager);
return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
}
+ nExtra = FORCE_ALIGNMENT(nExtra);
+ sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
+ !memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(pPager->fd), pPager->zFilename);
IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
@@ -27430,9 +29686,9 @@
pPager->zJournal = 0;
}
/* pPager->journalOpen = 0; */
- pPager->useJournal = useJournal && !memDb;
+ pPager->useJournal = useJournal;
pPager->noReadlock = noReadlock && readOnly;
/* pPager->stmtOpen = 0; */
/* pPager->stmtInUse = 0; */
/* pPager->nRef = 0; */
@@ -27459,35 +29715,18 @@
pPager->sync_flags = SQLITE_SYNC_NORMAL;
/* pPager->pFirst = 0; */
/* pPager->pFirstSynced = 0; */
/* pPager->pLast = 0; */
- pPager->nExtra = FORCE_ALIGNMENT(nExtra);
+ 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)); */
*ppPager = pPager;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- pPager->iInUseMM = 0;
- pPager->iInUseDB = 0;
- if( !memDb ){
-#ifndef SQLITE_MUTEX_NOOP
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
- sqlite3_mutex_enter(mutex);
- pPager->pNext = sqlite3PagerList;
- if( sqlite3PagerList ){
- assert( sqlite3PagerList->pPrev==0 );
- sqlite3PagerList->pPrev = pPager;
- }
- pPager->pPrev = 0;
- sqlite3PagerList = pPager;
- sqlite3_mutex_leave(mutex);
- }
-#endif
return SQLITE_OK;
}
/*
@@ -27497,27 +29736,15 @@
pPager->pBusyHandler = pBusyHandler;
}
/*
-** Set the destructor for this pager. If not NULL, the destructor is called
-** when the reference count on each page reaches zero. The destructor can
-** be used to clean up information in the extra segment appended to each page.
-**
-** The destructor is not called as a result sqlite3PagerClose().
-** Destructors are only called by sqlite3PagerUnref().
-*/
-SQLITE_PRIVATE void sqlite3PagerSetDestructor(Pager *pPager, void (*xDesc)(DbPage*,int)){
- pPager->xDestructor = xDesc;
-}
-
-/*
** Set the reinitializer for this pager. If not NULL, the reinitializer
** is called when the content of a page in cache is restored to its original
** value as a result of a rollback. The callback gives higher-level code
** 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;
}
/*
@@ -27525,28 +29752,30 @@
** inappropriate, then an alternative page size is set to that
** 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 && pPager->nRef==0
- ){
- char *pNew = (char *)sqlite3PageMalloc(pageSize);
- if( !pNew ){
- rc = SQLITE_NOMEM;
- }else{
- pagerEnter(pPager);
- pager_reset(pPager);
- pPager->pageSize = pageSize;
- setSectorSize(pPager);
- sqlite3PageFree(pPager->pTmpSpace);
- pPager->pTmpSpace = pNew;
- pagerLeave(pPager);
- }
- }
- *pPageSize = pPager->pageSize;
+ 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;
+ }
return rc;
}
/*
@@ -27612,9 +29841,9 @@
*/
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);
if( rc==SQLITE_IOERR_SHORT_READ ){
@@ -27637,19 +29866,18 @@
i64 n = 0;
int rc;
assert( pPager!=0 );
if( pPager->errCode ){
- return pPager->errCode;
+ rc = pPager->errCode;
+ return rc;
}
if( pPager->dbSize>=0 ){
n = pPager->dbSize;
} else {
assert(pPager->fd->pMethods||pPager->tempFile);
if( (pPager->fd->pMethods)
&& (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
- pPager->nRef++;
- pager_error(pPager, rc);
- pPager->nRef--;
+ pager_error(pPager, rc);
return rc;
}
if( n>0 && n<pPager->pageSize ){
n = 1;
@@ -27671,69 +29899,12 @@
}
return SQLITE_OK;
}
-
-#ifndef SQLITE_OMIT_MEMORYDB
-/*
-** Clear a PgHistory block
-*/
-static void clearHistory(PgHistory *pHist){
- sqlite3PageFree(pHist->pOrig);
- sqlite3PageFree(pHist->pStmt);
- pHist->pOrig = 0;
- pHist->pStmt = 0;
-}
-#else
-#define clearHistory(x)
-#endif
-
/*
** Forward declaration
*/
static int syncJournal(Pager*);
-
-/*
-** Unlink pPg from its hash chain. Also set the page number to 0 to indicate
-** that the page is not part of any hash chain. This is required because the
-** sqlite3PagerMovepage() routine can leave a page in the
-** pNextFree/pPrevFree list that is not a part of any hash-chain.
-*/
-static void unlinkHashChain(Pager *pPager, PgHdr *pPg){
- if( pPg->pgno==0 ){
- assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
- return;
- }
- if( pPg->pNextHash ){
- pPg->pNextHash->pPrevHash = pPg->pPrevHash;
- }
- if( pPg->pPrevHash ){
- assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg );
- pPg->pPrevHash->pNextHash = pPg->pNextHash;
- }else{
- int h = pPg->pgno & (pPager->nHash-1);
- pPager->aHash[h] = pPg->pNextHash;
- }
- if( MEMDB ){
- clearHistory(PGHDR_TO_HIST(pPg, pPager));
- }
- pPg->pgno = 0;
- pPg->pNextHash = pPg->pPrevHash = 0;
-}
-
-/*
-** Unlink a page from the free list (the list of all pages where nRef==0)
-** and from its hash collision chain.
-*/
-static void unlinkPage(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
-
- /* Unlink from free page list */
- lruListRemove(pPg);
-
- /* Unlink from the pgno hash table */
- unlinkHashChain(pPager, pPg);
-}
/*
** This routine is used to truncate the cache when a database
** is truncated. Drop from the cache all pages whose pgno is
@@ -27746,35 +29917,9 @@
** that page and guarantee a subsequent segfault, it seems better
** to zero it and hope that we error out sanely.
*/
static void pager_truncate_cache(Pager *pPager){
- PgHdr *pPg;
- PgHdr **ppPg;
- int dbSize = pPager->dbSize;
-
- ppPg = &pPager->pAll;
- while( (pPg = *ppPg)!=0 ){
- if( pPg->pgno<=dbSize ){
- ppPg = &pPg->pNextAll;
- }else if( pPg->nRef>0 ){
- memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
- ppPg = &pPg->pNextAll;
- }else{
- *ppPg = pPg->pNextAll;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( *ppPg ){
- (*ppPg)->pPrevAll = pPg->pPrevAll;
- }
-#endif
- IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
- PAGER_INCR(sqlite3_pager_pgfree_count);
- unlinkPage(pPg);
- makeClean(pPg);
- sqlite3PageFree(pPg->pData);
- sqlite3_free(pPg);
- pPager->nPage--;
- }
- }
+ sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
}
/*
** Try to obtain a lock on a file. Invoke the busy callback if the lock
@@ -27792,9 +29937,9 @@
assert( PAGER_RESERVED==RESERVED_LOCK );
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;
}else{
@@ -27813,39 +29958,25 @@
/*
** Truncate the file to the number of pages specified.
*/
SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
- int rc;
- assert( pPager->state>=PAGER_SHARED || MEMDB );
+ int rc = SQLITE_OK;
+ assert( pPager->state>=PAGER_SHARED );
+
sqlite3PagerPagecount(pPager, 0);
if( pPager->errCode ){
rc = pPager->errCode;
- return rc;
- }
- if( nPage>=(unsigned)pPager->dbSize ){
- return SQLITE_OK;
- }
- if( MEMDB ){
- pPager->dbSize = nPage;
- pager_truncate_cache(pPager);
- return SQLITE_OK;
- }
- pagerEnter(pPager);
- rc = syncJournal(pPager);
- pagerLeave(pPager);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Get an exclusive lock on the database before truncating. */
- pagerEnter(pPager);
- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
- pagerLeave(pPager);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- rc = pager_truncate(pPager, nPage);
+ }else if( nPage<(unsigned)pPager->dbSize ){
+ rc = syncJournal(pPager);
+ if( rc==SQLITE_OK ){
+ /* Get an exclusive lock on the database before truncating. */
+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pager_truncate(pPager, nPage);
+ }
+ }
+
return rc;
}
/*
@@ -27862,32 +29993,17 @@
** a hot journal may be left in the filesystem but no error is returned
** to the caller.
*/
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( !MEMDB ){
-#ifndef SQLITE_MUTEX_NOOP
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
- sqlite3_mutex_enter(mutex);
- if( pPager->pPrev ){
- pPager->pPrev->pNext = pPager->pNext;
- }else{
- sqlite3PagerList = pPager->pNext;
- }
- if( pPager->pNext ){
- pPager->pNext->pPrev = pPager->pPrev;
- }
- sqlite3_mutex_leave(mutex);
- }
-#endif
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
pPager->errCode = 0;
pPager->exclusiveMode = 0;
pager_reset(pPager);
- pagerUnlockAndRollback(pPager);
+ if( !MEMDB ){
+ pagerUnlockAndRollback(pPager);
+ }
enable_simulated_io_errors();
sqlite3EndBenignMalloc();
PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
IOTRACE(("CLOSE %p\n", pPager))
@@ -27894,8 +30010,9 @@
if( pPager->journalOpen ){
sqlite3OsClose(pPager->jfd);
}
sqlite3BitvecDestroy(pPager->pInJournal);
+ sqlite3BitvecDestroy(pPager->pAlwaysRollback);
if( pPager->stmtOpen ){
sqlite3OsClose(pPager->stfd);
}
sqlite3OsClose(pPager->fd);
@@ -27904,10 +30021,10 @@
** sqlite3OsDelete(pPager->zFilename);
** }
*/
- sqlite3_free(pPager->aHash);
sqlite3PageFree(pPager->pTmpSpace);
+ sqlite3PcacheClose(pPager->pPCache);
sqlite3_free(pPager);
return SQLITE_OK;
}
@@ -27920,44 +30037,13 @@
}
#endif
/*
-** The page_ref() function increments the reference count for a page.
-** If the page is currently on the freelist (the reference count is zero) then
-** remove it from the freelist.
-**
-** For non-test systems, page_ref() is a macro that calls _page_ref()
-** online of the reference count is zero. For test systems, page_ref()
-** is a real function so that we can set breakpoints and trace it.
-*/
-static void _page_ref(PgHdr *pPg){
- if( pPg->nRef==0 ){
- /* The page is currently on the freelist. Remove it. */
- lruListRemove(pPg);
- pPg->pPager->nRef++;
- }
- pPg->nRef++;
-}
-#ifdef SQLITE_DEBUG
- static void page_ref(PgHdr *pPg){
- if( pPg->nRef==0 ){
- _page_ref(pPg);
- }else{
- pPg->nRef++;
- }
- }
-#else
-# define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++)
-#endif
-
-/*
** Increment the reference count for a page. The input pointer is
** a reference to the page data.
*/
SQLITE_PRIVATE int sqlite3PagerRef(DbPage *pPg){
- pagerEnter(pPg->pPager);
- page_ref(pPg);
- pagerLeave(pPg->pPager);
+ sqlite3PcacheRef(pPg);
return SQLITE_OK;
}
/*
@@ -27985,16 +30071,16 @@
** This routine clears the needSync field of every page current held in
** memory.
*/
static int syncJournal(Pager *pPager){
- PgHdr *pPg;
int rc = SQLITE_OK;
/* Sync the journal before modifying the main database
** (assuming there is a journal and it needs to be synced.)
*/
if( pPager->needSync ){
- if( !pPager->tempFile ){
+ assert( !pPager->tempFile );
+ if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
assert( pPager->journalOpen );
if( 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
@@ -28035,12 +30121,9 @@
pPager->needSync = 0;
/* Erase the needSync flag from every page.
*/
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- pPg->needSync = 0;
- }
- lruListSetFirstSynced(pPager);
+ sqlite3PcacheClearFlags(pPager->pPCache, PGHDR_NEED_SYNC);
}
#ifndef NDEBUG
/* If the Pager.needSync flag is clear then the PgHdr.needSync
@@ -28047,100 +30130,24 @@
** flag must also be clear for all pages. Verify that this
** invariant is true.
*/
else{
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- assert( pPg->needSync==0 );
- }
- assert( pPager->lru.pFirstSynced==pPager->lru.pFirst );
- }
-#endif
-
- return rc;
-}
-
-/*
-** Merge two lists of pages connected by pDirty and in pgno order.
-** Do not both fixing the pPrevDirty pointers.
-*/
-static PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB){
- PgHdr result, *pTail;
- pTail = &result;
- while( pA && pB ){
- if( pA->pgno<pB->pgno ){
- pTail->pDirty = pA;
- pTail = pA;
- pA = pA->pDirty;
- }else{
- pTail->pDirty = pB;
- pTail = pB;
- pB = pB->pDirty;
- }
- }
- if( pA ){
- pTail->pDirty = pA;
- }else if( pB ){
- pTail->pDirty = pB;
- }else{
- pTail->pDirty = 0;
- }
- return result.pDirty;
-}
-
-/*
-** Sort the list of pages in accending order by pgno. Pages are
-** connected by pDirty pointers. The pPrevDirty pointers are
-** corrupted by this sort.
-*/
-#define N_SORT_BUCKET_ALLOC 25
-#define N_SORT_BUCKET 25
-#ifdef SQLITE_TEST
- int sqlite3_pager_n_sort_bucket = 0;
- #undef N_SORT_BUCKET
- #define N_SORT_BUCKET \
- (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
-#endif
-static PgHdr *sort_pagelist(PgHdr *pIn){
- PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
- int i;
- memset(a, 0, sizeof(a));
- while( pIn ){
- p = pIn;
- pIn = p->pDirty;
- p->pDirty = 0;
- for(i=0; i<N_SORT_BUCKET-1; i++){
- if( a[i]==0 ){
- a[i] = p;
- break;
- }else{
- p = merge_pagelist(a[i], p);
- a[i] = 0;
- }
- }
- if( i==N_SORT_BUCKET-1 ){
- /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET)
- ** elements in the input list. This is possible, but impractical.
- ** Testing this line is the point of global variable
- ** sqlite3_pager_n_sort_bucket.
- */
- a[i] = merge_pagelist(a[i], p);
- }
- }
- p = a[0];
- for(i=1; i<N_SORT_BUCKET; i++){
- p = merge_pagelist(p, a[i]);
- }
- return p;
+ sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_NEED_SYNC);
+ }
+#endif
+
+ return rc;
}
/*
** Given a list of pages (connected by the PgHdr.pDirty pointer) write
-** every one of those pages out to the database file and mark them all
-** as clean.
+** every one of those pages out to the database file. No calls are made
+** to the page-cache to mark the pages as clean. It is the responsibility
+** of the caller to use PcacheCleanAll() or PcacheMakeClean() to mark
+** the pages as clean.
*/
static int pager_write_pagelist(PgHdr *pList){
Pager *pPager;
- PgHdr *p;
int rc;
if( pList==0 ) return SQLITE_OK;
pPager = pList->pPager;
@@ -28165,13 +30172,8 @@
if( rc!=SQLITE_OK ){
return rc;
}
- pList = sort_pagelist(pList);
- for(p=pList; p; p=p->pDirty){
- assert( p->dirty );
- p->dirty = 0;
- }
while( pList ){
/* If the file has not yet been opened, open it now. */
if( !pPager->fd->pMethods ){
@@ -28184,11 +30186,11 @@
** than Pager.dbSize, this means sqlite3PagerTruncate() was called to
** make the file smaller (presumably by auto-vacuum code). Do not write
** any such pages to the file.
*/
- if( pList->pgno<=pPager->dbSize ){
+ if( pList->pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
i64 offset = (pList->pgno-1)*(i64)pPager->pageSize;
- char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
+ char *pData = CODEC2(pPager, pList->pData, pList->pgno, 6);
PAGERTRACE4("STORE %d page %d hash(%08x)\n",
PAGERID(pPager), pList->pgno, pager_pagehash(pList));
IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno));
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
@@ -28208,32 +30210,54 @@
pList->pageHash = pager_pagehash(pList);
#endif
pList = pList->pDirty;
}
- return SQLITE_OK;
-}
-
-/*
-** Collect every dirty page into a dirty list and
-** return a pointer to the head of that list. All pages are
-** collected even if they are still in use.
-*/
-static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
-
-#ifndef NDEBUG
- /* Verify the sanity of the dirty list when we are running
- ** in debugging mode. This is expensive, so do not
- ** do this on a normal build. */
- int n1 = 0;
- int n2 = 0;
- PgHdr *p;
- for(p=pPager->pAll; p; p=p->pNextAll){ if( p->dirty ) n1++; }
- for(p=pPager->pDirty; p; p=p->pDirty){ n2++; }
- assert( n1==n2 );
-#endif
-
- return pPager->pDirty;
-}
+
+ return SQLITE_OK;
+}
+
+/*
+** This function is called by the pcache layer when it has reached some
+** soft memory limit. The argument is a pointer to a purgeable Pager
+** object. This function attempts to make a single dirty page that has no
+** outstanding references (if one exists) clean so that it can be recycled
+** by the pcache layer.
+*/
+static int pagerStress(void *p, PgHdr *pPg){
+ Pager *pPager = (Pager *)p;
+ int rc = SQLITE_OK;
+
+ if( pPager->doNotSync ){
+ return SQLITE_OK;
+ }
+
+ assert( pPg->flags&PGHDR_DIRTY );
+ if( pPager->errCode==SQLITE_OK ){
+ if( pPg->flags&PGHDR_NEED_SYNC ){
+ rc = syncJournal(pPager);
+ if( rc==SQLITE_OK && pPager->fullSync &&
+ !(pPager->journalMode==PAGER_JOURNALMODE_MEMORY) &&
+ !(sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
+ ){
+ pPager->nRec = 0;
+ rc = writeJournalHdr(pPager);
+ }
+ }
+ if( rc==SQLITE_OK ){
+ pPg->pDirty = 0;
+ rc = pager_write_pagelist(pPg);
+ }
+ if( rc!=SQLITE_OK ){
+ pager_error(pPager, rc);
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ sqlite3PcacheMakeClean(pPg);
+ }
+ return rc;
+}
+
/*
** Return 1 if there is a hot journal on the given pager.
** A hot journal is one that needs to be played back.
@@ -28252,260 +30276,34 @@
** journal file exists and is not empty this routine assumes it
** is hot. The pager_playback() routine will discover that the
** journal file is not really hot and will no-op.
*/
-static int hasHotJournal(Pager *pPager){
+static int hasHotJournal(Pager *pPager, int *pExists){
sqlite3_vfs *pVfs = pPager->pVfs;
- int res = 0;
- if( pPager->useJournal && pPager->fd->pMethods ){
- int rc;
- int exists;
- int locked;
-
- rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
- if( rc==SQLITE_OK && exists ){
- rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
- }
-
- if( rc==SQLITE_OK && exists && !locked ){
- int nPage;
- rc = sqlite3PagerPagecount(pPager, &nPage);
- if( rc==SQLITE_OK && nPage==0 ){
+ int rc = SQLITE_OK;
+ int exists;
+ int locked;
+ assert( pPager!=0 );
+ assert( pPager->useJournal );
+ assert( pPager->fd->pMethods );
+ *pExists = 0;
+ rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
+ if( rc==SQLITE_OK && exists ){
+ rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
+ }
+ if( rc==SQLITE_OK && exists && !locked ){
+ int nPage;
+ rc = sqlite3PagerPagecount(pPager, &nPage);
+ if( rc==SQLITE_OK ){
+ if( nPage==0 ){
sqlite3OsDelete(pVfs, pPager->zJournal, 0);
- exists = 0;
- }
- }
-
- res = (rc!=SQLITE_OK ? -1 : (exists && !locked));
- }
-
- return res;
-}
-
-/*
-** Try to find a page in the cache that can be recycled.
-**
-** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It
-** does not set the pPager->errCode variable.
-*/
-static int pager_recycle(Pager *pPager, PgHdr **ppPg){
- PgHdr *pPg;
- *ppPg = 0;
-
- /* It is illegal to call this function unless the pager object
- ** pointed to by pPager has at least one free page (page with nRef==0).
- */
- assert(!MEMDB);
- assert(pPager->lru.pFirst);
-
- /* Find a page to recycle. Try to locate a page that does not
- ** require us to do an fsync() on the journal.
- */
- pPg = pPager->lru.pFirstSynced;
-
- /* If we could not find a page that does not require an fsync()
- ** on the journal file then fsync the journal file. This is a
- ** very slow operation, so we work hard to avoid it. But sometimes
- ** it can't be helped.
- */
- if( pPg==0 && pPager->lru.pFirst ){
- if( !pPager->errCode ){
- int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
- int rc = syncJournal(pPager);
- if( rc!=0 ){
- return rc;
- }
- if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
- /* If in full-sync mode, write a new journal header into the
- ** journal file. This is done to avoid ever modifying a journal
- ** header that is involved in the rollback of pages that have
- ** already been written to the database (in case the header is
- ** trashed when the nRec field is updated).
- */
- pPager->nRec = 0;
- assert( pPager->journalOff > 0 );
- assert( pPager->doNotSync==0 );
- rc = writeJournalHdr(pPager);
- if( rc!=0 ){
- return rc;
- }
- }
- }
- pPg = pPager->lru.pFirst;
- }
-
- assert( pPg->nRef==0 );
-
- /* Write the page to the database file if it is dirty.
- */
- if( pPg->dirty && !pPager->errCode ){
- int rc;
- assert( pPg->needSync==0 );
- makeClean(pPg);
- pPg->dirty = 1;
- pPg->pDirty = 0;
- rc = pager_write_pagelist( pPg );
- pPg->dirty = 0;
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- assert( pPg->dirty==0 || pPager->errCode );
-
- /* If the page we are recycling is marked as alwaysRollback, then
- ** set the global alwaysRollback flag, thus disabling the
- ** sqlite3PagerDontRollback() optimization for the rest of this transaction.
- ** It is necessary to do this because the page marked alwaysRollback
- ** might be reloaded at a later time but at that point we won't remember
- ** that is was marked alwaysRollback. This means that all pages must
- ** be marked as alwaysRollback from here on out.
- */
- if( pPg->alwaysRollback ){
- IOTRACE(("ALWAYS_ROLLBACK %p\n", pPager))
- pPager->alwaysRollback = 1;
- }
-
- /* Unlink the old page from the free list and the hash table
- */
- unlinkPage(pPg);
- assert( pPg->pgno==0 );
-
- *ppPg = pPg;
- return SQLITE_OK;
-}
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-/*
-** This function is called to free superfluous dynamically allocated memory
-** held by the pager system. Memory in use by any SQLite pager allocated
-** by the current thread may be sqlite3_free()ed.
-**
-** nReq is the number of bytes of memory required. Once this much has
-** been released, the function returns. The return value is the total number
-** of bytes of memory released.
-*/
-SQLITE_PRIVATE int sqlite3PagerReleaseMemory(int nReq){
- int nReleased = 0; /* Bytes of memory released so far */
- Pager *pPager; /* For looping over pagers */
- BusyHandler *savedBusy; /* Saved copy of the busy handler */
- int rc = SQLITE_OK;
-
- /* Acquire the memory-management mutex
- */
-#ifndef SQLITE_MUTEX_NOOP
- sqlite3_mutex *mutex; /* The MEM2 mutex */
- mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
- sqlite3_mutex_enter(mutex);
-
- /* Signal all database connections that memory management wants
- ** to have access to the pagers.
- */
- for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
- pPager->iInUseMM = 1;
- }
-
- while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){
- PgHdr *pPg;
- PgHdr *pRecycled;
-
- /* Try to find a page to recycle that does not require a sync(). If
- ** this is not possible, find one that does require a sync().
- */
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- pPg = sqlite3LruPageList.pFirstSynced;
- while( pPg && (pPg->needSync || pPg->pPager->iInUseDB) ){
- pPg = pPg->gfree.pNext;
- }
- if( !pPg ){
- pPg = sqlite3LruPageList.pFirst;
- while( pPg && pPg->pPager->iInUseDB ){
- pPg = pPg->gfree.pNext;
- }
- }
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
-
- /* If pPg==0, then the block above has failed to find a page to
- ** recycle. In this case return early - no further memory will
- ** be released.
- */
- if( !pPg ) break;
-
- pPager = pPg->pPager;
- assert(!pPg->needSync || pPg==pPager->lru.pFirst);
- assert(pPg->needSync || pPg==pPager->lru.pFirstSynced);
-
- savedBusy = pPager->pBusyHandler;
- pPager->pBusyHandler = 0;
- rc = pager_recycle(pPager, &pRecycled);
- pPager->pBusyHandler = savedBusy;
- assert(pRecycled==pPg || rc!=SQLITE_OK);
- if( rc==SQLITE_OK ){
- /* We've found a page to free. At this point the page has been
- ** removed from the page hash-table, free-list and synced-list
- ** (pFirstSynced). It is still in the all pages (pAll) list.
- ** Remove it from this list before freeing.
- **
- ** Todo: Check the Pager.pStmt list to make sure this is Ok. It
- ** probably is though.
- */
- PgHdr *pTmp;
- assert( pPg );
- if( pPg==pPager->pAll ){
- assert(pPg->pPrevAll==0);
- assert(pPg->pNextAll==0 || pPg->pNextAll->pPrevAll==pPg);
- pPager->pAll = pPg->pNextAll;
- if( pPager->pAll ){
- pPager->pAll->pPrevAll = 0;
- }
- }else{
- assert(pPg->pPrevAll);
- assert(pPg->pPrevAll->pNextAll==pPg);
- pTmp = pPg->pPrevAll;
- pTmp->pNextAll = pPg->pNextAll;
- if( pTmp->pNextAll ){
- pTmp->pNextAll->pPrevAll = pTmp;
- }
- }
- nReleased += (
- sizeof(*pPg) + pPager->pageSize
- + sizeof(u32) + pPager->nExtra
- + MEMDB*sizeof(PgHistory)
- );
- IOTRACE(("PGFREE %p %d *\n", pPager, pPg->pgno));
- PAGER_INCR(sqlite3_pager_pgfree_count);
- sqlite3PageFree(pPg->pData);
- sqlite3_free(pPg);
- pPager->nPage--;
- }else{
- /* An error occured whilst writing to the database file or
- ** journal in pager_recycle(). The error is not returned to the
- ** caller of this function. Instead, set the Pager.errCode variable.
- ** The error will be returned to the user (or users, in the case
- ** of a shared pager cache) of the pager for which the error occured.
- */
- assert(
- (rc&0xff)==SQLITE_IOERR ||
- rc==SQLITE_FULL ||
- rc==SQLITE_BUSY
- );
- assert( pPager->state>=PAGER_RESERVED );
- pager_error(pPager, rc);
- }
- }
-
- /* Clear the memory management flags and release the mutex
- */
- for(pPager=sqlite3PagerList; pPager; pPager=pPager->pNext){
- pPager->iInUseMM = 0;
- }
- sqlite3_mutex_leave(mutex);
-
- /* Return the number of bytes released
- */
- return nReleased;
-}
-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
+ }else{
+ *pExists = 1;
+ }
+ }
+ }
+ return rc;
+}
/*
** Read the content of page pPg out of the database file.
*/
@@ -28517,17 +30315,17 @@
if( !pPager->fd->pMethods ){
return SQLITE_IOERR_SHORT_READ;
}
offset = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize, offset);
+ rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, offset);
PAGER_INCR(sqlite3_pager_readdb_count);
PAGER_INCR(pPager->nRead);
IOTRACE(("PGIN %p %d\n", pPager, pgno));
if( pgno==1 ){
- memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24],
+ memcpy(&pPager->dbFileVers, &((u8*)pPg->pData)[24],
sizeof(pPager->dbFileVers));
}
- CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
+ CODEC1(pPager, pPg->pData, pPg->pgno, 3);
PAGERTRACE4("FETCH %d page %d hash(%08x)\n",
PAGERID(pPager), pPg->pgno, pager_pagehash(pPg));
return rc;
}
@@ -28543,18 +30341,20 @@
** is performed immediately.
*/
static int pagerSharedLock(Pager *pPager){
int rc = SQLITE_OK;
- int isHot = 0;
+ int isErrorReset = 0;
/* If this database is opened for exclusive access, has no outstanding
** page references and is in an error-state, now is the chance to clear
** the error. Discard the contents of the pager-cache and treat any
** open journal file as a hot-journal.
*/
- if( !MEMDB && pPager->exclusiveMode && pPager->nRef==0 && pPager->errCode ){
+ if( !MEMDB && pPager->exclusiveMode
+ && sqlite3PcacheRefCount(pPager->pPCache)==0 && pPager->errCode
+ ){
if( pPager->journalOpen ){
- isHot = 1;
+ isErrorReset = 1;
}
pPager->errCode = SQLITE_OK;
pager_reset(pPager);
}
@@ -28566,142 +30366,138 @@
if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
return pPager->errCode;
}
- if( pPager->state==PAGER_UNLOCK || isHot ){
+ if( pPager->state==PAGER_UNLOCK || isErrorReset ){
sqlite3_vfs *pVfs = pPager->pVfs;
- if( !MEMDB ){
- assert( pPager->nRef==0 );
- if( !pPager->noReadlock ){
- rc = pager_wait_on_lock(pPager, SHARED_LOCK);
- if( rc!=SQLITE_OK ){
- assert( pPager->state==PAGER_UNLOCK );
- return pager_error(pPager, rc);
- }
- assert( pPager->state>=SHARED_LOCK );
- }
-
- /* 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.
- */
- rc = hasHotJournal(pPager);
- if( rc<0 ){
- rc = SQLITE_IOERR_NOMEM;
+ 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);
+ }
+ 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( rc==1 || isHot ){
- /* 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( !isHot && 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;
- }
- }
- }
- if( rc!=SQLITE_OK ){
- if( rc!=SQLITE_NOMEM && rc!=SQLITE_IOERR_UNLOCK
- && rc!=SQLITE_IOERR_NOMEM
- ){
+ }
+ if( isErrorReset || isHotJournal ){
+ /* Get an EXCLUSIVE lock on the database file. At this point it is
+ ** important that a RESERVED lock is not obtained on the way to the
+ ** EXCLUSIVE lock. If it were, another process might open the
+ ** database file, detect the RESERVED lock, and conclude that the
+ ** database is safe to read while this process is still rolling it
+ ** back.
+ **
+ ** Because the intermediate RESERVED lock is not requested, the
+ ** second process will get to this point in the code and fail to
+ ** obtain its own EXCLUSIVE lock on the database file.
+ */
+ if( pPager->state<EXCLUSIVE_LOCK ){
+ rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK);
+ if( rc!=SQLITE_OK ){
+ rc = pager_error(pPager, rc);
+ goto failed;
+ }
+ pPager->state = PAGER_EXCLUSIVE;
+ }
+
+ /* Open the journal for read/write access. This is because in
+ ** exclusive-access mode the file descriptor will be kept open and
+ ** possibly used for a transaction later on. On some systems, the
+ ** OsTruncate() call used in exclusive-access mode also requires
+ ** a read/write file handle.
+ */
+ if( !isErrorReset && pPager->journalOpen==0 ){
+ int res;
+ rc = sqlite3OsAccess(pVfs,pPager->zJournal,SQLITE_ACCESS_EXISTS,&res);
+ if( rc==SQLITE_OK ){
+ if( res ){
+ int fout = 0;
+ int f = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_JOURNAL;
+ assert( !pPager->tempFile );
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, f, &fout);
+ assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
+ if( rc==SQLITE_OK && fout&SQLITE_OPEN_READONLY ){
+ rc = SQLITE_CANTOPEN;
+ sqlite3OsClose(pPager->jfd);
+ }
+ }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;
-
- /* 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( pPager->pAll ){
- /* The shared-lock has just been acquired on the database file
- ** and there are already pages in the cache (from a previous
- ** read or write transaction). Check to see if the database
- ** has been modified. If the database has changed, flush the
- ** cache.
- **
- ** Database changes is detected by looking at 15 bytes beginning
- ** at offset 24 into the file. The first 4 of these 16 bytes are
- ** a 32-bit counter that is incremented with each change. The
- ** other bytes change randomly with each file change when
- ** a codec is in use.
- **
- ** There is a vanishingly small chance that a change will not be
- ** detected. The chance of an undetected change is so small that
- ** it can be neglected.
- */
- char dbFileVers[sizeof(pPager->dbFileVers)];
- sqlite3PagerPagecount(pPager, 0);
-
- if( pPager->errCode ){
- rc = pPager->errCode;
+ }
+ }
+ 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)
+ );
+ }
+
+ 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->dbSize>0 ){
+ IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
+ rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
+ if( rc!=SQLITE_OK ){
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( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
- pager_reset(pPager);
- }
+ }else{
+ memset(dbFileVers, 0, sizeof(dbFileVers));
+ }
+
+ if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){
+ pager_reset(pPager);
}
}
assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED );
if( pPager->state==PAGER_UNLOCK ){
@@ -28717,122 +30513,48 @@
return rc;
}
/*
-** Allocate a PgHdr object. Either create a new one or reuse
-** an existing one that is not otherwise in use.
-**
-** A new PgHdr structure is created if any of the following are
-** true:
-**
-** (1) We have not exceeded our maximum allocated cache size
-** as set by the "PRAGMA cache_size" command.
-**
-** (2) There are no unused PgHdr objects available at this time.
-**
-** (3) This is an in-memory database.
-**
-** (4) There are no PgHdr objects that do not require a journal
-** file sync and a sync of the journal file is currently
-** prohibited.
-**
-** Otherwise, reuse an existing PgHdr. In other words, reuse an
-** existing PgHdr if all of the following are true:
-**
-** (1) We have reached or exceeded the maximum cache size
-** allowed by "PRAGMA cache_size".
-**
-** (2) There is a PgHdr available with PgHdr->nRef==0
-**
-** (3) We are not in an in-memory database
-**
-** (4) Either there is an available PgHdr that does not need
-** to be synced to disk or else disk syncing is currently
-** allowed.
-*/
-static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
- int rc = SQLITE_OK;
- PgHdr *pPg;
- int nByteHdr;
-
- /* Create a new PgHdr if any of the four conditions defined
- ** above are met: */
- if( pPager->nPage<pPager->mxPage
- || pPager->lru.pFirst==0
- || MEMDB
- || (pPager->lru.pFirstSynced==0 && pPager->doNotSync)
- ){
- void *pData;
- if( pPager->nPage>=pPager->nHash ){
- pager_resize_hash_table(pPager,
- pPager->nHash<256 ? 256 : pPager->nHash*2);
- if( pPager->nHash==0 ){
- rc = SQLITE_NOMEM;
- goto pager_allocate_out;
- }
- }
- pagerLeave(pPager);
- nByteHdr = sizeof(*pPg) + sizeof(u32) + pPager->nExtra
- + MEMDB*sizeof(PgHistory);
- pPg = sqlite3Malloc( nByteHdr );
- if( pPg ){
- pData = sqlite3PageMalloc( pPager->pageSize );
- if( pData==0 ){
- sqlite3_free(pPg);
- pPg = 0;
- }
- }
- pagerEnter(pPager);
- if( pPg==0 ){
- rc = SQLITE_NOMEM;
- goto pager_allocate_out;
- }
- memset(pPg, 0, nByteHdr);
- pPg->pData = pData;
- pPg->pPager = pPager;
- pPg->pNextAll = pPager->pAll;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( pPg->pNextAll ){
- pPg->pNextAll->pPrevAll = pPg;
- }
-#endif
- pPager->pAll = pPg;
- pPager->nPage++;
- }else{
- /* Recycle an existing page with a zero ref-count. */
- rc = pager_recycle(pPager, &pPg);
- if( rc==SQLITE_BUSY ){
- rc = SQLITE_IOERR_BLOCKED;
- }
- if( rc!=SQLITE_OK ){
- goto pager_allocate_out;
- }
- assert( pPager->state>=SHARED_LOCK );
- assert(pPg);
- }
- *ppPg = pPg;
-
-pager_allocate_out:
- return rc;
-}
-
-/*
** Make sure we have the content for a page. If the page was
** previously acquired with noContent==1, then the content was
** just initialized to zeros instead of being read from disk.
** But now we need the real data off of disk. So make sure we
** have it. Read it in if we do not have it already.
*/
static int pager_get_content(PgHdr *pPg){
- if( pPg->needRead ){
+ if( pPg->flags&PGHDR_NEED_READ ){
int rc = readDbPage(pPg->pPager, pPg, pPg->pgno);
if( rc==SQLITE_OK ){
- pPg->needRead = 0;
- }else{
- return rc;
- }
- }
- return SQLITE_OK;
+ pPg->flags &= ~PGHDR_NEED_READ;
+ }else{
+ return rc;
+ }
+ }
+ return SQLITE_OK;
+}
+
+/*
+** If the reference count has reached zero, and the pager is not in the
+** middle of a write transaction or opened in exclusive mode, unlock it.
+*/
+static void pagerUnlockIfUnused(Pager *pPager){
+ if( (sqlite3PcacheRefCount(pPager->pPCache)==0)
+ && (!pPager->exclusiveMode || pPager->journalOff>0)
+ ){
+ pagerUnlockAndRollback(pPager);
+ }
+}
+
+/*
+** Drop a page from the cache using sqlite3PcacheDrop().
+**
+** If this means there are now no pages with references to them, a rollback
+** occurs and the lock on the database is removed.
+*/
+static void pagerDropPage(DbPage *pPg){
+ Pager *pPager = pPg->pPager;
+ sqlite3PcacheDrop(pPg);
+ pagerUnlockIfUnused(pPager);
}
/*
** Acquire a page.
@@ -28865,18 +30587,21 @@
** sqlite3PagerWrite() is called on this page or if this routine is
** 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 */
int noContent /* Do not bother reading content from disk if true */
){
- PgHdr *pPg;
- int rc;
-
- assert( pPager->state==PAGER_UNLOCK || pPager->nRef>0 || pgno==1 );
+ PgHdr *pPg = 0;
+ int rc;
+
+ assert( pPager->state==PAGER_UNLOCK
+ || sqlite3PcacheRefCount(pPager->pPCache)>0
+ || pgno==1
+ );
/* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page
** number greater than this, or zero, is requested.
*/
@@ -28898,99 +30623,67 @@
return rc;
}
assert( pPager->state!=PAGER_UNLOCK );
- pPg = pager_lookup(pPager, pgno);
- if( pPg==0 ){
- /* The requested page is not in the page cache. */
- int nMax;
- int h;
+ rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, &pPg);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ if( pPg->pPager==0 ){
+ /* The pager cache has created a new page. Its content needs to
+ ** be initialized.
+ */
+ int nMax;
PAGER_INCR(pPager->nMiss);
- rc = pagerAllocatePage(pPager, &pPg);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- pPg->pgno = pgno;
- assert( !MEMDB || pgno>pPager->stmtSize );
- pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
- pPg->needSync = 0;
-
- makeClean(pPg);
- pPg->nRef = 1;
-
- pPager->nRef++;
- if( pPager->nExtra>0 ){
- memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
- }
+ pPg->pPager = pPager;
+ if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
+ pPg->flags |= PGHDR_IN_JOURNAL;
+ }
+ memset(pPg->pExtra, 0, pPager->nExtra);
+
rc = sqlite3PagerPagecount(pPager, &nMax);
if( rc!=SQLITE_OK ){
sqlite3PagerUnref(pPg);
return rc;
}
- /* Populate the page with data, either by reading from the database
- ** file, or by setting the entire page to zero.
- */
- if( nMax<(int)pgno || MEMDB || (noContent && !pPager->alwaysRollback) ){
+ if( nMax<(int)pgno || MEMDB || noContent ){
if( pgno>pPager->mxPgno ){
sqlite3PagerUnref(pPg);
return SQLITE_FULL;
}
- memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
- pPg->needRead = noContent && !pPager->alwaysRollback;
+ memset(pPg->pData, 0, pPager->pageSize);
+ if( noContent ){
+ pPg->flags |= PGHDR_NEED_READ;
+ }
IOTRACE(("ZERO %p %d\n", pPager, pgno));
}else{
rc = readDbPage(pPager, pPg, pgno);
if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
- pPg->pgno = 0;
- sqlite3PagerUnref(pPg);
- return rc;
- }
- pPg->needRead = 0;
- }
-
- /* Link the page into the page hash table */
- h = pgno & (pPager->nHash-1);
- assert( pgno!=0 );
- pPg->pNextHash = pPager->aHash[h];
- pPager->aHash[h] = pPg;
- if( pPg->pNextHash ){
- assert( pPg->pNextHash->pPrevHash==0 );
- pPg->pNextHash->pPrevHash = pPg;
- }
-
+ /* sqlite3PagerUnref(pPg); */
+ pagerDropPage(pPg);
+ return rc;
+ }
+ }
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}else{
/* The requested page is in the page cache. */
- assert(pPager->nRef>0 || pgno==1);
+ assert(sqlite3PcacheRefCount(pPager->pPCache)>0 || pgno==1);
PAGER_INCR(pPager->nHit);
if( !noContent ){
rc = pager_get_content(pPg);
if( rc ){
- return rc;
- }
- }
- page_ref(pPg);
- }
+ sqlite3PagerUnref(pPg);
+ return rc;
+ }
+ }
+ }
+
*ppPage = pPg;
return SQLITE_OK;
}
-SQLITE_PRIVATE int sqlite3PagerAcquire(
- Pager *pPager, /* The pager open on the database file */
- Pgno pgno, /* Page number to fetch */
- DbPage **ppPage, /* Write a pointer to the page here */
- int noContent /* Do not bother reading content from disk if true */
-){
- int rc;
- pagerEnter(pPager);
- rc = pagerAcquire(pPager, pgno, ppPage, noContent);
- pagerLeave(pPager);
- return rc;
-}
-
/*
** Acquire a page if it is already in the in-memory cache. Do
** not read the page from disk. Return a pointer to the page,
@@ -29003,21 +30696,17 @@
** has ever happened.
*/
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
PgHdr *pPg = 0;
-
assert( pPager!=0 );
assert( pgno!=0 );
- pagerEnter(pPager);
- if( pPager->state==PAGER_UNLOCK ){
- assert( !pPager->pAll || pPager->exclusiveMode );
- }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
- /* Do nothing */
- }else if( (pPg = pager_lookup(pPager, pgno))!=0 ){
- page_ref(pPg);
- }
- pagerLeave(pPager);
+ if( (pPager->state!=PAGER_UNLOCK)
+ && (pPager->errCode==SQLITE_OK || pPager->errCode==SQLITE_FULL)
+ ){
+ sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
+ }
+
return pPg;
}
/*
@@ -29028,41 +30717,13 @@
** are released, a rollback occurs and the lock on the database is
** removed.
*/
SQLITE_PRIVATE int sqlite3PagerUnref(DbPage *pPg){
- Pager *pPager;
-
- if( pPg==0 ) return SQLITE_OK;
- pPager = pPg->pPager;
-
- /* Decrement the reference count for this page
- */
- assert( pPg->nRef>0 );
- pagerEnter(pPg->pPager);
- pPg->nRef--;
-
- CHECK_PAGE(pPg);
-
- /* When the number of references to a page reach 0, call the
- ** destructor and add the page to the freelist.
- */
- if( pPg->nRef==0 ){
-
- lruListAdd(pPg);
- if( pPager->xDestructor ){
- pPager->xDestructor(pPg, pPager->pageSize);
- }
-
- /* When all pages reach the freelist, drop the read lock from
- ** the database file.
- */
- pPager->nRef--;
- assert( pPager->nRef>=0 );
- if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){
- pagerUnlockAndRollback(pPager);
- }
- }
- pagerLeave(pPager);
+ if( pPg ){
+ Pager *pPager = pPg->pPager;
+ sqlite3PcacheRelease(pPg);
+ pagerUnlockIfUnused(pPager);
+ }
return SQLITE_OK;
}
/*
@@ -29076,16 +30737,13 @@
sqlite3_vfs *pVfs = pPager->pVfs;
int flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_CREATE);
int rc;
- assert( !MEMDB );
assert( pPager->state>=PAGER_RESERVED );
assert( pPager->useJournal );
assert( pPager->pInJournal==0 );
sqlite3PagerPagecount(pPager, 0);
- pagerLeave(pPager);
- pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
- pagerEnter(pPager);
+ pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
if( pPager->pInJournal==0 ){
rc = SQLITE_NOMEM;
goto failed_to_open_journal;
}
@@ -29095,15 +30753,20 @@
flags |= (SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL);
}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)
- );
-#else
- rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
-#endif
+ rc = sqlite3JournalOpen(
+ pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
+ );
+#else
+ rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
+#endif
+ }
assert( rc!=SQLITE_OK || pPager->jfd->pMethods );
pPager->journalOff = 0;
pPager->setMaster = 0;
pPager->journalHdr = 0;
@@ -29116,9 +30779,8 @@
}
pPager->journalOpen = 1;
pPager->journalStarted = 0;
pPager->needSync = 0;
- pPager->alwaysRollback = 0;
pPager->nRec = 0;
if( pPager->errCode ){
rc = pPager->errCode;
goto failed_to_open_journal;
@@ -29173,34 +30835,29 @@
*/
SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
- pagerEnter(pPager);
assert( pPg->nRef>0 );
assert( pPager->state!=PAGER_UNLOCK );
if( pPager->state==PAGER_SHARED ){
assert( pPager->pInJournal==0 );
- if( MEMDB ){
- pPager->state = PAGER_EXCLUSIVE;
- pPager->origDbSize = pPager->dbSize;
- }else{
- rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK);
- if( rc==SQLITE_OK ){
- pPager->state = PAGER_RESERVED;
- if( exFlag ){
- rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
- }
- }
- if( rc!=SQLITE_OK ){
- pagerLeave(pPager);
- return rc;
- }
- pPager->dirtyCache = 0;
- PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager));
- if( pPager->useJournal && !pPager->tempFile
- && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
- rc = pager_open_journal(pPager);
- }
+ assert( !MEMDB );
+ sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
+ 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
@@ -29211,11 +30868,9 @@
assert( pPager->nRec==0 );
assert( pPager->origDbSize==0 );
assert( pPager->pInJournal==0 );
sqlite3PagerPagecount(pPager, 0);
- pagerLeave(pPager);
- pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
- pagerEnter(pPager);
+ pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
if( !pPager->pInJournal ){
rc = SQLITE_NOMEM;
}else{
pPager->origDbSize = pPager->dbSize;
@@ -29222,9 +30877,8 @@
rc = writeJournalHdr(pPager);
}
}
assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK );
- pagerLeave(pPager);
return rc;
}
/*
@@ -29231,39 +30885,17 @@
** Make a page dirty. Set its dirty flag and add it to the dirty
** page list.
*/
static void makeDirty(PgHdr *pPg){
- if( pPg->dirty==0 ){
- Pager *pPager = pPg->pPager;
- pPg->dirty = 1;
- pPg->pDirty = pPager->pDirty;
- if( pPager->pDirty ){
- pPager->pDirty->pPrevDirty = pPg;
- }
- pPg->pPrevDirty = 0;
- pPager->pDirty = pPg;
- }
+ sqlite3PcacheMakeDirty(pPg);
}
/*
** Make a page clean. Clear its dirty bit and remove it from the
** dirty page list.
*/
static void makeClean(PgHdr *pPg){
- if( pPg->dirty ){
- pPg->dirty = 0;
- if( pPg->pDirty ){
- assert( pPg->pDirty->pPrevDirty==pPg );
- pPg->pDirty->pPrevDirty = pPg->pPrevDirty;
- }
- if( pPg->pPrevDirty ){
- assert( pPg->pPrevDirty->pDirty==pPg );
- pPg->pPrevDirty->pDirty = pPg->pDirty;
- }else{
- assert( pPg->pPager->pDirty==pPg );
- pPg->pPager->pDirty = pPg->pDirty;
- }
- }
+ sqlite3PcacheMakeClean(pPg);
}
/*
@@ -29283,9 +30915,9 @@
** is a call to sqlite3PagerCommit() or sqlite3PagerRollback() to
** reset.
*/
static int pager_write(PgHdr *pPg){
- void *pData = PGHDR_TO_DATA(pPg);
+ void *pData = pPg->pData;
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
/* Check for errors
@@ -29317,9 +30949,11 @@
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
makeDirty(pPg);
- if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){
+ if( (pPg->flags&PGHDR_IN_JOURNAL)
+ && (pageInStatement(pPg) || pPager->stmtInUse==0)
+ ){
pPager->dirtyCache = 1;
pPager->dbModified = 1;
}else{
@@ -29347,69 +30981,64 @@
/* The transaction journal now exists and we have a RESERVED or an
** EXCLUSIVE lock on the main database file. Write the current page to
** the transaction journal if it is not there already.
*/
- if( !pPg->inJournal && (pPager->journalOpen || MEMDB) ){
+ if( !(pPg->flags&PGHDR_IN_JOURNAL) && pPager->journalOpen ){
if( (int)pPg->pgno <= pPager->origDbSize ){
- if( MEMDB ){
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
- assert( pHist->pOrig==0 );
- pHist->pOrig = sqlite3PageMalloc( pPager->pageSize );
- if( !pHist->pOrig ){
- return SQLITE_NOMEM;
- }
- memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
- }else{
- u32 cksum;
- char *pData2;
-
- /* We should never write to the journal file the page that
- ** contains the database locks. The following assert verifies
- ** that we do not. */
- assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
- pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
- cksum = pager_cksum(pPager, (u8*)pData2);
- rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize,
- pPager->journalOff + 4);
- pPager->journalOff += pPager->pageSize+4;
- }
- if( rc==SQLITE_OK ){
- rc = write32bits(pPager->jfd, pPager->journalOff, cksum);
- pPager->journalOff += 4;
- }
- IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno,
- pPager->journalOff, pPager->pageSize));
- PAGER_INCR(sqlite3_pager_writej_count);
- PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n",
- PAGERID(pPager), pPg->pgno, pPg->needSync, pager_pagehash(pPg));
-
- /* An error has occured writing to the journal file. The
- ** transaction will be rolled back by the layer above.
- */
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- pPager->nRec++;
- assert( pPager->pInJournal!=0 );
- sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
- pPg->needSync = !pPager->noSync;
- if( pPager->stmtInUse ){
- sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
- }
- }
- }else{
- pPg->needSync = !pPager->journalStarted && !pPager->noSync;
+ 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);
+ }
+ }else{
+ if( !pPager->journalStarted && !pPager->noSync ){
+ pPg->flags |= PGHDR_NEED_SYNC;
+ }
PAGERTRACE4("APPEND %d page %d needSync=%d\n",
- PAGERID(pPager), pPg->pgno, pPg->needSync);
- }
- if( pPg->needSync ){
+ PAGERID(pPager), pPg->pgno,
+ ((pPg->flags&PGHDR_NEED_SYNC)?1:0));
+ }
+ if( pPg->flags&PGHDR_NEED_SYNC ){
pPager->needSync = 1;
}
- pPg->inJournal = 1;
+ pPg->flags |= PGHDR_IN_JOURNAL;
}
/* If the statement journal is open and the page is not in it,
** then write the current page to the statement journal. Note that
@@ -29419,33 +31048,23 @@
if( pPager->stmtInUse
&& !pageInStatement(pPg)
&& (int)pPg->pgno<=pPager->stmtSize
){
- assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
- if( MEMDB ){
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- assert( pHist->pStmt==0 );
- pHist->pStmt = sqlite3PageMalloc( pPager->pageSize );
- if( pHist->pStmt ){
- memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
- }
- PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
- page_add_to_stmt_list(pPg);
- }else{
- i64 offset = pPager->stmtNRec*(4+pPager->pageSize);
- char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
- rc = write32bits(pPager->stfd, offset, pPg->pgno);
- if( rc==SQLITE_OK ){
- rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4);
- }
- PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- pPager->stmtNRec++;
- assert( pPager->pInStmt!=0 );
- sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
- }
+ 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 );
+ rc = write32bits(pPager->stfd, offset, pPg->pgno);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize, offset+4);
+ }
+ PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ pPager->stmtNRec++;
+ assert( pPager->pInStmt!=0 );
+ sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
}
/* Update the database size and return.
@@ -29452,9 +31071,9 @@
*/
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++;
}
}
return rc;
@@ -29476,10 +31095,9 @@
PgHdr *pPg = pDbPage;
Pager *pPager = pPg->pPager;
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
- pagerEnter(pPager);
- 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 */
int ii;
@@ -29487,8 +31105,9 @@
/* 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;
/* This trick assumes that both the page-size and sector-size are
@@ -29516,18 +31135,19 @@
if( pg!=PAGER_MJ_PGNO(pPager) ){
rc = sqlite3PagerGet(pPager, pg, &pPage);
if( rc==SQLITE_OK ){
rc = pager_write(pPage);
- if( pPage->needSync ){
+ if( pPage->flags&PGHDR_NEED_SYNC ){
needSync = 1;
}
sqlite3PagerUnref(pPage);
}
}
}else if( (pPage = pager_lookup(pPager, pg))!=0 ){
- if( pPage->needSync ){
+ if( pPage->flags&PGHDR_NEED_SYNC ){
needSync = 1;
}
+ sqlite3PagerUnref(pPage);
}
}
/* If the PgHdr.needSync flag is set for any of the nPage pages
@@ -29536,11 +31156,13 @@
** journal file must contain sync()ed copies of all of them
** 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->needSync = 1;
+ if( pPage ) pPage->flags |= PGHDR_NEED_SYNC;
+ sqlite3PagerUnref(pPage);
}
assert(pPager->needSync);
}
@@ -29548,9 +31170,8 @@
pPager->doNotSync = 0;
}else{
rc = pager_write(pDbPage);
}
- pagerLeave(pPager);
return rc;
}
/*
@@ -29559,9 +31180,9 @@
** to change the content of the page.
*/
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
- return pPg->dirty;
+ return pPg->flags&PGHDR_DIRTY;
}
#endif
/*
@@ -29587,16 +31208,26 @@
** the sqlite3PagerDontRollback() routine is called. But because the
** page contains critical data, we still need to be sure it gets
** rolled back in spite of the sqlite3PagerDontRollback() call.
*/
-SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage *pDbPage){
+SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage *pDbPage){
PgHdr *pPg = pDbPage;
Pager *pPager = pPg->pPager;
-
- if( MEMDB ) return;
- pagerEnter(pPager);
- pPg->alwaysRollback = 1;
- if( pPg->dirty && !pPager->stmtInUse ){
+ int rc;
+
+ if( pPg->pgno>pPager->origDbSize ){
+ return SQLITE_OK;
+ }
+ if( pPager->pAlwaysRollback==0 ){
+ assert( pPager->pInJournal );
+ pPager->pAlwaysRollback = sqlite3BitvecCreate(pPager->origDbSize);
+ if( !pPager->pAlwaysRollback ){
+ return SQLITE_NOMEM;
+ }
+ }
+ rc = sqlite3BitvecSet(pPager->pAlwaysRollback, pPg->pgno);
+
+ if( rc==SQLITE_OK && (pPg->flags&PGHDR_DIRTY) && !pPager->stmtInUse ){
assert( pPager->state>=PAGER_SHARED );
if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSize<pPager->dbSize ){
/* If this pages is the last page in the file and the file has grown
** during the current transaction, then do NOT mark the page as clean.
@@ -29608,15 +31239,15 @@
*/
}else{
PAGERTRACE3("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager));
IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno))
- makeClean(pPg);
+ pPg->flags |= PGHDR_DONT_WRITE;
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}
}
- pagerLeave(pPager);
+ return rc;
}
/*
** A call to this routine tells the pager that if a rollback occurs,
@@ -29631,23 +31262,23 @@
*/
SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){
Pager *pPager = pPg->pPager;
- pagerEnter(pPager);
assert( pPager->state>=PAGER_RESERVED );
/* If the journal file is not open, or DontWrite() has been called on
** this page (DontWrite() sets the alwaysRollback flag), then this
** function is a no-op.
*/
- if( pPager->journalOpen==0 || pPg->alwaysRollback || pPager->alwaysRollback ){
- pagerLeave(pPager);
- return;
- }
- assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */
+ if( pPager->journalOpen==0
+ || sqlite3BitvecTest(pPager->pAlwaysRollback, pPg->pgno)
+ || pPg->pgno>pPager->origDbSize
+ ){
+ return;
+ }
#ifdef SQLITE_SECURE_DELETE
- if( pPg->inJournal || (int)pPg->pgno > pPager->origDbSize ){
+ if( (pPg->flags & PGHDR_IN_JOURNAL)!=0 || (int)pPg->pgno>pPager->origDbSize ){
return;
}
#endif
@@ -29664,17 +31295,16 @@
/* assert( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ); */
assert( pPager->pInJournal!=0 );
sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
- pPg->inJournal = 1;
- pPg->needRead = 0;
+ pPg->flags |= PGHDR_IN_JOURNAL;
+ pPg->flags &= ~PGHDR_NEED_READ;
if( pPager->stmtInUse ){
assert( pPager->stmtSize >= pPager->origDbSize );
sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager));
IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno))
- pagerLeave(pPager);
}
/*
@@ -29685,8 +31315,11 @@
PgHdr *pPgHdr;
u32 change_counter;
int rc = SQLITE_OK;
+#ifndef SQLITE_ENABLE_ATOMIC_WRITE
+ assert( isDirect==0 ); /* isDirect is only true for atomic writes */
+#endif
if( !pPager->changeCountDone ){
/* Open page 1 of the file for writing. */
rc = sqlite3PagerGet(pPager, 1, &pPgHdr);
if( rc!=SQLITE_OK ) return rc;
@@ -29701,14 +31334,16 @@
/* Increment the value just read and write it back to byte 24. */
change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
change_counter++;
- put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter);
-
+ put32bits(((char*)pPgHdr->pData)+24, change_counter);
+
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
if( isDirect && pPager->fd->pMethods ){
- const void *zBuf = PGHDR_TO_DATA(pPgHdr);
+ const void *zBuf = pPgHdr->pData;
rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
}
+#endif
/* Release the page reference. */
sqlite3PagerUnref(pPgHdr);
pPager->changeCountDone = 1;
@@ -29720,11 +31355,13 @@
** Sync the pager file to disk.
*/
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager){
int rc;
- pagerEnter(pPager);
- rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
- pagerLeave(pPager);
+ if( MEMDB ){
+ rc = SQLITE_OK;
+ }else{
+ rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
+ }
return rc;
}
/*
@@ -29771,9 +31408,8 @@
}
PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n",
pPager->zFilename, zMaster, nTrunc);
- pagerEnter(pPager);
/* If this is an in-memory db, or no pages have been written to, or this
** function has already been called, it is a no-op.
*/
@@ -29791,14 +31427,16 @@
**
** If the optimization can be used, then the journal file will never
** be created for this transaction.
*/
- int useAtomicWrite = (
+ int useAtomicWrite;
+ pPg = sqlite3PcacheDirtyList(pPager->pPCache);
+ useAtomicWrite = (
!zMaster &&
pPager->journalOpen &&
pPager->journalOff==jrnlBufferSize(pPager) &&
nTrunc==0 &&
- (0==pPager->pDirty || 0==pPager->pDirty->pDirty)
+ (pPg==0 || pPg->pDirty==0)
);
assert( pPager->journalOpen || pPager->journalMode==PAGER_JOURNALMODE_OFF );
if( useAtomicWrite ){
/* Update the nRec field in the journal file. */
@@ -29865,9 +31503,9 @@
}
#endif
/* Write all dirty pages to the database file */
- pPg = pager_get_all_dirty_pages(pPager);
+ pPg = sqlite3PcacheDirtyList(pPager->pPCache);
rc = pager_write_pagelist(pPg);
if( rc!=SQLITE_OK ){
assert( rc!=SQLITE_IOERR_BLOCKED );
/* The error might have left the dirty list all fouled up here,
@@ -29878,9 +31516,9 @@
** is made to use an invalid dirty list.
*/
goto sync_exit;
}
- pPager->pDirty = 0;
+ sqlite3PcacheCleanAll(pPager->pPCache);
/* Sync the database file. */
if( !pPager->noSync && !noSync ){
rc = sqlite3OsSync(pPager->fd, pPager->sync_flags);
@@ -29900,9 +31538,8 @@
* better to return SQLITE_BUSY.
*/
rc = SQLITE_BUSY;
}
- pagerLeave(pPager);
return rc;
}
@@ -29913,10 +31550,9 @@
** and an error code is returned. If the commit worked, SQLITE_OK
** is returned.
*/
SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
- int rc;
- PgHdr *pPg;
+ int rc = SQLITE_OK;
if( pPager->errCode ){
return pPager->errCode;
}
@@ -29928,40 +31564,12 @@
pPager->exclusiveMode!=0) ){
assert( pPager->dirtyCache==0 || pPager->journalOpen==0 );
return SQLITE_OK;
}
- pagerEnter(pPager);
PAGERTRACE2("COMMIT %d\n", PAGERID(pPager));
- if( MEMDB ){
- pPg = pager_get_all_dirty_pages(pPager);
- while( pPg ){
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- clearHistory(pHist);
- pPg->dirty = 0;
- pPg->inJournal = 0;
- pHist->inStmt = 0;
- pPg->needSync = 0;
- pHist->pPrevStmt = pHist->pNextStmt = 0;
- pPg = pPg->pDirty;
- }
- pPager->pDirty = 0;
-#ifndef NDEBUG
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- assert( !pPg->alwaysRollback );
- assert( !pHist->pOrig );
- assert( !pHist->pStmt );
- }
-#endif
- pPager->pStmt = 0;
- pPager->state = PAGER_SHARED;
- pagerLeave(pPager);
- return SQLITE_OK;
- }
- assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
+ assert( pPager->state==PAGER_SYNCED || MEMDB || !pPager->dirtyCache );
rc = pager_end_transaction(pPager, pPager->setMaster);
rc = pager_error(pPager, rc);
- pagerLeave(pPager);
return rc;
}
/*
@@ -29976,79 +31584,39 @@
** codes are returned for all these occasions. Otherwise,
** SQLITE_OK is returned.
*/
SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
- int rc;
+ int rc = SQLITE_OK;
PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
- if( MEMDB ){
- PgHdr *p;
- for(p=pPager->pAll; p; p=p->pNextAll){
- PgHistory *pHist;
- assert( !p->alwaysRollback );
- if( !p->dirty ){
- assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
- assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
- continue;
- }
-
- pHist = PGHDR_TO_HIST(p, pPager);
- if( pHist->pOrig ){
- memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
- PAGERTRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager));
- }else{
- PAGERTRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager));
- }
- clearHistory(pHist);
- p->dirty = 0;
- p->inJournal = 0;
- pHist->inStmt = 0;
- pHist->pPrevStmt = pHist->pNextStmt = 0;
- if( pPager->xReiniter ){
- pPager->xReiniter(p, pPager->pageSize);
- }
- }
- pPager->pDirty = 0;
- pPager->pStmt = 0;
- pPager->dbSize = pPager->origDbSize;
- pager_truncate_cache(pPager);
- pPager->stmtInUse = 0;
- pPager->state = PAGER_SHARED;
- return SQLITE_OK;
- }
-
- pagerEnter(pPager);
if( !pPager->dirtyCache || !pPager->journalOpen ){
rc = pager_end_transaction(pPager, pPager->setMaster);
- pagerLeave(pPager);
- return rc;
- }
-
- if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
+ }else if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){
if( pPager->state>=PAGER_EXCLUSIVE ){
pager_playback(pPager, 0);
}
- pagerLeave(pPager);
- return pPager->errCode;
- }
- if( pPager->state==PAGER_RESERVED ){
- int rc2;
- rc = pager_playback(pPager, 0);
- rc2 = pager_end_transaction(pPager, pPager->setMaster);
- if( rc==SQLITE_OK ){
- rc = rc2;
- }
- }else{
- rc = pager_playback(pPager, 0);
- }
- /* pager_reset(pPager); */
- pPager->dbSize = -1;
-
- /* If an error occurs during a ROLLBACK, we can no longer trust the pager
- ** cache. So call pager_error() on the way out to make any error
- ** persistent.
- */
- rc = pager_error(pPager, rc);
- pagerLeave(pPager);
+ rc = pPager->errCode;
+ }else{
+ if( pPager->state==PAGER_RESERVED ){
+ int rc2;
+ rc = pager_playback(pPager, 0);
+ rc2 = pager_end_transaction(pPager, pPager->setMaster);
+ if( rc==SQLITE_OK ){
+ rc = rc2;
+ }
+ }else{
+ rc = pager_playback(pPager, 0);
+ }
+
+ if( !MEMDB ){
+ pPager->dbSize = -1;
+ }
+
+ /* If an error occurs during a ROLLBACK, we can no longer trust the pager
+ ** cache. So call pager_error() on the way out to make any error
+ ** persistent.
+ */
+ rc = pager_error(pPager, rc);
+ }
return rc;
}
/*
@@ -30062,9 +31630,16 @@
/*
** Return the number of references to the pager.
*/
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
- return pPager->nRef;
+ 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
/*
@@ -30071,11 +31646,11 @@
** This routine is used for testing and analysis only.
*/
SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){
static int a[11];
- a[0] = pPager->nRef;
- a[1] = pPager->nPage;
- a[2] = pPager->mxPage;
+ a[0] = sqlite3PcacheRefCount(pPager->pPCache);
+ a[1] = sqlite3PcachePagecount(pPager->pPCache);
+ a[2] = sqlite3PcacheGetCachesize(pPager->pPCache);
a[3] = pPager->dbSize;
a[4] = pPager->state;
a[5] = pPager->errCode;
a[6] = pPager->nHit;
@@ -30102,22 +31677,15 @@
assert( !pPager->stmtInUse );
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;
}
assert( pPager->journalOpen );
- pagerLeave(pPager);
assert( pPager->pInStmt==0 );
pPager->pInStmt = sqlite3BitvecCreate(pPager->dbSize);
- pagerEnter(pPager);
if( pPager->pInStmt==0 ){
/* sqlite3OsLock(pPager->fd, SHARED_LOCK); */
return SQLITE_NOMEM;
}
@@ -30125,11 +31693,15 @@
pPager->stmtSize = pPager->dbSize;
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;
}
@@ -30144,43 +31716,27 @@
return rc;
}
SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager *pPager){
int rc;
- pagerEnter(pPager);
- rc = pagerStmtBegin(pPager);
- pagerLeave(pPager);
+ rc = pagerStmtBegin(pPager);
return rc;
}
/*
** Commit a statement.
*/
SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager *pPager){
- pagerEnter(pPager);
- if( pPager->stmtInUse ){
- PgHdr *pPg, *pNext;
+ if( pPager->stmtInUse ){
PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
- if( !MEMDB ){
- /* sqlite3OsTruncate(pPager->stfd, 0); */
- sqlite3BitvecDestroy(pPager->pInStmt);
- pPager->pInStmt = 0;
- }else{
- for(pPg=pPager->pStmt; pPg; pPg=pNext){
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- pNext = pHist->pNextStmt;
- assert( pHist->inStmt );
- pHist->inStmt = 0;
- pHist->pPrevStmt = pHist->pNextStmt = 0;
- sqlite3PageFree(pHist->pStmt);
- pHist->pStmt = 0;
- }
- }
+ sqlite3BitvecDestroy(pPager->pInStmt);
+ pPager->pInStmt = 0;
pPager->stmtNRec = 0;
pPager->stmtInUse = 0;
- pPager->pStmt = 0;
- }
- pPager->stmtAutoopen = 0;
- pagerLeave(pPager);
+ if( sqlite3IsMemJournal(pPager->stfd) ){
+ sqlite3OsTruncate(pPager->stfd, 0);
+ }
+ }
+ pPager->stmtAutoopen = 0;
return SQLITE_OK;
}
/*
@@ -30187,34 +31743,16 @@
** Rollback a statement.
*/
SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager *pPager){
int rc;
- pagerEnter(pPager);
if( pPager->stmtInUse ){
PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
- if( MEMDB ){
- PgHdr *pPg;
- PgHistory *pHist;
- for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){
- pHist = PGHDR_TO_HIST(pPg, pPager);
- if( pHist->pStmt ){
- memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize);
- sqlite3PageFree(pHist->pStmt);
- pHist->pStmt = 0;
- }
- }
- pPager->dbSize = pPager->stmtSize;
- pager_truncate_cache(pPager);
- rc = SQLITE_OK;
- }else{
- rc = pager_stmt_playback(pPager);
- }
+ rc = pager_stmt_playback(pPager);
sqlite3PagerStmtCommit(pPager);
}else{
rc = SQLITE_OK;
}
pPager->stmtAutoopen = 0;
- pagerLeave(pPager);
return rc;
}
/*
@@ -30281,9 +31819,9 @@
** Move the page pPg to location pgno in the file.
**
** 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
** meta-data associated with pPg (i.e. data stored in the nExtra bytes
@@ -30292,60 +31830,60 @@
** A transaction must be active when this routine is called. It used to be
** required that a statement transaction was not active, but this restriction
** has been removed (CREATE INDEX needs to move a page when a statement
** transaction is active).
-*/
-SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){
- PgHdr *pPgOld; /* The page being overwritten. */
- int h;
+**
+** If the fourth argument, isCommit, is non-zero, then this page is being
+** moved as part of a database reorganization just before the transaction
+** is being committed. In this case, it is guaranteed that the database page
+** pPg refers to will not be written to again within this transaction.
+*/
+SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
+ PgHdr *pPgOld; /* The page being overwritten. */
Pgno needSyncPgno = 0;
- pagerEnter(pPager);
assert( pPg->nRef>0 );
PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n",
- PAGERID(pPager), pPg->pgno, pPg->needSync, pgno);
+ PAGERID(pPager), pPg->pgno, (pPg->flags&PGHDR_NEED_SYNC)?1:0, pgno);
IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno))
pager_get_content(pPg);
- if( pPg->needSync ){
+
+ /* If the journal needs to be sync()ed before page pPg->pgno can
+ ** be written to, store pPg->pgno in local variable needSyncPgno.
+ **
+ ** If the isCommit flag is set, there is no need to remember that
+ ** the journal needs to be sync()ed before database page pPg->pgno
+ ** can be written to. The caller has already promised not to write to it.
+ */
+ if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
needSyncPgno = pPg->pgno;
- assert( pPg->inJournal || (int)pgno>pPager->origDbSize );
- assert( pPg->dirty );
+ assert( (pPg->flags&PGHDR_IN_JOURNAL) || (int)pgno>pPager->origDbSize );
+ assert( pPg->flags&PGHDR_DIRTY );
assert( pPager->needSync );
}
-
- /* Unlink pPg from its hash-chain */
- unlinkHashChain(pPager, pPg);
/* If the cache contains a page with page-number pgno, remove it
** from its hash chain. Also, if the PgHdr.needSync was set for
** page pgno before the 'move' operation, it needs to be retained
** for the page moved there.
*/
- pPg->needSync = 0;
+ pPg->flags &= ~(PGHDR_NEED_SYNC|PGHDR_IN_JOURNAL);
pPgOld = pager_lookup(pPager, pgno);
+ assert( !pPgOld || pPgOld->nRef==1 );
+ if( pPgOld ){
+ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
+ }
+ if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
+ pPg->flags |= PGHDR_IN_JOURNAL;
+ }
+
+ sqlite3PcacheMove(pPg, pgno);
if( pPgOld ){
- assert( pPgOld->nRef==0 );
- unlinkHashChain(pPager, pPgOld);
- makeClean(pPgOld);
- pPg->needSync = pPgOld->needSync;
- }else{
- pPg->needSync = 0;
- }
- pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
-
- /* Change the page number for pPg and insert it into the new hash-chain. */
- assert( pgno!=0 );
- pPg->pgno = pgno;
- h = pgno & (pPager->nHash-1);
- if( pPager->aHash[h] ){
- assert( pPager->aHash[h]->pPrevHash==0 );
- pPager->aHash[h]->pPrevHash = pPg;
- }
- pPg->pNextHash = pPager->aHash[h];
- pPager->aHash[h] = pPg;
- pPg->pPrevHash = 0;
+ sqlite3PcacheMove(pPgOld, 0);
+ sqlite3PcacheRelease(pPgOld);
+ }
makeDirty(pPg);
pPager->dirtyCache = 1;
pPager->dbModified = 1;
@@ -30353,10 +31891,11 @@
if( needSyncPgno ){
/* If needSyncPgno is non-zero, then the journal file needs to be
** sync()ed before any data is written to database file page needSyncPgno.
** Currently, no such page exists in the page-cache and the
- ** Pager.pInJournal bit has been set. This needs to be remedied by loading
- ** the page into the pager-cache and setting the PgHdr.needSync flag.
+ ** "is journaled" bitvec flag has been set. This needs to be remedied by
+ ** loading the page into the pager-cache and setting the PgHdr.needSync
+ ** flag.
**
** If the attempt to load the page into the page-cache fails, (due
** to a malloc() or IO failure), clear the bit in the pInJournal[]
** array. Otherwise, if the page is loaded and written again in
@@ -30374,19 +31913,18 @@
if( rc!=SQLITE_OK ){
if( pPager->pInJournal && (int)needSyncPgno<=pPager->origDbSize ){
sqlite3BitvecClear(pPager->pInJournal, needSyncPgno);
}
- pagerLeave(pPager);
return rc;
}
pPager->needSync = 1;
- pPgHdr->needSync = 1;
- pPgHdr->inJournal = 1;
+ assert( pPager->noSync==0 && !MEMDB );
+ pPgHdr->flags |= PGHDR_NEED_SYNC;
+ pPgHdr->flags |= PGHDR_IN_JOURNAL;
makeDirty(pPgHdr);
sqlite3PagerUnref(pPgHdr);
}
- pagerLeave(pPager);
return SQLITE_OK;
}
#endif
@@ -30393,9 +31931,10 @@
/*
** Return a pointer to the data for the specified page.
*/
SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
- return PGHDR_TO_DATA(pPg);
+ assert( pPg->nRef>0 || pPg->pPager->memDb );
+ return pPg->pData;
}
/*
** Return a pointer to the Pager.nExtra bytes of "extra" space
@@ -30402,9 +31941,9 @@
** allocated along with the specified page.
*/
SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
Pager *pPager = pPg->pPager;
- return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0);
+ return (pPager?pPg->pExtra:0);
}
/*
** Get/set the locking-mode for this pager. Parameter eMode must be one
@@ -30428,26 +31967,36 @@
return (int)pPager->exclusiveMode;
}
/*
-** Get/set the journal-mode for this pager. Parameter eMode must be one
-** of PAGER_JOURNALMODE_QUERY, PAGER_JOURNALMODE_DELETE or
-** PAGER_JOURNALMODE_PERSIST. If the parameter is not _QUERY, then
-** the journal-mode is set to the value specified.
-**
-** The returned value is either PAGER_JOURNALMODE_DELETE or
-** PAGER_JOURNALMODE_PERSIST, indicating the current (possibly updated)
+** 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 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;
}
@@ -30476,9 +32025,9 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
**
-** $Id: btmutex.c,v 1.10 2008/07/14 19:39:17 drh Exp $
+** $Id: btmutex.c,v 1.11 2008/10/07 15:25:48 drh Exp $
**
** This file contains code used to implement mutexes on Btree objects.
** This code really belongs in btree.c. But btree.c is getting too
** big and we want to break it down some. This packaged seemed like
@@ -30496,9 +32045,9 @@
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btreeInt.h,v 1.26 2008/07/12 14:52:20 drh Exp $
+** $Id: btreeInt.h,v 1.34 2008/09/30 17:18:17 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
@@ -30753,23 +32302,20 @@
** stored in MemPage.pBt->mutex.
*/
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 */
- u8 zeroData; /* True if table stores keys only */
- u8 leafData; /* True if tables stores data on leaves only */
u8 hasData; /* True if this page stores data */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
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 */
struct _OvflCell { /* Cells that will not fit on aData[] */
u8 *pCell; /* Pointers to the body of the overflow cell */
u16 idx; /* Insert this cell before idx-th non-overflow cell */
} aOvfl[5];
@@ -30776,9 +32322,8 @@
BtShared *pBt; /* Pointer to BtShared that this page is part of */
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 */
};
/*
** The in-memory image of a disk page has the auxiliary information appended
@@ -30898,8 +32443,19 @@
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.
**
** The entry is identified by its MemPage and the index in
@@ -30917,10 +32473,8 @@
BtShared *pBt; /* The BtShared this cursor points to */
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 validNKey; /* True if info.nKey is valid */
@@ -30931,8 +32485,14 @@
#ifndef SQLITE_OMIT_INCRBLOB
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] */
};
/*
** Potential values for BtCursor.eState.
@@ -31010,9 +32570,9 @@
** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
** this test.
*/
#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno)
-#define PTRMAP_PTROFFSET(pBt, pgno) (5*(pgno-ptrmapPageno(pBt, pgno)-1))
+#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1))
#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno))
/*
** The pointer map is a lookup table that identifies the parent page for
@@ -31084,8 +32644,9 @@
int nPage; /* Number of pages in the database */
int *anRef; /* Number of times each page is referenced */
int mxErr; /* Stop accumulating errors when this reaches zero */
int nErr; /* Number of messages written to zErrMsg so far */
+ int mallocFailed; /* A memory allocation error has occurred */
StrAccum errMsg; /* Accumulate the error message text here */
};
/*
@@ -31099,15 +32660,14 @@
/*
** 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 ********************************************/
/************** Continuing where we left off in btmutex.c ********************/
@@ -31153,9 +32713,8 @@
if( !p->sharable ) return;
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.
*/
@@ -31185,9 +32744,8 @@
sqlite3_mutex_enter(pLater->pBt->mutex);
pLater->locked = 1;
}
}
-#endif /* SQLITE_MUTEX_NOOP */
}
/*
** Exit the recursive mutex on a Btree.
@@ -31421,9 +32979,9 @@
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.482 2008/07/12 14:52:20 drh Exp $
+** $Id: btree.c,v 1.526 2008/10/27 13:59:34 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
@@ -31445,24 +33003,35 @@
#else
# define TRACE(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.
-*/
-#ifdef SQLITE_TEST
-SQLITE_PRIVATE BtShared *sqlite3SharedCacheList = 0;
-SQLITE_PRIVATE int sqlite3SharedCacheEnabled = 0;
-#else
-static BtShared *sqlite3SharedCacheList = 0;
-static int sqlite3SharedCacheEnabled = 0;
+/*
+** Sometimes we need a small amount of code such as a variable initialization
+** to setup for a later assert() statement. We do not want this code to
+** appear when assert() is disabled. The following macro is therefore
+** used to contain that setup code. The "VVA" acronym stands for
+** "Verification, Validation, and Accreditation". In other words, the
+** code within VVA_ONLY() will only run during verification processes.
+*/
+#ifndef NDEBUG
+# define VVA_ONLY(X) X
+#else
+# define VVA_ONLY(X)
+#endif
+
+
+
+#ifndef SQLITE_OMIT_SHARED_CACHE
+/*
+** A list of BtShared objects that are eligible for participation
+** in shared cache. This variable has file scope during normal builds,
+** but the test harness needs to access it so we make it global for
+** test builds.
+*/
+#ifdef SQLITE_TEST
+SQLITE_PRIVATE BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
+#else
+static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
#endif
#endif /* SQLITE_OMIT_SHARED_CACHE */
#ifndef SQLITE_OMIT_SHARED_CACHE
@@ -31473,9 +33042,9 @@
** The shared cache setting effects only future calls to
** 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
@@ -31715,9 +33284,9 @@
** all that is required. Otherwise, if pCur is not open on an intKey
** 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);
if( rc==SQLITE_OK ){
@@ -31728,13 +33297,17 @@
}else{
rc = SQLITE_NOMEM;
}
}
- assert( !pCur->pPage->intKey || !pCur->pKey );
-
- if( rc==SQLITE_OK ){
- releasePage(pCur->pPage);
- pCur->pPage = 0;
+ assert( !pCur->apPage[0]->intKey || !pCur->pKey );
+
+ if( rc==SQLITE_OK ){
+ int i;
+ for(i=0; i<=pCur->iPage; i++){
+ releasePage(pCur->apPage[i]);
+ pCur->apPage[i] = 0;
+ }
+ pCur->iPage = -1;
pCur->eState = CURSOR_REQUIRESEEK;
}
invalidateOverflowCache(pCur);
@@ -31764,9 +33337,9 @@
/*
** 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;
pCur->eState = CURSOR_INVALID;
@@ -31786,9 +33359,9 @@
if( pCur->eState==CURSOR_FAULT ){
return pCur->skip;
}
pCur->eState = CURSOR_INVALID;
- rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip);
+ rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip);
if( rc==SQLITE_OK ){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
@@ -31869,9 +33442,9 @@
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage);
if( rc!=SQLITE_OK ){
return rc;
}
- offset = PTRMAP_PTROFFSET(pBt, key);
+ offset = PTRMAP_PTROFFSET(iPtrmap, key);
pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){
TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent));
@@ -31908,9 +33481,9 @@
return rc;
}
pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
- offset = PTRMAP_PTROFFSET(pBt, key);
+ offset = PTRMAP_PTROFFSET(iPtrmap, key);
assert( pEType!=0 );
*pEType = pPtrmap[offset];
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
@@ -31918,9 +33491,13 @@
if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;
return SQLITE_OK;
}
-#endif /* SQLITE_OMIT_AUTOVACUUM */
+#else /* if defined SQLITE_OMIT_AUTOVACUUM */
+ #define ptrmapPut(w,x,y,z) SQLITE_OK
+ #define ptrmapGet(w,x,y,z) SQLITE_OK
+ #define ptrmapPutOvfl(y,z) SQLITE_OK
+#endif
/*
** Given a btree page and a cell index (0 means the first cell on
** the page, 1 means the second cell, and so forth) return a pointer
@@ -31927,10 +33504,10 @@
** to the cell content.
**
** This routine works only for pages that do not contain overflow cells.
*/
-#define findCell(pPage, iCell) \
- ((pPage)->aData + get2byte(&(pPage)->aData[(pPage)->cellOffset+2*(iCell)]))
+#define findCell(P,I) \
+ ((P)->aData + ((P)->maskPage & get2byte(&(P)->aData[(P)->cellOffset+2*(I)])))
/*
** This a more complex version of findCell() that works for
** pages that do contain overflow cells. See insert
@@ -31975,33 +33552,32 @@
pInfo->pCell = pCell;
assert( pPage->leaf==0 || pPage->leaf==1 );
n = pPage->childPtrSize;
assert( n==4-4*pPage->leaf );
- if( pPage->hasData ){
- n += getVarint32(&pCell[n], nPayload);
- }else{
- nPayload = 0;
- }
- pInfo->nData = nPayload;
if( pPage->intKey ){
- n += getVarint(&pCell[n], (u64 *)&pInfo->nKey);
- }else{
- u32 x;
- n += getVarint32(&pCell[n], x);
- pInfo->nKey = x;
- nPayload += x;
+ if( pPage->hasData ){
+ n += getVarint32(&pCell[n], nPayload);
+ }else{
+ nPayload = 0;
+ }
+ n += getVarint(&pCell[n], (u64*)&pInfo->nKey);
+ pInfo->nData = nPayload;
+ }else{
+ pInfo->nData = 0;
+ n += getVarint32(&pCell[n], nPayload);
+ pInfo->nKey = nPayload;
}
pInfo->nPayload = nPayload;
pInfo->nHeader = n;
- if( nPayload<=pPage->maxLocal ){
+ if( likely(nPayload<=pPage->maxLocal) ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
*/
int nSize; /* Total size of cell content in bytes */
+ nSize = nPayload + n;
pInfo->nLocal = nPayload;
pInfo->iOverflow = 0;
- nSize = nPayload + n;
- if( nSize<4 ){
+ if( (nSize & ~3)==0 ){
nSize = 4; /* Minimum cell size is 4 */
}
pInfo->nSize = nSize;
}else{
@@ -32103,9 +33679,9 @@
int hdr; /* Offset to the page header */
int size; /* Size of a cell */
int usableSize; /* Number of usable bytes on a page */
int cellOffset; /* Offset to the cell pointer array */
- int brk; /* Offset to the cell content area */
+ int cbrk; /* Offset to the cell content area */
int nCell; /* Number of cells on the page */
unsigned char *data; /* The page data */
unsigned char *temp; /* Temp area for cell content */
@@ -32120,28 +33696,28 @@
cellOffset = pPage->cellOffset;
nCell = pPage->nCell;
assert( nCell==get2byte(&data[hdr+3]) );
usableSize = pPage->pBt->usableSize;
- brk = get2byte(&data[hdr+5]);
- memcpy(&temp[brk], &data[brk], usableSize - brk);
- brk = usableSize;
+ cbrk = get2byte(&data[hdr+5]);
+ memcpy(&temp[cbrk], &data[cbrk], usableSize - cbrk);
+ cbrk = usableSize;
for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */
pAddr = &data[cellOffset + i*2];
pc = get2byte(pAddr);
assert( pc<pPage->pBt->usableSize );
size = cellSizePtr(pPage, &temp[pc]);
- brk -= size;
- memcpy(&data[brk], &temp[pc], size);
- put2byte(pAddr, brk);
- }
- assert( brk>=cellOffset+2*nCell );
- put2byte(&data[hdr+5], brk);
+ cbrk -= size;
+ memcpy(&data[cbrk], &temp[pc], size);
+ put2byte(pAddr, cbrk);
+ }
+ assert( cbrk>=cellOffset+2*nCell );
+ put2byte(&data[hdr+5], cbrk);
data[hdr+1] = 0;
data[hdr+2] = 0;
data[hdr+7] = 0;
addr = cellOffset+2*nCell;
- memset(&data[addr], 0, brk-addr);
+ memset(&data[addr], 0, cbrk-addr);
}
/*
** Allocate nByte bytes of space on a page.
@@ -32282,127 +33858,132 @@
/*
** Decode the flags byte (the first byte of the header) for a page
** and initialize fields of the MemPage structure accordingly.
-*/
-static void decodeFlags(MemPage *pPage, int flagByte){
+**
+** Only the following combinations are supported. Anything different
+** indicates a corrupt database files:
+**
+** PTF_ZERODATA
+** PTF_ZERODATA | PTF_LEAF
+** PTF_LEAFDATA | PTF_INTKEY
+** PTF_LEAFDATA | PTF_INTKEY | PTF_LEAF
+*/
+static int decodeFlags(MemPage *pPage, int flagByte){
BtShared *pBt; /* A copy of pPage->pBt */
assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0;
- pPage->zeroData = (flagByte & PTF_ZERODATA)!=0;
- pPage->leaf = (flagByte & PTF_LEAF)!=0;
- pPage->childPtrSize = 4*(pPage->leaf==0);
+ pPage->leaf = flagByte>>3; assert( PTF_LEAF == 1<<3 );
+ flagByte &= ~PTF_LEAF;
+ pPage->childPtrSize = 4-4*pPage->leaf;
pBt = pPage->pBt;
- if( flagByte & PTF_LEAFDATA ){
- pPage->leafData = 1;
+ if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
+ pPage->intKey = 1;
+ pPage->hasData = pPage->leaf;
pPage->maxLocal = pBt->maxLeaf;
pPage->minLocal = pBt->minLeaf;
- }else{
- pPage->leafData = 0;
+ }else if( flagByte==PTF_ZERODATA ){
+ pPage->intKey = 0;
+ pPage->hasData = 0;
pPage->maxLocal = pBt->maxLocal;
pPage->minLocal = pBt->minLocal;
- }
- pPage->hasData = !(pPage->zeroData || (!pPage->leaf && pPage->leafData));
-}
-
-/*
-** 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.
+ }else{
+ return SQLITE_CORRUPT_BKPT;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Initialize the auxiliary information for a disk block.
**
** 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 */
- u8 *pOff; /* Iterator used to check all cell offsets are in range */
- u8 *pEnd; /* Pointer to end of cell offset array */
- u8 mask; /* Mask of bits that must be zero in MSB of cell offsets */
-
- pBt = pPage->pBt;
- assert( pBt!=0 );
- assert( pParent==0 || pParent->pBt==pBt );
- assert( sqlite3_mutex_held(pBt->mutex) );
+SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage){
+
+ 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;
- decodeFlags(pPage, data[hdr]);
- 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 */
+
+ 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;
+ }
+ 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.
+ **
+ ** Omitting this consistency check and using the pPage->maskPage mask
+ ** to prevent overrunning the page buffer in findCell() results in a
+ ** 2.5% performance gain.
+ */
+ {
+ u8 *pOff; /* Iterator used to check all cell offsets are in range */
+ u8 *pEnd; /* Pointer to end of cell offset array */
+ u8 mask; /* Mask of bits that must be zero in MSB of cell offsets */
+ mask = ~(((u8)(pBt->pageSize>>8))-1);
+ pEnd = &data[cellOffset + pPage->nCell*2];
+ for(pOff=&data[cellOffset]; pOff!=pEnd && !((*pOff)&mask); pOff+=2);
+ if( pOff!=pEnd ){
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;
- }
- pPage->nFree = nFree;
- if( nFree>=usableSize ){
- /* Free space cannot exceed total page size */
- return SQLITE_CORRUPT_BKPT;
- }
-
- /* Check that all the offsets in the cell offset array are within range. */
- mask = ~(((u8)(pBt->pageSize>>8))-1);
- pEnd = &data[cellOffset + pPage->nCell*2];
- for(pOff=&data[cellOffset]; pOff!=pEnd && !((*pOff)&mask); pOff+=2);
- if( pOff!=pEnd ){
- return SQLITE_CORRUPT_BKPT;
- }
-
- pPage->isInit = 1;
+ }
+#endif
+
+ pPage->isInit = 1;
+ }
return SQLITE_OK;
}
/*
@@ -32419,9 +34000,9 @@
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pBt->mutex) );
- memset(&data[hdr], 0, pBt->usableSize - hdr);
+ /*memset(&data[hdr], 0, pBt->usableSize - hdr);*/
data[hdr] = flags;
first = hdr + 8 + 4*((flags&PTF_LEAF)==0);
memset(&data[hdr+1], 0, 4);
data[hdr+7] = 0;
@@ -32430,11 +34011,27 @@
decodeFlags(pPage, flags);
pPage->hdrOffset = hdr;
pPage->cellOffset = first;
pPage->nOverflow = 0;
- pPage->idxShift = 0;
+ assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
+ pPage->maskPage = pBt->pageSize - 1;
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
@@ -32453,22 +34050,26 @@
MemPage **ppPage, /* Return the page in this parameter */
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;
- return SQLITE_OK;
+ *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
@@ -32477,23 +34078,44 @@
*/
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 */
-){
- int rc;
+ 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;
}
@@ -32512,42 +34134,24 @@
}
}
/*
-** This routine is called when the reference count for a page
-** reaches zero. We need to unref the pParent pointer when that
-** happens.
-*/
-static void pageDestructor(DbPage *pData, int pageSize){
- MemPage *pPage;
- assert( (pageSize & 7)==0 );
- pPage = (MemPage *)sqlite3PagerGetExtra(pData);
- assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
- if( pPage->pParent ){
- MemPage *pParent = pPage->pParent;
- assert( pParent->pBt==pPage->pBt );
- pPage->pParent = 0;
- releasePage(pParent);
- }
- pPage->isInit = 0;
-}
-
-/*
** During a rollback, when the pager reloads information into the cache
** so that the cache is restored to its original state at the start of
** the transaction, for each page restored this routine is called.
**
** 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){
- MemPage *pPage;
- assert( (pageSize & 7)==0 );
+static void pageReinit(DbPage *pData){
+ MemPage *pPage;
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);
+ }
}
}
/*
@@ -32615,9 +34219,9 @@
if( isMemdb==0
&& (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;
p->sharable = 1;
@@ -32628,9 +34232,9 @@
}
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 ){
p->pBt = pBt;
@@ -32682,9 +34286,8 @@
}
sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr);
p->pBt = pBt;
- sqlite3PagerSetDestructor(pBt->pPager, pageDestructor);
sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
pBt->pCursor = 0;
pBt->pPage1 = 0;
pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager);
@@ -32724,9 +34327,9 @@
if( p->sharable ){
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;
db->mallocFailed = 0;
@@ -32733,10 +34336,10 @@
goto btree_open_out;
}
}
sqlite3_mutex_enter(mutexShared);
- pBt->pNext = sqlite3SharedCacheList;
- sqlite3SharedCacheList = pBt;
+ pBt->pNext = GLOBAL(BtShared*,sqlite3SharedCacheList);
+ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt;
sqlite3_mutex_leave(mutexShared);
}
#endif
}
@@ -32802,12 +34405,12 @@
pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(pMaster);
pBt->nRef--;
if( pBt->nRef<=0 ){
- if( sqlite3SharedCacheList==pBt ){
- sqlite3SharedCacheList = pBt->pNext;
- }else{
- pList = sqlite3SharedCacheList;
+ if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
+ GLOBAL(BtShared*,sqlite3SharedCacheList) = pBt->pNext;
+ }else{
+ pList = GLOBAL(BtShared*,sqlite3SharedCacheList);
while( ALWAYS(pList) && pList->pNext!=pBt ){
pList=pList->pNext;
}
if( ALWAYS(pList) ){
@@ -33403,8 +35006,9 @@
sqlite3BtreeLeave(p);
return rc;
}
+
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** Set the pointer-map entries for all children of page pPage. Also, if
@@ -33419,9 +35023,9 @@
int isInitOrig = pPage->isInit;
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;
}
nCell = pPage->nCell;
@@ -33436,9 +35040,9 @@
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;
}
}
if( !pPage->leaf ){
@@ -33478,9 +35082,9 @@
int isInitOrig = pPage->isInit;
int i;
int nCell;
- sqlite3BtreeInitPage(pPage, 0);
+ sqlite3BtreeInitPage(pPage);
nCell = pPage->nCell;
for(i=0; i<nCell; i++){
u8 *pCell = findCell(pPage, i);
@@ -33523,9 +35127,10 @@
BtShared *pBt, /* Btree */
MemPage *pDbPage, /* Open page to move */
u8 eType, /* Pointer map 'type' entry for pDbPage */
Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */
- Pgno iFreePage /* The location to move pDbPage to */
+ Pgno iFreePage, /* The location to move pDbPage to */
+ int isCommit
){
MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */
Pgno iDbPage = pDbPage->pgno;
Pager *pPager = pBt->pPager;
@@ -33538,9 +35143,9 @@
/* Move page iDbPage from its current location to page number iFreePage */
TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
iDbPage, iFreePage, iPtrPage, eType));
- rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage);
+ rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit);
if( rc!=SQLITE_OK ){
return rc;
}
pDbPage->pgno = iFreePage;
@@ -33588,15 +35193,8 @@
rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
}
}
return rc;
-}
-
-static int pagerPagecount(Pager *pPager){
- int rc;
- int nPage;
- rc = sqlite3PagerPagecount(pPager, &nPage);
- return (rc==SQLITE_OK?nPage:-1);
}
/* Forward declaration required by incrVacuumStep(). */
static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
@@ -33688,9 +35286,9 @@
assert( iFreePg<iLastPg );
rc = sqlite3PagerWrite(pLastPg->pDbPage);
if( rc==SQLITE_OK ){
- rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg);
+ rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0);
}
releasePage(pLastPg);
if( rc!=SQLITE_OK ){
return rc;
@@ -33741,11 +35339,9 @@
*/
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);
assert(pBt->autoVacuum);
@@ -33967,9 +35563,9 @@
SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
BtCursor *p;
sqlite3BtreeEnter(pBtree);
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
- clearCursorPosition(p);
+ sqlite3BtreeClearCursor(p);
p->eState = CURSOR_FAULT;
p->skip = errCode;
}
sqlite3BtreeLeave(pBtree);
@@ -34144,8 +35740,11 @@
**
** 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 */
int iTable, /* Root page of table to open */
@@ -34179,9 +35778,9 @@
if( iTable==1 && pagerPagecount(pBt->pPager)==0 ){
rc = SQLITE_EMPTY;
goto create_cursor_exception;
}
- rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0);
+ rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
@@ -34202,9 +35801,9 @@
return SQLITE_OK;
create_cursor_exception:
- releasePage(pCur->pPage);
+ releasePage(pCur->apPage[0]);
unlockBtreeIfUnused(pBt);
return rc;
}
SQLITE_PRIVATE int sqlite3BtreeCursor(
@@ -34233,12 +35832,13 @@
*/
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{
pBt->pCursor = pCur->pNext;
@@ -34245,9 +35845,11 @@
}
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); */
sqlite3BtreeLeave(pBtree);
@@ -34259,14 +35861,15 @@
** Make a temporary cursor by filling in the fields of pTempCur.
** The temporary cursor is not on the cursor list for the Btree.
*/
SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){
- assert( cursorHoldsMutex(pCur) );
- memcpy(pTempCur, pCur, sizeof(*pCur));
+ int i;
+ assert( cursorHoldsMutex(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);
}
}
/*
@@ -34273,11 +35876,12 @@
** Delete a temporary cursor such as was made by the CreateTemporaryCursor()
** function above.
*/
SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){
- assert( cursorHoldsMutex(pCur) );
- if( pCur->pPage ){
- sqlite3PagerUnref(pCur->pPage->pDbPage);
+ int i;
+ assert( cursorHoldsMutex(pCur) );
+ for(i=0; i<=pCur->iPage; i++){
+ sqlite3PagerUnref(pCur->apPage[i]->pDbPage);
}
}
/*
@@ -34297,10 +35901,11 @@
*/
#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
#define assertCellInfo(x)
@@ -34308,22 +35913,24 @@
#ifdef _MSC_VER
/* 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 */
/*
@@ -34534,14 +36141,14 @@
unsigned char *aPayload;
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) );
getCellInfo(pCur);
@@ -34552,9 +36159,9 @@
offset += nKey;
}
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. */
if( offset<pCur->info.nLocal ){
@@ -34672,14 +36279,13 @@
assert( cursorHoldsMutex(pCur) );
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;
}
@@ -34705,10 +36311,10 @@
assert( cursorHoldsMutex(pCur) );
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;
}
@@ -34741,13 +36347,13 @@
MemPage *pPage;
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;
if( pPage->intKey ){
@@ -34804,22 +36410,24 @@
** page number of the child page to move to.
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
int rc;
- MemPage *pNewPage;
- MemPage *pOldPage;
+ int i = pCur->iPage;
+ MemPage *pNewPage;
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_CORRUPT_BKPT;
@@ -34826,27 +36434,27 @@
}
return SQLITE_OK;
}
-/*
-** 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.
-*/
-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;
-}
+#ifndef NDEBUG
+/*
+** Page pParent is an internal (non-leaf) tree page. This function
+** asserts that page number iChild is the left-child if the iIdx'th
+** cell in page pParent. Or, if iIdx is equal to the total number of
+** cells in pParent, that page number iChild is the right-child of
+** the page.
+*/
+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.
**
@@ -34855,27 +36463,21 @@
** right-most child page then pCur->idx is set to one more than
** 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 );
- 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;
}
/*
** Move the cursor to the root page
@@ -34893,36 +36495,43 @@
if( pCur->eState>=CURSOR_REQUIRESEEK ){
if( pCur->eState==CURSOR_FAULT ){
return pCur->skip;
}
- clearCursorPosition(pCur);
- }
- pRoot = pCur->pPage;
- if( pRoot && pRoot->pgno==pCur->pgnoRoot ){
- assert( pRoot->isInit );
+ sqlite3BtreeClearCursor(pCur);
+ }
+
+ 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 );
subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
assert( subpage>0 );
pCur->eState = CURSOR_VALID;
rc = moveToChild(pCur, subpage);
- }
- pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
+ }else{
+ pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
+ }
return rc;
}
/*
@@ -34938,11 +36547,11 @@
MemPage *pPage;
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;
}
@@ -34963,19 +36572,19 @@
MemPage *pPage;
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
** on success. Set *pRes to 0 if the cursor actually points to something
@@ -34988,13 +36597,13 @@
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
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);
}
}
@@ -35012,9 +36621,9 @@
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
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 );
*pRes = 0;
@@ -35026,14 +36635,13 @@
return rc;
}
/* Move the cursor so that it points to an entry near the key
-** specified by pKey/nKey/pUnKey. Return a success code.
-**
-** For INTKEY tables, only the nKey parameter is used. pKey
-** and pUnKey must be NULL. For index tables, either pUnKey
-** must point to a key that has already been unpacked, or else
-** pKey/nKey describes a blob containing the key.
+** specified by pIdxKey or intKey. Return a success code.
+**
+** For INTKEY tables, the intKey parameter is used. pIdxKey
+** must be NULL. For index tables, pIdxKey is used and intKey
+** is ignored.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
** were present. The cursor might point to an entry that comes
@@ -35053,124 +36661,107 @@
** *pRes>0 The cursor is left pointing at an entry that
** is larger than pKey.
**
*/
-SQLITE_PRIVATE int sqlite3BtreeMoveto(
- BtCursor *pCur, /* The cursor to be moved */
- const void *pKey, /* The key content for indices. Not used by tables */
- UnpackedRecord *pUnKey,/* Unpacked version of pKey */
- i64 nKey, /* Size of pKey. Or the key for tables */
- int biasRight, /* If true, bias the search to the high end */
- int *pRes /* Search result flag */
-){
- int rc;
- char aSpace[200];
+SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
+ BtCursor *pCur, /* The cursor to be moved */
+ UnpackedRecord *pIdxKey, /* Unpacked index key */
+ i64 intKey, /* The table key */
+ int biasRight, /* If true, bias the search to the high end */
+ int *pRes /* Write search results here */
+){
+ int rc;
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
- if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){
- if( pCur->info.nKey==nKey ){
+ if( pCur->eState==CURSOR_VALID && pCur->validNKey
+ && pCur->apPage[0]->intKey
+ ){
+ if( pCur->info.nKey==intKey ){
*pRes = 0;
return SQLITE_OK;
}
- if( pCur->atLast && pCur->info.nKey<nKey ){
+ if( pCur->atLast && pCur->info.nKey<intKey ){
*pRes = -1;
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 );
- return SQLITE_OK;
- }
- if( pCur->pPage->intKey ){
- /* We are given an SQL table to search. The key is the integer
- ** rowid contained in nKey. pKey and pUnKey should both be NULL */
- assert( pUnKey==0 );
- assert( pKey==0 );
- }else if( pUnKey==0 ){
- /* We are to search an SQL index using a key encoded as a blob.
- ** The blob is found at pKey and is nKey bytes in length. Unpack
- ** this key so that we can use it. */
- assert( pKey!=0 );
- pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
- aSpace, sizeof(aSpace));
- if( pUnKey==0 ) return SQLITE_NOMEM;
- }else{
- /* We are to search an SQL index using a key that is already unpacked
- ** and handed to us in pUnKey. */
- assert( pKey==0 );
- }
+ assert( pCur->apPage[pCur->iPage]->nCell==0 );
+ return SQLITE_OK;
+ }
+ 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;
- if( !pPage->intKey && pUnKey==0 ){
+ if( !pPage->intKey && pIdxKey==0 ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
if( biasRight ){
- pCur->idx = upr;
- }else{
- pCur->idx = (upr+lwr)/2;
+ pCur->aiIdx[pCur->iPage] = upr;
+ }else{
+ 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);
}
getVarint(pCell, (u64*)&nCellKey);
- if( nCellKey==nKey ){
+ if( nCellKey==intKey ){
c = 0;
- }else if( nCellKey<nKey ){
+ }else if( nCellKey<intKey ){
c = -1;
}else{
- assert( nCellKey>nKey );
+ assert( nCellKey>intKey );
c = +1;
}
}else{
int available;
pCellKey = (void *)fetchPayload(pCur, &available, 0);
nCellKey = pCur->info.nKey;
if( available>=nCellKey ){
- c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
+ c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
}else{
pCellKey = sqlite3Malloc( nCellKey );
if( pCellKey==0 ){
rc = SQLITE_NOMEM;
goto moveto_finish;
}
rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
- c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
+ c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
if( rc ) goto moveto_finish;
}
}
if( c==0 ){
pCur->info.nKey = nCellKey;
- if( pPage->leafData && !pPage->leaf ){
- lwr = pCur->idx;
+ if( pPage->intKey && !pPage->leaf ){
+ lwr = idx;
upr = lwr - 1;
break;
}else{
if( pRes ) *pRes = 0;
@@ -35178,17 +36769,17 @@
goto moveto_finish;
}
}
if( c<0 ){
- lwr = pCur->idx+1;
- }else{
- upr = pCur->idx-1;
+ lwr = idx+1;
+ }else{
+ 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 );
if( pPage->leaf ){
@@ -35198,24 +36789,49 @@
}else{
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);
if( rc ) goto moveto_finish;
}
moveto_finish:
+ return rc;
+}
+
+/*
+** In this version of BtreeMoveto, pKey is a packed index record
+** such as is generated by the OP_MakeRecord opcode. Unpack the
+** record and then call BtreeMovetoUnpacked() to do the work.
+*/
+SQLITE_PRIVATE int sqlite3BtreeMoveto(
+ BtCursor *pCur, /* Cursor open on the btree to be searched */
+ const void *pKey, /* Packed key if the btree is an index */
+ i64 nKey, /* Integer key for tables. Size of pKey for indices */
+ int bias, /* Bias search to the high end */
+ int *pRes /* Write search results here */
+){
+ int rc; /* Status code */
+ UnpackedRecord *pIdxKey; /* Unpacked index key */
+ UnpackedRecord aSpace[16]; /* Temp space for pIdxKey - to avoid a malloc */
+
+ if( pKey ){
+ pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
+ aSpace, sizeof(aSpace));
+ if( pIdxKey==0 ) return SQLITE_NOMEM;
+ }else{
+ pIdxKey = 0;
+ }
+ rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
if( pKey ){
- /* If we created our own unpacked key at the top of this
- ** procedure, then destroy that key before returning. */
- sqlite3VdbeDeleteUnpackedRecord(pUnKey);
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
}
return rc;
}
@@ -35250,8 +36866,9 @@
** this routine was called, then set *pRes=1.
*/
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
int rc;
+ int idx;
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
rc = restoreCursorPosition(pCur);
@@ -35258,9 +36875,8 @@
if( rc!=SQLITE_OK ){
return rc;
}
assert( pRes!=0 );
- pPage = pCur->pPage;
if( CURSOR_INVALID==pCur->eState ){
*pRes = 1;
return SQLITE_OK;
}
@@ -35270,15 +36886,16 @@
return SQLITE_OK;
}
pCur->skip = 0;
+ pPage = pCur->apPage[pCur->iPage];
+ idx = ++pCur->aiIdx[pCur->iPage];
assert( pPage->isInit );
- assert( pCur->idx<pPage->nCell );
-
- pCur->idx++;
+ assert( idx<=pPage->nCell );
+
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;
rc = moveToLeftmost(pCur);
@@ -35285,18 +36902,18 @@
*pRes = 0;
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->leafData ){
+ if( pPage->intKey ){
rc = sqlite3BtreeNext(pCur, pRes);
}else{
rc = SQLITE_OK;
}
@@ -35318,9 +36935,8 @@
** this routine was called, then set *pRes=1.
*/
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int rc;
- Pgno pgno;
MemPage *pPage;
assert( cursorHoldsMutex(pCur) );
rc = restoreCursorPosition(pCur);
@@ -35338,32 +36954,32 @@
return SQLITE_OK;
}
pCur->skip = 0;
- pPage = pCur->pPage;
- assert( pPage->isInit );
- assert( pCur->idx>=0 );
+ pPage = pCur->apPage[pCur->iPage];
+ assert( pPage->isInit );
if( !pPage->leaf ){
- pgno = get4byte( findCell(pPage, pCur->idx) );
- rc = moveToChild(pCur, pgno);
+ int idx = pCur->aiIdx[pCur->iPage];
+ rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
if( rc ){
return rc;
}
rc = moveToRightmost(pCur);
}else{
- while( pCur->idx==0 ){
- if( sqlite3BtreeIsRootPage(pPage) ){
+ while( pCur->aiIdx[pCur->iPage]==0 ){
+ if( pCur->iPage==0 ){
pCur->eState = CURSOR_INVALID;
*pRes = 1;
return SQLITE_OK;
}
sqlite3BtreeMoveToParent(pCur);
- pPage = pCur->pPage;
- }
- pCur->idx--;
+ }
pCur->info.nSize = 0;
pCur->validNKey = 0;
- if( pPage->leafData && !pPage->leaf ){
+
+ pCur->aiIdx[pCur->iPage]--;
+ pPage = pCur->apPage[pCur->iPage];
+ if( pPage->intKey && !pPage->leaf ){
rc = sqlite3BtreePrevious(pCur, pRes);
}else{
rc = SQLITE_OK;
}
@@ -35630,8 +37246,12 @@
end_allocate_page:
releasePage(pTrunk);
releasePage(pPrevTrunk);
+ if( rc==SQLITE_OK && sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
+ releasePage(*ppPage);
+ return SQLITE_CORRUPT_BKPT;
+ }
return rc;
}
/*
@@ -35647,10 +37267,8 @@
/* Prepare the page for freeing */
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);
if( rc ) return rc;
@@ -35665,17 +37283,15 @@
if( rc ) return rc;
memset(pPage->aData, 0, pPage->pBt->pageSize);
#endif
-#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the database supports auto-vacuum, write an entry in the pointer-map
** to indicate that the page is free.
*/
- if( pBt->autoVacuum ){
+ if( ISAUTOVACUUM ){
rc = ptrmapPut(pBt, pPage->pgno, PTRMAP_FREEPAGE, 0);
if( rc ) return rc;
}
-#endif
if( n==0 ){
/* This is the first free page */
rc = sqlite3PagerWrite(pPage->pDbPage);
@@ -35721,9 +37337,9 @@
if( rc==SQLITE_OK ){
put4byte(&pTrunk->aData[4], k+1);
put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
#ifndef SQLITE_SECURE_DELETE
- sqlite3PagerDontWrite(pPage->pDbPage);
+ rc = sqlite3PagerDontWrite(pPage->pDbPage);
#endif
}
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
}
@@ -35905,75 +37521,8 @@
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.
-*/
-static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){
- 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);
- }
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- return ptrmapPut(pBt, pgno, PTRMAP_BTREE, pNewParent->pgno);
- }
-#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.
-*/
-static int reparentChildPages(MemPage *pPage){
- int i;
- BtShared *pBt = pPage->pBt;
- int rc = SQLITE_OK;
-
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- if( pPage->leaf ) return SQLITE_OK;
-
- for(i=0; i<pPage->nCell; i++){
- u8 *pCell = findCell(pPage, i);
- rc = reparentPage(pBt, get4byte(pCell), pPage, i);
- if( rc!=SQLITE_OK ) return rc;
- }
- rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]),
- pPage, i);
- 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
** the cell content has been copied someplace else. This routine just
** removes the reference to the cell from pPage.
@@ -36001,9 +37550,8 @@
}
pPage->nCell--;
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
pPage->nFree += 2;
- pPage->idxShift = 1;
}
/*
** Insert a new cell on pPage at cell index "i". pCell points to the
@@ -36081,9 +37629,8 @@
ptr[1] = ptr[-1];
}
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
** the entry for the overflow page into the pointer map.
@@ -36163,9 +37710,9 @@
#define NN 1 /* Number of neighbors on either side of pPage */
#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
/*
** This version of balance() handles the common special case where
@@ -36183,15 +37730,17 @@
** pPage is the leaf page which is the right-most page in the tree.
** 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){
- int rc;
- MemPage *pNew;
+static int balance_quick(BtCursor *pCur){
+ int rc;
+ MemPage *pNew = 0;
Pgno pgnoNew;
u8 *pCell;
u16 szCell;
CellInfo info;
+ MemPage *pPage = pCur->apPage[pCur->iPage];
+ MemPage *pParent = pCur->apPage[pCur->iPage-1];
BtShared *pBt = pPage->pBt;
int parentIdx = pParent->nCell; /* pParent new divider cell index */
int parentSize; /* Size of new divider cell */
u8 parentCell[64]; /* Space for the new divider cell */
@@ -36201,67 +37750,79 @@
/* Allocate a new page. Insert the overflow cell from pPage
** 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;
-
- /* Set the parent of the newly allocated page to pParent. */
- pNew->pParent = pParent;
- sqlite3PagerRef(pParent->pDbPage);
-
- /* pPage is currently the right-child of pParent. Change this
- ** so that the right-child is the new page allocated above and
- ** pPage is the next-to-right child.
- **
- ** 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);
-
-#ifndef SQLITE_OMIT_AUTOVACUUM
- /* 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( pBt->autoVacuum ){
- rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
- if( rc==SQLITE_OK ){
- rc = ptrmapPutOvfl(pNew, 0);
- }
- if( rc!=SQLITE_OK ){
- releasePage(pNew);
- return rc;
- }
- }
-#endif
-
- /* 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);
+ if( rc==SQLITE_OK ){
+ pCell = pPage->aOvfl[0].pCell;
+ szCell = cellSizePtr(pPage, pCell);
+ zeroPage(pNew, pPage->aData[0]);
+ assemblePage(pNew, 1, &pCell, &szCell);
+ pPage->nOverflow = 0;
+
+ /* pPage is currently the right-child of pParent. Change this
+ ** so that the right-child is the new page allocated above and
+ ** pPage is the next-to-right child.
+ **
+ ** Ignore the return value of the call to fillInCell(). fillInCell()
+ ** may only return other than SQLITE_OK if it is required to allocate
+ ** one or more overflow pages. Since an internal table B-Tree cell
+ ** may never spill over onto an overflow page (it is a maximum of
+ ** 13 bytes in size), it is not neccessary to check the return code.
+ **
+ ** Similarly, the insertCell() function cannot fail if the page
+ ** being inserted into is already writable and the cell does not
+ ** contain an overflow pointer. So ignore this return code too.
+ */
+ assert( pPage->nCell>0 );
+ pCell = findCell(pPage, pPage->nCell-1);
+ sqlite3BtreeParseCellPtr(pPage, pCell, &info);
+ fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize);
+ assert( parentSize<64 );
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4);
+ put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno);
+ put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
+
+ /* If this is an auto-vacuum database, update the pointer map
+ ** with entries for the new page, and any pointer from the
+ ** cell on the page to an overflow page.
+ */
+ if( ISAUTOVACUUM ){
+ rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
+ if( rc==SQLITE_OK ){
+ rc = ptrmapPutOvfl(pNew, 0);
+ }
+ }
+
+ /* Release the reference to the new page. */
+ releasePage(pNew);
+ }
+
+ /* 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.
+ **
+ ** 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.
+ */
+ pPage->isInit = 0;
+ sqlite3BtreeInitPage(pPage);
+
+ /* If everything else succeeded, balance the parent page, in
+ ** case the divider cell inserted caused it to become overfull.
+ */
+ if( rc==SQLITE_OK ){
+ releasePage(pPage);
+ pCur->iPage--;
+ rc = balance(pCur, 0);
+ }
+ return rc;
}
#endif /* SQLITE_OMIT_QUICKBALANCE */
/*
@@ -36292,9 +37853,10 @@
** If this routine fails for any reason, it might leave the database
** 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[] */
int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */
@@ -36325,21 +37887,22 @@
u16 *szCell; /* Local size of all cells in apCell[] */
u8 *aCopy[NB]; /* Space for holding data of apCopy[] */
u8 *aSpace1; /* Space for copies of dividers cells before balance */
u8 *aSpace2 = 0; /* Space for overflow dividers cells after balance */
-#ifndef SQLITE_OMIT_AUTOVACUUM
u8 *aFrom = 0;
-#endif
-
+
+ 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;
}
@@ -36356,19 +37919,19 @@
** packing of data in the common case.
*/
if( pPage->leaf &&
pPage->intKey &&
- pPage->leafData &&
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
if( SQLITE_OK!=(rc = sqlite3PagerWrite(pPage->pDbPage)) ){
@@ -36379,29 +37942,16 @@
** Find the cell in the parent page whose left child points back
** 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
** the siblings. An attempt is made to find NN siblings on either
@@ -36427,11 +37977,11 @@
pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]);
}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++;
nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
@@ -36463,13 +38013,11 @@
assert( ((aCopy[i] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
}
aSpace1 = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
assert( ((aSpace1 - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
+ if( ISAUTOVACUUM ){
aFrom = &aSpace1[pBt->pageSize];
}
-#endif
aSpace2 = sqlite3PageMalloc(pBt->pageSize);
if( aSpace2==0 ){
rc = SQLITE_NOMEM;
goto balance_cleanup;
@@ -36505,18 +38053,17 @@
** leafData: 1 if pPage holds key+data and pParent holds only keys.
*/
nCell = 0;
leafCorrection = pPage->leaf*4;
- leafData = pPage->leafData && pPage->leaf;
+ leafData = pPage->hasData;
for(i=0; i<nOld; i++){
MemPage *pOld = apCopy[i];
int limit = pOld->nCell+pOld->nOverflow;
for(j=0; j<limit; j++){
assert( nCell<nMaxCells );
apCell[nCell] = findOverflowCell(pOld, j);
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
+ if( ISAUTOVACUUM ){
int a;
aFrom[nCell] = i;
for(a=0; a<pOld->nOverflow; a++){
if( pOld->aOvfl[a].pCell==apCell[nCell] ){
@@ -36524,9 +38071,8 @@
break;
}
}
}
-#endif
nCell++;
}
if( i<nOld-1 ){
u16 sz = cellSizePtr(pParent, apDiv[i]);
@@ -36546,13 +38092,11 @@
assert( sz<=pBt->pageSize/4 );
assert( iSpace1<=pBt->pageSize );
memcpy(pTemp, apDiv[i], sz);
apCell[nCell] = pTemp+leafCorrection;
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
+ if( ISAUTOVACUUM ){
aFrom[nCell] = 0xFF;
}
-#endif
dropCell(pParent, nxDiv, sz);
szCell[nCell] -= leafCorrection;
assert( get4byte(pTemp)==pgnoOld[i] );
if( !pOld->leaf ){
@@ -36732,26 +38276,27 @@
assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) );
assert( pNew->nOverflow==0 );
-#ifndef SQLITE_OMIT_AUTOVACUUM
/* If this is an auto-vacuum database, update the pointer map entries
** that point to the siblings that were rearranged. These can be: left
** children of cells, the right-child of the page, or overflow pages
** pointed to by cells.
*/
- if( pBt->autoVacuum ){
+ if( ISAUTOVACUUM ){
for(k=j; k<cntNew[i]; k++){
assert( k<nMaxCells );
if( aFrom[k]==0xFF || apCopy[aFrom[k]]->pgno!=pNew->pgno ){
rc = ptrmapPutOvfl(pNew, k-j);
+ if( rc==SQLITE_OK && leafCorrection==0 ){
+ rc = ptrmapPut(pBt, get4byte(apCell[k]), PTRMAP_BTREE, pNew->pgno);
+ }
if( rc!=SQLITE_OK ){
goto balance_cleanup;
}
}
}
}
-#endif
j = cntNew[i];
/* If the sibling page assembled above was not the right-most sibling,
@@ -36767,8 +38312,16 @@
sz = szCell[j] + leafCorrection;
pTemp = &aSpace2[iSpace2];
if( !pNew->leaf ){
memcpy(&pNew->aData[8], pCell, 4);
+ if( ISAUTOVACUUM
+ && (aFrom[j]==0xFF || apCopy[aFrom[j]]->pgno!=pNew->pgno)
+ ){
+ rc = ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno);
+ if( rc!=SQLITE_OK ){
+ goto balance_cleanup;
+ }
+ }
}else if( leafData ){
/* If the tree is a leaf-data tree, and the siblings are leaves,
** then there is no divider cell in apCell[]. Instead, the divider
** cell consists of the integer key for the right-most cell of
@@ -36803,29 +38356,43 @@
assert( iSpace2<=pBt->pageSize );
rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4);
if( rc!=SQLITE_OK ) goto balance_cleanup;
put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno);
-#ifndef SQLITE_OMIT_AUTOVACUUM
+
/* If this is an auto-vacuum database, and not a leaf-data tree,
** then update the pointer map with an entry for the overflow page
** that the cell just inserted points to (if any).
*/
- if( pBt->autoVacuum && !leafData ){
+ if( ISAUTOVACUUM && !leafData ){
rc = ptrmapPutOvfl(pParent, nxDiv);
if( rc!=SQLITE_OK ){
goto balance_cleanup;
}
}
-#endif
j++;
nxDiv++;
+ }
+
+ /* Set the pointer-map entry for the new sibling page. */
+ if( ISAUTOVACUUM ){
+ rc = ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno);
+ if( rc!=SQLITE_OK ){
+ goto balance_cleanup;
+ }
}
}
assert( j==nCell );
assert( nOld>0 );
assert( nNew>0 );
if( (pageFlags & PTF_LEAF)==0 ){
- memcpy(&apNew[nNew-1]->aData[8], &apCopy[nOld-1]->aData[8], 4);
+ u8 *zChild = &apCopy[nOld-1]->aData[8];
+ memcpy(&apNew[nNew-1]->aData[8], zChild, 4);
+ if( ISAUTOVACUUM ){
+ rc = ptrmapPut(pBt, get4byte(zChild), PTRMAP_BTREE, apNew[nNew-1]->pgno);
+ if( rc!=SQLITE_OK ){
+ goto balance_cleanup;
+ }
+ }
}
if( nxDiv==pParent->nCell+pParent->nOverflow ){
/* Right-most sibling is the right-most child of pParent */
put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew[nNew-1]);
@@ -36835,26 +38402,18 @@
put4byte(findOverflowCell(pParent, nxDiv), pgnoNew[nNew-1]);
}
/*
- ** Reparent children of all cells.
- */
- for(i=0; i<nNew; i++){
- rc = reparentChildPages(apNew[i]);
- if( rc!=SQLITE_OK ) goto balance_cleanup;
- }
- rc = reparentChildPages(pParent);
- if( rc!=SQLITE_OK ) goto balance_cleanup;
-
- /*
** Balance the parent page. Note that the current page (pPage) might
** have been added to the freelist so it might no longer be initialized.
** But the parent page will always be initialized.
*/
assert( pParent->isInit );
sqlite3ScratchFree(apCell);
apCell = 0;
- rc = balance(pParent, 0);
+ releasePage(pPage);
+ pCur->iPage--;
+ rc = balance(pCur, 0);
/*
** Cleanup before returning.
*/
@@ -36866,11 +38425,13 @@
}
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;
}
/*
@@ -36877,9 +38438,10 @@
** This routine is called for the root page of a btree when the root
** 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 */
BtShared *pBt; /* The main BTree structure */
@@ -36886,9 +38448,11 @@
int mxCellPerPage; /* Maximum number of cells per page */
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;
mxCellPerPage = MX_CELL(pBt);
@@ -36910,15 +38474,16 @@
** case, then do not do the transfer. Leave page 1 empty except
** 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 ){
/* The child information will fit on the root page, so do the
@@ -36942,28 +38507,18 @@
}
}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);
assert( pPage->nOverflow==0 );
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- int i;
- for(i=0; i<pPage->nCell; i++){
- rc = ptrmapPutOvfl(pPage, i);
- if( rc!=SQLITE_OK ){
- goto end_shallow_balance;
- }
- }
- }
-#endif
+ if( ISAUTOVACUUM ){
+ rc = setChildPtrmaps(pPage);
+ }
releasePage(pChild);
}
end_shallow_balance:
sqlite3_free(apCell);
@@ -36979,21 +38534,25 @@
** page an empty page with rightChild pointing to the new
** 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 usableSize; /* Total usable size of a page */
u8 *data; /* Content of the parent page */
u8 *cdata; /* Content of the child page */
int hdr; /* Offset to page header in parent */
- int brk; /* Offset to content of first cell in parent */
-
- assert( pPage->pParent==0 );
- assert( pPage->nOverflow>0 );
+ int cbrk; /* Offset to content of first cell in parent */
+
+ assert( pCur->iPage==0 );
+ assert( pCur->apPage[0]->nOverflow>0 );
+
+ VVA_ONLY( pCur->pagesShuffled = 1 );
+ pPage = pCur->apPage[0];
pBt = pPage->pBt;
assert( sqlite3_mutex_held(pBt->mutex) );
rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0);
if( rc ) return rc;
@@ -37000,63 +38559,71 @@
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
usableSize = pBt->usableSize;
data = pPage->aData;
hdr = pPage->hdrOffset;
- brk = get2byte(&data[hdr+5]);
+ cbrk = get2byte(&data[hdr+5]);
cdata = pChild->aData;
memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
- memcpy(&cdata[brk], &data[brk], usableSize-brk);
- if( pChild->isInit ) return SQLITE_CORRUPT;
- rc = sqlite3BtreeInitPage(pChild, pPage);
- if( rc ) goto balancedeeper_out;
- memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0]));
- pChild->nOverflow = pPage->nOverflow;
- if( pChild->nOverflow ){
- pChild->nFree = 0;
- }
- assert( pChild->nCell==pPage->nCell );
- zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF);
- put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild);
- TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno));
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( pBt->autoVacuum ){
- int i;
- rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno);
- if( rc ) goto balancedeeper_out;
- for(i=0; i<pChild->nCell; i++){
- rc = ptrmapPutOvfl(pChild, i);
- if( rc!=SQLITE_OK ){
- goto balancedeeper_out;
- }
- }
- }
-#endif
- rc = balance_nonroot(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.
-*/
-static int balance(MemPage *pPage, int insert){
- int rc = SQLITE_OK;
+ memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
+
+ 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);
+ if( rc==SQLITE_OK ){
+ rc = setChildPtrmaps(pChild);
+ }
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ pCur->iPage++;
+ pCur->apPage[1] = pChild;
+ pCur->aiIdx[0] = 0;
+ rc = balance_nonroot(pCur);
+ }else{
+ releasePage(pChild);
+ }
+
+ return rc;
+}
+
+/*
+** The page that pCur currently points to has just been modified in
+** some way. This function figures out if this modification means the
+** tree needs to be balanced, and if so calls the appropriate balancing
+** routine.
+**
+** Parameter isInsert is true if a new cell was just inserted into the
+** page, or false otherwise.
+*/
+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;
}
@@ -37148,8 +38715,9 @@
){
int rc;
int loc;
int szNew;
+ int idx;
MemPage *pPage;
Btree *p = pCur->pBtree;
BtShared *pBt = p->pBt;
unsigned char *oldCell;
@@ -37172,19 +38740,19 @@
return pCur->skip;
}
/* 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, 0, nKey, appendBias, &loc))
- ){
- return rc;
- }
-
- pPage = pCur->pPage;
+ SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
+ ){
+ return rc;
+ }
+
+ pPage = pCur->apPage[pCur->iPage];
assert( pPage->intKey || nKey>=0 );
- assert( pPage->leaf || !pPage->leafData );
+ assert( pPage->leaf || !pPage->intKey );
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, nKey, nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
assert( pPage->isInit );
@@ -37194,34 +38762,35 @@
rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew);
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);
+ dropCell(pPage, idx, szOld);
}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);
}
end_insert:
@@ -37229,12 +38798,13 @@
}
/*
** 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;
Btree *p = pCur->pBtree;
@@ -37250,9 +38820,9 @@
assert( !pBt->readOnly );
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 ){
return SQLITE_PERM; /* Did not open this cursor for writing */
@@ -37277,9 +38847,10 @@
/* Locate the cell within its page and leave pCell pointing to the
** 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);
}
rc = clearCell(pPage, pCell);
@@ -37295,48 +38866,132 @@
** next Cell after the one to be deleted is guaranteed to exist and
** to be a leaf so we can use it.
*/
BtCursor leafCur;
+ MemPage *pLeafPage;
+
unsigned char *pNext;
int notUsed;
unsigned char *tempCell = 0;
- assert( !pPage->leafData );
+ assert( !pPage->intKey );
sqlite3BtreeGetTempCursor(pCur, &leafCur);
rc = sqlite3BtreeNext(&leafCur, ¬Used);
if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(leafCur.pPage->pDbPage);
- }
- if( rc==SQLITE_OK ){
+ 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;
if( tempCell==0 ){
rc = SQLITE_NOMEM;
}
if( rc==SQLITE_OK ){
- rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0);
- }
- if( rc==SQLITE_OK ){
- put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild);
- rc = balance(pPage, 0);
- }
- if( rc==SQLITE_OK ){
- dropCell(leafCur.pPage, leafCur.idx, szNext);
- rc = balance(leafCur.pPage, 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, 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(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);
}
@@ -37441,9 +39096,9 @@
if( rc!=SQLITE_OK ){
releasePage(pRoot);
return rc;
}
- rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove);
+ rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
releasePage(pRoot);
/* Obtain the page at pgnoRoot */
if( rc!=SQLITE_OK ){
@@ -37501,9 +39156,10 @@
static int clearDatabasePage(
BtShared *pBt, /* The BTree that contains the table */
Pgno pgno, /* Page number to clear */
MemPage *pParent, /* Parent page. NULL for the root */
- int freePageFlag /* Deallocate page if true */
+ int freePageFlag, /* Deallocate page if true */
+ int *pnChange
){
MemPage *pPage = 0;
int rc;
unsigned char *pCell;
@@ -37513,22 +39169,25 @@
if( pgno>pagerPagecount(pBt->pPager) ){
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);
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
@@ -37547,10 +39206,14 @@
**
** 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.
-*/
-SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable){
+**
+** If pnChange is not NULL, then table iTable must be an intkey table. The
+** integer value pointed to by pnChange is incremented by the number of
+** entries in the table.
+*/
+SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
int rc;
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
pBt->db = p->db;
@@ -37560,9 +39223,9 @@
/* nothing to do */
}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;
}
@@ -37608,9 +39271,9 @@
}
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;
}
@@ -37649,9 +39312,9 @@
rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0);
if( rc!=SQLITE_OK ){
return rc;
}
- rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable);
+ rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable, 0);
releasePage(pMove);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -37734,16 +39397,34 @@
return rc;
}
assert( idx>=0 && idx<=15 );
- rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage);
- if( rc ){
- sqlite3BtreeLeave(p);
- return rc;
- }
- pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage);
+ 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);
+ }
*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.
*/
@@ -37798,9 +39479,9 @@
** restoreCursorPosition() here.
*/
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;
}
@@ -37836,8 +39517,11 @@
sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1);
}
sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
va_end(ap);
+ if( pCheck->errMsg.mallocFailed ){
+ pCheck->mallocFailed = 1;
+ }
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
@@ -38011,9 +39695,9 @@
checkAppendMsg(pCheck, zContext,
"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);
return 0;
@@ -38079,17 +39763,22 @@
*/
data = pPage->aData;
hdr = pPage->hdrOffset;
hit = sqlite3PageMalloc( pBt->pageSize );
- if( hit ){
+ if( hit==0 ){
+ pCheck->mallocFailed = 1;
+ }else{
memset(hit, 0, usableSize );
memset(hit, 1, get2byte(&data[hdr+5]));
nCell = get2byte(&data[hdr+3]);
cellStart = hdr + 12 - 4*pPage->leaf;
for(i=0; i<nCell; i++){
int pc = get2byte(&data[cellStart+i*2]);
- u16 size = cellSizePtr(pPage, &data[pc]);
+ u16 size = 1024;
int j;
+ if( pc<=usableSize ){
+ size = cellSizePtr(pPage, &data[pc]);
+ }
if( (pc+size-1)>=usableSize || pc<0 ){
checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage,0);
}else{
@@ -38135,12 +39824,12 @@
** This routine does a complete check of the given BTree file. aRoot[] is
** an array of pages numbers were each page number is the root page of
** a table. nRoot is the number of entries in aRoot.
**
-** If everything checks out, this routine returns NULL. If something is
-** amiss, an error message is written into memory obtained from malloc()
-** and a pointer to that error message is returned. The calling function
-** is responsible for freeing the error message when it is done.
+** Write the number of error seen in *pnErr. Except for some memory
+** allocation errors, nn error message is held in memory obtained from
+** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is
+** returned.
*/
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
Btree *p, /* The btree to be checked */
int *aRoot, /* An array of root pages numbers for individual trees */
@@ -38157,16 +39846,18 @@
sqlite3BtreeEnter(p);
pBt->db = p->db;
nRef = sqlite3PagerRefcount(pBt->pPager);
if( lockBtreeWithRetry(p)!=SQLITE_OK ){
+ *pnErr = 1;
sqlite3BtreeLeave(p);
- return sqlite3StrDup("Unable to acquire a read lock on the database");
+ return sqlite3DbStrDup(0, "cannot acquire a read lock on the database");
}
sCheck.pBt = pBt;
sCheck.pPager = pBt->pPager;
sCheck.nPage = pagerPagecount(sCheck.pPager);
sCheck.mxErr = mxErr;
sCheck.nErr = 0;
+ sCheck.mallocFailed = 0;
*pnErr = 0;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->nTrunc!=0 ){
sCheck.nPage = pBt->nTrunc;
@@ -38181,10 +39872,9 @@
if( !sCheck.anRef ){
unlockBtreeIfUnused(pBt);
*pnErr = 1;
sqlite3BtreeLeave(p);
- return sqlite3MPrintf(p->db, "Unable to malloc %d bytes",
- (sCheck.nPage+1)*sizeof(sCheck.anRef[0]));
+ return 0;
}
for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; }
i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ){
@@ -38244,8 +39934,13 @@
/* Clean up and report errors.
*/
sqlite3BtreeLeave(p);
sqlite3_free(sCheck.anRef);
+ if( sCheck.mallocFailed ){
+ sqlite3StrAccumReset(&sCheck.errMsg);
+ *pnErr = sCheck.nErr+1;
+ return 0;
+ }
*pnErr = sCheck.nErr;
if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg);
return sqlite3StrAccumFinish(&sCheck.errMsg);
}
@@ -38358,9 +40053,9 @@
** that and prevents the page from being written to the database. The
** page is still on the rollback journal, though. And that is the
** whole point of this block: to put pages on the rollback journal.
*/
- sqlite3PagerDontWrite(pDbPage);
+ rc = sqlite3PagerDontWrite(pDbPage);
}
sqlite3PagerUnref(pDbPage);
}
}
@@ -38402,13 +40097,17 @@
nCopy = nFromPageSize;
}
memcpy(zTo, zFrom, nCopy);
- sqlite3PagerUnref(pFromPage);
- }
- }
-
- if( pToPage ) sqlite3PagerUnref(pToPage);
+ sqlite3PagerUnref(pFromPage);
+ }
+ }
+
+ if( pToPage ){
+ MemPage *p = (MemPage *)sqlite3PagerGetExtra(pToPage);
+ p->isInit = 0;
+ sqlite3PagerUnref(pToPage);
+ }
}
}
/* If things have worked so far, the database file may need to be
@@ -38467,9 +40166,9 @@
rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage);
if( rc==SQLITE_OK ){
char *zFrom = sqlite3PagerGetData(pFromPage);
- rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
+ rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
sqlite3PagerUnref(pFromPage);
}
}
}
@@ -38627,9 +40326,9 @@
&& pCsr->pBt->inTransaction==TRANS_WRITE );
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;
}
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 0, 1);
@@ -38669,9 +40368,9 @@
*************************************************************************
** This file implements a FIFO queue of rowids used for processing
** UPDATE and DELETE statements.
**
-** $Id: vdbefifo.c,v 1.7 2008/06/15 02:51:48 drh Exp $
+** $Id: vdbefifo.c,v 1.8 2008/07/28 19:34:54 drh Exp $
*/
/*
** Constants FIFOSIZE_FIRST and FIFOSIZE_MAX are the initial
@@ -38688,14 +40387,14 @@
/*
** Allocate a new FifoPage and return a pointer to it. Return NULL if
** we run out of memory. Leave space on the page for nEntry entries.
*/
-static FifoPage *allocateFifoPage(int nEntry){
+static FifoPage *allocateFifoPage(sqlite3 *db, int nEntry){
FifoPage *pPage;
if( nEntry>FIFOSIZE_MAX ){
nEntry = FIFOSIZE_MAX;
}
- pPage = sqlite3Malloc( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
+ pPage = sqlite3DbMallocRaw(db, sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
if( pPage ){
pPage->nSlot = nEntry;
pPage->iWrite = 0;
pPage->iRead = 0;
@@ -38706,10 +40405,11 @@
/*
** Initialize a Fifo structure.
*/
-SQLITE_PRIVATE void sqlite3VdbeFifoInit(Fifo *pFifo){
+SQLITE_PRIVATE void sqlite3VdbeFifoInit(Fifo *pFifo, sqlite3 *db){
memset(pFifo, 0, sizeof(*pFifo));
+ pFifo->db = db;
}
/*
** Push a single 64-bit integer value into the Fifo. Return SQLITE_OK
@@ -38719,14 +40419,15 @@
SQLITE_PRIVATE int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){
FifoPage *pPage;
pPage = pFifo->pLast;
if( pPage==0 ){
- pPage = pFifo->pLast = pFifo->pFirst = allocateFifoPage(FIFOSIZE_FIRST);
+ pPage = pFifo->pLast = pFifo->pFirst =
+ allocateFifoPage(pFifo->db, FIFOSIZE_FIRST);
if( pPage==0 ){
return SQLITE_NOMEM;
}
}else if( pPage->iWrite>=pPage->nSlot ){
- pPage->pNext = allocateFifoPage(pFifo->nEntry);
+ pPage->pNext = allocateFifoPage(pFifo->db, pFifo->nEntry);
if( pPage->pNext==0 ){
return SQLITE_NOMEM;
}
pPage = pFifo->pLast = pPage->pNext;
@@ -38756,9 +40457,9 @@
*pVal = pPage->aSlot[pPage->iRead++];
pFifo->nEntry--;
if( pPage->iRead>=pPage->iWrite ){
pFifo->pFirst = pPage->pNext;
- sqlite3_free(pPage);
+ sqlite3DbFree(pFifo->db, pPage);
if( pFifo->nEntry==0 ){
assert( pFifo->pLast==pPage );
pFifo->pLast = 0;
}else{
@@ -38777,11 +40478,11 @@
SQLITE_PRIVATE void sqlite3VdbeFifoClear(Fifo *pFifo){
FifoPage *pPage, *pNextPage;
for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){
pNextPage = pPage->pNext;
- sqlite3_free(pPage);
- }
- sqlite3VdbeFifoInit(pFifo);
+ sqlite3DbFree(pFifo->db, pPage);
+ }
+ sqlite3VdbeFifoInit(pFifo, pFifo->db);
}
/************** End of vdbefifo.c ********************************************/
/************** Begin file vdbemem.c *****************************************/
@@ -38801,9 +40502,9 @@
** stores a single value in the VDBE. Mem is an opaque structure visible
** only within the VDBE. Interface routines refer to a Mem using the
** name sqlite_value
**
-** $Id: vdbemem.c,v 1.118 2008/07/09 16:51:51 drh Exp $
+** $Id: vdbemem.c,v 1.124 2008/10/30 17:21:13 danielk1977 Exp $
*/
/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
@@ -38866,17 +40567,17 @@
((pMem->flags&MEM_Static) ? 1 : 0)
);
if( n<32 ) n = 32;
- if( sqlite3MallocSize(pMem->zMalloc)<n ){
+ 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{
- sqlite3_free(pMem->zMalloc);
+ sqlite3DbFree(pMem->db, pMem->zMalloc);
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
}
}
@@ -38893,13 +40594,16 @@
return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
}
/*
-** Make the given Mem object MEM_Dyn.
+** Make the given Mem object MEM_Dyn. In other words, make it so
+** that any TEXT or BLOB content is stored in memory obtained from
+** malloc(). In this way, we know that the memory is safe to be
+** overwritten or altered.
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
-SQLITE_PRIVATE int sqlite3VdbeMemDynamicify(Mem *pMem){
+SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
int f;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
expandBlob(pMem);
f = pMem->flags;
@@ -38942,18 +40646,8 @@
return SQLITE_OK;
}
#endif
-
-/*
-** Make the given Mem object either MEM_Short or MEM_Dyn so that bytes
-** of the Mem.z[] array can be modified.
-**
-** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
-*/
-SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
- return sqlite3VdbeMemDynamicify(pMem);
-}
/*
** Make sure the given Mem is \u0000 terminated.
*/
@@ -39030,17 +40724,16 @@
if( pFunc && pFunc->xFinalize ){
sqlite3_context ctx;
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ memset(&ctx, 0, sizeof(ctx));
ctx.s.flags = MEM_Null;
ctx.s.db = pMem->db;
- ctx.s.zMalloc = 0;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
- ctx.isError = 0;
pFunc->xFinalize(&ctx);
assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
- sqlite3_free(pMem->zMalloc);
+ sqlite3DbFree(pMem->db, pMem->zMalloc);
*pMem = ctx.s;
rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK);
}
return rc;
@@ -39069,9 +40762,9 @@
** (Mem.type==SQLITE_TEXT).
*/
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p){
sqlite3VdbeMemReleaseExternal(p);
- sqlite3_free(p->zMalloc);
+ sqlite3DbFree(p->db, p->zMalloc);
p->z = 0;
p->zMalloc = 0;
p->xDel = 0;
}
@@ -39414,8 +41107,12 @@
if( sqlite3VdbeMemGrow(pMem, nAlloc, 0) ){
return SQLITE_NOMEM;
}
memcpy(pMem->z, z, nAlloc);
+ }else if( xDel==SQLITE_DYNAMIC ){
+ sqlite3VdbeMemRelease(pMem);
+ pMem->zMalloc = pMem->z = (char *)z;
+ pMem->xDel = 0;
}else{
sqlite3VdbeMemRelease(pMem);
pMem->z = (char *)z;
pMem->xDel = xDel;
@@ -39525,24 +41222,23 @@
/* The strings are already in the correct encoding. Call the
** 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;
}
}
/* If a NULL pointer was passed as the collate function, fall through
@@ -39749,13 +41445,13 @@
}
op = pExpr->op;
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
- zVal = sqlite3StrNDup((char*)pExpr->token.z, pExpr->token.n);
+ zVal = sqlite3DbStrNDup(db, (char*)pExpr->token.z, pExpr->token.n);
pVal = sqlite3ValueNew(db);
if( !zVal || !pVal ) goto no_mem;
sqlite3Dequote(zVal);
- sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3_free);
+ sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc);
}else{
sqlite3ValueApplyAffinity(pVal, affinity, enc);
@@ -39773,12 +41469,13 @@
assert( pExpr->token.z[0]=='x' || pExpr->token.z[0]=='X' );
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,
- 0, sqlite3_free);
+ 0, SQLITE_DYNAMIC);
}
#endif
*ppVal = pVal;
@@ -39785,9 +41482,9 @@
return SQLITE_OK;
no_mem:
db->mallocFailed = 1;
- sqlite3_free(zVal);
+ sqlite3DbFree(db, zVal);
sqlite3ValueFree(pVal);
*ppVal = 0;
return SQLITE_NOMEM;
}
@@ -39810,9 +41507,9 @@
*/
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
sqlite3VdbeMemRelease((Mem *)v);
- sqlite3_free(v);
+ sqlite3DbFree(((Mem*)v)->db, v);
}
/*
** Return the number of bytes in the sqlite3_value object assuming
@@ -39847,9 +41544,9 @@
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
-** $Id: vdbeaux.c,v 1.397 2008/07/11 21:02:54 drh Exp $
+** $Id: vdbeaux.c,v 1.413 2008/10/31 10:53:23 danielk1977 Exp $
*/
@@ -40132,9 +41829,9 @@
assert( -1-pOp->p2<p->nLabel );
pOp->p2 = aLabel[-1-pOp->p2];
}
}
- sqlite3_free(p->aLabel);
+ sqlite3DbFree(p->db, p->aLabel);
p->aLabel = 0;
*pMaxFuncArgs = nMaxArgs;
@@ -40262,18 +41959,18 @@
/*
** If the input FuncDef structure is ephemeral, then free it. If
** the FuncDef is not ephermal, then do nothing.
*/
-static void freeEphemeralFunction(FuncDef *pDef){
+static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
if( pDef && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
- sqlite3_free(pDef);
+ sqlite3DbFree(db, pDef);
}
}
/*
** Delete a P4 value if necessary.
*/
-static void freeP4(int p4type, void *p4){
+static void freeP4(sqlite3 *db, int p4type, void *p4){
if( p4 ){
switch( p4type ){
case P4_REAL:
case P4_INT64:
@@ -40281,20 +41978,20 @@
case P4_DYNAMIC:
case P4_KEYINFO:
case P4_INTARRAY:
case P4_KEYINFO_HANDOFF: {
- sqlite3_free(p4);
+ sqlite3DbFree(db, p4);
break;
}
case P4_VDBEFUNC: {
VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
- freeEphemeralFunction(pVdbeFunc->pFunc);
+ freeEphemeralFunction(db, pVdbeFunc->pFunc);
sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
- sqlite3_free(pVdbeFunc);
+ sqlite3DbFree(db, pVdbeFunc);
break;
}
case P4_FUNCDEF: {
- freeEphemeralFunction((FuncDef*)p4);
+ freeEphemeralFunction(db, (FuncDef*)p4);
break;
}
case P4_MEM: {
sqlite3ValueFree((sqlite3_value*)p4);
@@ -40310,10 +42007,11 @@
*/
SQLITE_PRIVATE void sqlite3VdbeChangeToNoop(Vdbe *p, int addr, int N){
if( p && p->aOp ){
VdbeOp *pOp = &p->aOp[addr];
+ sqlite3 *db = p->db;
while( N-- ){
- freeP4(pOp->p4type, pOp->p4.p);
+ freeP4(db, pOp->p4type, pOp->p4.p);
memset(pOp, 0, sizeof(pOp[0]));
pOp->opcode = OP_Noop;
pOp++;
}
@@ -40346,13 +42044,15 @@
** If addr<0 then change P4 on the most recently inserted instruction.
*/
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
Op *pOp;
+ sqlite3 *db;
assert( p!=0 );
+ db = p->db;
assert( p->magic==VDBE_MAGIC_INIT );
- if( p->aOp==0 || p->db->mallocFailed ){
+ if( p->aOp==0 || db->mallocFailed ){
if (n != P4_KEYINFO) {
- freeP4(n, (void*)*(char**)&zP4);
+ freeP4(db, n, (void*)*(char**)&zP4);
}
return;
}
assert( addr<p->nOp );
@@ -40360,9 +42060,9 @@
addr = p->nOp - 1;
if( addr<0 ) return;
}
pOp = &p->aOp[addr];
- freeP4(pOp->p4type, pOp->p4.p);
+ freeP4(db, pOp->p4type, pOp->p4.p);
pOp->p4.p = 0;
if( n==P4_INT32 ){
/* Note: this cast is safe, because the origin data point was an int
** that was cast to a (const char *). */
@@ -40418,9 +42118,9 @@
assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
if( p->nOp ){
char **pz = &p->aOp[p->nOp-1].zComment;
va_start(ap, zFormat);
- sqlite3_free(*pz);
+ sqlite3DbFree(p->db, *pz);
*pz = sqlite3VMPrintf(p->db, zFormat, ap);
va_end(ap);
}
}
@@ -40431,9 +42131,9 @@
assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
if( p->nOp ){
char **pz = &p->aOp[p->nOp-1].zComment;
va_start(ap, zFormat);
- sqlite3_free(*pz);
+ sqlite3DbFree(p->db, *pz);
*pz = sqlite3VMPrintf(p->db, zFormat, ap);
va_end(ap);
}
}
@@ -40586,21 +42286,36 @@
/*
** Release an array of N Mem elements
*/
-static void releaseMemArray(Mem *p, int N, int freebuffers){
+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 );
- if( freebuffers ){
+ 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{
- sqlite3VdbeMemReleaseExternal(p);
- }
- p->flags = MEM_Null;
- p++;
+ }else if( p->zMalloc ){
+ sqlite3DbFree(db, p->zMalloc);
+ p->zMalloc = 0;
+ }
+
+ p->flags = MEM_Null;
}
db->mallocFailed = malloc_failed;
}
}
@@ -40613,9 +42328,9 @@
for(ii=1; ii<=p->nMem; ii++){
Mem *pMem = &p->aMem[ii];
if( pMem->z && pMem->flags&MEM_Dyn ){
assert( !pMem->xDel );
- nFree += sqlite3MallocSize(pMem->z);
+ nFree += sqlite3DbMallocSize(pMem->db, pMem->z);
sqlite3VdbeMemRelease(pMem);
}
}
return nFree;
@@ -40651,9 +42366,9 @@
/* Even though this opcode does not use dynamic strings for
** the result, result columns may become dynamic if the user calls
** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
*/
- releaseMemArray(pMem, p->nMem, 1);
+ releaseMemArray(pMem, p->nMem);
do{
i = p->pc++;
}while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
@@ -40732,8 +42447,9 @@
pMem->flags = MEM_Str|MEM_Term;
pMem->z = pOp->zComment;
pMem->n = strlen(pMem->z);
pMem->enc = SQLITE_UTF8;
+ pMem->type = SQLITE_TEXT;
}else
#endif
{
pMem->flags = MEM_Null; /* Comment */
@@ -40932,13 +42648,10 @@
p->inVtabMethod = 0;
}
#endif
if( !pCx->ephemPseudoTable ){
- sqlite3_free(pCx->pData);
- }
- /* memset(pCx, 0, sizeof(Cursor)); */
- /* sqlite3_free(pCx->aType); */
- /* sqlite3_free(pCx); */
+ sqlite3DbFree(p->db, pCx->pData);
+ }
}
/*
** Close all cursors except for VTab cursors that are currently
@@ -40962,26 +42675,27 @@
** This routine will automatically close any cursors, lists, and/or
** sorters that were left open. It also deletes the values of
** variables in the aVar[] array.
*/
-static void Cleanup(Vdbe *p, int freebuffers){
- int i;
+static void Cleanup(Vdbe *p){
+ int i;
+ sqlite3 *db = p->db;
closeAllCursorsExceptActiveVtabs(p);
for(i=1; i<=p->nMem; i++){
MemSetTypeFlag(&p->aMem[i], MEM_Null);
}
- releaseMemArray(&p->aMem[1], p->nMem, freebuffers);
+ releaseMemArray(&p->aMem[1], p->nMem);
sqlite3VdbeFifoClear(&p->sFifo);
if( p->contextStack ){
for(i=0; i<p->contextStackTop; i++){
sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
}
- sqlite3_free(p->contextStack);
+ sqlite3DbFree(db, p->contextStack);
}
p->contextStack = 0;
p->contextStackDepth = 0;
p->contextStackTop = 0;
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
p->pResultSet = 0;
}
@@ -40993,14 +42707,15 @@
*/
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
Mem *pColName;
int n;
-
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1);
- sqlite3_free(p->aColName);
+ sqlite3 *db = p->db;
+
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ sqlite3DbFree(db, p->aColName);
n = nResColumn*COLNAME_N;
p->nResColumn = nResColumn;
- p->aColName = pColName = (Mem*)sqlite3DbMallocZero(p->db, sizeof(Mem)*n );
+ p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n );
if( p->aColName==0 ) return;
while( n-- > 0 ){
pColName->flags = MEM_Null;
pColName->db = p->db;
@@ -41013,30 +42728,31 @@
** zName must be a pointer to a nul terminated string.
**
** 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 sqlite3_free() when the vdbe is finished with
-** it. Otherwise, N bytes of zName are copied.
-*/
-SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe *p, int idx, int var, const char *zName, int N){
+** 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, /* 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( p->db->mallocFailed || !zName || pColName->flags&MEM_Term );
return rc;
}
/*
@@ -41044,9 +42760,9 @@
** db. If a transaction is active, commit it. If there is a
** write-transaction spanning more than one database file, this routine
** takes care of the master journal trickery.
*/
-static int vdbeCommit(sqlite3 *db){
+static int vdbeCommit(sqlite3 *db, Vdbe *p){
int i;
int nTrans = 0; /* Number of databases with an active write-transaction */
int rc = SQLITE_OK;
int needXcommit = 0;
@@ -41056,9 +42772,9 @@
** be done before determining whether a master journal file is
** required, as an xSync() callback may add an attached database
** to the transaction.
*/
- rc = sqlite3VtabSync(db, rc);
+ rc = sqlite3VtabSync(db, &p->zErrMsg);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -41135,9 +42851,9 @@
/* Select a master journal file name */
do {
u32 random;
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
sqlite3_randomness(sizeof(random), &random);
zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, random&0x7fffffff);
if( !zMaster ){
return SQLITE_NOMEM;
@@ -41151,9 +42867,9 @@
SQLITE_OPEN_EXCLUSIVE|SQLITE_OPEN_MASTER_JOURNAL, 0
);
}
if( rc!=SQLITE_OK ){
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
return rc;
}
/* Write the name of each database file in the transaction into the new
@@ -41175,9 +42891,9 @@
offset += strlen(zFile)+1;
if( rc!=SQLITE_OK ){
sqlite3OsCloseFree(pMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
return rc;
}
}
}
@@ -41190,9 +42906,9 @@
&& (0==(sqlite3OsDeviceCharacteristics(pMaster)&SQLITE_IOCAP_SEQUENTIAL))
&& (rc=sqlite3OsSync(pMaster, SQLITE_SYNC_NORMAL))!=SQLITE_OK) ){
sqlite3OsCloseFree(pMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
return rc;
}
/* Sync all the db files involved in the transaction. The same call
@@ -41212,9 +42928,9 @@
}
}
sqlite3OsCloseFree(pMaster);
if( rc!=SQLITE_OK ){
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
return rc;
}
/* Delete the master journal file. This commits the transaction. After
@@ -41221,9 +42937,9 @@
** doing this the directory is synced again before any individual
** transaction files are deleted.
*/
rc = sqlite3OsDelete(pVfs, zMaster, 1);
- sqlite3_free(zMaster);
+ sqlite3DbFree(db, zMaster);
zMaster = 0;
if( rc ){
return rc;
}
@@ -41420,9 +43136,9 @@
/* The auto-commit flag is true, and the vdbe program was
** successful or hit an 'OR FAIL' constraint. This means a commit
** is required.
*/
- int rc = vdbeCommit(db);
+ int rc = vdbeCommit(db, p);
if( rc==SQLITE_BUSY ){
sqlite3BtreeMutexArrayLeave(&p->aMutex);
return SQLITE_BUSY;
}else if( rc!=SQLITE_OK ){
@@ -41463,9 +43179,9 @@
if( pBt ){
rc = xFunc(pBt);
if( rc && (p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT) ){
p->rc = rc;
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
}
}
@@ -41524,9 +43240,9 @@
** To look at it another way, this routine resets the state of the
** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
** VDBE_MAGIC_INIT.
*/
-SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p, int freebuffers){
+SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
sqlite3 *db;
db = p->db;
/* If the VM did not run to completion or if it encountered an
@@ -41543,10 +43259,13 @@
** instructions yet, leave the main database error information unchanged.
*/
if( p->pc>=0 ){
if( p->zErrMsg ){
- sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,sqlite3_free);
+ sqlite3BeginBenignMalloc();
+ sqlite3ValueSetStr(db->pErr,-1,p->zErrMsg,SQLITE_UTF8,SQLITE_TRANSIENT);
+ sqlite3EndBenignMalloc();
db->errCode = p->rc;
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}else if( p->rc ){
sqlite3Error(db, p->rc, 0);
}else{
@@ -41557,15 +43276,16 @@
** to sqlite3_step(). For consistency (since sqlite3_step() was
** called), set the database error in this case as well.
*/
sqlite3Error(db, p->rc, 0);
- sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, sqlite3_free);
+ sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
/* Reclaim all memory used by the VDBE
*/
- Cleanup(p, freebuffers);
+ Cleanup(p);
/* Save profiling information from this VDBE run.
*/
#ifdef VDBE_PROFILE
@@ -41590,9 +43310,8 @@
}
}
#endif
p->magic = VDBE_MAGIC_INIT;
- p->aborted = 0;
return p->rc & db->errMask;
}
/*
@@ -41601,14 +43320,13 @@
*/
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
- rc = sqlite3VdbeReset(p, 1);
+ rc = sqlite3VdbeReset(p);
assert( (rc & p->db->errMask)==rc );
}else if( p->magic!=VDBE_MAGIC_INIT ){
return SQLITE_MISUSE;
}
- releaseMemArray(&p->aMem[1], p->nMem, 1);
sqlite3VdbeDelete(p);
return rc;
}
@@ -41635,39 +43353,41 @@
** Delete an entire VDBE.
*/
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
int i;
+ sqlite3 *db;
+
if( p==0 ) return;
- Cleanup(p, 1);
+ db = p->db;
if( p->pPrev ){
p->pPrev->pNext = p->pNext;
}else{
- assert( p->db->pVdbe==p );
- p->db->pVdbe = p->pNext;
+ assert( db->pVdbe==p );
+ db->pVdbe = p->pNext;
}
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
}
if( p->aOp ){
Op *pOp = p->aOp;
for(i=0; i<p->nOp; i++, pOp++){
- freeP4(pOp->p4type, pOp->p4.p);
+ freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_DEBUG
- sqlite3_free(pOp->zComment);
-#endif
- }
- sqlite3_free(p->aOp);
- }
- releaseMemArray(p->aVar, p->nVar, 1);
- sqlite3_free(p->aLabel);
+ sqlite3DbFree(db, pOp->zComment);
+#endif
+ }
+ sqlite3DbFree(db, p->aOp);
+ }
+ releaseMemArray(p->aVar, p->nVar);
+ sqlite3DbFree(db, p->aLabel);
if( p->aMem ){
- sqlite3_free(&p->aMem[1]);
- }
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N, 1);
- sqlite3_free(p->aColName);
- sqlite3_free(p->zSql);
+ sqlite3DbFree(db, &p->aMem[1]);
+ }
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ sqlite3DbFree(db, p->aColName);
+ sqlite3DbFree(db, p->zSql);
p->magic = VDBE_MAGIC_DEAD;
- sqlite3_free(p);
+ sqlite3DbFree(db, p);
}
/*
** If a MoveTo operation is pending on the given cursor, then do that
@@ -41680,11 +43400,10 @@
#ifdef SQLITE_TEST
extern int sqlite3_search_count;
#endif
assert( p->isTable );
- rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
- if( rc ) return rc;
- *p->pIncrKey = 0;
+ rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
+ if( rc ) return rc;
p->lastRowid = keyToInt(p->movetoTarget);
p->rowidIsValid = res==0;
if( res<0 ){
rc = sqlite3BtreeNext(p->pCursor, &res);
@@ -41711,11 +43430,11 @@
** The following functions:
**
** sqlite3VdbeSerialType()
** sqlite3VdbeSerialTypeLen()
-** sqlite3VdbeSerialRead()
** sqlite3VdbeSerialLen()
-** sqlite3VdbeSerialWrite()
+** sqlite3VdbeSerialPut()
+** sqlite3VdbeSerialGet()
**
** encapsulate the code that serializes values for storage in SQLite
** data and index records. Each serialized value consists of a
** 'serial-type' and a blob of data. The serial type is an 8-byte unsigned
@@ -42029,15 +43748,16 @@
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
const void *pKey, /* The binary record */
- void *pSpace, /* Space available to hold resulting object */
+ UnpackedRecord *pSpace,/* Space available to hold resulting object */
int szSpace /* Size of pSpace[] in bytes */
){
const unsigned char *aKey = (const unsigned char *)pKey;
UnpackedRecord *p;
int nByte;
- int i, idx, d;
+ int idx, d;
+ u16 u; /* Unsigned loop counter */
u32 szHdr;
Mem *pMem;
assert( sizeof(Mem)>sizeof(*p) );
@@ -42044,21 +43764,20 @@
nByte = sizeof(Mem)*(pKeyInfo->nField+2);
if( nByte>szSpace ){
p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( p==0 ) return 0;
- p->needFree = 1;
+ p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
}else{
p = pSpace;
- p->needFree = 0;
+ p->flags = UNPACKED_NEED_DESTROY;
}
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nField + 1;
- p->needDestroy = 1;
p->aMem = pMem = &((Mem*)p)[1];
idx = getVarint32(aKey, szHdr);
d = szHdr;
- i = 0;
- while( idx<szHdr && i<p->nField ){
+ u = 0;
+ while( idx<szHdr && u<p->nField ){
u32 serial_type;
idx += getVarint32( aKey+idx, serial_type);
if( d>=nKey && sqlite3VdbeSerialTypeLen(serial_type)>0 ) break;
@@ -42067,11 +43786,12 @@
pMem->flags = 0;
pMem->zMalloc = 0;
d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
pMem++;
- i++;
- }
- p->nField = i;
+ u++;
+ }
+ assert( u<=pKeyInfo->nField + 1 );
+ p->nField = u;
return (void*)p;
}
/*
@@ -42078,9 +43798,9 @@
** This routine destroys a UnpackedRecord object
*/
SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
if( p ){
- if( p->needDestroy ){
+ if( p->flags & UNPACKED_NEED_DESTROY ){
int i;
Mem *pMem;
for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
if( pMem->zMalloc ){
@@ -42087,36 +43807,43 @@
sqlite3VdbeMemRelease(pMem);
}
}
}
- if( p->needFree ){
- sqlite3_free(p);
+ if( p->flags & UNPACKED_NEED_FREE ){
+ sqlite3DbFree(p->pKeyInfo->db, p);
}
}
}
/*
** This function compares the two table rows or index records
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
-** or positive integer if {nKey1, pKey1} is less than, equal to or
-** greater than pPKey2. The {nKey1, pKey1} key must be a blob
+** or positive integer if key1 is less than, equal to or
+** greater than key2. The {nKey1, pKey1} key must be a blob
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
** key must be a parsed key such as obtained from
** sqlite3VdbeParseRecord.
**
** Key1 and Key2 do not have to contain the same number of fields.
-** But if the lengths differ, Key2 must be the shorter of the two.
-**
-** Historical note: In earlier versions of this routine both Key1
-** and Key2 were blobs obtained from OP_MakeRecord. But we found
-** that in typical use the same Key2 would be submitted multiple times
-** in a row. So an optimization was added to parse the Key2 key
-** separately and submit the parsed version. In this way, we avoid
-** parsing the same Key2 multiple times in a row.
+** The key with fewer fields is usually compares less than the
+** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
+** and the common prefixes are equal, then key1 is less than key2.
+** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
+** equal, then the keys are considered to be equal and
+** the parts beyond the common prefix are ignored.
+**
+** If the UNPACKED_IGNORE_ROWID flag is set, then the last byte of
+** the header of pKey1 is ignored. It is assumed that pKey1 is
+** an index key, and thus ends with a rowid value. The last byte
+** of the header will therefore be the serial type of the rowid:
+** one of 1, 2, 3, 4, 5, 6, 8, or 9 - the integer serial types.
+** The serial type of the final rowid will always be a single byte.
+** By ignoring this last byte of the header, we force the comparison
+** to ignore the rowid at the end of key1.
*/
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
- int nKey1, const void *pKey1,
- UnpackedRecord *pPKey2
+ int nKey1, const void *pKey1, /* Left key */
+ UnpackedRecord *pPKey2 /* Right key */
){
u32 d1; /* Offset into aKey[] of next data element */
u32 idx1; /* Offset into aKey[] of next header element */
u32 szHdr1; /* Number of bytes in header */
@@ -42134,8 +43861,11 @@
mem1.zMalloc = 0;
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
+ if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){
+ szHdr1--;
+ }
nField = pKeyInfo->nField;
while( idx1<szHdr1 && i<pPKey2->nField ){
u32 serial_type1;
@@ -42157,41 +43887,30 @@
i++;
}
if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1);
- /* One of the keys ran out of fields, but all the fields up to that point
- ** were equal. If the incrKey flag is true, then the second key is
- ** treated as larger.
- */
if( rc==0 ){
- if( pKeyInfo->incrKey ){
+ /* rc==0 here means that one of the keys ran out of fields and
+ ** all the fields up to that point were equal. If the UNPACKED_INCRKEY
+ ** flag is set, then break the tie by treating key2 as larger.
+ ** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
+ ** are considered to be equal. Otherwise, the longer key is the
+ ** larger. As it happens, the pPKey2 will always be the longer
+ ** if there is a difference.
+ */
+ if( pPKey2->flags & UNPACKED_INCRKEY ){
rc = -1;
- }else if( !pKeyInfo->prefixIsEqual ){
- if( d1<nKey1 ){
- rc = 1;
- }
+ }else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
+ /* Leave rc==0 */
+ }else if( idx1<szHdr1 ){
+ rc = 1;
}
}else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField
&& pKeyInfo->aSortOrder[i] ){
rc = -rc;
}
return rc;
-}
-
-/*
-** The argument is an index entry composed using the OP_MakeRecord opcode.
-** The last entry in this record should be an integer (specifically
-** an integer rowid). This routine returns the number of bytes in
-** that integer.
-*/
-SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8 *aKey){
- u32 szHdr; /* Size of the header */
- u32 typeRowid; /* Serial type of the rowid */
-
- (void)getVarint32(aKey, szHdr);
- (void)getVarint32(&aKey[szHdr-1], typeRowid);
- return sqlite3VdbeSerialTypeLen(typeRowid);
}
/*
@@ -42234,23 +43953,23 @@
** or greater than pKey. Return SQLITE_OK on success.
**
** pKey is either created without a rowid or is truncated so that it
** omits the rowid at the end. The rowid at the end of the index entry
-** is ignored as well.
+** is ignored as well. Hence, this routine only compares the prefixes
+** of the keys prior to the final rowid, not the entire key.
+**
+** pUnpacked may be an unpacked version of pKey,nKey. If pUnpacked is
+** supplied it is used in place of pKey,nKey.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
Cursor *pC, /* The cursor to compare against */
- UnpackedRecord *pUnpacked,
- int nKey, const u8 *pKey, /* The key to compare */
+ UnpackedRecord *pUnpacked, /* Unpacked version of pKey and nKey */
int *res /* Write the comparison result here */
){
i64 nCellKey = 0;
int rc;
BtCursor *pCur = pC->pCursor;
- int lenRowid;
- Mem m;
- UnpackedRecord *pRec;
- char zSpace[200];
+ Mem m;
sqlite3BtreeKeySize(pCur, &nCellKey);
if( nCellKey<=0 ){
*res = 0;
@@ -42262,22 +43981,10 @@
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
if( rc ){
return rc;
}
- lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z);
- if( !pUnpacked ){
- pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
- zSpace, sizeof(zSpace));
- }else{
- pRec = pUnpacked;
- }
- if( pRec==0 ){
- return SQLITE_NOMEM;
- }
- *res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec);
- if( !pUnpacked ){
- sqlite3VdbeDeleteUnpackedRecord(pRec);
- }
+ assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID );
+ *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}
@@ -42339,12 +44046,12 @@
**
** This file contains code use to implement APIs that are part of the
** VDBE.
**
-** $Id: vdbeapi.c,v 1.134 2008/06/19 02:52:25 drh Exp $
-*/
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+** $Id: vdbeapi.c,v 1.147 2008/10/13 10:37:50 danielk1977 Exp $
+*/
+
+#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
/*
** The following structure contains pointers to the end points of a
** doubly-linked list of all compiled SQL statements that may be holding
** buffers eligible for release when the sqlite3_release_memory() interface is
@@ -42498,8 +44205,9 @@
#define vdbeReprepare(x) sqlite3Reprepare(x)
#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
** execution environment changes in a way that would alter the program
@@ -42510,8 +44218,9 @@
SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p==0 || p->expired;
}
+#endif
/*
** The following routine destroys a virtual machine that is created by
** the sqlite3_compile() routine. The integer returned is an SQLITE_
@@ -42526,9 +44235,9 @@
if( pStmt==0 ){
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);
stmtLruRemove(v);
@@ -42552,9 +44261,9 @@
rc = SQLITE_OK;
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3_mutex_enter(v->db->mutex);
- rc = sqlite3VdbeReset(v, 1);
+ rc = sqlite3VdbeReset(v);
stmtLruAdd(v);
sqlite3VdbeMakeReady(v, -1, 0, 0, 0);
assert( (rc & (v->db->errMask))==rc );
sqlite3_mutex_leave(v->db->mutex);
@@ -42568,9 +44277,9 @@
SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
Vdbe *p = (Vdbe*)pStmt;
-#ifndef SQLITE_MUTEX_NOOP
+#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
for(i=0; i<p->nVar; i++){
@@ -42757,13 +44466,12 @@
}
/* Assert that malloc() has not failed */
db = p->db;
- assert( !db->mallocFailed );
-
- if( p->aborted ){
- return SQLITE_ABORT;
- }
+ if( db->mallocFailed ){
+ return SQLITE_NOMEM;
+ }
+
if( p->pc<=0 && p->expired ){
if( p->rc==SQLITE_OK ){
p->rc = SQLITE_SCHEMA;
}
@@ -42821,16 +44529,18 @@
db->xProfile(db->pProfileArg, p->aOp[0].p4.z, elapseTime);
}
#endif
- sqlite3Error(p->db, rc, 0);
+ db->errCode = rc;
+ /*sqlite3Error(p->db, rc, 0);*/
p->rc = sqlite3ApiExit(p->db, p->rc);
end_of_step:
assert( (rc&0xff)==rc );
if( p->zSql && (rc&0xff)<SQLITE_ROW ){
/* This behavior occurs if sqlite3_prepare_v2() was used to build
** the prepared statement. Return error codes directly */
- sqlite3Error(p->db, p->rc, 0);
+ p->db->errCode = p->rc;
+ /* sqlite3Error(p->db, p->rc, 0); */
return p->rc;
}else{
/* This is for legacy sqlite3_prepare() builds and when the code
** is SQLITE_ROW or SQLITE_DONE */
@@ -42878,9 +44588,9 @@
** finalized or reset the parser error message is available via
** sqlite3_errmsg() and sqlite3_errcode().
*/
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
- sqlite3_free(v->zErrMsg);
+ sqlite3DbFree(db, v->zErrMsg);
if( !db->mallocFailed ){
v->zErrMsg = sqlite3DbStrDup(db, zErr);
} else {
v->zErrMsg = 0;
@@ -43018,8 +44728,9 @@
xDelete(pAux);
}
}
+#ifndef SQLITE_OMIT_DEPRECATED
/*
** Return the number of times the Step function of a aggregate has been
** called.
**
@@ -43031,8 +44742,9 @@
SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){
assert( p && p->pFunc && p->pFunc->xStep );
return p->pMem->n;
}
+#endif
/*
** Return the number of columns in the result set for the statement pStmt.
*/
@@ -43156,11 +44868,15 @@
columnMallocFailure(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){
const void *val = sqlite3_value_text16( columnMem(pStmt,i) );
@@ -43328,19 +45044,26 @@
** Unbind the value bound to variable i in virtual machine p. This is the
** 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--;
pVar = &p->aVar[i];
@@ -43364,23 +45087,21 @@
Vdbe *p = (Vdbe *)pStmt;
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));
- }
- sqlite3Error(p->db, rc, 0);
- rc = sqlite3ApiExit(p->db, rc);
- }
- sqlite3_mutex_leave(p->db->mutex);
+ 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);
+ }
+ sqlite3_mutex_leave(p->db->mutex);
+ }
return rc;
}
@@ -43398,14 +45119,13 @@
}
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){
return sqlite3_bind_int64(p, i, (i64)iValue);
@@ -43412,22 +45132,22 @@
}
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(
sqlite3_stmt *pStmt,
@@ -43451,29 +45171,27 @@
#endif /* SQLITE_OMIT_UTF16 */
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));
}
- }
- rc = sqlite3ApiExit(p->db, rc);
- sqlite3_mutex_leave(p->db->mutex);
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ rc = sqlite3ApiExit(p->db, rc);
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;
}
/*
@@ -43550,9 +45268,9 @@
** Transfer all bindings from the first statement over to the second.
** 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;
if( (pFrom->magic!=VDBE_MAGIC_RUN && pFrom->magic!=VDBE_MAGIC_HALT)
@@ -43570,8 +45288,18 @@
sqlite3_mutex_leave(pTo->db->mutex);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
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
@@ -43597,8 +45325,18 @@
pNext = (sqlite3_stmt*)((Vdbe*)pStmt)->pNext;
}
sqlite3_mutex_leave(pDb->mutex);
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 ********************************************/
@@ -43646,9 +45384,9 @@
** of the code in this file is, therefore, important. See other comments
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.761 2008/07/11 21:02:54 drh Exp $
+** $Id: vdbe.c,v 1.784 2008/10/30 15:03:16 drh Exp $
*/
/*
** The following global variable is incremented every time a cursor
@@ -43710,14 +45448,8 @@
# 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.
*/
#define Stringify(P, enc) \
@@ -43776,9 +45508,9 @@
** created by mkopcodeh.awk during compilation. Data is obtained
** 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
** specified by mask.
@@ -44087,9 +45819,9 @@
**
** This file contains inline asm code for retrieving "high-performance"
** counters for x86 class CPUs.
**
-** $Id: hwtime.h,v 1.2 2008/06/12 02:24:39 shane Exp $
+** $Id: hwtime.h,v 1.3 2008/08/01 14:33:15 shane Exp $
*/
#ifndef _HWTIME_H_
#define _HWTIME_H_
@@ -44126,8 +45858,23 @@
__inline__ sqlite_uint64 sqlite3Hwtime(void){
unsigned long val;
__asm__ __volatile__ ("rdtsc" : "=A" (val));
return val;
+ }
+
+#elif (defined(__GNUC__) && defined(__ppc__))
+
+ __inline__ sqlite_uint64 sqlite3Hwtime(void){
+ unsigned long long retval;
+ unsigned long junk;
+ __asm__ __volatile__ ("\n\
+ 1: mftbu %1\n\
+ mftb %L0\n\
+ mftbu %0\n\
+ cmpw %0,%1\n\
+ bne 1b"
+ : "=r" (retval), "=r" (junk));
+ return retval;
}
#else
@@ -44231,8 +45978,10 @@
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif
+ UnpackedRecord aTempRec[16]; /* Space to hold a transient UnpackedRecord */
+
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
assert( db->magic==SQLITE_MAGIC_BUSY );
sqlite3BtreeMutexArrayEnter(&p->aMutex);
@@ -44566,14 +46315,14 @@
#ifndef SQLITE_OMIT_UTF16
if( encoding!=SQLITE_UTF8 ){
sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
- if( SQLITE_OK!=sqlite3VdbeMemDynamicify(pOut) ) goto no_mem;
+ if( SQLITE_OK!=sqlite3VdbeMemMakeWriteable(pOut) ) goto no_mem;
pOut->zMalloc = 0;
pOut->flags |= MEM_Static;
pOut->flags &= ~MEM_Dyn;
if( pOp->p4type==P4_DYNAMIC ){
- sqlite3_free(pOp->p4.z);
+ sqlite3DbFree(db, pOp->p4.z);
}
pOp->p4type = P4_DYNAMIC;
pOp->p4.z = pOut->z;
pOp->p1 = pOut->n;
@@ -44855,8 +46604,10 @@
case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
int flags;
+ applyNumericAffinity(pIn1);
+ applyNumericAffinity(pIn2);
flags = pIn1->flags | pIn2->flags;
if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
i64 a, b;
@@ -45000,9 +46751,9 @@
sqlite3VdbeMemMove(&ctx.s, pOut);
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 );
ctx.pColl = pOp[-1].p4.pColl;
@@ -45816,9 +47567,10 @@
** record, or if the end of the last field appears to be before the end
** 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;
}
}
@@ -45831,19 +47583,10 @@
*/
if( aOffset[p2] ){
assert( rc==SQLITE_OK );
if( zRec ){
- if( pDest->flags&MEM_Dyn ){
- sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], &sMem);
- sMem.db = db;
- rc = sqlite3VdbeMemCopy(pDest, &sMem);
- assert( !(sMem.flags&MEM_Dyn) );
- if( rc!=SQLITE_OK ){
- goto op_column_out;
- }
- }else{
- sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest);
- }
+ sqlite3VdbeMemReleaseExternal(pDest);
+ sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest);
}else{
len = sqlite3VdbeSerialTypeLen(aType[p2]);
sqlite3VdbeMemMove(&sMem, pDest);
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem);
@@ -46097,9 +47840,9 @@
*/
sqlite3SetString(&p->zErrMsg, db, "cannot %s transaction - "
"SQL statements in progress",
rollback ? "rollback" : "commit");
- rc = SQLITE_ERROR;
+ rc = SQLITE_BUSY;
}else if( i!=db->autoCommit ){
if( pOp->p2 ){
assert( i==1 );
sqlite3RollbackAll(db);
@@ -46281,9 +48024,9 @@
rc = SQLITE_OK;
iMeta = 0;
}
if( rc==SQLITE_OK && iMeta!=pOp->p2 ){
- sqlite3_free(p->zErrMsg);
+ sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
** stored with the in-memory representation of the schema, do
** not reload the schema from the database file.
@@ -46388,13 +48131,11 @@
pCur->nullRow = 1;
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor);
if( pOp->p4type==P4_KEYINFO ){
pCur->pKeyInfo = pOp->p4.pKeyInfo;
- pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
pCur->pKeyInfo->enc = ENC(p->db);
}else{
pCur->pKeyInfo = 0;
- pCur->pIncrKey = &pCur->bogusIncrKey;
}
switch( rc ){
case SQLITE_BUSY: {
p->pc = pc;
@@ -46492,15 +48233,13 @@
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1,
(KeyInfo*)pOp->p4.z, pCx->pCursor);
pCx->pKeyInfo = pOp->p4.pKeyInfo;
pCx->pKeyInfo->enc = ENC(p->db);
- pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
}else{
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
pCx->isTable = 1;
- pCx->pIncrKey = &pCx->bogusIncrKey;
}
}
pCx->isIndex = !pCx->isTable;
break;
@@ -46534,9 +48273,8 @@
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->pseudoTable = 1;
pCx->ephemPseudoTable = pOp->p2;
- pCx->pIncrKey = &pCx->bogusIncrKey;
pCx->isTable = 1;
pCx->isIndex = 0;
break;
}
@@ -46626,9 +48364,8 @@
if( pC->pCursor!=0 ){
int res, oc;
oc = pOp->opcode;
pC->nullRow = 0;
- *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
if( pC->isTable ){
i64 iKey = sqlite3VdbeIntValue(pIn3);
if( pOp->p2==0 ){
assert( pOp->opcode==OP_MoveGe );
@@ -46636,9 +48373,9 @@
pC->rowidIsValid = 0;
pC->deferredMoveto = 1;
break;
}
- rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res);
+ rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pC->lastRowid = iKey;
@@ -46649,20 +48386,22 @@
assert( pOp->p4type==P4_INT32 );
assert( nField>0 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = nField;
- r.needFree = 0;
- r.needDestroy = 0;
+ if( oc==OP_MoveGt || oc==OP_MoveLe ){
+ r.flags = UNPACKED_INCRKEY;
+ }else{
+ r.flags = 0;
+ }
r.aMem = &p->aMem[pOp->p3];
- rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
+ rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
pC->rowidIsValid = 0;
}
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
- *pC->pIncrKey = 0;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
if( oc==OP_MoveGe || oc==OP_MoveGt ){
@@ -46718,9 +48457,9 @@
** the first N serialized values exactly match the N serialized values
** in the record in register P3, where N is the total number of values in
** the P3 record (the P3 record is a prefix of the P1 record).
**
-** See also: NotFound, MoveTo, IsUnique, NotExists
+** See also: NotFound, IsUnique, NotExists
*/
/* Opcode: NotFound P1 P2 P3 * *
**
** Register P3 holds a blob constructed by MakeRecord. P1 is
@@ -46727,9 +48466,9 @@
** an index. If no entry exists in P1 that matches the blob then jump
** to P2. If an entry does existing, fall through. The cursor is left
** pointing to the entry that matches.
**
-** See also: Found, MoveTo, NotExists, IsUnique
+** See also: Found, NotExists, IsUnique
*/
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
int i = pOp->p1;
@@ -46738,15 +48477,22 @@
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pC = p->apCsr[i])->pCursor!=0 ){
int res;
+ UnpackedRecord *pIdxKey;
+
assert( pC->isTable==0 );
assert( pIn3->flags & MEM_Blob );
+ pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
+ aTempRec, sizeof(aTempRec));
+ if( pIdxKey==0 ){
+ goto no_mem;
+ }
if( pOp->opcode==OP_Found ){
- pC->pKeyInfo->prefixIsEqual = 1;
- }
- rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
- pC->pKeyInfo->prefixIsEqual = 0;
+ pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+ }
+ rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
if( rc!=SQLITE_OK ){
break;
}
alreadyExists = (res==0);
@@ -46764,9 +48510,9 @@
/* Opcode: IsUnique P1 P2 P3 P4 *
**
** The P3 register contains an integer record number. Call this
** record number R. The P4 register contains an index key created
-** using MakeIdxRec. Call it K.
+** using MakeRecord. Call it K.
**
** P1 is an index. So it has no data and its key consists of a
** record generated by OP_MakeRecord where the last field is the
** rowid of the entry that the index refers to.
@@ -46800,40 +48546,41 @@
assert( pCx!=0 );
pCrsr = pCx->pCursor;
if( pCrsr!=0 ){
int res;
- i64 v; /* The record number on the P1 entry that matches K */
- char *zKey; /* The value of K */
- int nKey; /* Number of bytes in K */
- int len; /* Number of bytes in K without the rowid at the end */
- int szRowid; /* Size of the rowid column at the end of zKey */
+ i64 v; /* The record number that matches K */
+ UnpackedRecord *pIdxKey; /* Unpacked version of P4 */
/* Make sure K is a string and make zKey point to K
*/
assert( pK->flags & MEM_Blob );
- zKey = pK->z;
- nKey = pK->n;
-
- szRowid = sqlite3VdbeIdxRowidLen((u8*)zKey);
- len = nKey-szRowid;
-
- /* Search for an entry in P1 where all but the last four bytes match K.
+ pIdxKey = sqlite3VdbeRecordUnpack(pCx->pKeyInfo, pK->n, pK->z,
+ aTempRec, sizeof(aTempRec));
+ if( pIdxKey==0 ){
+ goto no_mem;
+ }
+ pIdxKey->flags |= UNPACKED_IGNORE_ROWID;
+
+ /* Search for an entry in P1 where all but the last rowid match K
** If there is no such entry, jump immediately to P2.
*/
assert( pCx->deferredMoveto==0 );
pCx->cacheStatus = CACHE_STALE;
- rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res);
+ rc = sqlite3BtreeMovetoUnpacked(pCrsr, pIdxKey, 0, 0, &res);
if( rc!=SQLITE_OK ){
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
goto abort_due_to_error;
}
if( res<0 ){
rc = sqlite3BtreeNext(pCrsr, &res);
if( res ){
pc = pOp->p2 - 1;
- break;
- }
- }
- rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res);
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
+ break;
+ }
+ }
+ rc = sqlite3VdbeIdxKeyCompare(pCx, pIdxKey, &res);
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res>0 ){
pc = pOp->p2 - 1;
break;
@@ -46874,9 +48621,9 @@
** operation assumes the key is an integer and that P1 is a table whereas
** NotFound assumes key is a blob constructed from MakeRecord and
** P1 is an index.
**
-** See also: Found, MoveTo, NotFound, IsUnique
+** See also: Found, NotFound, IsUnique
*/
case OP_NotExists: { /* jump, in3 */
int i = pOp->p1;
Cursor *pC;
@@ -46888,9 +48635,9 @@
u64 iKey;
assert( pIn3->flags & MEM_Int );
assert( p->apCsr[i]->isTable );
iKey = intToKey(pIn3->u.i);
- rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res);
+ rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0,&res);
pC->lastRowid = pIn3->u.i;
pC->rowidIsValid = res==0;
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
@@ -47065,9 +48812,9 @@
if( cnt<5 ) v &= 0xffffff;
}
if( v==0 ) continue;
x = intToKey(v);
- rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res);
+ rx = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)x, 0, &res);
cnt++;
}while( cnt<100 && rx==SQLITE_OK && res==0 );
db->priorNewRowid = v;
if( rx==SQLITE_OK && res==0 ){
@@ -47139,9 +48886,9 @@
assert( pData->flags & (MEM_Blob|MEM_Str) );
}
if( pC->pseudoTable ){
if( !pC->ephemPseudoTable ){
- sqlite3_free(pC->pData);
+ sqlite3DbFree(db, pC->pData);
}
pC->iKey = iKey;
pC->nData = pData->n;
if( pData->z==pData->zMalloc || pC->ephemPseudoTable ){
@@ -47374,8 +49121,11 @@
pC = p->apCsr[i];
assert( pC!=0 );
pC->nullRow = 1;
pC->rowidIsValid = 0;
+ if( pC->pCursor ){
+ sqlite3BtreeClearCursor(pC->pCursor);
+ }
break;
}
/* Opcode: Last P1 P2 * * *
@@ -47424,8 +49174,9 @@
#ifdef SQLITE_TEST
sqlite3_sort_count++;
sqlite3_search_count--;
#endif
+ p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
/* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
**
@@ -47501,8 +49252,9 @@
pC->nullRow = 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
}
@@ -47542,9 +49294,9 @@
}
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
** index opened by cursor P1.
@@ -47561,12 +49313,11 @@
int res;
UnpackedRecord r;
r.pKeyInfo = pC->pKeyInfo;
r.nField = pOp->p3;
- r.needFree = 0;
- r.needDestroy = 0;
+ r.flags = 0;
r.aMem = &p->aMem[pOp->p2];
- rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res);
+ rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
}
assert( pC->deferredMoveto==0 );
@@ -47647,14 +49398,15 @@
assert( pOp->p5==0 || pOp->p5==1 );
assert( pOp->p4type==P4_INT32 );
r.pKeyInfo = pC->pKeyInfo;
r.nField = pOp->p4.i;
- r.needFree = 0;
- r.needDestroy = 0;
+ if( pOp->p5 ){
+ r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
+ }else{
+ r.flags = UNPACKED_IGNORE_ROWID;
+ }
r.aMem = &p->aMem[pOp->p3];
- *pC->pIncrKey = pOp->p5;
- rc = sqlite3VdbeIdxKeyCompare(pC, &r, 0, 0, &res);
- *pC->pIncrKey = 0;
+ rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
if( pOp->opcode==OP_IdxLT ){
res = -res;
}else{
assert( pOp->opcode==OP_IdxGE );
@@ -47719,9 +49471,9 @@
}
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
** remove the table or index from the database file.
@@ -47729,13 +49481,28 @@
** The table being clear is in the main database file if P2==0. If
** 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;
}
/* Opcode: CreateTable P1 P2 * * *
@@ -47815,12 +49582,13 @@
if( zSql==0 ) goto no_mem;
(void)sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
+ initData.rc = SQLITE_OK;
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
- if( rc==SQLITE_ABORT ) rc = initData.rc;
- sqlite3_free(zSql);
+ if( rc==SQLITE_OK ) rc = initData.rc;
+ sqlite3DbFree(db, zSql);
db->init.busy = 0;
(void)sqlite3SafetyOn(db);
if( rc==SQLITE_NOMEM ){
goto no_mem;
@@ -47910,9 +49678,9 @@
Mem *pnErr; /* Register keeping track of errors remaining */
nRoot = pOp->p2;
assert( nRoot>0 );
- aRoot = sqlite3Malloc( sizeof(int)*(nRoot+1) );
+ aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) );
if( aRoot==0 ) goto no_mem;
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pnErr = &p->aMem[pOp->p3];
assert( (pnErr->flags & MEM_Int)!=0 );
@@ -47925,18 +49693,20 @@
assert( pOp->p5<db->nDb );
assert( (p->btreeMask & (1<<pOp->p5))!=0 );
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
pnErr->u.i, &nErr);
+ sqlite3DbFree(db, aRoot);
pnErr->u.i -= nErr;
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
assert( z==0 );
+ }else if( z==0 ){
+ goto no_mem;
}else{
sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
}
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding);
- sqlite3_free(aRoot);
break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -47944,8 +49714,9 @@
**
** Write the integer from register P1 into the Fifo.
*/
case OP_FifoWrite: { /* in1 */
+ p->sFifo.db = db;
if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){
goto no_mem;
}
break;
@@ -47991,9 +49762,9 @@
pContext = &p->contextStack[i];
pContext->lastRowid = db->lastRowid;
pContext->nChange = p->nChange;
pContext->sFifo = p->sFifo;
- sqlite3VdbeFifoInit(&p->sFifo);
+ sqlite3VdbeFifoInit(&p->sFifo, db);
break;
}
/* Opcode: ContextPop * * *
@@ -48112,9 +49883,9 @@
ctx.s.xDel = 0;
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 );
ctx.pColl = pOp[-1].p4.pColl;
@@ -48245,13 +50016,23 @@
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VBegin * * * P4 *
**
-** P4 a pointer to an sqlite3_vtab structure. Call the xBegin method
-** for that table.
+** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
+** xBegin method for that table.
+**
+** Also, whether or not P4 is set, check that this is not being called from
+** within a callback to a virtual table xSync() method. If it is, set the
+** error code to SQLITE_LOCKED.
*/
case OP_VBegin: {
- rc = sqlite3VtabBegin(db, pOp->p4.pVtab);
+ sqlite3_vtab *pVtab = pOp->p4.pVtab;
+ rc = sqlite3VtabBegin(db, pVtab);
+ if( pVtab ){
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
+ }
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -48297,8 +50078,11 @@
assert(pVtab && pModule);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xOpen(pVtab, &pVtabCursor);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
pVtabCursor->pVtab = pVtab;
@@ -48341,14 +50125,18 @@
int iQuery;
const sqlite3_module *pModule;
Mem *pQuery = &p->aMem[pOp->p3];
Mem *pArgc = &pQuery[1];
+ sqlite3_vtab_cursor *pVtabCursor;
+ sqlite3_vtab *pVtab;
Cursor *pCur = p->apCsr[pOp->p1];
REGISTER_TRACE(pOp->p3, pQuery);
assert( pCur->pVtabCursor );
- pModule = pCur->pVtabCursor->pVtab->pModule;
+ pVtabCursor = pCur->pVtabCursor;
+ pVtab = pVtabCursor->pVtab;
+ pModule = pVtab->pModule;
/* Grab the index number and argc parameters */
assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
nArg = pArgc->u.i;
@@ -48364,13 +50152,18 @@
storeTypeInfo(apArg[i], 0);
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ sqlite3VtabLock(pVtab);
p->inVtabMethod = 1;
- rc = pModule->xFilter(pCur->pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
+ rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
p->inVtabMethod = 0;
- if( rc==SQLITE_OK ){
- res = pModule->xEof(pCur->pVtabCursor);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
+ sqlite3VtabUnlock(db, pVtab);
+ if( rc==SQLITE_OK ){
+ res = pModule->xEof(pVtabCursor);
}
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( res ){
@@ -48389,8 +50182,9 @@
** Store into register P2 the rowid of
** the virtual-table that the P1 cursor is pointing to.
*/
case OP_VRowid: { /* out2-prerelease */
+ sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
sqlite_int64 iRow;
Cursor *pCur = p->apCsr[pOp->p1];
@@ -48397,12 +50191,16 @@
assert( pCur->pVtabCursor );
if( pCur->nullRow ){
break;
}
- pModule = pCur->pVtabCursor->pVtab->pModule;
+ pVtab = pCur->pVtabCursor->pVtab;
+ pModule = pVtab->pModule;
assert( pModule->xRowid );
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = iRow;
break;
@@ -48416,8 +50214,9 @@
** the row of the virtual-table that the
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
+ sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
@@ -48428,9 +50227,10 @@
if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest);
break;
}
- pModule = pCur->pVtabCursor->pVtab->pModule;
+ pVtab = pCur->pVtabCursor->pVtab;
+ pModule = pVtab->pModule;
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
/* The output cell may already have a buffer allocated. Move
@@ -48442,8 +50242,11 @@
MemSetTypeFlag(&sContext.s, MEM_Null);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
/* Copy the result of the function to the P3 register. We
** do this regardless of whether or not an error occured to ensure any
** dynamic allocation in sContext.s (a Mem struct) is released.
@@ -48470,8 +50273,9 @@
** jump to instruction P2. Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: { /* jump */
+ sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res = 0;
Cursor *pCur = p->apCsr[pOp->p1];
@@ -48478,9 +50282,10 @@
assert( pCur->pVtabCursor );
if( pCur->nullRow ){
break;
}
- pModule = pCur->pVtabCursor->pVtab->pModule;
+ pVtab = pCur->pVtabCursor->pVtab;
+ pModule = pVtab->pModule;
assert( pModule->xNext );
/* Invoke the xNext() method of the module. There is no way for the
** underlying implementation to return an error if one occurs during
@@ -48488,11 +50293,16 @@
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ sqlite3VtabLock(pVtab);
p->inVtabMethod = 1;
rc = pModule->xNext(pCur->pVtabCursor);
p->inVtabMethod = 0;
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
+ sqlite3VtabUnlock(db, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
}
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
@@ -48522,8 +50332,11 @@
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
sqlite3VtabLock(pVtab);
rc = pVtab->pModule->xRename(pVtab, pName->z);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
sqlite3VtabUnlock(db, pVtab);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
@@ -48574,8 +50387,11 @@
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
sqlite3VtabLock(pVtab);
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
+ sqlite3DbFree(db, p->zErrMsg);
+ p->zErrMsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
sqlite3VtabUnlock(db, pVtab);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( pOp->p1 && rc==SQLITE_OK ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
@@ -48761,9 +50577,9 @@
*************************************************************************
**
** This file contains code used to implement incremental BLOB I/O.
**
-** $Id: vdbeblob.c,v 1.24 2008/07/10 00:32:42 drh Exp $
+** $Id: vdbeblob.c,v 1.26 2008/10/02 14:49:02 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_INCRBLOB
@@ -48864,9 +50680,9 @@
if( !pTab ){
if( sParse.zErrMsg ){
sqlite3_snprintf(sizeof(zErr), zErr, "%s", sParse.zErrMsg);
}
- sqlite3_free(sParse.zErrMsg);
+ sqlite3DbFree(db, sParse.zErrMsg);
rc = SQLITE_ERROR;
(void)sqlite3SafetyOff(db);
sqlite3BtreeLeaveAll(db);
goto blob_open_out;
@@ -48976,9 +50792,9 @@
goto blob_open_out;
}
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
if( db->mallocFailed ){
- sqlite3_free(pBlob);
+ sqlite3DbFree(db, pBlob);
goto blob_open_out;
}
pBlob->flags = flags;
pBlob->pCsr = v->apCsr[0]->pCursor;
@@ -49015,9 +50831,9 @@
Incrblob *p = (Incrblob *)pBlob;
int rc;
rc = sqlite3_finalize(p->pStmt);
- sqlite3_free(p);
+ sqlite3DbFree(p->db, p);
return rc;
}
/*
@@ -49034,19 +50850,19 @@
Incrblob *p = (Incrblob *)pBlob;
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.
- */
+ sqlite3_mutex_enter(db->mutex);
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
** returned, clean-up the statement handle.
@@ -49336,8 +51152,1557 @@
}
#endif
/************** End of journal.c *********************************************/
+/************** Begin file memjournal.c **************************************/
+/*
+<<<<<<< memjournal.c
+** 2008 October 17
+=======
+** 2008 October 7
+>>>>>>> 1.2
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains code use to implement an in-memory rollback journal.
+** The in-memory rollback journal is used to journal transactions for
+** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
+**
+** @(#) $Id: memjournal.c,v 1.2 2008/10/28 18:12:36 drh Exp $
+*/
+
+/* Forward references to internal structures */
+typedef struct MemJournal MemJournal;
+typedef struct FilePoint FilePoint;
+typedef struct FileChunk FileChunk;
+
+/* Space to hold the rollback journal is allocated in increments of
+** this many bytes.
+*/
+#define JOURNAL_CHUNKSIZE 1024
+
+/* Macro to find the minimum of two numeric values.
+*/
+#define MIN(x,y) ((x)<(y)?(x):(y))
+
+/*
+** 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
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains routines used for walking the parser tree for
+** an SQL statement.
+**
+** $Id: walker.c,v 1.1 2008/08/20 16:35:10 drh Exp $
+*/
+
+
+/*
+** Walk an expression tree. Invoke the callback once for each node
+** of the expression, while decending. (In other words, the callback
+** is invoked before visiting children.)
+**
+** The return value from the callback should be one of the WRC_*
+** constants to specify how to proceed with the walk.
+**
+** WRC_Continue Continue descending down the tree.
+**
+** WRC_Prune Do not descend into child nodes. But allow
+** the walk to continue with sibling nodes.
+**
+** WRC_Abort Do no more callbacks. Unwind the stack and
+** return the top-level walk call.
+**
+** The return value from this routine is WRC_Abort to abandon the tree walk
+** and WRC_Continue to continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
+ int rc;
+ if( pExpr==0 ) return WRC_Continue;
+ rc = pWalker->xExprCallback(pWalker, pExpr);
+ if( rc==WRC_Continue ){
+ if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, pExpr->pList) ) return WRC_Abort;
+ if( sqlite3WalkSelect(pWalker, pExpr->pSelect) ){
+ return WRC_Abort;
+ }
+ }
+ return rc & WRC_Abort;
+}
+
+/*
+** Call sqlite3WalkExpr() for every expression in list p or until
+** an abort request is seen.
+*/
+SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
+ int i, rc = WRC_Continue;
+ struct ExprList_item *pItem;
+ if( p ){
+ for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+ if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
+ }
+ }
+ return rc & WRC_Continue;
+}
+
+/*
+** Walk all expressions associated with SELECT statement p. Do
+** not invoke the SELECT callback on p, but do (of course) invoke
+** any expr callbacks and SELECT callbacks that come from subqueries.
+** Return WRC_Abort or WRC_Continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
+ if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
+ return WRC_Continue;
+}
+
+/*
+** Walk the parse trees associated with all subqueries in the
+** FROM clause of SELECT statement p. Do not invoke the select
+** callback on p, but do invoke it on each FROM clause subquery
+** and on any subqueries further down in the tree. Return
+** WRC_Abort or WRC_Continue;
+*/
+SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
+ SrcList *pSrc;
+ int i;
+ struct SrcList_item *pItem;
+
+ pSrc = p->pSrc;
+ if( pSrc ){
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+ if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+ return WRC_Abort;
+ }
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
+** Call sqlite3WalkExpr() for every expression in Select statement p.
+** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
+** on the compound select chain, p->pPrior.
+**
+** Return WRC_Continue under normal conditions. Return WRC_Abort if
+** there is an abort request.
+**
+** If the Walker does not have an xSelectCallback() then this routine
+** is a no-op returning WRC_Continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
+ int rc;
+ if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
+ rc = WRC_Continue;
+ while( p ){
+ rc = pWalker->xSelectCallback(pWalker, p);
+ if( rc ) break;
+ if( sqlite3WalkSelectExpr(pWalker, p) ) return WRC_Abort;
+ if( sqlite3WalkSelectFrom(pWalker, p) ) return WRC_Abort;
+ p = p->pPrior;
+ }
+ return rc & WRC_Abort;
+}
+
+/************** End of walker.c **********************************************/
+/************** Begin file resolve.c *****************************************/
+/*
+** 2008 August 18
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains routines used for walking the parser tree and
+** resolve all identifiers by associating them with a particular
+** table and column.
+**
+** $Id: resolve.c,v 1.10 2008/10/19 21:03:27 drh Exp $
+*/
+
+/*
+** Turn the pExpr expression into an alias for the iCol-th column of the
+** result set in pEList.
+**
+** If the result set column is a simple column reference, then this routine
+** makes an exact copy. But for any other kind of expression, this
+** routine make a copy of the result set column as the argument to the
+** TK_AS operator. The TK_AS operator causes the expression to be
+** evaluated just once and then reused for each alias.
+**
+** The reason for suppressing the TK_AS term when the expression is a simple
+** column reference is so that the column reference will be recognized as
+** usable by indices within the WHERE clause processing logic.
+**
+** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
+** that in a GROUP BY clause, the expression is evaluated twice. Hence:
+**
+** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
+**
+** Is equivalent to:
+**
+** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
+**
+** The result of random()%5 in the GROUP BY clause is probably different
+** from the result in the result-set. We might fix this someday. Or
+** then again, we might not...
+*/
+static void resolveAlias(
+ Parse *pParse, /* Parsing context */
+ ExprList *pEList, /* A result set */
+ int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
+ Expr *pExpr, /* Transform this into an alias to the result set */
+ const char *zType /* "GROUP" or "ORDER" or "" */
+){
+ Expr *pOrig; /* The iCol-th column of the result set */
+ Expr *pDup; /* Copy of pOrig */
+ sqlite3 *db; /* The database connection */
+
+ assert( iCol>=0 && iCol<pEList->nExpr );
+ pOrig = pEList->a[iCol].pExpr;
+ assert( pOrig!=0 );
+ assert( pOrig->flags & EP_Resolved );
+ db = pParse->db;
+ pDup = sqlite3ExprDup(db, pOrig);
+ if( pDup==0 ) return;
+ if( pDup->op!=TK_COLUMN && zType[0]!='G' ){
+ pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
+ if( pDup==0 ) return;
+ if( pEList->a[iCol].iAlias==0 ){
+ pEList->a[iCol].iAlias = ++pParse->nAlias;
+ }
+ pDup->iTable = pEList->a[iCol].iAlias;
+ }
+ if( pExpr->flags & EP_ExpCollate ){
+ pDup->pColl = pExpr->pColl;
+ pDup->flags |= EP_ExpCollate;
+ }
+ sqlite3ExprClear(db, pExpr);
+ memcpy(pExpr, pDup, sizeof(*pExpr));
+ sqlite3DbFree(db, pDup);
+}
+
+/*
+** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
+** that name in the set of source tables in pSrcList and make the pExpr
+** expression node refer back to that source column. The following changes
+** are made to pExpr:
+**
+** pExpr->iDb Set the index in db->aDb[] of the database X
+** (even if X is implied).
+** pExpr->iTable Set to the cursor number for the table obtained
+** from pSrcList.
+** pExpr->pTab Points to the Table structure of X.Y (even if
+** X and/or Y are implied.)
+** pExpr->iColumn Set to the column number within the table.
+** pExpr->op Set to TK_COLUMN.
+** pExpr->pLeft Any expression this points to is deleted
+** pExpr->pRight Any expression this points to is deleted.
+**
+** The pDbToken is the name of the database (the "X"). This value may be
+** NULL meaning that name is of the form Y.Z or Z. Any available database
+** can be used. The pTableToken is the name of the table (the "Y"). This
+** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it
+** means that the form of the name is Z and that columns from any table
+** can be used.
+**
+** If the name cannot be resolved unambiguously, leave an error message
+** in pParse and return non-zero. Return zero on success.
+*/
+static int lookupName(
+ Parse *pParse, /* The parsing context */
+ Token *pDbToken, /* Name of the database containing table, or NULL */
+ Token *pTableToken, /* Name of table containing column, or NULL */
+ Token *pColumnToken, /* Name of the column. */
+ NameContext *pNC, /* The name context used to resolve the name */
+ Expr *pExpr /* Make this EXPR node point to the selected column */
+){
+ char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
+ char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
+ char *zCol = 0; /* Name of the column. The "Z" */
+ int i, j; /* Loop counters */
+ int cnt = 0; /* Number of matching column names */
+ int cntTab = 0; /* Number of matching table names */
+ sqlite3 *db = pParse->db; /* The database connection */
+ struct SrcList_item *pItem; /* Use for looping over pSrcList items */
+ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
+ NameContext *pTopNC = pNC; /* First namecontext in the list */
+ Schema *pSchema = 0; /* Schema of the expression */
+
+ assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
+
+ /* Dequote and zero-terminate the names */
+ zDb = sqlite3NameFromToken(db, pDbToken);
+ zTab = sqlite3NameFromToken(db, pTableToken);
+ zCol = sqlite3NameFromToken(db, pColumnToken);
+ if( db->mallocFailed ){
+ goto lookupname_end;
+ }
+
+ /* Initialize the node to no-match */
+ pExpr->iTable = -1;
+ pExpr->pTab = 0;
+
+ /* Start at the inner-most context and move outward until a match is found */
+ while( pNC && cnt==0 ){
+ ExprList *pEList;
+ SrcList *pSrcList = pNC->pSrcList;
+
+ if( pSrcList ){
+ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
+ Table *pTab;
+ int iDb;
+ Column *pCol;
+
+ pTab = pItem->pTab;
+ assert( pTab!=0 && pTab->zName!=0 );
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( pTab->nCol>0 );
+ if( zTab ){
+ if( pItem->zAlias ){
+ char *zTabName = pItem->zAlias;
+ if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ }else{
+ char *zTabName = pTab->zName;
+ if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
+ continue;
+ }
+ }
+ }
+ if( 0==(cntTab++) ){
+ pExpr->iTable = pItem->iCursor;
+ pExpr->pTab = pTab;
+ pSchema = pTab->pSchema;
+ pMatch = pItem;
+ }
+ for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ IdList *pUsing;
+ cnt++;
+ pExpr->iTable = pItem->iCursor;
+ pExpr->pTab = pTab;
+ pMatch = pItem;
+ pSchema = pTab->pSchema;
+ /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+ pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+ if( i<pSrcList->nSrc-1 ){
+ if( pItem[1].jointype & JT_NATURAL ){
+ /* If this match occurred in the left table of a natural join,
+ ** then skip the right table to avoid a duplicate match */
+ pItem++;
+ i++;
+ }else if( (pUsing = pItem[1].pUsing)!=0 ){
+ /* If this match occurs on a column that is in the USING clause
+ ** of a join, skip the search of the right table of the join
+ ** to avoid a duplicate match there. */
+ int k;
+ for(k=0; k<pUsing->nId; k++){
+ if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
+ pItem++;
+ i++;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* If we have not already resolved the name, then maybe
+ ** it is a new.* or old.* trigger argument reference
+ */
+ if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
+ TriggerStack *pTriggerStack = pParse->trigStack;
+ Table *pTab = 0;
+ u32 *piColMask;
+ if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
+ pExpr->iTable = pTriggerStack->newIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
+ piColMask = &(pTriggerStack->newColMask);
+ }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
+ pExpr->iTable = pTriggerStack->oldIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
+ piColMask = &(pTriggerStack->oldColMask);
+ }
+
+ if( pTab ){
+ int iCol;
+ Column *pCol = pTab->aCol;
+
+ pSchema = pTab->pSchema;
+ cntTab++;
+ for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ cnt++;
+ pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
+ pExpr->pTab = pTab;
+ if( iCol>=0 ){
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
+ }
+ break;
+ }
+ }
+ }
+ }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+
+ /*
+ ** Perhaps the name is a reference to the ROWID
+ */
+ if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+ cnt = 1;
+ pExpr->iColumn = -1;
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ }
+
+ /*
+ ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
+ ** might refer to an result-set alias. This happens, for example, when
+ ** we are resolving names in the WHERE clause of the following command:
+ **
+ ** SELECT a+b AS x FROM table WHERE x<10;
+ **
+ ** In cases like this, replace pExpr with a copy of the expression that
+ ** forms the result set entry ("a+b" in the example) and return immediately.
+ ** Note that the expression in the result set should have already been
+ ** resolved by the time the WHERE clause is resolved.
+ */
+ if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
+ for(j=0; j<pEList->nExpr; j++){
+ char *zAs = pEList->a[j].zName;
+ if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ Expr *pOrig;
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ assert( pExpr->pList==0 );
+ assert( pExpr->pSelect==0 );
+ pOrig = pEList->a[j].pExpr;
+ if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
+ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
+ sqlite3DbFree(db, zCol);
+ return 2;
+ }
+ resolveAlias(pParse, pEList, j, pExpr, "");
+ cnt = 1;
+ pMatch = 0;
+ assert( zTab==0 && zDb==0 );
+ goto lookupname_end_2;
+ }
+ }
+ }
+
+ /* Advance to the next name context. The loop will exit when either
+ ** we have a match (cnt>0) or when we run out of name contexts.
+ */
+ if( cnt==0 ){
+ pNC = pNC->pNext;
+ }
+ }
+
+ /*
+ ** If X and Y are NULL (in other words if only the column name Z is
+ ** supplied) and the value of Z is enclosed in double-quotes, then
+ ** Z is a string literal if it doesn't match any column names. In that
+ ** case, we need to return right away and not make any changes to
+ ** pExpr.
+ **
+ ** Because no reference was made to outer contexts, the pNC->nRef
+ ** fields are not changed in any context.
+ */
+ if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
+ sqlite3DbFree(db, zCol);
+ pExpr->op = TK_STRING;
+ pExpr->pTab = 0;
+ return 0;
+ }
+
+ /*
+ ** cnt==0 means there was not match. cnt>1 means there were two or
+ ** more matches. Either way, we have an error.
+ */
+ if( cnt!=1 ){
+ const char *zErr;
+ zErr = cnt==0 ? "no such column" : "ambiguous column name";
+ if( zDb ){
+ sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
+ }else if( zTab ){
+ sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
+ }else{
+ sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
+ }
+ pTopNC->nErr++;
+ }
+
+ /* If a column from a table in pSrcList is referenced, then record
+ ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
+ ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
+ ** column number is greater than the number of bits in the bitmask
+ ** then set the high-order bit of the bitmask.
+ */
+ if( pExpr->iColumn>=0 && pMatch!=0 ){
+ int n = pExpr->iColumn;
+ testcase( n==sizeof(Bitmask)*8-1 );
+ if( n>=sizeof(Bitmask)*8 ){
+ n = sizeof(Bitmask)*8-1;
+ }
+ assert( pMatch->iCursor==pExpr->iTable );
+ pMatch->colUsed |= ((Bitmask)1)<<n;
+ }
+
+lookupname_end:
+ /* Clean up and return
+ */
+ sqlite3DbFree(db, zDb);
+ sqlite3DbFree(db, zTab);
+ sqlite3ExprDelete(db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ sqlite3ExprDelete(db, pExpr->pRight);
+ pExpr->pRight = 0;
+ pExpr->op = TK_COLUMN;
+lookupname_end_2:
+ sqlite3DbFree(db, zCol);
+ if( cnt==1 ){
+ assert( pNC!=0 );
+ sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
+ /* Increment the nRef value on all name contexts from TopNC up to
+ ** the point where the name matched. */
+ for(;;){
+ assert( pTopNC!=0 );
+ pTopNC->nRef++;
+ if( pTopNC==pNC ) break;
+ pTopNC = pTopNC->pNext;
+ }
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/*
+** This routine is callback for sqlite3WalkExpr().
+**
+** Resolve symbolic names into TK_COLUMN operators for the current
+** node in the expression tree. Return 0 to continue the search down
+** the tree or 2 to abort the tree walk.
+**
+** This routine also does error checking and name resolution for
+** function names. The operator for aggregate functions is changed
+** to TK_AGG_FUNCTION.
+*/
+static int resolveExprStep(Walker *pWalker, Expr *pExpr){
+ NameContext *pNC;
+ Parse *pParse;
+
+ pNC = pWalker->u.pNC;
+ assert( pNC!=0 );
+ pParse = pNC->pParse;
+ assert( pParse==pWalker->pParse );
+
+ if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
+ ExprSetProperty(pExpr, EP_Resolved);
+#ifndef NDEBUG
+ if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
+ SrcList *pSrcList = pNC->pSrcList;
+ int i;
+ for(i=0; i<pNC->pSrcList->nSrc; i++){
+ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
+ }
+ }
+#endif
+ switch( pExpr->op ){
+
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
+ /* The special operator TK_ROW means use the rowid for the first
+ ** column in the FROM clause. This is used by the LIMIT and ORDER BY
+ ** clause processing on UPDATE and DELETE statements.
+ */
+ case TK_ROW: {
+ SrcList *pSrcList = pNC->pSrcList;
+ struct SrcList_item *pItem;
+ assert( pSrcList && pSrcList->nSrc==1 );
+ pItem = pSrcList->a;
+ pExpr->op = TK_COLUMN;
+ pExpr->pTab = pItem->pTab;
+ pExpr->iTable = pItem->iCursor;
+ pExpr->iColumn = -1;
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ break;
+ }
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
+
+ /* A lone identifier is the name of a column.
+ */
+ case TK_ID: {
+ lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
+ return WRC_Prune;
+ }
+
+ /* A table name and column name: ID.ID
+ ** Or a database, table and column: ID.ID.ID
+ */
+ case TK_DOT: {
+ Token *pColumn;
+ Token *pTable;
+ Token *pDb;
+ Expr *pRight;
+
+ /* if( pSrcList==0 ) break; */
+ pRight = pExpr->pRight;
+ if( pRight->op==TK_ID ){
+ pDb = 0;
+ pTable = &pExpr->pLeft->token;
+ pColumn = &pRight->token;
+ }else{
+ assert( pRight->op==TK_DOT );
+ pDb = &pExpr->pLeft->token;
+ pTable = &pRight->pLeft->token;
+ pColumn = &pRight->pRight->token;
+ }
+ lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
+ return WRC_Prune;
+ }
+
+ /* Resolve function names
+ */
+ case TK_CONST_FUNC:
+ case TK_FUNCTION: {
+ ExprList *pList = pExpr->pList; /* The argument list */
+ int n = pList ? pList->nExpr : 0; /* Number of arguments */
+ int no_such_func = 0; /* True if no such function exists */
+ int wrong_num_args = 0; /* True if wrong number of arguments */
+ int is_agg = 0; /* True if is an aggregate function */
+ int auth; /* Authorization to use the function */
+ int nId; /* Number of characters in function name */
+ const char *zId; /* The function name. */
+ FuncDef *pDef; /* Information about the function */
+ int enc = ENC(pParse->db); /* The database encoding */
+
+ zId = (char*)pExpr->token.z;
+ nId = pExpr->token.n;
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
+ if( pDef==0 ){
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
+ if( pDef==0 ){
+ no_such_func = 1;
+ }else{
+ wrong_num_args = 1;
+ }
+ }else{
+ is_agg = pDef->xFunc==0;
+ }
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pDef ){
+ auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
+ if( auth!=SQLITE_OK ){
+ if( auth==SQLITE_DENY ){
+ sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
+ pDef->zName);
+ pNC->nErr++;
+ }
+ pExpr->op = TK_NULL;
+ return WRC_Prune;
+ }
+ }
+#endif
+ if( is_agg && !pNC->allowAgg ){
+ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+ pNC->nErr++;
+ is_agg = 0;
+ }else if( no_such_func ){
+ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+ pNC->nErr++;
+ }else if( wrong_num_args ){
+ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+ nId, zId);
+ pNC->nErr++;
+ }
+ if( is_agg ){
+ pExpr->op = TK_AGG_FUNCTION;
+ pNC->hasAgg = 1;
+ }
+ if( is_agg ) pNC->allowAgg = 0;
+ sqlite3WalkExprList(pWalker, pList);
+ if( is_agg ) pNC->allowAgg = 1;
+ /* FIX ME: Compute pExpr->affinity based on the expected return
+ ** type of the function
+ */
+ return WRC_Prune;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_SELECT:
+ case TK_EXISTS:
+#endif
+ case TK_IN: {
+ if( pExpr->pSelect ){
+ int nRef = pNC->nRef;
+#ifndef SQLITE_OMIT_CHECK
+ if( pNC->isCheck ){
+ sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
+ }
+#endif
+ sqlite3WalkSelect(pWalker, pExpr->pSelect);
+ assert( pNC->nRef>=nRef );
+ if( nRef!=pNC->nRef ){
+ ExprSetProperty(pExpr, EP_VarSelect);
+ }
+ }
+ break;
+ }
+#ifndef SQLITE_OMIT_CHECK
+ case TK_VARIABLE: {
+ if( pNC->isCheck ){
+ sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
+ }
+ break;
+ }
+#endif
+ }
+ return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
+}
+
+/*
+** pEList is a list of expressions which are really the result set of the
+** a SELECT statement. pE is a term in an ORDER BY or GROUP BY clause.
+** This routine checks to see if pE is a simple identifier which corresponds
+** to the AS-name of one of the terms of the expression list. If it is,
+** this routine return an integer between 1 and N where N is the number of
+** elements in pEList, corresponding to the matching entry. If there is
+** no match, or if pE is not a simple identifier, then this routine
+** return 0.
+**
+** pEList has been resolved. pE has not.
+*/
+static int resolveAsName(
+ Parse *pParse, /* Parsing context for error messages */
+ ExprList *pEList, /* List of expressions to scan */
+ Expr *pE /* Expression we are trying to match */
+){
+ int i; /* Loop counter */
+
+ if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
+ sqlite3 *db = pParse->db;
+ char *zCol = sqlite3NameFromToken(db, &pE->token);
+ if( zCol==0 ){
+ return -1;
+ }
+ for(i=0; i<pEList->nExpr; i++){
+ char *zAs = pEList->a[i].zName;
+ if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ sqlite3DbFree(db, zCol);
+ return i+1;
+ }
+ }
+ sqlite3DbFree(db, zCol);
+ }
+ return 0;
+}
+
+/*
+** pE is a pointer to an expression which is a single term in the
+** ORDER BY of a compound SELECT. The expression has not been
+** name resolved.
+**
+** At the point this routine is called, we already know that the
+** ORDER BY term is not an integer index into the result set. That
+** case is handled by the calling routine.
+**
+** Attempt to match pE against result set columns in the left-most
+** SELECT statement. Return the index i of the matching column,
+** as an indication to the caller that it should sort by the i-th column.
+** The left-most column is 1. In other words, the value returned is the
+** same integer value that would be used in the SQL statement to indicate
+** the column.
+**
+** If there is no match, return 0. Return -1 if an error occurs.
+*/
+static int resolveOrderByTermToExprList(
+ Parse *pParse, /* Parsing context for error messages */
+ Select *pSelect, /* The SELECT statement with the ORDER BY clause */
+ Expr *pE /* The specific ORDER BY term */
+){
+ int i; /* Loop counter */
+ ExprList *pEList; /* The columns of the result set */
+ NameContext nc; /* Name context for resolving pE */
+
+ assert( sqlite3ExprIsInteger(pE, &i)==0 );
+ pEList = pSelect->pEList;
+
+ /* Resolve all names in the ORDER BY term expression
+ */
+ memset(&nc, 0, sizeof(nc));
+ nc.pParse = pParse;
+ nc.pSrcList = pSelect->pSrc;
+ nc.pEList = pEList;
+ nc.allowAgg = 1;
+ nc.nErr = 0;
+ if( sqlite3ResolveExprNames(&nc, pE) ){
+ sqlite3ErrorClear(pParse);
+ return 0;
+ }
+
+ /* Try to match the ORDER BY expression against an expression
+ ** in the result set. Return an 1-based index of the matching
+ ** result-set entry.
+ */
+ for(i=0; i<pEList->nExpr; i++){
+ if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
+ return i+1;
+ }
+ }
+
+ /* If no match, return 0. */
+ return 0;
+}
+
+/*
+** Generate an ORDER BY or GROUP BY term out-of-range error.
+*/
+static void resolveOutOfRangeError(
+ Parse *pParse, /* The error context into which to write the error */
+ const char *zType, /* "ORDER" or "GROUP" */
+ int i, /* The index (1-based) of the term out of range */
+ int mx /* Largest permissible value of i */
+){
+ sqlite3ErrorMsg(pParse,
+ "%r %s BY term out of range - should be "
+ "between 1 and %d", i, zType, mx);
+}
+
+/*
+** Analyze the ORDER BY clause in a compound SELECT statement. Modify
+** each term of the ORDER BY clause is a constant integer between 1
+** and N where N is the number of columns in the compound SELECT.
+**
+** ORDER BY terms that are already an integer between 1 and N are
+** unmodified. ORDER BY terms that are integers outside the range of
+** 1 through N generate an error. ORDER BY terms that are expressions
+** are matched against result set expressions of compound SELECT
+** beginning with the left-most SELECT and working toward the right.
+** At the first match, the ORDER BY expression is transformed into
+** the integer column number.
+**
+** Return the number of errors seen.
+*/
+static int resolveCompoundOrderBy(
+ Parse *pParse, /* Parsing context. Leave error messages here */
+ Select *pSelect /* The SELECT statement containing the ORDER BY */
+){
+ int i;
+ ExprList *pOrderBy;
+ ExprList *pEList;
+ sqlite3 *db;
+ int moreToDo = 1;
+
+ pOrderBy = pSelect->pOrderBy;
+ if( pOrderBy==0 ) return 0;
+ db = pParse->db;
+#if SQLITE_MAX_COLUMN
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
+ return 1;
+ }
+#endif
+ for(i=0; i<pOrderBy->nExpr; i++){
+ pOrderBy->a[i].done = 0;
+ }
+ pSelect->pNext = 0;
+ while( pSelect->pPrior ){
+ pSelect->pPrior->pNext = pSelect;
+ pSelect = pSelect->pPrior;
+ }
+ while( pSelect && moreToDo ){
+ struct ExprList_item *pItem;
+ moreToDo = 0;
+ pEList = pSelect->pEList;
+ assert( pEList!=0 );
+ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+ int iCol = -1;
+ Expr *pE, *pDup;
+ if( pItem->done ) continue;
+ pE = pItem->pExpr;
+ if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( iCol<0 || iCol>pEList->nExpr ){
+ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
+ return 1;
+ }
+ }else{
+ iCol = resolveAsName(pParse, pEList, pE);
+ if( iCol==0 ){
+ pDup = sqlite3ExprDup(db, pE);
+ if( !db->mallocFailed ){
+ assert(pDup);
+ iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
+ }
+ sqlite3ExprDelete(db, pDup);
+ }
+ if( iCol<0 ){
+ return 1;
+ }
+ }
+ if( iCol>0 ){
+ CollSeq *pColl = pE->pColl;
+ int flags = pE->flags & EP_ExpCollate;
+ sqlite3ExprDelete(db, pE);
+ pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0, 0, 0);
+ if( pE==0 ) return 1;
+ pE->pColl = pColl;
+ pE->flags |= EP_IntValue | flags;
+ pE->iTable = iCol;
+ pItem->iCol = iCol;
+ pItem->done = 1;
+ }else{
+ moreToDo = 1;
+ }
+ }
+ pSelect = pSelect->pNext;
+ }
+ for(i=0; i<pOrderBy->nExpr; i++){
+ if( pOrderBy->a[i].done==0 ){
+ sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
+ "column in the result set", i+1);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
+** the SELECT statement pSelect. If any term is reference to a
+** result set expression (as determined by the ExprList.a.iCol field)
+** then convert that term into a copy of the corresponding result set
+** column.
+**
+** If any errors are detected, add an error message to pParse and
+** return non-zero. Return zero if no errors are seen.
+*/
+SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
+ Parse *pParse, /* Parsing context. Leave error messages here */
+ Select *pSelect, /* The SELECT statement containing the clause */
+ ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */
+ const char *zType /* "ORDER" or "GROUP" */
+){
+ int i;
+ sqlite3 *db = pParse->db;
+ ExprList *pEList;
+ struct ExprList_item *pItem;
+
+ if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
+#if SQLITE_MAX_COLUMN
+ if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
+ return 1;
+ }
+#endif
+ pEList = pSelect->pEList;
+ assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
+ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+ if( pItem->iCol ){
+ if( pItem->iCol>pEList->nExpr ){
+ resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
+ return 1;
+ }
+ resolveAlias(pParse, pEList, pItem->iCol-1, pItem->pExpr, zType);
+ }
+ }
+ return 0;
+}
+
+/*
+** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
+** The Name context of the SELECT statement is pNC. zType is either
+** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
+**
+** This routine resolves each term of the clause into an expression.
+** If the order-by term is an integer I between 1 and N (where N is the
+** number of columns in the result set of the SELECT) then the expression
+** in the resolution is a copy of the I-th result-set expression. If
+** the order-by term is an identify that corresponds to the AS-name of
+** a result-set expression, then the term resolves to a copy of the
+** result-set expression. Otherwise, the expression is resolved in
+** the usual way - using sqlite3ResolveExprNames().
+**
+** This routine returns the number of errors. If errors occur, then
+** an appropriate error message might be left in pParse. (OOM errors
+** excepted.)
+*/
+static int resolveOrderGroupBy(
+ NameContext *pNC, /* The name context of the SELECT statement */
+ Select *pSelect, /* The SELECT statement holding pOrderBy */
+ ExprList *pOrderBy, /* An ORDER BY or GROUP BY clause to resolve */
+ const char *zType /* Either "ORDER" or "GROUP", as appropriate */
+){
+ int i; /* Loop counter */
+ int iCol; /* Column number */
+ struct ExprList_item *pItem; /* A term of the ORDER BY clause */
+ Parse *pParse; /* Parsing context */
+ int nResult; /* Number of terms in the result set */
+
+ if( pOrderBy==0 ) return 0;
+ nResult = pSelect->pEList->nExpr;
+ pParse = pNC->pParse;
+ for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
+ Expr *pE = pItem->pExpr;
+ iCol = resolveAsName(pParse, pSelect->pEList, pE);
+ if( iCol<0 ){
+ return 1; /* OOM error */
+ }
+ if( iCol>0 ){
+ /* If an AS-name match is found, mark this ORDER BY column as being
+ ** a copy of the iCol-th result-set column. The subsequent call to
+ ** sqlite3ResolveOrderGroupBy() will convert the expression to a
+ ** copy of the iCol-th result-set expression. */
+ pItem->iCol = iCol;
+ continue;
+ }
+ if( sqlite3ExprIsInteger(pE, &iCol) ){
+ /* The ORDER BY term is an integer constant. Again, set the column
+ ** number so that sqlite3ResolveOrderGroupBy() will convert the
+ ** order-by term to a copy of the result-set expression */
+ if( iCol<1 ){
+ resolveOutOfRangeError(pParse, zType, i+1, nResult);
+ return 1;
+ }
+ pItem->iCol = iCol;
+ continue;
+ }
+
+ /* Otherwise, treat the ORDER BY term as an ordinary expression */
+ pItem->iCol = 0;
+ if( sqlite3ResolveExprNames(pNC, pE) ){
+ return 1;
+ }
+ }
+ return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
+}
+
+/*
+** Resolve names in the SELECT statement p and all of its descendents.
+*/
+static int resolveSelectStep(Walker *pWalker, Select *p){
+ NameContext *pOuterNC; /* Context that contains this SELECT */
+ NameContext sNC; /* Name context of this SELECT */
+ int isCompound; /* True if p is a compound select */
+ int nCompound; /* Number of compound terms processed so far */
+ Parse *pParse; /* Parsing context */
+ ExprList *pEList; /* Result set expression list */
+ int i; /* Loop counter */
+ ExprList *pGroupBy; /* The GROUP BY clause */
+ Select *pLeftmost; /* Left-most of SELECT of a compound */
+ sqlite3 *db; /* Database connection */
+
+
+ assert( p!=0 );
+ if( p->selFlags & SF_Resolved ){
+ return WRC_Prune;
+ }
+ pOuterNC = pWalker->u.pNC;
+ pParse = pWalker->pParse;
+ db = pParse->db;
+
+ /* Normally sqlite3SelectExpand() will be called first and will have
+ ** already expanded this SELECT. However, if this is a subquery within
+ ** an expression, sqlite3ResolveExprNames() will be called without a
+ ** prior call to sqlite3SelectExpand(). When that happens, let
+ ** sqlite3SelectPrep() do all of the processing for this SELECT.
+ ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
+ ** this routine in the correct order.
+ */
+ if( (p->selFlags & SF_Expanded)==0 ){
+ sqlite3SelectPrep(pParse, p, pOuterNC);
+ return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
+ }
+
+ isCompound = p->pPrior!=0;
+ nCompound = 0;
+ pLeftmost = p;
+ while( p ){
+ assert( (p->selFlags & SF_Expanded)!=0 );
+ assert( (p->selFlags & SF_Resolved)==0 );
+ p->selFlags |= SF_Resolved;
+
+ /* Resolve the expressions in the LIMIT and OFFSET clauses. These
+ ** are not allowed to refer to any names, so pass an empty NameContext.
+ */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ if( sqlite3ResolveExprNames(&sNC, p->pLimit) ||
+ sqlite3ResolveExprNames(&sNC, p->pOffset) ){
+ return WRC_Abort;
+ }
+
+ /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
+ ** resolve the result-set expression list.
+ */
+ sNC.allowAgg = 1;
+ sNC.pSrcList = p->pSrc;
+ sNC.pNext = pOuterNC;
+
+ /* Resolve names in the result set. */
+ pEList = p->pEList;
+ assert( pEList!=0 );
+ for(i=0; i<pEList->nExpr; i++){
+ Expr *pX = pEList->a[i].pExpr;
+ if( sqlite3ResolveExprNames(&sNC, pX) ){
+ return WRC_Abort;
+ }
+ }
+
+ /* Recursively resolve names in all subqueries
+ */
+ for(i=0; i<p->pSrc->nSrc; i++){
+ struct SrcList_item *pItem = &p->pSrc->a[i];
+ if( pItem->pSelect ){
+ const char *zSavedContext = pParse->zAuthContext;
+ if( pItem->zName ) pParse->zAuthContext = pItem->zName;
+ sqlite3ResolveSelectNames(pParse, pItem->pSelect, &sNC);
+ pParse->zAuthContext = zSavedContext;
+ if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
+ }
+ }
+
+ /* If there are no aggregate functions in the result-set, and no GROUP BY
+ ** expression, do not allow aggregates in any of the other expressions.
+ */
+ assert( (p->selFlags & SF_Aggregate)==0 );
+ pGroupBy = p->pGroupBy;
+ if( pGroupBy || sNC.hasAgg ){
+ p->selFlags |= SF_Aggregate;
+ }else{
+ sNC.allowAgg = 0;
+ }
+
+ /* If a HAVING clause is present, then there must be a GROUP BY clause.
+ */
+ if( p->pHaving && !pGroupBy ){
+ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
+ return WRC_Abort;
+ }
+
+ /* Add the expression list to the name-context before parsing the
+ ** other expressions in the SELECT statement. This is so that
+ ** expressions in the WHERE clause (etc.) can refer to expressions by
+ ** aliases in the result set.
+ **
+ ** Minor point: If this is the case, then the expression will be
+ ** re-evaluated for each reference to it.
+ */
+ sNC.pEList = p->pEList;
+ if( sqlite3ResolveExprNames(&sNC, p->pWhere) ||
+ sqlite3ResolveExprNames(&sNC, p->pHaving)
+ ){
+ return WRC_Abort;
+ }
+
+ /* The ORDER BY and GROUP BY clauses may not refer to terms in
+ ** outer queries
+ */
+ sNC.pNext = 0;
+ sNC.allowAgg = 1;
+
+ /* Process the ORDER BY clause for singleton SELECT statements.
+ ** The ORDER BY clause for compounds SELECT statements is handled
+ ** below, after all of the result-sets for all of the elements of
+ ** the compound have been resolved.
+ */
+ if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
+ return WRC_Abort;
+ }
+ if( db->mallocFailed ){
+ return WRC_Abort;
+ }
+
+ /* Resolve the GROUP BY clause. At the same time, make sure
+ ** the GROUP BY clause does not contain aggregate functions.
+ */
+ if( pGroupBy ){
+ struct ExprList_item *pItem;
+
+ if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
+ return WRC_Abort;
+ }
+ for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
+ if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
+ sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
+ "the GROUP BY clause");
+ return WRC_Abort;
+ }
+ }
+ }
+
+ /* Advance to the next term of the compound
+ */
+ p = p->pPrior;
+ nCompound++;
+ }
+
+ /* Resolve the ORDER BY on a compound SELECT after all terms of
+ ** the compound have been resolved.
+ */
+ if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
+ return WRC_Abort;
+ }
+
+ return WRC_Prune;
+}
+
+/*
+** This routine walks an expression tree and resolves references to
+** table columns and result-set columns. At the same time, do error
+** checking on function usage and set a flag if any aggregate functions
+** are seen.
+**
+** To resolve table columns references we look for nodes (or subtrees) of the
+** form X.Y.Z or Y.Z or just Z where
+**
+** X: The name of a database. Ex: "main" or "temp" or
+** the symbolic name assigned to an ATTACH-ed database.
+**
+** Y: The name of a table in a FROM clause. Or in a trigger
+** one of the special names "old" or "new".
+**
+** Z: The name of a column in table Y.
+**
+** The node at the root of the subtree is modified as follows:
+**
+** Expr.op Changed to TK_COLUMN
+** Expr.pTab Points to the Table object for X.Y
+** Expr.iColumn The column index in X.Y. -1 for the rowid.
+** Expr.iTable The VDBE cursor number for X.Y
+**
+**
+** To resolve result-set references, look for expression nodes of the
+** form Z (with no X and Y prefix) where the Z matches the right-hand
+** size of an AS clause in the result-set of a SELECT. The Z expression
+** is replaced by a copy of the left-hand side of the result-set expression.
+** Table-name and function resolution occurs on the substituted expression
+** tree. For example, in:
+**
+** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
+**
+** The "x" term of the order by is replaced by "a+b" to render:
+**
+** SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
+**
+** Function calls are checked to make sure that the function is
+** defined and that the correct number of arguments are specified.
+** If the function is an aggregate function, then the pNC->hasAgg is
+** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
+** If an expression contains aggregate functions then the EP_Agg
+** property on the expression is set.
+**
+** An error message is left in pParse if anything is amiss. The number
+** if errors is returned.
+*/
+SQLITE_PRIVATE int sqlite3ResolveExprNames(
+ NameContext *pNC, /* Namespace to resolve expressions in. */
+ Expr *pExpr /* The expression to be analyzed. */
+){
+ int savedHasAgg;
+ Walker w;
+
+ if( pExpr==0 ) return 0;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ {
+ Parse *pParse = pNC->pParse;
+ if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
+ return 1;
+ }
+ pParse->nHeight += pExpr->nHeight;
+ }
+#endif
+ savedHasAgg = pNC->hasAgg;
+ pNC->hasAgg = 0;
+ w.xExprCallback = resolveExprStep;
+ w.xSelectCallback = resolveSelectStep;
+ w.pParse = pNC->pParse;
+ w.u.pNC = pNC;
+ sqlite3WalkExpr(&w, pExpr);
+#if SQLITE_MAX_EXPR_DEPTH>0
+ pNC->pParse->nHeight -= pExpr->nHeight;
+#endif
+ if( pNC->nErr>0 ){
+ ExprSetProperty(pExpr, EP_Error);
+ }
+ if( pNC->hasAgg ){
+ ExprSetProperty(pExpr, EP_Agg);
+ }else if( savedHasAgg ){
+ pNC->hasAgg = 1;
+ }
+ return ExprHasProperty(pExpr, EP_Error);
+}
+
+
+/*
+** Resolve all names in all expressions of a SELECT and in all
+** decendents of the SELECT, including compounds off of p->pPrior,
+** subqueries in expressions, and subqueries used as FROM clause
+** terms.
+**
+** See sqlite3ResolveExprNames() for a description of the kinds of
+** transformations that occur.
+**
+** All SELECT statements should have been expanded using
+** sqlite3SelectExpand() prior to invoking this routine.
+*/
+SQLITE_PRIVATE void sqlite3ResolveSelectNames(
+ Parse *pParse, /* The parser context */
+ Select *p, /* The SELECT statement being coded. */
+ NameContext *pOuterNC /* Name context for parent SELECT statement */
+){
+ Walker w;
+
+ assert( p!=0 );
+ w.xExprCallback = resolveExprStep;
+ w.xSelectCallback = resolveSelectStep;
+ w.pParse = pParse;
+ w.u.pNC = pOuterNC;
+ sqlite3WalkSelect(&w, p);
+}
+
+/************** End of resolve.c *********************************************/
/************** Begin file expr.c ********************************************/
/*
** 2001 September 15
**
@@ -49351,9 +52716,9 @@
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.385 2008/07/09 01:39:44 drh Exp $
+** $Id: expr.c,v 1.400 2008/10/25 15:03:21 drh Exp $
*/
/*
** Return the 'affinity' of the expression pExpr if any.
@@ -49380,8 +52745,16 @@
if( op==TK_CAST ){
return sqlite3AffinityType(&pExpr->token);
}
#endif
+ if( (op==TK_COLUMN || op==TK_REGISTER) && pExpr->pTab!=0 ){
+ /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
+ int j = pExpr->iColumn;
+ if( j<0 ) return SQLITE_AFF_INTEGER;
+ assert( pExpr->pTab && j<pExpr->pTab->nCol );
+ return pExpr->pTab->aCol[j].affinity;
+ }
return pExpr->affinity;
}
/*
@@ -49390,20 +52763,21 @@
** The collating sequence is marked as "explicit" using the EP_ExpCollate
** flag. An explicit collating sequence will override implicit
** collating sequences.
*/
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
+SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){
char *zColl = 0; /* Dequoted name of collation sequence */
CollSeq *pColl;
- zColl = sqlite3NameFromToken(pParse->db, pName);
+ sqlite3 *db = pParse->db;
+ zColl = sqlite3NameFromToken(db, pCollName);
if( pExpr && zColl ){
pColl = sqlite3LocateCollSeq(pParse, zColl, -1);
if( pColl ){
pExpr->pColl = pColl;
pExpr->flags |= EP_ExpCollate;
}
}
- sqlite3_free(zColl);
+ sqlite3DbFree(db, zColl);
return pExpr;
}
/*
@@ -49411,15 +52785,31 @@
** there is no default collation type, return 0.
*/
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
CollSeq *pColl = 0;
- if( pExpr ){
+ Expr *p = pExpr;
+ while( p ){
int op;
- pColl = pExpr->pColl;
- op = pExpr->op;
- if( (op==TK_CAST || op==TK_UPLUS) && !pColl ){
- return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- }
+ pColl = p->pColl;
+ if( pColl ) break;
+ op = p->op;
+ if( (op==TK_COLUMN || op==TK_REGISTER) && p->pTab!=0 ){
+ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
+ const char *zColl;
+ int j = p->iColumn;
+ if( j>=0 ){
+ sqlite3 *db = pParse->db;
+ zColl = p->pTab->aCol[j].zColl;
+ pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);
+ pExpr->pColl = pColl;
+ }
+ break;
+ }
+ if( op!=TK_CAST && op!=TK_UPLUS ){
+ break;
+ }
+ p = p->pLeft;
}
if( sqlite3CheckCollSeq(pParse, pColl) ){
pColl = 0;
}
@@ -49596,9 +52986,9 @@
** Check that argument nHeight is less than or equal to the maximum
** expression depth allowed. If it is not, leave an error message in
** pParse.
*/
-static int checkExprHeight(Parse *pParse, int nHeight){
+SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
int rc = SQLITE_OK;
int mxHeight = pParse->db->aLimit[SQLITE_LIMIT_EXPR_DEPTH];
if( nHeight>mxHeight ){
sqlite3ErrorMsg(pParse,
@@ -49668,9 +53058,9 @@
** leave an error in pParse.
*/
SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){
exprSetHeight(p);
- checkExprHeight(pParse, p->nHeight);
+ sqlite3ExprCheckHeight(pParse, p->nHeight);
}
/*
** Return the maximum height of any expression tree referenced
@@ -49681,9 +53071,8 @@
heightOfSelect(p, &nHeight);
return nHeight;
}
#else
- #define checkExprHeight(x,y)
#define exprSetHeight(y)
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
/*
@@ -49704,10 +53093,10 @@
/* When malloc fails, delete pLeft and pRight. Expressions passed to
** this function must always be allocated with sqlite3Expr() for this
** reason.
*/
- sqlite3ExprDelete(pLeft);
- sqlite3ExprDelete(pRight);
+ sqlite3ExprDelete(db, pLeft);
+ sqlite3ExprDelete(db, pRight);
return 0;
}
pNew->op = op;
pNew->pLeft = pLeft;
@@ -49749,9 +53138,9 @@
const Token *pToken /* Argument token */
){
Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken);
if( p ){
- checkExprHeight(pParse, p->nHeight);
+ sqlite3ExprCheckHeight(pParse, p->nHeight);
}
return p;
}
@@ -49802,9 +53191,9 @@
*/
SQLITE_PRIVATE void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
assert( pRight!=0 );
assert( pLeft!=0 );
- if( pExpr && pRight->z && pLeft->z ){
+ if( pExpr ){
pExpr->span.z = pLeft->z;
pExpr->span.n = pRight->n + (pRight->z - pLeft->z);
}
}
@@ -49814,12 +53203,13 @@
** arguments.
*/
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
Expr *pNew;
+ sqlite3 *db = pParse->db;
assert( pToken );
- pNew = sqlite3DbMallocZero(pParse->db, sizeof(Expr) );
+ pNew = sqlite3DbMallocZero(db, sizeof(Expr) );
if( pNew==0 ){
- sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */
+ sqlite3ExprListDelete(db, pList); /* Avoid leaking memory when malloc fails */
return 0;
}
pNew->op = TK_FUNCTION;
pNew->pList = pList;
@@ -49913,19 +53303,27 @@
}
}
/*
+** Clear an expression structure without deleting the structure itself.
+** Substructure is deleted.
+*/
+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(Expr *p){
+SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p==0 ) return;
- if( p->span.dyn ) sqlite3_free((char*)p->span.z);
- if( p->token.dyn ) sqlite3_free((char*)p->token.z);
- sqlite3ExprDelete(p->pLeft);
- sqlite3ExprDelete(p->pRight);
- sqlite3ExprListDelete(p->pList);
- sqlite3SelectDelete(p->pSelect);
- sqlite3_free(p);
+ sqlite3ExprClear(db, p);
+ sqlite3DbFree(db, p);
}
/*
** The Expr.token field might be a string literal that is quoted.
@@ -49940,9 +53338,8 @@
sqlite3TokenCopy(db, &p->token, &p->token);
}
sqlite3Dequote((char*)p->token.z);
}
-
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
@@ -49974,9 +53371,9 @@
pNew->pSelect = sqlite3SelectDup(db, p->pSelect);
return pNew;
}
SQLITE_PRIVATE void sqlite3TokenCopy(sqlite3 *db, Token *pTo, Token *pFrom){
- if( pTo->dyn ) sqlite3_free((char*)pTo->z);
+ if( pTo->dyn ) sqlite3DbFree(db, (char*)pTo->z);
if( pFrom->z ){
pTo->n = pFrom->n;
pTo->z = (u8*)sqlite3DbStrNDup(db, (char*)pFrom->z, pFrom->n);
pTo->dyn = 1;
@@ -49994,9 +53391,9 @@
pNew->iECursor = 0;
pNew->nExpr = pNew->nAlloc = p->nExpr;
pNew->a = pItem = sqlite3DbMallocRaw(db, p->nExpr*sizeof(p->a[0]) );
if( pItem==0 ){
- sqlite3_free(pNew);
+ sqlite3DbFree(db, pNew);
return 0;
}
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
@@ -50012,10 +53409,11 @@
|| pOldExpr->span.z==0
|| db->mallocFailed );
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->sortOrder = pOldItem->sortOrder;
- pItem->isAgg = pOldItem->isAgg;
pItem->done = 0;
+ pItem->iCol = pOldItem->iCol;
+ pItem->iAlias = pOldItem->iAlias;
}
return pNew;
}
@@ -50045,8 +53443,11 @@
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
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++;
}
@@ -50065,9 +53466,9 @@
if( pNew==0 ) return 0;
pNew->nId = pNew->nAlloc = p->nId;
pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
if( pNew->a==0 ){
- sqlite3_free(pNew);
+ sqlite3DbFree(db, pNew);
return 0;
}
for(i=0; i<p->nId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
@@ -50081,9 +53482,8 @@
Select *pNew;
if( p==0 ) return 0;
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
if( pNew==0 ) return 0;
- pNew->isDistinct = p->isDistinct;
pNew->pEList = sqlite3ExprListDup(db, p->pEList);
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc);
pNew->pWhere = sqlite3ExprDup(db, p->pWhere);
pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy);
@@ -50094,12 +53494,9 @@
pNew->pLimit = sqlite3ExprDup(db, p->pLimit);
pNew->pOffset = sqlite3ExprDup(db, p->pOffset);
pNew->iLimit = 0;
pNew->iOffset = 0;
- pNew->isResolved = p->isResolved;
- pNew->isAgg = p->isAgg;
- pNew->usesEphm = 0;
- pNew->disallowOrderBy = 0;
+ pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
pNew->pRightmost = 0;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
@@ -50146,15 +53543,16 @@
struct ExprList_item *pItem = &pList->a[pList->nExpr++];
memset(pItem, 0, sizeof(*pItem));
pItem->zName = sqlite3NameFromToken(db, pName);
pItem->pExpr = pExpr;
+ pItem->iAlias = 0;
}
return pList;
no_mem:
/* Avoid leaking memory if malloc has failed. */
- sqlite3ExprDelete(pExpr);
- sqlite3ExprListDelete(pList);
+ sqlite3ExprDelete(db, pExpr);
+ sqlite3ExprListDelete(db, pList);
return 0;
}
/*
@@ -50176,109 +53574,50 @@
/*
** Delete an entire expression list.
*/
-SQLITE_PRIVATE void sqlite3ExprListDelete(ExprList *pList){
+SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
int i;
struct ExprList_item *pItem;
if( pList==0 ) return;
assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
assert( pList->nExpr<=pList->nAlloc );
for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
- sqlite3ExprDelete(pItem->pExpr);
- sqlite3_free(pItem->zName);
- }
- sqlite3_free(pList->a);
- sqlite3_free(pList);
-}
-
-/*
-** Walk an expression tree. Call xFunc for each node visited. xFunc
-** is called on the node before xFunc is called on the nodes children.
-**
-** The return value from xFunc determines whether the tree walk continues.
-** 0 means continue walking the tree. 1 means do not walk children
-** of the current node but continue with siblings. 2 means abandon
-** the tree walk completely.
-**
-** The return value from this routine is 1 to abandon the tree walk
-** and 0 to continue.
-**
-** NOTICE: This routine does *not* descend into subqueries.
-*/
-static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
-static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
- int rc;
- if( pExpr==0 ) return 0;
- rc = (*xFunc)(pArg, pExpr);
- if( rc==0 ){
- if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1;
- if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1;
- if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1;
- }
- return rc>1;
-}
-
-/*
-** Call walkExprTree() for every expression in list p.
-*/
-static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){
- int i;
- struct ExprList_item *pItem;
- if( !p ) return 0;
- for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
- if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1;
- }
- return 0;
-}
-
-/*
-** Call walkExprTree() for every expression in Select p, not including
-** expressions that are part of sub-selects in any FROM clause or the LIMIT
-** or OFFSET expressions..
-*/
-static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
- walkExprList(p->pEList, xFunc, pArg);
- walkExprTree(p->pWhere, xFunc, pArg);
- walkExprList(p->pGroupBy, xFunc, pArg);
- walkExprTree(p->pHaving, xFunc, pArg);
- walkExprList(p->pOrderBy, xFunc, pArg);
- if( p->pPrior ){
- walkSelectExpr(p->pPrior, xFunc, pArg);
- }
- return 0;
-}
-
-
-/*
-** This routine is designed as an xFunc for walkExprTree().
-**
-** pArg is really a pointer to an integer. If we can tell by looking
-** at pExpr that the expression that contains pExpr is not a constant
-** expression, then set *pArg to 0 and return 2 to abandon the tree walk.
-** If pExpr does does not disqualify the expression from being a constant
-** then do nothing.
-**
-** After walking the whole tree, if no nodes are found that disqualify
-** the expression as constant, then we assume the whole expression
-** is constant. See sqlite3ExprIsConstant() for additional information.
-*/
-static int exprNodeIsConstant(void *pArg, Expr *pExpr){
- int *pN = (int*)pArg;
-
- /* If *pArg is 3 then any term of the expression that comes from
+ sqlite3ExprDelete(db, pItem->pExpr);
+ sqlite3DbFree(db, pItem->zName);
+ }
+ sqlite3DbFree(db, pList->a);
+ sqlite3DbFree(db, pList);
+}
+
+/*
+** These routines are Walker callbacks. Walker.u.pi is a pointer
+** to an integer. These routines are checking an expression to see
+** if it is a constant. Set *Walker.u.pi to 0 if the expression is
+** not constant.
+**
+** These callback routines are used to implement the following:
+**
+** sqlite3ExprIsConstant()
+** sqlite3ExprIsConstantNotJoin()
+** sqlite3ExprIsConstantOrFunction()
+**
+*/
+static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
+
+ /* If pWalker->u.i is 3 then any term of the expression that comes from
** the ON or USING clauses of a join disqualifies the expression
** from being considered constant. */
- if( (*pN)==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
- *pN = 0;
- return 2;
+ if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
+ pWalker->u.i = 0;
+ return WRC_Abort;
}
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
- ** and *pArg==2 */
+ ** and pWalker->u.i==2 */
case TK_FUNCTION:
- if( (*pN)==2 ) return 0;
+ if( pWalker->u.i==2 ) return 0;
/* Fall through */
case TK_ID:
case TK_COLUMN:
case TK_DOT:
@@ -50294,18 +53633,25 @@
testcase( pExpr->op==TK_COLUMN );
testcase( pExpr->op==TK_DOT );
testcase( pExpr->op==TK_AGG_FUNCTION );
testcase( pExpr->op==TK_AGG_COLUMN );
- *pN = 0;
- return 2;
- case TK_IN:
- if( pExpr->pSelect ){
- *pN = 0;
- return 2;
- }
+ pWalker->u.i = 0;
+ return WRC_Abort;
default:
- return 0;
- }
+ return WRC_Continue;
+ }
+}
+static int selectNodeIsConstant(Walker *pWalker, Select *pSelect){
+ pWalker->u.i = 0;
+ return WRC_Abort;
+}
+static int exprIsConst(Expr *p, int initFlag){
+ Walker w;
+ w.u.i = initFlag;
+ w.xExprCallback = exprNodeIsConstant;
+ w.xSelectCallback = selectNodeIsConstant;
+ sqlite3WalkExpr(&w, p);
+ return w.u.i;
}
/*
** Walk an expression tree. Return 1 if the expression is constant
@@ -50315,11 +53661,9 @@
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
- int isConst = 1;
- walkExprTree(p, exprNodeIsConstant, &isConst);
- return isConst;
+ return exprIsConst(p, 1);
}
/*
** Walk an expression tree. Return 1 if the expression is constant
@@ -50327,11 +53671,9 @@
** Return 0 if it involves variables or function calls or terms from
** an ON or USING clause.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
- int isConst = 3;
- walkExprTree(p, exprNodeIsConstant, &isConst);
- return isConst!=0;
+ return exprIsConst(p, 3);
}
/*
** Walk an expression tree. Return 1 if the expression is constant
@@ -50342,11 +53684,9 @@
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p){
- int isConst = 2;
- walkExprTree(p, exprNodeIsConstant, &isConst);
- return isConst!=0;
+ return exprIsConst(p, 2);
}
/*
** If the expression p codes a constant integer that is small enough
@@ -50396,556 +53736,8 @@
if( sqlite3StrICmp(z, "OID")==0 ) return 1;
return 0;
}
-/*
-** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-** that name in the set of source tables in pSrcList and make the pExpr
-** expression node refer back to that source column. The following changes
-** are made to pExpr:
-**
-** pExpr->iDb Set the index in db->aDb[] of the database holding
-** the table.
-** pExpr->iTable Set to the cursor number for the table obtained
-** from pSrcList.
-** pExpr->iColumn Set to the column number within the table.
-** pExpr->op Set to TK_COLUMN.
-** pExpr->pLeft Any expression this points to is deleted
-** pExpr->pRight Any expression this points to is deleted.
-**
-** The pDbToken is the name of the database (the "X"). This value may be
-** NULL meaning that name is of the form Y.Z or Z. Any available database
-** can be used. The pTableToken is the name of the table (the "Y"). This
-** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it
-** means that the form of the name is Z and that columns from any table
-** can be used.
-**
-** If the name cannot be resolved unambiguously, leave an error message
-** in pParse and return non-zero. Return zero on success.
-*/
-static int lookupName(
- Parse *pParse, /* The parsing context */
- Token *pDbToken, /* Name of the database containing table, or NULL */
- Token *pTableToken, /* Name of table containing column, or NULL */
- Token *pColumnToken, /* Name of the column. */
- NameContext *pNC, /* The name context used to resolve the name */
- Expr *pExpr /* Make this EXPR node point to the selected column */
-){
- char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
- char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
- char *zCol = 0; /* Name of the column. The "Z" */
- int i, j; /* Loop counters */
- int cnt = 0; /* Number of matching column names */
- int cntTab = 0; /* Number of matching table names */
- sqlite3 *db = pParse->db; /* The database */
- struct SrcList_item *pItem; /* Use for looping over pSrcList items */
- struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
- NameContext *pTopNC = pNC; /* First namecontext in the list */
- Schema *pSchema = 0; /* Schema of the expression */
-
- assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
- zDb = sqlite3NameFromToken(db, pDbToken);
- zTab = sqlite3NameFromToken(db, pTableToken);
- zCol = sqlite3NameFromToken(db, pColumnToken);
- if( db->mallocFailed ){
- goto lookupname_end;
- }
-
- pExpr->iTable = -1;
- while( pNC && cnt==0 ){
- ExprList *pEList;
- SrcList *pSrcList = pNC->pSrcList;
-
- if( pSrcList ){
- for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
- Table *pTab;
- int iDb;
- Column *pCol;
-
- pTab = pItem->pTab;
- assert( pTab!=0 );
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( pTab->nCol>0 );
- if( zTab ){
- if( pItem->zAlias ){
- char *zTabName = pItem->zAlias;
- if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- }else{
- char *zTabName = pTab->zName;
- if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
- continue;
- }
- }
- }
- if( 0==(cntTab++) ){
- pExpr->iTable = pItem->iCursor;
- pSchema = pTab->pSchema;
- pMatch = pItem;
- }
- for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- const char *zColl = pTab->aCol[j].zColl;
- IdList *pUsing;
- cnt++;
- pExpr->iTable = pItem->iCursor;
- pMatch = pItem;
- pSchema = pTab->pSchema;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->affinity = pTab->aCol[j].affinity;
- if( (pExpr->flags & EP_ExpCollate)==0 ){
- pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
- }
- if( i<pSrcList->nSrc-1 ){
- if( pItem[1].jointype & JT_NATURAL ){
- /* If this match occurred in the left table of a natural join,
- ** then skip the right table to avoid a duplicate match */
- pItem++;
- i++;
- }else if( (pUsing = pItem[1].pUsing)!=0 ){
- /* If this match occurs on a column that is in the USING clause
- ** of a join, skip the search of the right table of the join
- ** to avoid a duplicate match there. */
- int k;
- for(k=0; k<pUsing->nId; k++){
- if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
- pItem++;
- i++;
- break;
- }
- }
- }
- }
- break;
- }
- }
- }
- }
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* If we have not already resolved the name, then maybe
- ** it is a new.* or old.* trigger argument reference
- */
- if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
- TriggerStack *pTriggerStack = pParse->trigStack;
- Table *pTab = 0;
- u32 *piColMask;
- if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->newIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- piColMask = &(pTriggerStack->newColMask);
- }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
- pExpr->iTable = pTriggerStack->oldIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- piColMask = &(pTriggerStack->oldColMask);
- }
-
- if( pTab ){
- int iCol;
- Column *pCol = pTab->aCol;
-
- pSchema = pTab->pSchema;
- cntTab++;
- for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- const char *zColl = pTab->aCol[iCol].zColl;
- cnt++;
- pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
- pExpr->affinity = pTab->aCol[iCol].affinity;
- if( (pExpr->flags & EP_ExpCollate)==0 ){
- pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
- }
- pExpr->pTab = pTab;
- if( iCol>=0 ){
- testcase( iCol==31 );
- testcase( iCol==32 );
- *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
- }
- break;
- }
- }
- }
- }
-#endif /* !defined(SQLITE_OMIT_TRIGGER) */
-
- /*
- ** Perhaps the name is a reference to the ROWID
- */
- if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
- cnt = 1;
- pExpr->iColumn = -1;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- }
-
- /*
- ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
- ** might refer to an result-set alias. This happens, for example, when
- ** we are resolving names in the WHERE clause of the following command:
- **
- ** SELECT a+b AS x FROM table WHERE x<10;
- **
- ** In cases like this, replace pExpr with a copy of the expression that
- ** forms the result set entry ("a+b" in the example) and return immediately.
- ** Note that the expression in the result set should have already been
- ** resolved by the time the WHERE clause is resolved.
- */
- if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
- for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- Expr *pDup, *pOrig;
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- assert( pExpr->pList==0 );
- assert( pExpr->pSelect==0 );
- pOrig = pEList->a[j].pExpr;
- if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
- sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
- sqlite3_free(zCol);
- return 2;
- }
- pDup = sqlite3ExprDup(db, pOrig);
- if( pExpr->flags & EP_ExpCollate ){
- pDup->pColl = pExpr->pColl;
- pDup->flags |= EP_ExpCollate;
- }
- if( pExpr->span.dyn ) sqlite3_free((char*)pExpr->span.z);
- if( pExpr->token.dyn ) sqlite3_free((char*)pExpr->token.z);
- memcpy(pExpr, pDup, sizeof(*pExpr));
- sqlite3_free(pDup);
- cnt = 1;
- pMatch = 0;
- assert( zTab==0 && zDb==0 );
- goto lookupname_end_2;
- }
- }
- }
-
- /* Advance to the next name context. The loop will exit when either
- ** we have a match (cnt>0) or when we run out of name contexts.
- */
- if( cnt==0 ){
- pNC = pNC->pNext;
- }
- }
-
- /*
- ** If X and Y are NULL (in other words if only the column name Z is
- ** supplied) and the value of Z is enclosed in double-quotes, then
- ** Z is a string literal if it doesn't match any column names. In that
- ** case, we need to return right away and not make any changes to
- ** pExpr.
- **
- ** Because no reference was made to outer contexts, the pNC->nRef
- ** fields are not changed in any context.
- */
- if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
- sqlite3_free(zCol);
- return 0;
- }
-
- /*
- ** cnt==0 means there was not match. cnt>1 means there were two or
- ** more matches. Either way, we have an error.
- */
- if( cnt!=1 ){
- const char *zErr;
- zErr = cnt==0 ? "no such column" : "ambiguous column name";
- if( zDb ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
- }else if( zTab ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
- }else{
- sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
- }
- pTopNC->nErr++;
- }
-
- /* If a column from a table in pSrcList is referenced, then record
- ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
- ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
- ** column number is greater than the number of bits in the bitmask
- ** then set the high-order bit of the bitmask.
- */
- if( pExpr->iColumn>=0 && pMatch!=0 ){
- int n = pExpr->iColumn;
- testcase( n==sizeof(Bitmask)*8-1 );
- if( n>=sizeof(Bitmask)*8 ){
- n = sizeof(Bitmask)*8-1;
- }
- assert( pMatch->iCursor==pExpr->iTable );
- pMatch->colUsed |= ((Bitmask)1)<<n;
- }
-
-lookupname_end:
- /* Clean up and return
- */
- sqlite3_free(zDb);
- sqlite3_free(zTab);
- sqlite3ExprDelete(pExpr->pLeft);
- pExpr->pLeft = 0;
- sqlite3ExprDelete(pExpr->pRight);
- pExpr->pRight = 0;
- pExpr->op = TK_COLUMN;
-lookupname_end_2:
- sqlite3_free(zCol);
- if( cnt==1 ){
- assert( pNC!=0 );
- sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
- if( pMatch && !pMatch->pSelect ){
- pExpr->pTab = pMatch->pTab;
- }
- /* Increment the nRef value on all name contexts from TopNC up to
- ** the point where the name matched. */
- for(;;){
- assert( pTopNC!=0 );
- pTopNC->nRef++;
- if( pTopNC==pNC ) break;
- pTopNC = pTopNC->pNext;
- }
- return 0;
- } else {
- return 1;
- }
-}
-
-/*
-** This routine is designed as an xFunc for walkExprTree().
-**
-** Resolve symbolic names into TK_COLUMN operators for the current
-** node in the expression tree. Return 0 to continue the search down
-** the tree or 2 to abort the tree walk.
-**
-** This routine also does error checking and name resolution for
-** function names. The operator for aggregate functions is changed
-** to TK_AGG_FUNCTION.
-*/
-static int nameResolverStep(void *pArg, Expr *pExpr){
- NameContext *pNC = (NameContext*)pArg;
- Parse *pParse;
-
- if( pExpr==0 ) return 1;
- assert( pNC!=0 );
- pParse = pNC->pParse;
-
- if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
- ExprSetProperty(pExpr, EP_Resolved);
-#ifndef NDEBUG
- if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
- SrcList *pSrcList = pNC->pSrcList;
- int i;
- for(i=0; i<pNC->pSrcList->nSrc; i++){
- assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
- }
- }
-#endif
- switch( pExpr->op ){
- /* Double-quoted strings (ex: "abc") are used as identifiers if
- ** possible. Otherwise they remain as strings. Single-quoted
- ** strings (ex: 'abc') are always string literals.
- */
- case TK_STRING: {
- if( pExpr->token.z[0]=='\'' ) break;
- /* Fall thru into the TK_ID case if this is a double-quoted string */
- }
- /* A lone identifier is the name of a column.
- */
- case TK_ID: {
- lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
- return 1;
- }
-
- /* A table name and column name: ID.ID
- ** Or a database, table and column: ID.ID.ID
- */
- case TK_DOT: {
- Token *pColumn;
- Token *pTable;
- Token *pDb;
- Expr *pRight;
-
- /* if( pSrcList==0 ) break; */
- pRight = pExpr->pRight;
- if( pRight->op==TK_ID ){
- pDb = 0;
- pTable = &pExpr->pLeft->token;
- pColumn = &pRight->token;
- }else{
- assert( pRight->op==TK_DOT );
- pDb = &pExpr->pLeft->token;
- pTable = &pRight->pLeft->token;
- pColumn = &pRight->pRight->token;
- }
- lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
- return 1;
- }
-
- /* Resolve function names
- */
- case TK_CONST_FUNC:
- case TK_FUNCTION: {
- ExprList *pList = pExpr->pList; /* The argument list */
- int n = pList ? pList->nExpr : 0; /* Number of arguments */
- int no_such_func = 0; /* True if no such function exists */
- int wrong_num_args = 0; /* True if wrong number of arguments */
- int is_agg = 0; /* True if is an aggregate function */
- int i;
- int auth; /* Authorization to use the function */
- int nId; /* Number of characters in function name */
- const char *zId; /* The function name. */
- FuncDef *pDef; /* Information about the function */
- int enc = ENC(pParse->db); /* The database encoding */
-
- zId = (char*)pExpr->token.z;
- nId = pExpr->token.n;
- pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
- if( pDef==0 ){
- pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
- if( pDef==0 ){
- no_such_func = 1;
- }else{
- wrong_num_args = 1;
- }
- }else{
- is_agg = pDef->xFunc==0;
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( pDef ){
- auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
- if( auth!=SQLITE_OK ){
- if( auth==SQLITE_DENY ){
- sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
- pDef->zName);
- pNC->nErr++;
- }
- pExpr->op = TK_NULL;
- return 1;
- }
- }
-#endif
- if( is_agg && !pNC->allowAgg ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
- pNC->nErr++;
- is_agg = 0;
- }else if( no_such_func ){
- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- pNC->nErr++;
- }else if( wrong_num_args ){
- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- pNC->nErr++;
- }
- if( is_agg ){
- pExpr->op = TK_AGG_FUNCTION;
- pNC->hasAgg = 1;
- }
- if( is_agg ) pNC->allowAgg = 0;
- for(i=0; pNC->nErr==0 && i<n; i++){
- walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
- }
- if( is_agg ) pNC->allowAgg = 1;
- /* FIX ME: Compute pExpr->affinity based on the expected return
- ** type of the function
- */
- return is_agg;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_SELECT:
- case TK_EXISTS:
-#endif
- case TK_IN: {
- if( pExpr->pSelect ){
- int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
- if( pNC->isCheck ){
- sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
- }
-#endif
- sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
- assert( pNC->nRef>=nRef );
- if( nRef!=pNC->nRef ){
- ExprSetProperty(pExpr, EP_VarSelect);
- }
- }
- break;
- }
-#ifndef SQLITE_OMIT_CHECK
- case TK_VARIABLE: {
- if( pNC->isCheck ){
- sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
- }
- break;
- }
-#endif
- }
- return 0;
-}
-
-/*
-** This routine walks an expression tree and resolves references to
-** table columns. Nodes of the form ID.ID or ID resolve into an
-** index to the table in the table list and a column offset. The
-** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
-** value is changed to the index of the referenced table in pTabList
-** plus the "base" value. The base value will ultimately become the
-** VDBE cursor number for a cursor that is pointing into the referenced
-** table. The Expr.iColumn value is changed to the index of the column
-** of the referenced table. The Expr.iColumn value for the special
-** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
-** alias for ROWID.
-**
-** Also resolve function names and check the functions for proper
-** usage. Make sure all function names are recognized and all functions
-** have the correct number of arguments. Leave an error message
-** in pParse->zErrMsg if anything is amiss. Return the number of errors.
-**
-** If the expression contains aggregate functions then set the EP_Agg
-** property on the expression.
-*/
-SQLITE_PRIVATE int sqlite3ExprResolveNames(
- NameContext *pNC, /* Namespace to resolve expressions in. */
- Expr *pExpr /* The expression to be analyzed. */
-){
- int savedHasAgg;
-
- if( pExpr==0 ) return 0;
-#if SQLITE_MAX_EXPR_DEPTH>0
- {
- if( checkExprHeight(pNC->pParse, pExpr->nHeight + pNC->pParse->nHeight) ){
- return 1;
- }
- pNC->pParse->nHeight += pExpr->nHeight;
- }
-#endif
- savedHasAgg = pNC->hasAgg;
- pNC->hasAgg = 0;
- walkExprTree(pExpr, nameResolverStep, pNC);
-#if SQLITE_MAX_EXPR_DEPTH>0
- pNC->pParse->nHeight -= pExpr->nHeight;
-#endif
- if( pNC->nErr>0 ){
- ExprSetProperty(pExpr, EP_Error);
- }
- if( pNC->hasAgg ){
- ExprSetProperty(pExpr, EP_Agg);
- }else if( savedHasAgg ){
- pNC->hasAgg = 1;
- }
- return ExprHasProperty(pExpr, EP_Error);
-}
-
-/*
-** A pointer instance of this structure is used to pass information
-** through walkExprTree into codeSubqueryStep().
-*/
-typedef struct QueryCoder QueryCoder;
-struct QueryCoder {
- Parse *pParse; /* The parsing context */
- NameContext *pNC; /* Namespace of first enclosing query */
-};
-
#ifdef SQLITE_TEST
int sqlite3_enable_in_opt = 1;
#else
#define sqlite3_enable_in_opt 1
@@ -50968,10 +53760,11 @@
Table *pTab;
if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */
if( p==0 ) return 0; /* right-hand side of IN is SELECT */
if( p->pPrior ) return 0; /* Not a compound SELECT */
- if( p->isDistinct ) return 0; /* No DISTINCT keyword */
- if( p->isAgg ) return 0; /* Contains no aggregate functions */
+ if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
+ return 0; /* No DISTINCT keyword and no aggregate functions */
+ }
if( p->pGroupBy ) return 0; /* Has no GROUP BY clause */
if( p->pLimit ) return 0; /* Has no LIMIT clause */
if( p->pOffset ) return 0;
if( p->pWhere ) return 0; /* Has no WHERE clause */
@@ -51134,13 +53927,15 @@
}
if( eType==0 ){
int rMayHaveNull = 0;
+ eType = IN_INDEX_EPH;
if( prNotFound ){
*prNotFound = rMayHaveNull = ++pParse->nMem;
- }
- sqlite3CodeSubselect(pParse, pX, rMayHaveNull);
- eType = IN_INDEX_EPH;
+ }else if( pX->pLeft->iColumn<0 && pX->pSelect==0 ){
+ eType = IN_INDEX_ROWID;
+ }
+ sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
}else{
pX->iTable = iTab;
}
return eType;
@@ -51157,11 +53952,22 @@
** x IN (SELECT a FROM b) -- IN operator with subquery on the right
**
** 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;
@@ -51187,14 +53993,15 @@
case TK_IN: {
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
** filled with single-field index keys representing the results
@@ -51208,9 +54015,9 @@
** 'x' nor the SELECT... statement are columns, then numeric affinity
** 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;
if( pExpr->pSelect ){
@@ -51221,12 +54028,13 @@
*/
SelectDest dest;
ExprList *pEList;
+ assert( !isRowid );
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.affinity = (int)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
- if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0) ){
+ if( sqlite3Select(pParse, pExpr->pSelect, &dest) ){
return;
}
pEList = pExpr->pSelect->pEList;
if( pEList && pEList->nExpr>0 ){
@@ -51248,13 +54056,14 @@
if( !affinity ){
affinity = SQLITE_AFF_NONE;
}
- keyInfo.aColl[0] = pExpr->pLeft->pColl;
+ keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
/* 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;
/* If the expression is not constant then we will need to
@@ -51271,16 +54080,24 @@
pParse->disableColCache++;
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;
}
case TK_EXISTS:
@@ -51303,11 +54120,11 @@
dest.eDest = SRT_Exists;
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm);
VdbeComment((v, "Init EXISTS result"));
}
- sqlite3ExprDelete(pSel->pLimit);
+ sqlite3ExprDelete(pParse->db, pSel->pLimit);
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
- if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0) ){
+ if( sqlite3Select(pParse, pSel, &dest) ){
return;
}
pExpr->iColumn = dest.iParm;
break;
@@ -51587,13 +54404,52 @@
}
}
/*
+** Generate code to store the value of the iAlias-th alias in register
+** target. The first time this is called, pExpr is evaluated to compute
+** the value of the alias. The value is stored in an auxiliary register
+** and the number of that register is returned. On subsequent calls,
+** the register number is returned without generating any code.
+**
+** Note that in order for this to work, code must be generated in the
+** same order that it is executed.
+**
+** Aliases are numbered starting with 1. So iAlias is in the range
+** of 1 to pParse->nAlias inclusive.
+**
+** pParse->aAlias[iAlias-1] records the register number where the value
+** of the iAlias-th alias is stored. If zero, that means that the
+** alias has not yet been computed.
+*/
+static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){
+ sqlite3 *db = pParse->db;
+ int iReg;
+ if( pParse->aAlias==0 ){
+ pParse->aAlias = sqlite3DbMallocZero(db,
+ sizeof(pParse->aAlias[0])*pParse->nAlias );
+ if( db->mallocFailed ) return 0;
+ }
+ assert( iAlias>0 && iAlias<=pParse->nAlias );
+ iReg = pParse->aAlias[iAlias-1];
+ if( iReg==0 ){
+ if( pParse->disableColCache ){
+ iReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
+ }else{
+ iReg = ++pParse->nMem;
+ sqlite3ExprCode(pParse, pExpr, iReg);
+ pParse->aAlias[iAlias-1] = iReg;
+ }
+ }
+ return iReg;
+}
+
+/*
** Generate code into the current Vdbe to evaluate the given
** expression. Attempt to store the results in register "target".
** Return the register where results are stored.
**
-** With this routine, there is no guaranteed that results will
+** With this routine, there is no guarantee that results will
** be stored in target. The result might be stored in some other
** register if it is convenient to do so. The calling function
** must check the return code and move the results to the desired
** register.
@@ -51604,10 +54460,12 @@
int inReg = target; /* Results stored in register inReg */
int regFree1 = 0; /* If non-zero free this temporary register */
int regFree2 = 0; /* If non-zero free this temporary register */
int r1, r2, r3, r4; /* Various register numbers */
-
- assert( v!=0 || pParse->db->mallocFailed );
+ sqlite3 *db;
+
+ db = pParse->db;
+ assert( v!=0 || db->mallocFailed );
assert( target>0 && target<=pParse->nMem );
if( v==0 ) return 0;
if( pExpr==0 ){
@@ -51651,9 +54509,9 @@
codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0, target);
break;
}
case TK_STRING: {
- sqlite3DequoteExpr(pParse->db, pExpr);
+ sqlite3DequoteExpr(db, pExpr);
sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0,
(char*)pExpr->token.z, pExpr->token.n);
break;
}
@@ -51685,8 +54543,12 @@
break;
}
case TK_REGISTER: {
inReg = pExpr->iTable;
+ break;
+ }
+ case TK_AS: {
+ inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft, target);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
@@ -51843,17 +54705,16 @@
int nId;
const char *zId;
int constMask = 0;
int i;
- sqlite3 *db = pParse->db;
u8 enc = ENC(db);
CollSeq *pColl = 0;
testcase( op==TK_CONST_FUNC );
testcase( op==TK_FUNCTION );
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
- pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
+ pDef = sqlite3FindFunction(db, zId, nId, nExpr, enc, 0);
assert( pDef!=0 );
if( pList ){
nExpr = pList->nExpr;
r1 = sqlite3GetTempRange(pParse, nExpr);
@@ -51883,14 +54744,14 @@
for(i=0; i<nExpr && i<32; i++){
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( !pColl ) pColl = pParse->db->pDfltColl;
+ if( pDef->flags & SQLITE_FUNC_NEEDCOLL ){
+ if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
(char*)pDef, P4_FUNCDEF);
@@ -51906,9 +54767,9 @@
case TK_SELECT: {
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;
}
@@ -51989,9 +54850,9 @@
sqlite3VdbeJumpHere(v, j4);
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);
}
@@ -52087,9 +54948,8 @@
testcase( pX->op==TK_COLUMN || pX->op==TK_REGISTER );
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1);
testcase( regFree1==0 );
cacheX.op = TK_REGISTER;
- cacheX.iColumn = 0;
opCompare.op = TK_EQ;
opCompare.pLeft = &cacheX;
pTest = &opCompare;
}
@@ -52129,9 +54989,9 @@
if( pExpr->iColumn!=OE_Ignore ){
assert( pExpr->iColumn==OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail );
- sqlite3DequoteExpr(pParse->db, pExpr);
+ sqlite3DequoteExpr(db, pExpr);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, 0,
(char*)pExpr->token.z, pExpr->token.n);
} else {
assert( pExpr->iColumn == OE_Ignore );
@@ -52207,9 +55067,8 @@
int iMem;
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
pExpr->iTable = iMem;
- pExpr->iColumn = pExpr->op;
pExpr->op = TK_REGISTER;
}
return inReg;
}
@@ -52278,10 +55137,10 @@
** factoring out of a loop, then evaluate the expression
** into a register and convert the expression into a TK_REGISTER
** expression.
*/
-static int evalConstExpr(void *pArg, Expr *pExpr){
- Parse *pParse = (Parse*)pArg;
+static int evalConstExpr(Walker *pWalker, Expr *pExpr){
+ Parse *pParse = pWalker->pParse;
switch( pExpr->op ){
case TK_REGISTER: {
return 1;
}
@@ -52307,14 +55166,13 @@
int r1 = ++pParse->nMem;
int r2;
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
- pExpr->iColumn = pExpr->op;
pExpr->op = TK_REGISTER;
pExpr->iTable = r2;
- return 1;
- }
- return 0;
+ return WRC_Prune;
+ }
+ return WRC_Continue;
}
/*
** Preevaluate constant subexpressions within pExpr and store the
@@ -52321,9 +55179,13 @@
** results in registers. Modify pExpr so that the constant subexpresions
** are TK_REGISTER opcodes that refer to the precomputed values.
*/
SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
- walkExprTree(pExpr, evalConstExpr, pParse);
+ Walker w;
+ w.xExprCallback = evalConstExpr;
+ w.xSelectCallback = 0;
+ w.pParse = pParse;
+ sqlite3WalkExpr(&w, pExpr);
}
/*
@@ -52335,21 +55197,28 @@
SQLITE_PRIVATE int sqlite3ExprCodeExprList(
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;
- assert( pList!=0 || pParse->db->mallocFailed );
- if( pList==0 ){
- return 0;
- }
+ assert( pList!=0 );
assert( target>0 );
n = pList->nExpr;
for(pItem=pList->a, i=0; i<n; i++, pItem++){
- sqlite3ExprCode(pParse, pItem->pExpr, target+i);
- if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n);
+ if( pItem->iAlias ){
+ int iReg = codeAlias(pParse, pItem->iAlias, pItem->pExpr, target+i);
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ if( iReg!=target+i ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i);
+ }
+ }else{
+ sqlite3ExprCode(pParse, pItem->pExpr, target+i);
+ }
+ if( doHardCopy ){
+ sqlite3ExprHardCopy(pParse, target, n);
+ }
}
return n;
}
@@ -52721,24 +55590,24 @@
return i;
}
/*
-** This is an xFunc for walkExprTree() used to implement
-** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
+** This is the xExprCallback for a tree walker. It is used to
+** implement sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
** for additional information.
-**
-** This routine analyzes the aggregate function at pExpr.
-*/
-static int analyzeAggregate(void *pArg, Expr *pExpr){
- int i;
- NameContext *pNC = (NameContext *)pArg;
+*/
+static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
+ int i;
+ NameContext *pNC = pWalker->u.pNC;
Parse *pParse = pNC->pParse;
SrcList *pSrcList = pNC->pSrcList;
AggInfo *pAggInfo = pNC->pAggInfo;
switch( pExpr->op ){
case TK_AGG_COLUMN:
case TK_COLUMN: {
+ testcase( pExpr->op==TK_AGG_COLUMN );
+ testcase( pExpr->op==TK_COLUMN );
/* Check to see if the column is in one of the tables in the FROM
** clause of the aggregate query */
if( pSrcList ){
struct SrcList_item *pItem = pSrcList->a;
@@ -52798,9 +55667,9 @@
break;
} /* endif pExpr->iTable==pItem->iCursor */
} /* end loop over pSrcList */
}
- return 1;
+ return WRC_Prune;
}
case TK_AGG_FUNCTION: {
/* The pNC->nDepth==0 test causes aggregate functions in subqueries
** to be ignored */
@@ -52836,23 +55705,24 @@
/* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
*/
pExpr->iAgg = i;
pExpr->pAggInfo = pAggInfo;
- return 1;
- }
- }
- }
-
- /* Recursively walk subqueries looking for TK_COLUMN nodes that need
- ** to be changed to TK_AGG_COLUMN. But increment nDepth so that
- ** TK_AGG_FUNCTION nodes in subqueries will be unchanged.
- */
- if( pExpr->pSelect ){
+ return WRC_Prune;
+ }
+ }
+ }
+ return WRC_Continue;
+}
+static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
+ NameContext *pNC = pWalker->u.pNC;
+ if( pNC->nDepth==0 ){
pNC->nDepth++;
- walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
+ sqlite3WalkSelect(pWalker, pSelect);
pNC->nDepth--;
- }
- return 0;
+ return WRC_Prune;
+ }else{
+ return WRC_Continue;
+ }
}
/*
** Analyze the given expression looking for aggregate functions and
@@ -52859,12 +55729,16 @@
** for variables that need to be added to the pParse->aAgg[] array.
** Make additional entries to the pParse->aAgg[] array as necessary.
**
** This routine should only be called after the expression has been
-** analyzed by sqlite3ExprResolveNames().
+** analyzed by sqlite3ResolveExprNames().
*/
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
- walkExprTree(pExpr, analyzeAggregate, pNC);
+ Walker w;
+ w.xExprCallback = analyzeAggregate;
+ w.xSelectCallback = analyzeAggregatesInSelect;
+ w.u.pNC = pNC;
+ sqlite3WalkExpr(&w, pExpr);
}
/*
** Call sqlite3ExprAnalyzeAggregates() for every expression in an
@@ -52936,9 +55810,9 @@
*************************************************************************
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
-** $Id: alter.c,v 1.46 2008/07/15 14:47:19 drh Exp $
+** $Id: alter.c,v 1.49 2008/10/30 17:21:13 danielk1977 Exp $
*/
/*
** The code in this file only exists if we are not omitting the
@@ -52996,15 +55870,15 @@
*/
do {
zCsr += len;
len = sqlite3GetToken(zCsr, &token);
- } while( token==TK_SPACE || token==TK_COMMENT );
+ } while( token==TK_SPACE );
assert( len>0 );
} while( token!=TK_LP && token!=TK_USING );
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, sqlite3_free);
+ sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
}
}
#ifndef SQLITE_OMIT_TRIGGER
@@ -53077,9 +55951,9 @@
** in the CREATE TRIGGER statement.
*/
zRet = sqlite3MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, sqlite3_free);
+ sqlite3_result_text(context, zRet, -1, SQLITE_DYNAMIC);
}
}
#endif /* !SQLITE_OMIT_TRIGGER */
@@ -53120,9 +55994,9 @@
zWhere = sqlite3MPrintf(db, "name=%Q", pTrig->name);
}else{
tmp = zWhere;
zWhere = sqlite3MPrintf(db, "%s OR name=%Q", zWhere, pTrig->name);
- sqlite3_free(tmp);
+ sqlite3DbFree(db, tmp);
}
}
}
}
@@ -53331,18 +56205,18 @@
"UPDATE sqlite_temp_master SET "
"sql = sqlite_rename_trigger(sql, %Q), "
"tbl_name = %Q "
"WHERE %s;", zName, zName, zWhere);
- sqlite3_free(zWhere);
+ sqlite3DbFree(db, zWhere);
}
#endif
/* Drop and reload the internal table schema. */
reloadTableSchema(pParse, pTab, zName);
exit_rename_table:
- sqlite3SrcListDelete(pSrc);
- sqlite3_free(zName);
+ sqlite3SrcListDelete(db, pSrc);
+ sqlite3DbFree(db, zName);
}
/*
@@ -53363,13 +56237,13 @@
Column *pCol; /* The new column */
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;
zTab = pNew->zName;
@@ -53440,9 +56314,9 @@
"WHERE type = 'table' AND name = %Q",
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
- sqlite3_free(zCol);
+ sqlite3DbFree(db, zCol);
}
/* If the default value of the new column is NULL, then set the file
** format to 2. If the default value of the new column is not NULL,
@@ -53507,8 +56381,9 @@
pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table));
if( !pNew ) goto exit_begin_add_column;
pParse->pNewTable = pNew;
pNew->nRef = 1;
+ pNew->db = db;
pNew->nCol = pTab->nCol;
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
@@ -53536,9 +56411,9 @@
if( !v ) goto exit_begin_add_column;
sqlite3ChangeCookie(pParse, iDb);
exit_begin_add_column:
- sqlite3SrcListDelete(pSrc);
+ sqlite3SrcListDelete(db, pSrc);
return;
}
#endif /* SQLITE_ALTER_TABLE */
@@ -53556,9 +56431,9 @@
**
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
-** @(#) $Id: analyze.c,v 1.42 2008/03/25 09:47:35 danielk1977 Exp $
+** @(#) $Id: analyze.c,v 1.43 2008/07/28 19:34:53 drh Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
/*
@@ -53860,9 +56735,9 @@
}else{
z = sqlite3NameFromToken(db, pName1);
if( z ){
pTab = sqlite3LocateTable(pParse, 0, z, 0);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
if( pTab ){
analyzeTable(pParse, pTab);
}
}
@@ -53874,9 +56749,9 @@
zDb = db->aDb[iDb].zName;
z = sqlite3NameFromToken(db, pTableName);
if( z ){
pTab = sqlite3LocateTable(pParse, 0, z, zDb);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
if( pTab ){
analyzeTable(pParse, pTab);
}
}
@@ -53961,9 +56836,9 @@
sInfo.zDatabase);
(void)sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
(void)sqlite3SafetyOn(db);
- sqlite3_free(zSql);
+ sqlite3DbFree(db, zSql);
return rc;
}
@@ -53983,9 +56858,9 @@
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
-** $Id: attach.c,v 1.76 2008/06/15 02:51:47 drh Exp $
+** $Id: attach.c,v 1.79 2008/10/28 17:52:39 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_ATTACH
/*
@@ -54010,9 +56885,9 @@
{
int rc = SQLITE_OK;
if( pExpr ){
if( pExpr->op!=TK_ID ){
- rc = sqlite3ExprResolveNames(pName, pExpr);
+ rc = sqlite3ResolveExprNames(pName, pExpr);
if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span);
return SQLITE_ERROR;
}
@@ -54185,9 +57060,9 @@
attach_error:
/* Return an error if we get here */
if( zErrDyn ){
sqlite3_result_error(context, zErrDyn, -1);
- sqlite3_free(zErrDyn);
+ sqlite3DbFree(db, zErrDyn);
}else{
zErr[sizeof(zErr)-1] = 0;
sqlite3_result_error(context, zErr, -1);
}
@@ -54254,10 +57129,9 @@
*/
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 */
Expr *pKey /* Database key for encryption extension */
@@ -54264,9 +57138,8 @@
){
int rc;
NameContext sName;
Vdbe *v;
- FuncDef *pFunc;
sqlite3* db = pParse->db;
int regArgs;
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -54276,9 +57149,9 @@
if( !zAuthArg ){
goto attach_end;
}
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
- sqlite3_free(zAuthArg);
+ sqlite3DbFree(db, zAuthArg);
if(rc!=SQLITE_OK ){
goto attach_end;
}
}
@@ -54303,11 +57176,10 @@
sqlite3ExprCode(pParse, pKey, regArgs+2);
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
** statement only). For DETACH, set it to false (expire all existing
@@ -54316,11 +57188,11 @@
sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH));
}
attach_end:
- sqlite3ExprDelete(pFilename);
- sqlite3ExprDelete(pDbname);
- sqlite3ExprDelete(pKey);
+ sqlite3ExprDelete(db, pFilename);
+ sqlite3ExprDelete(db, pDbname);
+ sqlite3ExprDelete(db, pKey);
}
/*
** Called by the parser to compile a DETACH statement.
@@ -54327,9 +57199,21 @@
**
** 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);
}
/*
** Called by the parser to compile an ATTACH statement.
@@ -54336,22 +57220,23 @@
**
** 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);
-}
-#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
-}
+ 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 */
/*
** Initialize a DbFixer structure. This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
@@ -54756,9 +57641,9 @@
** BEGIN TRANSACTION
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.490 2008/07/08 23:40:20 drh Exp $
+** $Id: build.c,v 1.499 2008/10/22 10:45:38 danielk1977 Exp $
*/
/*
** This routine is called when a new SQL statement is beginning to
@@ -54869,14 +57754,8 @@
db = pParse->db;
if( db->mallocFailed ) return;
if( pParse->nested ) return;
if( pParse->nErr ) return;
- if( !pParse->pVdbe ){
- if( pParse->rc==SQLITE_OK && pParse->nErr ){
- pParse->rc = SQLITE_ERROR;
- return;
- }
- }
/* Begin by generating some termination code at the end of the
** vdbe program
*/
@@ -54971,26 +57850,26 @@
SQLITE_PRIVATE void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
va_list ap;
char *zSql;
char *zErrMsg = 0;
+ sqlite3 *db = pParse->db;
# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
char saveBuf[SAVE_SZ];
if( pParse->nErr ) return;
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
va_start(ap, zFormat);
- zSql = sqlite3VMPrintf(pParse->db, zFormat, ap);
+ zSql = sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
if( zSql==0 ){
- pParse->db->mallocFailed = 1;
return; /* A malloc must have failed */
}
pParse->nested++;
memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
memset(&pParse->nVar, 0, SAVE_SZ);
sqlite3RunParser(pParse, zSql, &zErrMsg);
- sqlite3_free(zErrMsg);
- sqlite3_free(zSql);
+ sqlite3DbFree(db, zErrMsg);
+ sqlite3DbFree(db, zSql);
memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
pParse->nested--;
}
@@ -55090,10 +57969,11 @@
/*
** Reclaim the memory used by an index
*/
static void freeIndex(Index *p){
- sqlite3_free(p->zColAff);
- sqlite3_free(p);
+ sqlite3 *db = p->pTable->db;
+ sqlite3DbFree(db, p->zColAff);
+ sqlite3DbFree(db, p);
}
/*
** Remove the given index from the index hash table, and free
@@ -55185,9 +58065,9 @@
}
for(i=j=2; i<db->nDb; i++){
struct Db *pDb = &db->aDb[i];
if( pDb->pBt==0 ){
- sqlite3_free(pDb->zName);
+ sqlite3DbFree(db, pDb->zName);
pDb->zName = 0;
continue;
}
if( j<i ){
@@ -55198,9 +58078,9 @@
memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
db->nDb = j;
if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
- sqlite3_free(db->aDb);
+ sqlite3DbFree(db, db->aDb);
db->aDb = db->aDbStatic;
}
}
@@ -55216,17 +58096,18 @@
*/
static void sqliteResetColumnNames(Table *pTable){
int i;
Column *pCol;
+ sqlite3 *db = pTable->db;
assert( pTable!=0 );
if( (pCol = pTable->aCol)!=0 ){
for(i=0; i<pTable->nCol; i++, pCol++){
- sqlite3_free(pCol->zName);
- sqlite3ExprDelete(pCol->pDflt);
- sqlite3_free(pCol->zType);
- sqlite3_free(pCol->zColl);
- }
- sqlite3_free(pTable->aCol);
+ sqlite3DbFree(db, pCol->zName);
+ sqlite3ExprDelete(db, pCol->pDflt);
+ sqlite3DbFree(db, pCol->zType);
+ sqlite3DbFree(db, pCol->zColl);
+ }
+ sqlite3DbFree(db, pTable->aCol);
}
pTable->aCol = 0;
pTable->nCol = 0;
}
@@ -55243,10 +58124,12 @@
*/
SQLITE_PRIVATE void sqlite3DeleteTable(Table *pTable){
Index *pIndex, *pNext;
FKey *pFKey, *pNextFKey;
+ sqlite3 *db;
if( pTable==0 ) return;
+ db = pTable->db;
/* Do not delete the table until the reference count reaches zero. */
pTable->nRef--;
if( pTable->nRef>0 ){
@@ -55269,23 +58152,23 @@
for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
pNextFKey = pFKey->pNextFrom;
assert( sqlite3HashFind(&pTable->pSchema->aFKey,
pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
- sqlite3_free(pFKey);
+ sqlite3DbFree(db, pFKey);
}
#endif
/* Delete the Table structure itself.
*/
sqliteResetColumnNames(pTable);
- sqlite3_free(pTable->zName);
- sqlite3_free(pTable->zColAff);
- sqlite3SelectDelete(pTable->pSelect);
+ sqlite3DbFree(db, pTable->zName);
+ sqlite3DbFree(db, pTable->zColAff);
+ sqlite3SelectDelete(db, pTable->pSelect);
#ifndef SQLITE_OMIT_CHECK
- sqlite3ExprDelete(pTable->pCheck);
+ sqlite3ExprDelete(db, pTable->pCheck);
#endif
sqlite3VtabClear(pTable);
- sqlite3_free(pTable);
+ sqlite3DbFree(db, pTable);
}
/*
** Unlink the given table from the hash tables and the delete the
@@ -55373,9 +58256,9 @@
0==sqlite3StrICmp(pDb->zName, zName) ){
break;
}
}
- sqlite3_free(zName);
+ sqlite3DbFree(db, zName);
}
return i;
}
@@ -55564,8 +58447,9 @@
pTable->zName = zName;
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
+ pTable->db = db;
if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable);
pParse->pNewTable = pTable;
/* If this is the magic sqlite_sequence table used by autoincrement,
@@ -55643,9 +58527,9 @@
return;
/* If an error occurs, we jump here */
begin_table_error:
- sqlite3_free(zName);
+ sqlite3DbFree(db, zName);
return;
}
/*
@@ -55686,17 +58570,17 @@
if( z==0 ) return;
for(i=0; i<p->nCol; i++){
if( STRICMP(z, p->aCol[i].zName) ){
sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
return;
}
}
if( (p->nCol & 0x7)==0 ){
Column *aNew;
aNew = sqlite3DbRealloc(pParse->db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
if( aNew==0 ){
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
return;
}
p->aCol = aNew;
}
@@ -55801,15 +58685,17 @@
SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){
Table *p;
int i;
Column *pCol;
+ sqlite3 *db;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
if( i<0 ) return;
pCol = &p->aCol[i];
- sqlite3_free(pCol->zType);
- pCol->zType = sqlite3NameFromToken(pParse->db, pType);
+ db = pParse->db;
+ sqlite3DbFree(db, pCol->zType);
+ pCol->zType = sqlite3NameFromToken(db, pType);
pCol->affinity = sqlite3AffinityType(pType);
}
/*
@@ -55824,24 +58710,24 @@
*/
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
Table *p;
Column *pCol;
+ sqlite3 *db = pParse->db;
if( (p = pParse->pNewTable)!=0 ){
pCol = &(p->aCol[p->nCol-1]);
if( !sqlite3ExprIsConstantOrFunction(pExpr) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
}else{
Expr *pCopy;
- sqlite3 *db = pParse->db;
- sqlite3ExprDelete(pCol->pDflt);
+ sqlite3ExprDelete(db, pCol->pDflt);
pCol->pDflt = pCopy = sqlite3ExprDup(db, pExpr);
if( pCopy ){
sqlite3TokenCopy(db, &pCopy->span, &pExpr->span);
}
}
}
- sqlite3ExprDelete(pExpr);
+ sqlite3ExprDelete(db, pExpr);
}
/*
** Designate the PRIMARY KEY for the table. pList is a list of names
@@ -55871,14 +58757,14 @@
Table *pTab = pParse->pNewTable;
char *zType = 0;
int iCol = -1, i;
if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
- if( pTab->hasPrimKey ){
+ if( pTab->tabFlags & TF_HasPrimaryKey ){
sqlite3ErrorMsg(pParse,
"table \"%s\" has more than one primary key", pTab->zName);
goto primary_key_exit;
}
- pTab->hasPrimKey = 1;
+ pTab->tabFlags |= TF_HasPrimaryKey;
if( pList==0 ){
iCol = pTab->nCol - 1;
pTab->aCol[iCol].isPrimKey = 1;
}else{
@@ -55900,9 +58786,10 @@
if( zType && sqlite3StrICmp(zType, "INTEGER")==0
&& sortOrder==SQLITE_SO_ASC ){
pTab->iPKey = iCol;
pTab->keyConf = onError;
- pTab->autoInc = autoInc;
+ assert( autoInc==0 || autoInc==1 );
+ pTab->tabFlags |= autoInc*TF_Autoincrement;
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
"INTEGER PRIMARY KEY");
@@ -55912,9 +58799,9 @@
pList = 0;
}
primary_key_exit:
- sqlite3ExprListDelete(pList);
+ sqlite3ExprListDelete(pParse->db, pList);
return;
}
/*
@@ -55923,11 +58810,11 @@
SQLITE_PRIVATE void sqlite3AddCheckConstraint(
Parse *pParse, /* Parsing context */
Expr *pCheckExpr /* The check expression */
){
+ sqlite3 *db = pParse->db;
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
- sqlite3 *db = pParse->db;
if( pTab && !IN_DECLARE_VTAB ){
/* The CHECK expression must be duplicated so that tokens refer
** to malloced space and not the (ephemeral) text of the CREATE TABLE
** statement */
@@ -55934,9 +58821,9 @@
pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck,
sqlite3ExprDup(db, pCheckExpr));
}
#endif
- sqlite3ExprDelete(pCheckExpr);
+ sqlite3ExprDelete(db, pCheckExpr);
}
/*
** Set the collation function of the most recently parsed table column
@@ -55945,13 +58832,14 @@
SQLITE_PRIVATE void sqlite3AddCollateType(Parse *pParse, Token *pToken){
Table *p;
int i;
char *zColl; /* Dequoted name of collation sequence */
+ sqlite3 *db;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
-
- zColl = sqlite3NameFromToken(pParse->db, pToken);
+ db = pParse->db;
+ zColl = sqlite3NameFromToken(db, pToken);
if( !zColl ) return;
if( sqlite3LocateCollSeq(pParse, zColl, -1) ){
Index *pIdx;
@@ -55967,9 +58855,9 @@
pIdx->azColl[0] = p->aCol[i].zColl;
}
}
}else{
- sqlite3_free(zColl);
+ sqlite3DbFree(db, zColl);
}
}
/*
@@ -56186,9 +59074,9 @@
sSrc.a[0].iCursor = -1;
sNC.pParse = pParse;
sNC.pSrcList = &sSrc;
sNC.isCheck = 1;
- if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){
+ if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
return;
}
}
#endif /* !defined(SQLITE_OMIT_CHECK) */
@@ -56254,16 +59142,17 @@
if( pSelect ){
SelectDest dest;
Table *pSelTab;
+ assert(pParse->nTab==0);
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
sqlite3VdbeChangeP5(v, 1);
pParse->nTab = 2;
sqlite3SelectDestInit(&dest, SRT_Table, 1);
- sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+ sqlite3Select(pParse, pSelect, &dest);
sqlite3VdbeAddOp1(v, OP_Close, 1);
if( pParse->nErr==0 ){
- pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
if( pSelTab==0 ) return;
assert( p->aCol==0 );
p->nCol = pSelTab->nCol;
p->aCol = pSelTab->aCol;
@@ -56300,16 +59189,16 @@
pParse->regRoot,
zStmt,
pParse->regRowid
);
- sqlite3_free(zStmt);
+ sqlite3DbFree(db, zStmt);
sqlite3ChangeCookie(pParse, iDb);
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
- if( p->autoInc ){
+ if( p->tabFlags & TF_Autoincrement ){
Db *pDb = &db->aDb[iDb];
if( pDb->pSchema->pSeqTab==0 ){
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.sqlite_sequence(name,seq)",
@@ -56390,23 +59279,23 @@
sqlite3 *db = pParse->db;
if( pParse->nVar>0 ){
sqlite3ErrorMsg(pParse, "parameters are not allowed in views");
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
return;
}
sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ){
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
return;
}
sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlite3SchemaToIndex(db, p->pSchema);
if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)
&& sqlite3FixSelect(&sFix, pSelect)
){
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
return;
}
/* Make a copy of the entire SELECT statement that defines the view.
@@ -56414,9 +59303,9 @@
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite3_exec() call returns.
*/
p->pSelect = sqlite3SelectDup(db, pSelect);
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
if( db->mallocFailed ){
return;
}
if( !db->init.busy ){
@@ -56503,12 +59392,12 @@
pTable->nCol = -1;
#ifndef SQLITE_OMIT_AUTHORIZATION
xAuth = db->xAuth;
db->xAuth = 0;
- pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
db->xAuth = xAuth;
#else
- pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
#endif
pParse->nTab = n;
if( pSelTab ){
assert( pTable->aCol==0 );
@@ -56521,9 +59410,9 @@
}else{
pTable->nCol = 0;
nErr++;
}
- sqlite3SelectDelete(pSel);
+ sqlite3SelectDelete(db, pSel);
} else {
nErr++;
}
#endif /* SQLITE_OMIT_VIEW */
@@ -56740,9 +59629,9 @@
goto exit_drop_table;
}
}
#endif
- if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
goto exit_drop_table;
}
@@ -56795,9 +59684,9 @@
** the table being dropped. This is done before the table is dropped
** at the btree level, in case the sqlite_sequence table needs to
** move as a result of the drop (can happen in auto-vacuum mode).
*/
- if( pTab->autoInc ){
+ if( pTab->tabFlags & TF_Autoincrement ){
sqlite3NestedParse(pParse,
"DELETE FROM %s.sqlite_sequence WHERE name=%Q",
pDb->zName, pTab->zName
);
@@ -56837,9 +59726,9 @@
}
sqliteViewResetAll(db, iDb);
exit_drop_table:
- sqlite3SrcListDelete(pName);
+ sqlite3SrcListDelete(db, pName);
}
/*
** This routine is called to create a new foreign key on the table
@@ -56865,8 +59754,9 @@
Token *pTo, /* Name of the other table */
ExprList *pToCol, /* Columns in the other table */
int flags /* Conflict resolution algorithms. */
){
+ sqlite3 *db = pParse->db;
#ifndef SQLITE_OMIT_FOREIGN_KEY
FKey *pFKey = 0;
Table *p = pParse->pNewTable;
int nByte;
@@ -56899,9 +59789,9 @@
for(i=0; i<pToCol->nExpr; i++){
nByte += strlen(pToCol->a[i].zName) + 1;
}
}
- pFKey = sqlite3DbMallocZero(pParse->db, nByte );
+ pFKey = sqlite3DbMallocZero(db, nByte );
if( pFKey==0 ){
goto fk_end;
}
pFKey->pFrom = p;
@@ -56953,12 +59843,12 @@
p->pFKey = pFKey;
pFKey = 0;
fk_end:
- sqlite3_free(pFKey);
+ sqlite3DbFree(db, pFKey);
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
- sqlite3ExprListDelete(pFromCol);
- sqlite3ExprListDelete(pToCol);
+ sqlite3ExprListDelete(db, pFromCol);
+ sqlite3ExprListDelete(db, pToCol);
}
/*
** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
@@ -57128,9 +60018,9 @@
assert(0);
}
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 );
pTab = pParse->pNewTable;
@@ -57139,9 +60029,9 @@
}
pDb = &db->aDb[iDb];
if( pTab==0 || pParse->nErr ) goto exit_create_index;
- if( pTab->readOnly ){
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
}
#ifndef SQLITE_OMIT_VIEW
@@ -57231,11 +60121,12 @@
/* Figure out how many bytes of space are required to store explicitly
** specified collation sequence names.
*/
for(i=0; i<pList->nExpr; i++){
- Expr *pExpr = pList->a[i].pExpr;
- if( pExpr ){
- nExtra += (1 + strlen(pExpr->pColl->zName));
+ Expr *pExpr;
+ CollSeq *pColl;
+ if( (pExpr = pList->a[i].pExpr)!=0 && (pColl = pExpr->pColl)!=0 ){
+ nExtra += (1 + strlen(pColl->zName));
}
}
/*
@@ -57300,9 +60191,9 @@
** same column more than once cannot be an error because that would
** break backwards compatibility - it needs to be a warning.
*/
pIndex->aiColumn[i] = j;
- if( pListItem->pExpr ){
+ if( pListItem->pExpr && pListItem->pExpr->pColl ){
assert( pListItem->pExpr->pColl );
zColl = zExtra;
sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName);
zExtra += (strlen(zColl) + 1);
@@ -57443,9 +60334,9 @@
pTab->zName,
iMem,
zStmt
);
- sqlite3_free(zStmt);
+ sqlite3DbFree(db, zStmt);
/* Fill the index with data and reparse the schema. Code an OP_Expire
** to invalidate all pre-compiled statements.
*/
@@ -57483,11 +60374,11 @@
exit_create_index:
if( pIndex ){
freeIndex(pIndex);
}
- sqlite3ExprListDelete(pList);
- sqlite3SrcListDelete(pTblName);
- sqlite3_free(zName);
+ sqlite3ExprListDelete(db, pList);
+ sqlite3SrcListDelete(db, pTblName);
+ sqlite3DbFree(db, zName);
return;
}
/*
@@ -57614,9 +60505,9 @@
sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
}
exit_drop_index:
- sqlite3SrcListDelete(pName);
+ sqlite3SrcListDelete(db, pName);
}
/*
** pArray is a pointer to an array of objects. Each object in the
@@ -57684,9 +60575,9 @@
&pList->nAlloc,
&i
);
if( i<0 ){
- sqlite3IdListDelete(pList);
+ sqlite3IdListDelete(db, pList);
return 0;
}
pList->a[i].zName = sqlite3NameFromToken(db, pToken);
return pList;
@@ -57694,16 +60585,16 @@
/*
** Delete an IdList.
*/
-SQLITE_PRIVATE void sqlite3IdListDelete(IdList *pList){
+SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
int i;
if( pList==0 ) return;
for(i=0; i<pList->nId; i++){
- sqlite3_free(pList->a[i].zName);
- }
- sqlite3_free(pList->a);
- sqlite3_free(pList);
+ sqlite3DbFree(db, pList->a[i].zName);
+ }
+ sqlite3DbFree(db, pList->a);
+ sqlite3DbFree(db, pList);
}
/*
** Return the index in pList of the identifier named zId. Return -1
@@ -57760,9 +60651,9 @@
pList->nAlloc *= 2;
pNew = sqlite3DbRealloc(db, pList,
sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) );
if( pNew==0 ){
- sqlite3SrcListDelete(pList);
+ sqlite3SrcListDelete(db, pList);
return 0;
}
pList = pNew;
}
@@ -57778,9 +60669,8 @@
}
pItem->zName = sqlite3NameFromToken(db, pTable);
pItem->zDatabase = sqlite3NameFromToken(db, pDatabase);
pItem->iCursor = -1;
- pItem->isPopulated = 0;
pList->nSrc++;
return pList;
}
@@ -57804,22 +60694,23 @@
/*
** Delete an entire SrcList including all its substructure.
*/
-SQLITE_PRIVATE void sqlite3SrcListDelete(SrcList *pList){
+SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
int i;
struct SrcList_item *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
- sqlite3_free(pItem->zDatabase);
- sqlite3_free(pItem->zName);
- sqlite3_free(pItem->zAlias);
+ sqlite3DbFree(db, pItem->zDatabase);
+ sqlite3DbFree(db, pItem->zName);
+ sqlite3DbFree(db, pItem->zAlias);
+ sqlite3DbFree(db, pItem->zIndex);
sqlite3DeleteTable(pItem->pTab);
- sqlite3SelectDelete(pItem->pSelect);
- sqlite3ExprDelete(pItem->pOn);
- sqlite3IdListDelete(pItem->pUsing);
- }
- sqlite3_free(pList);
+ sqlite3SelectDelete(db, pItem->pSelect);
+ sqlite3ExprDelete(db, pItem->pOn);
+ sqlite3IdListDelete(db, pItem->pUsing);
+ }
+ sqlite3DbFree(db, pList);
}
/*
** This routine is called by the parser to add a new term to the
@@ -57850,11 +60741,11 @@
struct SrcList_item *pItem;
sqlite3 *db = pParse->db;
p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
if( p==0 || p->nSrc==0 ){
- sqlite3ExprDelete(pOn);
- sqlite3IdListDelete(pUsing);
- sqlite3SelectDelete(pSubquery);
+ sqlite3ExprDelete(db, pOn);
+ sqlite3IdListDelete(db, pUsing);
+ sqlite3SelectDelete(db, pSubquery);
return p;
}
pItem = &p->a[p->nSrc-1];
if( pAlias && pAlias->n ){
@@ -57863,8 +60754,26 @@
pItem->pSelect = pSubquery;
pItem->pOn = pOn;
pItem->pUsing = pUsing;
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
@@ -58157,13 +61066,13 @@
pColl = sqlite3FindCollSeq(db, ENC(db), zColl, -1, 0);
if( pColl ){
if( zColl ){
reindexDatabases(pParse, zColl);
- sqlite3_free(zColl);
- }
- return;
- }
- sqlite3_free(zColl);
+ sqlite3DbFree(db, zColl);
+ }
+ return;
+ }
+ sqlite3DbFree(db, zColl);
}
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
if( iDb<0 ) return;
z = sqlite3NameFromToken(db, pObjName);
@@ -58171,13 +61080,13 @@
zDb = db->aDb[iDb].zName;
pTab = sqlite3FindTable(db, z, zDb);
if( pTab ){
reindexTable(pParse, pTab, 0);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
return;
}
pIndex = sqlite3FindIndex(db, z, zDb);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
if( pIndex ){
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3RefillIndex(pParse, pIndex, -1);
return;
@@ -58190,9 +61099,9 @@
** Return a dynamicly allocated KeyInfo structure that can be used
** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
**
** If successful, a pointer to the new structure is returned. In this case
-** the caller is responsible for calling sqlite3_free() on the returned
+** the caller is responsible for calling sqlite3DbFree(db, ) on the returned
** pointer. If an error occurs (out of memory or missing collation
** sequence), NULL is returned and the state of pParse updated to reflect
** the error.
*/
@@ -58199,9 +61108,10 @@
SQLITE_PRIVATE KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
int i;
int nCol = pIdx->nColumn;
int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
- KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(pParse->db, nBytes);
+ sqlite3 *db = pParse->db;
+ KeyInfo *pKey = (KeyInfo *)sqlite3DbMallocZero(db, nBytes);
if( pKey ){
pKey->db = pParse->db;
pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
@@ -58215,9 +61125,9 @@
pKey->nField = nCol;
}
if( pParse->nErr ){
- sqlite3_free(pKey);
+ sqlite3DbFree(db, pKey);
pKey = 0;
}
return pKey;
}
@@ -58238,9 +61148,9 @@
**
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
-** $Id: callback.c,v 1.25 2008/07/08 14:52:10 drh Exp $
+** $Id: callback.c,v 1.32 2008/10/10 17:41:29 drh Exp $
*/
/*
@@ -58254,9 +61164,9 @@
if( db->xCollNeeded ){
char *zExternal = sqlite3DbStrNDup(db, zName, nName);
if( !zExternal ) return;
db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal);
- sqlite3_free(zExternal);
+ sqlite3DbFree(db, zExternal);
}
#ifndef SQLITE_OMIT_UTF16
if( db->xCollNeeded16 ){
char const *zExternal;
@@ -58406,9 +61316,9 @@
*/
assert( pDel==0 || pDel==pColl );
if( pDel!=0 ){
db->mallocFailed = 1;
- sqlite3_free(pDel);
+ sqlite3DbFree(db, pDel);
pColl = 0;
}
}
}
@@ -58446,8 +61356,89 @@
if( pColl ) pColl += enc-1;
return pColl;
}
+/* During the search for the best function definition, this procedure
+** is called to test how well the function passed as the first argument
+** matches the request for a function with nArg arguments in a system
+** that uses encoding enc. The value returned indicates how well the
+** request is matched. A higher value indicates a better match.
+**
+** The returned value is always between 1 and 6, as follows:
+**
+** 1: A variable arguments function that prefers UTF-8 when a UTF-16
+** encoding is requested, or vice versa.
+** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
+** requested, or vice versa.
+** 3: A variable arguments function using the same text encoding.
+** 4: A function with the exact number of arguments requested that
+** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
+** 5: A function with the exact number of arguments requested that
+** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
+** 6: An exact match.
+**
+*/
+static int matchQuality(FuncDef *p, int nArg, u8 enc){
+ int match = 0;
+ if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
+ match = 1;
+ if( p->nArg==nArg || nArg==-1 ){
+ match = 4;
+ }
+ if( enc==p->iPrefEnc ){
+ match += 2;
+ }
+ else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
+ (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
+ match += 1;
+ }
+ }
+ return match;
+}
+
+/*
+** Search a FuncDefHash for a function with the given name. Return
+** a pointer to the matching FuncDef if found, or 0 if there is no match.
+*/
+static FuncDef *functionSearch(
+ FuncDefHash *pHash, /* Hash table to search */
+ int h, /* Hash of the name */
+ const char *zFunc, /* Name of function */
+ int nFunc /* Number of bytes in zFunc */
+){
+ FuncDef *p;
+ for(p=pHash->a[h]; p; p=p->pHash){
+ if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){
+ return p;
+ }
+ }
+ return 0;
+}
+
+/*
+** Insert a new FuncDef into a FuncDefHash hash table.
+*/
+SQLITE_PRIVATE void sqlite3FuncDefInsert(
+ FuncDefHash *pHash, /* The hash table into which to insert */
+ FuncDef *pDef /* The function definition to insert */
+){
+ FuncDef *pOther;
+ int nName = strlen(pDef->zName);
+ u8 c1 = (u8)pDef->zName[0];
+ int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a);
+ pOther = functionSearch(pHash, h, pDef->zName, nName);
+ if( pOther ){
+ pDef->pNext = pOther->pNext;
+ pOther->pNext = pDef;
+ }else{
+ pDef->pNext = 0;
+ pDef->pHash = pHash->a[h];
+ pHash->a[h] = pDef;
+ }
+}
+
+
+
/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8. Return a
** pointer to the FuncDef structure that defines that function, or return
@@ -58475,72 +61466,62 @@
u8 enc, /* Preferred text encoding */
int createFlag /* Create new entry if true and does not otherwise exist */
){
FuncDef *p; /* Iterator variable */
- FuncDef *pFirst; /* First function with this name */
FuncDef *pBest = 0; /* Best match found so far */
- int bestmatch = 0;
+ int bestScore = 0; /* Score of best match */
+ int h; /* Hash value */
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
if( nArg<-1 ) nArg = -1;
-
- pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
- for(p=pFirst; p; p=p->pNext){
- /* During the search for the best function definition, bestmatch is set
- ** as follows to indicate the quality of the match with the definition
- ** pointed to by pBest:
- **
- ** 0: pBest is NULL. No match has been found.
- ** 1: A variable arguments function that prefers UTF-8 when a UTF-16
- ** encoding is requested, or vice versa.
- ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
- ** requested, or vice versa.
- ** 3: A variable arguments function using the same text encoding.
- ** 4: A function with the exact number of arguments requested that
- ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
- ** 5: A function with the exact number of arguments requested that
- ** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
- ** 6: An exact match.
- **
- ** A larger value of 'matchqual' indicates a more desirable match.
- */
- if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
- int match = 1; /* Quality of this match */
- if( p->nArg==nArg || nArg==-1 ){
- match = 4;
- }
- if( enc==p->iPrefEnc ){
- match += 2;
- }
- else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
- (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
- match += 1;
- }
-
- if( match>bestmatch ){
+ h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
+
+ /* First search for a match amongst the application-defined functions.
+ */
+ p = functionSearch(&db->aFunc, h, zName, nName);
+ while( p ){
+ int score = matchQuality(p, nArg, enc);
+ if( score>bestScore ){
+ pBest = p;
+ bestScore = score;
+ }
+ p = p->pNext;
+ }
+
+ /* If no match is found, search the built-in functions.
+ **
+ ** Except, if createFlag is true, that means that we are trying to
+ ** install a new function. Whatever FuncDef structure is returned will
+ ** have fields overwritten with new information appropriate for the
+ ** new function. But the FuncDefs for built-in functions are read-only.
+ ** So we must not search for built-ins when creating a new function.
+ */
+ if( !createFlag && !pBest ){
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ p = functionSearch(pHash, h, zName, nName);
+ while( p ){
+ int score = matchQuality(p, nArg, enc);
+ if( score>bestScore ){
pBest = p;
- bestmatch = match;
- }
- }
- }
-
- /* If the createFlag parameter is true, and the seach did not reveal an
+ bestScore = score;
+ }
+ p = p->pNext;
+ }
+ }
+
+ /* 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 && bestmatch<6 &&
- (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){
- pBest->nArg = nArg;
- pBest->pNext = pFirst;
+ if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&
+ (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
+ pBest->zName = (char *)&pBest[1];
+ pBest->nArg = nArg;
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
- if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
- db->mallocFailed = 1;
- sqlite3_free(pBest);
- return 0;
- }
+ sqlite3FuncDefInsert(&db->aFunc, pBest);
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
return pBest;
@@ -58549,9 +61530,9 @@
}
/*
** Free all resources held by the schema structure. The void* argument points
-** at a Schema struct. This function does not call sqlite3_free() on the
+** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the
** pointer itself, it just cleans up subsiduary resources (i.e. the contents
** of the schema hash tables).
**
** The Schema.cache_size variable is not cleared.
@@ -58563,16 +61544,16 @@
Schema *pSchema = (Schema *)p;
temp1 = pSchema->tblHash;
temp2 = pSchema->trigHash;
- sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0);
+ sqlite3HashInit(&pSchema->trigHash, 0);
sqlite3HashClear(&pSchema->aFKey);
sqlite3HashClear(&pSchema->idxHash);
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
- sqlite3DeleteTrigger((Trigger*)sqliteHashData(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);
}
@@ -58594,12 +61575,12 @@
}
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;
}
@@ -58619,9 +61600,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.170 2008/07/08 23:40:20 drh Exp $
+** $Id: delete.c,v 1.186 2008/10/31 10:53:23 danielk1977 Exp $
*/
/*
** Look up every table that is named in pSrc. If any table is not found,
@@ -58628,18 +61609,19 @@
** add an error message to pParse->zErrMsg and return NULL. If all tables
** 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;
}
@@ -58648,9 +61630,10 @@
** writable, generate an error message and return 1. If it is
** writable return 0;
*/
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
- if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
+ if( ((pTab->tabFlags & TF_Readonly)!=0
+ && (pParse->db->flags & SQLITE_WriteSchema)==0
&& pParse->nested==0)
#ifndef SQLITE_OMIT_VIRTUALTABLE
|| (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
#endif
@@ -58695,30 +61678,124 @@
** set of rows in the view that are to be added to the ephemeral table.
*/
SQLITE_PRIVATE void sqlite3MaterializeView(
Parse *pParse, /* Parsing context */
- Select *pView, /* View definition */
+ Table *pView, /* View definition */
Expr *pWhere, /* Optional WHERE clause to be added */
int iCur /* Cursor number for ephemerial table */
){
SelectDest dest;
Select *pDup;
sqlite3 *db = pParse->db;
- pDup = sqlite3SelectDup(db, pView);
+ pDup = sqlite3SelectDup(db, pView->pSelect);
if( pWhere ){
SrcList *pFrom;
+ Token viewName;
pWhere = sqlite3ExprDup(db, pWhere);
- pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, 0, pDup, 0, 0);
+ viewName.z = (u8*)pView->zName;
+ viewName.n = (unsigned int)strlen((const char*)viewName.z);
+ pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
- sqlite3Select(pParse, pDup, &dest, 0, 0, 0);
- sqlite3SelectDelete(pDup);
+ sqlite3Select(pParse, pDup, &dest);
+ sqlite3SelectDelete(db, pDup);
}
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
+#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
+/*
+** Generate an expression tree to implement the WHERE, ORDER BY,
+** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
+**
+** DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
+** \__________________________/
+** pLimitWhere (pInClause)
+*/
+SQLITE_PRIVATE Expr *sqlite3LimitWhere(
+ Parse *pParse, /* The parser context */
+ SrcList *pSrc, /* the FROM clause -- which tables to scan */
+ Expr *pWhere, /* The WHERE clause. May be null */
+ ExprList *pOrderBy, /* The ORDER BY clause. May be null */
+ Expr *pLimit, /* The LIMIT clause. May be null */
+ Expr *pOffset, /* The OFFSET clause. May be null */
+ char *zStmtType /* Either DELETE or UPDATE. For error messages. */
+){
+ Expr *pWhereRowid = NULL; /* WHERE rowid .. */
+ Expr *pInClause = NULL; /* WHERE rowid IN ( select ) */
+ Expr *pSelectRowid = NULL; /* SELECT rowid ... */
+ ExprList *pEList = NULL; /* Expression list contaning only pSelectRowid */
+ SrcList *pSelectSrc = NULL; /* SELECT rowid FROM x ... (dup of pSrc) */
+ Select *pSelect = NULL; /* Complete SELECT tree */
+
+ /* Check that there isn't an ORDER BY without a LIMIT clause.
+ */
+ if( pOrderBy && (pLimit == 0) ) {
+ sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
+ pParse->parseError = 1;
+ goto limit_where_cleanup_2;
+ }
+
+ /* We only need to generate a select expression if there
+ ** is a limit/offset term to enforce.
+ */
+ if( pLimit == 0 ) {
+ /* if pLimit is null, pOffset will always be null as well. */
+ assert( pOffset == 0 );
+ return pWhere;
+ }
+
+ /* Generate a select expression tree to enforce the limit/offset
+ ** term for the DELETE or UPDATE statement. For example:
+ ** DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
+ ** becomes:
+ ** DELETE FROM table_a WHERE rowid IN (
+ ** SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
+ ** );
+ */
+
+ pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
+ if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
+ pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0);
+ if( pEList == 0 ) goto limit_where_cleanup_2;
+
+ /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
+ ** and the SELECT subtree. */
+ pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc);
+ if( pSelectSrc == 0 ) {
+ sqlite3ExprListDelete(pParse->db, pEList);
+ goto limit_where_cleanup_2;
+ }
+
+ /* generate the SELECT expression tree. */
+ pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,pOrderBy,0,pLimit,pOffset);
+ if( pSelect == 0 ) return 0;
+
+ /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
+ pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
+ if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
+ pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
+ if( pInClause == 0 ) goto limit_where_cleanup_1;
+
+ pInClause->pSelect = pSelect;
+ sqlite3ExprSetHeight(pParse, pInClause);
+ return pInClause;
+
+ /* something went wrong. clean up anything allocated. */
+limit_where_cleanup_1:
+ sqlite3SelectDelete(pParse->db, pSelect);
+ return 0;
+
+limit_where_cleanup_2:
+ sqlite3ExprDelete(pParse->db, pWhere);
+ sqlite3ExprListDelete(pParse->db, pOrderBy);
+ sqlite3ExprDelete(pParse->db, pLimit);
+ sqlite3ExprDelete(pParse->db, pOffset);
+ return 0;
+}
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
/*
** Generate code for a DELETE FROM statement.
**
@@ -58743,9 +61820,10 @@
AuthContext sContext; /* Authorization context */
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 */
int triggers_exist = 0; /* True if any triggers exist */
@@ -58791,11 +61869,14 @@
}
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( sqlite3ViewGetColumnNames(pParse, pTab) ){
@@ -58851,18 +61932,20 @@
/* 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->pSelect, pWhere, iCur);
- }
+ sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+ }
+#endif
/* Resolve the column names in the WHERE clause.
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
- if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+ if( sqlite3ResolveExprNames(&sNC, pWhere) ){
goto delete_from_cleanup;
}
/* Initialize the counter of the number of rows deleted, if
@@ -58872,40 +61955,29 @@
memCnt = ++pParse->nMem;
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( !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);
- }
- }
- }
+ 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);
+ }
+ 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
*/
@@ -59016,15 +62088,15 @@
*/
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:
sqlite3AuthContextPop(&sContext);
- sqlite3SrcListDelete(pTabList);
- sqlite3ExprDelete(pWhere);
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprDelete(db, pWhere);
return;
}
/*
@@ -59169,11 +62241,10 @@
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: func.c,v 1.195 2008/07/08 22:28:49 shane Exp $
-*/
-
+** $Id: func.c,v 1.204 2008/10/28 17:52:39 danielk1977 Exp $
+*/
/*
** Return the collating function associated with a function.
*/
@@ -59980,16 +63051,16 @@
sqlite3 *db = sqlite3_context_db_handle(context);
nOut += nRep - nPattern;
if( nOut>=db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
- sqlite3_free(zOut);
+ sqlite3DbFree(db, zOut);
return;
}
zOld = zOut;
zOut = sqlite3_realloc(zOut, (int)nOut);
if( zOut==0 ){
sqlite3_result_error_nomem(context);
- sqlite3_free(zOld);
+ sqlite3DbFree(db, zOld);
return;
}
memcpy(&zOut[j], zRep, nRep);
j += nRep;
@@ -60030,9 +63101,9 @@
nIn = sqlite3_value_bytes(argv[0]);
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;
zCharSet = 0;
@@ -60086,8 +63157,9 @@
}
}
sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT);
}
+
#ifdef SQLITE_SOUNDEX
/*
** Compute the soundex encoding of a word.
@@ -60362,110 +63434,11 @@
** functions. This should be the only routine in this file with
** external linkage.
*/
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
- static const struct {
- char *zName;
- signed char nArg;
- u8 argType; /* 1: 0, 2: 1, 3: 2,... N: N-1. */
- u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */
- u8 needCollSeq;
- void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
- } aFuncs[] = {
- { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc },
- { "min", 0, 0, SQLITE_UTF8, 1, 0 },
- { "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc },
- { "max", 0, 1, SQLITE_UTF8, 1, 0 },
- { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc },
- { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc },
- { "substr", 2, 0, SQLITE_UTF8, 0, substrFunc },
- { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc },
- { "abs", 1, 0, SQLITE_UTF8, 0, absFunc },
- { "round", 1, 0, SQLITE_UTF8, 0, roundFunc },
- { "round", 2, 0, SQLITE_UTF8, 0, roundFunc },
- { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc },
- { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc },
- { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc },
- { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 },
- { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 },
- { "hex", 1, 0, SQLITE_UTF8, 0, hexFunc },
- { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
- { "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
- { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob },
- { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
- { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
- { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
- { "last_insert_rowid", 0, 0, SQLITE_UTF8, 0, last_insert_rowid },
- { "changes", 0, 0, SQLITE_UTF8, 0, changes },
- { "total_changes", 0, 0, SQLITE_UTF8, 0, total_changes },
- { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc },
- { "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc },
- { "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc },
- { "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc },
- { "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc },
- { "trim", 1, 3, SQLITE_UTF8, 0, trimFunc },
- { "trim", 2, 3, SQLITE_UTF8, 0, trimFunc },
- { "zeroblob", 1, 0, SQLITE_UTF8, 0, zeroblobFunc },
-#ifdef SQLITE_SOUNDEX
- { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
-#endif
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- { "load_extension", 1, 0, SQLITE_UTF8, 0, loadExt },
- { "load_extension", 2, 0, SQLITE_UTF8, 0, loadExt },
-#endif
- };
- static const struct {
- char *zName;
- signed char nArg;
- u8 argType;
- u8 needCollSeq;
- void (*xStep)(sqlite3_context*,int,sqlite3_value**);
- void (*xFinalize)(sqlite3_context*);
- } aAggs[] = {
- { "min", 1, 0, 1, minmaxStep, minMaxFinalize },
- { "max", 1, 1, 1, minmaxStep, minMaxFinalize },
- { "sum", 1, 0, 0, sumStep, sumFinalize },
- { "total", 1, 0, 0, sumStep, totalFinalize },
- { "avg", 1, 0, 0, sumStep, avgFinalize },
- { "count", 0, 0, 0, countStep, countFinalize },
- { "count", 1, 0, 0, countStep, countFinalize },
- { "group_concat", -1, 0, 0, groupConcatStep, groupConcatFinalize },
- };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- void *pArg;
- u8 argType = aFuncs[i].argType;
- pArg = SQLITE_INT_TO_PTR(argType);
- sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
- aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
- if( aFuncs[i].needCollSeq ){
- FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName,
- strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0);
- if( pFunc && aFuncs[i].needCollSeq ){
- pFunc->needCollSeq = 1;
- }
- }
- }
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions(db);
#endif
-#ifndef SQLITE_OMIT_PARSER
- sqlite3AttachFunctions(db);
-#endif
- for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
- void *pArg = SQLITE_INT_TO_PTR(aAggs[i].argType);
- sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
- pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
- if( aAggs[i].needCollSeq ){
- FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName,
- strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0);
- if( pFunc && aAggs[i].needCollSeq ){
- pFunc->needCollSeq = 1;
- }
- }
- }
- sqlite3RegisterDateTimeFunctions(db);
if( !db->mallocFailed ){
int rc = sqlite3_overload_function(db, "MATCH", 2);
assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
if( rc==SQLITE_NOMEM ){
@@ -60473,13 +63446,8 @@
}
}
#ifdef SQLITE_SSE
(void)sqlite3SseFunctions(db);
-#endif
-#ifdef SQLITE_CASE_SENSITIVE_LIKE
- sqlite3RegisterLikeFunctions(db, 1);
-#else
- sqlite3RegisterLikeFunctions(db, 0);
#endif
}
/*
@@ -60546,8 +63514,95 @@
*pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
return 1;
}
+/*
+** All all of the FuncDef structures in the aBuiltinFunc[] array above
+** to the global function hash table. This occurs at start-time (as
+** a consequence of calling sqlite3_initialize()).
+**
+** After this routine runs
+*/
+SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
+ /*
+ ** The following array holds FuncDef structures for all of the functions
+ ** defined in this file.
+ **
+ ** The array cannot be constant since changes are made to the
+ ** FuncDef.pHash elements at start-time. The elements of this array
+ ** are read-only after initialization is complete.
+ */
+ static SQLITE_WSD FuncDef aBuiltinFunc[] = {
+ FUNCTION(ltrim, 1, 1, 0, trimFunc ),
+ FUNCTION(ltrim, 2, 1, 0, trimFunc ),
+ FUNCTION(rtrim, 1, 2, 0, trimFunc ),
+ FUNCTION(rtrim, 2, 2, 0, trimFunc ),
+ FUNCTION(trim, 1, 3, 0, trimFunc ),
+ FUNCTION(trim, 2, 3, 0, trimFunc ),
+ FUNCTION(min, -1, 0, 1, minmaxFunc ),
+ FUNCTION(min, 0, 0, 1, 0 ),
+ AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(max, -1, 1, 1, minmaxFunc ),
+ FUNCTION(max, 0, 1, 1, 0 ),
+ AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(typeof, 1, 0, 0, typeofFunc ),
+ FUNCTION(length, 1, 0, 0, lengthFunc ),
+ FUNCTION(substr, 2, 0, 0, substrFunc ),
+ FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(abs, 1, 0, 0, absFunc ),
+ FUNCTION(round, 1, 0, 0, roundFunc ),
+ FUNCTION(round, 2, 0, 0, roundFunc ),
+ FUNCTION(upper, 1, 0, 0, upperFunc ),
+ FUNCTION(lower, 1, 0, 0, lowerFunc ),
+ FUNCTION(coalesce, 1, 0, 0, 0 ),
+ FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
+ FUNCTION(coalesce, 0, 0, 0, 0 ),
+ FUNCTION(hex, 1, 0, 0, hexFunc ),
+ FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
+ FUNCTION(random, -1, 0, 0, randomFunc ),
+ FUNCTION(randomblob, 1, 0, 0, randomBlob ),
+ FUNCTION(nullif, 2, 0, 1, nullifFunc ),
+ FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
+ FUNCTION(quote, 1, 0, 0, quoteFunc ),
+ FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
+ FUNCTION(changes, 0, 0, 0, changes ),
+ FUNCTION(total_changes, 0, 0, 0, total_changes ),
+ FUNCTION(replace, 3, 0, 0, replaceFunc ),
+ FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
+ #ifdef SQLITE_SOUNDEX
+ FUNCTION(soundex, 1, 0, 0, soundexFunc ),
+ #endif
+ #ifndef SQLITE_OMIT_LOAD_EXTENSION
+ FUNCTION(load_extension, 1, 0, 0, loadExt ),
+ FUNCTION(load_extension, 2, 0, 0, loadExt ),
+ #endif
+ AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
+ AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
+ AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
+ AGGREGATE(count, 0, 0, 0, countStep, countFinalize ),
+ AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
+ AGGREGATE(group_concat, -1, 0, 0, groupConcatStep, groupConcatFinalize),
+
+ LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ #ifdef SQLITE_CASE_SENSITIVE_LIKE
+ LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ #else
+ LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ #endif
+ };
+
+ int i;
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);
+
+ for(i=0; i<ArraySize(aBuiltinFunc); i++){
+ sqlite3FuncDefInsert(pHash, &aFunc[i]);
+ }
+ sqlite3RegisterDateTimeFunctions();
+}
+
/************** End of func.c ************************************************/
/************** Begin file insert.c ******************************************/
/*
** 2001 September 15
@@ -60562,9 +63617,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.247 2008/07/08 23:40:20 drh Exp $
+** $Id: insert.c,v 1.250 2008/10/31 10:53:23 danielk1977 Exp $
*/
/*
** Set P4 of the most recently inserted opcode to a column affinity
@@ -60594,10 +63649,11 @@
*/
int n;
Table *pTab = pIdx->pTable;
sqlite3 *db = sqlite3VdbeDb(v);
- pIdx->zColAff = (char *)sqlite3DbMallocRaw(db, pIdx->nColumn+2);
+ pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2);
if( !pIdx->zColAff ){
+ db->mallocFailed = 1;
return;
}
for(n=0; n<pIdx->nColumn; n++){
pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
@@ -60635,10 +63691,11 @@
char *zColAff;
int i;
sqlite3 *db = sqlite3VdbeDb(v);
- zColAff = (char *)sqlite3DbMallocRaw(db, pTab->nCol+1);
+ zColAff = (char *)sqlite3Malloc(pTab->nCol+1);
if( !zColAff ){
+ db->mallocFailed = 1;
return;
}
for(i=0; i<pTab->nCol; i++){
@@ -60712,9 +63769,9 @@
int iDb, /* Index of the database holding pTab */
Table *pTab /* The table we are writing to */
){
int memId = 0; /* Register holding maximum rowid */
- if( pTab->autoInc ){
+ if( pTab->tabFlags & TF_Autoincrement ){
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int iCur = pParse->nTab;
int addr; /* Address of the top of the loop */
@@ -60763,9 +63820,9 @@
int iDb, /* Index of the database holding pTab */
Table *pTab, /* Table we are inserting into */
int memId /* Memory cell holding the maximum rowid */
){
- if( pTab->autoInc ){
+ if( pTab->tabFlags & TF_Autoincrement ){
int iCur = pParse->nTab;
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int j1;
@@ -61079,9 +64136,9 @@
j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
VdbeComment((v, "Jump over SELECT coroutine"));
/* Resolve the expressions in the SELECT statement and execute it. */
- rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+ rc = sqlite3Select(pParse, pSelect, &dest);
if( rc || pParse->nErr || db->mallocFailed ){
goto insert_cleanup;
}
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */
@@ -61149,9 +64206,9 @@
srcTab = -1;
assert( useTempTable==0 );
nColumn = pList ? pList->nExpr : 0;
for(i=0; i<nColumn; i++){
- if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){
+ if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){
goto insert_cleanup;
}
}
}
@@ -61539,17 +64596,17 @@
*/
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:
- sqlite3SrcListDelete(pTabList);
- sqlite3ExprListDelete(pList);
- sqlite3SelectDelete(pSelect);
- sqlite3IdListDelete(pColumn);
- sqlite3_free(aRegIdx);
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprListDelete(db, pList);
+ sqlite3SelectDelete(db, pSelect);
+ sqlite3IdListDelete(db, pColumn);
+ sqlite3DbFree(db, aRegIdx);
}
/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE.
@@ -62082,9 +65139,9 @@
if( pDest->pTrigger ){
return 0; /* tab1 must not have triggers */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pDest->isVirtual ){
+ if( pDest->tabFlags & TF_Virtual ){
return 0; /* tab1 must not be a virtual table */
}
#endif
if( onError==OE_Default ){
@@ -62117,9 +65174,9 @@
assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */
if( pSelect->pPrior ){
return 0; /* SELECT may not be a compound query */
}
- if( pSelect->isDistinct ){
+ if( pSelect->selFlags & SF_Distinct ){
return 0; /* SELECT may not be DISTINCT */
}
pEList = pSelect->pEList;
assert( pEList!=0 );
@@ -62143,9 +65200,9 @@
if( pSrc==pDest ){
return 0; /* tab1 and tab2 may not be the same table */
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pSrc->isVirtual ){
+ if( pSrc->tabFlags & TF_Virtual ){
return 0; /* tab2 must not be a virtual table */
}
#endif
if( pSrc->pSelect ){
@@ -62234,9 +65291,9 @@
}else if( pDest->pIndex==0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
}else{
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- assert( pDest->autoInc==0 );
+ assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
@@ -62302,9 +65359,9 @@
** implement the programmer interface to the library. Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: legacy.c,v 1.27 2008/06/15 02:51:47 drh Exp $
+** $Id: legacy.c,v 1.29 2008/08/02 03:50:39 drh Exp $
*/
/*
@@ -62370,12 +65427,11 @@
}
}
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
- if( !azCols[i] ){
- db->mallocFailed = 1;
- goto exec_out;
- }
+ /* sqlite3VdbeSetColName() installs column names as UTF8
+ ** strings so there is no way for sqlite3_column_name() to fail. */
+ assert( azCols[i]!=0 );
}
nCallback++;
}
if( rc==SQLITE_ROW ){
@@ -62408,15 +65464,15 @@
break;
}
}
- sqlite3_free(azCols);
+ sqlite3DbFree(db, azCols);
azCols = 0;
}
exec_out:
if( pStmt ) sqlite3_finalize(pStmt);
- if( azCols ) sqlite3_free(azCols);
+ sqlite3DbFree(db, azCols);
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
int nErrMsg = 1 + strlen(sqlite3_errmsg(db));
@@ -62448,9 +65504,9 @@
*************************************************************************
** This file contains code used to dynamically load extensions into
** the SQLite library.
**
-** $Id: loadext.c,v 1.51 2008/07/08 14:17:35 danielk1977 Exp $
+** $Id: loadext.c,v 1.56 2008/10/12 00:27:53 shane Exp $
*/
#ifndef SQLITE_CORE
#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
@@ -62473,9 +65529,9 @@
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
**
-** @(#) $Id: sqlite3ext.h,v 1.24 2008/06/30 15:09:29 danielk1977 Exp $
+** @(#) $Id: sqlite3ext.h,v 1.25 2008/10/12 00:27:54 shane Exp $
*/
#ifndef _SQLITE3EXT_H_
#define _SQLITE3EXT_H_
@@ -62665,9 +65721,11 @@
** SQLITE_CORE macros is undefined.
*/
#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_bind_int64 sqlite3_api->bind_int64
@@ -62721,16 +65779,20 @@
#define sqlite3_errcode sqlite3_api->errcode
#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_libversion_number sqlite3_api->libversion_number
@@ -62766,9 +65828,11 @@
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#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
#define sqlite3_value_bytes sqlite3_api->value_bytes
@@ -62932,9 +65996,13 @@
** not NULL before calling it.
*/
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_bind_int64,
@@ -62987,9 +66055,13 @@
sqlite3_errcode,
sqlite3_errmsg,
sqlite3_errmsg16,
sqlite3_exec,
+#ifndef SQLITE_OMIT_DEPRECATED
sqlite3_expired,
+#else
+ 0,
+#endif
sqlite3_finalize,
sqlite3_free,
sqlite3_free_table,
sqlite3_get_autocommit,
@@ -63027,12 +66099,20 @@
sqlite3_set_auxdata,
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_value_bytes,
@@ -63081,9 +66161,9 @@
sqlite3_create_collation_v2,
sqlite3_file_control,
sqlite3_memory_highwater,
sqlite3_memory_used,
-#ifdef SQLITE_MUTEX_NOOP
+#ifdef SQLITE_MUTEX_OMIT
0,
0,
0,
0,
@@ -63134,9 +66214,9 @@
** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
**
** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
** error message text. The calling function should free this memory
-** by calling sqlite3_free().
+** by calling sqlite3DbFree(db, ).
*/
static int sqlite3LoadExtension(
sqlite3 *db, /* Load the extension into this database connection */
const char *zFile, /* Name of the shared library containing extension */
@@ -63173,9 +66253,9 @@
zErr[sizeof(zErr)-1] = '\0';
sqlite3_snprintf(sizeof(zErr)-1, zErr,
"unable to open shared library [%s]", zFile);
sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr);
- *pzErrMsg = sqlite3DbStrDup(db, zErr);
+ *pzErrMsg = sqlite3DbStrDup(0, zErr);
}
return SQLITE_ERROR;
}
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
@@ -63186,9 +66266,9 @@
zErr[sizeof(zErr)-1] = '\0';
sqlite3_snprintf(sizeof(zErr)-1, zErr,
"no entry point [%s] in shared library [%s]", zProc,zFile);
sqlite3OsDlError(pVfs, sizeof(zErr)-1, zErr);
- *pzErrMsg = sqlite3DbStrDup(db, zErr);
+ *pzErrMsg = sqlite3DbStrDup(0, zErr);
sqlite3OsDlClose(pVfs, handle);
}
return SQLITE_ERROR;
}else if( xInit(db, &zErrmsg, &sqlite3Apis) ){
@@ -63200,20 +66280,19 @@
return SQLITE_ERROR;
}
/* Append the new shared library handle to the db->aExtension array. */
- db->nExtension++;
- aHandle = sqlite3DbMallocZero(db, sizeof(handle)*db->nExtension);
+ aHandle = sqlite3DbMallocZero(db, sizeof(handle)*(db->nExtension+1));
if( aHandle==0 ){
return SQLITE_NOMEM;
}
if( db->nExtension>0 ){
- memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1));
- }
- sqlite3_free(db->aExtension);
+ memcpy(aHandle, db->aExtension, sizeof(handle)*db->nExtension);
+ }
+ sqlite3DbFree(db, db->aExtension);
db->aExtension = aHandle;
- db->aExtension[db->nExtension-1] = handle;
+ db->aExtension[db->nExtension++] = handle;
return SQLITE_OK;
}
SQLITE_API int sqlite3_load_extension(
sqlite3 *db, /* Load the extension into this database connection */
@@ -63237,9 +66316,9 @@
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; i<db->nExtension; i++){
sqlite3OsDlClose(db->pVfs, db->aExtension[i]);
}
- sqlite3_free(db->aExtension);
+ sqlite3DbFree(db, db->aExtension);
}
/*
** Enable or disable extension loading. Extension loading is disabled by
@@ -63275,12 +66354,28 @@
**
** 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
/*
** Register a statically linked extension that is automatically
@@ -63295,25 +66390,26 @@
}else
#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;
- }
- if( i==autoext.nExt ){
- int nByte = (autoext.nExt+1)*sizeof(autoext.aExt[0]);
+ for(i=0; i<wsdAutoext.nExt; i++){
+ if( wsdAutoext.aExt[i]==xInit ) break;
+ }
+ 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);
assert( (rc&0xff)==rc );
@@ -63328,15 +66424,16 @@
#ifndef SQLITE_OMIT_AUTOINIT
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);
}
}
@@ -63348,24 +66445,25 @@
int go = 1;
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) ){
sqlite3Error(db, SQLITE_ERROR,
@@ -63392,9 +66490,9 @@
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.182 2008/07/08 07:35:52 danielk1977 Exp $
+** $Id: pragma.c,v 1.192 2008/10/31 10:53:23 danielk1977 Exp $
*/
/* Ignore this whole file if pragmas are disabled
*/
@@ -63530,9 +66628,9 @@
int mem = ++pParse->nMem;
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);
}
@@ -63600,8 +66698,18 @@
return 0;
}
#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.
**
** Pragmas are of this form:
@@ -63654,9 +66762,9 @@
}else{
zRight = sqlite3NameFromToken(db, pValue);
}
- zDb = ((iDb>0)?pDb->zName:0);
+ zDb = ((pId2 && pId2->n>0)?pDb->zName:0);
if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
goto pragma_out;
}
@@ -63691,9 +66799,9 @@
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
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);
sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE);
@@ -63772,9 +66880,9 @@
iReg = ++pParse->nMem;
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
/*
** PRAGMA [database.]locking_mode
@@ -63817,26 +66925,28 @@
if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
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|memory|off)
*/
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--;
}
}
@@ -63870,12 +66980,14 @@
pPager = sqlite3BtreePager(pDb->pBt);
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);
}else
@@ -64040,17 +67152,19 @@
if( !zRight ){
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;
}
}
@@ -64061,13 +67175,13 @@
invalidateTempStorage(pParse);
}
sqlite3_free(sqlite3_temp_directory);
if( zRight[0] ){
- sqlite3_temp_directory = zRight;
- zRight = 0;
+ sqlite3_temp_directory = sqlite3DbStrDup(0, zRight);
}else{
sqlite3_temp_directory = 0;
}
+#endif /* SQLITE_OMIT_WSD */
}
}else
/*
@@ -64123,14 +67237,14 @@
int nHidden = 0;
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;
if( IsHiddenColumn(pCol) ){
@@ -64140,9 +67254,9 @@
sqlite3VdbeAddOp2(v, OP_Integer, i-nHidden, 1);
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{
sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
@@ -64162,11 +67276,11 @@
int i;
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);
sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
@@ -64188,11 +67302,11 @@
if( pIdx ){
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);
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
@@ -64208,11 +67322,11 @@
int i;
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 );
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
@@ -64227,10 +67341,10 @@
int i = 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);
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0);
@@ -64249,26 +67363,34 @@
v = sqlite3GetVdbe(pParse);
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;
}
@@ -64328,9 +67450,9 @@
/* Initialize the VDBE program */
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 ){
@@ -64507,9 +67629,9 @@
const struct EncName *pEnc;
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) ){
sqlite3VdbeChangeP4(v, -1, pEnc->zName, P4_STATIC);
@@ -64570,9 +67692,8 @@
if( sqlite3StrICmp(zLeft, "schema_version")==0
|| 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] ){
case 's': case 'S':
@@ -64609,9 +67730,9 @@
int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie);
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 */
@@ -64626,10 +67747,10 @@
int i;
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;
const char *zState = "unknown";
@@ -64645,8 +67766,9 @@
}
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
+
}else
#endif
#ifdef SQLITE_SSE
@@ -64702,10 +67824,10 @@
}
#endif
}
pragma_out:
- sqlite3_free(zLeft);
- sqlite3_free(zRight);
+ sqlite3DbFree(db, zLeft);
+ sqlite3DbFree(db, zRight);
}
#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */
@@ -64725,9 +67847,9 @@
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
-** $Id: prepare.c,v 1.89 2008/07/08 19:34:07 drh Exp $
+** $Id: prepare.c,v 1.98 2008/10/31 10:53:23 danielk1977 Exp $
*/
/*
** Fill the InitData structure with an error message that indicates
@@ -64737,14 +67859,15 @@
InitData *pData, /* Initialization context */
const char *zObj, /* Object being parsed at the point of error */
const char *zExtra /* Error information */
){
- if( !pData->db->mallocFailed ){
+ sqlite3 *db = pData->db;
+ if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
if( zObj==0 ) zObj = "?";
sqlite3SetString(pData->pzErrMsg, pData->db,
"malformed database schema (%s)", zObj);
if( zExtra && zExtra[0] ){
- *pData->pzErrMsg = sqlite3MPrintf(pData->db, "%z - %s",
+ *pData->pzErrMsg = sqlite3MAppendf(pData->db, *pData->pzErrMsg, "%s - %s",
*pData->pzErrMsg, zExtra);
}
}
pData->rc = SQLITE_CORRUPT;
@@ -64767,35 +67890,36 @@
sqlite3 *db = pData->db;
int iDb = pData->iDb;
assert( sqlite3_mutex_held(db->mutex) );
- pData->rc = SQLITE_OK;
DbClearProperty(db, iDb, DB_Empty);
if( db->mallocFailed ){
corruptSchema(pData, argv[0], 0);
return SQLITE_NOMEM;
}
assert( 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
** structures that describe the table, index, or view.
*/
char *zErr;
int rc;
+ u8 lookasideEnabled;
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = atoi(argv[1]);
+ lookasideEnabled = db->lookaside.bEnabled;
+ db->lookaside.bEnabled = 0;
rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
db->init.iDb = 0;
+ db->lookaside.bEnabled = lookasideEnabled;
assert( rc!=SQLITE_OK || zErr==0 );
if( SQLITE_OK!=rc ){
pData->rc = rc;
if( rc==SQLITE_NOMEM ){
@@ -64802,10 +67926,9 @@
db->mallocFailed = 1;
}else if( rc!=SQLITE_INTERRUPT ){
corruptSchema(pData, argv[0], zErr);
}
- sqlite3_free(zErr);
- return 1;
+ sqlite3DbFree(db, zErr);
}
}else if( argv[0]==0 ){
corruptSchema(pData, 0, 0);
}else{
@@ -64899,19 +68022,20 @@
azArg[2] = zMasterSchema;
azArg[3] = 0;
initData.db = db;
initData.iDb = iDb;
+ initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
(void)sqlite3SafetyOff(db);
- rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
+ sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
(void)sqlite3SafetyOn(db);
- if( rc ){
+ if( initData.rc ){
rc = initData.rc;
goto error_out;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
- pTab->readOnly = 1;
+ pTab->tabFlags |= TF_Readonly;
}
/* Create a cursor to hold the database open
*/
@@ -64930,9 +68054,9 @@
sqlite3BtreeEnter(pDb->pBt);
rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain);
if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
- goto leave_error_out;
+ goto initone_error_out;
}
/* Get the database meta information.
**
@@ -64952,14 +68076,14 @@
** the possible values of meta[4].
*/
if( rc==SQLITE_OK ){
int i;
- for(i=0; rc==SQLITE_OK && i<sizeof(meta)/sizeof(meta[0]); i++){
+ for(i=0; i<sizeof(meta)/sizeof(meta[0]); i++){
rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
- }
- if( rc ){
- sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
- goto leave_error_out;
+ if( rc ){
+ sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc));
+ goto initone_error_out;
+ }
}
}else{
memset(meta, 0, sizeof(meta));
}
@@ -64980,9 +68104,9 @@
if( meta[4]!=ENC(db) ){
sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
" text encoding as main database");
rc = SQLITE_ERROR;
- goto leave_error_out;
+ goto initone_error_out;
}
}
}else{
DbSetProperty(db, iDb, DB_Empty);
@@ -65009,9 +68133,9 @@
}
if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
sqlite3SetString(pzErrMsg, db, "unsupported file format");
rc = SQLITE_ERROR;
- goto leave_error_out;
+ goto initone_error_out;
}
/* Ticket #2804: When we open a database in the newer file format,
** clear the legacy_file_format pragma flag so that a VACUUM will
@@ -65044,11 +68168,11 @@
#ifndef SQLITE_OMIT_AUTHORIZATION
db->xAuth = xAuth;
}
#endif
- if( rc==SQLITE_ABORT ) rc = initData.rc;
+ if( rc==SQLITE_OK ) rc = initData.rc;
(void)sqlite3SafetyOn(db);
- sqlite3_free(zSql);
+ sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
if( rc==SQLITE_OK ){
sqlite3AnalysisLoad(db, iDb);
}
@@ -65074,9 +68198,9 @@
/* Jump here for an error that occurs after successfully allocating
** curMain and calling sqlite3BtreeEnter(). For an error that occurs
** before that point, jump to error_out.
*/
-leave_error_out:
+initone_error_out:
sqlite3BtreeCloseCursor(curMain);
sqlite3_free(curMain);
sqlite3BtreeLeave(pDb->pBt);
@@ -65278,9 +68402,9 @@
}
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
if( zSqlCopy ){
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
- sqlite3_free(zSqlCopy);
+ sqlite3DbFree(db, zSqlCopy);
sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
}else{
sParse.zTail = &zSql[nBytes];
}
@@ -65309,21 +68433,21 @@
#ifndef SQLITE_OMIT_EXPLAIN
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
@@ -65342,9 +68466,9 @@
}
if( zErrMsg ){
sqlite3Error(db, rc, "%s", zErrMsg);
- sqlite3_free(zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
}else{
sqlite3Error(db, rc, 0);
}
@@ -65398,9 +68522,9 @@
}else{
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;
}
@@ -65477,9 +68601,9 @@
*/
int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8);
*pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
}
- sqlite3_free(zSql8);
+ sqlite3DbFree(db, zSql8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -65534,26 +68658,26 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.456 2008/07/15 00:27:35 drh Exp $
+** $Id: select.c,v 1.482 2008/10/31 10:53:23 danielk1977 Exp $
*/
/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
*/
-static void clearSelect(Select *p){
- sqlite3ExprListDelete(p->pEList);
- sqlite3SrcListDelete(p->pSrc);
- sqlite3ExprDelete(p->pWhere);
- sqlite3ExprListDelete(p->pGroupBy);
- sqlite3ExprDelete(p->pHaving);
- sqlite3ExprListDelete(p->pOrderBy);
- sqlite3SelectDelete(p->pPrior);
- sqlite3ExprDelete(p->pLimit);
- sqlite3ExprDelete(p->pOffset);
+static void clearSelect(sqlite3 *db, Select *p){
+ sqlite3ExprListDelete(db, p->pEList);
+ sqlite3SrcListDelete(db, p->pSrc);
+ sqlite3ExprDelete(db, p->pWhere);
+ sqlite3ExprListDelete(db, p->pGroupBy);
+ sqlite3ExprDelete(db, p->pHaving);
+ sqlite3ExprListDelete(db, p->pOrderBy);
+ sqlite3SelectDelete(db, p->pPrior);
+ sqlite3ExprDelete(db, p->pLimit);
+ sqlite3ExprDelete(db, p->pOffset);
}
/*
** Initialize a SelectDest structure.
@@ -65600,18 +68724,18 @@
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy;
- pNew->isDistinct = isDistinct;
- pNew->op = TK_SELECT;
- assert( pOffset==0 || pLimit!=0 );
+ pNew->selFlags = isDistinct ? SF_Distinct : 0;
+ pNew->op = TK_SELECT;
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
- if( pNew==&standin) {
- clearSelect(pNew);
+ if( db->mallocFailed ) {
+ clearSelect(db, pNew);
+ if( pNew!=&standin ) sqlite3DbFree(db, pNew);
pNew = 0;
}
return pNew;
}
@@ -65618,12 +68742,12 @@
/*
** Delete the given Select structure and all of its substructures.
*/
-SQLITE_PRIVATE void sqlite3SelectDelete(Select *p){
+SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( p ){
- clearSelect(p);
- sqlite3_free(p);
+ clearSelect(db, p);
+ sqlite3DbFree(db, p);
}
}
/*
@@ -65724,17 +68848,19 @@
** {a"bc} -> {"a""bc"}
*/
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 ){
/* String contains " characters - copy and quote the string. */
@@ -66094,9 +69220,9 @@
}else if( eDest!=SRT_Exists ){
/* If the destination is an EXISTS(...) expression, the actual
** values returned by the SELECT are not required.
*/
- sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback);
+ sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
}
nColumn = nResultCol;
/* If the DISTINCT keyword was present on the SELECT statement
@@ -66211,9 +69337,9 @@
** case of a subroutine, the subroutine itself is responsible for
** popping the data from the stack.
*/
case SRT_Coroutine:
- case SRT_Callback: {
+ case SRT_Output: {
if( pOrderBy ){
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
pushOntoSorter(pParse, pOrderBy, p, r1);
@@ -66318,12 +69444,12 @@
int regRow;
int regRowid;
iTab = pOrderBy->iECursor;
- if( eDest==SRT_Callback || eDest==SRT_Coroutine ){
+ if( eDest==SRT_Output || eDest==SRT_Coroutine ){
pseudoTab = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn);
- sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Callback);
+ sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Output);
}
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
codeOffset(v, p, cont);
regRow = sqlite3GetTempReg(pParse);
@@ -66351,9 +69477,9 @@
/* The LIMIT clause will terminate the loop for us */
break;
}
#endif
- case SRT_Callback:
+ case SRT_Output:
case SRT_Coroutine: {
int i;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid);
@@ -66360,9 +69486,9 @@
for(i=0; i<nColumn; i++){
assert( regRow!=pDest->iMem+i );
sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
}
- if( eDest==SRT_Callback ){
+ if( eDest==SRT_Output ){
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
}else{
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);
@@ -66385,9 +69511,9 @@
*/
sqlite3VdbeResolveLabel(v, cont);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
sqlite3VdbeResolveLabel(v, brk);
- if( eDest==SRT_Callback || eDest==SRT_Coroutine ){
+ if( eDest==SRT_Output || eDest==SRT_Coroutine ){
sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
}
}
@@ -66552,15 +69678,15 @@
/* The vdbe must make its own copy of the column-type and other
** 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 */
}
@@ -66597,10 +69723,10 @@
p = pEList->a[i].pExpr;
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;
for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
@@ -66613,22 +69739,24 @@
}else{
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);
- }else{
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol));
- }
- }else{
- sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
+ }else{
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
+ }
+ }else{
+ sqlite3VdbeSetColName(v, i, COLNAME_NAME,
+ sqlite3DbStrNDup(db, (char*)p->span.z, p->span.n), SQLITE_DYNAMIC);
}
}
generateColumnTypes(pParse, pTabList, pEList);
}
@@ -66649,74 +69777,63 @@
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
/*
-** Forward declaration
-*/
-static int prepSelectStmt(Parse*, Select*);
-
-/*
-** Given a SELECT statement, generate a Table structure that describes
-** the result set of that SELECT.
-*/
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
- Table *pTab;
- int i, j;
- ExprList *pEList;
+** Given a an expression list (which is really the list of expressions
+** that form the result set of a SELECT statement) compute appropriate
+** column names for a table that would hold the expression list.
+**
+** All column names will be unique.
+**
+** Only the column names are computed. Column.zType, Column.zColl,
+** and other fields of Column are zeroed.
+**
+** Return SQLITE_OK on success. If a memory allocation error occurs,
+** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.
+*/
+static int selectColumnsFromExprList(
+ Parse *pParse, /* Parsing context */
+ ExprList *pEList, /* Expr list from which to derive column names */
+ int *pnCol, /* Write the number of columns here */
+ Column **paCol /* Write the new column list here */
+){
+ sqlite3 *db = pParse->db;
+ int i, j, cnt;
Column *aCol, *pCol;
- sqlite3 *db = pParse->db;
-
- if( sqlite3SelectResolve(pParse, pSelect, 0) ){
- return 0;
- }
-
- while( pSelect->pPrior ) pSelect = pSelect->pPrior;
- if( prepSelectStmt(pParse, pSelect) ){
- return 0;
- }
- if( sqlite3SelectResolve(pParse, pSelect, 0) ){
- return 0;
- }
- pTab = sqlite3DbMallocZero(db, sizeof(Table) );
- if( pTab==0 ){
- return 0;
- }
- pTab->nRef = 1;
- pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
- pEList = pSelect->pEList;
- pTab->nCol = pEList->nExpr;
- assert( pTab->nCol>0 );
- pTab->aCol = aCol = sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol);
- for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
- Expr *p;
- char *zType;
- char *zName;
- int nName;
- CollSeq *pColl;
- int cnt;
- NameContext sNC;
-
+ int nCol;
+ Expr *p;
+ char *zName;
+ int nName;
+
+ *pnCol = nCol = pEList->nExpr;
+ aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
+ if( aCol==0 ) return SQLITE_NOMEM;
+ for(i=0, pCol=aCol; i<nCol; i++, pCol++){
/* Get an appropriate name for the column
*/
p = pEList->a[i].pExpr;
assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
zName = sqlite3DbStrDup(db, zName);
- }else if( p->op==TK_COLUMN && p->pTab ){
- /* For columns use the column name name */
- int iCol = p->iColumn;
- if( iCol<0 ) iCol = p->pTab->iPKey;
- zName = sqlite3MPrintf(db, "%s", p->pTab->aCol[iCol].zName);
- }else{
- /* Use the original text of the column expression as its name */
- zName = sqlite3MPrintf(db, "%T", &p->span);
- }
- if( !zName || db->mallocFailed ){
- db->mallocFailed = 1;
- sqlite3_free(zName);
- sqlite3DeleteTable(pTab);
- return 0;
+ }else{
+ Expr *pCol = p;
+ Table *pTab;
+ while( pCol->op==TK_DOT ) pCol = pCol->pRight;
+ if( pCol->op==TK_COLUMN && (pTab = pCol->pTab)!=0 ){
+ /* For columns use the column name name */
+ int iCol = pCol->iColumn;
+ if( iCol<0 ) iCol = pTab->iPKey;
+ zName = sqlite3MPrintf(db, "%s",
+ iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
+ }else{
+ /* Use the original text of the column expression as its name */
+ zName = sqlite3MPrintf(db, "%T", &pCol->span);
+ }
+ }
+ if( db->mallocFailed ){
+ sqlite3DbFree(db, zName);
+ break;
}
sqlite3Dequote(zName);
/* Make sure the column name is unique. If the name is not unique,
@@ -66724,518 +69841,106 @@
*/
nName = strlen(zName);
for(j=cnt=0; j<i; j++){
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
+ char *zNewName;
zName[nName] = 0;
- zName = sqlite3MPrintf(db, "%z:%d", zName, ++cnt);
+ zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
+ sqlite3DbFree(db, zName);
+ zName = zNewName;
j = -1;
if( zName==0 ) break;
}
}
pCol->zName = zName;
-
- /* Get the typename, type affinity, and collating sequence for the
- ** column.
- */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pSrcList = pSelect->pSrc;
- zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
- pCol->zType = zType;
+ }
+ if( db->mallocFailed ){
+ int j;
+ for(j=0; j<i; j++){
+ sqlite3DbFree(db, aCol[j].zName);
+ }
+ sqlite3DbFree(db, aCol);
+ *paCol = 0;
+ *pnCol = 0;
+ return SQLITE_NOMEM;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Add type and collation information to a column list based on
+** a SELECT statement.
+**
+** The column list presumably came from selectColumnNamesFromExprList().
+** The column list has only names, not types or collations. This
+** routine goes through and adds the types and collations.
+**
+** This routine requires that all indentifiers in the SELECT
+** statement be resolved.
+*/
+static void selectAddColumnTypeAndCollation(
+ Parse *pParse, /* Parsing contexts */
+ int nCol, /* Number of columns */
+ Column *aCol, /* List of columns */
+ Select *pSelect /* SELECT used to determine types and collations */
+){
+ sqlite3 *db = pParse->db;
+ NameContext sNC;
+ Column *pCol;
+ CollSeq *pColl;
+ int i;
+ Expr *p;
+ struct ExprList_item *a;
+
+ assert( pSelect!=0 );
+ assert( (pSelect->selFlags & SF_Resolved)!=0 );
+ assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
+ if( db->mallocFailed ) return;
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pSrcList = pSelect->pSrc;
+ a = pSelect->pEList->a;
+ for(i=0, pCol=aCol; i<nCol; i++, pCol++){
+ p = a[i].pExpr;
+ pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
pCol->affinity = sqlite3ExprAffinity(p);
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl ){
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
}
}
- pTab->iPKey = -1;
- return pTab;
-}
-
-/*
-** Prepare a SELECT statement for processing by doing the following
-** things:
-**
-** (1) Make sure VDBE cursor numbers have been assigned to every
-** element of the FROM clause.
-**
-** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
-** defines FROM clause. When views appear in the FROM clause,
-** fill pTabList->a[].pSelect with a copy of the SELECT statement
-** that implements the view. A copy is made of the view's SELECT
-** statement so that we can freely modify or delete that statement
-** without worrying about messing up the presistent representation
-** of the view.
-**
-** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
-** on joins and the ON and USING clause of joins.
-**
-** (4) Scan the list of columns in the result set (pEList) looking
-** for instances of the "*" operator or the TABLE.* operator.
-** If found, expand each "*" to be every column in every table
-** and TABLE.* to be every column in TABLE.
-**
-** Return 0 on success. If there are problems, leave an error message
-** in pParse and return non-zero.
-*/
-static int prepSelectStmt(Parse *pParse, Select *p){
- int i, j, k, rc;
- SrcList *pTabList;
- ExprList *pEList;
- struct SrcList_item *pFrom;
- sqlite3 *db = pParse->db;
-
- if( p==0 || p->pSrc==0 || db->mallocFailed ){
- return 1;
- }
- pTabList = p->pSrc;
- pEList = p->pEList;
-
- /* Make sure cursor numbers have been assigned to all entries in
- ** the FROM clause of the SELECT statement.
- */
- sqlite3SrcListAssignCursors(pParse, p->pSrc);
-
- /* Look up every table named in the FROM clause of the select. If
- ** an entry of the FROM clause is a subquery instead of a table or view,
- ** then create a transient table structure to describe the subquery.
- */
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab;
- if( pFrom->pTab!=0 ){
- /* This statement has already been prepared. There is no need
- ** to go further. */
- assert( i==0 );
- return 0;
- }
- if( pFrom->zName==0 ){
-#ifndef SQLITE_OMIT_SUBQUERY
- /* A sub-query in the FROM clause of a SELECT */
- assert( pFrom->pSelect!=0 );
- if( pFrom->zAlias==0 ){
- pFrom->zAlias =
- sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect);
- }
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab =
- sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
- if( pTab==0 ){
- return 1;
- }
- /* The isEphem flag indicates that the Table structure has been
- ** dynamically allocated and may be freed at any time. In other words,
- ** pTab is not pointing to a persistent table structure that defines
- ** part of the schema. */
- pTab->isEphem = 1;
-#endif
- }else{
- /* An ordinary table or view name in the FROM clause */
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab =
- sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
- if( pTab==0 ){
- return 1;
- }
- pTab->nRef++;
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
- if( pTab->pSelect || IsVirtual(pTab) ){
- /* We reach here if the named table is a really a view */
- if( sqlite3ViewGetColumnNames(pParse, pTab) ){
- return 1;
- }
- /* If pFrom->pSelect!=0 it means we are dealing with a
- ** view within a view. The SELECT structure has already been
- ** copied by the outer view so we can skip the copy step here
- ** in the inner view.
- */
- if( pFrom->pSelect==0 ){
- pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
- }
- }
-#endif
- }
- }
-
- /* Process NATURAL keywords, and ON and USING clauses of joins.
- */
- if( sqliteProcessJoin(pParse, p) ) return 1;
-
- /* For every "*" that occurs in the column list, insert the names of
- ** all columns in all tables. And for every TABLE.* insert the names
- ** of all columns in TABLE. The parser inserted a special expression
- ** with the TK_ALL operator for each "*" that it found in the column list.
- ** The following code just has to locate the TK_ALL expressions and expand
- ** each one to the list of all columns in all tables.
- **
- ** The first loop just checks to see if there are any "*" operators
- ** that need expanding.
- */
- for(k=0; k<pEList->nExpr; k++){
- Expr *pE = pEList->a[k].pExpr;
- if( pE->op==TK_ALL ) break;
- if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
- && pE->pLeft && pE->pLeft->op==TK_ID ) break;
- }
- rc = 0;
- if( k<pEList->nExpr ){
- /*
- ** If we get here it means the result set contains one or more "*"
- ** operators that need to be expanded. Loop through each expression
- ** in the result set and expand them one by one.
- */
- struct ExprList_item *a = pEList->a;
- ExprList *pNew = 0;
- int flags = pParse->db->flags;
- int longNames = (flags & SQLITE_FullColNames)!=0 &&
- (flags & SQLITE_ShortColNames)==0;
-
- for(k=0; k<pEList->nExpr; k++){
- Expr *pE = a[k].pExpr;
- if( pE->op!=TK_ALL &&
- (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
- /* This particular expression does not need to be expanded.
- */
- pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
- if( pNew ){
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
- }else{
- rc = 1;
- }
- a[k].pExpr = 0;
- a[k].zName = 0;
- }else{
- /* This expression is a "*" or a "TABLE.*" and needs to be
- ** expanded. */
- int tableSeen = 0; /* Set to 1 when TABLE matches */
- char *zTName; /* text of name of TABLE */
- if( pE->op==TK_DOT && pE->pLeft ){
- zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
- }else{
- zTName = 0;
- }
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
- char *zTabName = pFrom->zAlias;
- if( zTabName==0 || zTabName[0]==0 ){
- zTabName = pTab->zName;
- }
- assert( zTabName );
- if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
- continue;
- }
- tableSeen = 1;
- for(j=0; j<pTab->nCol; j++){
- Expr *pExpr, *pRight;
- char *zName = pTab->aCol[j].zName;
-
- /* If a column is marked as 'hidden' (currently only possible
- ** for virtual tables), do not include it in the expanded
- ** result-set list.
- */
- if( IsHiddenColumn(&pTab->aCol[j]) ){
- assert(IsVirtual(pTab));
- continue;
- }
-
- if( i>0 ){
- struct SrcList_item *pLeft = &pTabList->a[i-1];
- if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
- columnIndex(pLeft->pTab, zName)>=0 ){
- /* In a NATURAL join, omit the join columns from the
- ** table on the right */
- continue;
- }
- if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
- /* In a join with a USING clause, omit columns in the
- ** using clause from the table on the right. */
- continue;
- }
- }
- pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
- if( pRight==0 ) break;
- setQuotedToken(pParse, &pRight->token, zName);
- if( longNames || pTabList->nSrc>1 ){
- Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
- if( pExpr==0 ) break;
- setQuotedToken(pParse, &pLeft->token, zTabName);
- setToken(&pExpr->span,
- sqlite3MPrintf(db, "%s.%s", zTabName, zName));
- pExpr->span.dyn = 1;
- pExpr->token.z = 0;
- pExpr->token.n = 0;
- pExpr->token.dyn = 0;
- }else{
- pExpr = pRight;
- pExpr->span = pExpr->token;
- pExpr->span.dyn = 0;
- }
- if( longNames ){
- pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
- }else{
- pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
- }
- }
- }
- if( !tableSeen ){
- if( zTName ){
- sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
- }else{
- sqlite3ErrorMsg(pParse, "no tables specified");
- }
- rc = 1;
- }
- sqlite3_free(zTName);
- }
- }
- sqlite3ExprListDelete(pEList);
- p->pEList = pNew;
- }
-#if SQLITE_MAX_COLUMN
- if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many columns in result set");
- rc = SQLITE_ERROR;
- }
-#endif
+}
+
+/*
+** Given a SELECT statement, generate a Table structure that describes
+** the result set of that SELECT.
+*/
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
+ Table *pTab;
+ sqlite3 *db = pParse->db;
+ int savedFlags;
+
+ savedFlags = db->flags;
+ db->flags &= ~SQLITE_FullColNames;
+ db->flags |= SQLITE_ShortColNames;
+ sqlite3SelectPrep(pParse, pSelect, 0);
+ if( pParse->nErr ) return 0;
+ while( pSelect->pPrior ) pSelect = pSelect->pPrior;
+ db->flags = savedFlags;
+ pTab = sqlite3DbMallocZero(db, sizeof(Table) );
+ if( pTab==0 ){
+ return 0;
+ }
+ pTab->db = db;
+ pTab->nRef = 1;
+ pTab->zName = 0;
+ selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
+ selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
+ pTab->iPKey = -1;
if( db->mallocFailed ){
- rc = SQLITE_NOMEM;
- }
- return rc;
-}
-
-/*
-** pE is a pointer to an expression which is a single term in
-** ORDER BY or GROUP BY clause.
-**
-** At the point this routine is called, we already know that the
-** ORDER BY term is not an integer index into the result set. That
-** casee is handled by the calling routine.
-**
-** If pE is a well-formed expression and the SELECT statement
-** is not compound, then return 0. This indicates to the
-** caller that it should sort by the value of the ORDER BY
-** expression.
-**
-** If the SELECT is compound, then attempt to match pE against
-** result set columns in the left-most SELECT statement. Return
-** the index i of the matching column, as an indication to the
-** caller that it should sort by the i-th column. If there is
-** no match, return -1 and leave an error message in pParse.
-*/
-static int matchOrderByTermToExprList(
- Parse *pParse, /* Parsing context for error messages */
- Select *pSelect, /* The SELECT statement with the ORDER BY clause */
- Expr *pE, /* The specific ORDER BY term */
- int idx, /* When ORDER BY term is this */
- int isCompound, /* True if this is a compound SELECT */
- u8 *pHasAgg /* True if expression contains aggregate functions */
-){
- int i; /* Loop counter */
- ExprList *pEList; /* The columns of the result set */
- NameContext nc; /* Name context for resolving pE */
-
- assert( sqlite3ExprIsInteger(pE, &i)==0 );
- pEList = pSelect->pEList;
-
- /* If the term is a simple identifier that try to match that identifier
- ** against a column name in the result set.
- */
- if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){
- sqlite3 *db = pParse->db;
- char *zCol = sqlite3NameFromToken(db, &pE->token);
- if( zCol==0 ){
- return -1;
- }
- for(i=0; i<pEList->nExpr; i++){
- char *zAs = pEList->a[i].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- sqlite3_free(zCol);
- return i+1;
- }
- }
- sqlite3_free(zCol);
- }
-
- /* Resolve all names in the ORDER BY term expression
- */
- memset(&nc, 0, sizeof(nc));
- nc.pParse = pParse;
- nc.pSrcList = pSelect->pSrc;
- nc.pEList = pEList;
- nc.allowAgg = 1;
- nc.nErr = 0;
- if( sqlite3ExprResolveNames(&nc, pE) ){
- if( isCompound ){
- sqlite3ErrorClear(pParse);
- return 0;
- }else{
- return -1;
- }
- }
- if( nc.hasAgg && pHasAgg ){
- *pHasAgg = 1;
- }
-
- /* For a compound SELECT, we need to try to match the ORDER BY
- ** expression against an expression in the result set
- */
- if( isCompound ){
- for(i=0; i<pEList->nExpr; i++){
- if( sqlite3ExprCompare(pEList->a[i].pExpr, pE) ){
- return i+1;
- }
- }
- }
- return 0;
-}
-
-
-/*
-** Analyze and ORDER BY or GROUP BY clause in a simple SELECT statement.
-** Return the number of errors seen.
-**
-** Every term of the ORDER BY or GROUP BY clause needs to be an
-** expression. If any expression is an integer constant, then
-** that expression is replaced by the corresponding
-** expression from the result set.
-*/
-static int processOrderGroupBy(
- Parse *pParse, /* Parsing context. Leave error messages here */
- Select *pSelect, /* The SELECT statement containing the clause */
- ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */
- int isOrder, /* 1 for ORDER BY. 0 for GROUP BY */
- u8 *pHasAgg /* Set to TRUE if any term contains an aggregate */
-){
- int i;
- sqlite3 *db = pParse->db;
- ExprList *pEList;
-
- if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
-#if SQLITE_MAX_COLUMN
- if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- const char *zType = isOrder ? "ORDER" : "GROUP";
- sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
- return 1;
- }
-#endif
- pEList = pSelect->pEList;
- if( pEList==0 ){
- return 0;
- }
- for(i=0; i<pOrderBy->nExpr; i++){
- int iCol;
- Expr *pE = pOrderBy->a[i].pExpr;
- if( sqlite3ExprIsInteger(pE, &iCol) ){
- if( iCol<=0 || iCol>pEList->nExpr ){
- const char *zType = isOrder ? "ORDER" : "GROUP";
- sqlite3ErrorMsg(pParse,
- "%r %s BY term out of range - should be "
- "between 1 and %d", i+1, zType, pEList->nExpr);
- return 1;
- }
- }else{
- iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg);
- if( iCol<0 ){
- return 1;
- }
- }
- if( iCol>0 ){
- CollSeq *pColl = pE->pColl;
- int flags = pE->flags & EP_ExpCollate;
- sqlite3ExprDelete(pE);
- pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr);
- pOrderBy->a[i].pExpr = pE;
- if( pE && pColl && flags ){
- pE->pColl = pColl;
- pE->flags |= flags;
- }
- }
- }
- return 0;
-}
-
-/*
-** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return
-** the number of errors seen.
-**
-** If iTable>0 then make the N-th term of the ORDER BY clause refer to
-** the N-th column of table iTable.
-**
-** If iTable==0 then transform each term of the ORDER BY clause to refer
-** to a column of the result set by number.
-*/
-static int processCompoundOrderBy(
- Parse *pParse, /* Parsing context. Leave error messages here */
- Select *pSelect /* The SELECT statement containing the ORDER BY */
-){
- int i;
- ExprList *pOrderBy;
- ExprList *pEList;
- sqlite3 *db;
- int moreToDo = 1;
-
- pOrderBy = pSelect->pOrderBy;
- if( pOrderBy==0 ) return 0;
- db = pParse->db;
-#if SQLITE_MAX_COLUMN
- if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
- return 1;
- }
-#endif
- for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].done = 0;
- }
- while( pSelect->pPrior ){
- pSelect = pSelect->pPrior;
- }
- while( pSelect && moreToDo ){
- moreToDo = 0;
- pEList = pSelect->pEList;
- if( pEList==0 ){
- return 1;
- }
- for(i=0; i<pOrderBy->nExpr; i++){
- int iCol = -1;
- Expr *pE, *pDup;
- if( pOrderBy->a[i].done ) continue;
- pE = pOrderBy->a[i].pExpr;
- if( sqlite3ExprIsInteger(pE, &iCol) ){
- if( iCol<0 || iCol>pEList->nExpr ){
- sqlite3ErrorMsg(pParse,
- "%r ORDER BY term out of range - should be "
- "between 1 and %d", i+1, pEList->nExpr);
- return 1;
- }
- }else{
- pDup = sqlite3ExprDup(db, pE);
- if( !db->mallocFailed ){
- assert(pDup);
- iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
- }
- sqlite3ExprDelete(pDup);
- if( iCol<0 ){
- return 1;
- }
- }
- if( iCol>0 ){
- pE->op = TK_INTEGER;
- pE->flags |= EP_IntValue;
- pE->iTable = iCol;
- pOrderBy->a[i].done = 1;
- }else{
- moreToDo = 1;
- }
- }
- pSelect = pSelect->pNext;
- }
- for(i=0; i<pOrderBy->nExpr; i++){
- if( pOrderBy->a[i].done==0 ){
- sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
- "column in the result set", i+1);
- return 1;
- }
- }
- return 0;
+ sqlite3DeleteTable(pTab);
+ return 0;
+ }
+ return pTab;
}
/*
** Get a VDBE for the given parser context. Create a new one if necessary.
@@ -67390,19 +70095,19 @@
Select *pPrior; /* Another SELECT immediately to our left */
Vdbe *v; /* Generate code to this VDBE */
SelectDest dest; /* Alternative data destination */
Select *pDelete = 0; /* Chain of simple selects to delete */
+ sqlite3 *db; /* Database connection */
/* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
*/
- if( p==0 || p->pPrior==0 ){
- rc = 1;
- goto multi_select_end;
- }
+ assert( p && p->pPrior ); /* Calling function guarantees this much */
+ db = pParse->db;
pPrior = p->pPrior;
assert( pPrior->pRightmost!=pPrior );
assert( pPrior->pRightmost==p->pRightmost );
+ dest = *pDest;
if( pPrior->pOrderBy ){
sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
selectOpName(p->op));
rc = 1;
@@ -67414,19 +70119,13 @@
rc = 1;
goto multi_select_end;
}
- /* Make sure we have a valid query engine. If not, create a new one.
- */
v = sqlite3GetVdbe(pParse);
- if( v==0 ){
- rc = 1;
- goto multi_select_end;
- }
+ assert( v!=0 ); /* The VDBE already created by calling function */
/* Create the destination temporary table if necessary
*/
- dest = *pDest;
if( dest.eDest==SRT_EphemTab ){
assert( p->pEList );
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr);
dest.eDest = SRT_Table;
@@ -67456,9 +70155,9 @@
int addr = 0;
assert( !pPrior->pLimit );
pPrior->pLimit = p->pLimit;
pPrior->pOffset = p->pOffset;
- rc = sqlite3Select(pParse, pPrior, &dest, 0, 0, 0);
+ rc = sqlite3Select(pParse, pPrior, &dest);
p->pLimit = 0;
p->pOffset = 0;
if( rc ){
goto multi_select_end;
@@ -67469,9 +70168,9 @@
if( p->iLimit ){
addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);
VdbeComment((v, "Jump ahead if LIMIT reached"));
}
- rc = sqlite3Select(pParse, p, &dest, 0, 0, 0);
+ rc = sqlite3Select(pParse, p, &dest);
pDelete = p->pPrior;
p->pPrior = pPrior;
if( rc ){
goto multi_select_end;
@@ -67504,43 +70203,43 @@
assert( p->pOrderBy==0 );
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
assert( p->addrOpenEphm[0] == -1 );
p->addrOpenEphm[0] = addr;
- p->pRightmost->usesEphm = 1;
+ p->pRightmost->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
}
/* Code the SELECT statements to our left
*/
assert( !pPrior->pOrderBy );
sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
- rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0);
+ rc = sqlite3Select(pParse, pPrior, &uniondest);
if( rc ){
goto multi_select_end;
}
/* Code the current SELECT statement
*/
- switch( p->op ){
- case TK_EXCEPT: op = SRT_Except; break;
- case TK_UNION: op = SRT_Union; break;
- case TK_ALL: op = SRT_Table; break;
- }
- p->pPrior = 0;
- p->disallowOrderBy = 0;
+ if( p->op==TK_EXCEPT ){
+ op = SRT_Except;
+ }else{
+ assert( p->op==TK_UNION );
+ op = SRT_Union;
+ }
+ p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
uniondest.eDest = op;
- rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0);
+ rc = sqlite3Select(pParse, p, &uniondest);
/* Query flattening in sqlite3Select() might refill p->pOrderBy.
** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
- sqlite3ExprListDelete(p->pOrderBy);
+ sqlite3ExprListDelete(db, p->pOrderBy);
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
- sqlite3ExprDelete(p->pLimit);
+ sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
p->iLimit = 0;
p->iOffset = 0;
@@ -67554,9 +70253,9 @@
*/
if( dest.eDest!=priorOp || unionTab!=dest.iParm ){
int iCont, iBreak, iStart;
assert( p->pEList );
- if( dest.eDest==SRT_Callback ){
+ if( dest.eDest==SRT_Output ){
Select *pFirst = p;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, 0, pFirst->pEList);
}
@@ -67592,15 +70291,15 @@
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
assert( p->addrOpenEphm[0] == -1 );
p->addrOpenEphm[0] = addr;
- p->pRightmost->usesEphm = 1;
+ p->pRightmost->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
- rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0);
+ rc = sqlite3Select(pParse, pPrior, &intersectdest);
if( rc ){
goto multi_select_end;
}
@@ -67614,12 +70313,12 @@
p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
intersectdest.iParm = tab2;
- rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0);
+ rc = sqlite3Select(pParse, p, &intersectdest);
pDelete = p->pPrior;
p->pPrior = pPrior;
- sqlite3ExprDelete(p->pLimit);
+ sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
if( rc ){
goto multi_select_end;
@@ -67628,9 +70327,9 @@
/* Generate code to take the intersection of the two temporary
** tables.
*/
assert( p->pEList );
- if( dest.eDest==SRT_Callback ){
+ if( dest.eDest==SRT_Output ){
Select *pFirst = p;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, 0, pFirst->pEList);
}
@@ -67661,9 +70360,9 @@
** SELECT statements to the left always skip this part. The right-most
** SELECT might also skip this part if it has no ORDER BY clause and
** no temp tables are required.
*/
- if( p->usesEphm ){
+ if( p->selFlags & SF_UsesEphemeral ){
int i; /* Loop counter */
KeyInfo *pKeyInfo; /* Collating sequence for the result set */
Select *pLoop; /* For looping through SELECT statements */
CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
@@ -67670,22 +70369,22 @@
int nCol; /* Number of columns in result set */
assert( p->pRightmost==p );
nCol = p->pEList->nExpr;
- pKeyInfo = sqlite3DbMallocZero(pParse->db,
+ pKeyInfo = sqlite3DbMallocZero(db,
sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));
if( !pKeyInfo ){
rc = SQLITE_NOMEM;
goto multi_select_end;
}
- pKeyInfo->enc = ENC(pParse->db);
+ pKeyInfo->enc = ENC(db);
pKeyInfo->nField = nCol;
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
*apColl = multiSelectCollSeq(pParse, p, i);
if( 0==*apColl ){
- *apColl = pParse->db->pDfltColl;
+ *apColl = db->pDfltColl;
}
}
for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
@@ -67701,15 +70400,15 @@
sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO);
pLoop->addrOpenEphm[i] = -1;
}
}
- sqlite3_free(pKeyInfo);
+ sqlite3DbFree(db, pKeyInfo);
}
multi_select_end:
pDest->iMem = dest.iMem;
pDest->nMem = dest.nMem;
- sqlite3SelectDelete(pDelete);
+ sqlite3SelectDelete(db, pDelete);
return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
@@ -67824,11 +70523,10 @@
break;
}
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
- /* Send the data to the callback function or to a subroutine. In the
- ** case of a subroutine, the subroutine itself is responsible for
- ** popping the data from the stack.
+ /* The results are stored in a sequence of registers
+ ** starting at pDest->iMem. Then the co-routine yields.
*/
case SRT_Coroutine: {
if( pDest->iMem==0 ){
pDest->iMem = sqlite3GetTempRange(pParse, pIn->nMem);
@@ -67838,9 +70536,13 @@
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);
break;
}
- case SRT_Callback: {
+ /* Results are stored in a sequence of registers. Then the
+ ** OP_ResultRow opcode is used to cause sqlite3_step() to return
+ ** the next row of result.
+ */
+ case SRT_Output: {
sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem);
sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem);
break;
}
@@ -67956,8 +70658,9 @@
** actually called using Gosub and they do not Return. EofA and EofB loop
** until all data is exhausted then jump to the "end" labe. AltB, AeqB,
** and AgtB jump to either L2 or to one of EofA or EofB.
*/
+#ifndef SQLITE_OMIT_COMPOUND_SELECT
static int multiSelectOrderBy(
Parse *pParse, /* Parsing context */
Select *p, /* The right-most of SELECTs to be coded */
SelectDest *pDest /* What to do with query results */
@@ -67990,17 +70693,17 @@
int labelCmpr; /* Label for the start of the merge algorithm */
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 nOrderBy; /* Number of terms in the ORDER BY clause */
int *aPermute; /* Mapping from ORDER BY terms to result set columns */
- u8 NotUsed; /* Dummy variables */
assert( p->pOrderBy!=0 );
+ assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */
db = pParse->db;
v = pParse->pVdbe;
if( v==0 ) return SQLITE_NOMEM;
labelEnd = sqlite3VdbeMakeLabel(v);
@@ -68013,11 +70716,8 @@
pPrior = p->pPrior;
assert( pPrior->pOrderBy==0 );
pOrderBy = p->pOrderBy;
assert( pOrderBy );
- if( processCompoundOrderBy(pParse, p) ){
- return SQLITE_ERROR;
- }
nOrderBy = pOrderBy->nExpr;
/* For operators other than UNION ALL we have to make sure that
** the ORDER BY clause covers every term of the result set. Add
@@ -68024,21 +70724,20 @@
** terms to the ORDER BY clause as necessary.
*/
if( op!=TK_ALL ){
for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
- for(j=0; j<nOrderBy; j++){
- Expr *pTerm = pOrderBy->a[j].pExpr;
- assert( pTerm->op==TK_INTEGER );
- assert( (pTerm->flags & EP_IntValue)!=0 );
- if( pTerm->iTable==i ) break;
+ struct ExprList_item *pItem;
+ for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
+ assert( pItem->iCol>0 );
+ if( pItem->iCol==i ) break;
}
if( j==nOrderBy ){
Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0);
if( pNew==0 ) return SQLITE_NOMEM;
pNew->flags |= EP_IntValue;
pNew->iTable = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0);
- nOrderBy++;
+ pOrderBy->a[nOrderBy++].iCol = i;
}
}
}
@@ -68050,14 +70749,12 @@
** collation.
*/
aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy);
if( aPermute ){
- for(i=0; i<nOrderBy; i++){
- Expr *pTerm = pOrderBy->a[i].pExpr;
- assert( pTerm->op==TK_INTEGER );
- assert( (pTerm->flags & EP_IntValue)!=0 );
- aPermute[i] = pTerm->iTable-1;
- assert( aPermute[i]>=0 && aPermute[i]<p->pEList->nExpr );
+ struct ExprList_item *pItem;
+ for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
+ assert( pItem->iCol>0 && pItem->iCol<=p->pEList->nExpr );
+ aPermute[i] = pItem->iCol - 1;
}
pKeyMerge =
sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
if( pKeyMerge ){
@@ -68094,9 +70791,9 @@
if( op==TK_ALL ){
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,
sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
@@ -68114,11 +70811,11 @@
/* Separate the left and the right query from one another
*/
p->pPrior = 0;
pPrior->pRightmost = 0;
- processOrderGroupBy(pParse, p, p->pOrderBy, 1, &NotUsed);
+ sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
if( pPrior->pPrior==0 ){
- processOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, 1, &NotUsed);
+ sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
}
/* Compute the limit registers */
computeLimitRegisters(pParse, p, labelEnd);
@@ -68130,11 +70827,11 @@
sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB);
}else{
regLimitA = regLimitB = 0;
}
- sqlite3ExprDelete(p->pLimit);
+ sqlite3ExprDelete(db, p->pLimit);
p->pLimit = 0;
- sqlite3ExprDelete(p->pOffset);
+ sqlite3ExprDelete(db, p->pOffset);
p->pOffset = 0;
regAddrA = ++pParse->nMem;
regEofA = ++pParse->nMem;
@@ -68156,9 +70853,9 @@
** left of the compound operator - the "A" select.
*/
VdbeNoopComment((v, "Begin coroutine for left SELECT"));
pPrior->iLimit = regLimitA;
- sqlite3Select(pParse, pPrior, &destA, 0, 0, 0);
+ sqlite3Select(pParse, pPrior, &destA);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
VdbeNoopComment((v, "End coroutine for left SELECT"));
@@ -68170,9 +70867,9 @@
savedLimit = p->iLimit;
savedOffset = p->iOffset;
p->iLimit = regLimitB;
p->iOffset = 0;
- sqlite3Select(pParse, p, &destB, 0, 0, 0);
+ sqlite3Select(pParse, p, &destB);
p->iLimit = savedLimit;
p->iOffset = savedOffset;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
@@ -68285,9 +70982,9 @@
sqlite3VdbeResolveLabel(v, labelEnd);
/* Set the number of output columns
*/
- if( pDest->eDest==SRT_Callback ){
+ if( pDest->eDest==SRT_Output ){
Select *pFirst = pPrior;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, 0, pFirst->pEList);
}
@@ -68294,18 +70991,19 @@
/* Reassembly the compound query so that it will be freed correctly
** by the calling function */
if( p->pPrior ){
- sqlite3SelectDelete(p->pPrior);
+ sqlite3SelectDelete(db, p->pPrior);
}
p->pPrior = pPrior;
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
return SQLITE_OK;
}
-
-#ifndef SQLITE_OMIT_VIEW
+#endif
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* Forward Declarations */
static void substExprList(sqlite3*, ExprList*, int, ExprList*);
static void substSelect(sqlite3*, Select *, int, ExprList *);
@@ -68378,19 +71076,28 @@
Select *p, /* SELECT statement in which to make substitutions */
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);
substExprList(db, p->pOrderBy, iTable, pEList);
substExpr(db, p->pHaving, iTable, pEList);
substExpr(db, p->pWhere, iTable, pEList);
substSelect(db, p->pPrior, iTable, pEList);
-}
-#endif /* !defined(SQLITE_OMIT_VIEW) */
-
-#ifndef SQLITE_OMIT_VIEW
+ 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) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries in order to speed
** execution. It returns 1 if it makes changes and 0 if no flattening
** occurs.
@@ -68422,10 +71129,10 @@
** (1) The subquery and the outer query do not both use aggregates.
**
** (2) The subquery is not an aggregate or the outer query is not a join.
**
-** (3) The subquery is not the right operand of a left outer join, or
-** the subquery is not itself a join. (Ticket #306)
+** (3) The subquery is not the right operand of a left outer join
+** (Originally ticket #306. Strenghtened by ticket #3300)
**
** (4) The subquery is not DISTINCT or the outer query is not a join.
**
** (5) The subquery is not DISTINCT or the outer query does not use
@@ -68445,10 +71152,10 @@
** use LIMIT.
**
** (11) The subquery and the outer query do not both have ORDER BY clauses.
**
-** (12) The subquery is not the right term of a LEFT OUTER JOIN or the
-** subquery has no WHERE clause. (added by ticket #350)
+** (12) Not implemented. Subsumed into restriction (3). Was previously
+** a separate restriction deriving from ticket #350.
**
** (13) The subquery and outer query do not both use LIMIT
**
** (14) The subquery does not use OFFSET
@@ -68475,8 +71182,11 @@
**
** (18) If the sub-query is a compound select, then all terms of the
** ORDER by clause of the parent must be simple references to
** columns of the sub-query.
+**
+** (19) The subquery does not use LIMIT or the outer query does not
+** have a WHERE clause.
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
@@ -68530,19 +71240,23 @@
if( p->pRightmost && pSub->pLimit && pSub->pOrderBy ){
return 0; /* Restriction (15) */
}
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
- if( (pSub->isDistinct || pSub->pLimit)
+ if( ((pSub->selFlags & SF_Distinct)!=0 || pSub->pLimit)
&& (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */
return 0;
}
- if( p->isDistinct && subqueryIsAgg ) return 0; /* Restriction (6) */
- if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){
+ if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
+ return 0; /* Restriction (6) */
+ }
+ if( p->pOrderBy && pSub->pOrderBy ){
return 0; /* Restriction (11) */
}
if( isAgg && pSub->pOrderBy ) return 0; /* Restriction (16) */
-
- /* Restriction 3: If the subquery is a join, make sure the subquery is
+ if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
+
+ /* OBSOLETE COMMENT 1:
+ ** Restriction 3: If the subquery is a join, make sure the subquery is
** not used as the right operand of an outer join. Examples of why this
** is not allowed:
**
** t1 LEFT OUTER JOIN (t2 JOIN t3)
@@ -68551,14 +71265,11 @@
**
** (t1 LEFT OUTER JOIN t2) JOIN t3
**
** which is not at all the same thing.
- */
- if( pSubSrc->nSrc>1 && (pSubitem->jointype & JT_OUTER)!=0 ){
- return 0;
- }
-
- /* Restriction 12: If the subquery is the right operand of a left outer
+ **
+ ** OBSOLETE COMMENT 2:
+ ** Restriction 12: If the subquery is the right operand of a left outer
** join, make sure the subquery has no WHERE clause.
** An examples of why this is not allowed:
**
** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
@@ -68568,10 +71279,15 @@
** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
**
** But the t2.x>0 test will always fail on a NULL row of t2, which
** effectively converts the OUTER JOIN into an INNER JOIN.
- */
- if( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){
+ **
+ ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
+ ** Ticket #3300 shows that flattening the right term of a LEFT JOIN
+ ** is fraught with danger. Best to avoid the whole thing. If the
+ ** subquery is the right term of a LEFT JOIN, then do not flatten.
+ */
+ if( (pSubitem->jointype & JT_OUTER)!=0 ){
return 0;
}
/* Restriction 17: If the sub-query is a compound SELECT, then it must
@@ -68579,13 +71295,13 @@
** that make up the compound SELECT are allowed to be aggregate or distinct
** queries.
*/
if( pSub->pPrior ){
- if( p->pPrior || isAgg || p->isDistinct || pSrc->nSrc!=1 ){
+ if( p->pPrior || isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
return 0;
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
- if( pSub1->isAgg || pSub1->isDistinct
+ if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
|| (pSub1->pPrior && pSub1->op!=TK_ALL)
|| !pSub1->pSrc || pSub1->pSrc->nSrc!=1
){
return 0;
@@ -68595,22 +71311,23 @@
/* Restriction 18. */
if( p->pOrderBy ){
int ii;
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
- Expr *pExpr = p->pOrderBy->a[ii].pExpr;
- if( pExpr->op!=TK_COLUMN || pExpr->iTable!=iParent ){
- return 0;
- }
- }
- }
- }
-
+ if( p->pOrderBy->a[ii].iCol==0 ) return 0;
+ }
+ }
+ }
+
+ /***** If we reach this point, flattening is permitted. *****/
+
+ /* Authorize the subquery */
pParse->zAuthContext = pSubitem->zName;
sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0);
pParse->zAuthContext = zSavedAuthContext;
- /* If the sub-query is a compound SELECT statement, then it must be
- ** a UNION ALL and the parent query must be of the form:
+ /* If the sub-query is a compound SELECT statement, then (by restrictions
+ ** 17 and 18 above) it must be a UNION ALL and the parent query must
+ ** be of the form:
**
** SELECT <expr-list> FROM (<sub-query>) <where-clause>
**
** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
@@ -68640,10 +71357,10 @@
p->pRightmost = 0;
pNew->pRightmost = 0;
}
- /* If we reach this point, it means flattening is permitted for the
- ** iFrom-th entry of the FROM clause in the outer query.
+ /* Begin flattening the iFrom-th entry of the FROM clause
+ ** in the outer query.
*/
pSub = pSub1 = pSubitem->pSelect;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc = pSubSrc->nSrc;
@@ -68659,19 +71376,33 @@
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
if( pSrc ){
+ Table *pTabToDel;
pSubitem = &pSrc->a[iFrom];
nSubSrc = pSubSrc->nSrc;
jointype = pSubitem->jointype;
- sqlite3DeleteTable(pSubitem->pTab);
- sqlite3_free(pSubitem->zDatabase);
- sqlite3_free(pSubitem->zName);
- sqlite3_free(pSubitem->zAlias);
- pSubitem->pTab = 0;
+ sqlite3DbFree(db, pSubitem->zDatabase);
+ sqlite3DbFree(db, pSubitem->zName);
+ sqlite3DbFree(db, pSubitem->zAlias);
pSubitem->zDatabase = 0;
pSubitem->zName = 0;
pSubitem->zAlias = 0;
+
+ /* If the FROM element is a subquery, defer deleting the Table
+ ** object associated with that subquery until code generation is
+ ** complete, since there may still exist Expr.pTab entires that
+ ** refer to the subquery even after flattening. Ticket #3346.
+ */
+ if( (pTabToDel = pSubitem->pTab)!=0 ){
+ if( pTabToDel->nRef==1 ){
+ pTabToDel->pNextZombie = pParse->pZombieTab;
+ pParse->pZombieTab = pTabToDel;
+ }else{
+ pTabToDel->nRef--;
+ }
+ }
+ pSubitem->pTab = 0;
}
if( nSubSrc!=1 || !pSrc ){
int extra = nSubSrc - 1;
for(i=(pSrc?1:0); i<nSubSrc; i++){
@@ -68745,9 +71476,9 @@
/* The flattened query is distinct if either the inner or the
** outer query is distinct.
*/
- pParent->isDistinct = pParent->isDistinct || pSub->isDistinct;
+ pParent->selFlags |= pSub->selFlags & SF_Distinct;
/*
** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
**
@@ -68762,13 +71493,13 @@
/* Finially, delete what is left of the subquery and return
** success.
*/
- sqlite3SelectDelete(pSub1);
+ sqlite3SelectDelete(db, pSub1);
return 1;
}
-#endif /* SQLITE_OMIT_VIEW */
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
** Analyze the SELECT statement passed as an argument to see if it
** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
@@ -68798,135 +71529,401 @@
return WHERE_ORDERBY_NORMAL;
}
/*
-** This routine resolves any names used in the result set of the
-** supplied SELECT statement. If the SELECT statement being resolved
-** is a sub-select, then pOuterNC is a pointer to the NameContext
-** of the parent SELECT.
-*/
-SQLITE_PRIVATE int sqlite3SelectResolve(
- Parse *pParse, /* The parser context */
- Select *p, /* The SELECT statement being coded. */
- NameContext *pOuterNC /* The outer name context. May be NULL. */
-){
- ExprList *pEList; /* Result set. */
- int i; /* For-loop variable used in multiple places */
- NameContext sNC; /* Local name-context */
- ExprList *pGroupBy; /* The group by clause */
-
- /* If this routine has run before, return immediately. */
- if( p->isResolved ){
- assert( !pOuterNC );
- return SQLITE_OK;
- }
- p->isResolved = 1;
-
- /* If there have already been errors, do nothing. */
- if( pParse->nErr>0 ){
- return SQLITE_ERROR;
- }
-
- /* Prepare the select statement. This call will allocate all cursors
- ** required to handle the tables and subqueries in the FROM clause.
- */
- if( prepSelectStmt(pParse, p) ){
- return SQLITE_ERROR;
- }
-
- /* Resolve the expressions in the LIMIT and OFFSET clauses. These
- ** are not allowed to refer to any names, so pass an empty NameContext.
- */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- if( sqlite3ExprResolveNames(&sNC, p->pLimit) ||
- sqlite3ExprResolveNames(&sNC, p->pOffset) ){
- return SQLITE_ERROR;
- }
-
- /* Set up the local name-context to pass to ExprResolveNames() to
- ** resolve the expression-list.
- */
- sNC.allowAgg = 1;
- sNC.pSrcList = p->pSrc;
- sNC.pNext = pOuterNC;
-
- /* Resolve names in the result set. */
+** 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:
+**
+** (1) Make sure VDBE cursor numbers have been assigned to every
+** element of the FROM clause.
+**
+** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
+** defines FROM clause. When views appear in the FROM clause,
+** fill pTabList->a[].pSelect with a copy of the SELECT statement
+** that implements the view. A copy is made of the view's SELECT
+** statement so that we can freely modify or delete that statement
+** without worrying about messing up the presistent representation
+** of the view.
+**
+** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
+** on joins and the ON and USING clause of joins.
+**
+** (4) Scan the list of columns in the result set (pEList) looking
+** for instances of the "*" operator or the TABLE.* operator.
+** If found, expand each "*" to be every column in every table
+** and TABLE.* to be every column in TABLE.
+**
+*/
+static int selectExpander(Walker *pWalker, Select *p){
+ Parse *pParse = pWalker->pParse;
+ int i, j, k;
+ SrcList *pTabList;
+ ExprList *pEList;
+ struct SrcList_item *pFrom;
+ sqlite3 *db = pParse->db;
+
+ if( db->mallocFailed ){
+ return WRC_Abort;
+ }
+ if( p->pSrc==0 || (p->selFlags & SF_Expanded)!=0 ){
+ return WRC_Prune;
+ }
+ p->selFlags |= SF_Expanded;
+ pTabList = p->pSrc;
pEList = p->pEList;
- if( !pEList ) return SQLITE_ERROR;
- for(i=0; i<pEList->nExpr; i++){
- Expr *pX = pEList->a[i].pExpr;
- if( sqlite3ExprResolveNames(&sNC, pX) ){
- return SQLITE_ERROR;
- }
- }
-
- /* If there are no aggregate functions in the result-set, and no GROUP BY
- ** expression, do not allow aggregates in any of the other expressions.
- */
- assert( !p->isAgg );
- pGroupBy = p->pGroupBy;
- if( pGroupBy || sNC.hasAgg ){
- p->isAgg = 1;
- }else{
- sNC.allowAgg = 0;
- }
-
- /* If a HAVING clause is present, then there must be a GROUP BY clause.
- */
- if( p->pHaving && !pGroupBy ){
- sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- return SQLITE_ERROR;
- }
-
- /* Add the expression list to the name-context before parsing the
- ** other expressions in the SELECT statement. This is so that
- ** expressions in the WHERE clause (etc.) can refer to expressions by
- ** aliases in the result set.
- **
- ** Minor point: If this is the case, then the expression will be
- ** re-evaluated for each reference to it.
- */
- sNC.pEList = p->pEList;
- if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
- sqlite3ExprResolveNames(&sNC, p->pHaving) ){
- return SQLITE_ERROR;
- }
- if( p->pPrior==0 ){
- if( processOrderGroupBy(pParse, p, p->pOrderBy, 1, &sNC.hasAgg) ){
- return SQLITE_ERROR;
- }
- }
- if( processOrderGroupBy(pParse, p, pGroupBy, 0, &sNC.hasAgg) ){
- return SQLITE_ERROR;
- }
-
- if( pParse->db->mallocFailed ){
- return SQLITE_NOMEM;
- }
-
- /* Make sure the GROUP BY clause does not contain aggregate functions.
- */
- if( pGroupBy ){
- struct ExprList_item *pItem;
-
- for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
- if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
- sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in "
- "the GROUP BY clause");
- return SQLITE_ERROR;
- }
- }
- }
-
- /* If this is one SELECT of a compound, be sure to resolve names
- ** in the other SELECTs.
- */
- if( p->pPrior ){
- return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC);
- }else{
- return SQLITE_OK;
- }
+
+ /* Make sure cursor numbers have been assigned to all entries in
+ ** the FROM clause of the SELECT statement.
+ */
+ sqlite3SrcListAssignCursors(pParse, pTabList);
+
+ /* Look up every table named in the FROM clause of the select. If
+ ** an entry of the FROM clause is a subquery instead of a table or view,
+ ** then create a transient table structure to describe the subquery.
+ */
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab;
+ if( pFrom->pTab!=0 ){
+ /* This statement has already been prepared. There is no need
+ ** to go further. */
+ assert( i==0 );
+ return WRC_Prune;
+ }
+ if( pFrom->zName==0 ){
+#ifndef SQLITE_OMIT_SUBQUERY
+ Select *pSel = pFrom->pSelect;
+ /* A sub-query in the FROM clause of a SELECT */
+ assert( pSel!=0 );
+ assert( pFrom->pTab==0 );
+ sqlite3WalkSelect(pWalker, pSel);
+ pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
+ if( pTab==0 ) return WRC_Abort;
+ pTab->db = db;
+ pTab->nRef = 1;
+ pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
+ while( pSel->pPrior ){ pSel = pSel->pPrior; }
+ selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
+ pTab->iPKey = -1;
+ pTab->tabFlags |= TF_Ephemeral;
+#endif
+ }else{
+ /* An ordinary table or view name in the FROM clause */
+ assert( pFrom->pTab==0 );
+ pFrom->pTab = pTab =
+ sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
+ if( pTab==0 ) return WRC_Abort;
+ pTab->nRef++;
+#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
+ if( pTab->pSelect || IsVirtual(pTab) ){
+ /* We reach here if the named table is a really a view */
+ if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
+
+ /* If pFrom->pSelect!=0 it means we are dealing with a
+ ** view within a view. The SELECT structure has already been
+ ** copied by the outer view so we can skip the copy step here
+ ** in the inner view.
+ */
+ if( pFrom->pSelect==0 ){
+ pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
+ sqlite3WalkSelect(pWalker, pFrom->pSelect);
+ }
+ }
+#endif
+ }
+
+ /* 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.
+ */
+ if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+ return WRC_Abort;
+ }
+
+ /* For every "*" that occurs in the column list, insert the names of
+ ** all columns in all tables. And for every TABLE.* insert the names
+ ** of all columns in TABLE. The parser inserted a special expression
+ ** with the TK_ALL operator for each "*" that it found in the column list.
+ ** The following code just has to locate the TK_ALL expressions and expand
+ ** each one to the list of all columns in all tables.
+ **
+ ** The first loop just checks to see if there are any "*" operators
+ ** that need expanding.
+ */
+ for(k=0; k<pEList->nExpr; k++){
+ Expr *pE = pEList->a[k].pExpr;
+ if( pE->op==TK_ALL ) break;
+ if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
+ && pE->pLeft && pE->pLeft->op==TK_ID ) break;
+ }
+ if( k<pEList->nExpr ){
+ /*
+ ** If we get here it means the result set contains one or more "*"
+ ** operators that need to be expanded. Loop through each expression
+ ** in the result set and expand them one by one.
+ */
+ struct ExprList_item *a = pEList->a;
+ ExprList *pNew = 0;
+ int flags = pParse->db->flags;
+ int longNames = (flags & SQLITE_FullColNames)!=0
+ && (flags & SQLITE_ShortColNames)==0;
+
+ for(k=0; k<pEList->nExpr; k++){
+ Expr *pE = a[k].pExpr;
+ if( pE->op!=TK_ALL &&
+ (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
+ /* This particular expression does not need to be expanded.
+ */
+ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
+ if( pNew ){
+ pNew->a[pNew->nExpr-1].zName = a[k].zName;
+ }
+ a[k].pExpr = 0;
+ a[k].zName = 0;
+ }else{
+ /* This expression is a "*" or a "TABLE.*" and needs to be
+ ** expanded. */
+ int tableSeen = 0; /* Set to 1 when TABLE matches */
+ char *zTName; /* text of name of TABLE */
+ if( pE->op==TK_DOT && pE->pLeft ){
+ zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
+ }else{
+ zTName = 0;
+ }
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab = pFrom->pTab;
+ char *zTabName = pFrom->zAlias;
+ if( zTabName==0 || zTabName[0]==0 ){
+ zTabName = pTab->zName;
+ }
+ if( db->mallocFailed ) break;
+ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+ continue;
+ }
+ tableSeen = 1;
+ for(j=0; j<pTab->nCol; j++){
+ Expr *pExpr, *pRight;
+ char *zName = pTab->aCol[j].zName;
+
+ /* If a column is marked as 'hidden' (currently only possible
+ ** for virtual tables), do not include it in the expanded
+ ** result-set list.
+ */
+ if( IsHiddenColumn(&pTab->aCol[j]) ){
+ assert(IsVirtual(pTab));
+ continue;
+ }
+
+ if( i>0 ){
+ struct SrcList_item *pLeft = &pTabList->a[i-1];
+ if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
+ columnIndex(pLeft->pTab, zName)>=0 ){
+ /* In a NATURAL join, omit the join columns from the
+ ** table on the right */
+ continue;
+ }
+ if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
+ /* In a join with a USING clause, omit columns in the
+ ** using clause from the table on the right. */
+ continue;
+ }
+ }
+ pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+ if( pRight==0 ) break;
+ setQuotedToken(pParse, &pRight->token, zName);
+ if( longNames || pTabList->nSrc>1 ){
+ Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ if( pExpr==0 ) break;
+ setQuotedToken(pParse, &pLeft->token, zTabName);
+ setToken(&pExpr->span,
+ sqlite3MPrintf(db, "%s.%s", zTabName, zName));
+ pExpr->span.dyn = 1;
+ pExpr->token.z = 0;
+ pExpr->token.n = 0;
+ pExpr->token.dyn = 0;
+ }else{
+ pExpr = pRight;
+ pExpr->span = pExpr->token;
+ pExpr->span.dyn = 0;
+ }
+ if( longNames ){
+ pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
+ }else{
+ pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
+ }
+ }
+ }
+ if( !tableSeen ){
+ if( zTName ){
+ sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
+ }else{
+ sqlite3ErrorMsg(pParse, "no tables specified");
+ }
+ }
+ sqlite3DbFree(db, zTName);
+ }
+ }
+ sqlite3ExprListDelete(db, pEList);
+ p->pEList = pNew;
+ }
+#if SQLITE_MAX_COLUMN
+ if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
+ sqlite3ErrorMsg(pParse, "too many columns in result set");
+ }
+#endif
+ return WRC_Continue;
+}
+
+/*
+** No-op routine for the parse-tree walker.
+**
+** When this routine is the Walker.xExprCallback then expression trees
+** are walked without any actions being taken at each node. Presumably,
+** when this routine is used for Walker.xExprCallback then
+** Walker.xSelectCallback is set to do something useful for every
+** subquery in the parser tree.
+*/
+static int exprWalkNoop(Walker *pWalker, Expr *pExpr){
+ return WRC_Continue;
+}
+
+/*
+** This routine "expands" a SELECT statement and all of its subqueries.
+** For additional information on what it means to "expand" a SELECT
+** statement, see the comment on the selectExpand worker callback above.
+**
+** Expanding a SELECT statement is the first step in processing a
+** SELECT statement. The SELECT statement must be expanded before
+** name resolution is performed.
+**
+** If anything goes wrong, an error message is written into pParse.
+** The calling function can detect the problem by looking at pParse->nErr
+** and/or pParse->db->mallocFailed.
+*/
+static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
+ Walker w;
+ w.xSelectCallback = selectExpander;
+ w.xExprCallback = exprWalkNoop;
+ w.pParse = pParse;
+ sqlite3WalkSelect(&w, pSelect);
+}
+
+
+#ifndef SQLITE_OMIT_SUBQUERY
+/*
+** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo()
+** interface.
+**
+** For each FROM-clause subquery, add Column.zType and Column.zColl
+** information to the Table structure that represents the result set
+** of that subquery.
+**
+** The Table structure that represents the result set was constructed
+** by selectExpander() but the type and collation information was omitted
+** at that point because identifiers had not yet been resolved. This
+** routine is called after identifier resolution.
+*/
+static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
+ Parse *pParse;
+ int i;
+ SrcList *pTabList;
+ struct SrcList_item *pFrom;
+
+ assert( p->selFlags & SF_Resolved );
+ if( (p->selFlags & SF_HasTypeInfo)==0 ){
+ p->selFlags |= SF_HasTypeInfo;
+ pParse = pWalker->pParse;
+ pTabList = p->pSrc;
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab = pFrom->pTab;
+ if( pTab && (pTab->tabFlags & TF_Ephemeral)!=0 ){
+ /* A sub-query in the FROM clause of a SELECT */
+ Select *pSel = pFrom->pSelect;
+ assert( pSel );
+ while( pSel->pPrior ) pSel = pSel->pPrior;
+ selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
+ }
+ }
+ }
+ return WRC_Continue;
+}
+#endif
+
+
+/*
+** This routine adds datatype and collating sequence information to
+** the Table structures of all FROM-clause subqueries in a
+** SELECT statement.
+**
+** Use this routine after name resolution.
+*/
+static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
+#ifndef SQLITE_OMIT_SUBQUERY
+ Walker w;
+ w.xSelectCallback = selectAddSubqueryTypeInfo;
+ w.xExprCallback = exprWalkNoop;
+ w.pParse = pParse;
+ sqlite3WalkSelect(&w, pSelect);
+#endif
+}
+
+
+/*
+** This routine sets of a SELECT statement for processing. The
+** following is accomplished:
+**
+** * VDBE Cursor numbers are assigned to all FROM-clause terms.
+** * Ephemeral Table objects are created for all FROM-clause subqueries.
+** * ON and USING clauses are shifted into WHERE statements
+** * Wildcards "*" and "TABLE.*" in result sets are expanded.
+** * Identifiers in expression are matched to tables.
+**
+** This routine acts recursively on all subqueries within the SELECT.
+*/
+SQLITE_PRIVATE void sqlite3SelectPrep(
+ Parse *pParse, /* The parser context */
+ Select *p, /* The SELECT statement being coded. */
+ NameContext *pOuterNC /* Name context for container */
+){
+ sqlite3 *db;
+ if( p==0 ) return;
+ db = pParse->db;
+ if( p->selFlags & SF_HasTypeInfo ) return;
+ if( pParse->nErr || db->mallocFailed ) return;
+ sqlite3SelectExpand(pParse, p);
+ if( pParse->nErr || db->mallocFailed ) return;
+ sqlite3ResolveSelectNames(pParse, p, pOuterNC);
+ if( pParse->nErr || db->mallocFailed ) return;
+ sqlite3SelectAddTypeInfo(pParse, p);
}
/*
** Reset the aggregate accumulator.
@@ -69005,13 +72002,13 @@
addrNext = sqlite3VdbeMakeLabel(v);
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);
}
if( !pColl ){
@@ -69033,107 +72030,66 @@
}
pAggInfo->directMode = 0;
}
-#if 0
-/*
-** This function is used when a SELECT statement is used to create a
-** temporary table for iterating through when running an INSTEAD OF
-** UPDATE or INSTEAD OF DELETE trigger.
-**
-** If possible, the SELECT statement is modified so that NULL values
-** are stored in the temporary table for all columns for which the
-** corresponding bit in argument mask is not set. If mask takes the
-** special value 0xffffffff, then all columns are populated.
-*/
-SQLITE_PRIVATE void sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){
- if( p && !p->pPrior && !p->isDistinct && mask!=0xffffffff ){
- ExprList *pEList;
- int i;
- sqlite3SelectResolve(pParse, p, 0);
- pEList = p->pEList;
- for(i=0; pEList && i<pEList->nExpr && i<32; i++){
- if( !(mask&((u32)1<<i)) ){
- sqlite3ExprDelete(pEList->a[i].pExpr);
- pEList->a[i].pExpr = sqlite3Expr(pParse->db, TK_NULL, 0, 0, 0);
- }
- }
- }
-}
-#endif
-
-/*
-** Generate code for the given SELECT statement.
+/*
+** Generate code for the SELECT statement given in the p argument.
**
** The results are distributed in various ways depending on the
** contents of the SelectDest structure pointed to by argument pDest
** as follows:
**
** pDest->eDest Result
** ------------ -------------------------------------------
-** SRT_Callback Invoke the callback for each row of the result.
-**
-** SRT_Mem Store first result in memory cell pDest->iParm
-**
-** SRT_Set Store results as keys of table pDest->iParm.
-** Apply the affinity pDest->affinity before storing them.
+** SRT_Output Generate a row of output (using the OP_ResultRow
+** opcode) for each row in the result set.
+**
+** SRT_Mem Only valid if the result is a single column.
+** Store the first column of the first result row
+** in register pDest->iParm then abandon the rest
+** of the query. This destination implies "LIMIT 1".
+**
+** SRT_Set The result must be a single column. Store each
+** row of result as the key in table pDest->iParm.
+** Apply the affinity pDest->affinity before storing
+** results. Used to implement "IN (SELECT ...)".
**
** SRT_Union Store results as a key in a temporary table pDest->iParm.
**
** SRT_Except Remove results from the temporary table pDest->iParm.
**
-** SRT_Table Store results in temporary table pDest->iParm
+** SRT_Table Store results in temporary table pDest->iParm.
+** This is like SRT_EphemTab except that the table
+** is assumed to already be open.
**
** SRT_EphemTab Create an temporary table pDest->iParm and store
** the result there. The cursor is left open after
-** returning.
-**
-** SRT_Coroutine Invoke a co-routine to compute a single row of
-** the result
+** returning. This is like SRT_Table except that
+** this destination uses OP_OpenEphemeral to create
+** the table first.
+**
+** SRT_Coroutine Generate a co-routine that returns a new row of
+** results each time it is invoked. The entry point
+** of the co-routine is stored in register pDest->iParm.
**
** SRT_Exists Store a 1 in memory cell pDest->iParm if the result
** set is not empty.
**
-** SRT_Discard Throw the results away.
-**
-** See the selectInnerLoop() function for a canonical listing of the
-** allowed values of eDest and their meanings.
+** SRT_Discard Throw the results away. This is used by SELECT
+** statements within triggers whose only purpose is
+** the side-effects of functions.
**
** This routine returns the number of errors. If any errors are
** encountered, then an appropriate error message is left in
** pParse->zErrMsg.
**
** This routine does NOT free the Select structure passed in. The
** calling function needs to do that.
-**
-** The pParent, parentTab, and *pParentAgg fields are filled in if this
-** SELECT is a subquery. This routine may try to combine this SELECT
-** with its parent to form a single flat query. In so doing, it might
-** change the parent query from a non-aggregate to an aggregate query.
-** For that reason, the pParentAgg flag is passed as a pointer, so it
-** can be changed.
-**
-** Example 1: The meaning of the pParent parameter.
-**
-** SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3;
-** \ \_______ subquery _______/ /
-** \ /
-** \____________________ outer query ___________________/
-**
-** This routine is called for the outer query first. For that call,
-** pParent will be NULL. During the processing of the outer query, this
-** routine is called recursively to handle the subquery. For the recursive
-** call, pParent will point to the outer query. Because the subquery is
-** the second element in a three-way join, the parentTab parameter will
-** be 1 (the 2nd value of a 0-indexed array.)
*/
SQLITE_PRIVATE int sqlite3Select(
Parse *pParse, /* The parser context */
Select *p, /* The SELECT statement being coded. */
- SelectDest *pDest, /* What to do with the query results */
- Select *pParent, /* Another SELECT for which this is a sub-query */
- int parentTab, /* Index in pParent->pSrc of this query */
- int *pParentAgg /* True if pParent uses aggregate functions */
+ SelectDest *pDest /* What to do with the query results */
){
int i, j; /* Loop counters */
WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */
Vdbe *v; /* The virtual machine under construction */
@@ -69167,11 +72123,12 @@
** results, so remove it if it were specified.
*/
assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
- p->isDistinct = 0;
- }
- if( sqlite3SelectResolve(pParse, p, 0) ){
+ p->selFlags &= ~SF_Distinct;
+ }
+ sqlite3SelectPrep(pParse, p, 0);
+ if( pParse->nErr ){
goto select_end;
}
p->pOrderBy = pOrderBy;
@@ -69178,9 +72135,9 @@
/* Make local copies of the parameters for this query.
*/
pTabList = p->pSrc;
- isAgg = p->isAgg;
+ isAgg = (p->selFlags & SF_Aggregate)!=0;
pEList = p->pEList;
if( pEList==0 ) goto select_end;
/*
@@ -69207,20 +72164,10 @@
struct SrcList_item *pItem = &pTabList->a[i];
SelectDest dest;
Select *pSub = pItem->pSelect;
int isAggSub;
- char *zName = pItem->zName;
-
- if( pSub==0 || pItem->isPopulated ) continue;
- if( zName!=0 ){ /* An sql view */
- const char *zSavedAuthContext = pParse->zAuthContext;
- pParse->zAuthContext = zName;
- rc = sqlite3SelectResolve(pParse, pSub, 0);
- pParse->zAuthContext = zSavedAuthContext;
- if( rc ){
- goto select_end;
- }
- }
+
+ if( pSub==0 || pItem->isPopulated ) continue;
/* Increment Parse.nHeight by the height of the largest expression
** tree refered to by this, the parent select. The child select
** may contain expression trees of at most
@@ -69230,17 +72177,20 @@
*/
pParse->nHeight += sqlite3SelectExprHeight(p);
/* Check to see if the subquery can be absorbed into the parent. */
- isAggSub = pSub->isAgg;
+ isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
if( isAggSub ){
- p->isAgg = isAgg = 1;
+ isAgg = 1;
+ p->selFlags |= SF_Aggregate;
}
i = -1;
}else{
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- sqlite3Select(pParse, pSub, &dest, p, i, &isAgg);
+ assert( pItem->isPopulated==0 );
+ sqlite3Select(pParse, pSub, &dest);
+ pItem->isPopulated = 1;
}
if( pParse->nErr || db->mallocFailed ){
goto select_end;
}
@@ -69254,9 +72204,9 @@
#endif
pWhere = p->pWhere;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
- isDistinct = p->isDistinct;
+ isDistinct = (p->selFlags & SF_Distinct)!=0;
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* If there is are a sequence of queries, do the earlier ones first.
*/
@@ -69289,14 +72239,14 @@
}
#endif
/* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
- ** GROUP BY may use an index, DISTINCT never does.
- */
- if( p->isDistinct && !p->isAgg && !p->pGroupBy ){
+ ** GROUP BY might use an index, DISTINCT never does.
+ */
+ if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && !p->pGroupBy ){
p->pGroupBy = sqlite3ExprListDup(db, p->pEList);
pGroupBy = p->pGroupBy;
- p->isDistinct = 0;
+ p->selFlags &= ~SF_Distinct;
isDistinct = 0;
}
/* If there is an ORDER BY clause, then this sorting
@@ -69377,22 +72327,27 @@
** one row of the input to the aggregator has been
** processed */
int iAbortFlag; /* Mem address which causes query abort if positive */
int groupBySort; /* Rows come from source in GROUP BY order */
-
-
- /* 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 */
-
+ int addrEnd; /* End of processing for this SELECT */
+
+ /* Remove any and all aliases between the result set and the
+ ** GROUP BY clause.
+ */
+ if( pGroupBy ){
+ int i; /* Loop counter */
+ struct ExprList_item *pItem; /* For looping over expression in a list */
+
+ for(i=p->pEList->nExpr, pItem=p->pEList->a; i>0; i--, pItem++){
+ pItem->iAlias = 0;
+ }
+ for(i=pGroupBy->nExpr, pItem=pGroupBy->a; i>0; i--, pItem++){
+ pItem->iAlias = 0;
+ }
+ }
+
+
+ /* 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
** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
@@ -69419,13 +72374,16 @@
** much more complex than aggregates without a GROUP BY.
*/
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
** that we do not need it after all, the OpenEphemeral instruction
@@ -69440,8 +72398,12 @@
/* Initialize memory locations used by GROUP BY aggregate processing
*/
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;
pParse->nMem += pGroupBy->nExpr;
@@ -69448,49 +72410,14 @@
sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
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;
if( pGroupBy==0 ){
@@ -69528,9 +72455,11 @@
for(i=0; i<sAggInfo.nColumn; i++){
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
if( pCol->iSorterColumn>=j ){
int r1 = j + regBase;
- int r2 = sqlite3ExprCodeGetColumn(pParse,
+ int r2;
+
+ r2 = sqlite3ExprCodeGetColumn(pParse,
pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
if( r1!=r2 ){
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
}
@@ -69605,8 +72534,44 @@
*/
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;
ExprList *pDel = 0;
@@ -69652,9 +72617,9 @@
*/
resetAccumulator(pParse, &sAggInfo);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
if( pWInfo==0 ){
- sqlite3ExprListDelete(pDel);
+ sqlite3ExprListDelete(db, pDel);
goto select_end;
}
updateAccumulator(pParse, &sAggInfo);
if( !pMinMax && flag ){
@@ -69669,9 +72634,9 @@
}
selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1,
pDest, addrEnd, addrEnd);
- sqlite3ExprListDelete(pDel);
+ sqlite3ExprListDelete(db, pDel);
}
sqlite3VdbeResolveLabel(v, addrEnd);
} /* endif aggregate query */
@@ -69681,21 +72646,8 @@
*/
if( pOrderBy ){
generateSortTail(pParse, p, v, pEList->nExpr, pDest);
}
-
-#ifndef SQLITE_OMIT_SUBQUERY
- /* If this was a subquery, we have now converted the subquery into a
- ** temporary table. So set the SrcList_item.isPopulated flag to prevent
- ** this subquery from being evaluated again and to force the use of
- ** the temporary table.
- */
- if( pParent ){
- assert( pParent->pSrc->nSrc>parentTab );
- assert( pParent->pSrc->a[parentTab].pSelect==p );
- pParent->pSrc->a[parentTab].isPopulated = 1;
- }
-#endif
/* Jump here to skip this query
*/
sqlite3VdbeResolveLabel(v, iEnd);
@@ -69709,17 +72661,16 @@
** successful coding of the SELECT.
*/
select_end:
- /* Identify column names if we will be using them in a callback. This
- ** step is skipped if the output is going to some other destination.
- */
- if( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){
+ /* Identify column names if results of the SELECT are to be output.
+ */
+ if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
generateColumnNames(pParse, pTabList, pEList);
}
- sqlite3_free(sAggInfo.aCol);
- sqlite3_free(sAggInfo.aFunc);
+ sqlite3DbFree(db, sAggInfo.aCol);
+ sqlite3DbFree(db, sAggInfo.aFunc);
return rc;
}
#if defined(SQLITE_DEBUG)
@@ -70032,27 +72983,27 @@
**
*************************************************************************
**
**
-** $Id: trigger.c,v 1.127 2008/07/08 23:40:20 drh Exp $
+** $Id: trigger.c,v 1.129 2008/08/20 16:35:10 drh Exp $
*/
#ifndef SQLITE_OMIT_TRIGGER
/*
** Delete a linked list of TriggerStep structures.
*/
-SQLITE_PRIVATE void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
+SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3 *db, TriggerStep *pTriggerStep){
while( pTriggerStep ){
TriggerStep * pTmp = pTriggerStep;
pTriggerStep = pTriggerStep->pNext;
- if( pTmp->target.dyn ) sqlite3_free((char*)pTmp->target.z);
- sqlite3ExprDelete(pTmp->pWhere);
- sqlite3ExprListDelete(pTmp->pExprList);
- sqlite3SelectDelete(pTmp->pSelect);
- sqlite3IdListDelete(pTmp->pIdList);
-
- sqlite3_free(pTmp);
+ if( pTmp->target.dyn ) sqlite3DbFree(db, (char*)pTmp->target.z);
+ sqlite3ExprDelete(db, pTmp->pWhere);
+ sqlite3ExprListDelete(db, pTmp->pExprList);
+ sqlite3SelectDelete(db, pTmp->pSelect);
+ sqlite3IdListDelete(db, pTmp->pIdList);
+
+ sqlite3DbFree(db, pTmp);
}
}
/*
@@ -70207,14 +73158,14 @@
assert( pParse->pNewTrigger==0 );
pParse->pNewTrigger = pTrigger;
trigger_cleanup:
- sqlite3_free(zName);
- sqlite3SrcListDelete(pTableName);
- sqlite3IdListDelete(pColumns);
- sqlite3ExprDelete(pWhen);
+ sqlite3DbFree(db, zName);
+ sqlite3SrcListDelete(db, pTableName);
+ sqlite3IdListDelete(db, pColumns);
+ sqlite3ExprDelete(db, pWhen);
if( !pParse->pNewTrigger ){
- sqlite3DeleteTrigger(pTrigger);
+ sqlite3DeleteTrigger(db, pTrigger);
}else{
assert( pParse->pNewTrigger==pTrigger );
}
}
@@ -70262,9 +73213,9 @@
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name,
pTrig->table, z);
- sqlite3_free(z);
+ sqlite3DbFree(db, z);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC
);
@@ -70289,11 +73240,11 @@
pTrig = 0;
}
triggerfinish_cleanup:
- sqlite3DeleteTrigger(pTrig);
+ sqlite3DeleteTrigger(db, pTrig);
assert( !pParse->pNewTrigger );
- sqlite3DeleteTriggerStep(pStepList);
+ sqlite3DeleteTriggerStep(db, pStepList);
}
/*
** Make a copy of all components of the given trigger step. This has
@@ -70311,24 +73262,24 @@
p->target.dyn = 1;
}
if( p->pSelect ){
Select *pNew = sqlite3SelectDup(db, p->pSelect);
- sqlite3SelectDelete(p->pSelect);
+ sqlite3SelectDelete(db, p->pSelect);
p->pSelect = pNew;
}
if( p->pWhere ){
Expr *pNew = sqlite3ExprDup(db, p->pWhere);
- sqlite3ExprDelete(p->pWhere);
+ sqlite3ExprDelete(db, p->pWhere);
p->pWhere = pNew;
}
if( p->pExprList ){
ExprList *pNew = sqlite3ExprListDup(db, p->pExprList);
- sqlite3ExprListDelete(p->pExprList);
+ sqlite3ExprListDelete(db, p->pExprList);
p->pExprList = pNew;
}
if( p->pIdList ){
IdList *pNew = sqlite3IdListDup(db, p->pIdList);
- sqlite3IdListDelete(p->pIdList);
+ sqlite3IdListDelete(db, p->pIdList);
p->pIdList = pNew;
}
}
@@ -70341,9 +73292,9 @@
*/
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3 *db, Select *pSelect){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ) {
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
return 0;
}
pTriggerStep->op = TK_SELECT;
@@ -70383,11 +73334,11 @@
pTriggerStep->pExprList = pEList;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(db, pTriggerStep);
}else{
- sqlite3IdListDelete(pColumn);
- sqlite3ExprListDelete(pEList);
- sqlite3SelectDelete(pSelect);
+ sqlite3IdListDelete(db, pColumn);
+ sqlite3ExprListDelete(db, pEList);
+ sqlite3SelectDelete(db, pSelect);
}
return pTriggerStep;
}
@@ -70405,10 +73356,10 @@
int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ){
- sqlite3ExprListDelete(pEList);
- sqlite3ExprDelete(pWhere);
+ sqlite3ExprListDelete(db, pEList);
+ sqlite3ExprDelete(db, pWhere);
return 0;
}
pTriggerStep->op = TK_UPDATE;
@@ -70432,9 +73383,9 @@
Expr *pWhere /* The WHERE clause */
){
TriggerStep *pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep));
if( pTriggerStep==0 ){
- sqlite3ExprDelete(pWhere);
+ sqlite3ExprDelete(db, pWhere);
return 0;
}
pTriggerStep->op = TK_DELETE;
@@ -70448,17 +73399,17 @@
/*
** Recursively delete a Trigger structure
*/
-SQLITE_PRIVATE void sqlite3DeleteTrigger(Trigger *pTrigger){
+SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
if( pTrigger==0 ) return;
- sqlite3DeleteTriggerStep(pTrigger->step_list);
- sqlite3_free(pTrigger->name);
- sqlite3_free(pTrigger->table);
- sqlite3ExprDelete(pTrigger->pWhen);
- sqlite3IdListDelete(pTrigger->pColumns);
- if( pTrigger->nameToken.dyn ) sqlite3_free((char*)pTrigger->nameToken.z);
- sqlite3_free(pTrigger);
+ sqlite3DeleteTriggerStep(db, pTrigger->step_list);
+ sqlite3DbFree(db, pTrigger->name);
+ sqlite3DbFree(db, pTrigger->table);
+ sqlite3ExprDelete(db, pTrigger->pWhen);
+ sqlite3IdListDelete(db, pTrigger->pColumns);
+ if( pTrigger->nameToken.dyn ) sqlite3DbFree(db, (char*)pTrigger->nameToken.z);
+ sqlite3DbFree(db, pTrigger);
}
/*
** This function is called to drop a trigger from the database schema.
@@ -70499,9 +73450,9 @@
}
sqlite3DropTriggerPtr(pParse, pTrigger);
drop_trigger_cleanup:
- sqlite3SrcListDelete(pName);
+ sqlite3SrcListDelete(db, pName);
}
/*
** Return a pointer to the Table structure for the table that a trigger
@@ -70591,9 +73542,9 @@
cc = cc->pNext;
}
assert(cc);
}
- sqlite3DeleteTrigger(pTrigger);
+ sqlite3DeleteTrigger(db, pTrigger);
db->flags |= SQLITE_InternChanges;
}
}
@@ -70700,11 +73651,10 @@
if( ss ){
SelectDest dest;
sqlite3SelectDestInit(&dest, SRT_Discard, 0);
- sqlite3SelectResolve(pParse, ss, 0);
- sqlite3Select(pParse, ss, &dest, 0, 0, 0);
- sqlite3SelectDelete(ss);
+ sqlite3Select(pParse, ss, &dest);
+ sqlite3SelectDelete(db, ss);
}
break;
}
case TK_UPDATE: {
@@ -70850,15 +73800,15 @@
/* code the WHEN clause */
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
whenExpr = sqlite3ExprDup(db, p->pWhen);
- if( db->mallocFailed || sqlite3ExprResolveNames(&sNC, whenExpr) ){
+ if( db->mallocFailed || sqlite3ResolveExprNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
- sqlite3ExprDelete(whenExpr);
+ sqlite3ExprDelete(db, whenExpr);
return 1;
}
sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, SQLITE_JUMPIFNULL);
- sqlite3ExprDelete(whenExpr);
+ sqlite3ExprDelete(db, whenExpr);
codeTriggerProgram(pParse, p->step_list, orconf);
/* Pop the entry off the trigger stack */
@@ -70889,9 +73839,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.180 2008/07/09 16:51:51 drh Exp $
+** $Id: update.c,v 1.186 2008/10/31 10:53:23 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
@@ -71070,9 +74020,9 @@
** that column.
*/
chngRowid = 0;
for(i=0; i<pChanges->nExpr; i++){
- if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
+ if( sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
@@ -71204,16 +74154,18 @@
/* 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->pSelect, pWhere, iCur);
- }
+ sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
+ }
+#endif
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
- if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+ if( sqlite3ResolveExprNames(&sNC, pWhere) ){
goto update_cleanup;
}
/* Begin the database scan
@@ -71307,8 +74259,9 @@
/* Generate the NEW table
*/
if( chngRowid ){
sqlite3ExprCodeAndCache(pParse, pRowidExpr, regRowid);
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
}else{
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regRowid);
}
regCols = sqlite3GetTempRange(pParse, pTab->nCol);
@@ -71441,18 +74394,18 @@
*/
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:
sqlite3AuthContextPop(&sContext);
- sqlite3_free(aRegIdx);
- sqlite3_free(aXRef);
- sqlite3SrcListDelete(pTabList);
- sqlite3ExprListDelete(pChanges);
- sqlite3ExprDelete(pWhere);
+ sqlite3DbFree(db, aRegIdx);
+ sqlite3DbFree(db, aXRef);
+ sqlite3SrcListDelete(db, pTabList);
+ sqlite3ExprListDelete(db, pChanges);
+ sqlite3ExprDelete(db, pWhere);
return;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -71525,9 +74478,9 @@
/* fill the ephemeral table
*/
sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
- sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+ sqlite3Select(pParse, pSelect, &dest);
/* Generate code to scan the ephemeral table and call VUpdate. */
iReg = ++pParse->nMem;
pParse->nMem += pTab->nCol+1;
@@ -71544,9 +74497,9 @@
sqlite3VdbeJumpHere(v, addr-1);
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
/* Cleanup */
- sqlite3SelectDelete(pSelect);
+ sqlite3SelectDelete(db, pSelect);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
/* Make sure "isView" gets undefined in case this file becomes part of
@@ -71571,9 +74524,9 @@
**
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
-** $Id: vacuum.c,v 1.81 2008/07/08 19:34:07 drh Exp $
+** $Id: vacuum.c,v 1.83 2008/08/26 21:07:27 drh Exp $
*/
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/*
@@ -71636,14 +74589,16 @@
*/
SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
+ Pager *pMainPager; /* Pager for database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
char *zSql = 0; /* SQL statements */
int saved_flags; /* Saved value of the db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
Db *pDb = 0; /* Database to detach at end of vacuum */
+ int isMemDb; /* True is vacuuming a :memory: database */
int nRes;
/* Save the current value of the write-schema flag before setting it. */
saved_flags = db->flags;
@@ -71656,8 +74611,10 @@
rc = SQLITE_ERROR;
goto end_of_vacuum;
}
pMain = db->aDb[0].pBt;
+ pMainPager = sqlite3BtreePager(pMain);
+ isMemDb = sqlite3PagerFile(pMainPager)->pMethods==0;
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
** occurs anyway. The integrity of the database is maintained by a
@@ -71692,9 +74649,9 @@
}
#endif
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes)
- || sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes)
+ || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes))
|| db->mallocFailed
){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
@@ -71813,8 +74770,11 @@
rc = sqlite3BtreeCopyFile(pMain, pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
+#endif
rc = sqlite3BtreeCommit(pMain);
}
if( rc==SQLITE_OK ){
@@ -71862,9 +74822,9 @@
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
-** $Id: vtab.c,v 1.70 2008/06/23 17:44:19 danielk1977 Exp $
+** $Id: vtab.c,v 1.76 2008/08/20 16:35:10 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
static int createModule(
@@ -71891,9 +74851,9 @@
pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
if( pDel && pDel->xDestroy ){
pDel->xDestroy(pDel->pAux);
}
- sqlite3_free(pDel);
+ sqlite3DbFree(db, pDel);
if( pDel==pMod ){
db->mallocFailed = 1;
}
sqlite3ResetInternalSchema(db, 0);
@@ -71966,19 +74926,20 @@
** record.
*/
SQLITE_PRIVATE void sqlite3VtabClear(Table *p){
sqlite3_vtab *pVtab = p->pVtab;
+ sqlite3 *db = p->db;
if( pVtab ){
assert( p->pMod && p->pMod->pModule );
- sqlite3VtabUnlock(p->pSchema->db, pVtab);
+ sqlite3VtabUnlock(db, pVtab);
p->pVtab = 0;
}
if( p->azModuleArg ){
int i;
for(i=0; i<p->nModuleArg; i++){
- sqlite3_free(p->azModuleArg[i]);
- }
- sqlite3_free(p->azModuleArg);
+ sqlite3DbFree(db, p->azModuleArg[i]);
+ }
+ sqlite3DbFree(db, p->azModuleArg);
}
}
/*
@@ -71994,12 +74955,12 @@
azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
if( azModuleArg==0 ){
int j;
for(j=0; j<i; j++){
- sqlite3_free(pTable->azModuleArg[j]);
- }
- sqlite3_free(zArg);
- sqlite3_free(pTable->azModuleArg);
+ sqlite3DbFree(db, pTable->azModuleArg[j]);
+ }
+ sqlite3DbFree(db, zArg);
+ sqlite3DbFree(db, pTable->azModuleArg);
pTable->nModuleArg = 0;
}else{
azModuleArg[i] = zArg;
azModuleArg[i+1] = 0;
@@ -72035,9 +74996,9 @@
db = pParse->db;
iDb = sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 );
- pTable->isVirtual = 1;
+ pTable->tabFlags |= TF_Virtual;
pTable->nModuleArg = 0;
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
@@ -72128,9 +75089,9 @@
pTab->zName,
zStmt,
pParse->regRowid
);
- sqlite3_free(zStmt);
+ sqlite3DbFree(db, zStmt);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
@@ -72227,9 +75188,9 @@
if( zErr==0 ){
*pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
}else {
*pzErr = sqlite3MPrintf(db, "%s", zErr);
- sqlite3_free(zErr);
+ sqlite3DbFree(db, zErr);
}
}else if( db->pVTab ){
const char *zFormat = "vtable constructor did not declare schema: %s";
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
@@ -72238,9 +75199,9 @@
if( rc==SQLITE_OK ){
rc = rc2;
}
db->pVTab = 0;
- sqlite3_free(zModuleName);
+ sqlite3DbFree(db, zModuleName);
/* If everything went according to plan, loop through the columns
** of the table to see if any of them contain the token "hidden".
** If so, set the Column.isHidden flag and remove the token from
@@ -72291,9 +75252,9 @@
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
Module *pMod;
int rc = SQLITE_OK;
- if( !pTab || !pTab->isVirtual || pTab->pVtab ){
+ if( !pTab || (pTab->tabFlags & TF_Virtual)==0 || pTab->pVtab ){
return SQLITE_OK;
}
pMod = pTab->pMod;
@@ -72307,9 +75268,9 @@
rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "%s", zErr);
}
- sqlite3_free(zErr);
+ sqlite3DbFree(db, zErr);
}
return rc;
}
@@ -72343,9 +75304,9 @@
** of the virtual table named zTab in database iDb.
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
-** In this case the caller must call sqlite3_free() on *pzErr.
+** In this case the caller must call sqlite3DbFree(db, ) on *pzErr.
*/
SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
int rc = SQLITE_OK;
Table *pTab;
@@ -72352,9 +75313,9 @@
Module *pMod;
const char *zModule;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
- assert(pTab && pTab->isVirtual && !pTab->pVtab);
+ assert(pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVtab);
pMod = pTab->pMod;
zModule = pTab->azModuleArg[0];
/* If the module has been registered and includes a Create method,
@@ -72393,9 +75354,9 @@
sqlite3Error(db, SQLITE_MISUSE, 0);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE;
}
- assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
+ assert((pTab->tabFlags & TF_Virtual)!=0 && pTab->nCol==0 && pTab->aCol==0);
memset(&sParse, 0, sizeof(Parse));
sParse.declareVtab = 1;
sParse.db = db;
@@ -72403,9 +75364,9 @@
if(
SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) &&
sParse.pNewTable &&
!sParse.pNewTable->pSelect &&
- !sParse.pNewTable->isVirtual
+ (sParse.pNewTable->tabFlags & TF_Virtual)==0
){
pTab->aCol = sParse.pNewTable->aCol;
pTab->nCol = sParse.pNewTable->nCol;
sParse.pNewTable->nCol = 0;
@@ -72412,9 +75373,9 @@
sParse.pNewTable->aCol = 0;
db->pVTab = 0;
} else {
sqlite3Error(db, SQLITE_ERROR, zErr);
- sqlite3_free(zErr);
+ sqlite3DbFree(db, zErr);
rc = SQLITE_ERROR;
}
sParse.declareVtab = 0;
@@ -72482,26 +75443,27 @@
x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
if( x ) x(pVtab);
sqlite3VtabUnlock(db, pVtab);
}
- sqlite3_free(db->aVTrans);
+ sqlite3DbFree(db, db->aVTrans);
db->nVTrans = 0;
db->aVTrans = 0;
}
}
/*
-** If argument rc2 is not SQLITE_OK, then return it and do nothing.
-** Otherwise, invoke the xSync method of all virtual tables in the
-** sqlite3.aVTrans array. Return the error code for the first error
-** that occurs, or SQLITE_OK if all xSync operations are successful.
-*/
-SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, int rc2){
+** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans
+** array. Return the error code for the first error that occurs, or
+** SQLITE_OK if all xSync operations are successful.
+**
+** Set *pzErrmsg to point to a buffer that should be released using
+** sqlite3DbFree() containing an error message, if one is available.
+*/
+SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
int i;
int rc = SQLITE_OK;
int rcsafety;
sqlite3_vtab **aVTrans = db->aVTrans;
- if( rc2!=SQLITE_OK ) return rc2;
rc = sqlite3SafetyOff(db);
db->aVTrans = 0;
for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){
@@ -72509,8 +75471,11 @@
int (*x)(sqlite3_vtab *);
x = pVtab->pModule->xSync;
if( x ){
rc = x(pVtab);
+ sqlite3DbFree(db, *pzErrmsg);
+ *pzErrmsg = pVtab->zErrMsg;
+ pVtab->zErrMsg = 0;
}
}
db->aVTrans = aVTrans;
rcsafety = sqlite3SafetyOn(db);
@@ -72576,13 +75541,11 @@
}
/* Invoke the xBegin method */
rc = pModule->xBegin(pVtab);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- rc = addToVTrans(db, pVtab);
+ if( rc==SQLITE_OK ){
+ rc = addToVTrans(db, pVtab);
+ }
}
return rc;
}
@@ -72620,9 +75583,9 @@
if( pExpr==0 ) return pDef;
if( pExpr->op!=TK_COLUMN ) return pDef;
pTab = pExpr->pTab;
if( pTab==0 ) return pDef;
- if( !pTab->isVirtual ) return pDef;
+ if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
pVtab = pTab->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
pMod = (sqlite3_module *)pVtab->pModule;
@@ -72636,9 +75599,14 @@
for(z=(unsigned char*)zLowerName; *z; z++){
*z = sqlite3UpperToLower[*z];
}
rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
- sqlite3_free(zLowerName);
+ sqlite3DbFree(db, zLowerName);
+ if( pVtab->zErrMsg ){
+ sqlite3Error(db, rc, "%s", pVtab->zErrMsg);
+ sqlite3DbFree(db, pVtab->zErrMsg);
+ pVtab->zErrMsg = 0;
+ }
}
if( rc==0 ){
return pDef;
}
@@ -72649,8 +75617,9 @@
if( pNew==0 ){
return pDef;
}
*pNew = *pDef;
+ pNew->zName = (char *)&pNew[1];
memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1);
pNew->xFunc = xFunc;
pNew->pUserData = pArg;
pNew->flags |= SQLITE_FUNC_EPHEM;
@@ -72699,9 +75668,9 @@
** rows. Indices are selected and used to speed the search when doing
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.317 2008/07/12 14:52:20 drh Exp $
+** $Id: where.c,v 1.327 2008/10/25 15:03:21 drh Exp $
*/
/*
** The number of bits in a Bitmask. "BMS" means "BitMask Size".
@@ -72774,9 +75743,9 @@
/*
** Allowed values of WhereTerm.flags
*/
-#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(pExpr) */
+#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */
#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */
#define TERM_CODED 0x04 /* This term is already coded */
#define TERM_COPIED 0x08 /* Has a child */
#define TERM_OR_OK 0x10 /* Used during OR-clause processing */
@@ -72885,15 +75854,16 @@
*/
static void whereClauseClear(WhereClause *pWC){
int i;
WhereTerm *a;
+ sqlite3 *db = pWC->pParse->db;
for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
if( a->flags & TERM_DYNAMIC ){
- sqlite3ExprDelete(a->pExpr);
+ sqlite3ExprDelete(db, a->pExpr);
}
}
if( pWC->a!=pWC->aStatic ){
- sqlite3_free(pWC->a);
+ sqlite3DbFree(db, pWC->a);
}
}
/*
@@ -72912,20 +75882,20 @@
WhereTerm *pTerm;
int idx;
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
- pWC->a = sqlite3Malloc( sizeof(pWC->a[0])*pWC->nSlot*2 );
- if( pWC->a==0 ){
- pWC->pParse->db->mallocFailed = 1;
+ sqlite3 *db = pWC->pParse->db;
+ pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
+ if( pWC->a==0 ){
if( flags & TERM_DYNAMIC ){
- sqlite3ExprDelete(p);
+ sqlite3ExprDelete(db, p);
}
pWC->a = pOld;
return 0;
}
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
- sqlite3_free(pOld);
+ sqlite3DbFree(db, pOld);
}
pWC->nSlot *= 2;
}
pTerm = &pWC->a[idx = pWC->nTerm];
@@ -73001,11 +75971,11 @@
** a bitmask indicating which tables are used in that expression
** tree.
**
** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ExprResolveNames() on the expression. See
+** previously invoked sqlite3ResolveExprNames() on the expression. See
** the header comment on that routine for additional information.
-** The sqlite3ExprResolveNames() routines looks for column names and
+** The sqlite3ResolveExprNames() routines looks for column names and
** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
** the VDBE cursor number of the table. This routine just has to
** translate the cursor numbers into bitmask values and OR all
** the bitmasks together.
@@ -73077,12 +76047,14 @@
** the left hand side of a comparison overrides any collation sequence
** attached to the right. For the same reason the EP_ExpCollate flag
** is not commuted.
*/
-static void exprCommute(Expr *pExpr){
+static void exprCommute(Parse *pParse, Expr *pExpr){
u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
+ pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
+ pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
@@ -73200,9 +76172,9 @@
** In order for the operator to be optimizible, the RHS must be a string
** literal that does not begin with a wildcard.
*/
static int isLikeOrGlob(
- sqlite3 *db, /* The database */
+ Parse *pParse, /* Parsing and code generating context */
Expr *pExpr, /* Test this expression */
int *pnPattern, /* Number of non-wildcard prefix characters */
int *pisComplete, /* True if the only wildcard is % in the last character */
int *pnoCase /* True if uppercase is equivalent to lowercase */
@@ -73212,8 +76184,9 @@
ExprList *pList;
int c, cnt;
char wc[3];
CollSeq *pColl;
+ sqlite3 *db = pParse->db;
if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
return 0;
}
@@ -73229,9 +76202,9 @@
pLeft = pList->a[1].pExpr;
if( pLeft->op!=TK_COLUMN ){
return 0;
}
- pColl = pLeft->pColl;
+ pColl = sqlite3ExprCollSeq(pParse, pLeft);
assert( pColl!=0 || pLeft->iColumn==-1 );
if( pColl==0 ){
/* No collation is defined for the ROWID. Use the default. */
pColl = db->pDfltColl;
@@ -73455,9 +76428,9 @@
if( pTerm->leftCursor>=0 ){
int idxNew;
pDup = sqlite3ExprDup(db, pExpr);
if( db->mallocFailed ){
- sqlite3ExprDelete(pDup);
+ sqlite3ExprDelete(db, pDup);
return;
}
idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
if( idxNew==0 ) return;
@@ -73469,9 +76442,9 @@
}else{
pDup = pExpr;
pNew = pTerm;
}
- exprCommute(pDup);
+ exprCommute(pParse, pDup);
pLeft = pDup->pLeft;
pNew->leftCursor = pLeft->iTable;
pNew->leftColumn = pLeft->iColumn;
pNew->prereqRight = prereqLeft;
@@ -73571,9 +76544,9 @@
pTerm = &pWC->a[idxTerm];
pWC->a[idxNew].iParent = idxTerm;
pTerm->nChild = 1;
}else{
- sqlite3ExprListDelete(pList);
+ sqlite3ExprListDelete(db, pList);
}
}
or_not_possible:
whereClauseClear(&sOr);
@@ -73590,9 +76563,9 @@
**
** The last character of the prefix "abc" is incremented to form the
** termination condition "abd".
*/
- if( isLikeOrGlob(db, pExpr, &nPattern, &isComplete, &noCase) ){
+ if( isLikeOrGlob(pParse, pExpr, &nPattern, &isComplete, &noCase) ){
Expr *pLeft, *pRight;
Expr *pStr1, *pStr2;
Expr *pNewExpr1, *pNewExpr2;
int idxNew1, idxNew2;
@@ -73940,8 +76913,9 @@
int orderByUsable, /* True if we can potential sort */
sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
){
Table *pTab = pSrc->pTab;
+ sqlite3_vtab *pVtab = pTab->pVtab;
sqlite3_index_info *pIdxInfo;
struct sqlite3_index_constraint *pIdxCons;
struct sqlite3_index_orderby *pIdxOrderBy;
struct sqlite3_index_constraint_usage *pUsage;
@@ -73963,9 +76937,9 @@
/* Count the number of possible WHERE clause constraints referring
** to this virtual table */
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+ assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
testcase( pTerm->eOperator==WO_IN );
testcase( pTerm->eOperator==WO_ISNULL );
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
nTerm++;
@@ -74013,9 +76987,9 @@
pUsage;
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
+ assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
testcase( pTerm->eOperator==WO_IN );
testcase( pTerm->eOperator==WO_ISNULL );
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
pIdxCons[j].iColumn = pTerm->leftColumn;
@@ -74051,9 +77025,9 @@
** be a pointer to an sqlite3_vtab structure. Otherwise
** sqlite3ViewGetColumnNames() would have picked up the error.
*/
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
- assert( pTab->pVtab );
+ assert( pVtab );
#if 0
if( pTab->pVtab==0 ){
sqlite3ErrorMsg(pParse, "undefined module %s for table %s",
pTab->azModuleArg[0], pTab->zName);
@@ -74104,11 +77078,23 @@
(void)sqlite3SafetyOff(pParse->db);
WHERETRACE(("xBestIndex for %s\n", pTab->zName));
TRACE_IDX_INPUTS(pIdxInfo);
- rc = pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
+ rc = pVtab->pModule->xBestIndex(pVtab, pIdxInfo);
TRACE_IDX_OUTPUTS(pIdxInfo);
(void)sqlite3SafetyOn(pParse->db);
+
+ if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ){
+ pParse->db->mallocFailed = 1;
+ }else if( !pVtab->zErrMsg ){
+ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
+ }else{
+ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
+ }
+ }
+ sqlite3DbFree(pParse->db, pVtab->zErrMsg);
+ pVtab->zErrMsg = 0;
for(i=0; i<pIdxInfo->nConstraint; i++){
if( !pIdxInfo->aConstraint[i].usable && pUsage[i].argvIndex>0 ){
sqlite3ErrorMsg(pParse,
@@ -74116,17 +77102,9 @@
return 0.0;
}
}
- if( rc!=SQLITE_OK ){
- if( rc==SQLITE_NOMEM ){
- pParse->db->mallocFailed = 1;
- }else {
- sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
- }
- }
- *(int*)&pIdxInfo->nOrderBy = nOrderBy;
-
+ *(int*)&pIdxInfo->nOrderBy = nOrderBy;
return pIdxInfo->estimatedCost;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -74146,8 +77124,18 @@
**
** * 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 */
WhereClause *pWC, /* The WHERE clause */
@@ -74173,8 +77161,11 @@
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
** anything other than a full table scan on this table. We might as
@@ -74189,76 +77180,79 @@
*pnEq = 0;
return 0.0;
}
- /* Check for a rowid=EXPR or rowid IN (...) constraints
- */
- pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
- if( pTerm ){
- Expr *pExpr;
- *ppIndex = 0;
- bestFlags = WHERE_ROWID_EQ;
- if( pTerm->eOperator & WO_EQ ){
- /* Rowid== is always the best pick. Look no further. Because only
- ** a single row is generated, output is always in sorted order */
- *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
- *pnEq = 1;
- WHERETRACE(("... best is rowid\n"));
- return 0.0;
- }else if( (pExpr = pTerm->pExpr)->pList!=0 ){
- /* Rowid IN (LIST): cost is NlogN where N is the number of list
- ** elements. */
- lowestCost = pExpr->pList->nExpr;
- lowestCost *= estLog(lowestCost);
- }else{
- /* Rowid IN (SELECT): cost is NlogN where N is the number of rows
- ** in the result of the inner select. We have no way to estimate
- ** that value so make a wild guess. */
- lowestCost = 200;
- }
- WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost));
- }
-
- /* Estimate the cost of a table scan. If we do not know how many
- ** entries are in the table, use 1 million as a guess.
- */
- 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{
- 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;
+ /* Check for a rowid=EXPR or rowid IN (...) constraints. If there was
+ ** an INDEXED BY clause attached to this table, skip this step.
+ */
+ if( !pSrc->pIndex ){
+ pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
+ if( pTerm ){
+ Expr *pExpr;
+ *ppIndex = 0;
+ bestFlags = WHERE_ROWID_EQ;
+ if( pTerm->eOperator & WO_EQ ){
+ /* Rowid== is always the best pick. Look no further. Because only
+ ** a single row is generated, output is always in sorted order */
+ *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
+ *pnEq = 1;
+ WHERETRACE(("... best is rowid\n"));
+ return 0.0;
+ }else if( (pExpr = pTerm->pExpr)->pList!=0 ){
+ /* Rowid IN (LIST): cost is NlogN where N is the number of list
+ ** elements. */
+ lowestCost = pExpr->pList->nExpr;
+ lowestCost *= estLog(lowestCost);
+ }else{
+ /* Rowid IN (SELECT): cost is NlogN where N is the number of rows
+ ** in the result of the inner select. We have no way to estimate
+ ** that value so make a wild guess. */
+ lowestCost = 200;
+ }
+ WHERETRACE(("... rowid IN cost: %.9g\n", lowestCost));
+ }
+
+ /* Estimate the cost of a table scan. If we do not know how many
+ ** entries are in the table, use 1 million as a guess.
+ */
+ cost = pProbe ? pProbe->aiRowEst[0] : 1000000;
+ WHERETRACE(("... table scan base cost: %.9g\n", cost));
+ flags = WHERE_ROWID_RANGE;
+
+ /* Check for constraints on a range of rowids in a table scan.
+ */
+ pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0);
+ if( pTerm ){
+ if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){
+ flags |= WHERE_TOP_LIMIT;
+ cost /= 3; /* Guess that rowid<EXPR eliminates two-thirds or rows */
+ }
+ if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
+ flags |= WHERE_BTM_LIMIT;
+ cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */
+ }
+ WHERETRACE(("... rowid range reduces cost to %.9g\n", cost));
+ }else{
+ flags = 0;
+ }
+
+ /* If the table scan does not satisfy the ORDER BY clause, increase
+ ** the cost by NlogN to cover the expense of sorting. */
+ if( pOrderBy ){
+ if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){
+ flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
+ if( rev ){
+ flags |= WHERE_REVERSE;
+ }
+ }else{
+ cost += cost*estLog(cost);
+ WHERETRACE(("... sorting increases cost to %.9g\n", cost));
+ }
+ }
+ if( cost<lowestCost ){
+ lowestCost = cost;
+ bestFlags = flags;
+ }
}
/* If the pSrc table is the right table of a LEFT JOIN then we may not
** use an index to satisfy IS NULL constraints on that table. This is
@@ -74272,9 +77266,12 @@
}
/* 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;
WHERETRACE(("... index %s:\n", pProbe->zName));
@@ -74457,11 +77454,9 @@
Expr *pX = pTerm->pExpr;
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 ){
iReg = iTarget;
@@ -74587,19 +77582,19 @@
/*
** Free a WhereInfo structure
*/
-static void whereInfoFree(WhereInfo *pWInfo){
+static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
if( pWInfo ){
int i;
for(i=0; i<pWInfo->nLevel; i++){
sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
if( pInfo ){
assert( pInfo->needToFreeIdxStr==0 );
- sqlite3_free(pInfo);
- }
- }
- sqlite3_free(pWInfo);
+ sqlite3DbFree(db, pInfo);
+ }
+ }
+ sqlite3DbFree(db, pWInfo);
}
}
@@ -74739,9 +77734,9 @@
db = pParse->db;
pWInfo = sqlite3DbMallocZero(db,
sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
if( db->mallocFailed ){
- goto whereBeginNoMem;
+ goto whereBeginError;
}
pWInfo->nLevel = pTabList->nSrc;
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
@@ -74786,9 +77781,9 @@
** and work forward so that the added virtual terms are never processed.
*/
exprAnalyzeAll(pTabList, &wc);
if( db->mallocFailed ){
- goto whereBeginNoMem;
+ goto whereBeginError;
}
/* Chose the best index to use for each table in the FROM clause.
**
@@ -74796,9 +77791,9 @@
**
** 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
**
** This loop also figures out the nesting order of tables in the FROM
@@ -74893,8 +77888,20 @@
pLevel->iIdxCur = -1;
}
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"));
/* If the total query only selects a single row, then the ORDER BY
@@ -74930,32 +77937,32 @@
char *zMsg;
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
zMsg = sqlite3MPrintf(db, "TABLE %s", pItem->zName);
if( pItem->zAlias ){
- zMsg = sqlite3MPrintf(db, "%z AS %s", zMsg, pItem->zAlias);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
}
if( (pIx = pLevel->pIdx)!=0 ){
- zMsg = sqlite3MPrintf(db, "%z WITH INDEX %s", zMsg, pIx->zName);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s", zMsg, pIx->zName);
}else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
- zMsg = sqlite3MPrintf(db, "%z USING PRIMARY KEY", zMsg);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s USING PRIMARY KEY", zMsg);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( pLevel->pBestIdx ){
sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
- zMsg = sqlite3MPrintf(db, "%z VIRTUAL TABLE INDEX %d:%s", zMsg,
+ zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
pBestIdx->idxNum, pBestIdx->idxStr);
}
#endif
if( pLevel->flags & WHERE_ORDERBY ){
- zMsg = sqlite3MPrintf(db, "%z ORDER BY", zMsg);
+ zMsg = sqlite3MAppendf(db, zMsg, "%s ORDER BY", zMsg);
}
sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel->iFrom, 0, zMsg, P4_DYNAMIC);
}
#endif /* SQLITE_OMIT_EXPLAIN */
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- if( pTab->isEphem || pTab->pSelect ) continue;
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( pLevel->pBestIdx ){
int iCur = pTabItem->iCursor;
sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0,
@@ -74993,9 +78000,9 @@
** program.
*/
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 */
int iIdxCur; /* The VDBE cursor for the index */
@@ -75086,17 +78093,19 @@
** we reference multiple rows using a "rowid IN (...)"
** 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 ){
/* Case 2: We have an inequality comparison against the ROWID field.
@@ -75351,14 +78360,16 @@
assert( bRev==0 );
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 );
testcase( pTerm->flags & TERM_CODED );
@@ -75368,9 +78379,12 @@
assert( pE!=0 );
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;
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
@@ -75450,11 +78464,11 @@
whereClauseClear(&wc);
return pWInfo;
/* Jump here if malloc fails */
-whereBeginNoMem:
+whereBeginError:
whereClauseClear(&wc);
- whereInfoFree(pWInfo);
+ whereInfoFree(db, pWInfo);
return 0;
}
/*
@@ -75461,21 +78475,24 @@
** Generate the end of the WHERE loop. See comments on
** sqlite3WhereBegin() for additional information.
*/
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
- Vdbe *v = pWInfo->pParse->pVdbe;
+ Parse *pParse = pWInfo->pParse;
+ Vdbe *v = pParse->pVdbe;
int i;
WhereLevel *pLevel;
SrcList *pTabList = pWInfo->pTabList;
+ sqlite3 *db = pParse->db;
/* Generate loop termination code.
*/
- sqlite3ExprClearColumnCache(pWInfo->pParse, -1);
+ sqlite3ExprClearColumnCache(pParse, -1);
for(i=pTabList->nSrc-1; i>=0; i--){
pLevel = &pWInfo->a[i];
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;
int j;
@@ -75484,9 +78501,9 @@
sqlite3VdbeJumpHere(v, pIn->topAddr+1);
sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->topAddr);
sqlite3VdbeJumpHere(v, pIn->topAddr-1);
}
- sqlite3_free(pLevel->aInLoop);
+ sqlite3DbFree(db, pLevel->aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->brk);
if( pLevel->iLeftJoin ){
int addr;
@@ -75510,9 +78527,9 @@
for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
- if( pTab->isEphem || pTab->pSelect ) continue;
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
}
if( pLevel->pIdx!=0 ){
@@ -75563,9 +78580,9 @@
}
/* Final cleanup
*/
- whereInfoFree(pWInfo);
+ whereInfoFree(db, pWInfo);
return;
}
/************** End of where.c ***********************************************/
@@ -75660,25 +78677,25 @@
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
-#define YYNOCODE 248
+#define YYNOCODE 249
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 59
#define sqlite3ParserTOKENTYPE Token
typedef union {
sqlite3ParserTOKENTYPE yy0;
- int yy46;
- struct LikeOp yy72;
- Expr* yy172;
- ExprList* yy174;
- Select* yy219;
- struct LimitVal yy234;
- TriggerStep* yy243;
- struct TrigEvent yy370;
- SrcList* yy373;
- struct {int value; int mask;} yy405;
- IdList* yy432;
+ 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
#endif
@@ -75685,18 +78702,22 @@
#define sqlite3ParserARG_SDECL Parse *pParse;
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 589
-#define YYNRULE 313
+#define YYNSTATE 598
+#define YYNRULE 315
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
+#if 0
+static YYMINORTYPE yyzerominor;
+#else
static const YYMINORTYPE yyzerominor;
+#endif
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
** functions that take a state number and lookahead value and return an
@@ -75744,418 +78765,422 @@
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 292, 903, 124, 588, 409, 172, 2, 418, 61, 61,
- /* 10 */ 61, 61, 519, 63, 63, 63, 63, 64, 64, 65,
- /* 20 */ 65, 65, 66, 210, 447, 212, 425, 431, 68, 63,
- /* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 210,
- /* 40 */ 391, 388, 396, 451, 60, 59, 297, 435, 436, 432,
- /* 50 */ 432, 62, 62, 61, 61, 61, 61, 263, 63, 63,
- /* 60 */ 63, 63, 64, 64, 65, 65, 65, 66, 210, 292,
- /* 70 */ 493, 494, 418, 489, 208, 82, 67, 420, 69, 154,
- /* 80 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
- /* 90 */ 210, 67, 462, 69, 154, 425, 431, 574, 264, 58,
- /* 100 */ 64, 64, 65, 65, 65, 66, 210, 397, 398, 422,
- /* 110 */ 422, 422, 292, 60, 59, 297, 435, 436, 432, 432,
- /* 120 */ 62, 62, 61, 61, 61, 61, 317, 63, 63, 63,
- /* 130 */ 63, 64, 64, 65, 65, 65, 66, 210, 425, 431,
- /* 140 */ 94, 65, 65, 65, 66, 210, 396, 210, 414, 34,
- /* 150 */ 56, 298, 442, 443, 410, 418, 60, 59, 297, 435,
- /* 160 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 208,
- /* 170 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
- /* 180 */ 210, 292, 372, 524, 295, 572, 113, 408, 522, 451,
- /* 190 */ 331, 317, 407, 20, 244, 340, 519, 396, 478, 531,
- /* 200 */ 505, 447, 212, 571, 570, 245, 530, 425, 431, 149,
- /* 210 */ 150, 397, 398, 414, 41, 211, 151, 533, 488, 489,
- /* 220 */ 418, 568, 569, 420, 292, 60, 59, 297, 435, 436,
- /* 230 */ 432, 432, 62, 62, 61, 61, 61, 61, 317, 63,
- /* 240 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 210,
- /* 250 */ 425, 431, 447, 333, 215, 422, 422, 422, 363, 299,
- /* 260 */ 414, 41, 397, 398, 366, 567, 211, 292, 60, 59,
- /* 270 */ 297, 435, 436, 432, 432, 62, 62, 61, 61, 61,
- /* 280 */ 61, 396, 63, 63, 63, 63, 64, 64, 65, 65,
- /* 290 */ 65, 66, 210, 425, 431, 491, 300, 524, 474, 66,
- /* 300 */ 210, 214, 474, 229, 411, 286, 534, 20, 449, 523,
- /* 310 */ 168, 60, 59, 297, 435, 436, 432, 432, 62, 62,
- /* 320 */ 61, 61, 61, 61, 474, 63, 63, 63, 63, 64,
- /* 330 */ 64, 65, 65, 65, 66, 210, 209, 480, 317, 77,
- /* 340 */ 292, 239, 300, 55, 484, 490, 397, 398, 181, 547,
- /* 350 */ 494, 345, 348, 349, 67, 152, 69, 154, 339, 524,
- /* 360 */ 414, 35, 350, 241, 221, 370, 425, 431, 579, 20,
- /* 370 */ 164, 118, 243, 343, 248, 344, 176, 322, 442, 443,
- /* 380 */ 414, 3, 80, 252, 60, 59, 297, 435, 436, 432,
- /* 390 */ 432, 62, 62, 61, 61, 61, 61, 174, 63, 63,
- /* 400 */ 63, 63, 64, 64, 65, 65, 65, 66, 210, 292,
- /* 410 */ 221, 550, 236, 487, 510, 353, 317, 118, 243, 343,
- /* 420 */ 248, 344, 176, 181, 317, 532, 345, 348, 349, 252,
- /* 430 */ 223, 415, 155, 464, 511, 425, 431, 350, 414, 34,
- /* 440 */ 465, 211, 177, 175, 160, 525, 414, 34, 338, 549,
- /* 450 */ 449, 323, 168, 60, 59, 297, 435, 436, 432, 432,
- /* 460 */ 62, 62, 61, 61, 61, 61, 415, 63, 63, 63,
- /* 470 */ 63, 64, 64, 65, 65, 65, 66, 210, 292, 542,
- /* 480 */ 335, 517, 504, 541, 456, 572, 302, 19, 331, 144,
- /* 490 */ 317, 390, 317, 330, 2, 362, 457, 294, 483, 373,
- /* 500 */ 269, 268, 252, 571, 425, 431, 589, 391, 388, 458,
- /* 510 */ 208, 495, 414, 49, 414, 49, 303, 586, 894, 230,
- /* 520 */ 894, 496, 60, 59, 297, 435, 436, 432, 432, 62,
- /* 530 */ 62, 61, 61, 61, 61, 201, 63, 63, 63, 63,
- /* 540 */ 64, 64, 65, 65, 65, 66, 210, 292, 317, 181,
- /* 550 */ 439, 255, 345, 348, 349, 370, 153, 583, 308, 251,
- /* 560 */ 309, 452, 76, 350, 78, 382, 211, 426, 427, 415,
- /* 570 */ 414, 27, 319, 425, 431, 440, 1, 22, 586, 893,
- /* 580 */ 396, 893, 544, 478, 320, 263, 438, 438, 429, 430,
- /* 590 */ 415, 60, 59, 297, 435, 436, 432, 432, 62, 62,
- /* 600 */ 61, 61, 61, 61, 237, 63, 63, 63, 63, 64,
- /* 610 */ 64, 65, 65, 65, 66, 210, 292, 428, 583, 374,
- /* 620 */ 224, 93, 517, 9, 159, 396, 557, 396, 456, 67,
- /* 630 */ 396, 69, 154, 399, 400, 401, 320, 328, 438, 438,
- /* 640 */ 457, 336, 425, 431, 361, 397, 398, 320, 433, 438,
- /* 650 */ 438, 582, 291, 458, 238, 327, 318, 222, 546, 292,
- /* 660 */ 60, 59, 297, 435, 436, 432, 432, 62, 62, 61,
- /* 670 */ 61, 61, 61, 225, 63, 63, 63, 63, 64, 64,
- /* 680 */ 65, 65, 65, 66, 210, 425, 431, 482, 313, 392,
- /* 690 */ 397, 398, 397, 398, 207, 397, 398, 825, 273, 517,
- /* 700 */ 251, 200, 292, 60, 59, 297, 435, 436, 432, 432,
- /* 710 */ 62, 62, 61, 61, 61, 61, 470, 63, 63, 63,
- /* 720 */ 63, 64, 64, 65, 65, 65, 66, 210, 425, 431,
- /* 730 */ 171, 160, 263, 263, 304, 415, 276, 395, 274, 263,
- /* 740 */ 517, 517, 263, 517, 192, 292, 60, 70, 297, 435,
- /* 750 */ 436, 432, 432, 62, 62, 61, 61, 61, 61, 379,
- /* 760 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66,
- /* 770 */ 210, 425, 431, 384, 559, 305, 306, 251, 415, 320,
- /* 780 */ 560, 438, 438, 561, 540, 360, 540, 387, 292, 196,
- /* 790 */ 59, 297, 435, 436, 432, 432, 62, 62, 61, 61,
- /* 800 */ 61, 61, 371, 63, 63, 63, 63, 64, 64, 65,
- /* 810 */ 65, 65, 66, 210, 425, 431, 396, 275, 251, 251,
- /* 820 */ 172, 250, 418, 415, 386, 367, 178, 179, 180, 469,
- /* 830 */ 311, 123, 156, 5, 297, 435, 436, 432, 432, 62,
- /* 840 */ 62, 61, 61, 61, 61, 317, 63, 63, 63, 63,
- /* 850 */ 64, 64, 65, 65, 65, 66, 210, 72, 324, 194,
- /* 860 */ 4, 317, 263, 317, 296, 263, 415, 414, 28, 317,
- /* 870 */ 257, 317, 321, 72, 324, 317, 4, 119, 165, 177,
- /* 880 */ 296, 397, 398, 414, 23, 414, 32, 418, 321, 326,
- /* 890 */ 421, 414, 53, 414, 52, 317, 158, 414, 98, 451,
- /* 900 */ 317, 263, 317, 277, 317, 326, 378, 471, 261, 317,
- /* 910 */ 259, 18, 478, 445, 445, 451, 317, 414, 96, 75,
- /* 920 */ 74, 469, 414, 101, 414, 102, 414, 112, 73, 315,
- /* 930 */ 316, 414, 114, 420, 294, 75, 74, 481, 414, 16,
- /* 940 */ 381, 317, 279, 467, 73, 315, 316, 72, 324, 420,
- /* 950 */ 4, 208, 317, 183, 296, 317, 186, 128, 84, 208,
- /* 960 */ 8, 341, 321, 414, 99, 422, 422, 422, 423, 424,
- /* 970 */ 11, 623, 380, 307, 414, 33, 413, 414, 97, 326,
- /* 980 */ 412, 422, 422, 422, 423, 424, 11, 415, 413, 451,
- /* 990 */ 415, 162, 412, 317, 499, 500, 226, 227, 228, 104,
- /* 1000 */ 448, 476, 317, 173, 507, 317, 509, 508, 317, 75,
- /* 1010 */ 74, 329, 205, 21, 281, 414, 24, 418, 73, 315,
- /* 1020 */ 316, 282, 317, 420, 414, 54, 460, 414, 115, 317,
- /* 1030 */ 414, 116, 502, 203, 147, 549, 514, 468, 128, 202,
- /* 1040 */ 317, 473, 204, 317, 414, 117, 317, 477, 317, 584,
- /* 1050 */ 317, 414, 25, 317, 249, 422, 422, 422, 423, 424,
- /* 1060 */ 11, 506, 414, 36, 512, 414, 37, 317, 414, 26,
- /* 1070 */ 414, 38, 414, 39, 526, 414, 40, 317, 254, 317,
- /* 1080 */ 128, 317, 418, 317, 256, 377, 278, 268, 585, 414,
- /* 1090 */ 42, 293, 317, 352, 317, 128, 208, 513, 258, 414,
- /* 1100 */ 43, 414, 44, 414, 29, 414, 30, 545, 260, 128,
- /* 1110 */ 317, 553, 317, 173, 414, 45, 414, 46, 317, 262,
- /* 1120 */ 383, 554, 317, 91, 564, 317, 91, 317, 581, 189,
- /* 1130 */ 290, 357, 414, 47, 414, 48, 267, 365, 368, 369,
- /* 1140 */ 414, 31, 270, 271, 414, 10, 272, 414, 50, 414,
- /* 1150 */ 51, 556, 566, 280, 283, 284, 578, 146, 419, 405,
- /* 1160 */ 231, 505, 444, 325, 516, 463, 163, 446, 552, 394,
- /* 1170 */ 466, 563, 246, 515, 518, 520, 402, 403, 404, 7,
- /* 1180 */ 314, 84, 232, 334, 347, 83, 332, 57, 170, 79,
- /* 1190 */ 213, 461, 125, 85, 337, 342, 492, 502, 497, 301,
- /* 1200 */ 498, 416, 105, 219, 247, 218, 503, 501, 233, 220,
- /* 1210 */ 287, 234, 527, 528, 235, 529, 417, 521, 354, 288,
- /* 1220 */ 184, 121, 185, 240, 535, 475, 242, 356, 187, 479,
- /* 1230 */ 188, 358, 537, 88, 190, 548, 364, 193, 132, 376,
- /* 1240 */ 555, 375, 133, 134, 135, 310, 562, 138, 136, 575,
- /* 1250 */ 576, 577, 580, 100, 393, 406, 217, 142, 624, 625,
- /* 1260 */ 103, 141, 265, 166, 167, 434, 71, 453, 441, 437,
- /* 1270 */ 450, 143, 538, 157, 120, 454, 161, 472, 455, 169,
- /* 1280 */ 459, 81, 6, 12, 13, 92, 95, 126, 216, 127,
- /* 1290 */ 111, 485, 486, 17, 86, 346, 106, 122, 253, 107,
- /* 1300 */ 87, 108, 182, 245, 355, 145, 351, 536, 129, 359,
- /* 1310 */ 312, 130, 543, 173, 539, 266, 191, 109, 289, 551,
- /* 1320 */ 195, 14, 131, 198, 197, 558, 137, 199, 139, 140,
- /* 1330 */ 15, 565, 89, 90, 573, 110, 385, 206, 148, 389,
- /* 1340 */ 285, 587,
+ /* 0 */ 296, 914, 125, 485, 2, 181, 539, 539, 92, 92,
+ /* 10 */ 92, 92, 489, 94, 94, 94, 94, 95, 95, 96,
+ /* 20 */ 96, 96, 76, 215, 264, 303, 527, 518, 57, 94,
+ /* 30 */ 94, 94, 94, 95, 95, 96, 96, 96, 76, 215,
+ /* 40 */ 68, 468, 87, 154, 91, 72, 305, 512, 510, 516,
+ /* 50 */ 516, 93, 93, 92, 92, 92, 92, 217, 94, 94,
+ /* 60 */ 94, 94, 95, 95, 96, 96, 96, 76, 215, 296,
+ /* 70 */ 10, 539, 539, 303, 489, 84, 482, 467, 463, 298,
+ /* 80 */ 94, 94, 94, 94, 95, 95, 96, 96, 96, 76,
+ /* 90 */ 215, 489, 475, 221, 179, 527, 518, 521, 295, 74,
+ /* 100 */ 114, 239, 349, 283, 350, 171, 409, 60, 404, 403,
+ /* 110 */ 536, 567, 256, 91, 72, 305, 512, 510, 516, 516,
+ /* 120 */ 93, 93, 92, 92, 92, 92, 215, 94, 94, 94,
+ /* 130 */ 94, 95, 95, 96, 96, 96, 76, 215, 296, 467,
+ /* 140 */ 463, 221, 415, 531, 531, 531, 482, 192, 114, 239,
+ /* 150 */ 349, 283, 350, 171, 369, 589, 467, 463, 196, 372,
+ /* 160 */ 256, 351, 354, 355, 527, 518, 150, 151, 68, 343,
+ /* 170 */ 87, 154, 356, 454, 323, 68, 409, 87, 154, 557,
+ /* 180 */ 536, 296, 91, 72, 305, 512, 510, 516, 516, 93,
+ /* 190 */ 93, 92, 92, 92, 92, 572, 94, 94, 94, 94,
+ /* 200 */ 95, 95, 96, 96, 96, 76, 215, 527, 518, 76,
+ /* 210 */ 215, 452, 322, 531, 531, 531, 95, 95, 96, 96,
+ /* 220 */ 96, 76, 215, 595, 594, 91, 72, 305, 512, 510,
+ /* 230 */ 516, 516, 93, 93, 92, 92, 92, 92, 233, 94,
+ /* 240 */ 94, 94, 94, 95, 95, 96, 96, 96, 76, 215,
+ /* 250 */ 515, 506, 317, 324, 296, 507, 507, 464, 289, 152,
+ /* 260 */ 157, 379, 257, 232, 462, 318, 513, 547, 342, 489,
+ /* 270 */ 225, 188, 217, 317, 551, 26, 181, 197, 539, 196,
+ /* 280 */ 527, 518, 351, 354, 355, 546, 545, 96, 96, 96,
+ /* 290 */ 76, 215, 231, 356, 548, 551, 33, 86, 91, 72,
+ /* 300 */ 305, 512, 510, 516, 516, 93, 93, 92, 92, 92,
+ /* 310 */ 92, 548, 94, 94, 94, 94, 95, 95, 96, 96,
+ /* 320 */ 96, 76, 215, 296, 492, 210, 549, 196, 108, 317,
+ /* 330 */ 351, 354, 355, 317, 467, 463, 386, 324, 317, 507,
+ /* 340 */ 507, 356, 311, 539, 543, 544, 155, 542, 209, 527,
+ /* 350 */ 518, 551, 33, 407, 291, 551, 44, 486, 553, 172,
+ /* 360 */ 551, 36, 564, 394, 632, 431, 296, 91, 72, 305,
+ /* 370 */ 512, 510, 516, 516, 93, 93, 92, 92, 92, 92,
+ /* 380 */ 548, 94, 94, 94, 94, 95, 95, 96, 96, 96,
+ /* 390 */ 76, 215, 527, 518, 67, 481, 337, 219, 309, 249,
+ /* 400 */ 588, 583, 417, 335, 248, 575, 579, 587, 334, 296,
+ /* 410 */ 91, 72, 305, 512, 510, 516, 516, 93, 93, 92,
+ /* 420 */ 92, 92, 92, 410, 94, 94, 94, 94, 95, 95,
+ /* 430 */ 96, 96, 96, 76, 215, 527, 518, 266, 216, 271,
+ /* 440 */ 446, 246, 238, 452, 244, 56, 310, 499, 498, 284,
+ /* 450 */ 489, 175, 247, 91, 72, 305, 512, 510, 516, 516,
+ /* 460 */ 93, 93, 92, 92, 92, 92, 194, 94, 94, 94,
+ /* 470 */ 94, 95, 95, 96, 96, 96, 76, 215, 359, 421,
+ /* 480 */ 180, 324, 296, 507, 507, 560, 476, 62, 324, 561,
+ /* 490 */ 507, 507, 460, 379, 257, 232, 376, 68, 474, 87,
+ /* 500 */ 154, 457, 526, 523, 217, 194, 408, 418, 527, 518,
+ /* 510 */ 209, 473, 332, 331, 548, 467, 463, 437, 1, 259,
+ /* 520 */ 174, 299, 489, 520, 519, 63, 91, 72, 305, 512,
+ /* 530 */ 510, 516, 516, 93, 93, 92, 92, 92, 92, 377,
+ /* 540 */ 94, 94, 94, 94, 95, 95, 96, 96, 96, 76,
+ /* 550 */ 215, 296, 522, 158, 548, 411, 18, 476, 317, 19,
+ /* 560 */ 299, 380, 220, 317, 554, 256, 173, 159, 156, 474,
+ /* 570 */ 279, 574, 344, 591, 21, 495, 495, 527, 518, 302,
+ /* 580 */ 551, 36, 473, 146, 402, 551, 44, 467, 463, 438,
+ /* 590 */ 905, 573, 905, 457, 597, 91, 72, 305, 512, 510,
+ /* 600 */ 516, 516, 93, 93, 92, 92, 92, 92, 8, 94,
+ /* 610 */ 94, 94, 94, 95, 95, 96, 96, 96, 76, 215,
+ /* 620 */ 296, 554, 363, 335, 584, 433, 317, 218, 346, 525,
+ /* 630 */ 586, 21, 578, 552, 326, 499, 498, 489, 191, 340,
+ /* 640 */ 430, 558, 234, 306, 429, 577, 527, 518, 551, 36,
+ /* 650 */ 201, 164, 170, 558, 149, 590, 368, 537, 441, 547,
+ /* 660 */ 179, 180, 381, 296, 91, 72, 305, 512, 510, 516,
+ /* 670 */ 516, 93, 93, 92, 92, 92, 92, 546, 94, 94,
+ /* 680 */ 94, 94, 95, 95, 96, 96, 96, 76, 215, 527,
+ /* 690 */ 518, 339, 492, 570, 288, 548, 438, 904, 209, 904,
+ /* 700 */ 455, 444, 467, 463, 492, 210, 296, 91, 72, 305,
+ /* 710 */ 512, 510, 516, 516, 93, 93, 92, 92, 92, 92,
+ /* 720 */ 377, 94, 94, 94, 94, 95, 95, 96, 96, 96,
+ /* 730 */ 76, 215, 527, 518, 554, 391, 525, 333, 85, 389,
+ /* 740 */ 209, 837, 373, 470, 21, 486, 327, 172, 282, 296,
+ /* 750 */ 91, 64, 305, 512, 510, 516, 516, 93, 93, 92,
+ /* 760 */ 92, 92, 92, 569, 94, 94, 94, 94, 95, 95,
+ /* 770 */ 96, 96, 96, 76, 215, 527, 518, 598, 534, 395,
+ /* 780 */ 425, 366, 425, 494, 290, 294, 393, 388, 445, 434,
+ /* 790 */ 426, 89, 296, 70, 72, 305, 512, 510, 516, 516,
+ /* 800 */ 93, 93, 92, 92, 92, 92, 217, 94, 94, 94,
+ /* 810 */ 94, 95, 95, 96, 96, 96, 76, 215, 527, 518,
+ /* 820 */ 387, 358, 533, 175, 80, 504, 20, 23, 144, 489,
+ /* 830 */ 288, 489, 534, 395, 288, 446, 437, 175, 305, 512,
+ /* 840 */ 510, 516, 516, 93, 93, 92, 92, 92, 92, 217,
+ /* 850 */ 94, 94, 94, 94, 95, 95, 96, 96, 96, 76,
+ /* 860 */ 215, 69, 328, 378, 4, 169, 22, 317, 315, 288,
+ /* 870 */ 539, 505, 193, 159, 224, 500, 325, 304, 118, 345,
+ /* 880 */ 347, 6, 317, 458, 260, 69, 328, 446, 4, 551,
+ /* 890 */ 35, 317, 315, 330, 467, 463, 467, 463, 316, 548,
+ /* 900 */ 325, 551, 3, 482, 551, 100, 317, 560, 317, 288,
+ /* 910 */ 286, 561, 592, 551, 48, 437, 317, 330, 317, 313,
+ /* 920 */ 449, 317, 453, 83, 77, 420, 280, 482, 551, 49,
+ /* 930 */ 551, 28, 90, 320, 321, 539, 487, 536, 551, 47,
+ /* 940 */ 551, 11, 236, 551, 46, 317, 275, 83, 77, 203,
+ /* 950 */ 508, 443, 568, 175, 175, 252, 90, 320, 321, 317,
+ /* 960 */ 270, 536, 440, 2, 317, 436, 317, 551, 98, 288,
+ /* 970 */ 531, 531, 531, 529, 528, 16, 288, 367, 317, 217,
+ /* 980 */ 317, 551, 29, 548, 260, 189, 551, 24, 551, 43,
+ /* 990 */ 268, 230, 254, 104, 531, 531, 531, 529, 528, 16,
+ /* 1000 */ 551, 17, 551, 54, 288, 371, 187, 202, 258, 317,
+ /* 1010 */ 211, 69, 328, 580, 4, 240, 317, 212, 315, 223,
+ /* 1020 */ 483, 160, 80, 376, 439, 317, 325, 168, 317, 452,
+ /* 1030 */ 374, 551, 42, 165, 317, 447, 186, 317, 551, 31,
+ /* 1040 */ 317, 548, 317, 330, 317, 237, 317, 551, 55, 317,
+ /* 1050 */ 551, 41, 471, 482, 317, 548, 551, 45, 288, 551,
+ /* 1060 */ 37, 206, 551, 110, 551, 112, 551, 25, 551, 34,
+ /* 1070 */ 317, 551, 50, 83, 77, 269, 551, 27, 317, 384,
+ /* 1080 */ 241, 232, 90, 320, 321, 297, 317, 536, 317, 213,
+ /* 1090 */ 217, 317, 551, 32, 317, 548, 317, 260, 260, 511,
+ /* 1100 */ 551, 113, 260, 450, 403, 317, 253, 317, 551, 51,
+ /* 1110 */ 551, 39, 491, 551, 40, 390, 551, 52, 551, 38,
+ /* 1120 */ 531, 531, 531, 529, 528, 16, 255, 551, 30, 551,
+ /* 1130 */ 111, 317, 314, 312, 317, 273, 317, 308, 317, 375,
+ /* 1140 */ 317, 115, 317, 497, 582, 267, 559, 496, 162, 245,
+ /* 1150 */ 242, 235, 263, 551, 53, 532, 551, 99, 551, 97,
+ /* 1160 */ 551, 102, 551, 103, 551, 109, 493, 243, 385, 524,
+ /* 1170 */ 329, 538, 466, 261, 148, 556, 400, 563, 465, 461,
+ /* 1180 */ 185, 562, 413, 117, 353, 565, 182, 250, 65, 583,
+ /* 1190 */ 469, 136, 207, 214, 134, 360, 204, 126, 348, 406,
+ /* 1200 */ 581, 362, 451, 75, 129, 85, 541, 200, 397, 398,
+ /* 1210 */ 300, 596, 199, 517, 383, 251, 133, 592, 501, 593,
+ /* 1220 */ 488, 422, 405, 71, 227, 190, 555, 262, 338, 131,
+ /* 1230 */ 274, 382, 88, 341, 122, 265, 293, 442, 120, 423,
+ /* 1240 */ 142, 370, 132, 428, 566, 73, 277, 222, 228, 176,
+ /* 1250 */ 336, 278, 66, 7, 319, 307, 585, 540, 281, 571,
+ /* 1260 */ 79, 364, 478, 107, 416, 576, 427, 101, 163, 419,
+ /* 1270 */ 292, 530, 226, 399, 105, 633, 634, 285, 208, 514,
+ /* 1280 */ 509, 82, 480, 503, 484, 145, 161, 167, 479, 477,
+ /* 1290 */ 448, 119, 472, 5, 14, 61, 12, 137, 301, 177,
+ /* 1300 */ 435, 139, 153, 414, 412, 229, 78, 116, 124, 195,
+ /* 1310 */ 272, 123, 81, 121, 247, 361, 143, 401, 141, 179,
+ /* 1320 */ 352, 357, 365, 276, 178, 140, 138, 432, 9, 456,
+ /* 1330 */ 424, 135, 183, 13, 184, 490, 205, 502, 130, 198,
+ /* 1340 */ 128, 127, 166, 15, 106, 550, 147, 287, 535, 396,
+ /* 1350 */ 915, 459, 915, 59, 915, 392, 58,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 16, 139, 140, 141, 168, 21, 144, 23, 69, 70,
- /* 10 */ 71, 72, 176, 74, 75, 76, 77, 78, 79, 80,
- /* 20 */ 81, 82, 83, 84, 78, 79, 42, 43, 73, 74,
+ /* 0 */ 16, 140, 141, 142, 143, 21, 23, 23, 69, 70,
+ /* 10 */ 71, 72, 23, 74, 75, 76, 77, 78, 79, 80,
+ /* 20 */ 81, 82, 83, 84, 205, 16, 42, 43, 73, 74,
/* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 40 */ 1, 2, 23, 58, 60, 61, 62, 63, 64, 65,
- /* 50 */ 66, 67, 68, 69, 70, 71, 72, 147, 74, 75,
+ /* 40 */ 219, 220, 221, 222, 60, 61, 62, 63, 64, 65,
+ /* 50 */ 66, 67, 68, 69, 70, 71, 72, 110, 74, 75,
/* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 70 */ 185, 186, 88, 88, 110, 22, 217, 92, 219, 220,
+ /* 70 */ 19, 88, 88, 16, 23, 22, 58, 88, 89, 151,
/* 80 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 90 */ 84, 217, 218, 219, 220, 42, 43, 238, 188, 46,
- /* 100 */ 78, 79, 80, 81, 82, 83, 84, 88, 89, 124,
- /* 110 */ 125, 126, 16, 60, 61, 62, 63, 64, 65, 66,
- /* 120 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76,
- /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43,
- /* 140 */ 44, 80, 81, 82, 83, 84, 23, 84, 169, 170,
- /* 150 */ 19, 164, 165, 166, 23, 23, 60, 61, 62, 63,
- /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 110,
- /* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 180 */ 84, 16, 123, 147, 150, 147, 21, 167, 168, 58,
- /* 190 */ 211, 147, 156, 157, 92, 216, 176, 23, 147, 176,
- /* 200 */ 177, 78, 79, 165, 166, 103, 183, 42, 43, 78,
- /* 210 */ 79, 88, 89, 169, 170, 228, 180, 181, 169, 88,
- /* 220 */ 88, 98, 99, 92, 16, 60, 61, 62, 63, 64,
- /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 147, 74,
+ /* 90 */ 84, 23, 20, 84, 22, 42, 43, 245, 246, 46,
+ /* 100 */ 91, 92, 93, 94, 95, 96, 88, 19, 186, 187,
+ /* 110 */ 92, 23, 103, 60, 61, 62, 63, 64, 65, 66,
+ /* 120 */ 67, 68, 69, 70, 71, 72, 84, 74, 75, 76,
+ /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 88,
+ /* 140 */ 89, 84, 20, 125, 126, 127, 58, 90, 91, 92,
+ /* 150 */ 93, 94, 95, 96, 226, 182, 88, 89, 90, 231,
+ /* 160 */ 103, 93, 94, 95, 42, 43, 78, 79, 219, 16,
+ /* 170 */ 221, 222, 104, 11, 16, 219, 88, 221, 222, 182,
+ /* 180 */ 92, 16, 60, 61, 62, 63, 64, 65, 66, 67,
+ /* 190 */ 68, 69, 70, 71, 72, 239, 74, 75, 76, 77,
+ /* 200 */ 78, 79, 80, 81, 82, 83, 84, 42, 43, 83,
+ /* 210 */ 84, 49, 148, 125, 126, 127, 78, 79, 80, 81,
+ /* 220 */ 82, 83, 84, 7, 8, 60, 61, 62, 63, 64,
+ /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 148, 74,
/* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 250 */ 42, 43, 78, 209, 210, 124, 125, 126, 224, 208,
- /* 260 */ 169, 170, 88, 89, 230, 227, 228, 16, 60, 61,
- /* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 280 */ 72, 23, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 290 */ 82, 83, 84, 42, 43, 160, 16, 147, 161, 83,
- /* 300 */ 84, 210, 161, 153, 169, 158, 156, 157, 161, 162,
- /* 310 */ 163, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 320 */ 69, 70, 71, 72, 161, 74, 75, 76, 77, 78,
- /* 330 */ 79, 80, 81, 82, 83, 84, 192, 200, 147, 131,
- /* 340 */ 16, 200, 16, 199, 20, 169, 88, 89, 90, 185,
- /* 350 */ 186, 93, 94, 95, 217, 22, 219, 220, 147, 147,
- /* 360 */ 169, 170, 104, 200, 84, 147, 42, 43, 156, 157,
- /* 370 */ 90, 91, 92, 93, 94, 95, 96, 164, 165, 166,
- /* 380 */ 169, 170, 131, 103, 60, 61, 62, 63, 64, 65,
- /* 390 */ 66, 67, 68, 69, 70, 71, 72, 155, 74, 75,
- /* 400 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 410 */ 84, 11, 221, 20, 30, 16, 147, 91, 92, 93,
- /* 420 */ 94, 95, 96, 90, 147, 181, 93, 94, 95, 103,
- /* 430 */ 212, 189, 155, 27, 50, 42, 43, 104, 169, 170,
- /* 440 */ 34, 228, 43, 201, 202, 181, 169, 170, 206, 49,
- /* 450 */ 161, 162, 163, 60, 61, 62, 63, 64, 65, 66,
- /* 460 */ 67, 68, 69, 70, 71, 72, 189, 74, 75, 76,
- /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 25,
- /* 480 */ 211, 147, 20, 29, 12, 147, 102, 19, 211, 21,
- /* 490 */ 147, 141, 147, 216, 144, 41, 24, 98, 20, 99,
- /* 500 */ 100, 101, 103, 165, 42, 43, 0, 1, 2, 37,
- /* 510 */ 110, 39, 169, 170, 169, 170, 182, 19, 20, 190,
- /* 520 */ 22, 49, 60, 61, 62, 63, 64, 65, 66, 67,
- /* 530 */ 68, 69, 70, 71, 72, 155, 74, 75, 76, 77,
- /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 147, 90,
- /* 550 */ 20, 20, 93, 94, 95, 147, 155, 59, 215, 225,
- /* 560 */ 215, 20, 130, 104, 132, 227, 228, 42, 43, 189,
- /* 570 */ 169, 170, 16, 42, 43, 20, 19, 22, 19, 20,
- /* 580 */ 23, 22, 18, 147, 106, 147, 108, 109, 63, 64,
- /* 590 */ 189, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 600 */ 69, 70, 71, 72, 147, 74, 75, 76, 77, 78,
- /* 610 */ 79, 80, 81, 82, 83, 84, 16, 92, 59, 55,
- /* 620 */ 212, 21, 147, 19, 147, 23, 188, 23, 12, 217,
- /* 630 */ 23, 219, 220, 7, 8, 9, 106, 186, 108, 109,
- /* 640 */ 24, 147, 42, 43, 208, 88, 89, 106, 92, 108,
- /* 650 */ 109, 244, 245, 37, 147, 39, 147, 182, 94, 16,
- /* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- /* 670 */ 70, 71, 72, 145, 74, 75, 76, 77, 78, 79,
- /* 680 */ 80, 81, 82, 83, 84, 42, 43, 80, 142, 143,
- /* 690 */ 88, 89, 88, 89, 148, 88, 89, 133, 14, 147,
- /* 700 */ 225, 155, 16, 60, 61, 62, 63, 64, 65, 66,
- /* 710 */ 67, 68, 69, 70, 71, 72, 114, 74, 75, 76,
- /* 720 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43,
- /* 730 */ 201, 202, 147, 147, 182, 189, 52, 147, 54, 147,
- /* 740 */ 147, 147, 147, 147, 155, 16, 60, 61, 62, 63,
- /* 750 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 213,
- /* 760 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 770 */ 84, 42, 43, 188, 188, 182, 182, 225, 189, 106,
- /* 780 */ 188, 108, 109, 188, 99, 100, 101, 241, 16, 155,
- /* 790 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- /* 800 */ 71, 72, 213, 74, 75, 76, 77, 78, 79, 80,
- /* 810 */ 81, 82, 83, 84, 42, 43, 23, 133, 225, 225,
- /* 820 */ 21, 225, 23, 189, 239, 236, 99, 100, 101, 22,
- /* 830 */ 242, 243, 155, 191, 62, 63, 64, 65, 66, 67,
- /* 840 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77,
- /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 22,
- /* 860 */ 19, 147, 147, 147, 23, 147, 189, 169, 170, 147,
- /* 870 */ 14, 147, 31, 16, 17, 147, 19, 147, 19, 43,
- /* 880 */ 23, 88, 89, 169, 170, 169, 170, 88, 31, 48,
- /* 890 */ 147, 169, 170, 169, 170, 147, 89, 169, 170, 58,
- /* 900 */ 147, 147, 147, 188, 147, 48, 188, 114, 52, 147,
- /* 910 */ 54, 19, 147, 124, 125, 58, 147, 169, 170, 78,
- /* 920 */ 79, 114, 169, 170, 169, 170, 169, 170, 87, 88,
- /* 930 */ 89, 169, 170, 92, 98, 78, 79, 80, 169, 170,
- /* 940 */ 91, 147, 188, 22, 87, 88, 89, 16, 17, 92,
- /* 950 */ 19, 110, 147, 155, 23, 147, 155, 22, 121, 110,
- /* 960 */ 68, 80, 31, 169, 170, 124, 125, 126, 127, 128,
- /* 970 */ 129, 112, 123, 208, 169, 170, 107, 169, 170, 48,
- /* 980 */ 111, 124, 125, 126, 127, 128, 129, 189, 107, 58,
- /* 990 */ 189, 5, 111, 147, 7, 8, 10, 11, 12, 13,
- /* 1000 */ 161, 20, 147, 22, 178, 147, 91, 92, 147, 78,
- /* 1010 */ 79, 147, 26, 19, 28, 169, 170, 23, 87, 88,
- /* 1020 */ 89, 35, 147, 92, 169, 170, 147, 169, 170, 147,
- /* 1030 */ 169, 170, 97, 47, 113, 49, 20, 203, 22, 53,
- /* 1040 */ 147, 147, 56, 147, 169, 170, 147, 147, 147, 20,
- /* 1050 */ 147, 169, 170, 147, 147, 124, 125, 126, 127, 128,
- /* 1060 */ 129, 147, 169, 170, 178, 169, 170, 147, 169, 170,
- /* 1070 */ 169, 170, 169, 170, 147, 169, 170, 147, 20, 147,
- /* 1080 */ 22, 147, 88, 147, 147, 99, 100, 101, 59, 169,
- /* 1090 */ 170, 105, 147, 20, 147, 22, 110, 178, 147, 169,
- /* 1100 */ 170, 169, 170, 169, 170, 169, 170, 20, 147, 22,
- /* 1110 */ 147, 20, 147, 22, 169, 170, 169, 170, 147, 147,
- /* 1120 */ 134, 20, 147, 22, 20, 147, 22, 147, 20, 232,
- /* 1130 */ 22, 233, 169, 170, 169, 170, 147, 147, 147, 147,
- /* 1140 */ 169, 170, 147, 147, 169, 170, 147, 169, 170, 169,
- /* 1150 */ 170, 147, 147, 147, 147, 147, 147, 191, 161, 149,
- /* 1160 */ 193, 177, 229, 223, 161, 172, 6, 229, 194, 146,
- /* 1170 */ 172, 194, 172, 172, 172, 161, 146, 146, 146, 22,
- /* 1180 */ 154, 121, 194, 118, 173, 119, 116, 120, 112, 130,
- /* 1190 */ 222, 152, 152, 98, 115, 98, 171, 97, 171, 40,
- /* 1200 */ 179, 189, 19, 84, 171, 226, 171, 173, 195, 226,
- /* 1210 */ 174, 196, 171, 171, 197, 171, 198, 179, 15, 174,
- /* 1220 */ 151, 60, 151, 204, 152, 205, 204, 152, 151, 205,
- /* 1230 */ 152, 38, 152, 130, 151, 184, 152, 184, 19, 15,
- /* 1240 */ 194, 152, 187, 187, 187, 152, 194, 184, 187, 33,
- /* 1250 */ 152, 152, 137, 159, 1, 20, 175, 214, 112, 112,
- /* 1260 */ 175, 214, 234, 112, 112, 92, 19, 11, 20, 107,
- /* 1270 */ 20, 19, 235, 19, 32, 20, 112, 114, 20, 22,
- /* 1280 */ 20, 22, 117, 22, 117, 237, 237, 19, 44, 20,
- /* 1290 */ 240, 20, 20, 231, 19, 44, 19, 243, 20, 19,
- /* 1300 */ 19, 19, 96, 103, 16, 21, 44, 17, 98, 36,
- /* 1310 */ 246, 45, 45, 22, 51, 133, 98, 19, 5, 1,
- /* 1320 */ 122, 19, 102, 14, 113, 17, 113, 115, 102, 122,
- /* 1330 */ 19, 123, 68, 68, 20, 14, 57, 135, 19, 3,
- /* 1340 */ 136, 4,
+ /* 250 */ 92, 20, 148, 106, 16, 108, 109, 27, 20, 22,
+ /* 260 */ 156, 99, 100, 101, 34, 144, 145, 148, 115, 23,
+ /* 270 */ 149, 19, 110, 148, 170, 171, 21, 156, 23, 90,
+ /* 280 */ 42, 43, 93, 94, 95, 166, 167, 80, 81, 82,
+ /* 290 */ 83, 84, 191, 104, 190, 170, 171, 132, 60, 61,
+ /* 300 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
+ /* 310 */ 72, 190, 74, 75, 76, 77, 78, 79, 80, 81,
+ /* 320 */ 82, 83, 84, 16, 78, 79, 20, 90, 21, 148,
+ /* 330 */ 93, 94, 95, 148, 88, 89, 215, 106, 148, 108,
+ /* 340 */ 109, 104, 217, 88, 98, 99, 156, 228, 229, 42,
+ /* 350 */ 43, 170, 171, 161, 159, 170, 171, 162, 163, 164,
+ /* 360 */ 170, 171, 170, 242, 112, 59, 16, 60, 61, 62,
+ /* 370 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ /* 380 */ 190, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ /* 390 */ 83, 84, 42, 43, 44, 20, 211, 212, 217, 14,
+ /* 400 */ 177, 178, 20, 213, 14, 91, 92, 184, 218, 16,
+ /* 410 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ /* 420 */ 70, 71, 72, 170, 74, 75, 76, 77, 78, 79,
+ /* 430 */ 80, 81, 82, 83, 84, 42, 43, 52, 193, 54,
+ /* 440 */ 162, 92, 52, 49, 54, 200, 165, 166, 167, 20,
+ /* 450 */ 23, 22, 103, 60, 61, 62, 63, 64, 65, 66,
+ /* 460 */ 67, 68, 69, 70, 71, 72, 43, 74, 75, 76,
+ /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 201,
+ /* 480 */ 156, 106, 16, 108, 109, 107, 12, 21, 106, 111,
+ /* 490 */ 108, 109, 22, 99, 100, 101, 148, 219, 24, 221,
+ /* 500 */ 222, 22, 42, 43, 110, 43, 170, 80, 42, 43,
+ /* 510 */ 229, 37, 187, 39, 190, 88, 89, 148, 19, 134,
+ /* 520 */ 156, 98, 23, 63, 64, 132, 60, 61, 62, 63,
+ /* 530 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 215,
+ /* 540 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ /* 550 */ 84, 16, 92, 148, 190, 20, 232, 12, 148, 19,
+ /* 560 */ 98, 237, 214, 148, 148, 103, 202, 203, 89, 24,
+ /* 570 */ 154, 30, 208, 157, 158, 125, 126, 42, 43, 210,
+ /* 580 */ 170, 171, 37, 113, 39, 170, 171, 88, 89, 19,
+ /* 590 */ 20, 50, 22, 114, 49, 60, 61, 62, 63, 64,
+ /* 600 */ 65, 66, 67, 68, 69, 70, 71, 72, 68, 74,
+ /* 610 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
+ /* 620 */ 16, 148, 234, 213, 20, 18, 148, 212, 218, 59,
+ /* 630 */ 157, 158, 168, 169, 165, 166, 167, 23, 22, 148,
+ /* 640 */ 25, 177, 148, 102, 29, 169, 42, 43, 170, 171,
+ /* 650 */ 99, 100, 101, 177, 181, 182, 41, 148, 20, 148,
+ /* 660 */ 22, 156, 55, 16, 60, 61, 62, 63, 64, 65,
+ /* 670 */ 66, 67, 68, 69, 70, 71, 72, 166, 74, 75,
+ /* 680 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 42,
+ /* 690 */ 43, 213, 78, 179, 148, 190, 19, 20, 229, 22,
+ /* 700 */ 148, 94, 88, 89, 78, 79, 16, 60, 61, 62,
+ /* 710 */ 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+ /* 720 */ 215, 74, 75, 76, 77, 78, 79, 80, 81, 82,
+ /* 730 */ 83, 84, 42, 43, 148, 189, 59, 148, 122, 228,
+ /* 740 */ 229, 134, 237, 157, 158, 162, 163, 164, 148, 16,
+ /* 750 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
+ /* 760 */ 70, 71, 72, 179, 74, 75, 76, 77, 78, 79,
+ /* 770 */ 80, 81, 82, 83, 84, 42, 43, 0, 1, 2,
+ /* 780 */ 99, 100, 101, 20, 148, 22, 240, 91, 7, 8,
+ /* 790 */ 9, 131, 16, 133, 61, 62, 63, 64, 65, 66,
+ /* 800 */ 67, 68, 69, 70, 71, 72, 110, 74, 75, 76,
+ /* 810 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43,
+ /* 820 */ 124, 20, 20, 22, 22, 20, 19, 22, 21, 23,
+ /* 830 */ 148, 23, 1, 2, 148, 162, 148, 22, 62, 63,
+ /* 840 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 110,
+ /* 850 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ /* 860 */ 84, 16, 17, 124, 19, 156, 19, 148, 23, 148,
+ /* 870 */ 23, 189, 202, 203, 201, 189, 31, 243, 244, 148,
+ /* 880 */ 80, 192, 148, 204, 148, 16, 17, 162, 19, 170,
+ /* 890 */ 171, 148, 23, 48, 88, 89, 88, 89, 210, 190,
+ /* 900 */ 31, 170, 171, 58, 170, 171, 148, 107, 148, 148,
+ /* 910 */ 189, 111, 97, 170, 171, 148, 148, 48, 148, 183,
+ /* 920 */ 114, 148, 114, 78, 79, 80, 201, 58, 170, 171,
+ /* 930 */ 170, 171, 87, 88, 89, 88, 162, 92, 170, 171,
+ /* 940 */ 170, 171, 223, 170, 171, 148, 148, 78, 79, 156,
+ /* 950 */ 189, 20, 20, 22, 22, 146, 87, 88, 89, 148,
+ /* 960 */ 148, 92, 142, 143, 148, 148, 148, 170, 171, 148,
+ /* 970 */ 125, 126, 127, 128, 129, 130, 148, 210, 148, 110,
+ /* 980 */ 148, 170, 171, 190, 148, 5, 170, 171, 170, 171,
+ /* 990 */ 10, 11, 12, 13, 125, 126, 127, 128, 129, 130,
+ /* 1000 */ 170, 171, 170, 171, 148, 148, 26, 156, 28, 148,
+ /* 1010 */ 189, 16, 17, 179, 19, 35, 148, 189, 23, 183,
+ /* 1020 */ 20, 156, 22, 148, 148, 148, 31, 47, 148, 49,
+ /* 1030 */ 148, 170, 171, 53, 148, 148, 56, 148, 170, 171,
+ /* 1040 */ 148, 190, 148, 48, 148, 189, 148, 170, 171, 148,
+ /* 1050 */ 170, 171, 148, 58, 148, 190, 170, 171, 148, 170,
+ /* 1060 */ 171, 156, 170, 171, 170, 171, 170, 171, 170, 171,
+ /* 1070 */ 148, 170, 171, 78, 79, 148, 170, 171, 148, 99,
+ /* 1080 */ 100, 101, 87, 88, 89, 105, 148, 92, 148, 214,
+ /* 1090 */ 110, 148, 170, 171, 148, 190, 148, 148, 148, 189,
+ /* 1100 */ 170, 171, 148, 186, 187, 148, 148, 148, 170, 171,
+ /* 1110 */ 170, 171, 148, 170, 171, 135, 170, 171, 170, 171,
+ /* 1120 */ 125, 126, 127, 128, 129, 130, 148, 170, 171, 170,
+ /* 1130 */ 171, 148, 183, 183, 148, 148, 148, 183, 148, 148,
+ /* 1140 */ 148, 148, 148, 230, 148, 148, 148, 148, 233, 148,
+ /* 1150 */ 148, 148, 148, 170, 171, 148, 170, 171, 170, 171,
+ /* 1160 */ 170, 171, 170, 171, 170, 171, 230, 205, 205, 195,
+ /* 1170 */ 225, 162, 195, 194, 192, 162, 150, 162, 173, 173,
+ /* 1180 */ 6, 173, 147, 60, 174, 173, 112, 173, 131, 178,
+ /* 1190 */ 153, 153, 153, 224, 19, 15, 152, 216, 98, 172,
+ /* 1200 */ 33, 153, 185, 238, 185, 122, 190, 152, 172, 153,
+ /* 1210 */ 40, 180, 152, 195, 15, 172, 188, 97, 147, 174,
+ /* 1220 */ 195, 153, 147, 238, 84, 185, 180, 195, 119, 188,
+ /* 1230 */ 196, 153, 98, 117, 19, 206, 175, 207, 188, 147,
+ /* 1240 */ 216, 153, 188, 153, 172, 120, 197, 227, 227, 152,
+ /* 1250 */ 118, 198, 121, 22, 155, 153, 172, 199, 206, 172,
+ /* 1260 */ 131, 38, 138, 241, 153, 172, 207, 160, 112, 236,
+ /* 1270 */ 175, 1, 176, 20, 176, 112, 112, 235, 112, 92,
+ /* 1280 */ 107, 19, 11, 20, 20, 19, 19, 22, 20, 20,
+ /* 1290 */ 114, 244, 20, 116, 116, 22, 22, 19, 247, 116,
+ /* 1300 */ 115, 20, 112, 20, 20, 44, 19, 32, 19, 96,
+ /* 1310 */ 20, 19, 19, 19, 103, 16, 21, 17, 98, 22,
+ /* 1320 */ 44, 44, 36, 134, 98, 45, 19, 45, 5, 1,
+ /* 1330 */ 51, 102, 123, 19, 113, 1, 14, 17, 113, 117,
+ /* 1340 */ 102, 123, 136, 19, 14, 20, 19, 137, 124, 3,
+ /* 1350 */ 248, 4, 248, 68, 248, 57, 68,
};
#define YY_SHIFT_USE_DFLT (-62)
-#define YY_SHIFT_MAX 389
+#define YY_SHIFT_MAX 396
static const short yy_shift_ofst[] = {
- /* 0 */ 39, 841, 986, -16, 841, 931, 931, 258, 123, -36,
- /* 10 */ 96, 931, 931, 931, 931, 931, -45, 400, 174, 19,
- /* 20 */ 132, -54, -54, 53, 165, 208, 251, 324, 393, 462,
- /* 30 */ 531, 600, 643, 686, 643, 643, 643, 643, 643, 643,
- /* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643,
- /* 50 */ 643, 643, 729, 772, 772, 857, 931, 931, 931, 931,
- /* 60 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
- /* 70 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
- /* 80 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
- /* 90 */ 931, 931, 931, 931, 931, 931, -61, -61, 6, 6,
- /* 100 */ 280, 22, 61, 399, 564, 19, 19, 19, 19, 19,
- /* 110 */ 19, 19, 216, 132, 63, -62, -62, -62, 131, 326,
- /* 120 */ 472, 472, 498, 559, 506, 799, 19, 799, 19, 19,
- /* 130 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- /* 140 */ 19, 849, 59, -36, -36, -36, -62, -62, -62, -15,
- /* 150 */ -15, 333, 459, 478, 557, 530, 541, 616, 602, 793,
- /* 160 */ 604, 607, 626, 19, 19, 881, 19, 19, 994, 19,
- /* 170 */ 19, 807, 19, 19, 673, 807, 19, 19, 384, 384,
- /* 180 */ 384, 19, 19, 673, 19, 19, 673, 19, 454, 685,
- /* 190 */ 19, 19, 673, 19, 19, 19, 673, 19, 19, 19,
- /* 200 */ 673, 673, 19, 19, 19, 19, 19, 468, 869, 921,
- /* 210 */ 132, 789, 789, 432, 406, 406, 406, 836, 406, 132,
- /* 220 */ 406, 132, 935, 837, 837, 1160, 1160, 1160, 1160, 1157,
- /* 230 */ -36, 1060, 1065, 1066, 1070, 1067, 1059, 1076, 1076, 1095,
- /* 240 */ 1079, 1095, 1079, 1097, 1097, 1159, 1097, 1100, 1097, 1183,
- /* 250 */ 1119, 1119, 1159, 1097, 1097, 1097, 1183, 1203, 1076, 1203,
- /* 260 */ 1076, 1203, 1076, 1076, 1193, 1103, 1203, 1076, 1161, 1161,
- /* 270 */ 1219, 1060, 1076, 1224, 1224, 1224, 1224, 1060, 1161, 1219,
- /* 280 */ 1076, 1216, 1216, 1076, 1076, 1115, -62, -62, -62, -62,
- /* 290 */ -62, -62, 525, 684, 727, 856, 859, 556, 555, 981,
- /* 300 */ 102, 987, 915, 1016, 1058, 1073, 1087, 1091, 1101, 1104,
- /* 310 */ 892, 1108, 1029, 1253, 1235, 1146, 1147, 1151, 1152, 1173,
- /* 320 */ 1162, 1247, 1248, 1250, 1252, 1256, 1254, 1255, 1257, 1258,
- /* 330 */ 1260, 1259, 1165, 1261, 1167, 1259, 1163, 1268, 1269, 1164,
- /* 340 */ 1271, 1272, 1242, 1244, 1275, 1251, 1277, 1278, 1280, 1281,
- /* 350 */ 1262, 1282, 1206, 1200, 1288, 1290, 1284, 1210, 1273, 1263,
- /* 360 */ 1266, 1291, 1267, 1182, 1218, 1298, 1313, 1318, 1220, 1264,
- /* 370 */ 1265, 1198, 1302, 1211, 1309, 1212, 1308, 1213, 1226, 1207,
- /* 380 */ 1311, 1208, 1314, 1321, 1279, 1202, 1204, 1319, 1336, 1337,
-};
-#define YY_REDUCE_USE_DFLT (-165)
-#define YY_REDUCE_MAX 291
+ /* 0 */ 831, 869, 980, -16, 869, 995, 995, 68, 246, 394,
+ /* 10 */ -53, 350, 995, 995, 995, 995, 995, -45, 162, 614,
+ /* 20 */ -11, -17, 626, 626, 53, 604, 122, 238, 535, 393,
+ /* 30 */ 165, 466, 307, 647, 647, 647, 647, 647, 647, 647,
+ /* 40 */ 647, 647, 647, 647, 647, 647, 647, 647, 647, 647,
+ /* 50 */ 647, 647, 690, 733, 776, 776, 845, 995, 995, 995,
+ /* 60 */ 995, 995, 995, 995, 995, 995, 995, 995, 995, 995,
+ /* 70 */ 995, 995, 995, 995, 995, 995, 995, 995, 995, 995,
+ /* 80 */ 995, 995, 995, 995, 995, 995, 995, 995, 995, 995,
+ /* 90 */ 995, 995, 995, 995, 995, 995, 995, -61, -61, 6,
+ /* 100 */ 6, 57, 138, 207, 607, 462, -11, -11, -17, 126,
+ /* 110 */ 42, -62, -62, -62, 88, 9, 545, 545, 677, 570,
+ /* 120 */ -11, -11, -11, -11, -11, 777, 696, -11, -11, -11,
+ /* 130 */ -11, -11, -11, -11, -11, -11, 255, -11, -11, 255,
+ /* 140 */ -11, -11, 739, -53, -53, -53, -62, -62, -62, 237,
+ /* 150 */ 18, 18, 189, 427, 499, 231, 808, 382, 806, 51,
+ /* 160 */ 375, 474, 681, -11, 541, -11, -11, -11, -11, 147,
+ /* 170 */ 541, -11, 847, 479, 147, -11, -11, -11, -11, -11,
+ /* 180 */ 147, -11, -11, -11, -11, -11, -11, -11, 800, 781,
+ /* 190 */ -11, -11, -11, 479, -11, -11, -11, 147, -11, -11,
+ /* 200 */ -11, 541, 147, 147, -11, -11, 147, 615, -11, 450,
+ /* 210 */ 450, 153, 153, 616, 660, -17, 470, 378, 230, 230,
+ /* 220 */ 616, -17, 230, 815, 153, 807, 423, -17, 230, 230,
+ /* 230 */ 1174, -53, 1123, 1074, 1074, 1074, 1057, 1175, 1180, 1100,
+ /* 240 */ 1167, 1123, 1074, 1083, 1180, 1074, 1100, 1170, 1180, 1199,
+ /* 250 */ 1100, 1120, 1174, 1083, 1174, 1074, 1170, 1123, 1167, 1199,
+ /* 260 */ 1140, 1083, 1109, 1074, 1134, 1116, 1199, 1215, 1174, 1175,
+ /* 270 */ 1074, 1199, 1100, 1074, 1125, 1140, 1180, 1132, 1131, 1231,
+ /* 280 */ 1134, 1116, 1074, 1100, 1100, 1129, 1223, 1124, 1074, 1100,
+ /* 290 */ 1215, -62, -62, -62, -62, -62, 460, 385, 390, 551,
+ /* 300 */ 216, 306, 72, 349, 763, 158, 314, 540, 801, 802,
+ /* 310 */ 805, 1000, 932, 931, 429, 252, 638, 1156, 1270, 1253,
+ /* 320 */ 1163, 1164, 1166, 1187, 1173, 1262, 1263, 1264, 1266, 1271,
+ /* 330 */ 1267, 1268, 1265, 1269, 1272, 1273, 1177, 1274, 1178, 1273,
+ /* 340 */ 1176, 1278, 1183, 1185, 1281, 1190, 1283, 1284, 1275, 1261,
+ /* 350 */ 1287, 1276, 1289, 1290, 1292, 1293, 1277, 1294, 1213, 1211,
+ /* 360 */ 1299, 1300, 1295, 1220, 1286, 1279, 1280, 1297, 1282, 1189,
+ /* 370 */ 1226, 1307, 1323, 1328, 1229, 1285, 1288, 1209, 1314, 1221,
+ /* 380 */ 1334, 1322, 1222, 1320, 1225, 1238, 1218, 1324, 1224, 1325,
+ /* 390 */ 1330, 1298, 1206, 1210, 1327, 1346, 1347,
+};
+#define YY_REDUCE_USE_DFLT (-182)
+#define YY_REDUCE_MAX 295
static const short yy_reduce_ofst[] = {
- /* 0 */ -138, 277, 546, 137, 401, -21, 44, 36, 38, 242,
- /* 10 */ -141, 191, 91, 269, 343, 345, -126, 589, 338, 150,
- /* 20 */ 147, -13, 213, 412, 412, 412, 412, 412, 412, 412,
- /* 30 */ 412, 412, 412, 412, 412, 412, 412, 412, 412, 412,
- /* 40 */ 412, 412, 412, 412, 412, 412, 412, 412, 412, 412,
- /* 50 */ 412, 412, 412, 412, 412, 211, 698, 714, 716, 722,
- /* 60 */ 724, 728, 748, 753, 755, 757, 762, 769, 794, 805,
- /* 70 */ 808, 846, 855, 858, 861, 875, 882, 893, 896, 899,
- /* 80 */ 901, 903, 906, 920, 930, 932, 934, 936, 945, 947,
- /* 90 */ 963, 965, 971, 975, 978, 980, 412, 412, 412, 412,
- /* 100 */ 20, 412, 412, 23, 34, 334, 475, 552, 593, 594,
- /* 110 */ 585, 212, 412, 289, 412, 412, 412, 412, 135, -164,
- /* 120 */ -115, 164, 407, 407, 350, 141, 51, 163, 596, -90,
- /* 130 */ 436, 218, 765, 438, 586, 592, 595, 715, 718, 408,
- /* 140 */ 754, 380, 634, 677, 798, 801, 144, 529, 588, 49,
- /* 150 */ 176, 244, 264, 329, 457, 329, 329, 451, 477, 494,
- /* 160 */ 507, 509, 528, 590, 730, 642, 509, 743, 839, 864,
- /* 170 */ 879, 834, 894, 900, 329, 834, 907, 914, 826, 886,
- /* 180 */ 919, 927, 937, 329, 951, 961, 329, 972, 897, 898,
- /* 190 */ 989, 990, 329, 991, 992, 995, 329, 996, 999, 1004,
- /* 200 */ 329, 329, 1005, 1006, 1007, 1008, 1009, 1010, 966, 967,
- /* 210 */ 997, 933, 938, 940, 993, 998, 1000, 984, 1001, 1003,
- /* 220 */ 1002, 1014, 1011, 974, 977, 1023, 1030, 1031, 1032, 1026,
- /* 230 */ 1012, 988, 1013, 1015, 1017, 1018, 968, 1039, 1040, 1019,
- /* 240 */ 1020, 1022, 1024, 1025, 1027, 1021, 1033, 1034, 1035, 1036,
- /* 250 */ 979, 983, 1038, 1041, 1042, 1044, 1045, 1069, 1072, 1071,
- /* 260 */ 1075, 1077, 1078, 1080, 1028, 1037, 1083, 1084, 1051, 1053,
- /* 270 */ 1043, 1046, 1089, 1055, 1056, 1057, 1061, 1052, 1063, 1047,
- /* 280 */ 1093, 1048, 1049, 1098, 1099, 1050, 1094, 1081, 1085, 1062,
- /* 290 */ 1054, 1064,
+ /* 0 */ -139, 190, 121, 278, 104, 185, 410, 473, 119, 324,
+ /* 10 */ 364, -44, 415, 125, 478, 181, 719, -179, 505, 511,
+ /* 20 */ 416, 195, 281, 469, -51, -51, -51, -51, -51, -51,
+ /* 30 */ -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
+ /* 40 */ -51, -51, -51, -51, -51, -51, -51, -51, -51, -51,
+ /* 50 */ -51, -51, -51, -51, -51, -51, 731, 734, 743, 758,
+ /* 60 */ 760, 768, 770, 773, 797, 811, 816, 818, 830, 832,
+ /* 70 */ 861, 868, 877, 880, 886, 889, 892, 894, 896, 898,
+ /* 80 */ 901, 906, 922, 930, 938, 940, 943, 946, 948, 957,
+ /* 90 */ 959, 983, 986, 988, 990, 992, 994, -51, -51, -51,
+ /* 100 */ -51, 464, -51, -51, -72, 223, 546, 586, 583, -51,
+ /* 110 */ -51, -51, -51, -51, 192, 476, -78, 917, -148, -148,
+ /* 120 */ 910, 954, 950, 949, 836, 820, 905, 856, 875, 828,
+ /* 130 */ 821, 761, 682, 686, 369, 348, 673, 688, 736, 725,
+ /* 140 */ 767, 721, 709, 793, 851, 865, 670, 634, 245, -27,
+ /* 150 */ 253, 336, -3, 64, 90, 101, 405, 101, 491, 494,
+ /* 160 */ 101, 325, 388, 64, 514, 509, 552, 589, 600, 101,
+ /* 170 */ 584, 636, 774, 679, 101, 798, 812, 817, 857, 876,
+ /* 180 */ 101, 887, 904, 927, 958, 964, 978, 987, 689, 809,
+ /* 190 */ 882, 991, 993, 679, 996, 997, 998, 101, 999, 1001,
+ /* 200 */ 1002, 834, 101, 101, 1003, 1004, 101, 915, 1007, 913,
+ /* 210 */ 936, 962, 963, 974, 945, 1009, 979, 982, 1005, 1006,
+ /* 220 */ 977, 1013, 1008, 1010, -181, 1026, 1011, 1015, 1012, 1014,
+ /* 230 */ 1035, 1016, 1017, 1037, 1038, 1039, 969, 981, 1044, 1027,
+ /* 240 */ 965, 1019, 1048, 1018, 1055, 1056, 1036, 1031, 1060, 1028,
+ /* 250 */ 1043, 1045, 1071, 1025, 1075, 1068, 1046, 1040, 985, 1041,
+ /* 260 */ 1020, 1032, 1034, 1078, 1029, 1030, 1050, 1061, 1092, 1024,
+ /* 270 */ 1088, 1054, 1072, 1090, 1049, 1021, 1097, 1053, 1058, 1099,
+ /* 280 */ 1052, 1059, 1102, 1084, 1087, 1033, 1042, 1022, 1111, 1093,
+ /* 290 */ 1095, 1107, 1096, 1098, 1047, 1051,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 595, 820, 902, 710, 902, 820, 902, 902, 848, 714,
- /* 10 */ 877, 818, 902, 902, 902, 902, 792, 902, 848, 902,
- /* 20 */ 626, 848, 848, 743, 902, 902, 902, 902, 902, 902,
- /* 30 */ 902, 902, 744, 902, 822, 817, 813, 815, 814, 821,
- /* 40 */ 745, 734, 741, 748, 726, 861, 750, 751, 757, 758,
- /* 50 */ 878, 876, 780, 779, 798, 902, 902, 902, 902, 902,
- /* 60 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 70 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 80 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 90 */ 902, 902, 902, 902, 902, 902, 782, 804, 781, 791,
- /* 100 */ 619, 783, 784, 679, 614, 902, 902, 902, 902, 902,
- /* 110 */ 902, 902, 785, 902, 786, 799, 800, 801, 902, 902,
- /* 120 */ 902, 902, 902, 902, 595, 710, 902, 710, 902, 902,
- /* 130 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 140 */ 902, 902, 902, 902, 902, 902, 704, 714, 895, 902,
- /* 150 */ 902, 670, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 160 */ 902, 902, 602, 600, 902, 702, 902, 902, 628, 902,
- /* 170 */ 902, 712, 902, 902, 717, 718, 902, 902, 902, 902,
- /* 180 */ 902, 902, 902, 616, 902, 902, 691, 902, 854, 902,
- /* 190 */ 902, 902, 868, 902, 902, 902, 866, 902, 902, 902,
- /* 200 */ 693, 753, 834, 902, 881, 883, 902, 902, 702, 711,
- /* 210 */ 902, 902, 902, 816, 737, 737, 737, 649, 737, 902,
- /* 220 */ 737, 902, 652, 747, 747, 599, 599, 599, 599, 669,
- /* 230 */ 902, 747, 738, 740, 730, 742, 902, 719, 719, 727,
- /* 240 */ 729, 727, 729, 681, 681, 666, 681, 652, 681, 826,
- /* 250 */ 831, 831, 666, 681, 681, 681, 826, 611, 719, 611,
- /* 260 */ 719, 611, 719, 719, 858, 860, 611, 719, 683, 683,
- /* 270 */ 759, 747, 719, 690, 690, 690, 690, 747, 683, 759,
- /* 280 */ 719, 880, 880, 719, 719, 888, 636, 654, 654, 863,
- /* 290 */ 895, 900, 902, 902, 902, 902, 766, 902, 902, 902,
- /* 300 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 310 */ 841, 902, 902, 902, 902, 771, 767, 902, 768, 902,
- /* 320 */ 696, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 330 */ 902, 819, 902, 731, 902, 739, 902, 902, 902, 902,
- /* 340 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 350 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 360 */ 856, 857, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 370 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 380 */ 902, 902, 902, 902, 887, 902, 902, 890, 596, 902,
- /* 390 */ 590, 593, 592, 594, 598, 601, 623, 624, 625, 603,
- /* 400 */ 604, 605, 606, 607, 608, 609, 615, 617, 635, 637,
- /* 410 */ 621, 639, 700, 701, 763, 694, 695, 699, 622, 774,
- /* 420 */ 765, 769, 770, 772, 773, 787, 788, 790, 796, 803,
- /* 430 */ 806, 789, 794, 795, 797, 802, 805, 697, 698, 809,
- /* 440 */ 629, 630, 633, 634, 844, 846, 845, 847, 632, 631,
- /* 450 */ 775, 778, 811, 812, 869, 870, 871, 872, 873, 807,
- /* 460 */ 720, 810, 793, 732, 735, 736, 733, 703, 713, 722,
- /* 470 */ 723, 724, 725, 708, 709, 715, 728, 761, 762, 716,
- /* 480 */ 705, 706, 707, 808, 764, 776, 777, 640, 641, 771,
- /* 490 */ 642, 643, 644, 682, 685, 686, 687, 645, 664, 667,
- /* 500 */ 668, 646, 653, 647, 648, 655, 656, 657, 660, 661,
- /* 510 */ 662, 663, 658, 659, 827, 828, 832, 830, 829, 650,
- /* 520 */ 651, 665, 638, 627, 620, 671, 674, 675, 676, 677,
- /* 530 */ 678, 680, 672, 673, 618, 610, 612, 721, 850, 859,
- /* 540 */ 855, 851, 852, 853, 613, 823, 824, 684, 755, 756,
- /* 550 */ 849, 862, 864, 760, 865, 867, 892, 688, 689, 692,
- /* 560 */ 833, 874, 746, 749, 752, 754, 835, 836, 837, 838,
- /* 570 */ 839, 842, 843, 840, 875, 879, 882, 884, 885, 886,
- /* 580 */ 889, 891, 896, 897, 898, 901, 899, 597, 591,
+ /* 0 */ 603, 832, 913, 719, 913, 913, 832, 913, 859, 913,
+ /* 10 */ 723, 888, 913, 913, 913, 913, 830, 804, 913, 859,
+ /* 20 */ 913, 635, 859, 859, 755, 913, 913, 913, 913, 913,
+ /* 30 */ 913, 913, 913, 770, 872, 829, 834, 887, 735, 760,
+ /* 40 */ 825, 753, 827, 889, 746, 756, 826, 833, 763, 762,
+ /* 50 */ 769, 757, 913, 792, 810, 791, 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, 623, 688, 913, 913, 913, 797,
+ /* 110 */ 798, 811, 812, 813, 913, 913, 913, 913, 913, 913,
+ /* 120 */ 913, 913, 913, 913, 913, 603, 913, 913, 913, 913,
+ /* 130 */ 913, 913, 913, 913, 913, 913, 719, 913, 913, 719,
+ /* 140 */ 913, 913, 913, 913, 913, 913, 723, 906, 713, 679,
+ /* 150 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
+ /* 160 */ 913, 913, 913, 913, 913, 845, 913, 913, 913, 877,
+ /* 170 */ 913, 913, 637, 727, 726, 913, 913, 913, 913, 913,
+ /* 180 */ 879, 913, 913, 913, 913, 609, 892, 894, 711, 611,
+ /* 190 */ 913, 913, 913, 721, 913, 913, 913, 702, 913, 913,
+ /* 200 */ 913, 913, 625, 700, 913, 913, 765, 865, 913, 913,
+ /* 210 */ 913, 737, 737, 759, 828, 913, 720, 711, 749, 749,
+ /* 220 */ 759, 913, 749, 661, 737, 913, 658, 913, 749, 749,
+ /* 230 */ 608, 913, 692, 728, 728, 728, 913, 771, 620, 690,
+ /* 240 */ 891, 692, 728, 759, 620, 728, 690, 675, 620, 699,
+ /* 250 */ 690, 661, 608, 759, 608, 728, 675, 692, 891, 699,
+ /* 260 */ 842, 759, 750, 728, 736, 741, 699, 838, 608, 771,
+ /* 270 */ 728, 699, 690, 728, 752, 842, 620, 742, 754, 678,
+ /* 280 */ 736, 741, 728, 690, 690, 871, 869, 899, 728, 690,
+ /* 290 */ 838, 645, 663, 663, 906, 911, 913, 913, 913, 913,
+ /* 300 */ 913, 913, 913, 913, 913, 913, 913, 852, 913, 913,
+ /* 310 */ 913, 913, 913, 913, 913, 778, 913, 913, 913, 913,
+ /* 320 */ 783, 779, 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, 654, 619, 624,
+ /* 400 */ 618, 621, 695, 694, 691, 617, 653, 652, 651, 783,
+ /* 410 */ 650, 649, 789, 616, 788, 776, 730, 820, 716, 861,
+ /* 420 */ 715, 714, 893, 615, 870, 866, 614, 725, 895, 862,
+ /* 430 */ 863, 912, 864, 622, 613, 739, 738, 774, 910, 773,
+ /* 440 */ 599, 740, 724, 835, 836, 612, 718, 717, 734, 733,
+ /* 450 */ 693, 767, 768, 732, 860, 896, 873, 731, 722, 605,
+ /* 460 */ 712, 745, 748, 634, 747, 744, 875, 633, 805, 822,
+ /* 470 */ 897, 729, 819, 884, 883, 772, 882, 881, 900, 880,
+ /* 480 */ 824, 823, 790, 876, 787, 600, 640, 641, 878, 632,
+ /* 490 */ 874, 610, 858, 856, 902, 857, 903, 855, 643, 642,
+ /* 500 */ 697, 607, 698, 639, 638, 701, 821, 707, 844, 706,
+ /* 510 */ 817, 885, 814, 606, 809, 807, 806, 758, 801, 818,
+ /* 520 */ 815, 907, 808, 802, 761, 908, 800, 799, 785, 784,
+ /* 530 */ 602, 782, 781, 764, 601, 766, 777, 846, 786, 631,
+ /* 540 */ 708, 704, 847, 848, 849, 850, 853, 854, 703, 909,
+ /* 550 */ 851, 775, 647, 636, 629, 674, 660, 680, 659, 683,
+ /* 560 */ 710, 709, 841, 843, 648, 840, 684, 630, 839, 668,
+ /* 570 */ 667, 685, 886, 672, 671, 670, 686, 646, 644, 669,
+ /* 580 */ 666, 890, 665, 664, 657, 656, 626, 687, 689, 681,
+ /* 590 */ 682, 627, 662, 655, 677, 676, 673, 696,
};
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
/* The next table maps tokens into fallback tokens. If a construct
@@ -76284,11 +79309,12 @@
0, /* DISTINCT => nothing */
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 */
0, /* WHERE => nothing */
@@ -76323,20 +79349,23 @@
** the information used by the action routines in the grammar.
** It is sometimes called the "minor" token.
*/
struct yyStackEntry {
- int stateno; /* The state-number */
- int major; /* The major token value. This is the code
- ** number for the token at this stack level */
- YYMINORTYPE minor; /* The user-supplied minor token value. This
- ** is the value of the token */
+ YYACTIONTYPE stateno; /* The state-number */
+ YYCODETYPE major; /* The major token value. This is the code
+ ** number for the token at this stack level */
+ YYMINORTYPE minor; /* The user-supplied minor token value. This
+ ** is the value of the token */
};
typedef struct yyStackEntry yyStackEntry;
/* The state of the parser is completely contained in an instance of
** the following structure */
struct yyParser {
int yyidx; /* Index of top element in stack */
+#ifdef YYTRACKMAXSTACKDEPTH
+ int yyidxMax; /* Maximum value of yyidx */
+#endif
int yyerrcnt; /* Shifts left before out of the error */
sqlite3ParserARG_SDECL /* A place to hold %extra_argument */
#if YYSTACKDEPTH<=0
int yystksz; /* Current side of the stack */
@@ -76409,42 +79438,42 @@
"REFERENCES", "AUTOINCR", "ON", "DELETE",
"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", "cmdx", "cmd",
- "explain", "transtype", "trans_opt", "nm",
- "create_table", "create_table_args", "temp", "ifnotexists",
- "dbnm", "columnlist", "conslist_opt", "select",
- "column", "columnid", "type", "carglist",
- "id", "ids", "typetoken", "typename",
- "signed", "plus_num", "minus_num", "carg",
- "ccons", "term", "expr", "onconf",
- "sortorder", "autoinc", "idxlist_opt", "refargs",
- "defer_subclause", "refarg", "refact", "init_deferred_pred_opt",
- "conslist", "tcons", "idxlist", "defer_subclause_opt",
- "orconf", "resolvetype", "raisetype", "ifexists",
- "fullname", "oneselect", "multiselect_op", "distinct",
- "selcollist", "from", "where_opt", "groupby_opt",
- "having_opt", "orderby_opt", "limit_opt", "sclp",
- "as", "seltablist", "stl_prefix", "joinop",
- "on_opt", "using_opt", "seltablist_paren", "joinop2",
- "inscollist", "sortlist", "sortitem", "nexprlist",
- "setlist", "insert_cmd", "inscollist_opt", "itemlist",
- "exprlist", "likeop", "escape", "between_op",
- "in_op", "case_operand", "case_exprlist", "case_else",
- "uniqueflag", "idxitem", "collate", "nmnum",
- "plus_opt", "number", "trigger_decl", "trigger_cmd_list",
- "trigger_time", "trigger_event", "foreach_clause", "when_clause",
- "trigger_cmd", "database_kw_opt", "key_opt", "add_column_fullname",
- "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg",
- "vtabargtoken", "lp", "anylist",
+ "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 */
#ifndef NDEBUG
@@ -76453,14 +79482,14 @@
static const char *const yyRuleName[] = {
/* 0 */ "input ::= cmdlist",
/* 1 */ "cmdlist ::= cmdlist ecmd",
/* 2 */ "cmdlist ::= ecmd",
- /* 3 */ "cmdx ::= cmd",
- /* 4 */ "ecmd ::= SEMI",
- /* 5 */ "ecmd ::= explain cmdx SEMI",
- /* 6 */ "explain ::=",
- /* 7 */ "explain ::= EXPLAIN",
- /* 8 */ "explain ::= EXPLAIN QUERY PLAN",
+ /* 3 */ "ecmd ::= SEMI",
+ /* 4 */ "ecmd ::= explain cmdx SEMI",
+ /* 5 */ "explain ::=",
+ /* 6 */ "explain ::= EXPLAIN",
+ /* 7 */ "explain ::= EXPLAIN QUERY PLAN",
+ /* 8 */ "cmdx ::= cmd",
/* 9 */ "cmd ::= BEGIN transtype trans_opt",
/* 10 */ "trans_opt ::=",
/* 11 */ "trans_opt ::= TRANSACTION",
/* 12 */ "trans_opt ::= TRANSACTION nm",
@@ -76576,9 +79605,9 @@
/* 122 */ "from ::=",
/* 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",
/* 130 */ "dbnm ::=",
@@ -76589,182 +79618,184 @@
/* 135 */ "joinop ::= JOIN_KW nm JOIN",
/* 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 idxitem collate sortorder",
- /* 240 */ "idxlist ::= idxitem collate sortorder",
- /* 241 */ "idxitem ::= nm",
- /* 242 */ "collate ::=",
- /* 243 */ "collate ::= COLLATE ids",
- /* 244 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 245 */ "cmd ::= VACUUM",
- /* 246 */ "cmd ::= VACUUM nm",
- /* 247 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 248 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 249 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
- /* 250 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 251 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 252 */ "cmd ::= PRAGMA nm dbnm",
- /* 253 */ "nmnum ::= plus_num",
- /* 254 */ "nmnum ::= nm",
- /* 255 */ "plus_num ::= plus_opt number",
- /* 256 */ "minus_num ::= MINUS number",
- /* 257 */ "number ::= INTEGER|FLOAT",
- /* 258 */ "plus_opt ::= PLUS",
- /* 259 */ "plus_opt ::=",
- /* 260 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 261 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 262 */ "trigger_time ::= BEFORE",
- /* 263 */ "trigger_time ::= AFTER",
- /* 264 */ "trigger_time ::= INSTEAD OF",
- /* 265 */ "trigger_time ::=",
- /* 266 */ "trigger_event ::= DELETE|INSERT",
- /* 267 */ "trigger_event ::= UPDATE",
- /* 268 */ "trigger_event ::= UPDATE OF inscollist",
- /* 269 */ "foreach_clause ::=",
- /* 270 */ "foreach_clause ::= FOR EACH ROW",
- /* 271 */ "when_clause ::=",
- /* 272 */ "when_clause ::= WHEN expr",
- /* 273 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 274 */ "trigger_cmd_list ::=",
- /* 275 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 277 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 278 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 279 */ "trigger_cmd ::= select",
- /* 280 */ "expr ::= RAISE LP IGNORE RP",
- /* 281 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 282 */ "raisetype ::= ROLLBACK",
- /* 283 */ "raisetype ::= ABORT",
- /* 284 */ "raisetype ::= FAIL",
- /* 285 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 286 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 287 */ "cmd ::= DETACH database_kw_opt expr",
- /* 288 */ "key_opt ::=",
- /* 289 */ "key_opt ::= KEY expr",
- /* 290 */ "database_kw_opt ::= DATABASE",
- /* 291 */ "database_kw_opt ::=",
- /* 292 */ "cmd ::= REINDEX",
- /* 293 */ "cmd ::= REINDEX nm dbnm",
- /* 294 */ "cmd ::= ANALYZE",
- /* 295 */ "cmd ::= ANALYZE nm dbnm",
- /* 296 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 297 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 298 */ "add_column_fullname ::= fullname",
- /* 299 */ "kwcolumn_opt ::=",
- /* 300 */ "kwcolumn_opt ::= COLUMNKW",
- /* 301 */ "cmd ::= create_vtab",
- /* 302 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 303 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
- /* 304 */ "vtabarglist ::= vtabarg",
- /* 305 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 306 */ "vtabarg ::=",
- /* 307 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 308 */ "vtabargtoken ::= ANY",
- /* 309 */ "vtabargtoken ::= lp anylist RP",
- /* 310 */ "lp ::= LP",
- /* 311 */ "anylist ::=",
- /* 312 */ "anylist ::= anylist ANY",
+ /* 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 */
@@ -76807,8 +79838,11 @@
yyParser *pParser;
pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
if( pParser ){
pParser->yyidx = -1;
+#ifdef YYTRACKMAXSTACKDEPTH
+ pParser->yyidxMax = 0;
+#endif
#if YYSTACKDEPTH<=0
yyGrowStack(pParser);
#endif
}
@@ -76819,9 +79853,14 @@
** symbol. The symbol can be either a terminal or nonterminal.
** "yymajor" is the symbol code, and "yypminor" is a pointer to
** the value.
*/
-static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
+static void yy_destructor(
+ yyParser *yypParser, /* The parser */
+ YYCODETYPE yymajor, /* Type code for object to destroy */
+ YYMINORTYPE *yypminor /* The object to be destroyed */
+){
+ sqlite3ParserARG_FETCH;
switch( yymajor ){
/* Here is inserted the actions which take place when a
** terminal or non-terminal is destroyed. This can happen
** when the symbol is popped from the stack during a
@@ -76831,70 +79870,70 @@
** Note: during a reduce, the only symbols destroyed are those
** 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 */
-{
-sqlite3SelectDelete((yypminor->yy219));
-}
- 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 235: /* when_clause */
- case 238: /* key_opt */
-{
-sqlite3ExprDelete((yypminor->yy172));
-}
- 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 */
-{
-sqlite3ExprListDelete((yypminor->yy174));
-}
- break;
- case 188: /* fullname */
- case 193: /* from */
- case 201: /* seltablist */
- case 202: /* stl_prefix */
-{
-sqlite3SrcListDelete((yypminor->yy373));
-}
- break;
- case 205: /* using_opt */
- case 208: /* inscollist */
- case 214: /* inscollist_opt */
-{
-sqlite3IdListDelete((yypminor->yy432));
-}
- break;
- case 231: /* trigger_cmd_list */
- case 236: /* trigger_cmd */
-{
-sqlite3DeleteTriggerStep((yypminor->yy243));
-}
- break;
- case 233: /* trigger_event */
-{
-sqlite3IdListDelete((yypminor->yy370).b);
+ case 156: /* select */
+ case 190: /* oneselect */
+ case 208: /* seltablist_paren */
+{
+sqlite3SelectDelete(pParse->db, (yypminor->yy43));
+}
+ break;
+ case 170: /* term */
+ case 171: /* expr */
+ case 195: /* where_opt */
+ case 197: /* having_opt */
+ case 206: /* on_opt */
+ case 212: /* sortitem */
+ case 220: /* escape */
+ case 223: /* case_operand */
+ case 225: /* case_else */
+ case 236: /* when_clause */
+ case 239: /* key_opt */
+{
+sqlite3ExprDelete(pParse->db, (yypminor->yy450));
+}
+ break;
+ case 175: /* idxlist_opt */
+ case 183: /* idxlist */
+ case 193: /* selcollist */
+ case 196: /* groupby_opt */
+ case 198: /* orderby_opt */
+ case 200: /* sclp */
+ case 211: /* sortlist */
+ case 213: /* nexprlist */
+ case 214: /* setlist */
+ case 217: /* itemlist */
+ case 218: /* exprlist */
+ case 224: /* case_exprlist */
+{
+sqlite3ExprListDelete(pParse->db, (yypminor->yy242));
+}
+ break;
+ case 189: /* fullname */
+ case 194: /* from */
+ case 202: /* seltablist */
+ case 203: /* stl_prefix */
+{
+sqlite3SrcListDelete(pParse->db, (yypminor->yy419));
+}
+ break;
+ case 207: /* using_opt */
+ case 210: /* inscollist */
+ case 216: /* inscollist_opt */
+{
+sqlite3IdListDelete(pParse->db, (yypminor->yy352));
+}
+ break;
+ case 232: /* trigger_cmd_list */
+ case 237: /* trigger_cmd */
+{
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy75));
+}
+ break;
+ case 234: /* trigger_event */
+{
+sqlite3IdListDelete(pParse->db, (yypminor->yy354).b);
}
break;
default: break; /* If no destructor action specified: do nothing */
}
@@ -76920,9 +79959,9 @@
yyTokenName[yytos->major]);
}
#endif
yymajor = yytos->major;
- yy_destructor( yymajor, &yytos->minor);
+ yy_destructor(pParser, yymajor, &yytos->minor);
pParser->yyidx--;
return yymajor;
}
@@ -76949,8 +79988,18 @@
free(pParser->yystack);
#endif
(*freeProc)((void*)pParser);
}
+
+/*
+** Return the peak depth of the stack for a parser.
+*/
+#ifdef YYTRACKMAXSTACKDEPTH
+SQLITE_PRIVATE int sqlite3ParserStackPeak(void *p){
+ yyParser *pParser = (yyParser*)p;
+ return pParser->yyidxMax;
+}
+#endif
/*
** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead.
@@ -77072,8 +80121,13 @@
YYMINORTYPE *yypMinor /* Pointer to the minor token to shift in */
){
yyStackEntry *yytos;
yypParser->yyidx++;
+#ifdef YYTRACKMAXSTACKDEPTH
+ if( yypParser->yyidx>yypParser->yyidxMax ){
+ yypParser->yyidxMax = yypParser->yyidx;
+ }
+#endif
#if YYSTACKDEPTH>0
if( yypParser->yyidx>=YYSTACKDEPTH ){
yyStackOverflow(yypParser, yypMinor);
return;
@@ -77109,321 +80163,323 @@
static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
unsigned char nrhs; /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
- { 139, 1 },
- { 140, 2 },
{ 140, 1 },
+ { 141, 2 },
+ { 141, 1 },
{ 142, 1 },
- { 141, 1 },
- { 141, 3 },
- { 144, 0 },
+ { 142, 3 },
+ { 143, 0 },
+ { 143, 1 },
+ { 143, 3 },
{ 144, 1 },
- { 144, 3 },
- { 143, 3 },
+ { 145, 3 },
+ { 147, 0 },
+ { 147, 1 },
+ { 147, 2 },
{ 146, 0 },
{ 146, 1 },
- { 146, 2 },
- { 145, 0 },
- { 145, 1 },
- { 145, 1 },
- { 145, 1 },
- { 143, 2 },
- { 143, 2 },
- { 143, 2 },
- { 143, 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 },
- { 163, 1 },
- { 163, 2 },
- { 164, 1 },
- { 164, 1 },
- { 159, 2 },
+ { 148, 1 },
+ { 148, 1 },
+ { 148, 1 },
{ 159, 0 },
- { 167, 3 },
- { 167, 1 },
- { 168, 2 },
- { 168, 4 },
- { 168, 3 },
- { 168, 3 },
- { 168, 2 },
- { 168, 2 },
+ { 159, 1 },
+ { 163, 1 },
+ { 163, 4 },
+ { 163, 6 },
+ { 164, 1 },
+ { 164, 2 },
+ { 165, 1 },
+ { 165, 1 },
+ { 160, 2 },
+ { 160, 0 },
{ 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 },
+ { 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 },
{ 178, 2 },
- { 178, 2 },
- { 178, 1 },
- { 178, 1 },
- { 176, 3 },
- { 176, 2 },
- { 179, 0 },
+ { 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, 2 },
- { 180, 1 },
+ { 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 },
- { 143, 4 },
- { 187, 2 },
- { 187, 0 },
- { 143, 8 },
- { 143, 4 },
- { 143, 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, 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 },
- { 197, 0 },
- { 197, 3 },
- { 209, 4 },
- { 209, 2 },
- { 210, 1 },
- { 172, 1 },
- { 172, 1 },
- { 172, 0 },
- { 195, 0 },
- { 195, 3 },
+ { 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, 2 },
- { 198, 0 },
- { 198, 2 },
- { 198, 4 },
- { 198, 4 },
- { 143, 4 },
- { 194, 0 },
- { 194, 2 },
- { 143, 6 },
- { 212, 5 },
- { 212, 3 },
- { 143, 8 },
- { 143, 5 },
- { 143, 6 },
- { 213, 2 },
- { 213, 1 },
- { 215, 3 },
+ { 196, 3 },
+ { 197, 0 },
+ { 197, 2 },
+ { 199, 0 },
+ { 199, 2 },
+ { 199, 4 },
+ { 199, 4 },
+ { 145, 5 },
+ { 195, 0 },
+ { 195, 2 },
+ { 145, 7 },
+ { 214, 5 },
+ { 214, 3 },
+ { 145, 8 },
+ { 145, 5 },
+ { 145, 6 },
+ { 215, 2 },
{ 215, 1 },
- { 214, 0 },
- { 214, 3 },
- { 208, 3 },
- { 208, 1 },
+ { 217, 3 },
+ { 217, 1 },
+ { 216, 0 },
+ { 216, 3 },
+ { 210, 3 },
+ { 210, 1 },
+ { 171, 1 },
+ { 171, 3 },
{ 170, 1 },
- { 170, 3 },
- { 169, 1 },
+ { 171, 1 },
+ { 171, 1 },
+ { 171, 3 },
+ { 171, 5 },
{ 170, 1 },
{ 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 },
+ { 220, 0 },
+ { 171, 4 },
+ { 171, 2 },
+ { 171, 3 },
+ { 171, 3 },
+ { 171, 4 },
+ { 171, 2 },
+ { 171, 2 },
+ { 171, 2 },
+ { 171, 2 },
+ { 221, 1 },
+ { 221, 2 },
+ { 171, 5 },
+ { 222, 1 },
+ { 222, 2 },
+ { 171, 5 },
+ { 171, 3 },
+ { 171, 5 },
+ { 171, 4 },
+ { 171, 4 },
+ { 171, 5 },
+ { 224, 5 },
+ { 224, 4 },
+ { 225, 2 },
+ { 225, 0 },
+ { 223, 1 },
{ 223, 0 },
- { 221, 1 },
- { 221, 0 },
- { 216, 1 },
- { 216, 0 },
- { 211, 3 },
- { 211, 1 },
- { 143, 11 },
- { 224, 1 },
- { 224, 0 },
- { 174, 0 },
- { 174, 3 },
- { 182, 5 },
- { 182, 3 },
- { 225, 1 },
+ { 218, 1 },
+ { 218, 0 },
+ { 213, 3 },
+ { 213, 1 },
+ { 145, 11 },
+ { 226, 1 },
{ 226, 0 },
- { 226, 2 },
- { 143, 4 },
- { 143, 1 },
- { 143, 2 },
- { 143, 5 },
- { 143, 5 },
- { 143, 5 },
- { 143, 5 },
- { 143, 6 },
- { 143, 3 },
- { 227, 1 },
- { 227, 1 },
- { 165, 2 },
+ { 175, 0 },
+ { 175, 3 },
+ { 183, 5 },
+ { 183, 3 },
+ { 227, 0 },
+ { 227, 2 },
+ { 145, 4 },
+ { 145, 1 },
+ { 145, 2 },
+ { 145, 5 },
+ { 145, 5 },
+ { 145, 5 },
+ { 145, 5 },
+ { 145, 6 },
+ { 145, 3 },
+ { 228, 1 },
+ { 228, 1 },
{ 166, 2 },
+ { 167, 2 },
+ { 230, 1 },
{ 229, 1 },
- { 228, 1 },
- { 228, 0 },
- { 143, 5 },
- { 230, 11 },
- { 232, 1 },
- { 232, 1 },
- { 232, 2 },
- { 232, 0 },
+ { 229, 0 },
+ { 145, 5 },
+ { 231, 11 },
{ 233, 1 },
{ 233, 1 },
- { 233, 3 },
- { 234, 0 },
+ { 233, 2 },
+ { 233, 0 },
+ { 234, 1 },
+ { 234, 1 },
{ 234, 3 },
{ 235, 0 },
- { 235, 2 },
- { 231, 3 },
- { 231, 0 },
- { 236, 6 },
- { 236, 8 },
- { 236, 5 },
- { 236, 4 },
- { 236, 1 },
- { 170, 4 },
- { 170, 6 },
- { 186, 1 },
- { 186, 1 },
- { 186, 1 },
- { 143, 4 },
- { 143, 6 },
- { 143, 3 },
+ { 235, 3 },
+ { 236, 0 },
+ { 236, 2 },
+ { 232, 3 },
+ { 232, 2 },
+ { 237, 6 },
+ { 237, 8 },
+ { 237, 5 },
+ { 237, 4 },
+ { 237, 1 },
+ { 171, 4 },
+ { 171, 6 },
+ { 187, 1 },
+ { 187, 1 },
+ { 187, 1 },
+ { 145, 4 },
+ { 145, 6 },
+ { 145, 3 },
+ { 239, 0 },
+ { 239, 2 },
+ { 238, 1 },
{ 238, 0 },
- { 238, 2 },
- { 237, 1 },
- { 237, 0 },
- { 143, 1 },
- { 143, 3 },
- { 143, 1 },
- { 143, 3 },
- { 143, 6 },
- { 143, 6 },
- { 239, 1 },
- { 240, 0 },
+ { 145, 1 },
+ { 145, 3 },
+ { 145, 1 },
+ { 145, 3 },
+ { 145, 6 },
+ { 145, 6 },
{ 240, 1 },
- { 143, 1 },
- { 143, 4 },
- { 241, 7 },
- { 242, 1 },
- { 242, 3 },
- { 243, 0 },
- { 243, 2 },
- { 244, 1 },
- { 244, 3 },
+ { 241, 0 },
+ { 241, 1 },
+ { 145, 1 },
+ { 145, 4 },
+ { 242, 7 },
+ { 243, 1 },
+ { 243, 3 },
+ { 244, 0 },
+ { 244, 2 },
{ 245, 1 },
- { 246, 0 },
- { 246, 2 },
+ { 245, 3 },
+ { 246, 1 },
+ { 247, 0 },
+ { 247, 2 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -77479,10 +80535,10 @@
*/
case 0: /* input ::= cmdlist */
case 1: /* cmdlist ::= cmdlist ecmd */
case 2: /* cmdlist ::= ecmd */
- case 4: /* ecmd ::= SEMI */
- case 5: /* ecmd ::= explain cmdx SEMI */
+ case 3: /* ecmd ::= SEMI */
+ case 4: /* ecmd ::= explain cmdx SEMI */
case 10: /* trans_opt ::= */
case 11: /* trans_opt ::= TRANSACTION */
case 12: /* trans_opt ::= TRANSACTION nm */
case 20: /* cmd ::= create_table create_table_args */
@@ -77499,47 +80555,47 @@
case 82: /* conslist ::= conslist COMMA tcons */
case 83: /* conslist ::= conslist tcons */
case 84: /* conslist ::= tcons */
case 85: /* tcons ::= CONSTRAINT nm */
- case 258: /* plus_opt ::= PLUS */
- case 259: /* plus_opt ::= */
- case 269: /* foreach_clause ::= */
- case 270: /* foreach_clause ::= FOR EACH ROW */
- case 290: /* database_kw_opt ::= DATABASE */
- case 291: /* database_kw_opt ::= */
- case 299: /* kwcolumn_opt ::= */
- case 300: /* kwcolumn_opt ::= COLUMNKW */
- case 304: /* vtabarglist ::= vtabarg */
- case 305: /* vtabarglist ::= vtabarglist COMMA vtabarg */
- case 307: /* vtabarg ::= vtabarg vtabargtoken */
- case 311: /* anylist ::= */
-{
-}
- break;
- case 3: /* cmdx ::= cmd */
-{ sqlite3FinishCoding(pParse); }
- break;
- case 6: /* explain ::= */
+ 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;
+ case 5: /* explain ::= */
{ sqlite3BeginParse(pParse, 0); }
break;
- case 7: /* explain ::= EXPLAIN */
+ case 6: /* explain ::= EXPLAIN */
{ sqlite3BeginParse(pParse, 1); }
break;
- case 8: /* explain ::= EXPLAIN QUERY PLAN */
+ case 7: /* explain ::= EXPLAIN QUERY PLAN */
{ sqlite3BeginParse(pParse, 2); }
break;
+ case 8: /* cmdx ::= cmd */
+{ sqlite3FinishCoding(pParse); }
+ break;
case 9: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy46);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy316);}
break;
case 13: /* transtype ::= */
-{yygotominor.yy46 = 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.yy46 = yymsp[0].major;}
+{yygotominor.yy316 = yymsp[0].major;}
break;
case 17: /* cmd ::= COMMIT trans_opt */
case 18: /* cmd ::= END trans_opt */
{sqlite3CommitTransaction(pParse);}
@@ -77548,9 +80604,9 @@
{sqlite3RollbackTransaction(pParse);}
break;
case 21: /* create_table ::= CREATE temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy46,0,0,yymsp[-2].minor.yy46);
+ 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 25: /* temp ::= */
@@ -77560,21 +80616,21 @@
case 90: /* defer_subclause_opt ::= */
case 101: /* ifexists ::= */
case 112: /* distinct ::= ALL */
case 113: /* distinct ::= */
- case 213: /* between_op ::= BETWEEN */
- case 216: /* in_op ::= IN */
-{yygotominor.yy46 = 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 64: /* autoinc ::= AUTOINCR */
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.yy46 = 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 */
{
sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
@@ -77581,10 +80637,10 @@
}
break;
case 27: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy219);
- sqlite3SelectDelete(yymsp[0].minor.yy219);
+ sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy43);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43);
}
break;
case 30: /* column ::= columnid type carglist */
{
@@ -77607,15 +80663,15 @@
case 42: /* typename ::= ids */
case 119: /* as ::= AS nm */
case 120: /* as ::= ids */
case 131: /* dbnm ::= DOT nm */
- case 241: /* idxitem ::= nm */
- case 243: /* collate ::= COLLATE ids */
- case 253: /* nmnum ::= plus_num */
- case 254: /* nmnum ::= nm */
- case 255: /* plus_num ::= plus_opt number */
- case 256: /* minus_num ::= MINUS number */
- case 257: /* number ::= INTEGER|FLOAT */
+ 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 */
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
@@ -77636,16 +80692,17 @@
{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
break;
case 50: /* ccons ::= DEFAULT term */
case 52: /* ccons ::= DEFAULT PLUS term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy172);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy450);}
break;
case 51: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy172);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy450);}
break;
case 53: /* ccons ::= DEFAULT MINUS term */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy172, 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;
case 54: /* ccons ::= DEFAULT id */
@@ -77654,66 +80711,66 @@
sqlite3AddDefaultValue(pParse,p);
}
break;
case 56: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy46);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy316);}
break;
case 57: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy46,yymsp[-2].minor.yy46);}
+{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.yy46,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.yy172);}
+{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.yy174,yymsp[0].minor.yy46);}
+{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.yy46);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy316);}
break;
case 62: /* ccons ::= COLLATE ids */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 65: /* refargs ::= */
-{ yygotominor.yy46 = OE_Restrict * 0x010101; }
+{ yygotominor.yy316 = OE_Restrict * 0x010101; }
break;
case 66: /* refargs ::= refargs refarg */
-{ yygotominor.yy46 = (yymsp[-1].minor.yy46 & yymsp[0].minor.yy405.mask) | yymsp[0].minor.yy405.value; }
+{ yygotominor.yy316 = (yymsp[-1].minor.yy316 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
break;
case 67: /* refarg ::= MATCH nm */
-{ yygotominor.yy405.value = 0; yygotominor.yy405.mask = 0x000000; }
+{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; }
break;
case 68: /* refarg ::= ON DELETE refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46; yygotominor.yy405.mask = 0x0000ff; }
+{ yygotominor.yy207.value = yymsp[0].minor.yy316; yygotominor.yy207.mask = 0x0000ff; }
break;
case 69: /* refarg ::= ON UPDATE refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46<<8; yygotominor.yy405.mask = 0x00ff00; }
+{ yygotominor.yy207.value = yymsp[0].minor.yy316<<8; yygotominor.yy207.mask = 0x00ff00; }
break;
case 70: /* refarg ::= ON INSERT refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46<<16; yygotominor.yy405.mask = 0xff0000; }
+{ yygotominor.yy207.value = yymsp[0].minor.yy316<<16; yygotominor.yy207.mask = 0xff0000; }
break;
case 71: /* refact ::= SET NULL */
-{ yygotominor.yy46 = OE_SetNull; }
+{ yygotominor.yy316 = OE_SetNull; }
break;
case 72: /* refact ::= SET DEFAULT */
-{ yygotominor.yy46 = OE_SetDflt; }
+{ yygotominor.yy316 = OE_SetDflt; }
break;
case 73: /* refact ::= CASCADE */
-{ yygotominor.yy46 = OE_Cascade; }
+{ yygotominor.yy316 = OE_Cascade; }
break;
case 74: /* refact ::= RESTRICT */
-{ yygotominor.yy46 = 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 91: /* defer_subclause_opt ::= defer_subclause */
case 93: /* onconf ::= ON CONFLICT resolvetype */
case 95: /* orconf ::= OR resolvetype */
case 96: /* resolvetype ::= raisetype */
- case 166: /* insert_cmd ::= INSERT orconf */
-{yygotominor.yy46 = yymsp[0].minor.yy46;}
+ 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;}
break;
@@ -77720,734 +80777,752 @@
case 81: /* conslist_opt ::= COMMA conslist */
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
break;
case 86: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy174,yymsp[0].minor.yy46,yymsp[-2].minor.yy46,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.yy174,yymsp[0].minor.yy46,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.yy172);}
+{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.yy174, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy174, yymsp[-1].minor.yy46);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy46);
+ 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.yy46 = OE_Default;}
+{yygotominor.yy316 = OE_Default;}
break;
case 97: /* resolvetype ::= IGNORE */
-{yygotominor.yy46 = OE_Ignore;}
+{yygotominor.yy316 = OE_Ignore;}
break;
case 98: /* resolvetype ::= REPLACE */
- case 167: /* insert_cmd ::= REPLACE */
-{yygotominor.yy46 = OE_Replace;}
+ case 170: /* insert_cmd ::= REPLACE */
+{yygotominor.yy316 = OE_Replace;}
break;
case 99: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy373, 0, yymsp[-1].minor.yy46);
+ 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.yy219, yymsp[-6].minor.yy46, yymsp[-4].minor.yy46);
+ 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.yy373, 1, yymsp[-1].minor.yy46);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy419, 1, yymsp[-1].minor.yy316);
}
break;
case 104: /* cmd ::= select */
{
- SelectDest dest = {SRT_Callback, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy219, &dest, 0, 0, 0);
- sqlite3SelectDelete(yymsp[0].minor.yy219);
+ SelectDest dest = {SRT_Output, 0, 0, 0, 0};
+ 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.yy219 = yymsp[0].minor.yy219;}
+{yygotominor.yy43 = yymsp[0].minor.yy43;}
break;
case 106: /* select ::= select multiselect_op oneselect */
{
- if( yymsp[0].minor.yy219 ){
- yymsp[0].minor.yy219->op = yymsp[-1].minor.yy46;
- yymsp[0].minor.yy219->pPrior = yymsp[-2].minor.yy219;
- }else{
- sqlite3SelectDelete(yymsp[-2].minor.yy219);
- }
- yygotominor.yy219 = yymsp[0].minor.yy219;
+ 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.yy43);
+ }
+ yygotominor.yy43 = yymsp[0].minor.yy43;
}
break;
case 108: /* multiselect_op ::= UNION ALL */
-{yygotominor.yy46 = 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.yy219 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy174,yymsp[-5].minor.yy373,yymsp[-4].minor.yy172,yymsp[-3].minor.yy174,yymsp[-2].minor.yy172,yymsp[-1].minor.yy174,yymsp[-7].minor.yy46,yymsp[0].minor.yy234.pLimit,yymsp[0].minor.yy234.pOffset);
+ 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.yy174 = yymsp[-1].minor.yy174;}
+ 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.yy174 = 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.yy174 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy174,yymsp[-1].minor.yy172,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.yy174 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy174, 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, 0);
+ 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.yy174 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy174, 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.yy373 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy373));}
+{yygotominor.yy419 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy419));}
break;
case 123: /* from ::= FROM seltablist */
{
- yygotominor.yy373 = yymsp[0].minor.yy373;
- sqlite3SrcListShiftJoinType(yygotominor.yy373);
+ yygotominor.yy419 = yymsp[0].minor.yy419;
+ sqlite3SrcListShiftJoinType(yygotominor.yy419);
}
break;
case 124: /* stl_prefix ::= seltablist joinop */
{
- yygotominor.yy373 = yymsp[-1].minor.yy373;
- if( yygotominor.yy373 && yygotominor.yy373->nSrc>0 ) yygotominor.yy373->a[yygotominor.yy373->nSrc-1].jointype = yymsp[0].minor.yy46;
+ 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.yy373 = 0;}
- break;
- case 126: /* seltablist ::= stl_prefix nm dbnm as on_opt using_opt */
-{
- yygotominor.yy373 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy373,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy172,yymsp[0].minor.yy432);
+{yygotominor.yy419 = 0;}
+ break;
+ case 126: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+{
+ yygotominor.yy419 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy419,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy450,yymsp[0].minor.yy352);
+ sqlite3SrcListIndexedBy(pParse, yygotominor.yy419, &yymsp[-2].minor.yy0);
}
break;
case 127: /* seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt */
{
- yygotominor.yy373 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy373,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy219,yymsp[-1].minor.yy172,yymsp[0].minor.yy432);
+ 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.yy373);
- yygotominor.yy219 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy373,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.yy373 = 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.yy46 = JT_INNER; }
+{ yygotominor.yy316 = JT_INNER; }
break;
case 134: /* joinop ::= JOIN_KW JOIN */
-{ yygotominor.yy46 = 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.yy46 = 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.yy46 = 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.yy172 = yymsp[0].minor.yy172;}
+ 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.yy172 = 0;}
- break;
- case 139: /* using_opt ::= USING LP inscollist RP */
- case 171: /* inscollist_opt ::= LP inscollist RP */
-{yygotominor.yy432 = yymsp[-1].minor.yy432;}
- break;
- case 140: /* using_opt ::= */
- case 170: /* inscollist_opt ::= */
-{yygotominor.yy432 = 0;}
- break;
- case 142: /* orderby_opt ::= ORDER BY sortlist */
- case 150: /* groupby_opt ::= GROUP BY nexprlist */
- case 230: /* exprlist ::= nexprlist */
-{yygotominor.yy174 = yymsp[0].minor.yy174;}
- break;
- case 143: /* sortlist ::= sortlist COMMA sortitem sortorder */
-{
- yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy174,yymsp[-1].minor.yy172,0);
- if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
-}
- break;
- case 144: /* sortlist ::= sortitem sortorder */
-{
- yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy172,0);
- if( yygotominor.yy174 && yygotominor.yy174->a ) yygotominor.yy174->a[0].sortOrder = yymsp[0].minor.yy46;
-}
- break;
- case 146: /* sortorder ::= ASC */
- case 148: /* sortorder ::= */
-{yygotominor.yy46 = SQLITE_SO_ASC;}
- break;
- case 147: /* sortorder ::= DESC */
-{yygotominor.yy46 = SQLITE_SO_DESC;}
- break;
- case 153: /* limit_opt ::= */
-{yygotominor.yy234.pLimit = 0; yygotominor.yy234.pOffset = 0;}
- break;
- case 154: /* limit_opt ::= LIMIT expr */
-{yygotominor.yy234.pLimit = yymsp[0].minor.yy172; yygotominor.yy234.pOffset = 0;}
- break;
- case 155: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yygotominor.yy234.pLimit = yymsp[-2].minor.yy172; yygotominor.yy234.pOffset = yymsp[0].minor.yy172;}
- break;
- case 156: /* limit_opt ::= LIMIT expr COMMA expr */
-{yygotominor.yy234.pOffset = yymsp[-2].minor.yy172; yygotominor.yy234.pLimit = yymsp[0].minor.yy172;}
- break;
- case 157: /* cmd ::= DELETE FROM fullname where_opt */
-{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy373,yymsp[0].minor.yy172);}
- break;
- case 160: /* cmd ::= UPDATE orconf fullname SET setlist where_opt */
-{
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy174,"set list");
- sqlite3Update(pParse,yymsp[-3].minor.yy373,yymsp[-1].minor.yy174,yymsp[0].minor.yy172,yymsp[-4].minor.yy46);
-}
- break;
- case 161: /* setlist ::= setlist COMMA nm EQ expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
- break;
- case 162: /* setlist ::= nm EQ expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
- break;
- case 163: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */
-{sqlite3Insert(pParse, yymsp[-5].minor.yy373, yymsp[-1].minor.yy174, 0, yymsp[-4].minor.yy432, yymsp[-7].minor.yy46);}
- break;
- case 164: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
-{sqlite3Insert(pParse, yymsp[-2].minor.yy373, 0, yymsp[0].minor.yy219, yymsp[-1].minor.yy432, yymsp[-4].minor.yy46);}
- break;
- case 165: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
-{sqlite3Insert(pParse, yymsp[-3].minor.yy373, 0, 0, yymsp[-2].minor.yy432, yymsp[-5].minor.yy46);}
- break;
- case 168: /* itemlist ::= itemlist COMMA expr */
- case 232: /* nexprlist ::= nexprlist COMMA expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy174,yymsp[0].minor.yy172,0);}
- break;
- case 169: /* itemlist ::= expr */
- case 233: /* nexprlist ::= expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,0);}
- break;
- case 172: /* inscollist ::= inscollist COMMA nm */
-{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy432,&yymsp[0].minor.yy0);}
- break;
- case 173: /* inscollist ::= nm */
-{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
- break;
- case 175: /* expr ::= LP expr RP */
-{yygotominor.yy172 = yymsp[-1].minor.yy172; sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
- break;
- case 176: /* term ::= NULL */
- case 181: /* term ::= INTEGER|FLOAT|BLOB */
- case 182: /* term ::= STRING */
-{yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
- break;
- case 177: /* expr ::= ID */
- case 178: /* expr ::= JOIN_KW */
-{yygotominor.yy172 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
- break;
- case 179: /* expr ::= nm DOT nm */
+ 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 142: /* using_opt ::= USING LP inscollist RP */
+ case 174: /* inscollist_opt ::= LP inscollist RP */
+{yygotominor.yy352 = yymsp[-1].minor.yy352;}
+ break;
+ case 143: /* using_opt ::= */
+ case 173: /* inscollist_opt ::= */
+{yygotominor.yy352 = 0;}
+ break;
+ case 145: /* orderby_opt ::= ORDER BY sortlist */
+ case 153: /* groupby_opt ::= GROUP BY nexprlist */
+ case 233: /* exprlist ::= nexprlist */
+{yygotominor.yy242 = yymsp[0].minor.yy242;}
+ break;
+ case 146: /* sortlist ::= sortlist COMMA sortitem sortorder */
+{
+ yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242,yymsp[-1].minor.yy450,0);
+ if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
+}
+ break;
+ case 147: /* sortlist ::= sortitem sortorder */
+{
+ yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy450,0);
+ if( yygotominor.yy242 && yygotominor.yy242->a ) yygotominor.yy242->a[0].sortOrder = yymsp[0].minor.yy316;
+}
+ break;
+ case 149: /* sortorder ::= ASC */
+ case 151: /* sortorder ::= */
+{yygotominor.yy316 = SQLITE_SO_ASC;}
+ break;
+ case 150: /* sortorder ::= DESC */
+{yygotominor.yy316 = SQLITE_SO_DESC;}
+ break;
+ case 156: /* limit_opt ::= */
+{yygotominor.yy84.pLimit = 0; yygotominor.yy84.pOffset = 0;}
+ break;
+ case 157: /* limit_opt ::= LIMIT expr */
+{yygotominor.yy84.pLimit = yymsp[0].minor.yy450; yygotominor.yy84.pOffset = 0;}
+ break;
+ case 158: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yygotominor.yy84.pLimit = yymsp[-2].minor.yy450; yygotominor.yy84.pOffset = yymsp[0].minor.yy450;}
+ break;
+ case 159: /* limit_opt ::= LIMIT expr COMMA expr */
+{yygotominor.yy84.pOffset = yymsp[-2].minor.yy450; yygotominor.yy84.pLimit = yymsp[0].minor.yy450;}
+ break;
+ case 160: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
+{
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy419, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy419,yymsp[0].minor.yy450);
+}
+ break;
+ case 163: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
+{
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy419, &yymsp[-3].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy242,"set list");
+ sqlite3Update(pParse,yymsp[-4].minor.yy419,yymsp[-1].minor.yy242,yymsp[0].minor.yy450,yymsp[-5].minor.yy316);
+}
+ break;
+ case 164: /* setlist ::= setlist COMMA nm EQ expr */
+{yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242,yymsp[0].minor.yy450,&yymsp[-2].minor.yy0);}
+ break;
+ case 165: /* setlist ::= nm EQ expr */
+{yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy450,&yymsp[-2].minor.yy0);}
+ break;
+ case 166: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */
+{sqlite3Insert(pParse, yymsp[-5].minor.yy419, yymsp[-1].minor.yy242, 0, yymsp[-4].minor.yy352, yymsp[-7].minor.yy316);}
+ break;
+ case 167: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
+{sqlite3Insert(pParse, yymsp[-2].minor.yy419, 0, yymsp[0].minor.yy43, yymsp[-1].minor.yy352, yymsp[-4].minor.yy316);}
+ break;
+ case 168: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
+{sqlite3Insert(pParse, yymsp[-3].minor.yy419, 0, 0, yymsp[-2].minor.yy352, yymsp[-5].minor.yy316);}
+ break;
+ case 171: /* itemlist ::= itemlist COMMA expr */
+ case 235: /* nexprlist ::= nexprlist COMMA expr */
+{yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[0].minor.yy450,0);}
+ break;
+ case 172: /* itemlist ::= expr */
+ case 236: /* nexprlist ::= expr */
+{yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy450,0);}
+ break;
+ case 175: /* inscollist ::= inscollist COMMA nm */
+{yygotominor.yy352 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy352,&yymsp[0].minor.yy0);}
+ break;
+ case 176: /* inscollist ::= nm */
+{yygotominor.yy352 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
+ break;
+ case 178: /* expr ::= LP expr RP */
+{yygotominor.yy450 = yymsp[-1].minor.yy450; sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+ break;
+ case 179: /* term ::= NULL */
+ case 184: /* term ::= INTEGER|FLOAT|BLOB */
+ case 185: /* term ::= STRING */
+{yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
+ break;
+ case 180: /* expr ::= ID */
+ case 181: /* expr ::= JOIN_KW */
+{yygotominor.yy450 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+ break;
+ 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.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
-}
- break;
- case 180: /* expr ::= nm DOT nm DOT nm */
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+}
+ break;
+ 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.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
-}
- break;
- case 183: /* expr ::= REGISTER */
-{yygotominor.yy172 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
- break;
- case 184: /* expr ::= VARIABLE */
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
+}
+ break;
+ case 186: /* expr ::= REGISTER */
+{yygotominor.yy450 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+ break;
+ case 187: /* expr ::= VARIABLE */
{
Token *pToken = &yymsp[0].minor.yy0;
- Expr *pExpr = yygotominor.yy172 = 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 */
-{
- yygotominor.yy172 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy172, &yymsp[0].minor.yy0);
-}
- break;
- case 186: /* expr ::= CAST LP expr AS typetoken RP */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy172, 0, &yymsp[-1].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
-}
- break;
- case 187: /* expr ::= ID LP distinct exprlist RP */
-{
- if( yymsp[-1].minor.yy174 && yymsp[-1].minor.yy174->nExpr>SQLITE_MAX_FUNCTION_ARG ){
+ case 188: /* expr ::= expr COLLATE ids */
+{
+ yygotominor.yy450 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy450, &yymsp[0].minor.yy0);
+}
+ break;
+ case 189: /* expr ::= CAST LP expr AS typetoken RP */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy450, 0, &yymsp[-1].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
+}
+ break;
+ case 190: /* expr ::= ID LP distinct exprlist RP */
+{
+ 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.yy172 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy174, &yymsp[-4].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
- if( yymsp[-2].minor.yy46 && yygotominor.yy172 ){
- yygotominor.yy172->flags |= EP_Distinct;
- }
-}
- break;
- case 188: /* expr ::= ID LP STAR RP */
-{
- yygotominor.yy172 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
-}
- break;
- case 189: /* term ::= CTIME_KW */
+ 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 191: /* expr ::= ID LP STAR RP */
+{
+ yygotominor.yy450 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+}
+ break;
+ case 192: /* term ::= CTIME_KW */
{
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
** treated as functions that return constants */
- yygotominor.yy172 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
- if( yygotominor.yy172 ){
- yygotominor.yy172->op = TK_CONST_FUNC;
- yygotominor.yy172->span = yymsp[0].minor.yy0;
- }
-}
- break;
- case 190: /* expr ::= expr AND expr */
- case 191: /* expr ::= expr OR expr */
- case 192: /* expr ::= expr LT|GT|GE|LE expr */
- case 193: /* expr ::= expr EQ|NE expr */
- case 194: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- case 195: /* expr ::= expr PLUS|MINUS expr */
- case 196: /* expr ::= expr STAR|SLASH|REM expr */
- case 197: /* expr ::= expr CONCAT expr */
-{yygotominor.yy172 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy172,yymsp[0].minor.yy172,0);}
- break;
- case 198: /* likeop ::= LIKE_KW */
- case 200: /* likeop ::= MATCH */
-{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 0;}
- break;
- case 199: /* likeop ::= NOT LIKE_KW */
- case 201: /* likeop ::= NOT MATCH */
-{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 1;}
- break;
- case 204: /* expr ::= expr likeop expr escape */
+ 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 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 201: /* likeop ::= LIKE_KW */
+ case 203: /* likeop ::= MATCH */
+{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 0;}
+ break;
+ case 202: /* likeop ::= NOT LIKE_KW */
+ case 204: /* likeop ::= NOT MATCH */
+{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 1;}
+ break;
+ case 207: /* expr ::= expr likeop expr escape */
{
ExprList *pList;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy172, 0);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy172, 0);
- if( yymsp[0].minor.yy172 ){
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy172, 0);
- }
- yygotominor.yy172 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy72.eOperator);
- if( yymsp[-2].minor.yy72.not ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy172->span, &yymsp[-1].minor.yy172->span);
- if( yygotominor.yy172 ) yygotominor.yy172->flags |= EP_InfixFunc;
-}
- break;
- case 205: /* expr ::= expr ISNULL|NOTNULL */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy172->span,&yymsp[0].minor.yy0);
-}
- break;
- case 206: /* expr ::= expr IS NULL */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0);
-}
- break;
- case 207: /* expr ::= expr NOT NULL */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0);
-}
- break;
- case 208: /* expr ::= expr IS NOT NULL */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,&yymsp[0].minor.yy0);
-}
- break;
- case 209: /* expr ::= NOT expr */
- case 210: /* expr ::= BITNOT expr */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
-}
- break;
- case 211: /* expr ::= MINUS expr */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
-}
- break;
- case 212: /* expr ::= PLUS expr */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
-}
- break;
- case 215: /* expr ::= expr between_op expr AND expr */
-{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy172, 0);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy172, 0);
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy172, 0, 0);
- if( yygotominor.yy172 ){
- yygotominor.yy172->pList = pList;
- }else{
- sqlite3ExprListDelete(pList);
- }
- if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy172->span);
-}
- break;
- case 218: /* expr ::= expr in_op LP exprlist RP */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy172, 0, 0);
- if( yygotominor.yy172 ){
- yygotominor.yy172->pList = yymsp[-1].minor.yy174;
- sqlite3ExprSetHeight(pParse, yygotominor.yy172);
- }else{
- sqlite3ExprListDelete(yymsp[-1].minor.yy174);
- }
- if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0);
- }
- break;
- case 219: /* expr ::= LP select RP */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
- if( yygotominor.yy172 ){
- yygotominor.yy172->pSelect = yymsp[-1].minor.yy219;
- sqlite3ExprSetHeight(pParse, yygotominor.yy172);
- }else{
- sqlite3SelectDelete(yymsp[-1].minor.yy219);
- }
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- }
- break;
- case 220: /* expr ::= expr in_op LP select RP */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy172, 0, 0);
- if( yygotominor.yy172 ){
- yygotominor.yy172->pSelect = yymsp[-1].minor.yy219;
- sqlite3ExprSetHeight(pParse, yygotominor.yy172);
- }else{
- sqlite3SelectDelete(yymsp[-1].minor.yy219);
- }
- if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0);
- }
- break;
- case 221: /* expr ::= expr in_op nm dbnm */
+ 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.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 208: /* expr ::= expr ISNULL|NOTNULL */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy450->span,&yymsp[0].minor.yy0);
+}
+ break;
+ case 209: /* expr ::= expr IS NULL */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0);
+}
+ break;
+ case 210: /* expr ::= expr NOT NULL */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0);
+}
+ break;
+ case 211: /* expr ::= expr IS NOT NULL */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,&yymsp[0].minor.yy0);
+}
+ break;
+ case 212: /* expr ::= NOT expr */
+ case 213: /* expr ::= BITNOT expr */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+}
+ break;
+ case 214: /* expr ::= MINUS expr */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+}
+ break;
+ case 215: /* expr ::= PLUS expr */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+}
+ break;
+ case 218: /* expr ::= expr between_op expr AND expr */
+{
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy450, 0);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy450, 0);
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy450, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pList = pList;
+ }else{
+ sqlite3ExprListDelete(pParse->db, pList);
+ }
+ if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy450->span);
+}
+ break;
+ case 221: /* expr ::= expr in_op LP exprlist RP */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy450, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pList = yymsp[-1].minor.yy242;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ }else{
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242);
+ }
+ 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 222: /* expr ::= LP select RP */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pSelect = yymsp[-1].minor.yy43;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
+ }
+ sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ }
+ break;
+ case 223: /* expr ::= expr in_op LP select RP */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy450, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pSelect = yymsp[-1].minor.yy43;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
+ }
+ 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 224: /* expr ::= expr in_op nm dbnm */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy172, 0, 0);
- if( yygotominor.yy172 ){
- yygotominor.yy172->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
- sqlite3ExprSetHeight(pParse, yygotominor.yy172);
- }else{
- sqlite3SrcListDelete(pSrc);
- }
- if( yymsp[-2].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
- }
- break;
- case 222: /* expr ::= EXISTS LP select RP */
-{
- Expr *p = yygotominor.yy172 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+ 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.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 225: /* expr ::= EXISTS LP select RP */
+{
+ Expr *p = yygotominor.yy450 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
if( p ){
- p->pSelect = yymsp[-1].minor.yy219;
+ p->pSelect = yymsp[-1].minor.yy43;
sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
- sqlite3ExprSetHeight(pParse, yygotominor.yy172);
- }else{
- sqlite3SelectDelete(yymsp[-1].minor.yy219);
- }
- }
- break;
- case 223: /* expr ::= CASE case_operand case_exprlist case_else END */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, 0);
- if( yygotominor.yy172 ){
- yygotominor.yy172->pList = yymsp[-2].minor.yy174;
- sqlite3ExprSetHeight(pParse, yygotominor.yy172);
- }else{
- sqlite3ExprListDelete(yymsp[-2].minor.yy174);
- }
- sqlite3ExprSpan(yygotominor.yy172, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
-}
- break;
- case 224: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
-{
- yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174, yymsp[-2].minor.yy172, 0);
- yygotominor.yy174 = sqlite3ExprListAppend(pParse,yygotominor.yy174, yymsp[0].minor.yy172, 0);
-}
- break;
- case 225: /* case_exprlist ::= WHEN expr THEN expr */
-{
- yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy172, 0);
- yygotominor.yy174 = sqlite3ExprListAppend(pParse,yygotominor.yy174, yymsp[0].minor.yy172, 0);
-}
- break;
- case 234: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
+ sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
+ }
+ }
+ break;
+ case 226: /* expr ::= CASE case_operand case_exprlist case_else END */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->pList = yymsp[-2].minor.yy242;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy450);
+ }else{
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy242);
+ }
+ sqlite3ExprSpan(yygotominor.yy450, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+}
+ break;
+ case 227: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+{
+ yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[-2].minor.yy450, 0);
+ yygotominor.yy242 = sqlite3ExprListAppend(pParse,yygotominor.yy242, yymsp[0].minor.yy450, 0);
+}
+ break;
+ case 228: /* case_exprlist ::= WHEN expr THEN expr */
+{
+ yygotominor.yy242 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy450, 0);
+ yygotominor.yy242 = sqlite3ExprListAppend(pParse,yygotominor.yy242, yymsp[0].minor.yy450, 0);
+}
+ break;
+ 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.yy174, yymsp[-9].minor.yy46,
- &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46);
-}
- break;
- case 235: /* uniqueflag ::= UNIQUE */
- case 283: /* raisetype ::= ABORT */
-{yygotominor.yy46 = OE_Abort;}
- break;
- case 236: /* uniqueflag ::= */
-{yygotominor.yy46 = OE_None;}
- break;
- case 239: /* idxlist ::= idxlist COMMA idxitem collate sortorder */
+ 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 238: /* uniqueflag ::= UNIQUE */
+ case 285: /* raisetype ::= ABORT */
+{yygotominor.yy316 = OE_Abort;}
+ break;
+ case 239: /* uniqueflag ::= */
+{yygotominor.yy316 = OE_None;}
+ break;
+ 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.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 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.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174, p, &yymsp[-2].minor.yy0);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index");
- if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
-}
- break;
- case 240: /* idxlist ::= idxitem collate sortorder */
-{
- Expr *p = 0;
- if( yymsp[-1].minor.yy0.n>0 ){
- p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
- sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy0);
- }
- yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy174, "index");
- if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46;
-}
- break;
- case 242: /* collate ::= */
+ 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 244: /* collate ::= */
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
break;
- case 244: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy373, yymsp[-1].minor.yy46);}
- break;
- case 245: /* cmd ::= VACUUM */
- case 246: /* cmd ::= VACUUM nm */
+ case 246: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy419, yymsp[-1].minor.yy316);}
+ break;
+ case 247: /* cmd ::= VACUUM */
+ case 248: /* cmd ::= VACUUM nm */
{sqlite3Vacuum(pParse);}
break;
- case 247: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
- case 248: /* cmd ::= PRAGMA nm dbnm EQ ON */
- case 249: /* 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 250: /* 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 251: /* 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 252: /* cmd ::= PRAGMA nm dbnm */
+ case 254: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 260: /* 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.yy243, &all);
-}
- break;
- case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy75, &all);
+}
+ break;
+ 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.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[0].minor.yy172, yymsp[-10].minor.yy46, yymsp[-8].minor.yy46);
+ 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 262: /* trigger_time ::= BEFORE */
- case 265: /* trigger_time ::= */
-{ yygotominor.yy46 = TK_BEFORE; }
- break;
- case 263: /* trigger_time ::= AFTER */
-{ yygotominor.yy46 = TK_AFTER; }
- break;
- case 264: /* trigger_time ::= INSTEAD OF */
-{ yygotominor.yy46 = TK_INSTEAD;}
- break;
- case 266: /* trigger_event ::= DELETE|INSERT */
- case 267: /* trigger_event ::= UPDATE */
-{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;}
- break;
- case 268: /* trigger_event ::= UPDATE OF inscollist */
-{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;}
- break;
- case 271: /* when_clause ::= */
- case 288: /* key_opt ::= */
-{ yygotominor.yy172 = 0; }
- break;
- case 272: /* when_clause ::= WHEN expr */
- case 289: /* key_opt ::= KEY expr */
-{ yygotominor.yy172 = yymsp[0].minor.yy172; }
- break;
- case 273: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 264: /* trigger_time ::= BEFORE */
+ case 267: /* trigger_time ::= */
+{ yygotominor.yy316 = TK_BEFORE; }
+ break;
+ case 265: /* trigger_time ::= AFTER */
+{ yygotominor.yy316 = TK_AFTER; }
+ break;
+ case 266: /* trigger_time ::= INSTEAD OF */
+{ yygotominor.yy316 = TK_INSTEAD;}
+ break;
+ case 268: /* trigger_event ::= DELETE|INSERT */
+ case 269: /* trigger_event ::= UPDATE */
+{yygotominor.yy354.a = yymsp[0].major; yygotominor.yy354.b = 0;}
+ break;
+ case 270: /* trigger_event ::= UPDATE OF inscollist */
+{yygotominor.yy354.a = TK_UPDATE; yygotominor.yy354.b = yymsp[0].minor.yy352;}
+ break;
+ case 273: /* when_clause ::= */
+ case 290: /* key_opt ::= */
+{ yygotominor.yy450 = 0; }
+ break;
+ case 274: /* when_clause ::= WHEN expr */
+ case 291: /* key_opt ::= KEY expr */
+{ yygotominor.yy450 = yymsp[0].minor.yy450; }
+ break;
+ case 275: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+{
+/*
+ if( yymsp[-2].minor.yy75 ){
+ yymsp[-2].minor.yy75->pLast->pNext = yymsp[-1].minor.yy75;
+ }else{
+ yymsp[-2].minor.yy75 = yymsp[-1].minor.yy75;
+ }
+*/
+ 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 276: /* trigger_cmd_list ::= trigger_cmd SEMI */
+{
+ /* if( yymsp[-1].minor.yy75 ) */
+ assert( yymsp[-1].minor.yy75!=0 );
+ yymsp[-1].minor.yy75->pLast = yymsp[-1].minor.yy75;
+ yygotominor.yy75 = yymsp[-1].minor.yy75;
+}
+ break;
+ case 277: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
+{ yygotominor.yy75 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy242, yymsp[0].minor.yy450, yymsp[-4].minor.yy316); }
+ break;
+ case 278: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
+{yygotominor.yy75 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy352, yymsp[-1].minor.yy242, 0, yymsp[-7].minor.yy316);}
+ break;
+ case 279: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
+{yygotominor.yy75 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy352, 0, yymsp[0].minor.yy43, yymsp[-4].minor.yy316);}
+ break;
+ case 280: /* trigger_cmd ::= DELETE FROM nm where_opt */
+{yygotominor.yy75 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy450);}
+ break;
+ case 281: /* trigger_cmd ::= select */
+{yygotominor.yy75 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy43); }
+ break;
+ case 282: /* expr ::= RAISE LP IGNORE RP */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
+ if( yygotominor.yy450 ){
+ yygotominor.yy450->iColumn = OE_Ignore;
+ sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
+ }
+}
+ break;
+ case 283: /* expr ::= RAISE LP raisetype COMMA nm RP */
+{
+ yygotominor.yy450 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ if( yygotominor.yy450 ) {
+ yygotominor.yy450->iColumn = yymsp[-3].minor.yy316;
+ sqlite3ExprSpan(yygotominor.yy450, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+ }
+}
+ break;
+ case 284: /* raisetype ::= ROLLBACK */
+{yygotominor.yy316 = OE_Rollback;}
+ break;
+ case 286: /* raisetype ::= FAIL */
+{yygotominor.yy316 = OE_Fail;}
+ break;
+ case 287: /* cmd ::= DROP TRIGGER ifexists fullname */
+{
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy419,yymsp[-1].minor.yy316);
+}
+ break;
+ case 288: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- if( yymsp[-2].minor.yy243 ){
- yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243;
- }else{
- yymsp[-2].minor.yy243 = yymsp[-1].minor.yy243;
- }
- yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243;
- yygotominor.yy243 = yymsp[-2].minor.yy243;
-}
- break;
- case 274: /* trigger_cmd_list ::= */
-{ yygotominor.yy243 = 0; }
- break;
- case 275: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
-{ yygotominor.yy243 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); }
- break;
- case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
-{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);}
- break;
- case 277: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
-{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);}
- break;
- case 278: /* trigger_cmd ::= DELETE FROM nm where_opt */
-{yygotominor.yy243 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy172);}
- break;
- case 279: /* trigger_cmd ::= select */
-{yygotominor.yy243 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy219); }
- break;
- case 280: /* expr ::= RAISE LP IGNORE RP */
+ sqlite3Attach(pParse, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, yymsp[0].minor.yy450);
+}
+ break;
+ case 289: /* cmd ::= DETACH database_kw_opt expr */
{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
- if( yygotominor.yy172 ){
- yygotominor.yy172->iColumn = OE_Ignore;
- sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
- }
-}
- break;
- case 281: /* expr ::= RAISE LP raisetype COMMA nm RP */
-{
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
- if( yygotominor.yy172 ) {
- yygotominor.yy172->iColumn = yymsp[-3].minor.yy46;
- sqlite3ExprSpan(yygotominor.yy172, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
- }
-}
- break;
- case 282: /* raisetype ::= ROLLBACK */
-{yygotominor.yy46 = OE_Rollback;}
- break;
- case 284: /* raisetype ::= FAIL */
-{yygotominor.yy46 = OE_Fail;}
- break;
- case 285: /* cmd ::= DROP TRIGGER ifexists fullname */
-{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46);
-}
- break;
- case 286: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
-{
- sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy172);
-}
- break;
- case 287: /* cmd ::= DETACH database_kw_opt expr */
-{
- sqlite3Detach(pParse, yymsp[0].minor.yy172);
-}
- break;
- case 292: /* cmd ::= REINDEX */
+ sqlite3Detach(pParse, yymsp[0].minor.yy450);
+}
+ break;
+ case 294: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 293: /* cmd ::= REINDEX nm dbnm */
+ case 295: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 294: /* cmd ::= ANALYZE */
+ case 296: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 295: /* cmd ::= ANALYZE nm dbnm */
+ case 297: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 296: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 298: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy0);
-}
- break;
- case 297: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy419,&yymsp[0].minor.yy0);
+}
+ break;
+ case 299: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
break;
- case 298: /* add_column_fullname ::= fullname */
+ case 300: /* add_column_fullname ::= fullname */
{
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373);
-}
- break;
- case 301: /* cmd ::= create_vtab */
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy419);
+}
+ break;
+ case 303: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 302: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 304: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 303: /* 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 306: /* vtabarg ::= */
+ case 308: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 308: /* vtabargtoken ::= ANY */
- case 309: /* vtabargtoken ::= lp anylist RP */
- case 310: /* lp ::= LP */
- case 312: /* 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;
};
yygoto = yyRuleInfo[yyruleno].lhs;
@@ -78638,9 +81713,9 @@
fprintf(yyTraceFILE,"%sDiscard input token %s\n",
yyTracePrompt,yyTokenName[yymajor]);
}
#endif
- yy_destructor(yymajor,&yyminorunion);
+ yy_destructor(yypParser, yymajor,&yyminorunion);
yymajor = YYNOCODE;
}else{
while(
yypParser->yyidx >= 0 &&
@@ -78651,9 +81726,9 @@
){
yy_pop_parser_stack(yypParser);
}
if( yypParser->yyidx < 0 || yymajor==0 ){
- yy_destructor(yymajor,&yyminorunion);
+ yy_destructor(yypParser,yymajor,&yyminorunion);
yy_parse_failed(yypParser);
yymajor = YYNOCODE;
}else if( yymx!=YYERRORSYMBOL ){
YYMINORTYPE u2;
@@ -78676,9 +81751,9 @@
if( yypParser->yyerrcnt<=0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
}
yypParser->yyerrcnt = 3;
- yy_destructor(yymajor,&yyminorunion);
+ yy_destructor(yypParser,yymajor,&yyminorunion);
if( yyendofinput ){
yy_parse_failed(yypParser);
}
yymajor = YYNOCODE;
@@ -78706,9 +81781,9 @@
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.146 2008/07/08 19:34:07 drh Exp $
+** $Id: tokenize.c,v 1.152 2008/09/01 15:52:11 drh Exp $
*/
/*
** The charMap() macro maps alphabetic characters into their
@@ -78759,9 +81834,9 @@
/***** This file contains automatically generated code ******
**
** The code in this file has been automatically generated by
**
-** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.31 2007/07/30 18:26:20 rse Exp $
+** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.32 2008/10/06 05:32:19 danielk1977 Exp $
**
** The code in this file implements a function that determines whether
** or not a given identifier is really an SQL keyword. The same thing
** might be implemented more directly using a hand-written hash table.
@@ -78768,91 +81843,91 @@
** But by using this automatically generated code, the size of the code
** 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, 45, 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, 89, 0, 0, 44,
+ 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,
+ 90, 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,
+ 51, 46, 73, 0, 0, 83, 102, 0, 109, 0, 35, 0, 0,
+ 28, 0, 75, 48, 53, 0, 20, 52, 0, 43,
+ };
+ 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, 32, 0, 21, 0, 0, 0, 0, 0, 29,
+ 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, 61, 11, 68,
+ 0, 8, 0, 93, 87, 0, 96, 0, 49, 0, 0, 64, 0,
+ 41, 103, 0, 27, 107, 36, 62, 72, 0, 0, 57, 0, 0,
};
- static const unsigned char aNext[116] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
- 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0,
- 17, 0, 0, 0, 36, 39, 0, 0, 25, 0, 0, 31, 0,
- 0, 0, 43, 52, 0, 0, 0, 53, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 51, 0, 0, 0, 0, 26, 0, 8, 46,
- 2, 0, 0, 0, 0, 0, 0, 0, 3, 58, 66, 0, 13,
- 0, 91, 85, 0, 94, 0, 74, 0, 0, 62, 0, 35, 101,
- 0, 0, 105, 23, 30, 60, 70, 0, 0, 59, 0, 0,
+ static const unsigned char aLen[117] = {
+ 7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
+ 7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 6,
+ 11, 2, 7, 5, 5, 9, 6, 10, 9, 7, 10, 6, 5,
+ 6, 6, 5, 6, 9, 4, 2, 5, 5, 6, 7, 3, 7,
+ 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, 12, 17, 7,
+ 8, 8, 2, 4, 4, 4, 4, 4, 2, 2, 4, 6, 2,
+ 3, 6, 5, 5, 5, 8, 3, 5, 5, 6, 4, 9, 3,
};
- static const unsigned char aLen[116] = {
- 6, 7, 3, 6, 6, 7, 7, 3, 4, 6, 4, 5, 3,
- 10, 9, 5, 4, 4, 3, 8, 2, 6, 11, 2, 7, 5,
- 5, 4, 6, 7, 10, 6, 5, 6, 6, 5, 6, 4, 9,
- 2, 5, 5, 7, 5, 9, 6, 7, 7, 3, 4, 4, 7,
- 3, 10, 4, 7, 6, 12, 6, 6, 9, 4, 6, 5, 4,
- 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7,
- 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8,
- 2, 4, 4, 4, 4, 4, 2, 2, 4, 6, 2, 3, 6,
- 5, 8, 5, 5, 8, 3, 5, 5, 6, 4, 9, 3,
- };
- static const unsigned short int aOffset[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_NOT, TK_NOTNULL, 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;
h = ((charMap(z[0])*4) ^
@@ -78935,9 +82010,9 @@
}
case '-': {
if( z[1]=='-' ){
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
- *tokenType = TK_COMMENT;
+ *tokenType = TK_SPACE;
return i;
}
*tokenType = TK_MINUS;
return 1;
@@ -78968,9 +82043,9 @@
return 1;
}
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
- *tokenType = TK_COMMENT;
+ *tokenType = TK_SPACE;
return i;
}
case '%': {
*tokenType = TK_REM;
@@ -79049,10 +82124,13 @@
break;
}
}
}
- if( c ){
+ if( c=='\'' ){
*tokenType = TK_STRING;
+ return i+1;
+ }else if( c!=0 ){
+ *tokenType = TK_ID;
return i+1;
}else{
*tokenType = TK_ILLEGAL;
return i;
@@ -79221,10 +82299,9 @@
pParse->rc = SQLITE_TOOBIG;
break;
}
switch( tokenType ){
- case TK_SPACE:
- case TK_COMMENT: {
+ case TK_SPACE: {
if( db->u1.isInterrupted ){
pParse->rc = SQLITE_INTERRUPT;
sqlite3SetString(pzErrMsg, db, "interrupt");
goto abort_parse;
@@ -79231,9 +82308,9 @@
}
break;
}
case TK_ILLEGAL: {
- sqlite3_free(*pzErrMsg);
+ sqlite3DbFree(db, *pzErrMsg);
*pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"",
&pParse->sLastToken);
nErr++;
goto abort_parse;
@@ -79259,8 +82336,13 @@
pParse->zTail = &zSql[i];
}
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
+#ifdef YYTRACKMAXSTACKDEPTH
+ sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK,
+ sqlite3ParserStackPeak(pEngine)
+ );
+#endif /* YYDEBUG */
sqlite3ParserFree(pEngine, sqlite3_free);
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM;
}
@@ -79270,9 +82352,9 @@
if( pParse->zErrMsg ){
if( *pzErrMsg==0 ){
*pzErrMsg = pParse->zErrMsg;
}else{
- sqlite3_free(pParse->zErrMsg);
+ sqlite3DbFree(db, pParse->zErrMsg);
}
pParse->zErrMsg = 0;
nErr++;
}
@@ -79281,15 +82363,15 @@
pParse->pVdbe = 0;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
if( pParse->nested==0 ){
- sqlite3_free(pParse->aTableLock);
+ sqlite3DbFree(db, pParse->aTableLock);
pParse->aTableLock = 0;
pParse->nTableLock = 0;
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlite3_free(pParse->apVtabLock);
+ sqlite3DbFree(db, pParse->apVtabLock);
#endif
if( !IN_DECLARE_VTAB ){
/* If the pParse->declareVtab flag is set, do not delete any table
@@ -79298,10 +82380,16 @@
*/
sqlite3DeleteTable(pParse->pNewTable);
}
- sqlite3DeleteTrigger(pParse->pNewTrigger);
- sqlite3_free(pParse->apVarExpr);
+ 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;
}
return nErr;
@@ -79603,9 +82691,9 @@
** implement the programmer interface to the library. Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.477 2008/07/15 14:47:19 drh Exp $
+** $Id: main.c,v 1.509 2008/10/30 15:03:16 drh Exp $
*/
#ifdef SQLITE_ENABLE_FTS3
/************** Include fts3.h in the middle of main.c ***********************/
@@ -79670,8 +82758,41 @@
/************** 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
*/
@@ -79702,68 +82823,149 @@
/*
** Initialize SQLite.
**
** This routine must be called to initialize the memory allocation,
-** VFS, and mutex subsystesms prior to doing any serious work with
+** VFS, and mutex subsystems prior to doing any serious work with
** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
** sqlite3_open().
**
** This routine is a no-op except on its very first call for the process,
** or for the first call after a call to sqlite3_shutdown.
+**
+** The first thread to call this routine runs the initialization to
+** completion. If subsequent threads call this routine before the first
+** thread has finished the initialization process, then the subsequent
+** threads must block until the first thread finishes with the initialization.
+**
+** The first thread might call this routine recursively. Recursive
+** calls to this routine should not block, of course. Otherwise the
+** initialization process would never complete.
+**
+** Let X be the first thread to enter this routine. Let Y be some other
+** thread. Then while the initial invocation of this routine by X is
+** incomplete, it is required that:
+**
+** * Calls to this routine from Y must block until the outer-most
+** call by X completes.
+**
+** * Recursive calls to this routine from thread X return immediately
+** without blocking.
*/
SQLITE_API int sqlite3_initialize(void){
- static int inProgress = 0;
- int rc;
-
- /* If SQLite is already initialized, this call is a no-op. */
- if( sqlite3Config.isInit ) return SQLITE_OK;
-
- /* Make sure the mutex system is initialized. */
+ 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( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
+
+ /* Make sure the mutex subsystem is initialized. If unable to
+ ** initialize the mutex subsystem, return early with the error.
+ ** If the system is so sick that we are unable to allocate a mutex,
+ ** there is not much SQLite is going to be able to do.
+ **
+ ** The mutex subsystem must take care of serializing its own
+ ** initialization.
+ */
rc = sqlite3MutexInit();
-
+ if( rc ) return rc;
+
+ /* Initialize the malloc() system and the recursive pInitMutex mutex.
+ ** This operation is protected by the STATIC_MASTER mutex. Note that
+ ** MutexAlloc() is called for a static mutex prior to initializing the
+ ** malloc subsystem - this implies that the allocation of a static
+ ** mutex must not require support from the malloc subsystem.
+ */
+ pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
+ sqlite3_mutex_enter(pMaster);
+ if( !sqlite3GlobalConfig.isMallocInit ){
+ rc = sqlite3MallocInit();
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3GlobalConfig.isMallocInit = 1;
+ if( !sqlite3GlobalConfig.pInitMutex ){
+ sqlite3GlobalConfig.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
+ if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+ }
if( rc==SQLITE_OK ){
-
- /* Initialize the malloc() system and the recursive pInitMutex mutex.
- ** This operation is protected by the STATIC_MASTER mutex.
- */
- sqlite3_mutex *pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
- sqlite3_mutex_enter(pMaster);
- if( !sqlite3Config.isMallocInit ){
- rc = sqlite3MallocInit();
- }
- if( rc==SQLITE_OK ){
- sqlite3Config.isMallocInit = 1;
- if( !sqlite3Config.pInitMutex ){
- sqlite3Config.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
- if( sqlite3Config.bCoreMutex && !sqlite3Config.pInitMutex ){
- rc = SQLITE_NOMEM;
- }
- }
- }
- sqlite3_mutex_leave(pMaster);
- if( rc!=SQLITE_OK ){
- return rc;
- }
-
- /* Enter the recursive pInitMutex mutex. After doing so, if the
- ** sqlite3Config.isInit flag is true, then some other thread has
- ** finished doing the initialization. If the inProgress flag is
- ** true, then this function is being called recursively from within
- ** the sqlite3_os_init() call below. In either case, exit early.
- */
- sqlite3_mutex_enter(sqlite3Config.pInitMutex);
- if( sqlite3Config.isInit || inProgress ){
- sqlite3_mutex_leave(sqlite3Config.pInitMutex);
- return SQLITE_OK;
- }
- sqlite3StatusReset();
- inProgress = 1;
+ sqlite3GlobalConfig.nRefInitMutex++;
+ }
+ sqlite3_mutex_leave(pMaster);
+
+ /* If unable to initialize the malloc subsystem, then return early.
+ ** There is little hope of getting SQLite to run if the malloc
+ ** subsystem cannot be initialized.
+ */
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+
+ /* Do the rest of the initialization under the recursive mutex so
+ ** that we will be able to handle recursive calls into
+ ** sqlite3_initialize(). The recursive calls normally come through
+ ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other
+ ** recursive calls might also be possible.
+ */
+ sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex);
+ if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){
+ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
+ sqlite3GlobalConfig.inProgress = 1;
+ memset(pHash, 0, sizeof(sqlite3GlobalFunctions));
+ sqlite3RegisterGlobalFunctions();
rc = sqlite3_os_init();
- inProgress = 0;
- sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
- sqlite3_mutex_leave(sqlite3Config.pInitMutex);
- }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PcacheInitialize();
+ sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
+ sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
+ }
+ sqlite3GlobalConfig.inProgress = 0;
+ sqlite3GlobalConfig.isInit = (rc==SQLITE_OK ? 1 : 0);
+ }
+ sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex);
+
+ /* Go back under the static mutex and clean up the recursive
+ ** mutex to prevent a resource leak.
+ */
+ sqlite3_mutex_enter(pMaster);
+ sqlite3GlobalConfig.nRefInitMutex--;
+ if( sqlite3GlobalConfig.nRefInitMutex<=0 ){
+ assert( sqlite3GlobalConfig.nRefInitMutex==0 );
+ sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
+ sqlite3GlobalConfig.pInitMutex = 0;
+ }
+ sqlite3_mutex_leave(pMaster);
+
+ /* The following is just a sanity check to make sure SQLite has
+ ** been compiled correctly. It is important to run this code, but
+ ** we don't want to run it too often and soak up CPU cycles for no
+ ** reason. So we run it once during initialization.
+ */
+#ifndef NDEBUG
+ /* This section of code's only "output" is via assert() statements. */
+ if ( rc==SQLITE_OK ){
+ u64 x = (((u64)1)<<63)-1;
+ double y;
+ assert(sizeof(x)==8);
+ assert(sizeof(x)==sizeof(y));
+ memcpy(&y, &x, 8);
+ assert( sqlite3IsNaN(y) );
+ }
+#endif
+
return rc;
}
/*
@@ -79772,21 +82974,16 @@
** while any part of SQLite is otherwise in use in any thread. This
** routine is not threadsafe. Not by a long shot.
*/
SQLITE_API int sqlite3_shutdown(void){
- sqlite3_mutex_free(sqlite3Config.pInitMutex);
- sqlite3Config.pInitMutex = 0;
- sqlite3Config.isMallocInit = 0;
- if( sqlite3Config.isInit ){
+ sqlite3GlobalConfig.isMallocInit = 0;
+ sqlite3PcacheShutdown();
+ 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;
}
/*
@@ -79803,103 +83000,201 @@
int rc = 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;
- }
+ sqlite3GlobalConfig.bCoreMutex = 1;
+ sqlite3GlobalConfig.bFullMutex = 1;
+ break;
+ }
+ case SQLITE_CONFIG_MUTEX: {
+ /* Specify an alternative mutex implementation */
+ sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*);
+ break;
+ }
+ case SQLITE_CONFIG_GETMUTEX: {
+ /* Retrieve the current mutex implementation */
+ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex;
+ break;
+ }
+#endif
+
+
case SQLITE_CONFIG_MALLOC: {
/* Specify an alternative malloc implementation */
- sqlite3Config.m = *va_arg(ap, sqlite3_mem_methods*);
+ sqlite3GlobalConfig.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;
- break;
- }
- case SQLITE_CONFIG_MUTEX: {
- /* Specify an alternative mutex implementation */
- sqlite3Config.mutex = *va_arg(ap, sqlite3_mutex_methods*);
- break;
- }
- case SQLITE_CONFIG_GETMUTEX: {
- /* Retrieve the current mutex implementation */
- *va_arg(ap, sqlite3_mutex_methods*) = sqlite3Config.mutex;
+ 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);
-
- if( sqlite3Config.pHeap==0 ){
+ sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
+ sqlite3GlobalConfig.nHeap = va_arg(ap, int);
+ sqlite3GlobalConfig.mnReq = va_arg(ap, int);
+
+ 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
** ENABLE_MEMSYS5 is defined, return an error.
** 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();
-#endif
- }
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5();
+#endif
+ }
+ break;
+ }
+#endif
+
+#if defined(SQLITE_ENABLE_MEMSYS6)
+ case SQLITE_CONFIG_CHUNKALLOC: {
+ sqlite3GlobalConfig.nSmall = va_arg(ap, int);
+ sqlite3GlobalConfig.m = *sqlite3MemGetMemsys6();
+ break;
+ }
+#endif
+
+ case SQLITE_CONFIG_LOOKASIDE: {
+ sqlite3GlobalConfig.szLookaside = va_arg(ap, int);
+ sqlite3GlobalConfig.nLookaside = va_arg(ap, int);
+ break;
+ }
+
+ default: {
+ rc = SQLITE_ERROR;
+ break;
+ }
+ }
+ va_end(ap);
+ return rc;
+}
+
+/*
+** Set up the lookaside buffers for a database connection.
+** Return SQLITE_OK on success.
+** If lookaside is already active, return SQLITE_BUSY.
+**
+** The sz parameter is the number of bytes in each lookaside slot.
+** The cnt parameter is the number of slots. If pStart is NULL the
+** space for the lookaside memory is obtained from sqlite3_malloc().
+** If pStart is not NULL then it is sz*cnt bytes of memory to use for
+** the lookaside memory.
+*/
+static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
+ void *pStart;
+ if( db->lookaside.nOut ){
+ return SQLITE_BUSY;
+ }
+ if( sz<0 ) sz = 0;
+ if( cnt<0 ) cnt = 0;
+ if( pBuf==0 ){
+ sz = (sz + 7)&~7;
+ sqlite3BeginBenignMalloc();
+ pStart = sqlite3Malloc( sz*cnt );
+ sqlite3EndBenignMalloc();
+ }else{
+ sz = sz&~7;
+ pStart = pBuf;
+ }
+ if( db->lookaside.bMalloced ){
+ sqlite3_free(db->lookaside.pStart);
+ }
+ db->lookaside.pStart = pStart;
+ db->lookaside.pFree = 0;
+ db->lookaside.sz = sz;
+ db->lookaside.bMalloced = pBuf==0;
+ if( pStart ){
+ int i;
+ LookasideSlot *p;
+ p = (LookasideSlot*)pStart;
+ for(i=cnt-1; i>=0; i--){
+ p->pNext = db->lookaside.pFree;
+ db->lookaside.pFree = p;
+ p = (LookasideSlot*)&((u8*)p)[sz];
+ }
+ db->lookaside.pEnd = p;
+ db->lookaside.bEnabled = 1;
+ }else{
+ db->lookaside.pEnd = 0;
+ db->lookaside.bEnabled = 0;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Configuration settings for an individual database connection
+*/
+SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
+ va_list ap;
+ int rc;
+ va_start(ap, op);
+ switch( op ){
+ case SQLITE_DBCONFIG_LOOKASIDE: {
+ void *pBuf = va_arg(ap, void*);
+ int sz = va_arg(ap, int);
+ int cnt = va_arg(ap, int);
+ rc = setupLookaside(db, pBuf, sz, cnt);
break;
}
-#endif
-
default: {
rc = SQLITE_ERROR;
break;
}
@@ -80052,16 +83347,19 @@
}
sqlite3ResetInternalSchema(db, 0);
assert( db->nDb<=2 );
assert( db->aDb==db->aDbStatic );
- for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
- FuncDef *pFunc, *pNext;
- for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
- pNext = pFunc->pNext;
- sqlite3_free(pFunc);
- }
- }
-
+ for(j=0; j<ArraySize(db->aFunc.a); j++){
+ FuncDef *pNext, *pHash, *p;
+ for(p=db->aFunc.a[j]; p; p=pHash){
+ pHash = p->pHash;
+ while( p ){
+ pNext = p->pNext;
+ sqlite3DbFree(db, p);
+ p = pNext;
+ }
+ }
+ }
for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
CollSeq *pColl = (CollSeq *)sqliteHashData(i);
/* Invoke any destructors registered for collation sequence user data. */
for(j=0; j<3; j++){
@@ -80068,9 +83366,9 @@
if( pColl[j].xDel ){
pColl[j].xDel(pColl[j].pUser);
}
}
- sqlite3_free(pColl);
+ sqlite3DbFree(db, pColl);
}
sqlite3HashClear(&db->aCollSeq);
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
@@ -80077,14 +83375,13 @@
Module *pMod = (Module *)sqliteHashData(i);
if( pMod->xDestroy ){
pMod->xDestroy(pMod->pAux);
}
- sqlite3_free(pMod);
+ sqlite3DbFree(db, pMod);
}
sqlite3HashClear(&db->aModule);
#endif
- sqlite3HashClear(&db->aFunc);
sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
if( db->pErr ){
sqlite3ValueFree(db->pErr);
}
@@ -80097,12 +83394,16 @@
** So it needs to be freed here. Todo: Why not roll the temp schema into
** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
- sqlite3_free(db->aDb[1].pSchema);
+ sqlite3DbFree(db, db->aDb[1].pSchema);
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);
+ }
sqlite3_free(db);
return SQLITE_OK;
}
@@ -80430,9 +83731,9 @@
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
zFunc8 = sqlite3Utf16to8(db, zFunctionName, -1);
rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal);
- sqlite3_free(zFunc8);
+ sqlite3DbFree(db, zFunc8);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -80728,8 +84029,17 @@
return SQLITE_NOMEM;
}
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
** and the encoding is enc.
@@ -80842,19 +84152,22 @@
#endif
#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
-#endif
-#if SQLITE_MAX_ATTACH<0 || SQLITE_MAX_ATTACH>30
-# error SQLITE_MAX_ATTACH must be between 0 and 30
+#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
#endif
#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
# error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
#endif
#if SQLITE_MAX_VARIABLE_NUMBER<1
# error SQLITE_MAX_VARIABLE_NUMBER must be at least 1
+#endif
+#if SQLITE_MAX_COLUMN>32767
+# error SQLITE_MAX_COLUMN must not exceed 32767
#endif
/*
@@ -80895,17 +84208,23 @@
){
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 */
flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
@@ -80915,15 +84234,16 @@
SQLITE_OPEN_MAIN_JOURNAL |
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);
db = 0;
@@ -80935,8 +84255,9 @@
db->priorNewRowid = 0;
db->nDb = 2;
db->magic = SQLITE_MAGIC_BUSY;
db->aDb = db->aDbStatic;
+
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
db->autoCommit = 1;
db->nextAutovac = -1;
@@ -80948,18 +84269,16 @@
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
| SQLITE_LoadExtension
#endif
;
- sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
- 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);
if( !db->pVfs ){
rc = SQLITE_ERROR;
- db->magic = SQLITE_MAGIC_SICK;
sqlite3Error(db, rc, "no such vfs: %s", zVfs);
goto opendb_out;
}
@@ -80971,9 +84290,8 @@
createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0);
createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
if( db->mallocFailed ){
- db->magic = SQLITE_MAGIC_SICK;
goto opendb_out;
}
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
assert( db->pDfltColl!=0 );
@@ -80993,10 +84311,12 @@
rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE,
flags | SQLITE_OPEN_MAIN_DB,
&db->aDb[0].pBt);
if( rc!=SQLITE_OK ){
- sqlite3Error(db, rc, 0);
- db->magic = SQLITE_MAGIC_SICK;
+ if( rc==SQLITE_IOERR_NOMEM ){
+ rc = SQLITE_NOMEM;
+ }
+ sqlite3Error(db, rc, 0);
goto opendb_out;
}
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
@@ -81053,9 +84373,8 @@
#endif
#ifdef SQLITE_ENABLE_ICU
if( !db->mallocFailed && rc==SQLITE_OK ){
- extern int sqlite3IcuInit(sqlite3*);
rc = sqlite3IcuInit(db);
}
#endif
@@ -81076,16 +84395,23 @@
sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt),
SQLITE_DEFAULT_LOCKING_MODE);
#endif
+ /* Enable the lookaside-malloc subsystem */
+ 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);
}
- if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){
+ rc = sqlite3_errcode(db);
+ if( rc==SQLITE_NOMEM ){
sqlite3_close(db);
db = 0;
+ }else if( rc!=SQLITE_OK ){
+ db->magic = SQLITE_MAGIC_SICK;
}
*ppDb = db;
return sqlite3ApiExit(0, rc);
}
@@ -81203,9 +84529,9 @@
assert( !db->mallocFailed );
zName8 = sqlite3Utf16to8(db, zName, -1);
if( zName8 ){
rc = createCollation(db, zName8, enc, pCtx, xCompare, 0);
- sqlite3_free(zName8);
+ sqlite3DbFree(db, zName8);
}
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
@@ -81248,15 +84574,17 @@
}
#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.
*/
SQLITE_API int sqlite3_global_recover(void){
return SQLITE_OK;
}
+#endif
#endif
/*
** Test to see whether or not the database connection is in autocommit
@@ -81280,8 +84608,9 @@
return SQLITE_CORRUPT;
}
#endif
+#ifndef SQLITE_OMIT_DEPRECATED
/*
** This is a convenience routine that makes sure that all thread-specific
** data for this thread has been deallocated.
**
@@ -81289,8 +84618,9 @@
** no-op. It is retained for historical compatibility.
*/
SQLITE_API void sqlite3_thread_cleanup(void){
}
+#endif
/*
** Return meta information about a specific column of a database table.
** See comment in sqlite3.h (sqlite.h.in) for details.
@@ -81369,9 +84699,9 @@
zDataType = pCol->zType;
zCollSeq = pCol->zColl;
notnull = pCol->notNull!=0;
primarykey = pCol->isPrimKey!=0;
- autoinc = pTab->iPKey==iCol && pTab->autoInc;
+ autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
}else{
zDataType = "INTEGER";
primarykey = 1;
}
@@ -81392,15 +84722,15 @@
if( pPrimaryKey ) *pPrimaryKey = primarykey;
if( pAutoinc ) *pAutoinc = autoinc;
if( SQLITE_OK==rc && !pTab ){
- sqlite3_free(zErrMsg);
- zErrMsg = sqlite3MPrintf("no such table column: %s.%s", zTableName,
+ sqlite3DbFree(db, zErrMsg);
+ zErrMsg = sqlite3MPrintf(db, "no such table column: %s.%s", zTableName,
zColumnName);
rc = SQLITE_ERROR;
}
sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg);
- sqlite3_free(zErrMsg);
+ sqlite3DbFree(db, zErrMsg);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -83622,9 +86952,9 @@
typedef struct QueryTerm {
short int nPhrase; /* How many following terms are part of the same phrase */
short int iPhrase; /* This is the i-th term of a phrase. */
short int iColumn; /* Column of the index that must match this term */
- 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 "*" */
char *pTerm; /* text of the term. '\000' terminated. malloced */
@@ -83718,8 +87048,9 @@
SEGDIR_DELETE_STMT,
SEGDIR_SELECT_SEGMENT_STMT,
SEGDIR_SELECT_ALL_STMT,
SEGDIR_DELETE_ALL_STMT,
+ SEGDIR_COUNT_STMT,
MAX_STMT /* Always at end! */
} fulltext_statement;
@@ -83760,8 +87091,9 @@
/* SEGDIR_SELECT_ALL */
"select start_block, leaves_end_block, root from %_segdir "
" order by level desc, idx asc",
/* SEGDIR_DELETE_ALL */ "delete from %_segdir",
+ /* SEGDIR_COUNT */ "select count(*), ifnull(max(level),0) from %_segdir",
};
/*
** A connection to a fulltext index is an instance of the following
@@ -83924,17 +87256,20 @@
return (rc==SQLITE_DONE) ? SQLITE_OK : rc;
}
/* Like sql_get_statement(), but for special replicated LEAF_SELECT
-** statements.
+** statements. idx -1 is a special case for an uncached version of
+** the statement (used in the optimize implementation).
*/
/* TODO(shess) Write version for generic statements and then share
** that between the cached-statement functions.
*/
static int sql_get_leaf_statement(fulltext_vtab *v, int idx,
sqlite3_stmt **ppStmt){
- assert( idx>=0 && idx<MERGE_COUNT );
- if( v->pLeafSelectStmts[idx]==NULL ){
+ assert( idx>=-1 && idx<MERGE_COUNT );
+ if( idx==-1 ){
+ return sql_prepare(v->db, v->zDb, v->zName, ppStmt, LEAF_SELECT);
+ }else if( v->pLeafSelectStmts[idx]==NULL ){
int rc = sql_prepare(v->db, v->zDb, v->zName, &v->pLeafSelectStmts[idx],
LEAF_SELECT);
if( rc!=SQLITE_OK ) return rc;
}else{
@@ -84261,8 +87596,39 @@
rc = sql_get_statement(v, BLOCK_DELETE_ALL_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
return sql_single_step(s);
+}
+
+/* Returns SQLITE_OK with *pnSegments set to the number of entries in
+** %_segdir and *piMaxLevel set to the highest level which has a
+** segment. Otherwise returns the SQLite error which caused failure.
+*/
+static int segdir_count(fulltext_vtab *v, int *pnSegments, int *piMaxLevel){
+ sqlite3_stmt *s;
+ int rc = sql_get_statement(v, SEGDIR_COUNT_STMT, &s);
+ if( rc!=SQLITE_OK ) return rc;
+
+ rc = sqlite3_step(s);
+ /* TODO(shess): This case should not be possible? Should stronger
+ ** measures be taken if it happens?
+ */
+ if( rc==SQLITE_DONE ){
+ *pnSegments = 0;
+ *piMaxLevel = 0;
+ return SQLITE_OK;
+ }
+ if( rc!=SQLITE_ROW ) return rc;
+
+ *pnSegments = sqlite3_column_int(s, 0);
+ *piMaxLevel = sqlite3_column_int(s, 1);
+
+ /* We expect only one row. We must execute another sqlite3_step()
+ * to complete the iteration; otherwise the table will remain locked. */
+ rc = sqlite3_step(s);
+ if( rc==SQLITE_DONE ) return SQLITE_OK;
+ if( rc==SQLITE_ROW ) return SQLITE_ERROR;
+ return rc;
}
/* TODO(shess) clearPendingTerms() is far down the file because
** writeZeroSegment() is far down the file because LeafWriter is far
@@ -85567,20 +88933,20 @@
return -1;
}
/*
-** 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
** term found is marked with nPhrase=0 and OR and "-" syntax is significant.
*/
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 */
){
const sqlite3_tokenizer_module *pModule = pTokenizer->pModule;
@@ -85588,63 +88954,59 @@
int firstIndex = pQuery->nTerms;
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++;
- }
- pModule->xNext(pCursor, &pToken, &nToken, &iBegin, &iEnd, &iPos);
+ 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, &zToken, &nToken, &iBegin, &iEnd, &iPos);
} else {
pTerm->nNear = SQLITE_FTS3_DEFAULT_NEAR_PARAM;
}
pTerm->nNear++;
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;
if( inPhrase ){
@@ -85864,23 +89226,45 @@
){
fulltext_cursor *c = (fulltext_cursor *) pCursor;
fulltext_vtab *v = cursor_vtab(c);
int rc;
- StringBuffer sb;
FTSTRACE(("FTS3 Filter %p\n",pCursor));
- initStringBuffer(&sb);
- append(&sb, "SELECT docid, ");
- appendList(&sb, v->nColumn, v->azContentColumn);
- append(&sb, " FROM %_content");
- if( idxNum!=QUERY_GENERIC ) append(&sb, " WHERE docid = ?");
- sqlite3_finalize(c->pStmt);
- rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt, stringBufferData(&sb));
- stringBufferDestroy(&sb);
- if( rc!=SQLITE_OK ) return rc;
-
- c->iCursorType = idxNum;
+ /* If the cursor has a statement that was not prepared according to
+ ** idxNum, clear it. I believe all calls to fulltextFilter with a
+ ** given cursor will have the same idxNum , but in this case it's
+ ** easy to be safe.
+ */
+ if( c->pStmt && c->iCursorType!=idxNum ){
+ sqlite3_finalize(c->pStmt);
+ c->pStmt = NULL;
+ }
+
+ /* Get a fresh statement appropriate to idxNum. */
+ /* TODO(shess): Add a prepared-statement cache in the vt structure.
+ ** The cache must handle multiple open cursors. Easier to cache the
+ ** statement variants at the vt to reduce malloc/realloc/free here.
+ ** Or we could have a StringBuffer variant which allowed stack
+ ** construction for small values.
+ */
+ if( !c->pStmt ){
+ StringBuffer sb;
+ initStringBuffer(&sb);
+ append(&sb, "SELECT docid, ");
+ appendList(&sb, v->nColumn, v->azContentColumn);
+ append(&sb, " FROM %_content");
+ if( idxNum!=QUERY_GENERIC ) append(&sb, " WHERE docid = ?");
+ rc = sql_prepare(v->db, v->zDb, v->zName, &c->pStmt,
+ stringBufferData(&sb));
+ stringBufferDestroy(&sb);
+ if( rc!=SQLITE_OK ) return rc;
+ c->iCursorType = idxNum;
+ }else{
+ sqlite3_reset(c->pStmt);
+ assert( c->iCursorType==idxNum );
+ }
+
switch( idxNum ){
case QUERY_GENERIC:
break;
@@ -87138,8 +90522,14 @@
return sqlite3_reset(pReader->pStmt);
}
static void leavesReaderDestroy(LeavesReader *pReader){
+ /* If idx is -1, that means we're using a non-cached statement
+ ** handle in the optimize() case, so we need to release it.
+ */
+ if( pReader->pStmt!=NULL && pReader->idx==-1 ){
+ sqlite3_finalize(pReader->pStmt);
+ }
leafReaderDestroy(&pReader->leafReader);
dataBufferDestroy(&pReader->rootData);
SCRAMBLE(pReader);
}
@@ -88104,8 +91494,287 @@
SQLITE_STATIC);
}
}
+/* OptLeavesReader is nearly identical to LeavesReader, except that
+** where LeavesReader is geared towards the merging of complete
+** segment levels (with exactly MERGE_COUNT segments), OptLeavesReader
+** is geared towards implementation of the optimize() function, and
+** can merge all segments simultaneously. This version may be
+** somewhat less efficient than LeavesReader because it merges into an
+** accumulator rather than doing an N-way merge, but since segment
+** size grows exponentially (so segment count logrithmically) this is
+** probably not an immediate problem.
+*/
+/* TODO(shess): Prove that assertion, or extend the merge code to
+** merge tree fashion (like the prefix-searching code does).
+*/
+/* TODO(shess): OptLeavesReader and LeavesReader could probably be
+** merged with little or no loss of performance for LeavesReader. The
+** merged code would need to handle >MERGE_COUNT segments, and would
+** also need to be able to optionally optimize away deletes.
+*/
+typedef struct OptLeavesReader {
+ /* Segment number, to order readers by age. */
+ int segment;
+ LeavesReader reader;
+} OptLeavesReader;
+
+static int optLeavesReaderAtEnd(OptLeavesReader *pReader){
+ return leavesReaderAtEnd(&pReader->reader);
+}
+static int optLeavesReaderTermBytes(OptLeavesReader *pReader){
+ return leavesReaderTermBytes(&pReader->reader);
+}
+static const char *optLeavesReaderData(OptLeavesReader *pReader){
+ return leavesReaderData(&pReader->reader);
+}
+static int optLeavesReaderDataBytes(OptLeavesReader *pReader){
+ return leavesReaderDataBytes(&pReader->reader);
+}
+static const char *optLeavesReaderTerm(OptLeavesReader *pReader){
+ return leavesReaderTerm(&pReader->reader);
+}
+static int optLeavesReaderStep(fulltext_vtab *v, OptLeavesReader *pReader){
+ return leavesReaderStep(v, &pReader->reader);
+}
+static int optLeavesReaderTermCmp(OptLeavesReader *lr1, OptLeavesReader *lr2){
+ return leavesReaderTermCmp(&lr1->reader, &lr2->reader);
+}
+/* Order by term ascending, segment ascending (oldest to newest), with
+** exhausted readers to the end.
+*/
+static int optLeavesReaderCmp(OptLeavesReader *lr1, OptLeavesReader *lr2){
+ int c = optLeavesReaderTermCmp(lr1, lr2);
+ if( c!=0 ) return c;
+ return lr1->segment-lr2->segment;
+}
+/* Bubble pLr[0] to appropriate place in pLr[1..nLr-1]. Assumes that
+** pLr[1..nLr-1] is already sorted.
+*/
+static void optLeavesReaderReorder(OptLeavesReader *pLr, int nLr){
+ while( nLr>1 && optLeavesReaderCmp(pLr, pLr+1)>0 ){
+ OptLeavesReader tmp = pLr[0];
+ pLr[0] = pLr[1];
+ pLr[1] = tmp;
+ nLr--;
+ pLr++;
+ }
+}
+
+/* optimize() helper function. Put the readers in order and iterate
+** through them, merging doclists for matching terms into pWriter.
+** Returns SQLITE_OK on success, or the SQLite error code which
+** prevented success.
+*/
+static int optimizeInternal(fulltext_vtab *v,
+ OptLeavesReader *readers, int nReaders,
+ LeafWriter *pWriter){
+ int i, rc = SQLITE_OK;
+ DataBuffer doclist, merged, tmp;
+
+ /* Order the readers. */
+ i = nReaders;
+ while( i-- > 0 ){
+ optLeavesReaderReorder(&readers[i], nReaders-i);
+ }
+
+ dataBufferInit(&doclist, LEAF_MAX);
+ dataBufferInit(&merged, LEAF_MAX);
+
+ /* Exhausted readers bubble to the end, so when the first reader is
+ ** at eof, all are at eof.
+ */
+ while( !optLeavesReaderAtEnd(&readers[0]) ){
+
+ /* Figure out how many readers share the next term. */
+ for(i=1; i<nReaders && !optLeavesReaderAtEnd(&readers[i]); i++){
+ if( 0!=optLeavesReaderTermCmp(&readers[0], &readers[i]) ) break;
+ }
+
+ /* Special-case for no merge. */
+ if( i==1 ){
+ /* Trim deletions from the doclist. */
+ dataBufferReset(&merged);
+ docListTrim(DL_DEFAULT,
+ optLeavesReaderData(&readers[0]),
+ optLeavesReaderDataBytes(&readers[0]),
+ -1, DL_DEFAULT, &merged);
+ }else{
+ DLReader dlReaders[MERGE_COUNT];
+ int iReader, nReaders;
+
+ /* Prime the pipeline with the first reader's doclist. After
+ ** one pass index 0 will reference the accumulated doclist.
+ */
+ dlrInit(&dlReaders[0], DL_DEFAULT,
+ optLeavesReaderData(&readers[0]),
+ optLeavesReaderDataBytes(&readers[0]));
+ iReader = 1;
+
+ assert( iReader<i ); /* Must execute the loop at least once. */
+ while( iReader<i ){
+ /* Merge 16 inputs per pass. */
+ for( nReaders=1; iReader<i && nReaders<MERGE_COUNT;
+ iReader++, nReaders++ ){
+ dlrInit(&dlReaders[nReaders], DL_DEFAULT,
+ optLeavesReaderData(&readers[iReader]),
+ optLeavesReaderDataBytes(&readers[iReader]));
+ }
+
+ /* Merge doclists and swap result into accumulator. */
+ dataBufferReset(&merged);
+ docListMerge(&merged, dlReaders, nReaders);
+ tmp = merged;
+ merged = doclist;
+ doclist = tmp;
+
+ while( nReaders-- > 0 ){
+ dlrDestroy(&dlReaders[nReaders]);
+ }
+
+ /* Accumulated doclist to reader 0 for next pass. */
+ dlrInit(&dlReaders[0], DL_DEFAULT, doclist.pData, doclist.nData);
+ }
+
+ /* Destroy reader that was left in the pipeline. */
+ dlrDestroy(&dlReaders[0]);
+
+ /* Trim deletions from the doclist. */
+ dataBufferReset(&merged);
+ docListTrim(DL_DEFAULT, doclist.pData, doclist.nData,
+ -1, DL_DEFAULT, &merged);
+ }
+
+ /* Only pass doclists with hits (skip if all hits deleted). */
+ if( merged.nData>0 ){
+ rc = leafWriterStep(v, pWriter,
+ optLeavesReaderTerm(&readers[0]),
+ optLeavesReaderTermBytes(&readers[0]),
+ merged.pData, merged.nData);
+ if( rc!=SQLITE_OK ) goto err;
+ }
+
+ /* Step merged readers to next term and reorder. */
+ while( i-- > 0 ){
+ rc = optLeavesReaderStep(v, &readers[i]);
+ if( rc!=SQLITE_OK ) goto err;
+
+ optLeavesReaderReorder(&readers[i], nReaders-i);
+ }
+ }
+
+ err:
+ dataBufferDestroy(&doclist);
+ dataBufferDestroy(&merged);
+ return rc;
+}
+
+/* Implement optimize() function for FTS3. optimize(t) merges all
+** segments in the fts index into a single segment. 't' is the magic
+** table-named column.
+*/
+static void optimizeFunc(sqlite3_context *pContext,
+ int argc, sqlite3_value **argv){
+ fulltext_cursor *pCursor;
+ if( argc>1 ){
+ sqlite3_result_error(pContext, "excess arguments to optimize()",-1);
+ }else if( sqlite3_value_type(argv[0])!=SQLITE_BLOB ||
+ sqlite3_value_bytes(argv[0])!=sizeof(pCursor) ){
+ sqlite3_result_error(pContext, "illegal first argument to optimize",-1);
+ }else{
+ fulltext_vtab *v;
+ int i, rc, iMaxLevel;
+ OptLeavesReader *readers;
+ int nReaders;
+ LeafWriter writer;
+ sqlite3_stmt *s;
+
+ memcpy(&pCursor, sqlite3_value_blob(argv[0]), sizeof(pCursor));
+ v = cursor_vtab(pCursor);
+
+ /* Flush any buffered updates before optimizing. */
+ rc = flushPendingTerms(v);
+ if( rc!=SQLITE_OK ) goto err;
+
+ rc = segdir_count(v, &nReaders, &iMaxLevel);
+ if( rc!=SQLITE_OK ) goto err;
+ if( nReaders==0 || nReaders==1 ){
+ sqlite3_result_text(pContext, "Index already optimal", -1,
+ SQLITE_STATIC);
+ return;
+ }
+
+ rc = sql_get_statement(v, SEGDIR_SELECT_ALL_STMT, &s);
+ if( rc!=SQLITE_OK ) goto err;
+
+ readers = sqlite3_malloc(nReaders*sizeof(readers[0]));
+ if( readers==NULL ) goto err;
+
+ /* Note that there will already be a segment at this position
+ ** until we call segdir_delete() on iMaxLevel.
+ */
+ leafWriterInit(iMaxLevel, 0, &writer);
+
+ i = 0;
+ while( (rc = sqlite3_step(s))==SQLITE_ROW ){
+ sqlite_int64 iStart = sqlite3_column_int64(s, 0);
+ sqlite_int64 iEnd = sqlite3_column_int64(s, 1);
+ const char *pRootData = sqlite3_column_blob(s, 2);
+ int nRootData = sqlite3_column_bytes(s, 2);
+
+ assert( i<nReaders );
+ rc = leavesReaderInit(v, -1, iStart, iEnd, pRootData, nRootData,
+ &readers[i].reader);
+ if( rc!=SQLITE_OK ) break;
+
+ readers[i].segment = i;
+ i++;
+ }
+
+ /* If we managed to succesfully read them all, optimize them. */
+ if( rc==SQLITE_DONE ){
+ assert( i==nReaders );
+ rc = optimizeInternal(v, readers, nReaders, &writer);
+ }
+
+ while( i-- > 0 ){
+ leavesReaderDestroy(&readers[i].reader);
+ }
+ sqlite3_free(readers);
+
+ /* If we've successfully gotten to here, delete the old segments
+ ** and flush the interior structure of the new segment.
+ */
+ if( rc==SQLITE_OK ){
+ for( i=0; i<=iMaxLevel; i++ ){
+ rc = segdir_delete(v, i);
+ if( rc!=SQLITE_OK ) break;
+ }
+
+ if( rc==SQLITE_OK ) rc = leafWriterFinalize(v, &writer);
+ }
+
+ leafWriterDestroy(&writer);
+
+ if( rc!=SQLITE_OK ) goto err;
+
+ sqlite3_result_text(pContext, "Index optimized", -1, SQLITE_STATIC);
+ return;
+
+ /* TODO(shess): Error-handling needs to be improved along the
+ ** lines of the dump_ functions.
+ */
+ err:
+ {
+ char buf[512];
+ sqlite3_snprintf(sizeof(buf), buf, "Error in optimize: %s",
+ sqlite3_errmsg(sqlite3_context_db_handle(pContext)));
+ sqlite3_result_error(pContext, buf, -1);
+ }
+ }
+}
+
#ifdef SQLITE_TEST
/* Generate an error of the form "<prefix>: <msg>". If msg is NULL,
** pull the error from the context's db handle.
*/
@@ -88501,8 +92170,11 @@
return 1;
}else if( strcmp(zName,"offsets")==0 ){
*pxFunc = snippetOffsetsFunc;
return 1;
+ }else if( strcmp(zName,"optimize")==0 ){
+ *pxFunc = optimizeFunc;
+ return 1;
#ifdef SQLITE_TEST
/* NOTE(shess): These functions are present only for testing
** purposes. No particular effort is made to optimize their
** execution or how they build their results.
@@ -88634,8 +92306,9 @@
if( SQLITE_OK==rc
&& SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", -1))
+ && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", -1))
#ifdef SQLITE_TEST
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "dump_terms", -1))
&& SQLITE_OK==(rc = sqlite3_overload_function(db, "dump_doclist", -1))
#endif
@@ -90288,9 +93961,9 @@
*************************************************************************
** This file contains code for implementations of the r-tree and r*-tree
** algorithms packaged as an SQLite virtual table module.
**
-** $Id: rtree.c,v 1.6 2008/07/14 15:37:01 danielk1977 Exp $
+** $Id: rtree.c,v 1.10 2008/10/25 17:10:10 danielk1977 Exp $
*/
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_RTREE)
@@ -90333,18 +94006,18 @@
#endif
#ifndef SQLITE_CORE
- #include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#else
- #include "sqlite3.h"
-#endif
-
-
+#endif
+
+
+#ifndef SQLITE_AMALGAMATION
typedef sqlite3_int64 i64;
typedef unsigned char u8;
typedef unsigned int u32;
+#endif
typedef struct Rtree Rtree;
typedef struct RtreeCursor RtreeCursor;
typedef struct RtreeNode RtreeNode;
@@ -90872,9 +94545,9 @@
/* Forward declaration for the function that does the work of
** 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
);
/*
** Rtree virtual table module xCreate method.
@@ -90885,9 +94558,9 @@
int argc, const char *const*argv,
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);
}
/*
** Rtree virtual table module xConnect method.
@@ -90898,9 +94571,9 @@
int argc, const char *const*argv,
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);
}
/*
** Increment the r-tree reference count.
@@ -91388,8 +95061,15 @@
}
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( p->usable && p->iColumn>0 ){
@@ -91441,8 +95121,10 @@
pIdxInfo->needToFreeIdxStr = 1;
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;
}
/*
@@ -91485,8 +95167,27 @@
p1->aCoord[ii].i = MIN(p1->aCoord[ii].i, p2->aCoord[ii].i);
p1->aCoord[ii+1].i = MAX(p1->aCoord[ii+1].i, p2->aCoord[ii+1].i);
}
}
+}
+
+/*
+** 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.
@@ -91653,9 +95354,9 @@
RtreeNode *pParent = p->pParent;
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);
}
@@ -92895,20 +96596,20 @@
** argv[...] -> column names...
*/
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 */
"Wrong number of columns for an rtree table", /* 1 */
@@ -93098,4 +96799,761 @@
#endif
/************** End of rtree.c ***********************************************/
+/************** Begin file icu.c *********************************************/
+/*
+** 2007 May 6
+**
+** 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.
+**
+*************************************************************************
+** $Id: icu.c,v 1.7 2007/12/13 21:54:11 drh Exp $
+**
+** This file implements an integration between the ICU library
+** ("International Components for Unicode", an open-source library
+** for handling unicode data) and SQLite. The integration uses
+** ICU to provide the following to SQLite:
+**
+** * An implementation of the SQL regexp() function (and hence REGEXP
+** operator) using the ICU uregex_XX() APIs.
+**
+** * Implementations of the SQL scalar upper() and lower() functions
+** for case mapping.
+**
+** * Integration of ICU and SQLite collation seqences.
+**
+** * An implementation of the LIKE operator that uses ICU to
+** provide case-independent matching.
+*/
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
+
+/* Include ICU headers */
+#include <unicode/utypes.h>
+#include <unicode/uregex.h>
+#include <unicode/ustring.h>
+#include <unicode/ucol.h>
+
+
+#ifndef SQLITE_CORE
+ SQLITE_EXTENSION_INIT1
+#else
+#endif
+
+/*
+** Maximum length (in bytes) of the pattern in a LIKE or GLOB
+** operator.
+*/
+#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
+# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
+#endif
+
+/*
+** Version of sqlite3_free() that is always a function, never a macro.
+*/
+static void xFree(void *p){
+ sqlite3_free(p);
+}
+
+/*
+** Compare two UTF-8 strings for equality where the first string is
+** a "LIKE" expression. Return true (1) if they are the same and
+** false (0) if they are different.
+*/
+static int icuLikeCompare(
+ const uint8_t *zPattern, /* LIKE pattern */
+ const uint8_t *zString, /* The UTF-8 string to compare against */
+ const UChar32 uEsc /* The escape character */
+){
+ static const int MATCH_ONE = (UChar32)'_';
+ static const int MATCH_ALL = (UChar32)'%';
+
+ int iPattern = 0; /* Current byte index in zPattern */
+ int iString = 0; /* Current byte index in zString */
+
+ int prevEscape = 0; /* True if the previous character was uEsc */
+
+ while( zPattern[iPattern]!=0 ){
+
+ /* Read (and consume) the next character from the input pattern. */
+ UChar32 uPattern;
+ U8_NEXT_UNSAFE(zPattern, iPattern, uPattern);
+ assert(uPattern!=0);
+
+ /* There are now 4 possibilities:
+ **
+ ** 1. uPattern is an unescaped match-all character "%",
+ ** 2. uPattern is an unescaped match-one character "_",
+ ** 3. uPattern is an unescaped escape character, or
+ ** 4. uPattern is to be handled as an ordinary character
+ */
+ if( !prevEscape && uPattern==MATCH_ALL ){
+ /* Case 1. */
+ uint8_t c;
+
+ /* Skip any MATCH_ALL or MATCH_ONE characters that follow a
+ ** MATCH_ALL. For each MATCH_ONE, skip one character in the
+ ** test string.
+ */
+ while( (c=zPattern[iPattern]) == MATCH_ALL || c == MATCH_ONE ){
+ if( c==MATCH_ONE ){
+ if( zString[iString]==0 ) return 0;
+ U8_FWD_1_UNSAFE(zString, iString);
+ }
+ iPattern++;
+ }
+
+ if( zPattern[iPattern]==0 ) return 1;
+
+ while( zString[iString] ){
+ if( icuLikeCompare(&zPattern[iPattern], &zString[iString], uEsc) ){
+ return 1;
+ }
+ U8_FWD_1_UNSAFE(zString, iString);
+ }
+ return 0;
+
+ }else if( !prevEscape && uPattern==MATCH_ONE ){
+ /* Case 2. */
+ if( zString[iString]==0 ) return 0;
+ U8_FWD_1_UNSAFE(zString, iString);
+
+ }else if( !prevEscape && uPattern==uEsc){
+ /* Case 3. */
+ prevEscape = 1;
+
+ }else{
+ /* Case 4. */
+ UChar32 uString;
+ U8_NEXT_UNSAFE(zString, iString, uString);
+ uString = u_foldCase(uString, U_FOLD_CASE_DEFAULT);
+ uPattern = u_foldCase(uPattern, U_FOLD_CASE_DEFAULT);
+ if( uString!=uPattern ){
+ return 0;
+ }
+ prevEscape = 0;
+ }
+ }
+
+ return zString[iString]==0;
+}
+
+/*
+** Implementation of the like() SQL function. This function implements
+** the build-in LIKE operator. The first argument to the function is the
+** pattern and the second argument is the string. So, the SQL statements:
+**
+** A LIKE B
+**
+** is implemented as like(B, A). If there is an escape character E,
+**
+** A LIKE B ESCAPE E
+**
+** is mapped to like(B, A, E).
+*/
+static void icuLikeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *zA = sqlite3_value_text(argv[0]);
+ const unsigned char *zB = sqlite3_value_text(argv[1]);
+ UChar32 uEsc = 0;
+
+ /* Limit the length of the LIKE or GLOB pattern to avoid problems
+ ** of deep recursion and N*N behavior in patternCompare().
+ */
+ if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){
+ sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
+ return;
+ }
+
+
+ if( argc==3 ){
+ /* The escape character string must consist of a single UTF-8 character.
+ ** Otherwise, return an error.
+ */
+ int nE= sqlite3_value_bytes(argv[2]);
+ const unsigned char *zE = sqlite3_value_text(argv[2]);
+ int i = 0;
+ if( zE==0 ) return;
+ U8_NEXT(zE, i, nE, uEsc);
+ if( i!=nE){
+ sqlite3_result_error(context,
+ "ESCAPE expression must be a single character", -1);
+ return;
+ }
+ }
+
+ if( zA && zB ){
+ sqlite3_result_int(context, icuLikeCompare(zA, zB, uEsc));
+ }
+}
+
+/*
+** This function is called when an ICU function called from within
+** the implementation of an SQL scalar function returns an error.
+**
+** The scalar function context passed as the first argument is
+** loaded with an error message based on the following two args.
+*/
+static void icuFunctionError(
+ sqlite3_context *pCtx, /* SQLite scalar function context */
+ const char *zName, /* Name of ICU function that failed */
+ UErrorCode e /* Error code returned by ICU function */
+){
+ char zBuf[128];
+ sqlite3_snprintf(128, zBuf, "ICU error: %s(): %s", zName, u_errorName(e));
+ zBuf[127] = '\0';
+ sqlite3_result_error(pCtx, zBuf, -1);
+}
+
+/*
+** Function to delete compiled regexp objects. Registered as
+** a destructor function with sqlite3_set_auxdata().
+*/
+static void icuRegexpDelete(void *p){
+ URegularExpression *pExpr = (URegularExpression *)p;
+ uregex_close(pExpr);
+}
+
+/*
+** Implementation of SQLite REGEXP operator. This scalar function takes
+** two arguments. The first is a regular expression pattern to compile
+** the second is a string to match against that pattern. If either
+** argument is an SQL NULL, then NULL Is returned. Otherwise, the result
+** is 1 if the string matches the pattern, or 0 otherwise.
+**
+** SQLite maps the regexp() function to the regexp() operator such
+** that the following two are equivalent:
+**
+** zString REGEXP zPattern
+** regexp(zPattern, zString)
+**
+** Uses the following ICU regexp APIs:
+**
+** uregex_open()
+** uregex_matches()
+** uregex_close()
+*/
+static void icuRegexpFunc(sqlite3_context *p, int nArg, sqlite3_value **apArg){
+ UErrorCode status = U_ZERO_ERROR;
+ URegularExpression *pExpr;
+ UBool res;
+ const UChar *zString = sqlite3_value_text16(apArg[1]);
+
+ /* If the left hand side of the regexp operator is NULL,
+ ** then the result is also NULL.
+ */
+ if( !zString ){
+ return;
+ }
+
+ pExpr = sqlite3_get_auxdata(p, 0);
+ if( !pExpr ){
+ const UChar *zPattern = sqlite3_value_text16(apArg[0]);
+ if( !zPattern ){
+ return;
+ }
+ pExpr = uregex_open(zPattern, -1, 0, 0, &status);
+
+ if( U_SUCCESS(status) ){
+ sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete);
+ }else{
+ assert(!pExpr);
+ icuFunctionError(p, "uregex_open", status);
+ return;
+ }
+ }
+
+ /* Configure the text that the regular expression operates on. */
+ uregex_setText(pExpr, zString, -1, &status);
+ if( !U_SUCCESS(status) ){
+ icuFunctionError(p, "uregex_setText", status);
+ return;
+ }
+
+ /* Attempt the match */
+ res = uregex_matches(pExpr, 0, &status);
+ if( !U_SUCCESS(status) ){
+ icuFunctionError(p, "uregex_matches", status);
+ return;
+ }
+
+ /* Set the text that the regular expression operates on to a NULL
+ ** pointer. This is not really necessary, but it is tidier than
+ ** leaving the regular expression object configured with an invalid
+ ** pointer after this function returns.
+ */
+ uregex_setText(pExpr, 0, 0, &status);
+
+ /* Return 1 or 0. */
+ sqlite3_result_int(p, res ? 1 : 0);
+}
+
+/*
+** Implementations of scalar functions for case mapping - upper() and
+** lower(). Function upper() converts its input to upper-case (ABC).
+** Function lower() converts to lower-case (abc).
+**
+** ICU provides two types of case mapping, "general" case mapping and
+** "language specific". Refer to ICU documentation for the differences
+** between the two.
+**
+** To utilise "general" case mapping, the upper() or lower() scalar
+** functions are invoked with one argument:
+**
+** upper('ABC') -> 'abc'
+** lower('abc') -> 'ABC'
+**
+** To access ICU "language specific" case mapping, upper() or lower()
+** should be invoked with two arguments. The second argument is the name
+** of the locale to use. Passing an empty string ("") or SQL NULL value
+** as the second argument is the same as invoking the 1 argument version
+** of upper() or lower().
+**
+** lower('I', 'en_us') -> 'i'
+** lower('I', 'tr_tr') -> 'ı' (small dotless i)
+**
+** http://www.icu-project.org/userguide/posix.html#case_mappings
+*/
+static void icuCaseFunc16(sqlite3_context *p, int nArg, sqlite3_value **apArg){
+ const UChar *zInput;
+ UChar *zOutput;
+ int nInput;
+ int nOutput;
+
+ UErrorCode status = U_ZERO_ERROR;
+ const char *zLocale = 0;
+
+ assert(nArg==1 || nArg==2);
+ if( nArg==2 ){
+ zLocale = (const char *)sqlite3_value_text(apArg[1]);
+ }
+
+ zInput = sqlite3_value_text16(apArg[0]);
+ if( !zInput ){
+ return;
+ }
+ nInput = sqlite3_value_bytes16(apArg[0]);
+
+ nOutput = nInput * 2 + 2;
+ zOutput = sqlite3_malloc(nOutput);
+ if( !zOutput ){
+ return;
+ }
+
+ if( sqlite3_user_data(p) ){
+ u_strToUpper(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status);
+ }else{
+ u_strToLower(zOutput, nOutput/2, zInput, nInput/2, zLocale, &status);
+ }
+
+ if( !U_SUCCESS(status) ){
+ icuFunctionError(p, "u_strToLower()/u_strToUpper", status);
+ return;
+ }
+
+ sqlite3_result_text16(p, zOutput, -1, xFree);
+}
+
+/*
+** Collation sequence destructor function. The pCtx argument points to
+** a UCollator structure previously allocated using ucol_open().
+*/
+static void icuCollationDel(void *pCtx){
+ UCollator *p = (UCollator *)pCtx;
+ ucol_close(p);
+}
+
+/*
+** Collation sequence comparison function. The pCtx argument points to
+** a UCollator structure previously allocated using ucol_open().
+*/
+static int icuCollationColl(
+ void *pCtx,
+ int nLeft,
+ const void *zLeft,
+ int nRight,
+ const void *zRight
+){
+ UCollationResult res;
+ UCollator *p = (UCollator *)pCtx;
+ res = ucol_strcoll(p, (UChar *)zLeft, nLeft/2, (UChar *)zRight, nRight/2);
+ switch( res ){
+ case UCOL_LESS: return -1;
+ case UCOL_GREATER: return +1;
+ case UCOL_EQUAL: return 0;
+ }
+ assert(!"Unexpected return value from ucol_strcoll()");
+ return 0;
+}
+
+/*
+** Implementation of the scalar function icu_load_collation().
+**
+** This scalar function is used to add ICU collation based collation
+** types to an SQLite database connection. It is intended to be called
+** as follows:
+**
+** SELECT icu_load_collation(<locale>, <collation-name>);
+**
+** Where <locale> is a string containing an ICU locale identifier (i.e.
+** "en_AU", "tr_TR" etc.) and <collation-name> is the name of the
+** collation sequence to create.
+*/
+static void icuLoadCollation(
+ sqlite3_context *p,
+ int nArg,
+ sqlite3_value **apArg
+){
+ sqlite3 *db = (sqlite3 *)sqlite3_user_data(p);
+ UErrorCode status = U_ZERO_ERROR;
+ const char *zLocale; /* Locale identifier - (eg. "jp_JP") */
+ const char *zName; /* SQL Collation sequence name (eg. "japanese") */
+ UCollator *pUCollator; /* ICU library collation object */
+ int rc; /* Return code from sqlite3_create_collation_x() */
+
+ assert(nArg==2);
+ zLocale = (const char *)sqlite3_value_text(apArg[0]);
+ zName = (const char *)sqlite3_value_text(apArg[1]);
+
+ if( !zLocale || !zName ){
+ return;
+ }
+
+ pUCollator = ucol_open(zLocale, &status);
+ if( !U_SUCCESS(status) ){
+ icuFunctionError(p, "ucol_open", status);
+ return;
+ }
+ assert(p);
+
+ rc = sqlite3_create_collation_v2(db, zName, SQLITE_UTF16, (void *)pUCollator,
+ icuCollationColl, icuCollationDel
+ );
+ if( rc!=SQLITE_OK ){
+ ucol_close(pUCollator);
+ sqlite3_result_error(p, "Error registering collation function", -1);
+ }
+}
+
+/*
+** Register the ICU extension functions with database db.
+*/
+SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
+ struct IcuScalar {
+ const char *zName; /* Function name */
+ int nArg; /* Number of arguments */
+ int enc; /* Optimal text encoding */
+ void *pContext; /* sqlite3_user_data() context */
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
+ } scalars[] = {
+ {"regexp",-1, SQLITE_ANY, 0, icuRegexpFunc},
+
+ {"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16},
+ {"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16},
+ {"upper", 1, SQLITE_UTF16, (void*)1, icuCaseFunc16},
+ {"upper", 2, SQLITE_UTF16, (void*)1, icuCaseFunc16},
+
+ {"lower", 1, SQLITE_UTF8, 0, icuCaseFunc16},
+ {"lower", 2, SQLITE_UTF8, 0, icuCaseFunc16},
+ {"upper", 1, SQLITE_UTF8, (void*)1, icuCaseFunc16},
+ {"upper", 2, SQLITE_UTF8, (void*)1, icuCaseFunc16},
+
+ {"like", 2, SQLITE_UTF8, 0, icuLikeFunc},
+ {"like", 3, SQLITE_UTF8, 0, icuLikeFunc},
+
+ {"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation},
+ };
+
+ int rc = SQLITE_OK;
+ int i;
+
+ for(i=0; rc==SQLITE_OK && i<(sizeof(scalars)/sizeof(struct IcuScalar)); i++){
+ struct IcuScalar *p = &scalars[i];
+ rc = sqlite3_create_function(
+ db, p->zName, p->nArg, p->enc, p->pContext, p->xFunc, 0, 0
+ );
+ }
+
+ return rc;
+}
+
+#if !SQLITE_CORE
+SQLITE_API int sqlite3_extension_init(
+ sqlite3 *db,
+ char **pzErrMsg,
+ const sqlite3_api_routines *pApi
+){
+ SQLITE_EXTENSION_INIT2(pApi)
+ return sqlite3IcuInit(db);
+}
+#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: fts3_icu.c,v 1.3 2008/09/01 18:34:20 danielk1977 Exp $
+*/
+
+#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3)
+#ifdef SQLITE_ENABLE_ICU
+
+
+#include <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 ********************************************/