summaryrefslogtreecommitdiff
path: root/ext/sqlite3/libsqlite/sqlite3.c
diff options
context:
space:
mode:
authorScott MacVicar <scottmac@php.net>2008-09-15 01:17:48 +0000
committerScott MacVicar <scottmac@php.net>2008-09-15 01:17:48 +0000
commitd95bc4293d613c640f27cadc8f91b2efe5840105 (patch)
treeeefe5f8e0407f5846dd2ca89abc4ad1277e47b8c /ext/sqlite3/libsqlite/sqlite3.c
parentd33c7bbd968239ac52156f5a3dccac1ff9f384b0 (diff)
downloadphp-git-d95bc4293d613c640f27cadc8f91b2efe5840105.tar.gz
Sync libsqlite to 3.6.2 with some VC6 patches
Diffstat (limited to 'ext/sqlite3/libsqlite/sqlite3.c')
-rw-r--r--ext/sqlite3/libsqlite/sqlite3.c10599
1 files changed, 5945 insertions, 4654 deletions
diff --git a/ext/sqlite3/libsqlite/sqlite3.c b/ext/sqlite3/libsqlite/sqlite3.c
index 6389f6177b..af42232200 100644
--- a/ext/sqlite3/libsqlite/sqlite3.c
+++ b/ext/sqlite3/libsqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.1. By combining all the individual C code files into this
+** version 3.6.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a one translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -11,13 +11,13 @@
** programs, you need this file and the "sqlite3.h" header file that defines
** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy in the first
-** 6279 lines past this header comment.) Additional code files may be
+** 6312 lines past this header comment.) Additional code files may be
** needed if you want a wrapper to interface SQLite with your choice of
** programming language. The code for the "sqlite3" command-line shell
** is also in a separate file. This file contains only code for the core
** SQLite library.
**
-** This amalgamation was generated on 2008-08-05 21:36:42 UTC.
+** This amalgamation was generated on 2008-08-30 16:23:32 UTC.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
@@ -387,12 +387,12 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
** the default.
*/
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+ defined(SQLITE_POW2_MEMORY_SIZE)>1
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+defined(SQLITE_POW2_MEMORY_SIZE)>1
# error "At most one of the following compile-time configuration options\
is allows: SQLITE_SYSTEM_MALLOC, SQLITE_MEMDEBUG, SQLITE_MEMORY_SIZE,\
SQLITE_MMAP_HEAP_SIZE, SQLITE_POW2_MEMORY_SIZE"
#endif
-#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+ defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+ defined(SQLITE_POW2_MEMORY_SIZE)==0
+#if defined(SQLITE_SYSTEM_MALLOC)+defined(SQLITE_MEMDEBUG)+defined(SQLITE_MEMORY_SIZE)+defined(SQLITE_MMAP_HEAP_SIZE)+defined(SQLITE_POW2_MEMORY_SIZE)==0
# define SQLITE_SYSTEM_MALLOC 1
#endif
@@ -421,6 +421,9 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
# define _XOPEN_SOURCE 500 /* Needed to enable pthread recursive mutexes */
#endif
+/*
+** The TCL headers are only needed when compiling the TCL bindings.
+*/
#if defined(SQLITE_TCL) || defined(TCLSH)
# include <tcl.h>
#endif
@@ -492,6 +495,31 @@ extern "C" {
#endif
/*
+** Add the ability to mark interfaces as deprecated.
+*/
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+ /* GCC added the deprecated attribute in version 3.1 */
+ #define SQLITE_DEPRECATED __attribute__ ((deprecated))
+#elif defined(_MSC_VER) && (_MSC_VER>1200)
+ #define SQLITE_DEPRECATED __declspec(deprecated)
+#else
+ #define SQLITE_DEPRECATED
+#endif
+
+/*
+** Add the ability to mark interfaces as experimental.
+*/
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+ /* I can confirm that it does not work on version 4.1.0... */
+ /* First appears in GCC docs for version 4.3.0 */
+ #define SQLITE_EXPERIMENTAL __attribute__ ((warning ("is experimental")))
+#elif defined(_MSC_VER)&& (_MSC_VER>1200)
+ #define SQLITE_EXPERIMENTAL __declspec(deprecated("was declared experimental"))
+#else
+ #define SQLITE_EXPERIMENTAL
+#endif
+
+/*
** Ensure these symbols were not defined by some previous header file.
*/
#ifdef SQLITE_VERSION
@@ -531,8 +559,8 @@ extern "C" {
** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z
** are the major version, minor version, and release number.
*/
-#define SQLITE_VERSION "3.6.1"
-#define SQLITE_VERSION_NUMBER 3006001
+#define SQLITE_VERSION "3.6.2"
+#define SQLITE_VERSION_NUMBER 3006002
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
@@ -931,6 +959,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8))
#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8))
#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
+#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
/*
** CAPI3REF: Flags For File Open Operations {H10230} <H11120> <H12700>
@@ -953,6 +982,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_OPEN_SUBJOURNAL 0x00002000
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000
#define SQLITE_OPEN_NOMUTEX 0x00008000
+#define SQLITE_OPEN_FULLMUTEX 0x00010000
/*
** CAPI3REF: Device Characteristics {H10240} <H11120>
@@ -1406,7 +1436,7 @@ SQLITE_API int sqlite3_os_end(void);
** 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, ...);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_config(int, ...);
/*
** CAPI3REF: Configure database connections {H10180} <S20000>
@@ -1427,7 +1457,7 @@ SQLITE_API int sqlite3_config(int, ...);
** New verbs are likely to be added in future releases of SQLite.
** Additional arguments depend on the verb.
*/
-SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Memory Allocation Routines {H10155} <S20120>
@@ -2516,6 +2546,11 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** previous call. Disable the authorizer by installing a NULL callback.
** The authorizer is disabled by default.
**
+** 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()].
@@ -2526,11 +2561,11 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** authorizer callback with database connection D.
**
** {H12502} The authorizer callback is invoked as SQL statements are
-** being compiled.
+** 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.
**
@@ -2538,7 +2573,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** described is processed normally.
**
** {H12505} When the authorizer callback returns [SQLITE_DENY], 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 error message
** explaining that access is denied.
@@ -2612,21 +2647,21 @@ SQLITE_API int sqlite3_set_authorizer(
** INVARIANTS:
**
** {H12551} The second parameter to an
-** [sqlite3_set_authorizer | authorizer callback] is always an integer
+** [sqlite3_set_authorizer | authorizer callback] shall be an integer
** [SQLITE_COPY | authorizer code] that specifies what action
** is being authorized.
**
** {H12552} The 3rd and 4th parameters to the
** [sqlite3_set_authorizer | authorization callback]
-** 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.
**
** {H12553} The 5th parameter to the
-** [sqlite3_set_authorizer | authorizer callback] is the name
+** [sqlite3_set_authorizer | authorizer callback] shall be the name
** of the database (example: "main", "temp", etc.) if applicable.
**
** {H12554} The 6th parameter to the
-** [sqlite3_set_authorizer | authorizer callback] is the name
+** [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.
@@ -2686,16 +2721,17 @@ SQLITE_API int sqlite3_set_authorizer(
**
** INVARIANTS:
**
-** {H12281} The callback function registered by [sqlite3_trace()] is
+** {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.
**
-** {H12282} Each call to [sqlite3_trace()] overrides the previously
+** {H12282} Each call to [sqlite3_trace()] shall override the previously
** registered trace callback.
**
-** {H12283} A NULL trace callback disables tracing.
+** {H12283} A NULL trace callback shall disable tracing.
**
-** {H12284} The first argument to the trace callback is a copy of
+** {H12284} The first argument to the trace callback shall be a copy of
** the pointer which was the 3rd argument to [sqlite3_trace()].
**
** {H12285} The second argument to the trace callback is a
@@ -2719,8 +2755,8 @@ SQLITE_API int sqlite3_set_authorizer(
** of the number of nanoseconds of wall-clock time required to
** run the SQL statement from start to finish.
*/
-SQLITE_API 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*);
/*
@@ -2889,11 +2925,11 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** reading and writing if possible, or for reading only if the
** file is write protected by the operating system.
**
-** {H12713} If the G parameter to [sqlite3_open(v2(F,D,G,V)] omits the
+** {H12713} If the G parameter to [sqlite3_open_v2(F,D,G,V)] omits the
** bit value [SQLITE_OPEN_CREATE] and the database does not
** previously exist, an error is returned.
**
-** {H12714} If the G parameter to [sqlite3_open(v2(F,D,G,V)] contains the
+** {H12714} If the G parameter to [sqlite3_open_v2(F,D,G,V)] contains the
** bit value [SQLITE_OPEN_CREATE] and the database does not
** previously exist, then an attempt is made to create and
** initialize the database.
@@ -4387,12 +4423,12 @@ SQLITE_API int sqlite3_create_function16(
** 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);
+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);
/*
** CAPI3REF: Obtaining SQL Function Parameter Values {H15100} <S20200>
@@ -5817,7 +5853,7 @@ struct sqlite3_index_info {
** 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 */
@@ -5832,7 +5868,7 @@ SQLITE_API int sqlite3_create_module(
** except that it allows a destructor function to be specified. It is
** even more experimental than the rest of the virtual tables API.
*/
-SQLITE_API 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 */
@@ -5904,7 +5940,7 @@ struct sqlite3_vtab_cursor {
** 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);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
/*
** CAPI3REF: Overload A Function For A Virtual Table {H18300} <S20400>
@@ -5925,7 +5961,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
** 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
@@ -6582,7 +6618,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
**
** See also: [sqlite3_db_status()]
*/
-SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
/*
** CAPI3REF: Database Connection Status {H17201} <S60200>
@@ -6602,7 +6638,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
**
** See also: [sqlite3_status()].
*/
-SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters {H17250} <H17200>
@@ -6983,12 +7019,11 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
#define TK_ILLEGAL 144
#define TK_SPACE 145
#define TK_UNCLOSED_STRING 146
-#define TK_COMMENT 147
-#define TK_FUNCTION 148
-#define TK_COLUMN 149
-#define TK_AGG_FUNCTION 150
-#define TK_AGG_COLUMN 151
-#define TK_CONST_FUNC 152
+#define TK_FUNCTION 147
+#define TK_COLUMN 148
+#define TK_AGG_FUNCTION 149
+#define TK_AGG_COLUMN 150
+#define TK_CONST_FUNC 151
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -7129,7 +7164,7 @@ typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
-typedef 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,
@@ -7218,6 +7253,7 @@ 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;
@@ -7236,6 +7272,8 @@ 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;
@@ -7370,8 +7408,6 @@ 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 */
@@ -7385,11 +7421,17 @@ SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeMoveto(
BtCursor*,
const void *pKey,
- struct UnpackedRecord *pUnKey,
i64 nKey,
int bias,
int *pRes
);
+SQLITE_PRIVATE int sqlite3BtreeMovetoUnpacked(
+ BtCursor*,
+ UnpackedRecord *pUnKey,
+ i64 intKey,
+ int bias,
+ int *pRes
+);
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*);
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
@@ -7505,7 +7547,6 @@ typedef struct Vdbe Vdbe;
*/
typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
-typedef struct UnpackedRecord UnpackedRecord;
/*
** A single instruction of the virtual machine has an opcode
@@ -7840,7 +7881,8 @@ SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int);
#endif
-SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,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*);
@@ -7933,9 +7975,8 @@ typedef struct PgHdr DbPage;
** 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 int sqlite3PagerOpen(sqlite3_vfs *, Pager **ppPager, const char*, void(*)(DbPage*), 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 int sqlite3PagerSetPagesize(Pager*, u16*);
SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
@@ -7959,7 +8000,7 @@ 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*);
@@ -7976,10 +8017,7 @@ 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
+SQLITE_PRIVATE void sqlite3PagerAlwaysRollback(Pager *pPager);
#ifdef SQLITE_HAS_CODEC
SQLITE_PRIVATE void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
@@ -8008,6 +8046,177 @@ void enable_simulated_io_errors(void);
/************** End of pager.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
+/************** Include pcache.h in the middle of sqliteInt.h ****************/
+/************** Begin file pcache.h ******************************************/
+/*
+** 2008 August 05
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This header file defines the interface that the sqlite page cache
+** subsystem.
+**
+** @(#) $Id$
+*/
+
+#ifndef _PCACHE_H_
+
+typedef struct PgHdr PgHdr;
+typedef struct PCache PCache;
+
+/*
+** Every page in the cache is controlled by an instance of the following
+** structure.
+*/
+struct PgHdr {
+ void *pData; /* Content of this page */
+ void *pExtra; /* Extra content */
+ PgHdr *pDirty; /* Transient list of dirty pages */
+ Pgno pgno; /* Page number for this page */
+ Pager *pPager; /* The pager this page is part of */
+#ifdef SQLITE_CHECK_PAGES
+ u32 pageHash; /* Hash of page content */
+#endif
+ u16 flags; /* PGHDR flags defined below */
+ /**********************************************************************
+ ** Elements above are public. All that follows is private to pcache.c
+ ** and should not be accessed by other modules.
+ */
+ i16 nRef; /* Number of users of this page */
+ PCache *pCache; /* Cache that owns this page */
+ void *apSave[2]; /* Journal entries for in-memory databases */
+ /**********************************************************************
+ ** Elements above are accessible at any time by the owner of the cache
+ ** without the need for a mutex. The elements that follow can only be
+ ** accessed while holding the SQLITE_MUTEX_STATIC_LRU mutex.
+ */
+ PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */
+ PgHdr *pNext, *pPrev; /* List of clean or dirty pages */
+ PgHdr *pNextLru, *pPrevLru; /* Part of global LRU list */
+};
+
+/* Bit values for PgHdr.flags */
+#define PGHDR_IN_JOURNAL 0x001 /* Page is in rollback journal */
+#define PGHDR_IN_STMTJRNL 0x002 /* Page is in the statement journal */
+#define PGHDR_DIRTY 0x004 /* Page has changed */
+#define PGHDR_NEED_SYNC 0x008 /* Peed to fsync this page */
+#define PGHDR_NEED_READ 0x020 /* Content is unread */
+#define PGHDR_IS_INIT 0x040 /* pData is initialized */
+#define PGHDR_REUSE_UNLIKELY 0x080 /* Hint: Reuse is unlikely */
+#define PGHDR_DONT_WRITE 0x100 /* Do not write content to disk */
+
+/* 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 */
+ void (*xDestroy)(PgHdr *), /* Called to destroy a page */
+ int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */
+ void *pStress, /* Argument to xStress */
+ PCache *pToInit /* Preallocated space for the PCache */
+);
+
+/* 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);
+
+/* Routines used to implement transactions on memory-only databases. */
+SQLITE_PRIVATE int sqlite3PcachePreserve(PgHdr*, int); /* Preserve current page content */
+SQLITE_PRIVATE void sqlite3PcacheCommit(PCache*, int); /* Drop preserved copy */
+SQLITE_PRIVATE void sqlite3PcacheRollback(PCache*, int); /* Rollback to preserved copy */
+
+/* Get a list of all dirty pages in the cache, sorted by page number */
+SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*);
+
+/* Reset and close the cache object */
+SQLITE_PRIVATE void sqlite3PcacheClose(PCache*);
+
+/* Set flags on all pages in the page cache */
+SQLITE_PRIVATE void sqlite3PcacheSetFlags(PCache*, int andMask, int orMask);
+
+/* Assert flags settings on all pages. Debugging only */
+SQLITE_PRIVATE void sqlite3PcacheAssertFlags(PCache*, int trueMask, int falseMask);
+
+/* 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*);
+
+/* Return the total number of pages stored in the cache */
+SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*);
+
+/* Iterate through all pages currently stored in the cache. This interface
+** is only available if SQLITE_CHECK_PAGES is defined when the library is
+** built.
+*/
+SQLITE_PRIVATE void sqlite3PcacheIterate(PCache *pCache, void (*xIter)(PgHdr *));
+
+/* 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);
+
+/* Try to return memory used by the pcache module to the main memory heap */
+SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int);
+
+SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*);
+
+#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 **********************************************/
@@ -8473,7 +8682,7 @@ struct Lookaside {
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
int nOut; /* Number of buffers currently checked out */
int mxOut; /* Highwater mark for nOut */
- LookasideSlot *pFree; /* List if available buffers */
+ LookasideSlot *pFree; /* List of available buffers */
void *pStart; /* First byte of available memory space */
void *pEnd; /* First byte past end of available space */
};
@@ -8482,6 +8691,16 @@ struct LookasideSlot {
};
/*
+** A hash table for function definitions.
+**
+** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
+** Collisions are on the FuncDef.pHash chain.
+*/
+struct FuncDefHash {
+ FuncDef *a[23]; /* Hash table for functions */
+};
+
+/*
** Each database is an instance of the following structure.
**
** The sqlite.lastRowid records the last insert rowid generated by an
@@ -8577,7 +8796,7 @@ struct sqlite3 {
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 */
@@ -8642,7 +8861,7 @@ struct sqlite3 {
** points to a linked list of these structures.
*/
struct FuncDef {
- i16 nArg; /* Number of arguments. -1 means unlimited */
+ i8 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_* */
@@ -8651,10 +8870,51 @@ struct FuncDef {
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 */
+
+/*
+** 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, 0, SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName}
+#define LIKEFUNC(zName, nArg, arg, flags) \
+ {nArg, SQLITE_UTF8, 0, flags, (void *)arg, 0, likeFunc, 0, 0, #zName}
+#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
+ {nArg, SQLITE_UTF8, nc, 0, SQLITE_INT_TO_PTR(arg), 0, 0, xStep,xFinal, #zName}
+
+
+/*
** Each SQLite module (virtual table definition) is defined by an
** instance of the following structure, stored in the sqlite3.aModule
** hash table.
@@ -8667,13 +8927,6 @@ struct Module {
};
/*
-** Possible values for FuncDef.flags
-*/
-#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
-#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
-#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
-
-/*
** information about each column of an SQL table is held in an instance
** of this structure.
*/
@@ -8721,7 +8974,7 @@ struct CollSeq {
};
/*
-** 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 */
@@ -8739,7 +8992,7 @@ struct CollSeq {
**
** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and
** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve
-** the speed a little by 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
@@ -8785,14 +9038,14 @@ struct CollSeq {
** that the datatype of the PRIMARY KEY must be INTEGER for this field to
** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
-** is generated for each row of the table. 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
@@ -8800,47 +9053,54 @@ struct CollSeq {
** of a SELECT statement.
*/
struct Table {
- sqlite3 *db; /* Associated database connection. Might be NULL. */
- char *zName; /* Name of the table */
- int nCol; /* Number of columns in this table */
- Column *aCol; /* Information about each column */
- int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */
- Index *pIndex; /* List of SQL indexes on this table. */
- int tnum; /* Root BTree node for this table (see note above) */
- Select *pSelect; /* NULL for tables. Points to definition if a view. */
- int nRef; /* Number of pointers to this Table */
- Trigger *pTrigger; /* List of SQL triggers on this table */
- FKey *pFKey; /* Linked list of all foreign keys in this table */
- char *zColAff; /* String defining the affinity of each column */
+ 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 */
+ int addColOffset; /* Offset in CREATE TABLE stmt 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 */
+ Module *pMod; /* Pointer to the implementation of the module */
+ sqlite3_vtab *pVtab; /* Pointer to the module instance */
+ int nModuleArg; /* Number of arguments to the module */
+ char **azModuleArg; /* Text of all module args. [0] is module name */
+#endif
+ Schema *pSchema; /* Schema that contains this table */
};
/*
+** Allowed values for Tabe.tabFlags.
+*/
+#define TF_Readonly 0x01 /* Read-only system table */
+#define TF_Ephemeral 0x02 /* An emphermal table */
+#define TF_HasPrimaryKey 0x04 /* Table has a primary key */
+#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
+#define TF_Virtual 0x10 /* Is a virtual table */
+#define TF_NeedMetadata 0x20 /* aCol[].zType and aCol[].pColl missing */
+
+
+
+/*
** Test to see whether or not a table is a virtual table. This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
-# define IsVirtual(X) ((X)->isVirtual)
+# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
# define IsHiddenColumn(X) ((X)->isHidden)
#else
# define IsVirtual(X) 0
@@ -8932,22 +9192,46 @@ struct FKey {
** An instance of the following structure is passed as the first
** argument to sqlite3VdbeKeyCompare and is used to control the
** comparison of the two index keys.
-**
-** If the KeyInfo.incrKey value is true and the comparison would
-** otherwise be equal, then return a result as if the second key
-** were larger.
*/
struct KeyInfo {
sqlite3 *db; /* The database connection */
u8 enc; /* Text encoding - one of the TEXT_Utf* values */
- 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.
**
@@ -9110,7 +9394,7 @@ struct Expr {
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
Select *pSelect; /* When the expression is a sub-select. Also the
** right side of "<expr> IN (<select>)" */
- Table *pTab; /* Table for 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
@@ -9156,8 +9440,9 @@ struct ExprList {
Expr *pExpr; /* The list of expressions */
char *zName; /* Token associated with this expression */
u8 sortOrder; /* 1 for DESC or 0 for ASC */
- u8 isAgg; /* True if this is an aggregate like count(*) */
u8 done; /* A flag to indicate when processing is finished */
+ u16 iCol; /* For ORDER BY, column number in result set */
+ u16 iAlias; /* Index into Parse.aAlias[] for zName */
} *a; /* One entry for each expression */
};
@@ -9371,12 +9656,8 @@ struct NameContext {
struct Select {
ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
- u8 isDistinct; /* True if the DISTINCT keyword is present */
- u8 isResolved; /* True once sqlite3SelectResolve() has run. */
- u8 isAgg; /* True if this is an aggregate query */
- u8 usesEphm; /* True if uses an OpenEphemeral opcode */
- u8 disallowOrderBy; /* Do not allow an ORDER BY to be attached if TRUE */
char affinity; /* MakeRecord with this affinity for SRT_Set */
+ u16 selFlags; /* Various SF_* values */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
@@ -9392,7 +9673,20 @@ struct 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 */
@@ -9402,7 +9696,7 @@ struct Select {
/* 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 */
@@ -9485,6 +9779,8 @@ struct Parse {
int nVarExpr; /* Number of used slots in apVarExpr[] */
int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */
Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */
+ int nAlias; /* Number of aliased result set columns */
+ int *aAlias; /* Register used to hold aliased result */
u8 explain; /* True if the EXPLAIN flag is found on the query */
Token sErrToken; /* The token at which the error occurred */
Token sNameToken; /* Token with unqualified schema object name */
@@ -9726,11 +10022,40 @@ struct Sqlite3Config {
int isInit; /* True after initialization has finished */
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 */
};
/*
+** 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.
*/
@@ -9793,7 +10118,6 @@ 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);
@@ -9838,7 +10162,7 @@ SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3*, int);
SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,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*);
@@ -9881,7 +10205,7 @@ 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(sqlite3*, Select*);
@@ -9916,7 +10240,6 @@ 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*);
@@ -9948,9 +10271,12 @@ 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*);
@@ -9961,7 +10287,7 @@ SQLITE_PRIVATE int sqlite3SafetyOff(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
-SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Select*, Expr*, int);
+SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
#ifndef SQLITE_OMIT_TRIGGER
SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
@@ -10014,7 +10340,6 @@ 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);
@@ -10088,6 +10413,7 @@ SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
SQLITE_PRIVATE struct Sqlite3Config sqlite3Config;
+SQLITE_PRIVATE FuncDefHash sqlite3GlobalFunctions;
#endif
SQLITE_PRIVATE void sqlite3RootPageMoved(Db*, int, int);
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
@@ -10097,7 +10423,10 @@ 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 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 *);
@@ -10219,9 +10548,11 @@ SQLITE_PRIVATE int sqlite3JournalCreate(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*);
@@ -10330,6 +10661,14 @@ SQLITE_PRIVATE struct Sqlite3Config sqlite3Config = {
/* 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 FuncDefHash sqlite3GlobalFunctions;
+
/************** End of global.c **********************************************/
/************** Begin file status.c ******************************************/
/*
@@ -10360,14 +10699,6 @@ static struct {
/*
-** Reset the status records. This routine is called by
-** sqlite3_initialize().
-*/
-SQLITE_PRIVATE void sqlite3StatusReset(void){
- memset(&sqlite3Stat, 0, sizeof(sqlite3Stat));
-}
-
-/*
** Return the current value of a status parameter.
*/
SQLITE_PRIVATE int sqlite3StatusValue(int op){
@@ -11496,44 +11827,28 @@ static void currentTimeFunc(
** 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 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);
- }
+ 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
- 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" }
+ FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
+ FUNCTION(current_timestamp, 0, "%Y-%m-%d", 0, currentTimeFunc),
+ FUNCTION(current_date, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
+#endif
};
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);
+ for(i=0; i<ArraySize(aDateTimeFuncs); i++){
+ sqlite3FuncDefInsert(&sqlite3GlobalFunctions, &aDateTimeFuncs[i]);
}
-#endif
}
/************** End of date.c ************************************************/
@@ -12076,7 +12391,7 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){
extern int backtrace(void**,int);
extern void backtrace_symbols_fd(void*const*,int,int);
#else
-# define backtrace(A,B) 0
+# define backtrace(A,B) 1
# define backtrace_symbols_fd(A,B,C)
#endif
@@ -15366,8 +15681,11 @@ SQLITE_API void sqlite3_soft_heap_limit(int n){
*/
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;
@@ -15613,10 +15931,10 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
}else{
int i;
i = mem0.aScratchFree[--mem0.nScratchFree];
- sqlite3_mutex_leave(mem0.mutex);
i *= sqlite3Config.szScratch;
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
+ sqlite3_mutex_leave(mem0.mutex);
p = (void*)&((char*)sqlite3Config.pScratch)[i];
}
}
@@ -15686,6 +16004,7 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
** and that memory is of the right size and is not completely
** consumed. Otherwise, failover to sqlite3Malloc().
*/
+#if 0
SQLITE_PRIVATE void *sqlite3PageMalloc(int n){
void *p;
assert( n>0 );
@@ -15766,6 +16085,7 @@ SQLITE_PRIVATE void sqlite3PageFree(void *p){
}
}
}
+#endif
/*
** TRUE if p is a lookaside memory allocation from db
@@ -16294,7 +16614,6 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
- etByte errorflag = 0; /* True if an error is encountered */
etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -16318,7 +16637,6 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
if( c==0 ) break;
}
if( (c=(*++fmt))==0 ){
- errorflag = 1;
sqlite3StrAccumAppend(pAccum, "%", 1);
break;
}
@@ -17219,13 +17537,11 @@ struct Cursor {
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 */
@@ -17490,28 +17806,6 @@ struct Vdbe {
};
/*
-** An instance of the following structure holds information about a
-** single index record that has already been parsed out into individual
-** values.
-**
-** A record is an object that contains one or more fields of data.
-** Records are used to store the content of a table row and to store
-** the key of an index. A blob encoding of a record is created by
-** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
-** OP_Column opcode.
-**
-** This structure holds a record that has already been disassembled
-** into its constitutent fields.
-*/
-struct UnpackedRecord {
- KeyInfo *pKeyInfo; /* Collation and sort-order information */
- u16 nField; /* Number of entries in apMem[] */
- u8 needFree; /* True if memory obtained from sqlite3_malloc() */
- u8 needDestroy; /* True if apMem[]s should be destroyed on close */
- Mem *aMem; /* Values */
-};
-
-/*
** The following are allowed values for Vdbe.magic
*/
#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
@@ -17535,10 +17829,9 @@ 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*, int, int*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -17962,7 +18255,7 @@ SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
unsigned char *zOut = zIn;
unsigned char *zStart = zIn;
- unsigned char *zTerm;
+ unsigned char *zTerm = &zIn[strlen((char *)zIn)];
u32 c;
while( zIn[0] ){
@@ -18039,7 +18332,7 @@ SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
** It checks that the primitives for serializing and deserializing
** characters in each encoding are inverses of each other.
*/
-SQLITE_PRIVATE void sqlite3UtfSelfTest(){
+SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
unsigned int i, t;
unsigned char zBuf[20];
unsigned char *z;
@@ -20598,7 +20891,7 @@ static int os2Open(
int *pOutFlags /* Status return flags */
){
HFILE h;
- ULONG ulFileAttribute = 0;
+ ULONG ulFileAttribute = FILE_NORMAL;
ULONG ulOpenFlags = 0;
ULONG ulOpenMode = 0;
os2File *pFile = (os2File*)id;
@@ -20623,7 +20916,6 @@ static int os2Open(
OSTRACE2( "OPEN want %d\n", flags );
- /*ulOpenMode = flags & SQLITE_OPEN_READWRITE ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY;*/
if( flags & SQLITE_OPEN_READWRITE ){
ulOpenMode |= OPEN_ACCESS_READWRITE;
OSTRACE1( "OPEN read/write\n" );
@@ -20632,7 +20924,6 @@ static int os2Open(
OSTRACE1( "OPEN read only\n" );
}
- /*ulOpenFlags = flags & SQLITE_OPEN_CREATE ? OPEN_ACTION_CREATE_IF_NEW : OPEN_ACTION_FAIL_IF_NEW;*/
if( flags & SQLITE_OPEN_CREATE ){
ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
OSTRACE1( "OPEN open new/create\n" );
@@ -20641,7 +20932,6 @@ static int os2Open(
OSTRACE1( "OPEN open existing\n" );
}
- /*ulOpenMode |= flags & SQLITE_OPEN_MAIN_DB ? OPEN_SHARE_DENYNONE : OPEN_SHARE_DENYWRITE;*/
if( flags & SQLITE_OPEN_MAIN_DB ){
ulOpenMode |= OPEN_SHARE_DENYNONE;
OSTRACE1( "OPEN share read/write\n" );
@@ -20650,18 +20940,15 @@ static int os2Open(
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];
#ifdef NDEBUG /* when debugging we want to make sure it is deleted */
ulFileAttribute = FILE_HIDDEN;
#endif
- ulFileAttribute = FILE_NORMAL;
os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
OSTRACE1( "OPEN hidden/delete on close file attributes\n" );
}else{
- ulFileAttribute = FILE_ARCHIVED | FILE_NORMAL;
pFile->pathToDel = NULL;
OSTRACE1( "OPEN normal file attribute\n" );
}
@@ -21084,6 +21371,7 @@ struct unixFile {
#if SQLITE_THREADSAFE
pthread_t tid; /* The thread that "owns" this unixFile */
#endif
+ int lastErrno; /* The unix errno from the last I/O error */
};
/*
@@ -21574,6 +21862,12 @@ static struct openCnt *openList = 0;
#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(){
@@ -21819,7 +22113,11 @@ static int detectLockingStyle(
{ "hfs", LOCKING_STYLE_POSIX },
{ "ufs", LOCKING_STYLE_POSIX },
{ "afpfs", LOCKING_STYLE_AFP },
+#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
+ { "smbfs", LOCKING_STYLE_AFP },
+#else
{ "smbfs", LOCKING_STYLE_FLOCK },
+#endif
{ "msdos", LOCKING_STYLE_DOTFILE },
{ "webdav", LOCKING_STYLE_NONE },
{ 0, 0 }
@@ -21831,7 +22129,7 @@ static int detectLockingStyle(
return LOCKING_STYLE_NONE;
}
if( pVfs->pAppData ){
- return (int)pVfs->pAppData;
+ return SQLITE_PTR_TO_INT(pVfs->pAppData);
}
if( statfs(filePath, &fsInfo) != -1 ){
@@ -22327,13 +22625,77 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){
}
/*
+** This routine translates a standard POSIX errno code into something
+** useful to the clients of the sqlite3 functions. Specifically, it is
+** intended to translate a variety of "try again" errors into SQLITE_BUSY
+** and a variety of "please close the file descriptor NOW" errors into
+** SQLITE_IOERR
+**
+** Errors during initialization of locks, or file system support for locks,
+** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
+*/
+static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
+ switch (posixError) {
+ case 0:
+ return SQLITE_OK;
+
+ case EAGAIN:
+ case ETIMEDOUT:
+ case EBUSY:
+ case EINTR:
+ case ENOLCK:
+ /* random NFS retry error, unless during file system support
+ * introspection, in which it actually means what it says */
+ return SQLITE_BUSY;
+
+ case EACCES:
+ /* EACCES is like EAGAIN during locking operations, but not any other time*/
+ if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
+ return SQLITE_BUSY;
+ }
+ /* else fall through */
+ case EPERM:
+ return SQLITE_PERM;
+
+ case EDEADLK:
+ return SQLITE_IOERR_BLOCKED;
+
+#if EOPNOTSUPP!=ENOTSUP
+ case EOPNOTSUPP:
+ /* something went terribly awry, unless during file system support
+ * introspection, in which it actually means what it says */
+#endif
+ case ENOTSUP:
+ /* invalid fd, unless during file system support introspection, in which
+ * it actually means what it says */
+ 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; );
@@ -22343,28 +22705,31 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
/* Check if a thread in this process holds such a lock */
if( pFile->pLock->locktype>SHARED_LOCK ){
- 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);
+ OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
- *pResOut = r;
- return SQLITE_OK;
+ *pResOut = reserved;
+ return rc;
}
/*
@@ -22510,7 +22875,11 @@ static int unixLock(sqlite3_file *id, int locktype){
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;
}
}
@@ -22520,24 +22889,36 @@ static int unixLock(sqlite3_file *id, int locktype){
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
+ int tErrno = 0;
assert( pLock->cnt==0 );
assert( pLock->locktype==0 );
/* Now get the read-lock */
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
- 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++;
@@ -22567,7 +22948,11 @@ static int unixLock(sqlite3_file *id, int locktype){
}
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;
+ }
}
}
@@ -22626,7 +23011,12 @@ static int unixUnlock(sqlite3_file *id, int locktype){
lock.l_start = SHARED_FIRST;
lock.l_len = SHARED_SIZE;
if( fcntl(h, F_SETLK, &lock)==(-1) ){
- 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;
@@ -22636,7 +23026,12 @@ static int unixUnlock(sqlite3_file *id, int locktype){
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 ){
@@ -22657,8 +23052,13 @@ static int unixUnlock(sqlite3_file *id, int locktype){
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;
}
}
@@ -22681,6 +23081,8 @@ static int unixUnlock(sqlite3_file *id, int locktype){
}
}
}
+
+end_unlock:
leaveMutex();
if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
@@ -22768,14 +23170,11 @@ struct ByteRangeLockPB2
#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
@@ -22787,55 +23186,63 @@ static int _AFPFSSetLock(
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 */
+ 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 0;
+ return SQLITE_OK;
}
}
-/*
- ** 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.
- */
+/* 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;
- assert( pFile );
+ 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);
+ 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;
}
}
- 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;
}
/* AFP-style locking following the behavior of unixLock, see the unixLock
@@ -22885,9 +23292,9 @@ static int afpLock(sqlite3_file *id, int locktype){
|| (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;
}
}
@@ -22896,23 +23303,29 @@ static int afpLock(sqlite3_file *id, int locktype){
** operating system calls for the specified lock.
*/
if( locktype==SHARED_LOCK ){
- int lk, failed;
+ int lk, lrc1, lrc2, lrc1Errno;
- /* Now get the read-lock */
+ /* 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);
-
- /* Drop the temporary PENDING lock */
- if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)) {
- rc = SQLITE_IOERR_UNLOCK; /* This should never happen */
- goto afp_end_lock;
+ lrc1 = _AFPFSSetLock(context->filePath, pFile,
+ SHARED_FIRST+context->sharedLockByte, 1, 1);
+ if( IS_LOCK_ERROR(lrc1) ){
+ lrc1Errno = pFile->lastErrno;
}
+ /* Drop the temporary PENDING lock */
+ lrc2 = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 0);
- if( failed ){
- rc = SQLITE_BUSY;
+ 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;
+ } else if( lrc1 != SQLITE_OK ) {
+ rc = lrc1;
} else {
pFile->locktype = SHARED_LOCK;
}
@@ -22925,7 +23338,7 @@ static int afpLock(sqlite3_file *id, int locktype){
assert( 0!=pFile->locktype );
if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
/* Acquire a RESERVED lock */
- failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
+ failed = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);
}
if (!failed && locktype == EXCLUSIVE_LOCK) {
/* Acquire an EXCLUSIVE lock */
@@ -22933,22 +23346,21 @@ static int afpLock(sqlite3_file *id, int locktype){
/* Remove the shared lock before trying the range. we'll need to
** reestablish the shared lock if we can't get the afpUnlock
*/
- if (!_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 */
+ rc = failed;
}
}
- if( failed && rc == SQLITE_OK){
- rc = SQLITE_BUSY;
+ if( failed ){
+ rc = failed;
}
}
@@ -22980,7 +23392,7 @@ static int afpUnlock(sqlite3_file *id, int locktype) {
assert( pFile );
OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
pFile->locktype, getpid());
-
+
assert( locktype<=SHARED_LOCK );
if( pFile->locktype<=locktype ){
return SQLITE_OK;
@@ -22989,45 +23401,46 @@ static int afpUnlock(sqlite3_file *id, int locktype) {
return SQLITE_MISUSE;
}
enterMutex();
+ int failed = SQLITE_OK;
if( pFile->locktype>SHARED_LOCK ){
if( locktype==SHARED_LOCK ){
- int failed = 0;
/* unlock the exclusive range - then re-establish the shared lock */
if (pFile->locktype==EXCLUSIVE_LOCK) {
- failed = _AFPFSSetLock(context->filePath, pFile->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)
@@ -23056,27 +23469,62 @@ static int afpClose(sqlite3_file *id) {
*/
typedef void flockLockingContext;
+/* flock-style reserved lock checking following the behavior of
+ ** unixCheckReservedLock, see the unixCheckReservedLock function comments */
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
- int 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 */
+ 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 = r;
- return SQLITE_OK;
+ *pResOut = reserved;
+ return rc;
}
static int flockLock(sqlite3_file *id, int locktype) {
+ int rc = SQLITE_OK;
+ int lrc;
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) {
@@ -23085,20 +23533,29 @@ static int flockLock(sqlite3_file *id, int locktype) {
}
/* 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 */
@@ -23114,9 +23571,14 @@ static int flockUnlock(sqlite3_file *id, int locktype) {
/* 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;
}
@@ -23134,27 +23596,50 @@ static int flockClose(sqlite3_file *id) {
#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;
+ 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 = r;
- return SQLITE_OK;
+ *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. */
@@ -23163,32 +23648,48 @@ static int dotlockLock(sqlite3_file *id, int 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 */
@@ -23203,7 +23704,16 @@ static int dotlockUnlock(sqlite3_file *id, int locktype) {
}
/* 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;
}
@@ -23405,7 +23915,8 @@ static int fillInUnixFile(
break;
#endif
}
-
+
+ pNew->lastErrno = 0;
if( rc!=SQLITE_OK ){
if( dirfd>=0 ) close(dirfd);
close(h);
@@ -26136,6 +26647,1271 @@ bitvec_end:
#endif /* SQLITE_OMIT_BUILTIN_TEST */
/************** End of bitvec.c **********************************************/
+/************** Begin file pcache.c ******************************************/
+/*
+** 2008 August 05
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements that page cache.
+**
+** @(#) $Id$
+*/
+
+/*
+** A complete page cache is an instance of this structure.
+**
+** 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 */
+ void (*xDestroy)(PgHdr*); /* Called when refcnt goes 1->0 */
+ int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
+ void *pStress; /* Argument to xStress */
+ /**********************************************************************
+ ** The final group of elements can only be accessed while holding the
+ ** mutex. Both the cache owner and any other thread must hold the mutex
+ ** to read or write any of these elements.
+ */
+ int nPage; /* Total number of pages in apHash */
+ int nHash; /* Number of slots in apHash[] */
+ PgHdr **apHash; /* Hash table for fast lookup by pgno */
+ PgHdr *pClean; /* List of clean pages in use */
+};
+
+/*
+** 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 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 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.mutex)
+#define pcacheExitMutex() sqlite3_mutex_leave(pcache.mutex)
+#define pcacheMutexHeld() sqlite3_mutex_held(pcache.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.mutex) );
+ assert( (pPage->flags&PGHDR_DIRTY)==0 );
+ if( pPage->pCache->bPurgeable==0 ) return;
+ if( pPage->pNextLru ){
+ assert( pcache.pLruTail!=pPage );
+ pPage->pNextLru->pPrevLru = pPage->pPrevLru;
+ }else{
+ assert( pcache.pLruTail==pPage );
+ pcache.pLruTail = pPage->pPrevLru;
+ }
+ if( pPage->pPrevLru ){
+ assert( pcache.pLruHead!=pPage );
+ pPage->pPrevLru->pNextLru = pPage->pNextLru;
+ }else{
+ assert( pcache.pLruHead==pPage );
+ pcache.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.mutex) );
+ assert( (pPage->flags&PGHDR_DIRTY)==0 );
+ if( pPage->pCache->bPurgeable==0 ) return;
+ if( pcache.pLruTail && (pPage->flags & PGHDR_REUSE_UNLIKELY)!=0 ){
+ /* If reuse is unlikely. Put the page at the end of the LRU list
+ ** where it will be recycled sooner rather than later.
+ */
+ assert( pcache.pLruHead );
+ pPage->pNextLru = 0;
+ pPage->pPrevLru = pcache.pLruTail;
+ pcache.pLruTail->pNextLru = pPage;
+ pcache.pLruTail = pPage;
+ pPage->flags &= ~PGHDR_REUSE_UNLIKELY;
+ }else{
+ /* If reuse is possible. the page goes at the beginning of the LRU
+ ** list so that it will be the last to be recycled.
+ */
+ if( pcache.pLruHead ){
+ pcache.pLruHead->pPrevLru = pPage;
+ }
+ pPage->pNextLru = pcache.pLruHead;
+ pcache.pLruHead = pPage;
+ pPage->pPrevLru = 0;
+ if( pcache.pLruTail==0 ){
+ pcache.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.szSlot = sz;
+ pcache.pStart = pBuf;
+ pcache.pFree = 0;
+ while( n-- ){
+ p = (PgFreeslot*)pBuf;
+ p->pNext = pcache.pFree;
+ pcache.pFree = p;
+ pBuf = (void*)&((char*)pBuf)[sz];
+ }
+ pcache.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.
+*/
+void *pcacheMalloc(int sz, PCache *pCache){
+ assert( sqlite3_mutex_held(pcache.mutex) );
+ if( sz<=pcache.szSlot && pcache.pFree ){
+ PgFreeslot *p = pcache.pFree;
+ pcache.pFree = p->pNext;
+ 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(sz){
+ void *p;
+ pcacheEnterMutex();
+ p = pcacheMalloc(sz, 0);
+ pcacheExitMutex();
+ return p;
+}
+
+/*
+** Release a pager memory allocation
+*/
+void pcacheFree(void *p){
+ assert( sqlite3_mutex_held(pcache.mutex) );
+ if( p==0 ) return;
+ if( p>=pcache.pStart && p<pcache.pEnd ){
+ PgFreeslot *pSlot;
+ sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
+ pSlot = (PgFreeslot*)p;
+ pSlot->pNext = pcache.pFree;
+ pcache.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.mutex) );
+ p = pcacheMalloc(sz, pCache);
+ if( p==0 ) return 0;
+ memset(p, 0, sizeof(PgHdr));
+ p->pData = (void*)&p[1];
+ p->pExtra = (void*)&((char*)p->pData)[pCache->szPage];
+ if( pCache->bPurgeable ){
+ pcache.nCurrentPage++;
+ }
+ return p;
+}
+
+/*
+** Deallocate a page
+*/
+static void pcachePageFree(PgHdr *p){
+ assert( sqlite3_mutex_held(pcache.mutex) );
+ if( p->pCache->bPurgeable ){
+ pcache.nCurrentPage--;
+ }
+ pcacheFree(p->apSave[0]);
+ pcacheFree(p->apSave[1]);
+ pcacheFree(p);
+}
+
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+/*
+** Return the number of bytes that will be returned to the heap when
+** the argument is passed to pcachePageFree().
+*/
+static int pcachePageSize(PgHdr *p){
+ assert( sqlite3_mutex_held(pcache.mutex) );
+ assert( !pcache.pStart );
+ assert( p->apSave[0]==0 );
+ assert( p->apSave[1]==0 );
+ assert( p && p->pCache );
+ return sqlite3MallocSize(p);
+}
+#endif
+
+/*
+** Attempt to 'recycle' a page from the global LRU list. Only clean,
+** unreferenced pages from purgeable caches are eligible for recycling.
+**
+** This function removes page pcache.pLruTail from the global LRU list,
+** and from the hash-table and PCache.pClean list of the owner pcache.
+** There should be no other references to the page.
+**
+** A pointer to the recycled page is returned, or NULL if no page is
+** eligible for recycling.
+*/
+static PgHdr *pcacheRecyclePage(){
+ PgHdr *p = 0;
+ assert( sqlite3_mutex_held(pcache.mutex) );
+
+ if( (p=pcache.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.isInit );
+ assert( sqlite3_mutex_held(pcache.mutex) );
+
+ *ppPage = 0;
+
+ /* If we have reached the limit for pinned/dirty pages, and there is at
+ ** least one dirty page, invoke the xStress callback to cause a page to
+ ** become clean.
+ */
+ expensive_assert( pCache->nPinned==pcachePinnedCount(pCache) );
+ expensive_assert( pcacheCheckSynced(pCache) );
+ if( pCache->xStress
+ && pCache->pDirty
+ && pCache->nPinned>=(pcache.nMaxPage+pCache->nMin-pcache.nMinPage)
+ ){
+ 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 the global page limit has been reached, try to recycle a page. */
+ if( pCache->bPurgeable && pcache.nCurrentPage>=pcache.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.isInit==0 );
+ memset(&pcache, 0, sizeof(pcache));
+ if( sqlite3Config.bCoreMutex ){
+ /* No need to check the return value of sqlite3_mutex_alloc().
+ ** Allocating a static mutex cannot fail.
+ */
+ pcache.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
+ }
+ pcache.isInit = 1;
+ return SQLITE_OK;
+}
+SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
+ memset(&pcache, 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 */
+ void (*xDestroy)(PgHdr*), /* Called to destroy a page */
+ int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
+ void *pStress, /* Argument to xStress */
+ PCache *p /* Preallocated space for the PCache */
+){
+ assert( pcache.isInit );
+ memset(p, 0, sizeof(PCache));
+ p->szPage = szPage;
+ p->szExtra = szExtra;
+ p->bPurgeable = bPurgeable;
+ p->xDestroy = xDestroy;
+ p->xStress = xStress;
+ p->pStress = pStress;
+ p->nMax = 100;
+ p->nMin = 10;
+
+ pcacheEnterMutex();
+ if( bPurgeable ){
+ pcache.nMaxPage += p->nMax;
+ pcache.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.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;
+ if( p->pCache->xDestroy ){
+ p->pCache->xDestroy(p);
+ }
+ pCache->nRef--;
+ if( (p->flags&PGHDR_DIRTY)==0 ){
+ pCache->nPinned--;
+ pcacheEnterMutex();
+ if( pcache.nCurrentPage>pcache.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;
+}
+
+void pcacheMakeClean(PgHdr *p){
+ PCache *pCache = p->pCache;
+ assert( p->apSave[0]==0 && p->apSave[1]==0 );
+ assert( p->flags & PGHDR_DIRTY );
+ pcacheRemoveFromList(&pCache->pDirty, p);
+ pcacheAddToList(&pCache->pClean, p);
+ p->flags &= ~PGHDR_DIRTY;
+ if( p->nRef==0 ){
+ pcacheAddToLruList(p);
+ pCache->nPinned--;
+ }
+ 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 ){
+ assert( p->apSave[0]==0 && p->apSave[1]==0 );
+ pcacheRemoveFromList(&pCache->pDirty, p);
+ p->flags &= ~PGHDR_DIRTY;
+ pcacheAddToList(&pCache->pClean, p);
+ if( p->nRef==0 ){
+ pcacheAddToLruList(p);
+ pCache->nPinned--;
+ }
+ }
+ 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 ){
+ p->flags |= PGHDR_REUSE_UNLIKELY;
+ pcacheFree(p->apSave[0]);
+ pcacheFree(p->apSave[1]);
+ p->apSave[0] = 0;
+ p->apSave[1] = 0;
+ if( (p->flags & PGHDR_DIRTY) ){
+ pcacheMakeClean(p);
+ }
+ }
+ pcacheAddToHash(p);
+ pcacheExitMutex();
+}
+
+/*
+** Remove all content from a page cache
+*/
+void pcacheClear(PCache *pCache){
+ PgHdr *p, *pNext;
+ assert( sqlite3_mutex_held(pcache.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(){
+ PgHdr *p;
+ assert( sqlite3_mutex_held(pcache.mutex) );
+ while( pcache.nCurrentPage>pcache.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.nMaxPage -= pCache->nMax;
+ pcache.nMinPage -= pCache->nMin;
+ pcacheEnforceMaxPage();
+ }
+ sqlite3_free(pCache->apHash);
+ pcacheExitMutex();
+}
+
+/*
+** Preserve the content of the page. It is assumed that the content
+** has not been preserved already.
+**
+** If idJournal==0 then this is for the overall transaction.
+** If idJournal==1 then this is for the statement journal.
+**
+** This routine is used for in-memory databases only.
+**
+** Return SQLITE_OK or SQLITE_NOMEM if a memory allocation fails.
+*/
+SQLITE_PRIVATE int sqlite3PcachePreserve(PgHdr *p, int idJournal){
+ void *x;
+ int sz;
+ assert( p->pCache->bPurgeable==0 );
+ assert( p->apSave[idJournal]==0 );
+ sz = p->pCache->szPage;
+ p->apSave[idJournal] = x = sqlite3PageMalloc( sz );
+ if( x==0 ) return SQLITE_NOMEM;
+ memcpy(x, p->pData, sz);
+ return SQLITE_OK;
+}
+
+/*
+** Commit a change previously preserved.
+*/
+SQLITE_PRIVATE void sqlite3PcacheCommit(PCache *pCache, int idJournal){
+ PgHdr *p;
+ pcacheEnterMutex(); /* Mutex is required to call pcacheFree() */
+ for(p=pCache->pDirty; p; p=p->pNext){
+ if( p->apSave[idJournal] ){
+ pcacheFree(p->apSave[idJournal]);
+ p->apSave[idJournal] = 0;
+ }
+ }
+ pcacheExitMutex();
+}
+
+/*
+** Rollback a change previously preserved.
+*/
+SQLITE_PRIVATE void sqlite3PcacheRollback(PCache *pCache, int idJournal){
+ PgHdr *p;
+ int sz;
+ pcacheEnterMutex(); /* Mutex is required to call pcacheFree() */
+ sz = pCache->szPage;
+ for(p=pCache->pDirty; p; p=p->pNext){
+ if( p->apSave[idJournal] ){
+ memcpy(p->pData, p->apSave[idJournal], sz);
+ pcacheFree(p->apSave[idJournal]);
+ p->apSave[idJournal] = 0;
+ }
+ }
+ pcacheExitMutex();
+}
+
+/*
+** 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 );
+ }
+}
+
+/*
+** 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;
+}
+
+/*
+** 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 sqlite3PcacheSetFlags(PCache *pCache, int andMask, int orMask){
+ PgHdr *p;
+
+ assert( (orMask&PGHDR_NEED_SYNC)==0 );
+
+ /* Obtain the global mutex before modifying any PgHdr.flags variables
+ ** or traversing the LRU list.
+ */
+ pcacheEnterMutex();
+
+ for(p=pCache->pDirty; p; p=p->pNext){
+ p->flags = (p->flags&andMask)|orMask;
+ }
+ for(p=pCache->pClean; p; p=p->pNext){
+ p->flags = (p->flags&andMask)|orMask;
+ }
+
+ if( 0==(andMask&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.nMaxPage -= pCache->nMax;
+ pcache.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.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.pLruHead; p; p=p->pNextLru){
+ nRecyclable++;
+ }
+
+ *pnCurrent = pcache.nCurrentPage;
+ *pnMax = pcache.nMaxPage;
+ *pnMin = pcache.nMinPage;
+ *pnRecyclable = nRecyclable;
+}
+#endif
+
+
+/************** End of pcache.c **********************************************/
/************** Begin file pager.c *******************************************/
/*
** 2001 September 15
@@ -26267,173 +28043,6 @@ bitvec_end:
*/
#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
*/
@@ -26446,15 +28055,6 @@ struct PgHistory {
#endif
/*
-** Convert a pointer to a PgHdr into a pointer to its data
-** and back again.
-*/
-#define PGHDR_TO_DATA(P) ((P)->pData)
-#define PGHDR_TO_EXTRA(G,P) ((void*)&((G)[1]))
-#define PGHDR_TO_HIST(P,PGR) \
- ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->nExtra])
-
-/*
** A open page cache is an instance of the following structure.
**
** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or
@@ -26501,21 +28101,17 @@ struct Pager {
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 */
@@ -26532,17 +28128,10 @@ struct Pager {
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 */
};
/*
@@ -26554,22 +28143,11 @@ struct Pager {
SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */
SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */
SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */
-SQLITE_API int sqlite3_pager_pgfree_count = 0; /* Number of cache pages freed */
# define PAGER_INCR(v) v++
#else
# define PAGER_INCR(v)
#endif
-/*
-** The following variable points to the head of a double-linked list
-** of all pagers that are eligible for page stealing by the
-** sqlite3_release_memory() interface. Access to this list is
-** protected by the SQLITE_MUTEX_STATIC_MEM2 mutex.
-*/
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
-static Pager *sqlite3PagerList = 0;
-static PagerLruList sqlite3LruPageList = {0, 0, 0};
-#endif
/*
@@ -26640,164 +28218,6 @@ static const unsigned char aJournalMagic[] = {
#define PAGER_MAX_PGNO 2147483647
/*
-** The pagerEnter() and pagerLeave() routines acquire and release
-** a mutex on each pager. The mutex is recursive.
-**
-** This is a special-purpose mutex. It only provides mutual exclusion
-** between the Btree and the Memory Management sqlite3_release_memory()
-** function. It does not prevent, for example, two Btrees from accessing
-** the same pager at the same time. Other general-purpose mutexes in
-** the btree layer handle that chore.
-*/
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- static void pagerEnter(Pager *p){
- p->iInUseDB++;
- if( p->iInUseMM && p->iInUseDB==1 ){
-#ifndef SQLITE_MUTEX_NOOP
- sqlite3_mutex *mutex;
- mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
- p->iInUseDB = 0;
- sqlite3_mutex_enter(mutex);
- p->iInUseDB = 1;
- sqlite3_mutex_leave(mutex);
- }
- assert( p->iInUseMM==0 );
- }
- static void pagerLeave(Pager *p){
- p->iInUseDB--;
- assert( p->iInUseDB>=0 );
- }
-#else
-# define pagerEnter(X)
-# define pagerLeave(X)
-#endif
-
-/*
-** Add page pPg to the end of the linked list managed by structure
-** pList (pPg becomes the last entry in the list - the most recently
-** used). Argument pLink should point to either pPg->free or pPg->gfree,
-** depending on whether pPg is being added to the pager-specific or
-** global LRU list.
-*/
-static void listAdd(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){
- pLink->pNext = 0;
- pLink->pPrev = pList->pLast;
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- assert(pLink==&pPg->free || pLink==&pPg->gfree);
- assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
-#endif
-
- if( pList->pLast ){
- int iOff = (char *)pLink - (char *)pPg;
- PagerLruLink *pLastLink = (PagerLruLink *)(&((u8 *)pList->pLast)[iOff]);
- pLastLink->pNext = pPg;
- }else{
- assert(!pList->pFirst);
- pList->pFirst = pPg;
- }
-
- pList->pLast = pPg;
- if( !pList->pFirstSynced && pPg->needSync==0 ){
- pList->pFirstSynced = pPg;
- }
-}
-
-/*
-** Remove pPg from the list managed by the structure pointed to by pList.
-**
-** Argument pLink should point to either pPg->free or pPg->gfree, depending
-** on whether pPg is being added to the pager-specific or global LRU list.
-*/
-static void listRemove(PagerLruList *pList, PagerLruLink *pLink, PgHdr *pPg){
- int iOff = (char *)pLink - (char *)pPg;
-
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- assert(pLink==&pPg->free || pLink==&pPg->gfree);
- assert(pLink==&pPg->gfree || pList!=&sqlite3LruPageList);
-#endif
-
- if( pPg==pList->pFirst ){
- pList->pFirst = pLink->pNext;
- }
- if( pPg==pList->pLast ){
- pList->pLast = pLink->pPrev;
- }
- if( pLink->pPrev ){
- PagerLruLink *pPrevLink = (PagerLruLink *)(&((u8 *)pLink->pPrev)[iOff]);
- pPrevLink->pNext = pLink->pNext;
- }
- if( pLink->pNext ){
- PagerLruLink *pNextLink = (PagerLruLink *)(&((u8 *)pLink->pNext)[iOff]);
- pNextLink->pPrev = pLink->pPrev;
- }
- if( pPg==pList->pFirstSynced ){
- PgHdr *p = pLink->pNext;
- while( p && p->needSync ){
- PagerLruLink *pL = (PagerLruLink *)(&((u8 *)p)[iOff]);
- p = pL->pNext;
- }
- pList->pFirstSynced = p;
- }
-
- pLink->pNext = pLink->pPrev = 0;
-}
-
-/*
-** Add page pPg to the list of free pages for the pager. If
-** memory-management is enabled, also add the page to the global
-** list of free pages.
-*/
-static void lruListAdd(PgHdr *pPg){
- listAdd(&pPg->pPager->lru, &pPg->free, pPg);
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( !pPg->pPager->memDb ){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- listAdd(&sqlite3LruPageList, &pPg->gfree, pPg);
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- }
-#endif
-}
-
-/*
-** Remove page pPg from the list of free pages for the associated pager.
-** If memory-management is enabled, also remove pPg from the global list
-** of free pages.
-*/
-static void lruListRemove(PgHdr *pPg){
- listRemove(&pPg->pPager->lru, &pPg->free, pPg);
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( !pPg->pPager->memDb ){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- listRemove(&sqlite3LruPageList, &pPg->gfree, pPg);
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- }
-#endif
-}
-
-/*
-** This function is called just after the needSync flag has been cleared
-** from all pages managed by pPager (usually because the journal file
-** has just been synced). It updates the pPager->lru.pFirstSynced variable
-** and, if memory-management is enabled, the sqlite3LruPageList.pFirstSynced
-** variable also.
-*/
-static void lruListSetFirstSynced(Pager *pPager){
- pPager->lru.pFirstSynced = pPager->lru.pFirst;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( !pPager->memDb ){
- PgHdr *p;
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- for(p=sqlite3LruPageList.pFirst; p && p->needSync; p=p->gfree.pNext);
- assert(p==pPager->lru.pFirstSynced || p==sqlite3LruPageList.pFirstSynced);
- sqlite3LruPageList.pFirstSynced = p;
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU));
- }
-#endif
-}
-
-/*
** Return true if page *pPg has already been written to the statement
** journal (or statement snapshot has been created, if *pPg is part
** of an in-memory database).
@@ -26805,54 +28225,13 @@ static void lruListSetFirstSynced(Pager *pPager){
static int pageInStatement(PgHdr *pPg){
Pager *pPager = pPg->pPager;
if( MEMDB ){
- return PGHDR_TO_HIST(pPg, pPager)->inStmt;
+ return pPg->apSave[1]!=0;
}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;
- }
-}
-
-/*
** Read a 32-bit integer from the given file descriptor. Store the integer
** that is read in *pRes. Return SQLITE_OK if everything worked, or an
** error code is something goes wrong.
@@ -26961,7 +28340,9 @@ static int pager_error(Pager *pPager, int rc){
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.
@@ -26990,8 +28371,10 @@ static u32 pager_datahash(int nByte, unsigned char *pData){
return hash;
}
static u32 pager_pagehash(PgHdr *pPage){
- return pager_datahash(pPage->pPager->pageSize,
- (unsigned char *)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);
}
/*
@@ -27002,15 +28385,15 @@ static u32 pager_pagehash(PgHdr *pPage){
#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 || MEMDB
+ || (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.
@@ -27381,40 +28764,12 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
}
/*
-** Add or remove a page from the list of all pages that are in the
-** statement journal.
-**
-** The Pager keeps a separate list of pages that are currently in
-** the statement journal. This helps the sqlite3PagerStmtCommit()
-** routine run MUCH faster for the common case where there are many
-** pages in memory but only a few are in the statement journal.
-*/
-static void page_add_to_stmt_list(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
- assert( MEMDB );
- if( !pHist->inStmt ){
- assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 );
- if( pPager->pStmt ){
- PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg;
- }
- pHist->pNextStmt = pPager->pStmt;
- pPager->pStmt = pPg;
- pHist->inStmt = 1;
- }
-}
-
-/*
** Find a page in the hash table given its page number. Return
** a pointer to the page or NULL if not found.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
PgHdr *p;
- 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;
}
@@ -27425,27 +28780,8 @@ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
** to access those pages will likely result in a coredump.
*/
static void pager_reset(Pager *pPager){
- PgHdr *pPg, *pNext;
if( pPager->errCode ) return;
- 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);
}
/*
@@ -27474,6 +28810,8 @@ static void pager_unlock(Pager *pPager){
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
@@ -27510,17 +28848,12 @@ static void pager_unlock(Pager *pPager){
** do not attempt the rollback.
*/
static void pagerUnlockAndRollback(Pager *p){
- /* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */
if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){
sqlite3BeginBenignMalloc();
sqlite3PagerRollback(p);
sqlite3EndBenignMalloc();
}
pager_unlock(p);
-#if 0
- assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );
- assert( p->errCode || !p->stmtOpen || p->exclusiveMode );
-#endif
}
/*
@@ -27541,7 +28874,6 @@ static void pagerUnlockAndRollback(Pager *p){
** a file is an expensive operation.
*/
static int pager_end_transaction(Pager *pPager, int hasMaster){
- PgHdr *pPg;
int rc = SQLITE_OK;
int rc2 = SQLITE_OK;
assert( !MEMDB );
@@ -27570,16 +28902,15 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
}
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);
+ sqlite3PcacheIterate(pPager->pPCache, pager_set_pagehash);
#endif
- }
- pPager->pDirty = 0;
+ sqlite3PcacheSetFlags(pPager->pPCache,
+ ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
+ );
pPager->dirtyCache = 0;
pPager->nRec = 0;
}else{
@@ -27595,7 +28926,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
pPager->origDbSize = 0;
pPager->setMaster = 0;
pPager->needSync = 0;
- lruListSetFirstSynced(pPager);
+ /* lruListSetFirstSynced(pPager); */
pPager->dbSize = -1;
pPager->dbModified = 0;
@@ -27639,15 +28970,15 @@ static void makeClean(PgHdr*);
** 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 */
@@ -27655,10 +28986,10 @@ static int pager_playback_one_page(
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);
@@ -27678,7 +29009,7 @@ static int pager_playback_one_page(
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;
@@ -27724,13 +29055,12 @@ static int pager_playback_one_page(
pPg = pager_lookup(pPager, pgno);
PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));
- if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || 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
@@ -27740,12 +29070,12 @@ static int pager_playback_one_page(
** 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);
}
+ if( isMainJrnl ) makeClean(pPg);
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
@@ -27757,6 +29087,7 @@ static int pager_playback_one_page(
/* Decode the page just read from disk */
CODEC1(pPager, pData, pPg->pgno, 3);
+ sqlite3PcacheRelease(pPg);
}
return rc;
}
@@ -28210,11 +29541,7 @@ end_stmt_playback:
** 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);
}
/*
@@ -28244,10 +29571,10 @@ SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
-SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int 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
@@ -28286,6 +29613,8 @@ static int sqlite3PagerOpentemp(
return rc;
}
+static int pagerStress(void *,PgHdr *);
+
/*
** Create a new page cache and put a pointer to the page cache in *ppPager.
** The file to be cached need not exist. The file is not locked until
@@ -28304,6 +29633,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
sqlite3_vfs *pVfs, /* The virtual file system to use */
Pager **ppPager, /* Return the Pager structure here */
const char *zFilename, /* Name of the database file to open */
+ void (*xDesc)(DbPage*), /* Page destructor function */
int nExtra, /* Extra bytes append to each in-memory page */
int flags, /* flags controlling this file */
int vfsFlags /* flags passed through to sqlite3_vfs.xOpen() */
@@ -28318,6 +29648,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
int journalFileSize = sqlite3JournalSize(pVfs);
+ int pcacheSize = sqlite3PcacheSize();
int szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;
char *zPathname = 0;
int nPathname = 0;
@@ -28354,6 +29685,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* Allocate memory for the pager structure */
pPager = sqlite3MallocZero(
sizeof(*pPager) + /* Pager structure */
+ pcacheSize + /* PCache object */
journalFileSize + /* The journal file structure */
pVfs->szOsFile * 3 + /* The main db and two journal files */
3*nPathname + 40 /* zFilename, zDirectory, zJournal */
@@ -28362,7 +29694,8 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
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];
@@ -28440,6 +29773,9 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
sqlite3_free(pPager);
return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc);
}
+ nExtra = FORCE_ALIGNMENT(nExtra);
+ sqlite3PcacheOpen(szPageDflt, nExtra, !memDb, xDesc,
+ !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))
@@ -28487,7 +29823,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* 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 ){
@@ -28496,24 +29832,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
/* 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;
}
@@ -28525,18 +29843,6 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusy
}
/*
-** 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
@@ -28557,19 +29863,19 @@ SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){
u16 pageSize = *pPageSize;
assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
if( pageSize && pageSize!=pPager->pageSize
- && !pPager->memDb && pPager->nRef==0
+ && (pPager->memDb==0 || pPager->dbSize==0)
+ && sqlite3PcacheRefCount(pPager->pPCache)==0
){
char *pNew = (char *)sqlite3PageMalloc(pageSize);
if( !pNew ){
rc = SQLITE_NOMEM;
}else{
- pagerEnter(pPager);
pager_reset(pPager);
pPager->pageSize = pageSize;
- setSectorSize(pPager);
+ if( !pPager->memDb ) setSectorSize(pPager);
sqlite3PageFree(pPager->pTmpSpace);
pPager->pTmpSpace = pNew;
- pagerLeave(pPager);
+ sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
}
}
*pPageSize = pPager->pageSize;
@@ -28665,7 +29971,8 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
int rc;
assert( pPager!=0 );
if( pPager->errCode ){
- return pPager->errCode;
+ rc = pPager->errCode;
+ return rc;
}
if( pPager->dbSize>=0 ){
n = pPager->dbSize;
@@ -28673,9 +29980,7 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
assert(pPager->fd->pMethods||pPager->tempFile);
if( (pPager->fd->pMethods)
&& (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){
- pPager->nRef++;
pager_error(pPager, rc);
- pPager->nRef--;
return rc;
}
if( n>0 && n<pPager->pageSize ){
@@ -28699,69 +30004,12 @@ SQLITE_PRIVATE int sqlite3PagerPagecount(Pager *pPager, int *pnPage){
return SQLITE_OK;
}
-
-#ifndef SQLITE_OMIT_MEMORYDB
-/*
-** Clear a PgHistory block
-*/
-static void clearHistory(PgHistory *pHist){
- sqlite3PageFree(pHist->pOrig);
- sqlite3PageFree(pHist->pStmt);
- pHist->pOrig = 0;
- pHist->pStmt = 0;
-}
-#else
-#define clearHistory(x)
-#endif
-
/*
** Forward declaration
*/
static int syncJournal(Pager*);
/*
-** Unlink pPg from its hash chain. Also set the page number to 0 to indicate
-** that the page is not part of any hash chain. This is required because the
-** sqlite3PagerMovepage() routine can leave a page in the
-** pNextFree/pPrevFree list that is not a part of any hash-chain.
-*/
-static void unlinkHashChain(Pager *pPager, PgHdr *pPg){
- if( pPg->pgno==0 ){
- assert( pPg->pNextHash==0 && pPg->pPrevHash==0 );
- return;
- }
- if( pPg->pNextHash ){
- pPg->pNextHash->pPrevHash = pPg->pPrevHash;
- }
- if( pPg->pPrevHash ){
- assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg );
- pPg->pPrevHash->pNextHash = pPg->pNextHash;
- }else{
- int h = pPg->pgno & (pPager->nHash-1);
- pPager->aHash[h] = pPg->pNextHash;
- }
- if( MEMDB ){
- clearHistory(PGHDR_TO_HIST(pPg, pPager));
- }
- pPg->pgno = 0;
- pPg->pNextHash = pPg->pPrevHash = 0;
-}
-
-/*
-** Unlink a page from the free list (the list of all pages where nRef==0)
-** and from its hash collision chain.
-*/
-static void unlinkPage(PgHdr *pPg){
- Pager *pPager = pPg->pPager;
-
- /* Unlink from free page list */
- lruListRemove(pPg);
-
- /* Unlink from the pgno hash table */
- unlinkHashChain(pPager, pPg);
-}
-
-/*
** This routine is used to truncate the cache when a database
** is truncated. Drop from the cache all pages whose pgno is
** larger than pPager->dbSize and is unreferenced.
@@ -28774,33 +30022,7 @@ static void unlinkPage(PgHdr *pPg){
** 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);
}
/*
@@ -28841,37 +30063,29 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
** Truncate the file to the number of pages specified.
*/
SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
- int rc;
+ int rc = SQLITE_OK;
assert( pPager->state>=PAGER_SHARED || MEMDB );
+
+
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;
+ }else if( nPage<(unsigned)pPager->dbSize ){
+ if( MEMDB ){
+ pPager->dbSize = nPage;
+ pager_truncate_cache(pPager);
+ }else{
+ rc = syncJournal(pPager);
+ if( rc==SQLITE_OK ){
+ /* Get an exclusive lock on the database before truncating. */
+ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pager_truncate(pPager, nPage);
+ }
+ }
}
- rc = pager_truncate(pPager, nPage);
return rc;
}
@@ -28890,23 +30104,6 @@ SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
** to the caller.
*/
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( !MEMDB ){
-#ifndef SQLITE_MUTEX_NOOP
- sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM2);
-#endif
- sqlite3_mutex_enter(mutex);
- if( pPager->pPrev ){
- pPager->pPrev->pNext = pPager->pNext;
- }else{
- sqlite3PagerList = pPager->pNext;
- }
- if( pPager->pNext ){
- pPager->pNext->pPrev = pPager->pPrev;
- }
- sqlite3_mutex_leave(mutex);
- }
-#endif
disable_simulated_io_errors();
sqlite3BeginBenignMalloc();
@@ -28922,6 +30119,7 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
sqlite3OsClose(pPager->jfd);
}
sqlite3BitvecDestroy(pPager->pInJournal);
+ sqlite3BitvecDestroy(pPager->pAlwaysRollback);
if( pPager->stmtOpen ){
sqlite3OsClose(pPager->stfd);
}
@@ -28932,8 +30130,8 @@ SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager){
** }
*/
- sqlite3_free(pPager->aHash);
sqlite3PageFree(pPager->pTmpSpace);
+ sqlite3PcacheClose(pPager->pPCache);
sqlite3_free(pPager);
return SQLITE_OK;
}
@@ -28948,42 +30146,11 @@ SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *p){
#endif
/*
-** The page_ref() function increments the reference count for a page.
-** If the page is currently on the freelist (the reference count is zero) then
-** remove it from the freelist.
-**
-** For non-test systems, page_ref() is a macro that calls _page_ref()
-** online of the reference count is zero. For test systems, page_ref()
-** is a real function so that we can set breakpoints and trace it.
-*/
-static void _page_ref(PgHdr *pPg){
- if( pPg->nRef==0 ){
- /* The page is currently on the freelist. Remove it. */
- lruListRemove(pPg);
- pPg->pPager->nRef++;
- }
- pPg->nRef++;
-}
-#ifdef SQLITE_DEBUG
- static void page_ref(PgHdr *pPg){
- if( pPg->nRef==0 ){
- _page_ref(pPg);
- }else{
- pPg->nRef++;
- }
- }
-#else
-# define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++)
-#endif
-
-/*
** Increment the reference count for a page. The input pointer is
** a reference to the page data.
*/
SQLITE_PRIVATE int sqlite3PagerRef(DbPage *pPg){
- pagerEnter(pPg->pPager);
- page_ref(pPg);
- pagerLeave(pPg->pPager);
+ sqlite3PcacheRef(pPg);
return SQLITE_OK;
}
@@ -29013,7 +30180,6 @@ SQLITE_PRIVATE int sqlite3PagerRef(DbPage *pPg){
** memory.
*/
static int syncJournal(Pager *pPager){
- PgHdr *pPg;
int rc = SQLITE_OK;
/* Sync the journal before modifying the main database
@@ -29063,10 +30229,8 @@ static int syncJournal(Pager *pPager){
/* Erase the needSync flag from every page.
*/
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- pPg->needSync = 0;
- }
- lruListSetFirstSynced(pPager);
+ sqlite3PcacheSetFlags(pPager->pPCache, ~PGHDR_NEED_SYNC, 0);
+ /* lruListSetFirstSynced(pPager); */
}
#ifndef NDEBUG
@@ -29075,10 +30239,8 @@ static int syncJournal(Pager *pPager){
** invariant is true.
*/
else{
- for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
- assert( pPg->needSync==0 );
- }
- assert( pPager->lru.pFirstSynced==pPager->lru.pFirst );
+ sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_NEED_SYNC);
+ /* assert( pPager->lru.pFirstSynced==pPager->lru.pFirst ); */
}
#endif
@@ -29086,87 +30248,14 @@ static int syncJournal(Pager *pPager){
}
/*
-** Merge two lists of pages connected by pDirty and in pgno order.
-** Do not both fixing the pPrevDirty pointers.
-*/
-static PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB){
- PgHdr result, *pTail;
- pTail = &result;
- while( pA && pB ){
- if( pA->pgno<pB->pgno ){
- pTail->pDirty = pA;
- pTail = pA;
- pA = pA->pDirty;
- }else{
- pTail->pDirty = pB;
- pTail = pB;
- pB = pB->pDirty;
- }
- }
- if( pA ){
- pTail->pDirty = pA;
- }else if( pB ){
- pTail->pDirty = pB;
- }else{
- pTail->pDirty = 0;
- }
- return result.pDirty;
-}
-
-/*
-** Sort the list of pages in accending order by pgno. Pages are
-** connected by pDirty pointers. The pPrevDirty pointers are
-** corrupted by this sort.
-*/
-#define N_SORT_BUCKET_ALLOC 25
-#define N_SORT_BUCKET 25
-#ifdef SQLITE_TEST
- int sqlite3_pager_n_sort_bucket = 0;
- #undef N_SORT_BUCKET
- #define N_SORT_BUCKET \
- (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC)
-#endif
-static PgHdr *sort_pagelist(PgHdr *pIn){
- PgHdr *a[N_SORT_BUCKET_ALLOC], *p;
- int i;
- memset(a, 0, sizeof(a));
- while( pIn ){
- p = pIn;
- pIn = p->pDirty;
- p->pDirty = 0;
- for(i=0; i<N_SORT_BUCKET-1; i++){
- if( a[i]==0 ){
- a[i] = p;
- break;
- }else{
- p = merge_pagelist(a[i], p);
- a[i] = 0;
- }
- }
- if( i==N_SORT_BUCKET-1 ){
- /* Coverage: To get here, there need to be 2^(N_SORT_BUCKET)
- ** elements in the input list. This is possible, but impractical.
- ** Testing this line is the point of global variable
- ** sqlite3_pager_n_sort_bucket.
- */
- a[i] = merge_pagelist(a[i], p);
- }
- }
- p = a[0];
- for(i=1; i<N_SORT_BUCKET; i++){
- p = merge_pagelist(p, a[i]);
- }
- return p;
-}
-
-/*
** Given a list of pages (connected by the PgHdr.pDirty pointer) write
-** every one of those pages out to the database file 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;
@@ -29193,11 +30282,6 @@ static int pager_write_pagelist(PgHdr *pList){
return rc;
}
- pList = sort_pagelist(pList);
- for(p=pList; p; p=p->pDirty){
- assert( p->dirty );
- p->dirty = 0;
- }
while( pList ){
/* If the file has not yet been opened, open it now. */
@@ -29212,9 +30296,9 @@ static int pager_write_pagelist(PgHdr *pList){
** make the file smaller (presumably by auto-vacuum code). Do not write
** any such pages to the file.
*/
- if( pList->pgno<=pPager->dbSize ){
+ 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));
@@ -29234,33 +30318,56 @@ static int pager_write_pagelist(PgHdr *pList){
#ifdef SQLITE_CHECK_PAGES
pList->pageHash = pager_pagehash(pList);
#endif
+ /* makeClean(pList); */
pList = pList->pDirty;
}
+
+ /* sqlite3PcacheCleanAll(pPager->pPCache); */
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.
+** 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 PgHdr *pager_get_all_dirty_pages(Pager *pPager){
+static int pagerStress(void *p, PgHdr *pPg){
+ Pager *pPager = (Pager *)p;
+ int rc = SQLITE_OK;
-#ifndef NDEBUG
- /* Verify the sanity of the dirty list when we are running
- ** in debugging mode. This is expensive, so do not
- ** do this on a normal build. */
- int n1 = 0;
- int n2 = 0;
- PgHdr *p;
- for(p=pPager->pAll; p; p=p->pNextAll){ if( p->dirty ) n1++; }
- for(p=pPager->pDirty; p; p=p->pDirty){ n2++; }
- assert( n1==n2 );
-#endif
+ if( pPager->doNotSync ){
+ return SQLITE_OK;
+ }
- return pPager->pDirty;
+ 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 &&
+ !(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.
@@ -29283,256 +30390,29 @@ static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
static int hasHotJournal(Pager *pPager, int *pExists){
sqlite3_vfs *pVfs = pPager->pVfs;
int rc = SQLITE_OK;
+ int exists;
+ int locked;
+ assert( pPager!=0 );
+ assert( pPager->useJournal );
+ assert( pPager->fd->pMethods );
*pExists = 0;
- if( pPager->useJournal && pPager->fd->pMethods ){
- int exists;
- int locked;
-
- rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
- if( rc==SQLITE_OK && exists ){
- rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
- }
-
- if( rc==SQLITE_OK && exists && !locked ){
- int nPage;
- rc = sqlite3PagerPagecount(pPager, &nPage);
- if( rc==SQLITE_OK ){
- if( nPage==0 ){
- sqlite3OsDelete(pVfs, pPager->zJournal, 0);
- }else{
- *pExists = 1;
- }
- }
- }
- }
-
- return rc;
-}
-
-/*
-** Try to find a page in the cache that can be recycled.
-**
-** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It
-** does not set the pPager->errCode variable.
-*/
-static int pager_recycle(Pager *pPager, PgHdr **ppPg){
- PgHdr *pPg;
- *ppPg = 0;
-
- /* It is illegal to call this function unless the pager object
- ** pointed to by pPager has at least one free page (page with nRef==0).
- */
- assert(!MEMDB);
- assert(pPager->lru.pFirst);
-
- /* Find a page to recycle. Try to locate a page that does not
- ** require us to do an fsync() on the journal.
- */
- pPg = pPager->lru.pFirstSynced;
-
- /* If we could not find a page that does not require an fsync()
- ** on the journal file then fsync the journal file. This is a
- ** very slow operation, so we work hard to avoid it. But sometimes
- ** it can't be helped.
- */
- if( pPg==0 && pPager->lru.pFirst ){
- if( !pPager->errCode ){
- int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
- int rc = syncJournal(pPager);
- if( rc!=0 ){
- return rc;
- }
- if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
- /* If in full-sync mode, write a new journal header into the
- ** journal file. This is done to avoid ever modifying a journal
- ** header that is involved in the rollback of pages that have
- ** already been written to the database (in case the header is
- ** trashed when the nRec field is updated).
- */
- pPager->nRec = 0;
- assert( pPager->journalOff > 0 );
- assert( pPager->doNotSync==0 );
- rc = writeJournalHdr(pPager);
- if( rc!=0 ){
- return rc;
- }
- }
- }
- pPg = pPager->lru.pFirst;
- }
-
- assert( pPg->nRef==0 );
-
- /* Write the page to the database file if it is dirty.
- */
- if( pPg->dirty && !pPager->errCode ){
- int rc;
- assert( pPg->needSync==0 );
- makeClean(pPg);
- pPg->dirty = 1;
- pPg->pDirty = 0;
- rc = pager_write_pagelist( pPg );
- pPg->dirty = 0;
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
- 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;
+ rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
+ if( rc==SQLITE_OK && exists ){
+ rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
}
-
- /* 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 && exists && !locked ){
+ int nPage;
+ rc = sqlite3PagerPagecount(pPager, &nPage);
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;
- }
+ if( nPage==0 ){
+ sqlite3OsDelete(pVfs, pPager->zJournal, 0);
}else{
- assert(pPg->pPrevAll);
- assert(pPg->pPrevAll->pNextAll==pPg);
- pTmp = pPg->pPrevAll;
- pTmp->pNextAll = pPg->pNextAll;
- if( pTmp->pNextAll ){
- pTmp->pNextAll->pPrevAll = pTmp;
- }
+ *pExists = 1;
}
- 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;
+ return rc;
}
-#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
/*
** Read the content of page pPg out of the database file.
@@ -29546,15 +30426,15 @@ static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){
return SQLITE_IOERR_SHORT_READ;
}
offset = (pgno-1)*(i64)pPager->pageSize;
- rc = sqlite3OsRead(pPager->fd, 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;
@@ -29579,7 +30459,9 @@ static int pagerSharedLock(Pager *pPager){
** the error. Discard the contents of the pager-cache and treat any
** open journal file as a hot-journal.
*/
- if( !MEMDB && pPager->exclusiveMode && pPager->nRef==0 && pPager->errCode ){
+ if( !MEMDB && pPager->exclusiveMode
+ && sqlite3PcacheRefCount(pPager->pPCache)==0 && pPager->errCode
+ ){
if( pPager->journalOpen ){
isErrorReset = 1;
}
@@ -29599,7 +30481,7 @@ static int pagerSharedLock(Pager *pPager){
sqlite3_vfs *pVfs = pPager->pVfs;
if( !MEMDB ){
int isHotJournal;
- assert( pPager->nRef==0 );
+ assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
if( !pPager->noReadlock ){
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
if( rc!=SQLITE_OK ){
@@ -29693,7 +30575,7 @@ static int pagerSharedLock(Pager *pPager){
);
}
- if( pPager->pAll ){
+ 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
@@ -29748,104 +30630,6 @@ static int pagerSharedLock(Pager *pPager){
}
/*
-** Allocate a PgHdr object. Either create a new one or reuse
-** an existing one that is not otherwise in use.
-**
-** A new PgHdr structure is created if any of the following are
-** true:
-**
-** (1) We have not exceeded our maximum allocated cache size
-** as set by the "PRAGMA cache_size" command.
-**
-** (2) There are no unused PgHdr objects available at this time.
-**
-** (3) This is an in-memory database.
-**
-** (4) There are no PgHdr objects that do not require a journal
-** file sync and a sync of the journal file is currently
-** prohibited.
-**
-** Otherwise, reuse an existing PgHdr. In other words, reuse an
-** existing PgHdr if all of the following are true:
-**
-** (1) We have reached or exceeded the maximum cache size
-** allowed by "PRAGMA cache_size".
-**
-** (2) There is a PgHdr available with PgHdr->nRef==0
-**
-** (3) We are not in an in-memory database
-**
-** (4) Either there is an available PgHdr that does not need
-** to be synced to disk or else disk syncing is currently
-** allowed.
-*/
-static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
- int rc = SQLITE_OK;
- PgHdr *pPg;
- int nByteHdr;
-
- /* Create a new PgHdr if any of the four conditions defined
- ** above are met: */
- if( pPager->nPage<pPager->mxPage
- || pPager->lru.pFirst==0
- || MEMDB
- || (pPager->lru.pFirstSynced==0 && pPager->doNotSync)
- ){
- void *pData;
- if( pPager->nPage>=pPager->nHash ){
- pager_resize_hash_table(pPager,
- pPager->nHash<256 ? 256 : pPager->nHash*2);
- if( pPager->nHash==0 ){
- rc = SQLITE_NOMEM;
- goto pager_allocate_out;
- }
- }
- pagerLeave(pPager);
- nByteHdr = sizeof(*pPg) + sizeof(u32) + pPager->nExtra
- + MEMDB*sizeof(PgHistory);
- pPg = sqlite3Malloc( nByteHdr );
- if( pPg ){
- pData = sqlite3PageMalloc( pPager->pageSize );
- if( pData==0 ){
- sqlite3_free(pPg);
- pPg = 0;
- }
- }
- pagerEnter(pPager);
- if( pPg==0 ){
- rc = SQLITE_NOMEM;
- goto pager_allocate_out;
- }
- memset(pPg, 0, nByteHdr);
- pPg->pData = pData;
- pPg->pPager = pPager;
- pPg->pNextAll = pPager->pAll;
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- if( pPg->pNextAll ){
- pPg->pNextAll->pPrevAll = pPg;
- }
-#endif
- pPager->pAll = pPg;
- pPager->nPage++;
- }else{
- /* Recycle an existing page with a zero ref-count. */
- rc = pager_recycle(pPager, &pPg);
- if( rc==SQLITE_BUSY ){
- rc = SQLITE_IOERR_BLOCKED;
- }
- if( rc!=SQLITE_OK ){
- goto pager_allocate_out;
- }
- assert( pPager->state>=SHARED_LOCK );
- assert(pPg);
- }
- *ppPg = pPg;
-
-pager_allocate_out:
- return rc;
-}
-
-/*
** Make sure we have the content for a page. If the page was
** previously acquired with noContent==1, then the content was
** just initialized to zeros instead of being read from disk.
@@ -29853,10 +30637,10 @@ pager_allocate_out:
** 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;
+ pPg->flags &= ~PGHDR_NEED_READ;
}else{
return rc;
}
@@ -29865,6 +30649,30 @@ static int pager_get_content(PgHdr *pPg){
}
/*
+** If the reference count has reached zero, and the pager is not in the
+** middle of a write transaction or opened in exclusive mode, unlock it.
+*/
+static void pagerUnlockIfUnused(Pager *pPager){
+ if( (sqlite3PcacheRefCount(pPager->pPCache)==0)
+ && (!pPager->exclusiveMode || pPager->journalOff>0)
+ ){
+ pagerUnlockAndRollback(pPager);
+ }
+}
+
+/*
+** Drop a page from the cache using sqlite3PcacheDrop().
+**
+** If this means there are now no pages with references to them, a rollback
+** occurs and the lock on the database is removed.
+*/
+static void pagerDropPage(DbPage *pPg){
+ Pager *pPager = pPg->pPager;
+ sqlite3PcacheDrop(pPg);
+ pagerUnlockIfUnused(pPager);
+}
+
+/*
** Acquire a page.
**
** A read lock on the disk file is obtained when the first page is acquired.
@@ -29902,10 +30710,13 @@ static int pagerAcquire(
DbPage **ppPage, /* Write a pointer to the page here */
int noContent /* Do not bother reading content from disk if true */
){
- PgHdr *pPg;
+ PgHdr *pPg = 0;
int rc;
- assert( pPager->state==PAGER_UNLOCK || pPager->nRef>0 || pgno==1 );
+ 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.
@@ -29929,84 +30740,66 @@ static int pagerAcquire(
}
assert( pPager->state!=PAGER_UNLOCK );
- pPg = pager_lookup(pPager, pgno);
- if( pPg==0 ){
- /* The requested page is not in the page cache. */
+ 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;
- int h;
PAGER_INCR(pPager->nMiss);
- rc = pagerAllocatePage(pPager, &pPg);
- if( rc!=SQLITE_OK ){
- return rc;
+ pPg->pPager = pPager;
+ if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
+ pPg->flags |= PGHDR_IN_JOURNAL;
}
+ memset(pPg->pExtra, 0, pPager->nExtra);
- pPg->pgno = pgno;
- assert( !MEMDB || pgno>pPager->stmtSize );
- pPg->inJournal = sqlite3BitvecTest(pPager->pInJournal, pgno);
- pPg->needSync = 0;
-
- makeClean(pPg);
- pPg->nRef = 1;
-
- pPager->nRef++;
- if( pPager->nExtra>0 ){
- memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra);
- }
rc = sqlite3PagerPagecount(pPager, &nMax);
if( rc!=SQLITE_OK ){
sqlite3PagerUnref(pPg);
return rc;
}
- /* 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);
+ /* sqlite3PagerUnref(pPg); */
+ pagerDropPage(pPg);
return rc;
}
- pPg->needRead = 0;
}
-
- /* Link the page into the page hash table */
- h = pgno & (pPager->nHash-1);
- assert( pgno!=0 );
- pPg->pNextHash = pPager->aHash[h];
- pPager->aHash[h] = pPg;
- if( pPg->pNextHash ){
- assert( pPg->pNextHash->pPrevHash==0 );
- pPg->pNextHash->pPrevHash = pPg;
- }
-
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}else{
/* The requested page is in the page cache. */
- assert(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 ){
+ sqlite3PagerUnref(pPg);
return rc;
}
}
- page_ref(pPg);
}
+
*ppPage = pPg;
return SQLITE_OK;
}
+
SQLITE_PRIVATE int sqlite3PagerAcquire(
Pager *pPager, /* The pager open on the database file */
Pgno pgno, /* Page number to fetch */
@@ -30014,9 +30807,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
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;
}
@@ -30034,19 +30825,15 @@ SQLITE_PRIVATE int sqlite3PagerAcquire(
*/
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);
+ if( (pPager->state!=PAGER_UNLOCK)
+ && (pPager->errCode==SQLITE_OK || pPager->errCode==SQLITE_FULL)
+ ){
+ sqlite3PcacheFetch(pPager->pPCache, pgno, 0, &pPg);
}
- pagerLeave(pPager);
+
return pPg;
}
@@ -30059,39 +30846,11 @@ SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
** 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);
- }
+ if( pPg ){
+ Pager *pPager = pPg->pPager;
+ sqlite3PcacheRelease(pPg);
+ pagerUnlockIfUnused(pPager);
}
- pagerLeave(pPager);
return SQLITE_OK;
}
@@ -30112,9 +30871,7 @@ static int pager_open_journal(Pager *pPager){
assert( pPager->useJournal );
assert( pPager->pInJournal==0 );
sqlite3PagerPagecount(pPager, 0);
- pagerLeave(pPager);
pPager->pInJournal = sqlite3BitvecCreate(pPager->dbSize);
- pagerEnter(pPager);
if( pPager->pInJournal==0 ){
rc = SQLITE_NOMEM;
goto failed_to_open_journal;
@@ -30147,7 +30904,6 @@ static int pager_open_journal(Pager *pPager){
pPager->journalOpen = 1;
pPager->journalStarted = 0;
pPager->needSync = 0;
- pPager->alwaysRollback = 0;
pPager->nRec = 0;
if( pPager->errCode ){
rc = pPager->errCode;
@@ -30204,11 +30960,11 @@ failed_to_open_journal:
SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
Pager *pPager = pPg->pPager;
int rc = SQLITE_OK;
- pagerEnter(pPager);
assert( pPg->nRef>0 );
assert( pPager->state!=PAGER_UNLOCK );
if( pPager->state==PAGER_SHARED ){
assert( pPager->pInJournal==0 );
+ sqlite3PcacheAssertFlags(pPager->pPCache, 0, PGHDR_IN_JOURNAL);
if( MEMDB ){
pPager->state = PAGER_EXCLUSIVE;
pPager->origDbSize = pPager->dbSize;
@@ -30221,7 +30977,6 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
}
}
if( rc!=SQLITE_OK ){
- pagerLeave(pPager);
return rc;
}
pPager->dirtyCache = 0;
@@ -30242,9 +30997,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
assert( pPager->origDbSize==0 );
assert( pPager->pInJournal==0 );
sqlite3PagerPagecount(pPager, 0);
- pagerLeave(pPager);
pPager->pInJournal = sqlite3BitvecCreate( pPager->dbSize );
- pagerEnter(pPager);
if( !pPager->pInJournal ){
rc = SQLITE_NOMEM;
}else{
@@ -30253,7 +31006,6 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
}
}
assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK );
- pagerLeave(pPager);
return rc;
}
@@ -30262,16 +31014,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(DbPage *pPg, int exFlag){
** 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);
}
/*
@@ -30279,20 +31022,7 @@ static void makeDirty(PgHdr *pPg){
** 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);
}
@@ -30314,7 +31044,7 @@ static void makeClean(PgHdr *pPg){
** 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;
@@ -30348,7 +31078,9 @@ static int pager_write(PgHdr *pPg){
** 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{
@@ -30378,17 +31110,14 @@ static int pager_write(PgHdr *pPg){
** EXCLUSIVE lock on the main database file. Write the current page to
** the transaction journal if it is not there already.
*/
- if( !pPg->inJournal && (pPager->journalOpen || MEMDB) ){
+ if( !(pPg->flags&PGHDR_IN_JOURNAL) && (pPager->journalOpen || MEMDB) ){
if( (int)pPg->pgno <= pPager->origDbSize ){
if( MEMDB ){
- PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno);
- assert( pHist->pOrig==0 );
- pHist->pOrig = sqlite3PageMalloc( pPager->pageSize );
- if( !pHist->pOrig ){
- return SQLITE_NOMEM;
+ rc = sqlite3PcachePreserve(pPg, 0);
+ if( rc!=SQLITE_OK ){
+ return rc;
}
- memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
}else{
u32 cksum;
char *pData2;
@@ -30413,7 +31142,8 @@ static int pager_write(PgHdr *pPg){
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));
+ 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.
@@ -30425,20 +31155,25 @@ static int pager_write(PgHdr *pPg){
pPager->nRec++;
assert( pPager->pInJournal!=0 );
sqlite3BitvecSet(pPager->pInJournal, pPg->pgno);
- pPg->needSync = !pPager->noSync;
+ if( !pPager->noSync ){
+ pPg->flags |= PGHDR_NEED_SYNC;
+ }
if( pPager->stmtInUse ){
sqlite3BitvecSet(pPager->pInStmt, pPg->pgno);
}
}
}else{
- pPg->needSync = !pPager->journalStarted && !pPager->noSync;
+ if( !pPager->journalStarted && !pPager->noSync ){
+ pPg->flags |= PGHDR_NEED_SYNC;
+ }
PAGERTRACE4("APPEND %d page %d needSync=%d\n",
- PAGERID(pPager), pPg->pgno, pPg->needSync);
+ PAGERID(pPager), pPg->pgno,
+ ((pPg->flags&PGHDR_NEED_SYNC)?1:0));
}
- if( pPg->needSync ){
+ 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,
@@ -30450,16 +31185,14 @@ static int pager_write(PgHdr *pPg){
&& !pageInStatement(pPg)
&& (int)pPg->pgno<=pPager->stmtSize
){
- assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
+ assert( (pPg->flags&PGHDR_IN_JOURNAL)
+ || (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);
+ rc = sqlite3PcachePreserve(pPg, 1);
+ if( rc!=SQLITE_OK ){
+ return rc;
}
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);
@@ -30507,7 +31240,6 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
Pager *pPager = pPg->pPager;
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
- pagerEnter(pPager);
if( !MEMDB && nPagePerSector>1 ){
Pgno nPageCount; /* Total number of pages in database file */
Pgno pg1; /* First page of the sector pPg is located on. */
@@ -30547,16 +31279,17 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
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);
}
}
@@ -30569,7 +31302,8 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
if( needSync ){
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);
}
@@ -30579,7 +31313,6 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
}else{
rc = pager_write(pDbPage);
}
- pagerLeave(pPager);
return rc;
}
@@ -30590,7 +31323,7 @@ SQLITE_PRIVATE int sqlite3PagerWrite(DbPage *pDbPage){
*/
#ifndef NDEBUG
SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
- return pPg->dirty;
+ return pPg->flags&PGHDR_DIRTY;
}
#endif
@@ -30618,14 +31351,24 @@ SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage *pPg){
** page contains critical data, we still need to be sure it gets
** rolled back in spite of the sqlite3PagerDontRollback() call.
*/
-SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage *pDbPage){
+SQLITE_PRIVATE int sqlite3PagerDontWrite(DbPage *pDbPage){
PgHdr *pPg = pDbPage;
Pager *pPager = pPg->pPager;
+ int rc;
- if( MEMDB ) return;
- pagerEnter(pPager);
- pPg->alwaysRollback = 1;
- if( pPg->dirty && !pPager->stmtInUse ){
+ if( MEMDB || 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
@@ -30639,13 +31382,13 @@ SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage *pDbPage){
}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;
}
/*
@@ -30662,21 +31405,22 @@ SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage *pDbPage){
SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){
Pager *pPager = pPg->pPager;
- pagerEnter(pPager);
assert( pPager->state>=PAGER_RESERVED );
/* If the journal file is not open, or DontWrite() has been called on
** this page (DontWrite() sets the alwaysRollback flag), then this
** function is a no-op.
*/
- if( pPager->journalOpen==0 || pPg->alwaysRollback || pPager->alwaysRollback ){
- pagerLeave(pPager);
+ if( pPager->journalOpen==0
+ || sqlite3BitvecTest(pPager->pAlwaysRollback, pPg->pgno)
+ || pPg->pgno>pPager->origDbSize
+ ){
return;
}
assert( !MEMDB ); /* For a memdb, pPager->journalOpen is always 0 */
#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
@@ -30695,15 +31439,14 @@ SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage *pPg){
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);
}
@@ -30735,11 +31478,11 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){
/* Increment the value just read and write it back to byte 24. */
change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
change_counter++;
- put32bits(((char*)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
@@ -30756,9 +31499,11 @@ static int pager_incr_changecounter(Pager *pPager, int isDirect){
*/
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;
}
@@ -30807,7 +31552,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n",
pPager->zFilename, zMaster, nTrunc);
- pagerEnter(pPager);
/* If this is an in-memory db, or no pages have been written to, or this
** function has already been called, it is a no-op.
@@ -30827,12 +31571,13 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
** If the optimization can be used, then the journal file will never
** be created for this transaction.
*/
+ pPg = sqlite3PcacheDirtyList(pPager->pPCache);
int 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 ){
@@ -30901,7 +31646,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
#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 );
@@ -30914,7 +31659,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
*/
goto sync_exit;
}
- pPager->pDirty = 0;
+ sqlite3PcacheCleanAll(pPager->pPCache);
/* Sync the database file. */
if( !pPager->noSync && !noSync ){
@@ -30936,7 +31681,6 @@ sync_exit:
*/
rc = SQLITE_BUSY;
}
- pagerLeave(pPager);
return rc;
}
@@ -30949,8 +31693,7 @@ sync_exit:
** is returned.
*/
SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
- int rc;
- PgHdr *pPg;
+ int rc = SQLITE_OK;
if( pPager->errCode ){
return pPager->errCode;
@@ -30964,38 +31707,19 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
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;
+ sqlite3PcacheCommit(pPager->pPCache, 0);
+ sqlite3PcacheCleanAll(pPager->pPCache);
+ sqlite3PcacheSetFlags(pPager->pPCache,
+ ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
+ );
pPager->state = PAGER_SHARED;
- pagerLeave(pPager);
- return SQLITE_OK;
+ }else{
+ assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
+ rc = pager_end_transaction(pPager, pPager->setMaster);
+ rc = pager_error(pPager, rc);
}
- assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache );
- rc = pager_end_transaction(pPager, pPager->setMaster);
- rc = pager_error(pPager, rc);
- pagerLeave(pPager);
return rc;
}
@@ -31012,77 +31736,46 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
** 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;
+ sqlite3PcacheRollback(pPager->pPCache, 1);
+ sqlite3PcacheRollback(pPager->pPCache, 0);
+ sqlite3PcacheCleanAll(pPager->pPCache);
+ sqlite3PcacheSetFlags(pPager->pPCache,
+ ~(PGHDR_IN_JOURNAL | PGHDR_NEED_SYNC), 0
+ );
pPager->dbSize = pPager->origDbSize;
pager_truncate_cache(pPager);
pPager->stmtInUse = 0;
pPager->state = PAGER_SHARED;
- return SQLITE_OK;
- }
-
- pagerEnter(pPager);
- if( !pPager->dirtyCache || !pPager->journalOpen ){
+ }else 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;
- }
+ rc = pPager->errCode;
}else{
- rc = pager_playback(pPager, 0);
- }
- /* pager_reset(pPager); */
- pPager->dbSize = -1;
+ 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 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);
+ 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;
}
@@ -31098,7 +31791,7 @@ SQLITE_PRIVATE int sqlite3PagerIsreadonly(Pager *pPager){
** Return the number of references to the pager.
*/
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
- return pPager->nRef;
+ return sqlite3PcacheRefCount(pPager->pPCache);
}
#ifdef SQLITE_TEST
@@ -31107,9 +31800,9 @@ SQLITE_PRIVATE int sqlite3PagerRefcount(Pager *pPager){
*/
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;
@@ -31148,10 +31841,8 @@ static int pagerStmtBegin(Pager *pPager){
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;
@@ -31180,9 +31871,7 @@ stmt_begin_failed:
}
SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager *pPager){
int rc;
- pagerEnter(pPager);
rc = pagerStmtBegin(pPager);
- pagerLeave(pPager);
return rc;
}
@@ -31190,31 +31879,19 @@ SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager *pPager){
** Commit a statement.
*/
SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager *pPager){
- pagerEnter(pPager);
if( pPager->stmtInUse ){
- PgHdr *pPg, *pNext;
PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager));
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;
- }
+ sqlite3PcacheCommit(pPager->pPCache, 1);
}
pPager->stmtNRec = 0;
pPager->stmtInUse = 0;
- pPager->pStmt = 0;
}
pPager->stmtAutoopen = 0;
- pagerLeave(pPager);
return SQLITE_OK;
}
@@ -31223,20 +31900,10 @@ SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager *pPager){
*/
SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager *pPager){
int rc;
- pagerEnter(pPager);
if( pPager->stmtInUse ){
PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager));
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;
- }
- }
+ sqlite3PcacheRollback(pPager->pPCache, 1);
pPager->dbSize = pPager->stmtSize;
pager_truncate_cache(pPager);
rc = SQLITE_OK;
@@ -31248,7 +31915,6 @@ SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager *pPager){
rc = SQLITE_OK;
}
pPager->stmtAutoopen = 0;
- pagerLeave(pPager);
return rc;
}
@@ -31336,14 +32002,12 @@ SQLITE_PRIVATE void sqlite3PagerSetCodec(
*/
SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
PgHdr *pPgOld; /* The page being overwritten. */
- int h;
Pgno needSyncPgno = 0;
- pagerEnter(pPager);
assert( pPg->nRef>0 );
PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n",
- PAGERID(pPager), pPg->pgno, pPg->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);
@@ -31355,44 +32019,33 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
** the journal needs to be sync()ed before database page pPg->pgno
** can be written to. The caller has already promised not to write to it.
*/
- if( pPg->needSync && !isCommit ){
+ 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 ){
- assert( pPgOld->nRef==0 );
- unlinkHashChain(pPager, pPgOld);
- makeClean(pPgOld);
- pPg->needSync = pPgOld->needSync;
- }else{
- pPg->needSync = 0;
+ pPg->flags |= (pPgOld->flags&PGHDR_NEED_SYNC);
+ }
+ if( sqlite3BitvecTest(pPager->pInJournal, pgno) ){
+ pPg->flags |= PGHDR_IN_JOURNAL;
}
- 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;
+ sqlite3PcacheMove(pPg, pgno);
+ if( pPgOld ){
+ sqlite3PcacheMove(pPgOld, 0);
+ sqlite3PcacheRelease(pPgOld);
}
- pPg->pNextHash = pPager->aHash[h];
- pPager->aHash[h] = pPg;
- pPg->pPrevHash = 0;
makeDirty(pPg);
pPager->dirtyCache = 1;
@@ -31424,17 +32077,15 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
if( pPager->pInJournal && (int)needSyncPgno<=pPager->origDbSize ){
sqlite3BitvecClear(pPager->pInJournal, needSyncPgno);
}
- pagerLeave(pPager);
return rc;
}
pPager->needSync = 1;
- pPgHdr->needSync = 1;
- pPgHdr->inJournal = 1;
+ pPgHdr->flags |= PGHDR_NEED_SYNC;
+ pPgHdr->flags |= PGHDR_IN_JOURNAL;
makeDirty(pPgHdr);
sqlite3PagerUnref(pPgHdr);
}
- pagerLeave(pPager);
return SQLITE_OK;
}
#endif
@@ -31443,7 +32094,8 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
** Return a pointer to the data for the specified page.
*/
SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
- return PGHDR_TO_DATA(pPg);
+ assert( pPg->nRef>0 );
+ return pPg->pData;
}
/*
@@ -31452,7 +32104,7 @@ SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *pPg){
*/
SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *pPg){
Pager *pPager = pPg->pPager;
- return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0);
+ return (pPager?pPg->pExtra:0);
}
/*
@@ -32836,7 +33488,7 @@ SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur){
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;
@@ -33156,7 +33808,7 @@ static void defragmentPage(MemPage *pPage){
int size; /* Size of a cell */
int usableSize; /* Number of usable bytes on a page */
int cellOffset; /* Offset to the cell pointer array */
- int 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 */
@@ -33173,26 +33825,26 @@ static void defragmentPage(MemPage *pPage){
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);
+ cbrk -= size;
+ memcpy(&data[cbrk], &temp[pc], size);
+ put2byte(pAddr, cbrk);
}
- assert( brk>=cellOffset+2*nCell );
- put2byte(&data[hdr+5], brk);
+ 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);
}
/*
@@ -33593,18 +34245,19 @@ static void releasePage(MemPage *pPage){
** reaches zero. We need to unref the pParent pointer when that
** happens.
*/
-static void pageDestructor(DbPage *pData, int pageSize){
+static void pageDestructor(DbPage *pData){
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);
+ if( pPage ){
+ assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) );
+ if( pPage->pParent ){
+ MemPage *pParent = pPage->pParent;
+ assert( pParent->pBt==pPage->pBt );
+ pPage->pParent = 0;
+ releasePage(pParent);
+ }
+ pPage->isInit = 0;
}
- pPage->isInit = 0;
}
/*
@@ -33748,7 +34401,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
}
pBt->busyHdr.xFunc = sqlite3BtreeInvokeBusyHandler;
pBt->busyHdr.pArg = pBt;
- rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
+ rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename, pageDestructor,
EXTRA_SIZE, flags, vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
@@ -33759,7 +34412,6 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
sqlite3PagerSetBusyhandler(pBt->pPager, &pBt->busyHdr);
p->pBt = pBt;
- sqlite3PagerSetDestructor(pBt->pPager, pageDestructor);
sqlite3PagerSetReiniter(pBt->pPager, pageReinit);
pBt->pCursor = 0;
pBt->pPage1 = 0;
@@ -35949,6 +36601,7 @@ SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur){
assert( !sqlite3BtreeIsRootPage(pPage) );
pParent = pPage->pParent;
assert( pParent!=0 );
+ assert( pPage->pDbPage->nRef>0 );
idxParent = pPage->idxParent;
sqlite3PagerRef(pParent->pDbPage);
releasePage(pPage);
@@ -36109,12 +36762,11 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
}
/* Move the cursor so that it points to an entry near the key
-** specified by pKey/nKey/pUnKey. Return a success code.
+** specified by pIdxKey or intKey. 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.
+** 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
@@ -36136,16 +36788,14 @@ SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
** 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 */
+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;
- char aSpace[200];
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
@@ -36153,11 +36803,11 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto(
/* 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->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;
}
@@ -36175,24 +36825,7 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto(
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->pPage->intKey || pIdxKey );
for(;;){
int lwr, upr;
Pgno chldPg;
@@ -36200,7 +36833,7 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto(
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;
}
@@ -36222,12 +36855,12 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto(
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{
@@ -36235,7 +36868,7 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto(
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 ){
@@ -36243,7 +36876,7 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto(
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;
}
@@ -36293,10 +36926,35 @@ SQLITE_PRIVATE int sqlite3BtreeMoveto(
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;
}
@@ -36802,7 +37460,7 @@ static int freePage(MemPage *pPage){
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));
@@ -38109,7 +38767,7 @@ static int balance_deeper(MemPage *pPage){
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 */
+ int cbrk; /* Offset to content of first cell in parent */
assert( pPage->pParent==0 );
assert( pPage->nOverflow>0 );
@@ -38121,10 +38779,10 @@ static int balance_deeper(MemPage *pPage){
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);
+ memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
if( pChild->isInit ) return SQLITE_CORRUPT;
rc = sqlite3BtreeInitPage(pChild, pPage);
if( rc ) goto balancedeeper_out;
@@ -38297,7 +38955,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
clearCursorPosition(pCur);
if(
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
- SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc))
+ SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
){
return rc;
}
@@ -39213,8 +39871,11 @@ static int checkTreePage(
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);
@@ -39491,7 +40152,7 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
** page is still on the rollback journal, though. And that is the
** whole point of this block: to put pages on the rollback journal.
*/
- sqlite3PagerDontWrite(pDbPage);
+ rc = sqlite3PagerDontWrite(pDbPage);
}
sqlite3PagerUnref(pDbPage);
}
@@ -39600,7 +40261,7 @@ static int btreeCopyFile(Btree *pTo, Btree *pFrom){
rc = sqlite3PagerGet(pBtFrom->pPager, iFrom, &pFromPage);
if( rc==SQLITE_OK ){
char *zFrom = sqlite3PagerGetData(pFromPage);
- rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
+ rc = sqlite3OsWrite(pFile, zFrom, nFromPageSize, iOff);
sqlite3PagerUnref(pFromPage);
}
}
@@ -40158,12 +40819,11 @@ SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
sqlite3_context ctx;
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ memset(&ctx, 0, sizeof(ctx));
ctx.s.flags = MEM_Null;
ctx.s.db = pMem->db;
- ctx.s.zMalloc = 0;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
- ctx.isError = 0;
pFunc->xFinalize(&ctx);
assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
sqlite3DbFree(pMem->db, pMem->zMalloc);
@@ -42812,9 +43472,8 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(Cursor *p){
extern int sqlite3_search_count;
#endif
assert( p->isTable );
- rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
+ rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
- *p->pIncrKey = 0;
p->lastRowid = keyToInt(p->movetoTarget);
p->rowidIsValid = res==0;
if( res<0 ){
@@ -43161,7 +43820,7 @@ 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;
@@ -43177,14 +43836,13 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
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;
@@ -43202,6 +43860,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
pMem++;
u++;
}
+ assert( u<=pKeyInfo->nField + 1 );
p->nField = u;
return (void*)p;
}
@@ -43211,7 +43870,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeRecordUnpack(
*/
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++){
@@ -43220,7 +43879,7 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
}
}
}
- if( p->needFree ){
+ if( p->flags & UNPACKED_NEED_FREE ){
sqlite3DbFree(p->pKeyInfo->db, p);
}
}
@@ -43229,25 +43888,32 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
/*
** This function compares the two table rows or index records
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
-** or positive integer if {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 */
@@ -43267,6 +43933,9 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
+ if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){
+ szHdr1--;
+ }
nField = pKeyInfo->nField;
while( idx1<szHdr1 && i<pPKey2->nField ){
u32 serial_type1;
@@ -43290,17 +43959,21 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
}
if( mem1.zMalloc ) sqlite3VdbeMemRelease(&mem1);
- /* One of the keys ran out of fields, but all the fields up to that point
- ** were equal. If the incrKey flag is true, then the second key is
- ** treated as larger.
- */
if( rc==0 ){
- 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] ){
@@ -43309,26 +43982,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
return rc;
}
-
-/*
-** The argument is an index entry composed using the OP_MakeRecord opcode.
-** The last entry in this record should be an integer (specifically
-** an integer rowid). This routine returns the number of bytes in
-** that integer.
-*/
-SQLITE_PRIVATE int sqlite3VdbeIdxRowidLen(const u8 *aKey, int nKey, int *pRowidLen){
- u32 szHdr; /* Size of the header */
- u32 typeRowid; /* Serial type of the rowid */
-
- (void)getVarint32(aKey, szHdr);
- if( szHdr>nKey ){
- return SQLITE_CORRUPT_BKPT;
- }
- (void)getVarint32(&aKey[szHdr-1], typeRowid);
- *pRowidLen = sqlite3VdbeSerialTypeLen(typeRowid);
- return SQLITE_OK;
-}
-
+
/*
** pCur points at an index entry created using the OP_MakeRecord opcode.
@@ -43371,21 +44025,21 @@ SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
**
** pKey is either created without a rowid or is truncated so that it
** omits the rowid at the end. The rowid at the end of the index entry
-** is ignored as well.
+** 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];
sqlite3BtreeKeySize(pCur, &nCellKey);
if( nCellKey<=0 ){
@@ -43395,24 +44049,12 @@ SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(
m.db = 0;
m.flags = 0;
m.zMalloc = 0;
- if( (rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m))
- || (rc = sqlite3VdbeIdxRowidLen((u8*)m.z, m.n, &lenRowid))
- ){
+ rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
+ if( rc ){
return rc;
}
- 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;
}
@@ -43479,7 +44121,7 @@ SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe *v){
** $Id$
*/
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+#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
@@ -43894,7 +44536,9 @@ static int sqlite3Step(Vdbe *p){
/* Assert that malloc() has not failed */
db = p->db;
- assert( !db->mallocFailed );
+ if( db->mallocFailed ){
+ return SQLITE_NOMEM;
+ }
if( p->pc<=0 && p->expired ){
if( p->rc==SQLITE_OK ){
@@ -45382,6 +46026,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif
+ UnpackedRecord aTempRec[16]; /* Space to hold a transient UnpackedRecord */
+
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
assert( db->magic==SQLITE_MAGIC_BUSY );
@@ -47532,11 +48178,9 @@ case OP_OpenWrite: {
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor);
if( pOp->p4type==P4_KEYINFO ){
pCur->pKeyInfo = pOp->p4.pKeyInfo;
- pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
pCur->pKeyInfo->enc = ENC(p->db);
}else{
pCur->pKeyInfo = 0;
- pCur->pIncrKey = &pCur->bogusIncrKey;
}
switch( rc ){
case SQLITE_BUSY: {
@@ -47636,13 +48280,11 @@ case OP_OpenEphemeral: {
(KeyInfo*)pOp->p4.z, pCx->pCursor);
pCx->pKeyInfo = pOp->p4.pKeyInfo;
pCx->pKeyInfo->enc = ENC(p->db);
- pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
}
pCx->isTable = 0;
}else{
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
pCx->isTable = 1;
- pCx->pIncrKey = &pCx->bogusIncrKey;
}
}
pCx->isIndex = !pCx->isTable;
@@ -47678,7 +48320,6 @@ case OP_OpenPseudo: {
pCx->nullRow = 1;
pCx->pseudoTable = 1;
pCx->ephemPseudoTable = pOp->p2;
- pCx->pIncrKey = &pCx->bogusIncrKey;
pCx->isTable = 1;
pCx->isIndex = 0;
break;
@@ -47770,7 +48411,6 @@ case OP_MoveGt: { /* jump, in3 */
int res, oc;
oc = pOp->opcode;
pC->nullRow = 0;
- *pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
if( pC->isTable ){
i64 iKey = sqlite3VdbeIntValue(pIn3);
if( pOp->p2==0 ){
@@ -47780,7 +48420,7 @@ case OP_MoveGt: { /* jump, in3 */
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;
}
@@ -47793,10 +48433,13 @@ case OP_MoveGt: { /* jump, in3 */
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;
}
@@ -47804,7 +48447,6 @@ case OP_MoveGt: { /* jump, in3 */
}
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
- *pC->pIncrKey = 0;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
@@ -47862,7 +48504,7 @@ case OP_MoveGt: { /* jump, in3 */
** in the record in register P3, where N is the total number of values in
** the P3 record (the P3 record is a prefix of the P1 record).
**
-** See also: NotFound, MoveTo, IsUnique, NotExists
+** See also: NotFound, IsUnique, NotExists
*/
/* Opcode: NotFound P1 P2 P3 * *
**
@@ -47871,7 +48513,7 @@ case OP_MoveGt: { /* jump, in3 */
** to P2. If an entry does existing, fall through. The cursor is left
** pointing to the entry that matches.
**
-** See also: Found, MoveTo, NotExists, IsUnique
+** See also: Found, NotExists, IsUnique
*/
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
@@ -47882,13 +48524,20 @@ case OP_Found: { /* jump, in3 */
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;
+ pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
}
- rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
- pC->pKeyInfo->prefixIsEqual = 0;
+ rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
if( rc!=SQLITE_OK ){
break;
}
@@ -47908,7 +48557,7 @@ case OP_Found: { /* jump, in3 */
**
** The P3 register contains an integer record number. Call this
** record number R. The P4 register contains an index key created
-** using 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
@@ -47944,45 +48593,39 @@ case OP_IsUnique: { /* jump, in3 */
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;
-
- /* sqlite3VdbeIdxRowidLen() only returns other than SQLITE_OK when the
- ** record passed as an argument corrupt. Since the record in this case
- ** has just been created by an OP_MakeRecord instruction, and not loaded
- ** from the database file, it is not possible for it to be corrupt.
- ** Therefore, assert(rc==SQLITE_OK).
- */
- rc = sqlite3VdbeIdxRowidLen((u8*)zKey, nKey, &szRowid);
- assert(rc==SQLITE_OK);
- len = nKey-szRowid;
+ 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 four bytes match K.
+ /* 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;
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
break;
}
}
- rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res);
+ rc = sqlite3VdbeIdxKeyCompare(pCx, pIdxKey, &res);
+ sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res>0 ){
pc = pOp->p2 - 1;
@@ -48025,7 +48668,7 @@ case OP_IsUnique: { /* jump, in3 */
** 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;
@@ -48039,7 +48682,7 @@ case OP_NotExists: { /* jump, in3 */
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;
@@ -48216,7 +48859,7 @@ case OP_NewRowid: { /* out2-prerelease */
}
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;
@@ -48712,10 +49355,9 @@ case OP_IdxDelete: {
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);
}
@@ -48798,12 +49440,13 @@ case OP_IdxGE: { /* jump, in3 */
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{
@@ -48966,9 +49609,10 @@ case OP_ParseSchema: {
(void)sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
+ initData.rc = SQLITE_OK;
assert( !db->mallocFailed );
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
- if( rc==SQLITE_ABORT ) rc = initData.rc;
+ if( rc==SQLITE_OK ) rc = initData.rc;
sqlite3DbFree(db, zSql);
db->init.busy = 0;
(void)sqlite3SafetyOn(db);
@@ -50535,6 +51179,1289 @@ SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *pVfs){
#endif
/************** End of journal.c *********************************************/
+/************** Begin file walker.c ******************************************/
+/*
+** 2008 August 16
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains routines used for walking the parser tree for
+** an SQL statement.
+**
+** $Id$
+*/
+
+
+/*
+** Walk an expression tree. Invoke the callback once for each node
+** of the expression, while decending. (In other words, the callback
+** is invoked before visiting children.)
+**
+** The return value from the callback should be one of the WRC_*
+** constants to specify how to proceed with the walk.
+**
+** WRC_Continue Continue descending down the tree.
+**
+** WRC_Prune Do not descend into child nodes. But allow
+** the walk to continue with sibling nodes.
+**
+** WRC_Abort Do no more callbacks. Unwind the stack and
+** return the top-level walk call.
+**
+** The return value from this routine is WRC_Abort to abandon the tree walk
+** and WRC_Continue to continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
+ int rc;
+ if( pExpr==0 ) return WRC_Continue;
+ rc = pWalker->xExprCallback(pWalker, pExpr);
+ if( rc==WRC_Continue ){
+ if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, pExpr->pList) ) return WRC_Abort;
+ if( sqlite3WalkSelect(pWalker, pExpr->pSelect) ){
+ return WRC_Abort;
+ }
+ }
+ return rc & WRC_Abort;
+}
+
+/*
+** Call sqlite3WalkExpr() for every expression in list p or until
+** an abort request is seen.
+*/
+SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
+ int i, rc = WRC_Continue;
+ struct ExprList_item *pItem;
+ if( p ){
+ for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+ if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
+ }
+ }
+ return rc & WRC_Continue;
+}
+
+/*
+** Walk all expressions associated with SELECT statement p. Do
+** not invoke the SELECT callback on p, but do (of course) invoke
+** any expr callbacks and SELECT callbacks that come from subqueries.
+** Return WRC_Abort or WRC_Continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
+ if( sqlite3WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
+ if( sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
+ if( sqlite3WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
+ return WRC_Continue;
+}
+
+/*
+** Walk the parse trees associated with all subqueries in the
+** FROM clause of SELECT statement p. Do not invoke the select
+** callback on p, but do invoke it on each FROM clause subquery
+** and on any subqueries further down in the tree. Return
+** WRC_Abort or WRC_Continue;
+*/
+SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
+ SrcList *pSrc;
+ int i;
+ struct SrcList_item *pItem;
+
+ pSrc = p->pSrc;
+ if( pSrc ){
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
+ if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
+ return WRC_Abort;
+ }
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
+** Call sqlite3WalkExpr() for every expression in Select statement p.
+** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
+** on the compound select chain, p->pPrior.
+**
+** Return WRC_Continue under normal conditions. Return WRC_Abort if
+** there is an abort request.
+**
+** If the Walker does not have an xSelectCallback() then this routine
+** is a no-op returning WRC_Continue.
+*/
+SQLITE_PRIVATE int sqlite3WalkSelect(Walker *pWalker, Select *p){
+ int rc;
+ if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
+ rc = WRC_Continue;
+ while( p ){
+ rc = pWalker->xSelectCallback(pWalker, p);
+ if( rc ) break;
+ if( sqlite3WalkSelectExpr(pWalker, p) ) return WRC_Abort;
+ if( sqlite3WalkSelectFrom(pWalker, p) ) return WRC_Abort;
+ p = p->pPrior;
+ }
+ return rc & WRC_Abort;
+}
+
+/************** End of walker.c **********************************************/
+/************** Begin file resolve.c *****************************************/
+/*
+** 2008 August 18
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** This file contains routines used for walking the parser tree and
+** resolve all identifiers by associating them with a particular
+** table and column.
+**
+** $Id$
+*/
+
+/*
+** Turn the pExpr expression into an alias for the iCol-th column of the
+** result set in pEList.
+**
+** If the result set column is a simple column reference, then this routine
+** makes an exact copy. But for any other kind of expression, this
+** routine make a copy of the result set column as the argument to the
+** TK_AS operator. The TK_AS operator causes the expression to be
+** evaluated just once and then reused for each alias.
+**
+** The reason for suppressing the TK_AS term when the expression is a simple
+** column reference is so that the column reference will be recognized as
+** usable by indices within the WHERE clause processing logic.
+**
+** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
+** that in a GROUP BY clause, the expression is evaluated twice. Hence:
+**
+** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
+**
+** Is equivalent to:
+**
+** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
+**
+** The result of random()%5 in the GROUP BY clause is probably different
+** from the result in the result-set. We might fix this someday. Or
+** then again, we might not...
+*/
+static void resolveAlias(
+ Parse *pParse, /* Parsing context */
+ ExprList *pEList, /* A result set */
+ int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
+ Expr *pExpr, /* Transform this into an alias to the result set */
+ const char *zType /* "GROUP" or "ORDER" or "" */
+){
+ Expr *pOrig; /* The iCol-th column of the result set */
+ Expr *pDup; /* Copy of pOrig */
+ sqlite3 *db; /* The database connection */
+
+ assert( iCol>=0 && iCol<pEList->nExpr );
+ pOrig = pEList->a[iCol].pExpr;
+ assert( pOrig!=0 );
+ assert( pOrig->flags & EP_Resolved );
+ db = pParse->db;
+ pDup = sqlite3ExprDup(db, pOrig);
+ if( pDup==0 ) return;
+ if( pDup->op!=TK_COLUMN && zType[0]!='G' ){
+ pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
+ if( pDup==0 ) return;
+ if( pEList->a[iCol].iAlias==0 ){
+ pEList->a[iCol].iAlias = ++pParse->nAlias;
+ }
+ pDup->iTable = pEList->a[iCol].iAlias;
+ }
+ if( pExpr->flags & EP_ExpCollate ){
+ pDup->pColl = pExpr->pColl;
+ pDup->flags |= EP_ExpCollate;
+ }
+ if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
+ if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
+ memcpy(pExpr, pDup, sizeof(*pExpr));
+ sqlite3DbFree(db, pDup);
+}
+
+/*
+** 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;
+ 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 ){
+ /* 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
@@ -50579,6 +52506,14 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
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;
}
@@ -50589,11 +52524,11 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
** flag. An explicit collating sequence will override implicit
** collating sequences.
*/
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){
+SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){
char *zColl = 0; /* Dequoted name of collation sequence */
CollSeq *pColl;
sqlite3 *db = pParse->db;
- zColl = sqlite3NameFromToken(db, pName);
+ zColl = sqlite3NameFromToken(db, pCollName);
if( pExpr && zColl ){
pColl = sqlite3LocateCollSeq(pParse, zColl, -1);
if( pColl ){
@@ -50611,13 +52546,29 @@ SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName
*/
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;
@@ -50796,7 +52747,7 @@ static int codeCompare(
** 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 ){
@@ -50868,7 +52819,7 @@ static void exprSetHeight(Expr *p){
*/
SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){
exprSetHeight(p);
- checkExprHeight(pParse, p->nHeight);
+ sqlite3ExprCheckHeight(pParse, p->nHeight);
}
/*
@@ -50881,7 +52832,6 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){
return nHeight;
}
#else
- #define checkExprHeight(x,y)
#define exprSetHeight(y)
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
@@ -50949,7 +52899,7 @@ SQLITE_PRIVATE Expr *sqlite3PExpr(
){
Expr *p = sqlite3Expr(pParse->db, op, pLeft, pRight, pToken);
if( p ){
- checkExprHeight(pParse, p->nHeight);
+ sqlite3ExprCheckHeight(pParse, p->nHeight);
}
return p;
}
@@ -51142,7 +53092,6 @@ SQLITE_PRIVATE void sqlite3DequoteExpr(sqlite3 *db, Expr *p){
sqlite3Dequote((char*)p->token.z);
}
-
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
@@ -51213,8 +53162,9 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){
|| db->mallocFailed );
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->sortOrder = pOldItem->sortOrder;
- pItem->isAgg = pOldItem->isAgg;
pItem->done = 0;
+ pItem->iCol = pOldItem->iCol;
+ pItem->iAlias = pOldItem->iAlias;
}
return pNew;
}
@@ -51282,7 +53232,6 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p){
if( p==0 ) return 0;
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
if( pNew==0 ) return 0;
- pNew->isDistinct = p->isDistinct;
pNew->pEList = sqlite3ExprListDup(db, p->pEList);
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc);
pNew->pWhere = sqlite3ExprDup(db, p->pWhere);
@@ -51295,10 +53244,7 @@ SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3 *db, Select *p){
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;
@@ -51347,6 +53293,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(
memset(pItem, 0, sizeof(*pItem));
pItem->zName = sqlite3NameFromToken(db, pName);
pItem->pExpr = pExpr;
+ pItem->iAlias = 0;
}
return pList;
@@ -51392,92 +53339,33 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *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.
+** 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.
**
-** 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().
+** These callback routines are used to implement the following:
**
-** 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.
+** sqlite3ExprIsConstant()
+** sqlite3ExprIsConstantNotJoin()
+** sqlite3ExprIsConstantOrFunction()
**
-** 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;
+static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
- /* If *pArg is 3 then any term of the expression that comes from
+ /* 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:
@@ -51495,17 +53383,24 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){
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
@@ -51516,9 +53411,7 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){
** a constant.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
- int isConst = 1;
- walkExprTree(p, exprNodeIsConstant, &isConst);
- return isConst;
+ return exprIsConst(p, 1);
}
/*
@@ -51528,9 +53421,7 @@ SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr *p){
** 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);
}
/*
@@ -51543,9 +53434,7 @@ SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
** a constant.
*/
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr *p){
- int isConst = 2;
- walkExprTree(p, exprNodeIsConstant, &isConst);
- return isConst!=0;
+ return exprIsConst(p, 2);
}
/*
@@ -51597,554 +53486,6 @@ SQLITE_PRIVATE int sqlite3IsRowid(const char *z){
return 0;
}
-/*
-** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
-** that name in the set of source tables in pSrcList and make the pExpr
-** expression node refer back to that source column. The following changes
-** are made to pExpr:
-**
-** pExpr->iDb Set the index in db->aDb[] of the database holding
-** the table.
-** pExpr->iTable Set to the cursor number for the table obtained
-** from pSrcList.
-** pExpr->iColumn Set to the column number within the table.
-** pExpr->op Set to TK_COLUMN.
-** pExpr->pLeft Any expression this points to is deleted
-** pExpr->pRight Any expression this points to is deleted.
-**
-** The pDbToken is the name of the database (the "X"). This value may be
-** NULL meaning that name is of the form Y.Z or Z. Any available database
-** can be used. The pTableToken is the name of the table (the "Y"). This
-** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it
-** means that the form of the name is Z and that columns from any table
-** can be used.
-**
-** If the name cannot be resolved unambiguously, leave an error message
-** in pParse and return non-zero. Return zero on success.
-*/
-static int lookupName(
- Parse *pParse, /* The parsing context */
- Token *pDbToken, /* Name of the database containing table, or NULL */
- Token *pTableToken, /* Name of table containing column, or NULL */
- Token *pColumnToken, /* Name of the column. */
- NameContext *pNC, /* The name context used to resolve the name */
- Expr *pExpr /* Make this EXPR node point to the selected column */
-){
- char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
- char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */
- char *zCol = 0; /* Name of the column. The "Z" */
- int i, j; /* Loop counters */
- int cnt = 0; /* Number of matching column names */
- int cntTab = 0; /* Number of matching table names */
- sqlite3 *db = pParse->db; /* The database */
- struct SrcList_item *pItem; /* Use for looping over pSrcList items */
- struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
- NameContext *pTopNC = pNC; /* First namecontext in the list */
- Schema *pSchema = 0; /* Schema of the expression */
-
- assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
- zDb = sqlite3NameFromToken(db, pDbToken);
- zTab = sqlite3NameFromToken(db, pTableToken);
- zCol = sqlite3NameFromToken(db, pColumnToken);
- if( db->mallocFailed ){
- goto lookupname_end;
- }
-
- pExpr->iTable = -1;
- while( pNC && cnt==0 ){
- ExprList *pEList;
- SrcList *pSrcList = pNC->pSrcList;
-
- if( pSrcList ){
- for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
- Table *pTab;
- int iDb;
- Column *pCol;
-
- pTab = pItem->pTab;
- assert( pTab!=0 );
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( pTab->nCol>0 );
- if( zTab ){
- if( pItem->zAlias ){
- char *zTabName = pItem->zAlias;
- if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- }else{
- char *zTabName = pTab->zName;
- if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
- continue;
- }
- }
- }
- if( 0==(cntTab++) ){
- pExpr->iTable = pItem->iCursor;
- pSchema = pTab->pSchema;
- pMatch = pItem;
- }
- for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- const char *zColl = pTab->aCol[j].zColl;
- IdList *pUsing;
- cnt++;
- pExpr->iTable = pItem->iCursor;
- pMatch = pItem;
- pSchema = pTab->pSchema;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->affinity = pTab->aCol[j].affinity;
- if( (pExpr->flags & EP_ExpCollate)==0 ){
- pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
- }
- if( i<pSrcList->nSrc-1 ){
- if( pItem[1].jointype & JT_NATURAL ){
- /* If this match occurred in the left table of a natural join,
- ** then skip the right table to avoid a duplicate match */
- pItem++;
- i++;
- }else if( (pUsing = pItem[1].pUsing)!=0 ){
- /* If this match occurs on a column that is in the USING clause
- ** of a join, skip the search of the right table of the join
- ** to avoid a duplicate match there. */
- int k;
- for(k=0; k<pUsing->nId; k++){
- if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
- pItem++;
- i++;
- break;
- }
- }
- }
- }
- break;
- }
- }
- }
- }
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* If we have not already resolved the name, then maybe
- ** it is a new.* or old.* trigger argument reference
- */
- if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
- TriggerStack *pTriggerStack = pParse->trigStack;
- Table *pTab = 0;
- u32 *piColMask;
- if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->newIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- piColMask = &(pTriggerStack->newColMask);
- }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
- pExpr->iTable = pTriggerStack->oldIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- piColMask = &(pTriggerStack->oldColMask);
- }
-
- if( pTab ){
- int iCol;
- Column *pCol = pTab->aCol;
-
- pSchema = pTab->pSchema;
- cntTab++;
- for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) {
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- const char *zColl = pTab->aCol[iCol].zColl;
- cnt++;
- pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol;
- pExpr->affinity = pTab->aCol[iCol].affinity;
- if( (pExpr->flags & EP_ExpCollate)==0 ){
- pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
- }
- pExpr->pTab = pTab;
- if( iCol>=0 ){
- testcase( iCol==31 );
- testcase( iCol==32 );
- *piColMask |= ((u32)1<<iCol) | (iCol>=32?0xffffffff:0);
- }
- break;
- }
- }
- }
- }
-#endif /* !defined(SQLITE_OMIT_TRIGGER) */
-
- /*
- ** Perhaps the name is a reference to the ROWID
- */
- if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
- cnt = 1;
- pExpr->iColumn = -1;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- }
-
- /*
- ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
- ** might refer to an result-set alias. This happens, for example, when
- ** we are resolving names in the WHERE clause of the following command:
- **
- ** SELECT a+b AS x FROM table WHERE x<10;
- **
- ** In cases like this, replace pExpr with a copy of the expression that
- ** forms the result set entry ("a+b" in the example) and return immediately.
- ** Note that the expression in the result set should have already been
- ** resolved by the time the WHERE clause is resolved.
- */
- if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
- for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- Expr *pDup, *pOrig;
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- assert( pExpr->pList==0 );
- assert( pExpr->pSelect==0 );
- pOrig = pEList->a[j].pExpr;
- if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
- sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
- sqlite3DbFree(db, zCol);
- return 2;
- }
- pDup = sqlite3ExprDup(db, pOrig);
- if( pExpr->flags & EP_ExpCollate ){
- pDup->pColl = pExpr->pColl;
- pDup->flags |= EP_ExpCollate;
- }
- if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
- if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
- memcpy(pExpr, pDup, sizeof(*pExpr));
- sqlite3DbFree(db, pDup);
- cnt = 1;
- pMatch = 0;
- assert( zTab==0 && zDb==0 );
- goto lookupname_end_2;
- }
- }
- }
-
- /* Advance to the next name context. The loop will exit when either
- ** we have a match (cnt>0) or when we run out of name contexts.
- */
- if( cnt==0 ){
- pNC = pNC->pNext;
- }
- }
-
- /*
- ** If X and Y are NULL (in other words if only the column name Z is
- ** supplied) and the value of Z is enclosed in double-quotes, then
- ** Z is a string literal if it doesn't match any column names. In that
- ** case, we need to return right away and not make any changes to
- ** pExpr.
- **
- ** Because no reference was made to outer contexts, the pNC->nRef
- ** fields are not changed in any context.
- */
- if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
- sqlite3DbFree(db, zCol);
- return 0;
- }
-
- /*
- ** cnt==0 means there was not match. cnt>1 means there were two or
- ** more matches. Either way, we have an error.
- */
- if( cnt!=1 ){
- const char *zErr;
- zErr = cnt==0 ? "no such column" : "ambiguous column name";
- if( zDb ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
- }else if( zTab ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
- }else{
- sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
- }
- pTopNC->nErr++;
- }
-
- /* If a column from a table in pSrcList is referenced, then record
- ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
- ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
- ** column number is greater than the number of bits in the bitmask
- ** then set the high-order bit of the bitmask.
- */
- if( pExpr->iColumn>=0 && pMatch!=0 ){
- int n = pExpr->iColumn;
- testcase( n==sizeof(Bitmask)*8-1 );
- if( n>=sizeof(Bitmask)*8 ){
- n = sizeof(Bitmask)*8-1;
- }
- assert( pMatch->iCursor==pExpr->iTable );
- pMatch->colUsed |= ((Bitmask)1)<<n;
- }
-
-lookupname_end:
- /* Clean up and return
- */
- sqlite3DbFree(db, zDb);
- sqlite3DbFree(db, zTab);
- sqlite3ExprDelete(db, pExpr->pLeft);
- pExpr->pLeft = 0;
- sqlite3ExprDelete(db, pExpr->pRight);
- pExpr->pRight = 0;
- pExpr->op = TK_COLUMN;
-lookupname_end_2:
- sqlite3DbFree(db, zCol);
- if( cnt==1 ){
- assert( pNC!=0 );
- sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
- if( pMatch && !pMatch->pSelect ){
- pExpr->pTab = pMatch->pTab;
- }
- /* Increment the nRef value on all name contexts from TopNC up to
- ** the point where the name matched. */
- for(;;){
- assert( pTopNC!=0 );
- pTopNC->nRef++;
- if( pTopNC==pNC ) break;
- pTopNC = pTopNC->pNext;
- }
- return 0;
- } else {
- return 1;
- }
-}
-
-/*
-** This routine is designed as an xFunc for walkExprTree().
-**
-** Resolve symbolic names into TK_COLUMN operators for the current
-** node in the expression tree. Return 0 to continue the search down
-** the tree or 2 to abort the tree walk.
-**
-** This routine also does error checking and name resolution for
-** function names. The operator for aggregate functions is changed
-** to TK_AGG_FUNCTION.
-*/
-static int nameResolverStep(void *pArg, Expr *pExpr){
- NameContext *pNC = (NameContext*)pArg;
- Parse *pParse;
-
- if( pExpr==0 ) return 1;
- assert( pNC!=0 );
- pParse = pNC->pParse;
-
- if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
- ExprSetProperty(pExpr, EP_Resolved);
-#ifndef NDEBUG
- if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
- SrcList *pSrcList = pNC->pSrcList;
- int i;
- for(i=0; i<pNC->pSrcList->nSrc; i++){
- assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
- }
- }
-#endif
- switch( pExpr->op ){
- /* Double-quoted strings (ex: "abc") are used as identifiers if
- ** possible. Otherwise they remain as strings. Single-quoted
- ** strings (ex: 'abc') are always string literals.
- */
- case TK_STRING: {
- if( pExpr->token.z[0]=='\'' ) break;
- /* Fall thru into the TK_ID case if this is a double-quoted string */
- }
- /* A lone identifier is the name of a column.
- */
- case TK_ID: {
- lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
- return 1;
- }
-
- /* A table name and column name: ID.ID
- ** Or a database, table and column: ID.ID.ID
- */
- case TK_DOT: {
- Token *pColumn;
- Token *pTable;
- Token *pDb;
- Expr *pRight;
-
- /* if( pSrcList==0 ) break; */
- pRight = pExpr->pRight;
- if( pRight->op==TK_ID ){
- pDb = 0;
- pTable = &pExpr->pLeft->token;
- pColumn = &pRight->token;
- }else{
- assert( pRight->op==TK_DOT );
- pDb = &pExpr->pLeft->token;
- pTable = &pRight->pLeft->token;
- pColumn = &pRight->pRight->token;
- }
- lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
- return 1;
- }
-
- /* Resolve function names
- */
- case TK_CONST_FUNC:
- case TK_FUNCTION: {
- ExprList *pList = pExpr->pList; /* The argument list */
- int n = pList ? pList->nExpr : 0; /* Number of arguments */
- int no_such_func = 0; /* True if no such function exists */
- int wrong_num_args = 0; /* True if wrong number of arguments */
- int is_agg = 0; /* True if is an aggregate function */
- int i;
- int auth; /* Authorization to use the function */
- int nId; /* Number of characters in function name */
- const char *zId; /* The function name. */
- FuncDef *pDef; /* Information about the function */
- int enc = ENC(pParse->db); /* The database encoding */
-
- zId = (char*)pExpr->token.z;
- nId = pExpr->token.n;
- pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
- if( pDef==0 ){
- pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
- if( pDef==0 ){
- no_such_func = 1;
- }else{
- wrong_num_args = 1;
- }
- }else{
- is_agg = pDef->xFunc==0;
- }
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( pDef ){
- auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
- if( auth!=SQLITE_OK ){
- if( auth==SQLITE_DENY ){
- sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
- pDef->zName);
- pNC->nErr++;
- }
- pExpr->op = TK_NULL;
- return 1;
- }
- }
-#endif
- if( is_agg && !pNC->allowAgg ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
- pNC->nErr++;
- is_agg = 0;
- }else if( no_such_func ){
- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- pNC->nErr++;
- }else if( wrong_num_args ){
- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- pNC->nErr++;
- }
- if( is_agg ){
- pExpr->op = TK_AGG_FUNCTION;
- pNC->hasAgg = 1;
- }
- if( is_agg ) pNC->allowAgg = 0;
- for(i=0; pNC->nErr==0 && i<n; i++){
- walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
- }
- if( is_agg ) pNC->allowAgg = 1;
- /* FIX ME: Compute pExpr->affinity based on the expected return
- ** type of the function
- */
- return is_agg;
- }
-#ifndef SQLITE_OMIT_SUBQUERY
- case TK_SELECT:
- case TK_EXISTS:
-#endif
- case TK_IN: {
- if( pExpr->pSelect ){
- int nRef = pNC->nRef;
-#ifndef SQLITE_OMIT_CHECK
- if( pNC->isCheck ){
- sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
- }
-#endif
- sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
- assert( pNC->nRef>=nRef );
- if( nRef!=pNC->nRef ){
- ExprSetProperty(pExpr, EP_VarSelect);
- }
- }
- break;
- }
-#ifndef SQLITE_OMIT_CHECK
- case TK_VARIABLE: {
- if( pNC->isCheck ){
- sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
- }
- break;
- }
-#endif
- }
- return 0;
-}
-
-/*
-** This routine walks an expression tree and resolves references to
-** table columns. Nodes of the form ID.ID or ID resolve into an
-** index to the table in the table list and a column offset. The
-** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
-** value is changed to the index of the referenced table in pTabList
-** plus the "base" value. The base value will ultimately become the
-** VDBE cursor number for a cursor that is pointing into the referenced
-** table. The Expr.iColumn value is changed to the index of the column
-** of the referenced table. The Expr.iColumn value for the special
-** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
-** alias for ROWID.
-**
-** Also resolve function names and check the functions for proper
-** usage. Make sure all function names are recognized and all functions
-** have the correct number of arguments. Leave an error message
-** in pParse->zErrMsg if anything is amiss. Return the number of errors.
-**
-** If the expression contains aggregate functions then set the EP_Agg
-** property on the expression.
-*/
-SQLITE_PRIVATE int sqlite3ExprResolveNames(
- NameContext *pNC, /* Namespace to resolve expressions in. */
- Expr *pExpr /* The expression to be analyzed. */
-){
- int savedHasAgg;
-
- if( pExpr==0 ) return 0;
-#if SQLITE_MAX_EXPR_DEPTH>0
- {
- if( checkExprHeight(pNC->pParse, pExpr->nHeight + pNC->pParse->nHeight) ){
- return 1;
- }
- pNC->pParse->nHeight += pExpr->nHeight;
- }
-#endif
- savedHasAgg = pNC->hasAgg;
- pNC->hasAgg = 0;
- walkExprTree(pExpr, nameResolverStep, pNC);
-#if SQLITE_MAX_EXPR_DEPTH>0
- pNC->pParse->nHeight -= pExpr->nHeight;
-#endif
- if( pNC->nErr>0 ){
- ExprSetProperty(pExpr, EP_Error);
- }
- if( pNC->hasAgg ){
- ExprSetProperty(pExpr, EP_Agg);
- }else if( savedHasAgg ){
- pNC->hasAgg = 1;
- }
- return ExprHasProperty(pExpr, EP_Error);
-}
-
-/*
-** A pointer instance of this structure is used to pass information
-** through walkExprTree into codeSubqueryStep().
-*/
-typedef struct QueryCoder QueryCoder;
-struct QueryCoder {
- Parse *pParse; /* The parsing context */
- NameContext *pNC; /* Namespace of first enclosing query */
-};
-
#ifdef SQLITE_TEST
int sqlite3_enable_in_opt = 1;
#else
@@ -52169,8 +53510,9 @@ static int isCandidateForInOpt(Select *p){
if( !sqlite3_enable_in_opt ) return 0; /* IN optimization must be enabled */
if( p==0 ) return 0; /* right-hand side of IN is SELECT */
if( p->pPrior ) return 0; /* Not a compound SELECT */
- if( p->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;
@@ -52425,7 +53767,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHav
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;
@@ -52449,7 +53791,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHav
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);
@@ -52506,7 +53848,7 @@ SQLITE_PRIVATE void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr, int rMayHav
}
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;
@@ -52788,11 +54130,46 @@ SQLITE_PRIVATE void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){
}
/*
+** Generate code to store the value of the iAlias-th alias in register
+** target. The first time this is called, pExpr is evaluated to compute
+** the value of the alias. The value is stored in an auxiliary register
+** and the number of that register is returned. On subsequent calls,
+** the register number is returned without generating any code.
+**
+** Note that in order for this to work, code must be generated in the
+** same order that it is executed.
+**
+** Aliases are numbered starting with 1. So iAlias is in the range
+** of 1 to pParse->nAlias inclusive.
+**
+** pParse->aAlias[iAlias-1] records the register number where the value
+** of the iAlias-th alias is stored. If zero, that means that the
+** alias has not yet been computed.
+*/
+static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr){
+ 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 ){
+ 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
@@ -52805,8 +54182,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
int regFree1 = 0; /* If non-zero free this temporary register */
int regFree2 = 0; /* If non-zero free this temporary register */
int r1, r2, r3, r4; /* Various register numbers */
+ sqlite3 *db;
- assert( v!=0 || pParse->db->mallocFailed );
+ db = pParse->db;
+ assert( v!=0 || db->mallocFailed );
assert( target>0 && target<=pParse->nMem );
if( v==0 ) return 0;
@@ -52852,7 +54231,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int 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;
@@ -52888,6 +54267,10 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
inReg = pExpr->iTable;
break;
}
+ case TK_AS: {
+ inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft);
+ break;
+ }
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
@@ -53044,7 +54427,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
const char *zId;
int constMask = 0;
int i;
- sqlite3 *db = pParse->db;
u8 enc = ENC(db);
CollSeq *pColl = 0;
@@ -53052,7 +54434,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
testcase( op==TK_FUNCTION );
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
- pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
+ pDef = sqlite3FindFunction(db, zId, nId, nExpr, enc, 0);
assert( pDef!=0 );
if( pList ){
nExpr = pList->nExpr;
@@ -53089,7 +54471,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
}
}
if( pDef->needCollSeq ){
- if( !pColl ) pColl = pParse->db->pDfltColl;
+ if( !pColl ) pColl = db->pDfltColl;
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
@@ -53288,7 +54670,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
testcase( regFree1==0 );
cacheX.op = TK_REGISTER;
- cacheX.iColumn = 0;
opCompare.op = TK_EQ;
opCompare.pLeft = &cacheX;
pTest = &opCompare;
@@ -53330,7 +54711,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
assert( pExpr->iColumn==OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail );
- sqlite3DequoteExpr(pParse->db, pExpr);
+ sqlite3DequoteExpr(db, pExpr);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, 0,
(char*)pExpr->token.z, pExpr->token.n);
} else {
@@ -53408,7 +54789,6 @@ SQLITE_PRIVATE int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int targe
iMem = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
pExpr->iTable = iMem;
- pExpr->iColumn = pExpr->op;
pExpr->op = TK_REGISTER;
}
return inReg;
@@ -53479,8 +54859,8 @@ static int isAppropriateForFactoring(Expr *p){
** 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;
@@ -53508,12 +54888,11 @@ static int evalConstExpr(void *pArg, Expr *pExpr){
int r2;
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
if( r1!=r2 ) sqlite3ReleaseTempReg(pParse, r1);
- pExpr->iColumn = pExpr->op;
pExpr->op = TK_REGISTER;
pExpr->iTable = r2;
- return 1;
+ return WRC_Prune;
}
- return 0;
+ return WRC_Continue;
}
/*
@@ -53522,7 +54901,11 @@ static int evalConstExpr(void *pArg, Expr *pExpr){
** 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);
}
@@ -53540,14 +54923,17 @@ SQLITE_PRIVATE int sqlite3ExprCodeExprList(
){
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( pItem->iAlias ){
+ int iReg = codeAlias(pParse, pItem->iAlias, pItem->pExpr);
+ Vdbe *v = sqlite3GetVdbe(pParse);
+ sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i);
+ }else{
+ sqlite3ExprCode(pParse, pItem->pExpr, target+i);
+ }
if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n);
}
return n;
@@ -53922,15 +55308,13 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){
}
/*
-** 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){
+static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
int i;
- NameContext *pNC = (NameContext *)pArg;
+ NameContext *pNC = pWalker->u.pNC;
Parse *pParse = pNC->pParse;
SrcList *pSrcList = pNC->pSrcList;
AggInfo *pAggInfo = pNC->pAggInfo;
@@ -53938,6 +55322,8 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
switch( pExpr->op ){
case TK_AGG_COLUMN:
case TK_COLUMN: {
+ testcase( pExpr->op==TK_AGG_COLUMN );
+ testcase( pExpr->op==TK_COLUMN );
/* Check to see if the column is in one of the tables in the FROM
** clause of the aggregate query */
if( pSrcList ){
@@ -53999,7 +55385,7 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
} /* 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
@@ -54037,21 +55423,22 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
*/
pExpr->iAgg = i;
pExpr->pAggInfo = pAggInfo;
- return 1;
+ return WRC_Prune;
}
}
}
-
- /* 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_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 WRC_Prune;
+ }else{
+ return WRC_Continue;
}
- return 0;
}
/*
@@ -54060,10 +55447,14 @@ static int analyzeAggregate(void *pArg, Expr *pExpr){
** 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);
}
/*
@@ -54197,7 +55588,7 @@ static void renameTableFunc(
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 );
@@ -55212,7 +56603,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
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;
@@ -57074,12 +58465,12 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
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;
@@ -57103,7 +58494,8 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
&& 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 "
@@ -57390,7 +58782,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
sNC.pParse = pParse;
sNC.pSrcList = &sSrc;
sNC.isCheck = 1;
- if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){
+ if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){
return;
}
}
@@ -57463,10 +58855,10 @@ SQLITE_PRIVATE void sqlite3EndTable(
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;
@@ -57512,7 +58904,7 @@ SQLITE_PRIVATE void sqlite3EndTable(
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
- if( p->autoInc ){
+ if( p->tabFlags & TF_Autoincrement ){
Db *pDb = &db->aDb[iDb];
if( pDb->pSchema->pSeqTab==0 ){
sqlite3NestedParse(pParse,
@@ -57708,10 +59100,10 @@ SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
#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 ){
@@ -57945,7 +59337,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
}
}
#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;
}
@@ -58000,7 +59392,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
** at the btree level, in case the sqlite_sequence table needs to
** move as a result of the drop (can happen in auto-vacuum mode).
*/
- if( pTab->autoInc ){
+ if( pTab->tabFlags & TF_Autoincrement ){
sqlite3NestedParse(pParse,
"DELETE FROM %s.sqlite_sequence WHERE name=%Q",
pDb->zName, pTab->zName
@@ -58070,6 +59462,7 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
ExprList *pToCol, /* Columns in the other table */
int flags /* Conflict resolution algorithms. */
){
+ sqlite3 *db = pParse->db;
#ifndef SQLITE_OMIT_FOREIGN_KEY
FKey *pFKey = 0;
Table *p = pParse->pNewTable;
@@ -58077,10 +59470,8 @@ SQLITE_PRIVATE void sqlite3CreateForeignKey(
int i;
int nCol;
char *z;
- sqlite3 *db;
assert( pTo!=0 );
- db = pParse->db;
if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end;
if( pFromCol==0 ){
int iCol = p->nCol-1;
@@ -58346,7 +59737,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
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;
}
@@ -58438,9 +59829,10 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
** 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));
}
}
@@ -58507,7 +59899,7 @@ SQLITE_PRIVATE void sqlite3CreateIndex(
** 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);
@@ -59654,6 +61046,87 @@ SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(
return pColl;
}
+/* During the search for the best function definition, this procedure
+** is called to test how well the function passed as the first argument
+** matches the request for a function with nArg arguments in a system
+** that uses encoding enc. The value returned indicates how well the
+** request is matched. A higher value indicates a better match.
+**
+** The returned value is always between 1 and 6, as follows:
+**
+** 1: A variable arguments function that prefers UTF-8 when a UTF-16
+** encoding is requested, or vice versa.
+** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
+** requested, or vice versa.
+** 3: A variable arguments function using the same text encoding.
+** 4: A function with the exact number of arguments requested that
+** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
+** 5: A function with the exact number of arguments requested that
+** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
+** 6: An exact match.
+**
+*/
+static int matchQuality(FuncDef *p, int nArg, u8 enc){
+ int match = 0;
+ if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
+ match = 1;
+ if( p->nArg==nArg || nArg==-1 ){
+ match = 4;
+ }
+ if( enc==p->iPrefEnc ){
+ match += 2;
+ }
+ else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
+ (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
+ match += 1;
+ }
+ }
+ return match;
+}
+
+/*
+** Search a FuncDefHash for a function with the given name. Return
+** a pointer to the matching FuncDef if found, or 0 if there is no match.
+*/
+static FuncDef *functionSearch(
+ FuncDefHash *pHash, /* Hash table to search */
+ int h, /* Hash of the name */
+ const char *zFunc, /* Name of function */
+ int nFunc /* Number of bytes in zFunc */
+){
+ FuncDef *p;
+ for(p=pHash->a[h]; p; p=p->pHash){
+ if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){
+ return p;
+ }
+ }
+ return 0;
+}
+
+/*
+** Insert a new FuncDef into a FuncDefHash hash table.
+*/
+SQLITE_PRIVATE void sqlite3FuncDefInsert(
+ FuncDefHash *pHash, /* The hash table into which to insert */
+ FuncDef *pDef /* The function definition to insert */
+){
+ FuncDef *pOther;
+ int nName = strlen(pDef->zName);
+ u8 c1 = (u8)pDef->zName[0];
+ int h = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash->a);
+ pOther = functionSearch(pHash, h, pDef->zName, nName);
+ if( pOther ){
+ pDef->pNext = pOther->pNext;
+ pOther->pNext = pDef;
+ }else{
+ pDef->pNext = 0;
+ pDef->pHash = pHash->a[h];
+ pHash->a[h] = pDef;
+ }
+}
+
+
+
/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8. Return a
@@ -59683,51 +61156,39 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
int createFlag /* Create new entry if true and does not otherwise exist */
){
FuncDef *p; /* Iterator variable */
- FuncDef *pFirst; /* First function with this name */
FuncDef *pBest = 0; /* Best match found so far */
- int 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;
+ h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
- 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 ){
+ 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 the createFlag parameter is false and no match was found amongst
+ ** the custom functions stored in sqlite3.aFunc, try to find a built-in
+ ** function to use.
+ */
+ if( !createFlag && !pBest ){
+ p = functionSearch(&sqlite3GlobalFunctions, h, zName, nName);
+ while( p ){
+ int score = matchQuality(p, nArg, enc);
+ if( score>bestScore ){
pBest = p;
- bestmatch = match;
+ bestScore = score;
}
+ p = p->pNext;
}
}
@@ -59735,18 +61196,14 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction(
** 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 ){
+ if( createFlag && bestScore<6 &&
+ (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
+ pBest->zName = (char *)&pBest[1];
pBest->nArg = nArg;
- pBest->pNext = pFirst;
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;
- sqlite3DbFree(db, pBest);
- return 0;
- }
+ sqlite3FuncDefInsert(&db->aFunc, pBest);
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
@@ -59856,7 +61313,8 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
** 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)
@@ -59903,7 +61361,7 @@ SQLITE_PRIVATE void sqlite3OpenTable(
*/
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 */
){
@@ -59911,16 +61369,19 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
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);
+ sqlite3Select(pParse, pDup, &dest);
sqlite3SelectDelete(db, pDup);
}
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
@@ -60060,7 +61521,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
** a ephemeral table.
*/
if( isView ){
- sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur);
+ sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
}
/* Resolve the column names in the WHERE clause.
@@ -60068,7 +61529,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
- if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+ if( sqlite3ResolveExprNames(&sNC, pWhere) ){
goto delete_from_cleanup;
}
@@ -60380,7 +61841,6 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
** $Id$
*/
-
/*
** Return the collating function associated with a function.
*/
@@ -61570,108 +63030,12 @@ static void groupConcatFinalize(sqlite3_context *context){
** external linkage.
*/
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
- static const struct {
- char *zName;
- signed char nArg;
- u8 argType; /* 1: 0, 2: 1, 3: 2,... N: N-1. */
- u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */
- u8 needCollSeq;
- void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
- } aFuncs[] = {
- { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc },
- { "min", 0, 0, SQLITE_UTF8, 1, 0 },
- { "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc },
- { "max", 0, 1, SQLITE_UTF8, 1, 0 },
- { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc },
- { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc },
- { "substr", 2, 0, SQLITE_UTF8, 0, substrFunc },
- { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc },
- { "abs", 1, 0, SQLITE_UTF8, 0, absFunc },
- { "round", 1, 0, SQLITE_UTF8, 0, roundFunc },
- { "round", 2, 0, SQLITE_UTF8, 0, roundFunc },
- { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc },
- { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc },
- { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc },
- { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 },
- { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 },
- { "hex", 1, 0, SQLITE_UTF8, 0, hexFunc },
- { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
- { "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
- { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob },
- { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
- { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
- { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc },
- { "last_insert_rowid", 0, 0, SQLITE_UTF8, 0, last_insert_rowid },
- { "changes", 0, 0, SQLITE_UTF8, 0, changes },
- { "total_changes", 0, 0, SQLITE_UTF8, 0, total_changes },
- { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc },
- { "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc },
- { "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc },
- { "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc },
- { "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc },
- { "trim", 1, 3, SQLITE_UTF8, 0, trimFunc },
- { "trim", 2, 3, SQLITE_UTF8, 0, trimFunc },
- { "zeroblob", 1, 0, SQLITE_UTF8, 0, zeroblobFunc },
-#ifdef SQLITE_SOUNDEX
- { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
-#endif
-#ifndef SQLITE_OMIT_LOAD_EXTENSION
- { "load_extension", 1, 0, SQLITE_UTF8, 0, loadExt },
- { "load_extension", 2, 0, SQLITE_UTF8, 0, loadExt },
-#endif
- };
- static const struct {
- char *zName;
- signed char nArg;
- u8 argType;
- u8 needCollSeq;
- void (*xStep)(sqlite3_context*,int,sqlite3_value**);
- void (*xFinalize)(sqlite3_context*);
- } aAggs[] = {
- { "min", 1, 0, 1, minmaxStep, minMaxFinalize },
- { "max", 1, 1, 1, minmaxStep, minMaxFinalize },
- { "sum", 1, 0, 0, sumStep, sumFinalize },
- { "total", 1, 0, 0, sumStep, totalFinalize },
- { "avg", 1, 0, 0, sumStep, avgFinalize },
- { "count", 0, 0, 0, countStep, countFinalize },
- { "count", 1, 0, 0, countStep, countFinalize },
- { "group_concat", -1, 0, 0, groupConcatStep, groupConcatFinalize },
- };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- void *pArg;
- u8 argType = aFuncs[i].argType;
- pArg = SQLITE_INT_TO_PTR(argType);
- sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
- aFuncs[i].eTextRep, pArg, aFuncs[i].xFunc, 0, 0);
- if( aFuncs[i].needCollSeq ){
- FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName,
- strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0);
- if( pFunc && aFuncs[i].needCollSeq ){
- pFunc->needCollSeq = 1;
- }
- }
- }
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions(db);
#endif
#ifndef SQLITE_OMIT_PARSER
sqlite3AttachFunctions(db);
#endif
- for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
- void *pArg = SQLITE_INT_TO_PTR(aAggs[i].argType);
- sqlite3CreateFunc(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8,
- pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize);
- if( aAggs[i].needCollSeq ){
- FuncDef *pFunc = sqlite3FindFunction( db, aAggs[i].zName,
- strlen(aAggs[i].zName), aAggs[i].nArg, SQLITE_UTF8, 0);
- if( pFunc && aAggs[i].needCollSeq ){
- pFunc->needCollSeq = 1;
- }
- }
- }
- sqlite3RegisterDateTimeFunctions(db);
if( !db->mallocFailed ){
int rc = sqlite3_overload_function(db, "MATCH", 2);
assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
@@ -61682,11 +63046,6 @@ SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
#ifdef SQLITE_SSE
(void)sqlite3SseFunctions(db);
#endif
-#ifdef SQLITE_CASE_SENSITIVE_LIKE
- sqlite3RegisterLikeFunctions(db, 1);
-#else
- sqlite3RegisterLikeFunctions(db, 0);
-#endif
}
/*
@@ -61754,6 +63113,90 @@ SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocas
return 1;
}
+/*
+** The following array holds FuncDef structures for all of the functions
+** defined in this file.
+**
+** The array cannot be constant since changes are made to the
+** FuncDef.pHash elements at start-time. The elements of this array
+** are read-only after initialization is complete.
+*/
+static FuncDef aBuiltinFunc[] = {
+ FUNCTION(ltrim, 1, 1, 0, trimFunc ),
+ FUNCTION(ltrim, 2, 1, 0, trimFunc ),
+ FUNCTION(rtrim, 1, 2, 0, trimFunc ),
+ FUNCTION(rtrim, 2, 2, 0, trimFunc ),
+ FUNCTION(trim, 1, 3, 0, trimFunc ),
+ FUNCTION(trim, 2, 3, 0, trimFunc ),
+ FUNCTION(min, -1, 0, 1, minmaxFunc ),
+ FUNCTION(min, 0, 0, 1, 0 ),
+ AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(max, -1, 1, 1, minmaxFunc ),
+ FUNCTION(max, 0, 1, 1, 0 ),
+ AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
+ FUNCTION(typeof, 1, 0, 0, typeofFunc ),
+ FUNCTION(length, 1, 0, 0, lengthFunc ),
+ FUNCTION(substr, 2, 0, 0, substrFunc ),
+ FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(abs, 1, 0, 0, absFunc ),
+ FUNCTION(round, 1, 0, 0, roundFunc ),
+ FUNCTION(round, 2, 0, 0, roundFunc ),
+ FUNCTION(upper, 1, 0, 0, upperFunc ),
+ FUNCTION(lower, 1, 0, 0, lowerFunc ),
+ FUNCTION(coalesce, 1, 0, 0, 0 ),
+ FUNCTION(coalesce, -1, 0, 0, ifnullFunc ),
+ FUNCTION(coalesce, 0, 0, 0, 0 ),
+ FUNCTION(hex, 1, 0, 0, hexFunc ),
+ FUNCTION(ifnull, 2, 0, 1, ifnullFunc ),
+ FUNCTION(random, -1, 0, 0, randomFunc ),
+ FUNCTION(randomblob, 1, 0, 0, randomBlob ),
+ FUNCTION(nullif, 2, 0, 1, nullifFunc ),
+ FUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
+ FUNCTION(quote, 1, 0, 0, quoteFunc ),
+ FUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
+ FUNCTION(changes, 0, 0, 0, changes ),
+ FUNCTION(total_changes, 0, 0, 0, total_changes ),
+ FUNCTION(replace, 3, 0, 0, replaceFunc ),
+ FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
+#ifdef SQLITE_SOUNDEX
+ FUNCTION(soundex, 1, 0, 0, soundexFunc ),
+#endif
+#ifndef SQLITE_OMIT_LOAD_EXTENSION
+ FUNCTION(load_extension, 1, 0, 0, loadExt ),
+ FUNCTION(load_extension, 2, 0, 0, loadExt ),
+#endif
+ AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
+ AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
+ AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
+ AGGREGATE(count, 0, 0, 0, countStep, countFinalize ),
+ AGGREGATE(count, 1, 0, 0, countStep, countFinalize ),
+ AGGREGATE(group_concat, -1, 0, 0, groupConcatStep, groupConcatFinalize),
+
+ LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
+ LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+ LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
+#else
+ LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
+ LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
+#endif
+};
+
+/*
+** All all of the FuncDef structures in the aBuiltinFunc[] array above
+** to the global function hash table. This occurs at start-time (as
+** a consequence of calling sqlite3_initialize()).
+**
+** After this routine runs
+*/
+SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
+ int i;
+ for(i=0; i<ArraySize(aBuiltinFunc); i++){
+ sqlite3FuncDefInsert(&sqlite3GlobalFunctions, &aBuiltinFunc[i]);
+ }
+ sqlite3RegisterDateTimeFunctions();
+}
+
/************** End of func.c ************************************************/
/************** Begin file insert.c ******************************************/
/*
@@ -61922,7 +63365,7 @@ static int autoIncBegin(
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;
@@ -61973,7 +63416,7 @@ static void autoIncEnd(
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];
@@ -62289,7 +63732,7 @@ SQLITE_PRIVATE void sqlite3Insert(
VdbeComment((v, "Jump over SELECT coroutine"));
/* Resolve the expressions in the SELECT statement and execute it. */
- rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0);
+ rc = sqlite3Select(pParse, pSelect, &dest);
if( rc || pParse->nErr || db->mallocFailed ){
goto insert_cleanup;
}
@@ -62359,7 +63802,7 @@ SQLITE_PRIVATE void sqlite3Insert(
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;
}
}
@@ -63292,7 +64735,7 @@ static int xferOptimization(
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
@@ -63327,7 +64770,7 @@ static int xferOptimization(
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;
@@ -63353,7 +64796,7 @@ static int xferOptimization(
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
@@ -63444,7 +64887,7 @@ static int xferOptimization(
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);
@@ -64862,7 +66305,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
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;
}
@@ -65944,7 +67387,8 @@ static void corruptSchema(
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);
@@ -65974,7 +67418,6 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
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);
@@ -66014,7 +67457,6 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
corruptSchema(pData, argv[0], zErr);
}
sqlite3DbFree(db, zErr);
- return 1;
}
}else if( argv[0]==0 ){
corruptSchema(pData, 0, 0);
@@ -66110,17 +67552,18 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
azArg[3] = 0;
initData.db = db;
initData.iDb = iDb;
+ initData.rc = SQLITE_OK;
initData.pzErrMsg = pzErrMsg;
(void)sqlite3SafetyOff(db);
- 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
@@ -66255,7 +67698,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
db->xAuth = xAuth;
}
#endif
- if( rc==SQLITE_ABORT ) rc = initData.rc;
+ if( rc==SQLITE_OK ) rc = initData.rc;
(void)sqlite3SafetyOn(db);
sqlite3DbFree(db, zSql);
#ifndef SQLITE_OMIT_ANALYZE
@@ -66811,7 +68254,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy;
- pNew->isDistinct = isDistinct;
+ pNew->selFlags = isDistinct ? SF_Distinct : 0;
pNew->op = TK_SELECT;
assert( pOffset==0 || pLimit!=0 );
pNew->pLimit = pLimit;
@@ -66819,8 +68262,9 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
- if( pNew==&standin) {
+ if( db->mallocFailed ) {
clearSelect(db, pNew);
+ if( pNew!=&standin ) sqlite3DbFree(db, pNew);
pNew = 0;
}
return pNew;
@@ -67305,7 +68749,7 @@ static void selectInnerLoop(
/* If the destination is an EXISTS(...) expression, the actual
** values returned by the SELECT are not required.
*/
- sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Callback);
+ sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
}
nColumn = nResultCol;
@@ -67422,7 +68866,7 @@ static void selectInnerLoop(
** 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);
@@ -67529,10 +68973,10 @@ static void generateSortTail(
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);
@@ -67562,7 +69006,7 @@ static void generateSortTail(
break;
}
#endif
- case SRT_Callback:
+ case SRT_Output:
case SRT_Coroutine: {
int i;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid);
@@ -67571,7 +69015,7 @@ static void generateSortTail(
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{
@@ -67596,7 +69040,7 @@ static void generateSortTail(
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);
}
@@ -67860,58 +69304,36 @@ static const char *selectOpName(int id){
#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.
+** 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.
*/
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
- Table *pTab;
- int i, j, rc;
- ExprList *pEList;
- Column *aCol, *pCol;
+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 savedFlags;
+ int i, j, cnt;
+ Column *aCol, *pCol;
+ int nCol;
+ Expr *p;
+ char *zName;
+ int nName;
- savedFlags = db->flags;
- db->flags &= ~SQLITE_FullColNames;
- db->flags |= SQLITE_ShortColNames;
- rc = sqlite3SelectResolve(pParse, pSelect, 0);
- if( rc==SQLITE_OK ){
- while( pSelect->pPrior ) pSelect = pSelect->pPrior;
- rc = prepSelectStmt(pParse, pSelect);
- if( rc==SQLITE_OK ){
- rc = sqlite3SelectResolve(pParse, pSelect, 0);
- }
- }
- db->flags = savedFlags;
- if( rc ){
- return 0;
- }
- pTab = sqlite3DbMallocZero(db, sizeof(Table) );
- if( pTab==0 ){
- return 0;
- }
- pTab->db = db;
- pTab->nRef = 1;
- pTab->zName = zTabName ? sqlite3DbStrDup(db, zTabName) : 0;
- pEList = pSelect->pEList;
- pTab->nCol = pEList->nExpr;
- assert( pTab->nCol>0 );
- pTab->aCol = aCol = sqlite3DbMallocZero(db, sizeof(pTab->aCol[0])*pTab->nCol);
- testcase( aCol==0 );
- for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
- Expr *p;
- char *zType;
- char *zName;
- int nName;
- CollSeq *pColl;
- int cnt;
- NameContext sNC;
-
+ *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;
@@ -67919,14 +69341,20 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Se
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);
+ 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);
@@ -67950,518 +69378,94 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Se
}
}
pCol->zName = zName;
-
- /* Get the typename, type affinity, and collating sequence for the
- ** column.
- */
- memset(&sNC, 0, sizeof(sNC));
- sNC.pSrcList = pSelect->pSrc;
- zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
- pCol->zType = zType;
- pCol->affinity = sqlite3ExprAffinity(p);
- pColl = sqlite3ExprCollSeq(pParse, p);
- if( pColl ){
- pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
- }
}
- pTab->iPKey = -1;
if( db->mallocFailed ){
- sqlite3DeleteTable(pTab);
- return 0;
- }
- return pTab;
-}
-
-/*
-** Prepare a SELECT statement for processing by doing the following
-** things:
-**
-** (1) Make sure VDBE cursor numbers have been assigned to every
-** element of the FROM clause.
-**
-** (2) Fill in the pTabList->a[].pTab fields in the SrcList that
-** defines FROM clause. When views appear in the FROM clause,
-** fill pTabList->a[].pSelect with a copy of the SELECT statement
-** that implements the view. A copy is made of the view's SELECT
-** statement so that we can freely modify or delete that statement
-** without worrying about messing up the presistent representation
-** of the view.
-**
-** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword
-** on joins and the ON and USING clause of joins.
-**
-** (4) Scan the list of columns in the result set (pEList) looking
-** for instances of the "*" operator or the TABLE.* operator.
-** If found, expand each "*" to be every column in every table
-** and TABLE.* to be every column in TABLE.
-**
-** Return 0 on success. If there are problems, leave an error message
-** in pParse and return non-zero.
-*/
-static int prepSelectStmt(Parse *pParse, Select *p){
- int i, j, k, rc;
- SrcList *pTabList;
- ExprList *pEList;
- struct SrcList_item *pFrom;
- sqlite3 *db = pParse->db;
-
- if( p==0 || p->pSrc==0 || db->mallocFailed ){
- return 1;
- }
- pTabList = p->pSrc;
- pEList = p->pEList;
-
- /* Make sure cursor numbers have been assigned to all entries in
- ** the FROM clause of the SELECT statement.
- */
- sqlite3SrcListAssignCursors(pParse, p->pSrc);
-
- /* Look up every table named in the FROM clause of the select. If
- ** an entry of the FROM clause is a subquery instead of a table or view,
- ** then create a transient table structure to describe the subquery.
- */
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab;
- if( pFrom->pTab!=0 ){
- /* This statement has already been prepared. There is no need
- ** to go further. */
- assert( i==0 );
- return 0;
- }
- if( pFrom->zName==0 ){
-#ifndef SQLITE_OMIT_SUBQUERY
- /* A sub-query in the FROM clause of a SELECT */
- assert( pFrom->pSelect!=0 );
- if( pFrom->zAlias==0 ){
- pFrom->zAlias =
- sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pFrom->pSelect);
- }
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab =
- sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
- if( pTab==0 ){
- return 1;
- }
- /* The isEphem flag indicates that the Table structure has been
- ** dynamically allocated and may be freed at any time. In other words,
- ** pTab is not pointing to a persistent table structure that defines
- ** part of the schema. */
- pTab->isEphem = 1;
-#endif
- }else{
- /* An ordinary table or view name in the FROM clause */
- assert( pFrom->pTab==0 );
- pFrom->pTab = pTab =
- sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
- if( pTab==0 ){
- return 1;
- }
- pTab->nRef++;
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
- if( pTab->pSelect || IsVirtual(pTab) ){
- /* We reach here if the named table is a really a view */
- if( sqlite3ViewGetColumnNames(pParse, pTab) ){
- return 1;
- }
- /* If pFrom->pSelect!=0 it means we are dealing with a
- ** view within a view. The SELECT structure has already been
- ** copied by the outer view so we can skip the copy step here
- ** in the inner view.
- */
- if( pFrom->pSelect==0 ){
- pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
- }
- }
-#endif
- }
- }
-
- /* Process NATURAL keywords, and ON and USING clauses of joins.
- */
- if( sqliteProcessJoin(pParse, p) ) return 1;
-
- /* For every "*" that occurs in the column list, insert the names of
- ** all columns in all tables. And for every TABLE.* insert the names
- ** of all columns in TABLE. The parser inserted a special expression
- ** with the TK_ALL operator for each "*" that it found in the column list.
- ** The following code just has to locate the TK_ALL expressions and expand
- ** each one to the list of all columns in all tables.
- **
- ** The first loop just checks to see if there are any "*" operators
- ** that need expanding.
- */
- for(k=0; k<pEList->nExpr; k++){
- Expr *pE = pEList->a[k].pExpr;
- if( pE->op==TK_ALL ) break;
- if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
- && pE->pLeft && pE->pLeft->op==TK_ID ) break;
- }
- rc = 0;
- if( k<pEList->nExpr ){
- /*
- ** If we get here it means the result set contains one or more "*"
- ** operators that need to be expanded. Loop through each expression
- ** in the result set and expand them one by one.
- */
- struct ExprList_item *a = pEList->a;
- ExprList *pNew = 0;
- int flags = pParse->db->flags;
- int longNames = (flags & SQLITE_FullColNames)!=0
- && (flags & SQLITE_ShortColNames)==0;
-
- for(k=0; k<pEList->nExpr; k++){
- Expr *pE = a[k].pExpr;
- if( pE->op!=TK_ALL &&
- (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
- /* This particular expression does not need to be expanded.
- */
- pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
- if( pNew ){
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
- }else{
- rc = 1;
- }
- a[k].pExpr = 0;
- a[k].zName = 0;
- }else{
- /* This expression is a "*" or a "TABLE.*" and needs to be
- ** expanded. */
- int tableSeen = 0; /* Set to 1 when TABLE matches */
- char *zTName; /* text of name of TABLE */
- if( pE->op==TK_DOT && pE->pLeft ){
- zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
- }else{
- zTName = 0;
- }
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
- char *zTabName = pFrom->zAlias;
- if( zTabName==0 || zTabName[0]==0 ){
- zTabName = pTab->zName;
- }
- assert( zTabName );
- if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
- continue;
- }
- tableSeen = 1;
- for(j=0; j<pTab->nCol; j++){
- Expr *pExpr, *pRight;
- char *zName = pTab->aCol[j].zName;
-
- /* If a column is marked as 'hidden' (currently only possible
- ** for virtual tables), do not include it in the expanded
- ** result-set list.
- */
- if( IsHiddenColumn(&pTab->aCol[j]) ){
- assert(IsVirtual(pTab));
- continue;
- }
-
- if( i>0 ){
- struct SrcList_item *pLeft = &pTabList->a[i-1];
- if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
- columnIndex(pLeft->pTab, zName)>=0 ){
- /* In a NATURAL join, omit the join columns from the
- ** table on the right */
- continue;
- }
- if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
- /* In a join with a USING clause, omit columns in the
- ** using clause from the table on the right. */
- continue;
- }
- }
- pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
- if( pRight==0 ) break;
- setQuotedToken(pParse, &pRight->token, zName);
- if( longNames || pTabList->nSrc>1 ){
- Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
- if( pExpr==0 ) break;
- setQuotedToken(pParse, &pLeft->token, zTabName);
-#if 1
- setToken(&pExpr->span,
- sqlite3MPrintf(db, "%s.%s", zTabName, zName));
- pExpr->span.dyn = 1;
-#else
- pExpr->span = pRight->token;
- pExpr->span.dyn = 0;
-#endif
- pExpr->token.z = 0;
- pExpr->token.n = 0;
- pExpr->token.dyn = 0;
- }else{
- pExpr = pRight;
- pExpr->span = pExpr->token;
- pExpr->span.dyn = 0;
- }
- if( longNames ){
- pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
- }else{
- pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
- }
- }
- }
- if( !tableSeen ){
- if( zTName ){
- sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
- }else{
- sqlite3ErrorMsg(pParse, "no tables specified");
- }
- rc = 1;
- }
- sqlite3DbFree(db, zTName);
- }
+ int j;
+ for(j=0; j<i; j++){
+ sqlite3DbFree(db, aCol[j].zName);
}
- sqlite3ExprListDelete(db, pEList);
- p->pEList = pNew;
- }
-#if SQLITE_MAX_COLUMN
- if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many columns in result set");
- rc = SQLITE_ERROR;
- }
-#endif
- if( db->mallocFailed ){
- rc = SQLITE_NOMEM;
+ sqlite3DbFree(db, aCol);
+ *paCol = 0;
+ *pnCol = 0;
+ return SQLITE_NOMEM;
}
- return rc;
+ return SQLITE_OK;
}
/*
-** 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 */
+** 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 */
){
- 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 ){
- sqlite3DbFree(db, zCol);
- return i+1;
- }
- }
- sqlite3DbFree(db, zCol);
- }
-
- /* Resolve all names in the ORDER BY term expression
- */
- memset(&nc, 0, sizeof(nc));
- nc.pParse = pParse;
- nc.pSrcList = pSelect->pSrc;
- nc.pEList = pEList;
- nc.allowAgg = 1;
- nc.nErr = 0;
- if( sqlite3ExprResolveNames(&nc, pE) ){
- if( isCompound ){
- sqlite3ErrorClear(pParse);
- return 0;
- }else{
- return -1;
- }
- }
- if( nc.hasAgg && pHasAgg ){
- *pHasAgg = 1;
- }
+ sqlite3 *db = pParse->db;
+ NameContext sNC;
+ Column *pCol;
+ CollSeq *pColl;
+ int i;
+ Expr *p;
+ struct ExprList_item *a;
- /* 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;
- }
+ 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);
}
}
- 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.
+** Given a SELECT statement, generate a Table structure that describes
+** the result set of that SELECT.
*/
-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;
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
+ Table *pTab;
sqlite3 *db = pParse->db;
- ExprList *pEList;
+ int savedFlags;
- 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 ){
+ 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;
}
- for(i=0; i<pOrderBy->nExpr; i++){
- int iCol;
- Expr *pE = pOrderBy->a[i].pExpr;
- if( sqlite3ExprIsInteger(pE, &iCol) ){
- if( iCol<=0 || iCol>pEList->nExpr ){
- const char *zType = isOrder ? "ORDER" : "GROUP";
- sqlite3ErrorMsg(pParse,
- "%r %s BY term out of range - should be "
- "between 1 and %d", i+1, zType, pEList->nExpr);
- return 1;
- }
- }else{
- iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg);
- if( iCol<0 ){
- return 1;
- }
- }
- if( iCol>0 ){
- CollSeq *pColl = pE->pColl;
- int flags = pE->flags & EP_ExpCollate;
- sqlite3ExprDelete(db, pE);
- pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr);
- pOrderBy->a[i].pExpr = pE;
- if( pE && pColl && flags ){
- pE->pColl = pColl;
- pE->flags |= flags;
- }
- }
- }
- return 0;
-}
-
-/*
-** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return
-** the number of errors seen.
-**
-** If iTable>0 then make the N-th term of the ORDER BY clause refer to
-** the N-th column of table iTable.
-**
-** If iTable==0 then transform each term of the ORDER BY clause to refer
-** to a column of the result set by number.
-*/
-static int processCompoundOrderBy(
- Parse *pParse, /* Parsing context. Leave error messages here */
- Select *pSelect /* The SELECT statement containing the ORDER BY */
-){
- int i;
- ExprList *pOrderBy;
- ExprList *pEList;
- sqlite3 *db;
- int moreToDo = 1;
-
- pOrderBy = pSelect->pOrderBy;
- if( pOrderBy==0 ) return 0;
- db = pParse->db;
-#if SQLITE_MAX_COLUMN
- if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
- sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
- return 1;
- }
-#endif
- for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].done = 0;
- }
- while( pSelect->pPrior ){
- pSelect = pSelect->pPrior;
- }
- while( pSelect && moreToDo ){
- moreToDo = 0;
- pEList = pSelect->pEList;
- if( pEList==0 ){
- return 1;
- }
- for(i=0; i<pOrderBy->nExpr; i++){
- int iCol = -1;
- Expr *pE, *pDup;
- if( pOrderBy->a[i].done ) continue;
- pE = pOrderBy->a[i].pExpr;
- if( sqlite3ExprIsInteger(pE, &iCol) ){
- if( iCol<0 || iCol>pEList->nExpr ){
- sqlite3ErrorMsg(pParse,
- "%r ORDER BY term out of range - should be "
- "between 1 and %d", i+1, pEList->nExpr);
- return 1;
- }
- }else{
- pDup = sqlite3ExprDup(db, pE);
- if( !db->mallocFailed ){
- assert(pDup);
- iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
- }
- sqlite3ExprDelete(db, pDup);
- if( iCol<0 ){
- return 1;
- }
- }
- if( iCol>0 ){
- pE->op = TK_INTEGER;
- pE->flags |= EP_IntValue;
- pE->iTable = iCol;
- pOrderBy->a[i].done = 1;
- }else{
- moreToDo = 1;
- }
- }
- pSelect = pSelect->pNext;
- }
- for(i=0; i<pOrderBy->nExpr; i++){
- if( pOrderBy->a[i].done==0 ){
- sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
- "column in the result set", i+1);
- return 1;
- }
+ pTab->db = db;
+ pTab->nRef = 1;
+ pTab->zName = 0;
+ selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
+ selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
+ pTab->iPKey = -1;
+ if( db->mallocFailed ){
+ sqlite3DeleteTable(pTab);
+ return 0;
}
- return 0;
+ return pTab;
}
/*
@@ -68628,6 +69632,7 @@ static int multiSelect(
pPrior = p->pPrior;
assert( pPrior->pRightmost!=pPrior );
assert( pPrior->pRightmost==p->pRightmost );
+ dest = *pDest;
if( pPrior->pOrderBy ){
sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
selectOpName(p->op));
@@ -68646,7 +69651,6 @@ static int multiSelect(
/* Create the destination temporary table if necessary
*/
- dest = *pDest;
if( dest.eDest==SRT_EphemTab ){
assert( p->pEList );
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr);
@@ -68678,7 +69682,7 @@ static int multiSelect(
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 ){
@@ -68691,7 +69695,7 @@ static int multiSelect(
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 ){
@@ -68726,7 +69730,7 @@ static int multiSelect(
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 );
}
@@ -68734,7 +69738,7 @@ static int multiSelect(
*/
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;
}
@@ -68748,13 +69752,12 @@ static int multiSelect(
op = SRT_Union;
}
p->pPrior = 0;
- p->disallowOrderBy = 0;
pLimit = p->pLimit;
p->pLimit = 0;
pOffset = p->pOffset;
p->pOffset = 0;
uniondest.eDest = op;
- rc = sqlite3Select(pParse, p, &uniondest, 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(db, p->pOrderBy);
@@ -68777,7 +69780,7 @@ static int multiSelect(
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);
@@ -68815,13 +69818,13 @@ static int multiSelect(
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;
}
@@ -68837,7 +69840,7 @@ static int multiSelect(
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(db, p->pLimit);
@@ -68851,7 +69854,7 @@ static int multiSelect(
** 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);
@@ -68884,7 +69887,7 @@ static int multiSelect(
** SELECT might also skip this part if it has no ORDER BY clause and
** no temp tables are required.
*/
- if( p->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 */
@@ -69047,9 +70050,8 @@ static int generateOutputSubroutine(
}
#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 ){
@@ -69061,7 +70063,11 @@ static int generateOutputSubroutine(
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;
@@ -69220,7 +70226,6 @@ static int multiSelectOrderBy(
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 );
db = pParse->db;
@@ -69237,9 +70242,6 @@ static int multiSelectOrderBy(
assert( pPrior->pOrderBy==0 );
pOrderBy = p->pOrderBy;
assert( pOrderBy );
- if( processCompoundOrderBy(pParse, p) ){
- return SQLITE_ERROR;
- }
nOrderBy = pOrderBy->nExpr;
/* For operators other than UNION ALL we have to make sure that
@@ -69248,11 +70250,10 @@ static int multiSelectOrderBy(
*/
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);
@@ -69260,7 +70261,7 @@ static int multiSelectOrderBy(
pNew->flags |= EP_IntValue;
pNew->iTable = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0);
- nOrderBy++;
+ pOrderBy->a[nOrderBy++].iCol = i;
}
}
}
@@ -69274,12 +70275,10 @@ static int multiSelectOrderBy(
*/
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));
@@ -69338,9 +70337,9 @@ static int multiSelectOrderBy(
*/
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 */
@@ -69380,7 +70379,7 @@ static int multiSelectOrderBy(
*/
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"));
@@ -69394,7 +70393,7 @@ static int multiSelectOrderBy(
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);
@@ -69509,7 +70508,7 @@ static int multiSelectOrderBy(
/* 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);
@@ -69647,8 +70646,8 @@ static void substSelect(
**
** (2) The subquery is not an aggregate or the outer query is not a join.
**
-** (3) The subquery is not the right operand of a left outer join, 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.
**
@@ -69670,8 +70669,8 @@ static void substSelect(
**
** (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
**
@@ -69701,6 +70700,9 @@ static void substSelect(
** ORDER by clause of the parent must be simple references to
** columns of the sub-query.
**
+** (19) The subquery does not use LIMIT or the outer query does not
+** have a WHERE clause.
+**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
@@ -69755,17 +70757,21 @@ static int flattenSubquery(
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) */
+ if( pSub->pLimit && p->pWhere ) return 0; /* Restriction (19) */
- /* Restriction 3: If the subquery is a join, make sure the subquery is
+ /* 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:
**
@@ -69776,12 +70782,9 @@ static int flattenSubquery(
** (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:
**
@@ -69793,8 +70796,13 @@ static int flattenSubquery(
**
** But the t2.x>0 test will always fail on a NULL row of t2, which
** effectively converts the OUTER JOIN into an INNER JOIN.
+ **
+ ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
+ ** Ticket #3300 shows that flattening the right term of a LEFT JOIN
+ ** is fraught with danger. Best to avoid the whole thing. If the
+ ** subquery is the right term of a LEFT JOIN, then do not flatten.
*/
- if( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){
+ if( (pSubitem->jointype & JT_OUTER)!=0 ){
return 0;
}
@@ -69804,11 +70812,11 @@ static int flattenSubquery(
** 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
){
@@ -69820,20 +70828,21 @@ static int flattenSubquery(
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>
**
@@ -69865,8 +70874,8 @@ static int flattenSubquery(
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){
@@ -69970,7 +70979,7 @@ static int flattenSubquery(
/* 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;
@@ -70023,133 +71032,369 @@ static int minMaxQuery(Parse *pParse, Select *p){
}
/*
-** 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.
+** 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.
+**
*/
-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;
+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 there have already been errors, do nothing. */
- if( pParse->nErr>0 ){
- return SQLITE_ERROR;
+ if( db->mallocFailed ){
+ return WRC_Abort;
}
-
- /* 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;
+ if( p->pSrc==0 || (p->selFlags & SF_Expanded)!=0 ){
+ return WRC_Prune;
}
+ p->selFlags |= SF_Expanded;
+ pTabList = p->pSrc;
+ pEList = p->pEList;
- /* Resolve the expressions in the LIMIT and OFFSET clauses. These
- ** are not allowed to refer to any names, so pass an empty NameContext.
+ /* Make sure cursor numbers have been assigned to all entries in
+ ** the FROM clause of the SELECT statement.
*/
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- if( sqlite3ExprResolveNames(&sNC, p->pLimit) ||
- sqlite3ExprResolveNames(&sNC, p->pOffset) ){
- return SQLITE_ERROR;
- }
+ sqlite3SrcListAssignCursors(pParse, pTabList);
- /* Set up the local name-context to pass to ExprResolveNames() to
- ** resolve the expression-list.
+ /* 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.
*/
- sNC.allowAgg = 1;
- sNC.pSrcList = p->pSrc;
- sNC.pNext = pOuterNC;
-
- /* Resolve names in the result set. */
- pEList = p->pEList;
- if( !pEList ) return SQLITE_ERROR;
- for(i=0; i<pEList->nExpr; i++){
- Expr *pX = pEList->a[i].pExpr;
- if( sqlite3ExprResolveNames(&sNC, pX) ){
- return SQLITE_ERROR;
+ 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 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 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
+ }
}
- /* If a HAVING clause is present, then there must be a GROUP BY clause.
+ /* Process NATURAL keywords, and ON and USING clauses of joins.
*/
- if( p->pHaving && !pGroupBy ){
- sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- return SQLITE_ERROR;
+ if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+ 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.
+ /* 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.
**
- ** Minor point: If this is the case, then the expression will be
- ** re-evaluated for each reference to it.
+ ** The first loop just checks to see if there are any "*" operators
+ ** that need expanding.
*/
- sNC.pEList = p->pEList;
- if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||
- sqlite3ExprResolveNames(&sNC, p->pHaving) ){
- return SQLITE_ERROR;
+ 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( p->pPrior==0 ){
- if( processOrderGroupBy(pParse, p, p->pOrderBy, 1, &sNC.hasAgg) ){
- return SQLITE_ERROR;
+ if( k<pEList->nExpr ){
+ /*
+ ** If we get here it means the result set contains one or more "*"
+ ** operators that need to be expanded. Loop through each expression
+ ** in the result set and expand them one by one.
+ */
+ struct ExprList_item *a = pEList->a;
+ ExprList *pNew = 0;
+ int flags = pParse->db->flags;
+ int longNames = (flags & SQLITE_FullColNames)!=0
+ && (flags & SQLITE_ShortColNames)==0;
+
+ for(k=0; k<pEList->nExpr; k++){
+ Expr *pE = a[k].pExpr;
+ if( pE->op!=TK_ALL &&
+ (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
+ /* This particular expression does not need to be expanded.
+ */
+ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr, 0);
+ if( pNew ){
+ pNew->a[pNew->nExpr-1].zName = a[k].zName;
+ }
+ a[k].pExpr = 0;
+ a[k].zName = 0;
+ }else{
+ /* This expression is a "*" or a "TABLE.*" and needs to be
+ ** expanded. */
+ int tableSeen = 0; /* Set to 1 when TABLE matches */
+ char *zTName; /* text of name of TABLE */
+ if( pE->op==TK_DOT && pE->pLeft ){
+ zTName = sqlite3NameFromToken(db, &pE->pLeft->token);
+ }else{
+ zTName = 0;
+ }
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+ Table *pTab = pFrom->pTab;
+ char *zTabName = pFrom->zAlias;
+ if( zTabName==0 || zTabName[0]==0 ){
+ zTabName = pTab->zName;
+ }
+ if( db->mallocFailed ) break;
+ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+ continue;
+ }
+ tableSeen = 1;
+ for(j=0; j<pTab->nCol; j++){
+ Expr *pExpr, *pRight;
+ char *zName = pTab->aCol[j].zName;
+
+ /* If a column is marked as 'hidden' (currently only possible
+ ** for virtual tables), do not include it in the expanded
+ ** result-set list.
+ */
+ if( IsHiddenColumn(&pTab->aCol[j]) ){
+ assert(IsVirtual(pTab));
+ continue;
+ }
+
+ if( i>0 ){
+ struct SrcList_item *pLeft = &pTabList->a[i-1];
+ if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
+ columnIndex(pLeft->pTab, zName)>=0 ){
+ /* In a NATURAL join, omit the join columns from the
+ ** table on the right */
+ continue;
+ }
+ if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
+ /* In a join with a USING clause, omit columns in the
+ ** using clause from the table on the right. */
+ continue;
+ }
+ }
+ pRight = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+ if( pRight==0 ) break;
+ setQuotedToken(pParse, &pRight->token, zName);
+ if( longNames || pTabList->nSrc>1 ){
+ Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, 0);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ if( pExpr==0 ) break;
+ setQuotedToken(pParse, &pLeft->token, zTabName);
+ setToken(&pExpr->span,
+ sqlite3MPrintf(db, "%s.%s", zTabName, zName));
+ pExpr->span.dyn = 1;
+ pExpr->token.z = 0;
+ pExpr->token.n = 0;
+ pExpr->token.dyn = 0;
+ }else{
+ pExpr = pRight;
+ pExpr->span = pExpr->token;
+ pExpr->span.dyn = 0;
+ }
+ if( longNames ){
+ pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pExpr->span);
+ }else{
+ pNew = sqlite3ExprListAppend(pParse, pNew, pExpr, &pRight->token);
+ }
+ }
+ }
+ if( !tableSeen ){
+ if( zTName ){
+ sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
+ }else{
+ sqlite3ErrorMsg(pParse, "no tables specified");
+ }
+ }
+ sqlite3DbFree(db, zTName);
+ }
}
+ sqlite3ExprListDelete(db, pEList);
+ p->pEList = pNew;
}
- if( processOrderGroupBy(pParse, p, pGroupBy, 0, &sNC.hasAgg) ){
- return SQLITE_ERROR;
+#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;
+}
- if( pParse->db->mallocFailed ){
- return SQLITE_NOMEM;
- }
+/*
+** 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;
+}
- /* 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;
+/*
+** 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
- /* 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;
- }
+
+/*
+** 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);
}
/*
@@ -70259,7 +71504,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
}
/*
-** 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
@@ -70267,33 +71512,43 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
**
** pDest->eDest Result
** ------------ -------------------------------------------
-** SRT_Callback Invoke the callback for each row of the result.
+** SRT_Output Generate a row of output (using the OP_ResultRow
+** opcode) for each row in the result set.
**
-** SRT_Mem Store first result in memory cell pDest->iParm
+** 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 Store results as keys of table pDest->iParm.
-** Apply the affinity pDest->affinity before storing them.
+** 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.
+** returning. This is like SRT_Table except that
+** this destination uses OP_OpenEphemeral to create
+** the table first.
**
-** SRT_Coroutine Invoke a co-routine to compute a single row of
-** the result
+** 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
@@ -70301,35 +71556,11 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
**
** This routine does NOT free the Select structure passed in. The
** calling function needs to do that.
-**
-** The pParent, parentTab, and *pParentAgg fields are filled in if this
-** SELECT is a subquery. This routine may try to combine this SELECT
-** with its parent to form a single flat query. In so doing, it might
-** change the parent query from a non-aggregate to an aggregate query.
-** For that reason, the pParentAgg flag is passed as a pointer, so it
-** can be changed.
-**
-** Example 1: The meaning of the pParent parameter.
-**
-** SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3;
-** \ \_______ subquery _______/ /
-** \ /
-** \____________________ outer query ___________________/
-**
-** This routine is called for the outer query first. For that call,
-** pParent will be NULL. During the processing of the outer query, this
-** routine is called recursively to handle the subquery. For the recursive
-** call, pParent will point to the outer query. Because the subquery is
-** the second element in a three-way join, the parentTab parameter will
-** be 1 (the 2nd value of a 0-indexed array.)
*/
SQLITE_PRIVATE int sqlite3Select(
Parse *pParse, /* The parser context */
Select *p, /* The SELECT statement being coded. */
- SelectDest *pDest, /* What to do with the query results */
- 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() */
@@ -70365,9 +71596,10 @@ SQLITE_PRIVATE int sqlite3Select(
*/
assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
- p->isDistinct = 0;
+ p->selFlags &= ~SF_Distinct;
}
- if( sqlite3SelectResolve(pParse, p, 0) ){
+ sqlite3SelectPrep(pParse, p, 0);
+ if( pParse->nErr ){
goto select_end;
}
p->pOrderBy = pOrderBy;
@@ -70376,7 +71608,7 @@ SQLITE_PRIVATE int sqlite3Select(
/* 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;
@@ -70405,18 +71637,8 @@ SQLITE_PRIVATE int sqlite3Select(
SelectDest dest;
Select *pSub = pItem->pSelect;
int isAggSub;
- char *zName = pItem->zName;
if( pSub==0 || pItem->isPopulated ) continue;
- if( zName!=0 ){ /* An sql view */
- const char *zSavedAuthContext = pParse->zAuthContext;
- pParse->zAuthContext = zName;
- rc = sqlite3SelectResolve(pParse, pSub, 0);
- pParse->zAuthContext = zSavedAuthContext;
- if( rc ){
- goto select_end;
- }
- }
/* Increment Parse.nHeight by the height of the largest expression
** tree refered to by this, the parent select. The child select
@@ -70428,15 +71650,18 @@ SQLITE_PRIVATE int sqlite3Select(
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;
@@ -70452,7 +71677,7 @@ SQLITE_PRIVATE int sqlite3Select(
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.
@@ -70487,12 +71712,12 @@ SQLITE_PRIVATE int sqlite3Select(
#endif
/* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
- ** GROUP BY may use an index, DISTINCT never does.
+ ** GROUP BY might use an index, DISTINCT never does.
*/
- if( p->isDistinct && !p->isAgg && !p->pGroupBy ){
+ 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;
}
@@ -70726,20 +71951,14 @@ SQLITE_PRIVATE int sqlite3Select(
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
if( pCol->iSorterColumn>=j ){
int r1 = j + regBase;
-#ifndef NDEBUG
- int r2 =
-#endif
- sqlite3ExprCodeGetColumn(pParse,
+ int r2;
+
+ r2 = sqlite3ExprCodeGetColumn(pParse,
pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
+ if( r1!=r2 ){
+ sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
+ }
j++;
-
- /* sAggInfo.aCol[] only contains one entry per column. So
- ** The reference to pCol->iColumn,pCol->iTable must have been
- ** the first reference to that column. Hence,
- ** sqliteExprCodeGetColumn is guaranteed to put the result in
- ** the column requested.
- */
- assert( r1==r2 );
}
}
regRecord = sqlite3GetTempReg(pParse);
@@ -70888,19 +72107,6 @@ SQLITE_PRIVATE int sqlite3Select(
generateSortTail(pParse, p, v, pEList->nExpr, pDest);
}
-#ifndef SQLITE_OMIT_SUBQUERY
- /* If this was a subquery, we have now converted the subquery into a
- ** temporary table. So set the SrcList_item.isPopulated flag to prevent
- ** this subquery from being evaluated again and to force the use of
- ** the temporary table.
- */
- if( pParent ){
- assert( pParent->pSrc->nSrc>parentTab );
- assert( pParent->pSrc->a[parentTab].pSelect==p );
- pParent->pSrc->a[parentTab].isPopulated = 1;
- }
-#endif
-
/* Jump here to skip this query
*/
sqlite3VdbeResolveLabel(v, iEnd);
@@ -70915,10 +72121,9 @@ SQLITE_PRIVATE int sqlite3Select(
*/
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.
+ /* Identify column names if results of the SELECT are to be output.
*/
- if( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){
+ if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
generateColumnNames(pParse, pTabList, pEList);
}
@@ -71906,8 +73111,7 @@ static int codeTriggerProgram(
SelectDest dest;
sqlite3SelectDestInit(&dest, SRT_Discard, 0);
- sqlite3SelectResolve(pParse, ss, 0);
- sqlite3Select(pParse, ss, &dest, 0, 0, 0);
+ sqlite3Select(pParse, ss, &dest);
sqlite3SelectDelete(db, ss);
}
break;
@@ -72056,7 +73260,7 @@ SQLITE_PRIVATE int sqlite3CodeRowTrigger(
/* 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(db, whenExpr);
return 1;
@@ -72276,7 +73480,7 @@ SQLITE_PRIVATE void sqlite3Update(
*/
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++){
@@ -72411,13 +73615,13 @@ SQLITE_PRIVATE void sqlite3Update(
** a ephemeral table.
*/
if( isView ){
- sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, iCur);
+ sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
}
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
- if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+ if( sqlite3ResolveExprNames(&sNC, pWhere) ){
goto update_cleanup;
}
@@ -72731,7 +73935,7 @@ static void updateVirtualTable(
/* 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;
@@ -72842,12 +74046,14 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
+ Pager *pMainPager; /* Pager for database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
char *zSql = 0; /* SQL statements */
int saved_flags; /* Saved value of the db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
Db *pDb = 0; /* Database to detach at end of vacuum */
+ int isMemDb; /* True is vacuuming a :memory: database */
int nRes;
/* Save the current value of the write-schema flag before setting it. */
@@ -72862,6 +74068,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
goto end_of_vacuum;
}
pMain = db->aDb[0].pBt;
+ pMainPager = sqlite3BtreePager(pMain);
+ isMemDb = sqlite3PagerFile(pMainPager)->pMethods==0;
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
@@ -72898,7 +74106,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
#endif
if( sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain), nRes)
- || sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes)
+ || (!isMemDb && sqlite3BtreeSetPageSize(pTemp, db->nextPagesize, nRes))
|| db->mallocFailed
){
rc = SQLITE_NOMEM;
@@ -73019,6 +74227,9 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
+#endif
rc = sqlite3BtreeCommit(pMain);
}
@@ -73242,7 +74453,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
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));
@@ -73498,7 +74709,7 @@ 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;
}
@@ -73559,7 +74770,7 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab,
const char *zModule;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
- assert(pTab && pTab->isVirtual && !pTab->pVtab);
+ assert(pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVtab);
pMod = pTab->pMod;
zModule = pTab->azModuleArg[0];
@@ -73600,7 +74811,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
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;
@@ -73610,7 +74821,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) &&
sParse.pNewTable &&
!sParse.pNewTable->pSelect &&
- !sParse.pNewTable->isVirtual
+ (sParse.pNewTable->tabFlags & TF_Virtual)==0
){
pTab->aCol = sParse.pNewTable->aCol;
pTab->nCol = sParse.pNewTable->nCol;
@@ -73829,7 +75040,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
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 );
@@ -73863,6 +75074,7 @@ SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(
return pDef;
}
*pNew = *pDef;
+ pNew->zName = (char *)&pNew[1];
memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1);
pNew->xFunc = xFunc;
pNew->pUserData = pArg;
@@ -74216,9 +75428,9 @@ static void createMask(ExprMaskSet *pMaskSet, int iCursor){
** 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
@@ -74292,10 +75504,12 @@ static int allowedOp(int op){
** 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;
@@ -74415,7 +75629,7 @@ static void exprAnalyzeAll(
** 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 */
@@ -74427,6 +75641,7 @@ static int isLikeOrGlob(
int c, cnt;
char wc[3];
CollSeq *pColl;
+ sqlite3 *db = pParse->db;
if( !sqlite3IsLikeFunction(db, pExpr, pnoCase, wc) ){
return 0;
@@ -74444,7 +75659,7 @@ static int isLikeOrGlob(
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. */
@@ -74684,7 +75899,7 @@ static void exprAnalyze(
pDup = pExpr;
pNew = pTerm;
}
- exprCommute(pDup);
+ exprCommute(pParse, pDup);
pLeft = pDup->pLeft;
pNew->leftCursor = pLeft->iTable;
pNew->leftColumn = pLeft->iColumn;
@@ -74805,7 +76020,7 @@ or_not_possible:
** 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;
@@ -75179,7 +76394,7 @@ static double bestVirtualIndex(
** to this virtual table */
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- 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;
@@ -75229,7 +76444,7 @@ static double bestVirtualIndex(
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;
@@ -76174,7 +77389,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
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;
@@ -76733,7 +77948,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
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);
}
@@ -76883,23 +78098,23 @@ struct AttachKey { int type; Token key; };
** defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
-#define YYNOCODE 248
+#define YYNOCODE 247
#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;
+ struct TrigEvent yy30;
+ Expr* yy62;
+ SrcList* yy151;
+ struct LimitVal yy220;
+ struct LikeOp yy222;
+ IdList* yy240;
+ int yy280;
+ struct {int value; int mask;} yy359;
+ TriggerStep* yy360;
+ Select* yy375;
+ ExprList* yy418;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -76908,8 +78123,8 @@ typedef union {
#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 590
+#define YYNRULE 312
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
@@ -76917,7 +78132,11 @@ typedef union {
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
+#if 0
+static YYMINORTYPE yyzerominor;
+#else
static const YYMINORTYPE yyzerominor;
+#endif
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
@@ -76967,416 +78186,417 @@ static const YYMINORTYPE yyzerominor;
** 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 */ 292, 903, 120, 589, 2, 172, 419, 419, 62, 62,
+ /* 10 */ 62, 62, 209, 64, 64, 64, 64, 65, 65, 66,
+ /* 20 */ 66, 66, 67, 211, 392, 389, 426, 432, 69, 64,
+ /* 30 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 211,
+ /* 40 */ 448, 213, 397, 452, 61, 60, 297, 436, 437, 433,
+ /* 50 */ 433, 63, 63, 62, 62, 62, 62, 264, 64, 64,
+ /* 60 */ 64, 64, 65, 65, 66, 66, 66, 67, 211, 292,
+ /* 70 */ 317, 419, 419, 490, 211, 83, 68, 421, 70, 154,
+ /* 80 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
+ /* 90 */ 211, 489, 415, 36, 181, 426, 432, 448, 265, 59,
+ /* 100 */ 65, 65, 66, 66, 66, 67, 211, 398, 399, 423,
+ /* 110 */ 423, 423, 292, 61, 60, 297, 436, 437, 433, 433,
+ /* 120 */ 63, 63, 62, 62, 62, 62, 317, 64, 64, 64,
+ /* 130 */ 64, 65, 65, 66, 66, 66, 67, 211, 426, 432,
+ /* 140 */ 95, 313, 394, 475, 237, 172, 208, 419, 415, 35,
+ /* 150 */ 57, 67, 211, 201, 411, 475, 61, 60, 297, 436,
+ /* 160 */ 437, 433, 433, 63, 63, 62, 62, 62, 62, 503,
+ /* 170 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
+ /* 180 */ 211, 292, 481, 524, 542, 573, 109, 416, 541, 452,
+ /* 190 */ 331, 317, 408, 21, 240, 340, 409, 522, 317, 68,
+ /* 200 */ 362, 70, 154, 572, 571, 519, 492, 426, 432, 149,
+ /* 210 */ 150, 380, 419, 415, 42, 412, 151, 533, 202, 490,
+ /* 220 */ 415, 50, 532, 421, 292, 61, 60, 297, 436, 437,
+ /* 230 */ 433, 433, 63, 63, 62, 62, 62, 62, 388, 64,
+ /* 240 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 211,
+ /* 250 */ 426, 432, 416, 333, 216, 423, 423, 423, 66, 66,
+ /* 260 */ 66, 67, 211, 491, 568, 212, 308, 292, 61, 60,
+ /* 270 */ 297, 436, 437, 433, 433, 63, 63, 62, 62, 62,
+ /* 280 */ 62, 397, 64, 64, 64, 64, 65, 65, 66, 66,
+ /* 290 */ 66, 67, 211, 426, 432, 182, 300, 410, 345, 348,
+ /* 300 */ 349, 531, 506, 252, 68, 519, 70, 154, 530, 350,
+ /* 310 */ 231, 61, 60, 297, 436, 437, 433, 433, 63, 63,
+ /* 320 */ 62, 62, 62, 62, 575, 64, 64, 64, 64, 65,
+ /* 330 */ 65, 66, 66, 66, 67, 211, 525, 317, 303, 78,
+ /* 340 */ 292, 238, 300, 511, 485, 153, 398, 399, 182, 494,
+ /* 350 */ 495, 345, 348, 349, 320, 152, 439, 439, 339, 415,
+ /* 360 */ 28, 328, 350, 512, 222, 370, 426, 432, 547, 495,
+ /* 370 */ 164, 114, 244, 343, 249, 344, 176, 583, 291, 416,
+ /* 380 */ 415, 3, 81, 253, 61, 60, 297, 436, 437, 433,
+ /* 390 */ 433, 63, 63, 62, 62, 62, 62, 174, 64, 64,
+ /* 400 */ 64, 64, 65, 65, 66, 66, 66, 67, 211, 292,
+ /* 410 */ 222, 587, 894, 488, 894, 302, 573, 114, 244, 343,
+ /* 420 */ 249, 344, 176, 182, 317, 397, 345, 348, 349, 253,
+ /* 430 */ 224, 416, 155, 549, 572, 426, 432, 350, 68, 463,
+ /* 440 */ 70, 154, 397, 175, 160, 397, 415, 35, 338, 587,
+ /* 450 */ 893, 584, 893, 61, 60, 297, 436, 437, 433, 433,
+ /* 460 */ 63, 63, 62, 62, 62, 62, 416, 64, 64, 64,
+ /* 470 */ 64, 65, 65, 66, 66, 66, 67, 211, 292, 550,
+ /* 480 */ 448, 213, 505, 373, 270, 269, 171, 160, 331, 584,
+ /* 490 */ 398, 399, 317, 330, 209, 383, 212, 159, 427, 428,
+ /* 500 */ 569, 570, 483, 524, 426, 432, 336, 398, 399, 230,
+ /* 510 */ 398, 399, 534, 21, 415, 42, 239, 549, 479, 430,
+ /* 520 */ 431, 475, 61, 60, 297, 436, 437, 433, 433, 63,
+ /* 530 */ 63, 62, 62, 62, 62, 264, 64, 64, 64, 64,
+ /* 540 */ 65, 65, 66, 66, 66, 67, 211, 292, 429, 287,
+ /* 550 */ 457, 256, 450, 523, 168, 215, 197, 295, 317, 353,
+ /* 560 */ 242, 317, 458, 298, 443, 444, 468, 373, 270, 269,
+ /* 570 */ 322, 443, 444, 426, 432, 459, 558, 496, 209, 299,
+ /* 580 */ 415, 35, 544, 415, 50, 1, 177, 497, 479, 397,
+ /* 590 */ 416, 61, 60, 297, 436, 437, 433, 433, 63, 63,
+ /* 600 */ 62, 62, 62, 62, 484, 64, 64, 64, 64, 65,
+ /* 610 */ 65, 66, 66, 66, 67, 211, 292, 317, 524, 375,
+ /* 620 */ 457, 94, 335, 590, 392, 389, 212, 580, 21, 309,
+ /* 630 */ 10, 363, 458, 212, 397, 209, 366, 391, 2, 415,
+ /* 640 */ 29, 294, 426, 432, 195, 459, 253, 327, 372, 361,
+ /* 650 */ 440, 450, 323, 168, 398, 399, 252, 147, 546, 292,
+ /* 660 */ 61, 60, 297, 436, 437, 433, 433, 63, 63, 62,
+ /* 670 */ 62, 62, 62, 317, 64, 64, 64, 64, 65, 65,
+ /* 680 */ 66, 66, 66, 67, 211, 426, 432, 210, 318, 453,
+ /* 690 */ 320, 223, 439, 439, 56, 415, 24, 826, 252, 398,
+ /* 700 */ 399, 193, 292, 61, 60, 297, 436, 437, 433, 433,
+ /* 710 */ 63, 63, 62, 62, 62, 62, 226, 64, 64, 64,
+ /* 720 */ 64, 65, 65, 66, 66, 66, 67, 211, 426, 432,
+ /* 730 */ 311, 119, 264, 304, 396, 416, 320, 19, 439, 439,
+ /* 740 */ 400, 401, 402, 85, 274, 292, 61, 71, 297, 436,
+ /* 750 */ 437, 433, 433, 63, 63, 62, 62, 62, 62, 371,
+ /* 760 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
+ /* 770 */ 211, 426, 432, 385, 115, 320, 18, 439, 439, 446,
+ /* 780 */ 446, 374, 277, 5, 275, 264, 8, 252, 292, 341,
+ /* 790 */ 60, 297, 436, 437, 433, 433, 63, 63, 62, 62,
+ /* 800 */ 62, 62, 397, 64, 64, 64, 64, 65, 65, 66,
+ /* 810 */ 66, 66, 67, 211, 426, 432, 414, 397, 422, 470,
+ /* 820 */ 413, 22, 305, 387, 252, 419, 560, 193, 414, 264,
+ /* 830 */ 264, 370, 413, 190, 297, 436, 437, 433, 433, 63,
+ /* 840 */ 63, 62, 62, 62, 62, 479, 64, 64, 64, 64,
+ /* 850 */ 65, 65, 66, 66, 66, 67, 211, 73, 324, 306,
+ /* 860 */ 4, 416, 264, 276, 296, 449, 177, 398, 399, 317,
+ /* 870 */ 561, 562, 321, 73, 324, 317, 4, 540, 360, 540,
+ /* 880 */ 296, 329, 398, 399, 461, 371, 158, 317, 321, 326,
+ /* 890 */ 419, 415, 33, 471, 317, 165, 225, 415, 54, 452,
+ /* 900 */ 317, 264, 317, 278, 317, 326, 307, 367, 472, 415,
+ /* 910 */ 53, 470, 178, 179, 180, 452, 415, 99, 317, 76,
+ /* 920 */ 75, 294, 415, 97, 415, 102, 415, 103, 74, 315,
+ /* 930 */ 316, 319, 264, 421, 469, 76, 75, 482, 317, 382,
+ /* 940 */ 415, 108, 379, 474, 74, 315, 316, 73, 324, 421,
+ /* 950 */ 4, 209, 317, 156, 296, 317, 184, 465, 209, 187,
+ /* 960 */ 415, 110, 321, 258, 466, 423, 423, 423, 424, 425,
+ /* 970 */ 12, 381, 478, 280, 415, 17, 250, 415, 100, 326,
+ /* 980 */ 507, 423, 423, 423, 424, 425, 12, 416, 624, 452,
+ /* 990 */ 416, 162, 508, 416, 317, 513, 227, 228, 229, 105,
+ /* 1000 */ 514, 262, 317, 260, 20, 317, 144, 434, 317, 76,
+ /* 1010 */ 75, 77, 206, 79, 282, 317, 415, 34, 74, 315,
+ /* 1020 */ 316, 283, 317, 421, 415, 98, 251, 415, 25, 526,
+ /* 1030 */ 415, 55, 441, 204, 23, 549, 257, 415, 111, 203,
+ /* 1040 */ 317, 477, 205, 173, 415, 112, 317, 259, 317, 515,
+ /* 1050 */ 317, 181, 317, 261, 245, 423, 423, 423, 424, 425,
+ /* 1060 */ 12, 263, 415, 113, 357, 246, 317, 268, 415, 26,
+ /* 1070 */ 415, 37, 415, 38, 415, 27, 317, 500, 501, 510,
+ /* 1080 */ 509, 317, 365, 317, 368, 378, 279, 269, 415, 39,
+ /* 1090 */ 369, 293, 317, 255, 317, 181, 209, 271, 415, 40,
+ /* 1100 */ 317, 272, 317, 415, 41, 415, 43, 352, 317, 181,
+ /* 1110 */ 317, 273, 557, 317, 415, 44, 415, 45, 317, 545,
+ /* 1120 */ 384, 181, 415, 30, 415, 31, 317, 585, 567, 317,
+ /* 1130 */ 415, 46, 415, 47, 317, 415, 48, 317, 281, 284,
+ /* 1140 */ 415, 49, 553, 554, 173, 92, 285, 579, 415, 32,
+ /* 1150 */ 406, 415, 11, 565, 420, 92, 415, 51, 146, 415,
+ /* 1160 */ 52, 582, 232, 290, 325, 517, 586, 445, 447, 464,
+ /* 1170 */ 467, 506, 520, 163, 247, 516, 395, 518, 552, 347,
+ /* 1180 */ 403, 404, 405, 564, 7, 314, 85, 334, 332, 233,
+ /* 1190 */ 84, 234, 80, 170, 58, 214, 417, 462, 121, 86,
+ /* 1200 */ 337, 342, 499, 493, 235, 301, 236, 503, 418, 498,
+ /* 1210 */ 248, 124, 504, 502, 220, 354, 288, 241, 527, 476,
+ /* 1220 */ 243, 528, 480, 521, 529, 289, 185, 358, 535, 186,
+ /* 1230 */ 89, 356, 189, 188, 117, 537, 364, 191, 548, 194,
+ /* 1240 */ 219, 132, 142, 221, 376, 377, 555, 133, 134, 310,
+ /* 1250 */ 135, 136, 266, 563, 538, 581, 576, 141, 93, 393,
+ /* 1260 */ 96, 138, 407, 577, 578, 107, 218, 101, 104, 118,
+ /* 1270 */ 312, 625, 626, 166, 435, 167, 438, 442, 72, 454,
+ /* 1280 */ 451, 143, 157, 169, 455, 456, 460, 6, 14, 82,
+ /* 1290 */ 473, 13, 122, 161, 123, 486, 487, 217, 87, 346,
+ /* 1300 */ 125, 126, 116, 254, 88, 127, 183, 246, 355, 145,
+ /* 1310 */ 536, 128, 173, 359, 192, 351, 267, 130, 9, 551,
+ /* 1320 */ 131, 196, 90, 539, 91, 129, 15, 198, 556, 543,
+ /* 1330 */ 199, 559, 200, 137, 139, 566, 16, 140, 106, 574,
+ /* 1340 */ 207, 148, 286, 390, 386, 588,
};
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, 139, 140, 141, 142, 21, 23, 23, 69, 70,
+ /* 10 */ 71, 72, 110, 74, 75, 76, 77, 78, 79, 80,
+ /* 20 */ 81, 82, 83, 84, 1, 2, 42, 43, 73, 74,
/* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 40 */ 1, 2, 23, 58, 60, 61, 62, 63, 64, 65,
+ /* 40 */ 78, 79, 23, 58, 60, 61, 62, 63, 64, 65,
/* 50 */ 66, 67, 68, 69, 70, 71, 72, 147, 74, 75,
/* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 70 */ 185, 186, 88, 88, 110, 22, 217, 92, 219, 220,
+ /* 70 */ 147, 88, 88, 88, 84, 22, 217, 92, 219, 220,
/* 80 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 90 */ 84, 217, 218, 219, 220, 42, 43, 238, 188, 46,
+ /* 90 */ 84, 169, 169, 170, 22, 42, 43, 78, 188, 46,
/* 100 */ 78, 79, 80, 81, 82, 83, 84, 88, 89, 124,
/* 110 */ 125, 126, 16, 60, 61, 62, 63, 64, 65, 66,
/* 120 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76,
/* 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,
+ /* 140 */ 44, 143, 144, 161, 221, 21, 148, 23, 169, 170,
+ /* 150 */ 19, 83, 84, 155, 23, 161, 60, 61, 62, 63,
+ /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 97,
/* 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,
+ /* 180 */ 84, 16, 200, 147, 25, 147, 21, 189, 29, 58,
+ /* 190 */ 211, 147, 156, 157, 200, 216, 167, 168, 147, 217,
+ /* 200 */ 41, 219, 220, 165, 166, 176, 160, 42, 43, 78,
+ /* 210 */ 79, 213, 88, 169, 170, 169, 180, 181, 155, 88,
+ /* 220 */ 169, 170, 181, 92, 16, 60, 61, 62, 63, 64,
+ /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 240, 74,
/* 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,
+ /* 250 */ 42, 43, 189, 209, 210, 124, 125, 126, 80, 81,
+ /* 260 */ 82, 83, 84, 169, 226, 227, 215, 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,
+ /* 290 */ 82, 83, 84, 42, 43, 90, 16, 168, 93, 94,
+ /* 300 */ 95, 176, 177, 147, 217, 176, 219, 220, 183, 104,
+ /* 310 */ 190, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ /* 320 */ 69, 70, 71, 72, 237, 74, 75, 76, 77, 78,
+ /* 330 */ 79, 80, 81, 82, 83, 84, 181, 147, 182, 131,
+ /* 340 */ 16, 147, 16, 30, 20, 155, 88, 89, 90, 185,
+ /* 350 */ 186, 93, 94, 95, 106, 22, 108, 109, 147, 169,
+ /* 360 */ 170, 186, 104, 50, 84, 147, 42, 43, 185, 186,
+ /* 370 */ 90, 91, 92, 93, 94, 95, 96, 243, 244, 189,
/* 380 */ 169, 170, 131, 103, 60, 61, 62, 63, 64, 65,
/* 390 */ 66, 67, 68, 69, 70, 71, 72, 155, 74, 75,
/* 400 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 410 */ 84, 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,
+ /* 410 */ 84, 19, 20, 20, 22, 102, 147, 91, 92, 93,
+ /* 420 */ 94, 95, 96, 90, 147, 23, 93, 94, 95, 103,
+ /* 430 */ 212, 189, 155, 49, 165, 42, 43, 104, 217, 218,
+ /* 440 */ 219, 220, 23, 201, 202, 23, 169, 170, 206, 19,
+ /* 450 */ 20, 59, 22, 60, 61, 62, 63, 64, 65, 66,
/* 460 */ 67, 68, 69, 70, 71, 72, 189, 74, 75, 76,
- /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 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,
+ /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 11,
+ /* 480 */ 78, 79, 20, 99, 100, 101, 201, 202, 211, 59,
+ /* 490 */ 88, 89, 147, 216, 110, 226, 227, 147, 42, 43,
+ /* 500 */ 98, 99, 80, 147, 42, 43, 147, 88, 89, 153,
+ /* 510 */ 88, 89, 156, 157, 169, 170, 147, 49, 147, 63,
+ /* 520 */ 64, 161, 60, 61, 62, 63, 64, 65, 66, 67,
+ /* 530 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77,
+ /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 92, 158,
+ /* 550 */ 12, 20, 161, 162, 163, 210, 155, 150, 147, 16,
+ /* 560 */ 200, 147, 24, 164, 165, 166, 22, 99, 100, 101,
+ /* 570 */ 164, 165, 166, 42, 43, 37, 188, 39, 110, 208,
+ /* 580 */ 169, 170, 18, 169, 170, 19, 43, 49, 147, 23,
/* 590 */ 189, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 600 */ 69, 70, 71, 72, 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,
+ /* 600 */ 69, 70, 71, 72, 20, 74, 75, 76, 77, 78,
+ /* 610 */ 79, 80, 81, 82, 83, 84, 16, 147, 147, 55,
+ /* 620 */ 12, 21, 211, 0, 1, 2, 227, 156, 157, 215,
+ /* 630 */ 19, 224, 24, 227, 23, 110, 229, 141, 142, 169,
+ /* 640 */ 170, 98, 42, 43, 22, 37, 103, 39, 123, 208,
+ /* 650 */ 20, 161, 162, 163, 88, 89, 147, 113, 94, 16,
/* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
- /* 670 */ 70, 71, 72, 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,
+ /* 670 */ 70, 71, 72, 147, 74, 75, 76, 77, 78, 79,
+ /* 680 */ 80, 81, 82, 83, 84, 42, 43, 192, 147, 20,
+ /* 690 */ 106, 182, 108, 109, 199, 169, 170, 133, 147, 88,
+ /* 700 */ 89, 155, 16, 60, 61, 62, 63, 64, 65, 66,
+ /* 710 */ 67, 68, 69, 70, 71, 72, 145, 74, 75, 76,
/* 720 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43,
- /* 730 */ 201, 202, 147, 147, 182, 189, 52, 147, 54, 147,
- /* 740 */ 147, 147, 147, 147, 155, 16, 60, 61, 62, 63,
+ /* 730 */ 241, 242, 147, 182, 147, 189, 106, 19, 108, 109,
+ /* 740 */ 7, 8, 9, 121, 14, 16, 60, 61, 62, 63,
/* 750 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 213,
/* 760 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 770 */ 84, 42, 43, 188, 188, 182, 182, 225, 189, 106,
- /* 780 */ 188, 108, 109, 188, 99, 100, 101, 241, 16, 155,
+ /* 770 */ 84, 42, 43, 188, 147, 106, 230, 108, 109, 124,
+ /* 780 */ 125, 235, 52, 191, 54, 147, 68, 147, 16, 80,
/* 790 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- /* 800 */ 71, 72, 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,
+ /* 800 */ 71, 72, 23, 74, 75, 76, 77, 78, 79, 80,
+ /* 810 */ 81, 82, 83, 84, 42, 43, 107, 23, 147, 22,
+ /* 820 */ 111, 19, 182, 238, 147, 23, 188, 155, 107, 147,
+ /* 830 */ 147, 147, 111, 231, 62, 63, 64, 65, 66, 67,
/* 840 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77,
- /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 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,
+ /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 182,
+ /* 860 */ 19, 189, 147, 133, 23, 161, 43, 88, 89, 147,
+ /* 870 */ 188, 188, 31, 16, 17, 147, 19, 99, 100, 101,
+ /* 880 */ 23, 147, 88, 89, 147, 213, 89, 147, 31, 48,
+ /* 890 */ 88, 169, 170, 114, 147, 19, 212, 169, 170, 58,
+ /* 900 */ 147, 147, 147, 188, 147, 48, 208, 235, 114, 169,
+ /* 910 */ 170, 114, 99, 100, 101, 58, 169, 170, 147, 78,
+ /* 920 */ 79, 98, 169, 170, 169, 170, 169, 170, 87, 88,
+ /* 930 */ 89, 16, 147, 92, 203, 78, 79, 80, 147, 91,
+ /* 940 */ 169, 170, 188, 147, 87, 88, 89, 16, 17, 92,
+ /* 950 */ 19, 110, 147, 155, 23, 147, 155, 27, 110, 155,
+ /* 960 */ 169, 170, 31, 14, 34, 124, 125, 126, 127, 128,
+ /* 970 */ 129, 123, 147, 188, 169, 170, 147, 169, 170, 48,
+ /* 980 */ 147, 124, 125, 126, 127, 128, 129, 189, 112, 58,
+ /* 990 */ 189, 5, 178, 189, 147, 178, 10, 11, 12, 13,
+ /* 1000 */ 178, 52, 147, 54, 19, 147, 21, 92, 147, 78,
+ /* 1010 */ 79, 130, 26, 132, 28, 147, 169, 170, 87, 88,
/* 1020 */ 89, 35, 147, 92, 169, 170, 147, 169, 170, 147,
- /* 1030 */ 169, 170, 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,
+ /* 1030 */ 169, 170, 20, 47, 22, 49, 147, 169, 170, 53,
+ /* 1040 */ 147, 20, 56, 22, 169, 170, 147, 147, 147, 20,
+ /* 1050 */ 147, 22, 147, 147, 92, 124, 125, 126, 127, 128,
+ /* 1060 */ 129, 147, 169, 170, 232, 103, 147, 147, 169, 170,
+ /* 1070 */ 169, 170, 169, 170, 169, 170, 147, 7, 8, 91,
+ /* 1080 */ 92, 147, 147, 147, 147, 99, 100, 101, 169, 170,
+ /* 1090 */ 147, 105, 147, 20, 147, 22, 110, 147, 169, 170,
+ /* 1100 */ 147, 147, 147, 169, 170, 169, 170, 20, 147, 22,
+ /* 1110 */ 147, 147, 147, 147, 169, 170, 169, 170, 147, 20,
+ /* 1120 */ 134, 22, 169, 170, 169, 170, 147, 20, 147, 147,
+ /* 1130 */ 169, 170, 169, 170, 147, 169, 170, 147, 147, 147,
+ /* 1140 */ 169, 170, 20, 20, 22, 22, 147, 147, 169, 170,
+ /* 1150 */ 149, 169, 170, 20, 161, 22, 169, 170, 191, 169,
+ /* 1160 */ 170, 20, 193, 22, 223, 161, 59, 228, 228, 172,
+ /* 1170 */ 172, 177, 161, 6, 172, 172, 146, 172, 194, 173,
+ /* 1180 */ 146, 146, 146, 194, 22, 154, 121, 118, 116, 194,
+ /* 1190 */ 119, 195, 130, 112, 120, 222, 189, 152, 152, 98,
+ /* 1200 */ 115, 98, 179, 171, 196, 40, 197, 97, 198, 171,
+ /* 1210 */ 171, 19, 171, 173, 84, 15, 174, 204, 171, 205,
+ /* 1220 */ 204, 171, 205, 179, 171, 174, 151, 38, 152, 151,
+ /* 1230 */ 130, 152, 152, 151, 60, 152, 152, 151, 184, 184,
+ /* 1240 */ 225, 19, 214, 225, 152, 15, 194, 187, 187, 152,
+ /* 1250 */ 187, 187, 233, 194, 234, 137, 33, 214, 236, 1,
+ /* 1260 */ 236, 184, 20, 152, 152, 239, 175, 159, 175, 242,
+ /* 1270 */ 245, 112, 112, 112, 92, 112, 107, 20, 19, 11,
+ /* 1280 */ 20, 19, 19, 22, 20, 20, 20, 117, 117, 22,
+ /* 1290 */ 114, 22, 19, 112, 20, 20, 20, 44, 19, 44,
+ /* 1300 */ 19, 19, 32, 20, 19, 19, 96, 103, 16, 21,
+ /* 1310 */ 17, 98, 22, 36, 98, 44, 133, 19, 5, 1,
+ /* 1320 */ 102, 122, 68, 51, 68, 45, 19, 113, 1, 45,
+ /* 1330 */ 14, 17, 115, 113, 102, 123, 19, 122, 14, 20,
+ /* 1340 */ 135, 19, 136, 3, 57, 4,
};
-#define YY_SHIFT_USE_DFLT (-62)
-#define YY_SHIFT_MAX 389
+#define YY_SHIFT_USE_DFLT (-99)
+#define YY_SHIFT_MAX 390
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,
+ /* 0 */ 23, 841, 986, -16, 841, 931, 931, 258, 402, 384,
+ /* 10 */ -98, 96, 931, 931, 931, 931, 931, -45, 468, 19,
+ /* 20 */ 419, -17, -38, -38, 53, 165, 208, 251, 324, 393,
+ /* 30 */ 462, 531, 600, 643, 686, 643, 643, 643, 643, 643,
/* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643,
- /* 50 */ 643, 643, 729, 772, 772, 857, 931, 931, 931, 931,
+ /* 50 */ 643, 643, 643, 729, 772, 772, 857, 931, 931, 931,
/* 60 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
/* 70 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
/* 80 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931,
- /* 90 */ 931, 931, 931, 931, 931, 931, -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,
+ /* 90 */ 931, 931, 931, 931, 931, 931, 931, -61, -61, 6,
+ /* 100 */ 6, 280, 22, 178, 543, 564, 419, 419, 68, -17,
+ /* 110 */ -10, -99, -99, -99, 131, 326, 538, 538, 392, 430,
+ /* 120 */ 623, 124, 419, 124, 419, 419, 419, 419, 419, 419,
+ /* 130 */ 419, 419, 419, 419, 419, 419, 419, 419, 419, 419,
+ /* 140 */ 419, 848, 525, -98, -98, -98, -99, -99, -99, -15,
+ /* 150 */ -15, 333, 205, 584, 566, 630, 669, 608, 779, 794,
+ /* 160 */ 611, 422, 733, 419, 419, 709, 419, 419, 802, 419,
+ /* 170 */ 419, 797, 419, 419, 248, 797, 419, 419, 313, 313,
+ /* 180 */ 313, 419, 419, 419, 248, 419, 419, 248, 419, 159,
+ /* 190 */ 778, 419, 419, 248, 419, 419, 419, 248, 419, 419,
+ /* 200 */ 419, 248, 248, 419, 419, 419, 419, 419, 985, 721,
+ /* 210 */ 544, -17, 655, 655, 881, 930, 930, 930, 823, 930,
+ /* 220 */ -17, 930, -17, 72, 622, 622, 1167, 1167, 1167, 1167,
+ /* 230 */ 1162, -98, 1065, 1069, 1071, 1072, 1074, 1062, 1081, 1081,
+ /* 240 */ 1101, 1085, 1101, 1085, 1103, 1103, 1165, 1103, 1110, 1103,
+ /* 250 */ 1192, 1130, 1130, 1165, 1103, 1103, 1103, 1192, 1200, 1081,
+ /* 260 */ 1200, 1081, 1200, 1081, 1081, 1189, 1100, 1200, 1081, 1174,
+ /* 270 */ 1174, 1222, 1065, 1081, 1230, 1230, 1230, 1230, 1065, 1174,
+ /* 280 */ 1222, 1081, 1223, 1223, 1081, 1081, 1118, -99, -99, -99,
+ /* 290 */ -99, -99, 456, 730, 813, 949, 876, 915, 1012, 1021,
+ /* 300 */ 962, 1070, 988, 1029, 1073, 1087, 1099, 1122, 1123, 1133,
+ /* 310 */ 718, 1141, 1107, 1258, 1242, 1159, 1160, 1161, 1163, 1182,
+ /* 320 */ 1169, 1259, 1257, 1260, 1262, 1268, 1263, 1264, 1261, 1265,
+ /* 330 */ 1266, 1267, 1170, 1269, 1171, 1267, 1176, 1273, 1274, 1181,
+ /* 340 */ 1275, 1276, 1270, 1253, 1279, 1255, 1281, 1283, 1282, 1285,
+ /* 350 */ 1271, 1286, 1210, 1204, 1292, 1293, 1288, 1213, 1277, 1272,
+ /* 360 */ 1280, 1290, 1284, 1183, 1216, 1298, 1313, 1318, 1218, 1254,
+ /* 370 */ 1256, 1199, 1307, 1214, 1327, 1316, 1217, 1314, 1220, 1232,
+ /* 380 */ 1215, 1317, 1212, 1319, 1324, 1287, 1205, 1206, 1322, 1340,
+ /* 390 */ 1341,
};
-#define YY_REDUCE_USE_DFLT (-165)
+#define YY_REDUCE_USE_DFLT (-142)
#define YY_REDUCE_MAX 291
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 */ -138, 277, -2, -18, 190, -21, 44, 36, 38, 546,
+ /* 10 */ 242, 87, -77, 345, 411, 51, 414, 221, 672, 269,
+ /* 20 */ 356, 391, 399, 406, -141, -141, -141, -141, -141, -141,
+ /* 30 */ -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+ /* 40 */ -141, -141, -141, -141, -141, -141, -141, -141, -141, -141,
+ /* 50 */ -141, -141, -141, -141, -141, -141, 211, 470, 526, 722,
+ /* 60 */ 728, 740, 747, 753, 755, 757, 771, 791, 805, 808,
+ /* 70 */ 847, 855, 858, 861, 868, 875, 893, 899, 901, 903,
+ /* 80 */ 905, 919, 929, 934, 936, 945, 947, 953, 955, 961,
+ /* 90 */ 963, 966, 971, 979, 982, 987, 990, -141, -141, -141,
+ /* 100 */ -141, 29, -141, -141, 125, 407, 585, 471, -141, 490,
+ /* 110 */ -141, -141, -141, -141, 46, 129, 164, 183, 134, 134,
+ /* 120 */ 496, -6, 371, 360, 156, 509, 551, 640, -90, 441,
+ /* 130 */ 677, 218, 698, 388, 638, 682, 683, 715, 754, 684,
+ /* 140 */ 785, 63, 401, 798, 801, 804, 495, 285, 489, -78,
+ /* 150 */ 94, 41, 155, 120, 194, 120, 120, 175, 350, 359,
+ /* 160 */ 369, 541, 571, 587, 627, 592, 541, 671, 704, 734,
+ /* 170 */ 737, 731, 796, 825, 120, 731, 829, 833, 814, 817,
+ /* 180 */ 822, 879, 882, 889, 120, 900, 906, 120, 914, 602,
+ /* 190 */ 832, 920, 935, 120, 937, 943, 950, 120, 954, 964,
+ /* 200 */ 965, 120, 120, 981, 991, 992, 999, 1000, 1001, 967,
+ /* 210 */ 969, 993, 939, 940, 941, 997, 998, 1002, 994, 1003,
+ /* 220 */ 1004, 1005, 1011, 1006, 984, 989, 1030, 1034, 1035, 1036,
+ /* 230 */ 1031, 1007, 995, 996, 1008, 1009, 1010, 973, 1045, 1046,
+ /* 240 */ 1013, 1014, 1016, 1017, 1032, 1038, 1023, 1039, 1040, 1041,
+ /* 250 */ 1042, 1015, 1018, 1044, 1047, 1050, 1053, 1051, 1075, 1076,
+ /* 260 */ 1078, 1079, 1082, 1080, 1083, 1019, 1020, 1086, 1084, 1054,
+ /* 270 */ 1055, 1028, 1052, 1092, 1060, 1061, 1063, 1064, 1059, 1077,
+ /* 280 */ 1043, 1097, 1022, 1024, 1111, 1112, 1026, 1108, 1091, 1093,
+ /* 290 */ 1027, 1025,
};
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,
+ /* 0 */ 595, 821, 902, 711, 902, 821, 902, 902, 848, 902,
+ /* 10 */ 715, 877, 819, 902, 902, 902, 902, 793, 902, 848,
+ /* 20 */ 902, 627, 848, 848, 744, 902, 902, 902, 902, 902,
+ /* 30 */ 902, 902, 902, 745, 902, 823, 818, 814, 816, 815,
+ /* 40 */ 822, 746, 735, 742, 749, 727, 861, 751, 752, 758,
+ /* 50 */ 759, 878, 876, 781, 780, 799, 902, 902, 902, 902,
/* 60 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
/* 70 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
/* 80 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 90 */ 902, 902, 902, 902, 902, 902, 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,
+ /* 90 */ 902, 902, 902, 902, 902, 902, 902, 783, 805, 782,
+ /* 100 */ 792, 620, 784, 785, 680, 615, 902, 902, 786, 902,
+ /* 110 */ 787, 800, 801, 802, 902, 902, 902, 902, 902, 902,
+ /* 120 */ 595, 711, 902, 711, 902, 902, 902, 902, 902, 902,
/* 130 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 140 */ 902, 902, 902, 902, 902, 902, 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,
+ /* 140 */ 902, 902, 902, 902, 902, 902, 705, 715, 895, 902,
+ /* 150 */ 902, 671, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 160 */ 902, 902, 603, 601, 902, 703, 902, 902, 629, 902,
+ /* 170 */ 902, 713, 902, 902, 718, 719, 902, 902, 902, 902,
+ /* 180 */ 902, 902, 902, 902, 617, 902, 902, 692, 902, 854,
+ /* 190 */ 902, 902, 902, 868, 902, 902, 902, 866, 902, 902,
+ /* 200 */ 902, 694, 754, 834, 902, 881, 883, 902, 902, 703,
+ /* 210 */ 712, 902, 902, 902, 817, 738, 738, 738, 650, 738,
+ /* 220 */ 902, 738, 902, 653, 748, 748, 600, 600, 600, 600,
+ /* 230 */ 670, 902, 748, 739, 741, 731, 743, 902, 720, 720,
+ /* 240 */ 728, 730, 728, 730, 682, 682, 667, 682, 653, 682,
+ /* 250 */ 827, 831, 831, 667, 682, 682, 682, 827, 612, 720,
+ /* 260 */ 612, 720, 612, 720, 720, 858, 860, 612, 720, 684,
+ /* 270 */ 684, 760, 748, 720, 691, 691, 691, 691, 748, 684,
+ /* 280 */ 760, 720, 880, 880, 720, 720, 888, 637, 655, 655,
+ /* 290 */ 895, 900, 902, 902, 902, 902, 767, 902, 902, 902,
/* 300 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 310 */ 841, 902, 902, 902, 902, 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,
+ /* 310 */ 841, 902, 902, 902, 902, 772, 768, 902, 769, 902,
+ /* 320 */ 697, 902, 902, 902, 902, 902, 902, 902, 902, 902,
+ /* 330 */ 902, 820, 902, 732, 902, 740, 902, 902, 902, 902,
/* 340 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
/* 350 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
/* 360 */ 856, 857, 902, 902, 902, 902, 902, 902, 902, 902,
/* 370 */ 902, 902, 902, 902, 902, 902, 902, 902, 902, 902,
- /* 380 */ 902, 902, 902, 902, 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,
+ /* 380 */ 902, 902, 902, 902, 902, 887, 902, 902, 890, 596,
+ /* 390 */ 902, 591, 593, 594, 598, 599, 602, 624, 625, 626,
+ /* 400 */ 604, 605, 606, 607, 608, 609, 610, 616, 618, 636,
+ /* 410 */ 638, 622, 640, 701, 702, 764, 695, 696, 700, 623,
+ /* 420 */ 775, 766, 770, 771, 773, 774, 788, 789, 791, 797,
+ /* 430 */ 804, 807, 790, 795, 796, 798, 803, 806, 698, 699,
+ /* 440 */ 810, 630, 631, 634, 635, 844, 846, 845, 847, 633,
+ /* 450 */ 632, 776, 779, 812, 813, 869, 870, 871, 872, 873,
+ /* 460 */ 808, 721, 811, 794, 733, 736, 737, 734, 704, 714,
+ /* 470 */ 723, 724, 725, 726, 709, 710, 716, 729, 762, 763,
+ /* 480 */ 717, 706, 707, 708, 809, 765, 777, 778, 641, 642,
+ /* 490 */ 772, 643, 644, 645, 683, 686, 687, 688, 646, 665,
+ /* 500 */ 668, 669, 647, 654, 648, 649, 656, 657, 658, 661,
+ /* 510 */ 662, 663, 664, 659, 660, 828, 829, 832, 830, 651,
+ /* 520 */ 652, 666, 639, 628, 621, 672, 675, 676, 677, 678,
+ /* 530 */ 679, 681, 673, 674, 619, 611, 613, 722, 850, 859,
+ /* 540 */ 855, 851, 852, 853, 614, 824, 825, 685, 756, 757,
+ /* 550 */ 849, 862, 864, 761, 865, 867, 863, 892, 689, 690,
+ /* 560 */ 693, 833, 874, 747, 750, 753, 755, 835, 836, 837,
+ /* 570 */ 838, 839, 842, 843, 840, 875, 879, 882, 884, 885,
+ /* 580 */ 886, 889, 891, 896, 897, 898, 901, 899, 597, 592,
};
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
@@ -77642,8 +78862,8 @@ static const char *const yyTokenName[] = {
"VARIABLE", "CASE", "WHEN", "THEN",
"ELSE", "INDEX", "ALTER", "TO",
"ADD", "COLUMNKW", "error", "input",
- "cmdlist", "ecmd", "cmdx", "cmd",
- "explain", "transtype", "trans_opt", "nm",
+ "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",
@@ -77663,12 +78883,12 @@ static const char *const yyTokenName[] = {
"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",
+ "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 */
@@ -77679,12 +78899,12 @@ 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",
@@ -77915,80 +79135,79 @@ static const char *const yyRuleName[] = {
/* 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",
+ /* 239 */ "idxlist ::= idxlist COMMA nm collate sortorder",
+ /* 240 */ "idxlist ::= nm collate sortorder",
+ /* 241 */ "collate ::=",
+ /* 242 */ "collate ::= COLLATE ids",
+ /* 243 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 244 */ "cmd ::= VACUUM",
+ /* 245 */ "cmd ::= VACUUM nm",
+ /* 246 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 247 */ "cmd ::= PRAGMA nm dbnm EQ ON",
+ /* 248 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
+ /* 249 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 250 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 251 */ "cmd ::= PRAGMA nm dbnm",
+ /* 252 */ "nmnum ::= plus_num",
+ /* 253 */ "nmnum ::= nm",
+ /* 254 */ "plus_num ::= plus_opt number",
+ /* 255 */ "minus_num ::= MINUS number",
+ /* 256 */ "number ::= INTEGER|FLOAT",
+ /* 257 */ "plus_opt ::= PLUS",
+ /* 258 */ "plus_opt ::=",
+ /* 259 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
+ /* 260 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 261 */ "trigger_time ::= BEFORE",
+ /* 262 */ "trigger_time ::= AFTER",
+ /* 263 */ "trigger_time ::= INSTEAD OF",
+ /* 264 */ "trigger_time ::=",
+ /* 265 */ "trigger_event ::= DELETE|INSERT",
+ /* 266 */ "trigger_event ::= UPDATE",
+ /* 267 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 268 */ "foreach_clause ::=",
+ /* 269 */ "foreach_clause ::= FOR EACH ROW",
+ /* 270 */ "when_clause ::=",
+ /* 271 */ "when_clause ::= WHEN expr",
+ /* 272 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 273 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 274 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
+ /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
+ /* 276 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
+ /* 277 */ "trigger_cmd ::= DELETE FROM nm where_opt",
+ /* 278 */ "trigger_cmd ::= select",
+ /* 279 */ "expr ::= RAISE LP IGNORE RP",
+ /* 280 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 281 */ "raisetype ::= ROLLBACK",
+ /* 282 */ "raisetype ::= ABORT",
+ /* 283 */ "raisetype ::= FAIL",
+ /* 284 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 285 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 286 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 287 */ "key_opt ::=",
+ /* 288 */ "key_opt ::= KEY expr",
+ /* 289 */ "database_kw_opt ::= DATABASE",
+ /* 290 */ "database_kw_opt ::=",
+ /* 291 */ "cmd ::= REINDEX",
+ /* 292 */ "cmd ::= REINDEX nm dbnm",
+ /* 293 */ "cmd ::= ANALYZE",
+ /* 294 */ "cmd ::= ANALYZE nm dbnm",
+ /* 295 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 296 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 297 */ "add_column_fullname ::= fullname",
+ /* 298 */ "kwcolumn_opt ::=",
+ /* 299 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 300 */ "cmd ::= create_vtab",
+ /* 301 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 302 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
+ /* 303 */ "vtabarglist ::= vtabarg",
+ /* 304 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 305 */ "vtabarg ::=",
+ /* 306 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 307 */ "vtabargtoken ::= ANY",
+ /* 308 */ "vtabargtoken ::= lp anylist RP",
+ /* 309 */ "lp ::= LP",
+ /* 310 */ "anylist ::=",
+ /* 311 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */
@@ -78069,7 +79288,7 @@ static void yy_destructor(
case 189: /* oneselect */
case 206: /* seltablist_paren */
{
-sqlite3SelectDelete(pParse->db, (yypminor->yy219));
+sqlite3SelectDelete(pParse->db, (yypminor->yy375));
}
break;
case 169: /* term */
@@ -78081,10 +79300,10 @@ sqlite3SelectDelete(pParse->db, (yypminor->yy219));
case 218: /* escape */
case 221: /* case_operand */
case 223: /* case_else */
- case 235: /* when_clause */
- case 238: /* key_opt */
+ case 234: /* when_clause */
+ case 237: /* key_opt */
{
-sqlite3ExprDelete(pParse->db, (yypminor->yy172));
+sqlite3ExprDelete(pParse->db, (yypminor->yy62));
}
break;
case 174: /* idxlist_opt */
@@ -78100,7 +79319,7 @@ sqlite3ExprDelete(pParse->db, (yypminor->yy172));
case 216: /* exprlist */
case 222: /* case_exprlist */
{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy174));
+sqlite3ExprListDelete(pParse->db, (yypminor->yy418));
}
break;
case 188: /* fullname */
@@ -78108,25 +79327,25 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy174));
case 201: /* seltablist */
case 202: /* stl_prefix */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy373));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy151));
}
break;
case 205: /* using_opt */
case 208: /* inscollist */
case 214: /* inscollist_opt */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy432));
+sqlite3IdListDelete(pParse->db, (yypminor->yy240));
}
break;
- case 231: /* trigger_cmd_list */
- case 236: /* trigger_cmd */
+ case 230: /* trigger_cmd_list */
+ case 235: /* trigger_cmd */
{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy243));
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy360));
}
break;
- case 233: /* trigger_event */
+ case 232: /* trigger_event */
{
-sqlite3IdListDelete(pParse->db, (yypminor->yy370).b);
+sqlite3IdListDelete(pParse->db, (yypminor->yy30).b);
}
break;
default: break; /* If no destructor action specified: do nothing */
@@ -78361,13 +79580,13 @@ static const struct {
{ 139, 1 },
{ 140, 2 },
{ 140, 1 },
- { 142, 1 },
{ 141, 1 },
{ 141, 3 },
- { 144, 0 },
- { 144, 1 },
+ { 142, 0 },
+ { 142, 1 },
+ { 142, 3 },
+ { 143, 1 },
{ 144, 3 },
- { 143, 3 },
{ 146, 0 },
{ 146, 1 },
{ 146, 2 },
@@ -78375,10 +79594,10 @@ static const struct {
{ 145, 1 },
{ 145, 1 },
{ 145, 1 },
- { 143, 2 },
- { 143, 2 },
- { 143, 2 },
- { 143, 2 },
+ { 144, 2 },
+ { 144, 2 },
+ { 144, 2 },
+ { 144, 2 },
{ 148, 6 },
{ 151, 0 },
{ 151, 3 },
@@ -78457,12 +79676,12 @@ static const struct {
{ 185, 1 },
{ 185, 1 },
{ 185, 1 },
- { 143, 4 },
+ { 144, 4 },
{ 187, 2 },
{ 187, 0 },
- { 143, 8 },
- { 143, 4 },
- { 143, 1 },
+ { 144, 8 },
+ { 144, 4 },
+ { 144, 1 },
{ 155, 1 },
{ 155, 3 },
{ 190, 1 },
@@ -78515,15 +79734,15 @@ static const struct {
{ 198, 2 },
{ 198, 4 },
{ 198, 4 },
- { 143, 4 },
+ { 144, 4 },
{ 194, 0 },
{ 194, 2 },
- { 143, 6 },
+ { 144, 6 },
{ 212, 5 },
{ 212, 3 },
- { 143, 8 },
- { 143, 5 },
- { 143, 6 },
+ { 144, 8 },
+ { 144, 5 },
+ { 144, 6 },
{ 213, 2 },
{ 213, 1 },
{ 215, 3 },
@@ -78592,85 +79811,84 @@ static const struct {
{ 216, 0 },
{ 211, 3 },
{ 211, 1 },
- { 143, 11 },
+ { 144, 11 },
{ 224, 1 },
{ 224, 0 },
{ 174, 0 },
{ 174, 3 },
{ 182, 5 },
{ 182, 3 },
- { 225, 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 },
+ { 225, 0 },
+ { 225, 2 },
+ { 144, 4 },
+ { 144, 1 },
+ { 144, 2 },
+ { 144, 5 },
+ { 144, 5 },
+ { 144, 5 },
+ { 144, 5 },
+ { 144, 6 },
+ { 144, 3 },
+ { 226, 1 },
+ { 226, 1 },
{ 165, 2 },
{ 166, 2 },
- { 229, 1 },
{ 228, 1 },
- { 228, 0 },
- { 143, 5 },
- { 230, 11 },
+ { 227, 1 },
+ { 227, 0 },
+ { 144, 5 },
+ { 229, 11 },
+ { 231, 1 },
+ { 231, 1 },
+ { 231, 2 },
+ { 231, 0 },
{ 232, 1 },
{ 232, 1 },
- { 232, 2 },
- { 232, 0 },
- { 233, 1 },
- { 233, 1 },
+ { 232, 3 },
+ { 233, 0 },
{ 233, 3 },
{ 234, 0 },
- { 234, 3 },
- { 235, 0 },
- { 235, 2 },
- { 231, 3 },
- { 231, 0 },
- { 236, 6 },
- { 236, 8 },
- { 236, 5 },
- { 236, 4 },
- { 236, 1 },
+ { 234, 2 },
+ { 230, 3 },
+ { 230, 2 },
+ { 235, 6 },
+ { 235, 8 },
+ { 235, 5 },
+ { 235, 4 },
+ { 235, 1 },
{ 170, 4 },
{ 170, 6 },
{ 186, 1 },
{ 186, 1 },
{ 186, 1 },
- { 143, 4 },
- { 143, 6 },
- { 143, 3 },
- { 238, 0 },
- { 238, 2 },
- { 237, 1 },
+ { 144, 4 },
+ { 144, 6 },
+ { 144, 3 },
{ 237, 0 },
- { 143, 1 },
- { 143, 3 },
- { 143, 1 },
- { 143, 3 },
- { 143, 6 },
- { 143, 6 },
+ { 237, 2 },
+ { 236, 1 },
+ { 236, 0 },
+ { 144, 1 },
+ { 144, 3 },
+ { 144, 1 },
+ { 144, 3 },
+ { 144, 6 },
+ { 144, 6 },
+ { 238, 1 },
+ { 239, 0 },
{ 239, 1 },
- { 240, 0 },
- { 240, 1 },
- { 143, 1 },
- { 143, 4 },
- { 241, 7 },
- { 242, 1 },
- { 242, 3 },
- { 243, 0 },
- { 243, 2 },
+ { 144, 1 },
+ { 144, 4 },
+ { 240, 7 },
+ { 241, 1 },
+ { 241, 3 },
+ { 242, 0 },
+ { 242, 2 },
+ { 243, 1 },
+ { 243, 3 },
{ 244, 1 },
- { 244, 3 },
- { 245, 1 },
- { 246, 0 },
- { 246, 2 },
+ { 245, 0 },
+ { 245, 2 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -78728,8 +79946,8 @@ static void yy_reduce(
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 */
@@ -78748,45 +79966,45 @@ static void yy_reduce(
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 ::= */
+ case 257: /* plus_opt ::= PLUS */
+ case 258: /* plus_opt ::= */
+ case 268: /* foreach_clause ::= */
+ case 269: /* foreach_clause ::= FOR EACH ROW */
+ case 289: /* database_kw_opt ::= DATABASE */
+ case 290: /* database_kw_opt ::= */
+ case 298: /* kwcolumn_opt ::= */
+ case 299: /* kwcolumn_opt ::= COLUMNKW */
+ case 303: /* vtabarglist ::= vtabarg */
+ case 304: /* vtabarglist ::= vtabarglist COMMA vtabarg */
+ case 306: /* vtabarg ::= vtabarg vtabargtoken */
+ case 310: /* anylist ::= */
{
}
break;
- case 3: /* cmdx ::= cmd */
-{ sqlite3FinishCoding(pParse); }
- break;
- case 6: /* explain ::= */
+ 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.yy280);}
break;
case 13: /* transtype ::= */
-{yygotominor.yy46 = TK_DEFERRED;}
+{yygotominor.yy280 = 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.yy280 = yymsp[0].major;}
break;
case 17: /* cmd ::= COMMIT trans_opt */
case 18: /* cmd ::= END trans_opt */
@@ -78797,7 +80015,7 @@ static void yy_reduce(
break;
case 21: /* create_table ::= CREATE temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy46,0,0,yymsp[-2].minor.yy46);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy280,0,0,yymsp[-2].minor.yy280);
}
break;
case 22: /* ifnotexists ::= */
@@ -78811,7 +80029,7 @@ static void yy_reduce(
case 113: /* distinct ::= */
case 213: /* between_op ::= BETWEEN */
case 216: /* in_op ::= IN */
-{yygotominor.yy46 = 0;}
+{yygotominor.yy280 = 0;}
break;
case 23: /* ifnotexists ::= IF NOT EXISTS */
case 24: /* temp ::= TEMP */
@@ -78821,7 +80039,7 @@ static void yy_reduce(
case 111: /* distinct ::= DISTINCT */
case 214: /* between_op ::= NOT BETWEEN */
case 217: /* in_op ::= NOT IN */
-{yygotominor.yy46 = 1;}
+{yygotominor.yy280 = 1;}
break;
case 26: /* create_table_args ::= LP columnlist conslist_opt RP */
{
@@ -78830,8 +80048,8 @@ static void yy_reduce(
break;
case 27: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy219);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy219);
+ sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy375);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy375);
}
break;
case 30: /* column ::= columnid type carglist */
@@ -78856,13 +80074,12 @@ static void yy_reduce(
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 242: /* collate ::= COLLATE ids */
+ case 252: /* nmnum ::= plus_num */
+ case 253: /* nmnum ::= nm */
+ case 254: /* plus_num ::= plus_opt number */
+ case 255: /* minus_num ::= MINUS number */
+ case 256: /* number ::= INTEGER|FLOAT */
{yygotominor.yy0 = yymsp[0].minor.yy0;}
break;
case 38: /* type ::= typetoken */
@@ -78885,14 +80102,14 @@ static void yy_reduce(
break;
case 50: /* ccons ::= DEFAULT term */
case 52: /* ccons ::= DEFAULT PLUS term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy172);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy62);}
break;
case 51: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy172);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy62);}
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.yy62, 0, 0);
sqlite3AddDefaultValue(pParse,p);
}
break;
@@ -78903,55 +80120,55 @@ static void yy_reduce(
}
break;
case 56: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy46);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy280);}
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.yy280,yymsp[0].minor.yy280,yymsp[-2].minor.yy280);}
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.yy280,0,0,0,0);}
break;
case 59: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy172);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy62);}
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.yy418,yymsp[0].minor.yy280);}
break;
case 61: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy46);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy280);}
break;
case 62: /* ccons ::= COLLATE ids */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 65: /* refargs ::= */
-{ yygotominor.yy46 = OE_Restrict * 0x010101; }
+{ yygotominor.yy280 = 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.yy280 = (yymsp[-1].minor.yy280 & yymsp[0].minor.yy359.mask) | yymsp[0].minor.yy359.value; }
break;
case 67: /* refarg ::= MATCH nm */
-{ yygotominor.yy405.value = 0; yygotominor.yy405.mask = 0x000000; }
+{ yygotominor.yy359.value = 0; yygotominor.yy359.mask = 0x000000; }
break;
case 68: /* refarg ::= ON DELETE refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46; yygotominor.yy405.mask = 0x0000ff; }
+{ yygotominor.yy359.value = yymsp[0].minor.yy280; yygotominor.yy359.mask = 0x0000ff; }
break;
case 69: /* refarg ::= ON UPDATE refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46<<8; yygotominor.yy405.mask = 0x00ff00; }
+{ yygotominor.yy359.value = yymsp[0].minor.yy280<<8; yygotominor.yy359.mask = 0x00ff00; }
break;
case 70: /* refarg ::= ON INSERT refact */
-{ yygotominor.yy405.value = yymsp[0].minor.yy46<<16; yygotominor.yy405.mask = 0xff0000; }
+{ yygotominor.yy359.value = yymsp[0].minor.yy280<<16; yygotominor.yy359.mask = 0xff0000; }
break;
case 71: /* refact ::= SET NULL */
-{ yygotominor.yy46 = OE_SetNull; }
+{ yygotominor.yy280 = OE_SetNull; }
break;
case 72: /* refact ::= SET DEFAULT */
-{ yygotominor.yy46 = OE_SetDflt; }
+{ yygotominor.yy280 = OE_SetDflt; }
break;
case 73: /* refact ::= CASCADE */
-{ yygotominor.yy46 = OE_Cascade; }
+{ yygotominor.yy280 = OE_Cascade; }
break;
case 74: /* refact ::= RESTRICT */
-{ yygotominor.yy46 = OE_Restrict; }
+{ yygotominor.yy280 = OE_Restrict; }
break;
case 75: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
case 76: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
@@ -78960,7 +80177,7 @@ static void yy_reduce(
case 95: /* orconf ::= OR resolvetype */
case 96: /* resolvetype ::= raisetype */
case 166: /* insert_cmd ::= INSERT orconf */
-{yygotominor.yy46 = yymsp[0].minor.yy46;}
+{yygotominor.yy280 = yymsp[0].minor.yy280;}
break;
case 80: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
@@ -78969,96 +80186,96 @@ static void yy_reduce(
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
break;
case 86: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy174,yymsp[0].minor.yy46,yymsp[-2].minor.yy46,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy418,yymsp[0].minor.yy280,yymsp[-2].minor.yy280,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.yy418,yymsp[0].minor.yy280,0,0,0,0);}
break;
case 88: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy172);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy62);}
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.yy418, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy418, yymsp[-1].minor.yy280);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy280);
}
break;
case 92: /* onconf ::= */
case 94: /* orconf ::= */
-{yygotominor.yy46 = OE_Default;}
+{yygotominor.yy280 = OE_Default;}
break;
case 97: /* resolvetype ::= IGNORE */
-{yygotominor.yy46 = OE_Ignore;}
+{yygotominor.yy280 = OE_Ignore;}
break;
case 98: /* resolvetype ::= REPLACE */
case 167: /* insert_cmd ::= REPLACE */
-{yygotominor.yy46 = OE_Replace;}
+{yygotominor.yy280 = 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.yy151, 0, yymsp[-1].minor.yy280);
}
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.yy375, yymsp[-6].minor.yy280, yymsp[-4].minor.yy280);
}
break;
case 103: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy373, 1, yymsp[-1].minor.yy46);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy151, 1, yymsp[-1].minor.yy280);
}
break;
case 104: /* cmd ::= select */
{
- SelectDest dest = {SRT_Callback, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy219, &dest, 0, 0, 0);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy219);
+ SelectDest dest = {SRT_Output, 0, 0, 0, 0};
+ sqlite3Select(pParse, yymsp[0].minor.yy375, &dest);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy375);
}
break;
case 105: /* select ::= oneselect */
case 128: /* seltablist_paren ::= select */
-{yygotominor.yy219 = yymsp[0].minor.yy219;}
+{yygotominor.yy375 = yymsp[0].minor.yy375;}
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;
+ if( yymsp[0].minor.yy375 ){
+ yymsp[0].minor.yy375->op = yymsp[-1].minor.yy280;
+ yymsp[0].minor.yy375->pPrior = yymsp[-2].minor.yy375;
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy219);
+ sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy375);
}
- yygotominor.yy219 = yymsp[0].minor.yy219;
+ yygotominor.yy375 = yymsp[0].minor.yy375;
}
break;
case 108: /* multiselect_op ::= UNION ALL */
-{yygotominor.yy46 = TK_ALL;}
+{yygotominor.yy280 = 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.yy375 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy418,yymsp[-5].minor.yy151,yymsp[-4].minor.yy62,yymsp[-3].minor.yy418,yymsp[-2].minor.yy62,yymsp[-1].minor.yy418,yymsp[-7].minor.yy280,yymsp[0].minor.yy220.pLimit,yymsp[0].minor.yy220.pOffset);
}
break;
case 114: /* sclp ::= selcollist COMMA */
case 238: /* idxlist_opt ::= LP idxlist RP */
-{yygotominor.yy174 = yymsp[-1].minor.yy174;}
+{yygotominor.yy418 = yymsp[-1].minor.yy418;}
break;
case 115: /* sclp ::= */
case 141: /* orderby_opt ::= */
case 149: /* groupby_opt ::= */
case 231: /* exprlist ::= */
case 237: /* idxlist_opt ::= */
-{yygotominor.yy174 = 0;}
+{yygotominor.yy418 = 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.yy418 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy418,yymsp[-1].minor.yy62,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.yy418 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy418, p, 0);
}
break;
case 118: /* selcollist ::= sclp nm DOT STAR */
@@ -79066,63 +80283,63 @@ static void yy_reduce(
Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
- yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy174, pDot, 0);
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy418, pDot, 0);
}
break;
case 121: /* as ::= */
{yygotominor.yy0.n = 0;}
break;
case 122: /* from ::= */
-{yygotominor.yy373 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy373));}
+{yygotominor.yy151 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy151));}
break;
case 123: /* from ::= FROM seltablist */
{
- yygotominor.yy373 = yymsp[0].minor.yy373;
- sqlite3SrcListShiftJoinType(yygotominor.yy373);
+ yygotominor.yy151 = yymsp[0].minor.yy151;
+ sqlite3SrcListShiftJoinType(yygotominor.yy151);
}
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.yy151 = yymsp[-1].minor.yy151;
+ if( yygotominor.yy151 && yygotominor.yy151->nSrc>0 ) yygotominor.yy151->a[yygotominor.yy151->nSrc-1].jointype = yymsp[0].minor.yy280;
}
break;
case 125: /* stl_prefix ::= */
-{yygotominor.yy373 = 0;}
+{yygotominor.yy151 = 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.yy151 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy151,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy62,yymsp[0].minor.yy240);
}
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.yy151 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy151,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy375,yymsp[-1].minor.yy62,yymsp[0].minor.yy240);
}
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.yy151);
+ yygotominor.yy375 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy151,0,0,0,0,0,0,0);
}
break;
case 130: /* dbnm ::= */
{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.yy151 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
break;
case 133: /* joinop ::= COMMA|JOIN */
-{ yygotominor.yy46 = JT_INNER; }
+{ yygotominor.yy280 = JT_INNER; }
break;
case 134: /* joinop ::= JOIN_KW JOIN */
-{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+{ yygotominor.yy280 = 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.yy280 = 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.yy280 = 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 */
@@ -79132,7 +80349,7 @@ static void yy_reduce(
case 202: /* escape ::= ESCAPE expr */
case 226: /* case_else ::= ELSE expr */
case 228: /* case_operand ::= expr */
-{yygotominor.yy172 = yymsp[0].minor.yy172;}
+{yygotominor.yy62 = yymsp[0].minor.yy62;}
break;
case 138: /* on_opt ::= */
case 151: /* having_opt ::= */
@@ -79140,107 +80357,107 @@ static void yy_reduce(
case 203: /* escape ::= */
case 227: /* case_else ::= */
case 229: /* case_operand ::= */
-{yygotominor.yy172 = 0;}
+{yygotominor.yy62 = 0;}
break;
case 139: /* using_opt ::= USING LP inscollist RP */
case 171: /* inscollist_opt ::= LP inscollist RP */
-{yygotominor.yy432 = yymsp[-1].minor.yy432;}
+{yygotominor.yy240 = yymsp[-1].minor.yy240;}
break;
case 140: /* using_opt ::= */
case 170: /* inscollist_opt ::= */
-{yygotominor.yy432 = 0;}
+{yygotominor.yy240 = 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;}
+{yygotominor.yy418 = yymsp[0].minor.yy418;}
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;
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy418,yymsp[-1].minor.yy62,0);
+ if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280;
}
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;
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy62,0);
+ if( yygotominor.yy418 && yygotominor.yy418->a ) yygotominor.yy418->a[0].sortOrder = yymsp[0].minor.yy280;
}
break;
case 146: /* sortorder ::= ASC */
case 148: /* sortorder ::= */
-{yygotominor.yy46 = SQLITE_SO_ASC;}
+{yygotominor.yy280 = SQLITE_SO_ASC;}
break;
case 147: /* sortorder ::= DESC */
-{yygotominor.yy46 = SQLITE_SO_DESC;}
+{yygotominor.yy280 = SQLITE_SO_DESC;}
break;
case 153: /* limit_opt ::= */
-{yygotominor.yy234.pLimit = 0; yygotominor.yy234.pOffset = 0;}
+{yygotominor.yy220.pLimit = 0; yygotominor.yy220.pOffset = 0;}
break;
case 154: /* limit_opt ::= LIMIT expr */
-{yygotominor.yy234.pLimit = yymsp[0].minor.yy172; yygotominor.yy234.pOffset = 0;}
+{yygotominor.yy220.pLimit = yymsp[0].minor.yy62; yygotominor.yy220.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;}
+{yygotominor.yy220.pLimit = yymsp[-2].minor.yy62; yygotominor.yy220.pOffset = yymsp[0].minor.yy62;}
break;
case 156: /* limit_opt ::= LIMIT expr COMMA expr */
-{yygotominor.yy234.pOffset = yymsp[-2].minor.yy172; yygotominor.yy234.pLimit = yymsp[0].minor.yy172;}
+{yygotominor.yy220.pOffset = yymsp[-2].minor.yy62; yygotominor.yy220.pLimit = yymsp[0].minor.yy62;}
break;
case 157: /* cmd ::= DELETE FROM fullname where_opt */
-{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy373,yymsp[0].minor.yy172);}
+{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy151,yymsp[0].minor.yy62);}
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);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy418,"set list");
+ sqlite3Update(pParse,yymsp[-3].minor.yy151,yymsp[-1].minor.yy418,yymsp[0].minor.yy62,yymsp[-4].minor.yy280);
}
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);}
+{yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418,yymsp[0].minor.yy62,&yymsp[-2].minor.yy0);}
break;
case 162: /* setlist ::= nm EQ expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
+{yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy62,&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);}
+{sqlite3Insert(pParse, yymsp[-5].minor.yy151, yymsp[-1].minor.yy418, 0, yymsp[-4].minor.yy240, yymsp[-7].minor.yy280);}
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);}
+{sqlite3Insert(pParse, yymsp[-2].minor.yy151, 0, yymsp[0].minor.yy375, yymsp[-1].minor.yy240, yymsp[-4].minor.yy280);}
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);}
+{sqlite3Insert(pParse, yymsp[-3].minor.yy151, 0, 0, yymsp[-2].minor.yy240, yymsp[-5].minor.yy280);}
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);}
+{yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy418,yymsp[0].minor.yy62,0);}
break;
case 169: /* itemlist ::= expr */
case 233: /* nexprlist ::= expr */
-{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,0);}
+{yygotominor.yy418 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy62,0);}
break;
case 172: /* inscollist ::= inscollist COMMA nm */
-{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy432,&yymsp[0].minor.yy0);}
+{yygotominor.yy240 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy240,&yymsp[0].minor.yy0);}
break;
case 173: /* inscollist ::= nm */
-{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
+{yygotominor.yy240 = 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); }
+{yygotominor.yy62 = yymsp[-1].minor.yy62; sqlite3ExprSpan(yygotominor.yy62,&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);}
+{yygotominor.yy62 = 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);}
+{yygotominor.yy62 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
break;
case 179: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
- yygotominor.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
}
break;
case 180: /* expr ::= nm DOT nm DOT nm */
@@ -79249,56 +80466,56 @@ static void yy_reduce(
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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
}
break;
case 183: /* expr ::= REGISTER */
-{yygotominor.yy172 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+{yygotominor.yy62 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
break;
case 184: /* expr ::= VARIABLE */
{
Token *pToken = &yymsp[0].minor.yy0;
- Expr *pExpr = yygotominor.yy172 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
+ Expr *pExpr = yygotominor.yy62 = 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);
+ yygotominor.yy62 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy62, &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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy62, 0, &yymsp[-1].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
}
break;
case 187: /* expr ::= ID LP distinct exprlist RP */
{
- if( yymsp[-1].minor.yy174 && yymsp[-1].minor.yy174->nExpr>SQLITE_MAX_FUNCTION_ARG ){
+ if( yymsp[-1].minor.yy418 && yymsp[-1].minor.yy418->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;
+ yygotominor.yy62 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy418, &yymsp[-4].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+ if( yymsp[-2].minor.yy280 && yygotominor.yy62 ){
+ yygotominor.yy62->flags |= EP_Distinct;
}
}
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);
+ yygotominor.yy62 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
break;
case 189: /* 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;
+ yygotominor.yy62 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
+ if( yygotominor.yy62 ){
+ yygotominor.yy62->op = TK_CONST_FUNC;
+ yygotominor.yy62->span = yymsp[0].minor.yy0;
}
}
break;
@@ -79310,391 +80527,400 @@ static void yy_reduce(
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);}
+{yygotominor.yy62 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy62,yymsp[0].minor.yy62,0);}
break;
case 198: /* likeop ::= LIKE_KW */
case 200: /* likeop ::= MATCH */
-{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 0;}
+{yygotominor.yy222.eOperator = yymsp[0].minor.yy0; yygotominor.yy222.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;}
+{yygotominor.yy222.eOperator = yymsp[0].minor.yy0; yygotominor.yy222.not = 1;}
break;
case 204: /* 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);
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy62, 0);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy62, 0);
+ if( yymsp[0].minor.yy62 ){
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy62, 0);
}
- 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;
+ yygotominor.yy62 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy222.eOperator);
+ if( yymsp[-2].minor.yy222.not ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy62->span, &yymsp[-1].minor.yy62->span);
+ if( yygotominor.yy62 ) yygotominor.yy62->flags |= EP_InfixFunc;
}
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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy62->span,&yymsp[0].minor.yy0);
}
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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-2].minor.yy62->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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->span);
}
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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy62->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;
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62, 0);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy62, 0);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy62, 0, 0);
+ if( yygotominor.yy62 ){
+ yygotominor.yy62->pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, 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);
+ if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy62->span);
}
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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0, 0);
+ if( yygotominor.yy62 ){
+ yygotominor.yy62->pList = yymsp[-1].minor.yy418;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy62);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy174);
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy418);
}
- 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);
+ if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0);
}
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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy62 ){
+ yygotominor.yy62->pSelect = yymsp[-1].minor.yy375;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy62);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375);
}
- sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy62,&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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy62, 0, 0);
+ if( yygotominor.yy62 ){
+ yygotominor.yy62->pSelect = yymsp[-1].minor.yy375;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy62);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375);
}
- 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);
+ if( yymsp[-3].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-4].minor.yy62->span,&yymsp[0].minor.yy0);
}
break;
case 221: /* 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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy62, 0, 0);
+ if( yygotominor.yy62 ){
+ yygotominor.yy62->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy62);
}else{
sqlite3SrcListDelete(pParse->db, 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);
+ if( yymsp[-2].minor.yy280 ) yygotominor.yy62 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy62, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy62,&yymsp[-3].minor.yy62->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
}
break;
case 222: /* expr ::= EXISTS LP select RP */
{
- Expr *p = yygotominor.yy172 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+ Expr *p = yygotominor.yy62 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
if( p ){
- p->pSelect = yymsp[-1].minor.yy219;
+ p->pSelect = yymsp[-1].minor.yy375;
sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
- sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy62);
}else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy375);
}
}
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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, 0);
+ if( yygotominor.yy62 ){
+ yygotominor.yy62->pList = yymsp[-2].minor.yy418;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy62);
}else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy174);
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy418);
}
- sqlite3ExprSpan(yygotominor.yy172, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy62, &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);
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418, yymsp[-2].minor.yy62, 0);
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,yygotominor.yy418, yymsp[0].minor.yy62, 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);
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy62, 0);
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,yygotominor.yy418, yymsp[0].minor.yy62, 0);
}
break;
case 234: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
{
sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
- sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy174, yymsp[-9].minor.yy46,
- &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46);
+ sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy418, yymsp[-9].minor.yy280,
+ &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy280);
}
break;
case 235: /* uniqueflag ::= UNIQUE */
- case 283: /* raisetype ::= ABORT */
-{yygotominor.yy46 = OE_Abort;}
+ case 282: /* raisetype ::= ABORT */
+{yygotominor.yy280 = OE_Abort;}
break;
case 236: /* uniqueflag ::= */
-{yygotominor.yy46 = OE_None;}
+{yygotominor.yy280 = OE_None;}
break;
- case 239: /* idxlist ::= idxlist COMMA idxitem collate sortorder */
+ case 239: /* 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.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;
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy418, p, &yymsp[-2].minor.yy0);
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy418, "index");
+ if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280;
}
break;
- case 240: /* idxlist ::= idxitem collate sortorder */
+ case 240: /* 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,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;
+ yygotominor.yy418 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0);
+ sqlite3ExprListCheckLength(pParse, yygotominor.yy418, "index");
+ if( yygotominor.yy418 ) yygotominor.yy418->a[yygotominor.yy418->nExpr-1].sortOrder = yymsp[0].minor.yy280;
}
break;
- case 242: /* collate ::= */
+ case 241: /* 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);}
+ case 243: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy151, yymsp[-1].minor.yy280);}
break;
- case 245: /* cmd ::= VACUUM */
- case 246: /* cmd ::= VACUUM nm */
+ case 244: /* cmd ::= VACUUM */
+ case 245: /* 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 246: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 247: /* cmd ::= PRAGMA nm dbnm EQ ON */
+ case 248: /* 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 249: /* 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 250: /* 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 251: /* 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 259: /* 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);
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy360, &all);
}
break;
- case 261: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 260: /* 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.yy280, yymsp[-4].minor.yy30.a, yymsp[-4].minor.yy30.b, yymsp[-2].minor.yy151, yymsp[0].minor.yy62, yymsp[-10].minor.yy280, yymsp[-8].minor.yy280);
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; }
+ case 261: /* trigger_time ::= BEFORE */
+ case 264: /* trigger_time ::= */
+{ yygotominor.yy280 = TK_BEFORE; }
break;
- case 263: /* trigger_time ::= AFTER */
-{ yygotominor.yy46 = TK_AFTER; }
+ case 262: /* trigger_time ::= AFTER */
+{ yygotominor.yy280 = TK_AFTER; }
break;
- case 264: /* trigger_time ::= INSTEAD OF */
-{ yygotominor.yy46 = TK_INSTEAD;}
+ case 263: /* trigger_time ::= INSTEAD OF */
+{ yygotominor.yy280 = TK_INSTEAD;}
break;
- case 266: /* trigger_event ::= DELETE|INSERT */
- case 267: /* trigger_event ::= UPDATE */
-{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;}
+ case 265: /* trigger_event ::= DELETE|INSERT */
+ case 266: /* trigger_event ::= UPDATE */
+{yygotominor.yy30.a = yymsp[0].major; yygotominor.yy30.b = 0;}
break;
- case 268: /* trigger_event ::= UPDATE OF inscollist */
-{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;}
+ case 267: /* trigger_event ::= UPDATE OF inscollist */
+{yygotominor.yy30.a = TK_UPDATE; yygotominor.yy30.b = yymsp[0].minor.yy240;}
break;
- case 271: /* when_clause ::= */
- case 288: /* key_opt ::= */
-{ yygotominor.yy172 = 0; }
+ case 270: /* when_clause ::= */
+ case 287: /* key_opt ::= */
+{ yygotominor.yy62 = 0; }
break;
- case 272: /* when_clause ::= WHEN expr */
- case 289: /* key_opt ::= KEY expr */
-{ yygotominor.yy172 = yymsp[0].minor.yy172; }
+ case 271: /* when_clause ::= WHEN expr */
+ case 288: /* key_opt ::= KEY expr */
+{ yygotominor.yy62 = yymsp[0].minor.yy62; }
break;
- case 273: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 272: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- if( yymsp[-2].minor.yy243 ){
- yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243;
+/*
+ if( yymsp[-2].minor.yy360 ){
+ yymsp[-2].minor.yy360->pLast->pNext = yymsp[-1].minor.yy360;
}else{
- yymsp[-2].minor.yy243 = yymsp[-1].minor.yy243;
+ yymsp[-2].minor.yy360 = yymsp[-1].minor.yy360;
}
- yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243;
- yygotominor.yy243 = yymsp[-2].minor.yy243;
+*/
+ assert( yymsp[-2].minor.yy360!=0 );
+ yymsp[-2].minor.yy360->pLast->pNext = yymsp[-1].minor.yy360;
+ yymsp[-2].minor.yy360->pLast = yymsp[-1].minor.yy360;
+ yygotominor.yy360 = yymsp[-2].minor.yy360;
}
break;
- case 274: /* trigger_cmd_list ::= */
-{ yygotominor.yy243 = 0; }
+ case 273: /* trigger_cmd_list ::= trigger_cmd SEMI */
+{
+ /* if( yymsp[-1].minor.yy360 ) */
+ assert( yymsp[-1].minor.yy360!=0 );
+ yymsp[-1].minor.yy360->pLast = yymsp[-1].minor.yy360;
+ yygotominor.yy360 = yymsp[-1].minor.yy360;
+}
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); }
+ case 274: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
+{ yygotominor.yy360 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy418, yymsp[0].minor.yy62, yymsp[-4].minor.yy280); }
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);}
+ case 275: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
+{yygotominor.yy360 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy240, yymsp[-1].minor.yy418, 0, yymsp[-7].minor.yy280);}
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);}
+ case 276: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
+{yygotominor.yy360 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy240, 0, yymsp[0].minor.yy375, yymsp[-4].minor.yy280);}
break;
- case 278: /* trigger_cmd ::= DELETE FROM nm where_opt */
-{yygotominor.yy243 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy172);}
+ case 277: /* trigger_cmd ::= DELETE FROM nm where_opt */
+{yygotominor.yy360 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy62);}
break;
- case 279: /* trigger_cmd ::= select */
-{yygotominor.yy243 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy219); }
+ case 278: /* trigger_cmd ::= select */
+{yygotominor.yy360 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy375); }
break;
- case 280: /* expr ::= RAISE LP IGNORE RP */
+ case 279: /* expr ::= RAISE LP IGNORE RP */
{
- 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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
+ if( yygotominor.yy62 ){
+ yygotominor.yy62->iColumn = OE_Ignore;
+ sqlite3ExprSpan(yygotominor.yy62, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
}
}
break;
- case 281: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 280: /* 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);
+ yygotominor.yy62 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ if( yygotominor.yy62 ) {
+ yygotominor.yy62->iColumn = yymsp[-3].minor.yy280;
+ sqlite3ExprSpan(yygotominor.yy62, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
}
}
break;
- case 282: /* raisetype ::= ROLLBACK */
-{yygotominor.yy46 = OE_Rollback;}
+ case 281: /* raisetype ::= ROLLBACK */
+{yygotominor.yy280 = OE_Rollback;}
break;
- case 284: /* raisetype ::= FAIL */
-{yygotominor.yy46 = OE_Fail;}
+ case 283: /* raisetype ::= FAIL */
+{yygotominor.yy280 = OE_Fail;}
break;
- case 285: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 284: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46);
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy151,yymsp[-1].minor.yy280);
}
break;
- case 286: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 285: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy172);
+ sqlite3Attach(pParse, yymsp[-3].minor.yy62, yymsp[-1].minor.yy62, yymsp[0].minor.yy62);
}
break;
- case 287: /* cmd ::= DETACH database_kw_opt expr */
+ case 286: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlite3Detach(pParse, yymsp[0].minor.yy172);
+ sqlite3Detach(pParse, yymsp[0].minor.yy62);
}
break;
- case 292: /* cmd ::= REINDEX */
+ case 291: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 293: /* cmd ::= REINDEX nm dbnm */
+ case 292: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 294: /* cmd ::= ANALYZE */
+ case 293: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 295: /* cmd ::= ANALYZE nm dbnm */
+ case 294: /* 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 295: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy0);
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy151,&yymsp[0].minor.yy0);
}
break;
- case 297: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+ case 296: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
break;
- case 298: /* add_column_fullname ::= fullname */
+ case 297: /* add_column_fullname ::= fullname */
{
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373);
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy151);
}
break;
- case 301: /* cmd ::= create_vtab */
+ case 300: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 302: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 301: /* 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 302: /* 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 305: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 308: /* vtabargtoken ::= ANY */
- case 309: /* vtabargtoken ::= lp anylist RP */
- case 310: /* lp ::= LP */
- case 312: /* anylist ::= anylist ANY */
+ case 307: /* vtabargtoken ::= ANY */
+ case 308: /* vtabargtoken ::= lp anylist RP */
+ case 309: /* lp ::= LP */
+ case 311: /* anylist ::= anylist ANY */
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
};
@@ -80184,7 +81410,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
case '-': {
if( z[1]=='-' ){
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
- *tokenType = TK_COMMENT;
+ *tokenType = TK_SPACE;
return i;
}
*tokenType = TK_MINUS;
@@ -80217,7 +81443,7 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
- *tokenType = TK_COMMENT;
+ *tokenType = TK_SPACE;
return i;
}
case '%': {
@@ -80298,9 +81524,12 @@ SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
}
}
- if( c ){
+ if( c=='\'' ){
*tokenType = TK_STRING;
return i+1;
+ }else if( c!=0 ){
+ *tokenType = TK_ID;
+ return i+1;
}else{
*tokenType = TK_ILLEGAL;
return i;
@@ -80470,8 +81699,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
break;
}
switch( tokenType ){
- case TK_SPACE:
- case TK_COMMENT: {
+ case TK_SPACE: {
if( db->u1.isInterrupted ){
pParse->rc = SQLITE_INTERRUPT;
sqlite3SetString(pzErrMsg, db, "interrupt");
@@ -80554,6 +81782,7 @@ abort_parse:
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->apVarExpr);
+ sqlite3DbFree(db, pParse->aAlias);
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}
@@ -80956,68 +82185,126 @@ SQLITE_API char *sqlite3_temp_directory = 0;
** 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;
+ static int inProgress = 0; /* Prevent recursion */
+ sqlite3_mutex *pMaster; /* The main static mutex */
+ int rc; /* Result code */
- /* If SQLite is already initialized, this call is a no-op. */
+ /* If SQLite is already completely initialized, then this call
+ ** to sqlite3_initialize() should be a no-op. But the initialization
+ ** must be complete. So isInit must not be set until the very end
+ ** of this routine.
+ */
if( sqlite3Config.isInit ) return SQLITE_OK;
- /* Make sure the mutex system is initialized. */
+ /* 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( !sqlite3Config.isMallocInit ){
+ rc = sqlite3MallocInit();
+ }
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;
- }
+ 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;
- }
+ sqlite3Config.nRefInitMutex++;
+ }
+ sqlite3_mutex_leave(pMaster);
- /* 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();
+ /* 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(sqlite3Config.pInitMutex);
+ if( sqlite3Config.isInit==0 && inProgress==0 ){
inProgress = 1;
+ memset(&sqlite3GlobalFunctions, 0, sizeof(sqlite3GlobalFunctions));
+ sqlite3RegisterGlobalFunctions();
rc = sqlite3_os_init();
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PcacheInitialize();
+ sqlite3PCacheBufferSetup(sqlite3Config.pPage, sqlite3Config.szPage,
+ sqlite3Config.nPage);
+ }
inProgress = 0;
sqlite3Config.isInit = (rc==SQLITE_OK ? 1 : 0);
- sqlite3_mutex_leave(sqlite3Config.pInitMutex);
}
+ sqlite3_mutex_leave(sqlite3Config.pInitMutex);
+
+ /* Go back under the static mutex and clean up the recursive
+ ** mutex to prevent a resource leak.
+ */
+ sqlite3_mutex_enter(pMaster);
+ sqlite3Config.nRefInitMutex--;
+ if( sqlite3Config.nRefInitMutex<=0 ){
+ assert( sqlite3Config.nRefInitMutex==0 );
+ sqlite3_mutex_free(sqlite3Config.pInitMutex);
+ sqlite3Config.pInitMutex = 0;
+ }
+ sqlite3_mutex_leave(pMaster);
- /* Check NaN support. */
+ /* 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 ){
@@ -81040,9 +82327,8 @@ SQLITE_API int sqlite3_initialize(void){
** 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;
+ sqlite3PcacheShutdown();
if( sqlite3Config.isInit ){
sqlite3_os_end();
}
@@ -81207,12 +82493,13 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
}
if( sz<0 ) sz = 0;
if( cnt<0 ) cnt = 0;
- sz = (sz+7)&~7;
if( pBuf==0 ){
+ sz = (sz + 7)&~7;
sqlite3BeginBenignMalloc();
pStart = sqlite3Malloc( sz*cnt );
sqlite3EndBenignMalloc();
}else{
+ sz = sz&~7;
pStart = pBuf;
}
if( db->lookaside.bMalloced ){
@@ -81409,14 +82696,17 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
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;
- sqlite3DbFree(db, 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. */
@@ -81439,7 +82729,6 @@ SQLITE_API int sqlite3_close(sqlite3 *db){
sqlite3HashClear(&db->aModule);
#endif
- sqlite3HashClear(&db->aFunc);
sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
if( db->pErr ){
sqlite3ValueFree(db->pErr);
@@ -82205,8 +83494,8 @@ static const int aHardLimit[] = {
#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_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
@@ -82214,6 +83503,9 @@ static const int aHardLimit[] = {
#if SQLITE_MAX_VARIABLE_NUMBER<1
# error SQLITE_MAX_VARIABLE_NUMBER must be at least 1
#endif
+#if SQLITE_MAX_COLUMN>32767
+# error SQLITE_MAX_COLUMN must not exceed 32767
+#endif
/*
@@ -82309,7 +83601,6 @@ static int openDatabase(
| SQLITE_LoadExtension
#endif
;
- sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0);
@@ -82318,7 +83609,6 @@ static int openDatabase(
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;
}
@@ -82332,7 +83622,6 @@ static int openDatabase(
createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0);
createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0);
if( db->mallocFailed ){
- db->magic = SQLITE_MAGIC_SICK;
goto opendb_out;
}
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
@@ -82355,7 +83644,6 @@ static int openDatabase(
&db->aDb[0].pBt);
if( rc!=SQLITE_OK ){
sqlite3Error(db, rc, 0);
- db->magic = SQLITE_MAGIC_SICK;
goto opendb_out;
}
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
@@ -82445,9 +83733,12 @@ opendb_out:
assert( db->mutex!=0 || isThreadsafe==0 || sqlite3Config.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);
@@ -82733,7 +84024,7 @@ SQLITE_API int sqlite3_table_column_metadata(
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;