@@ -1,7 +1,7 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.6.2. By combining all the individual C code files into this
+** version 3.6.7. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a one translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
** of 5% are more are commonly seen when SQLite is compiled as a single
@@ -10,15 +10,15 @@
** This file is all you need to compile SQLite. To use SQLite in other
** programs, you need this file and the "sqlite3.h" header file that defines
** the programming interface to the SQLite library. (If you do not have
** the "sqlite3.h" header file at hand, you will find a copy in the first
-** 6728 lines past this header comment.) Additional code files may be
+** 6735 lines past this header comment.) Additional code files may be
** needed if you want a wrapper to interface SQLite with your choice of
** programming language. The code for the "sqlite3" command-line shell
** is also in a separate file. This file contains only code for the core
** SQLite library.
**
-** This amalgamation was generated on 2008-11-27 02:28:55 UTC.
+** This amalgamation was generated on 2008-12-16 18:01:52 UTC.
*/
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
@@ -40,9 +40,9 @@
**
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.798 2008/11/19 16:52:44 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.809 2008/12/10 21:19:57 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -248,9 +248,9 @@
#pragma warn -rch /* unreachable code */
#pragma warn -ccc /* Condition is always true or false */
#pragma warn -aus /* Assigned value is never used */
#pragma warn -csu /* Comparing signed and unsigned */
-#pragma warn -spa /* Suspicous pointer arithmetic */
+#pragma warn -spa /* Suspicious pointer arithmetic */
#endif
/* Needed for various definitions... */
#ifndef _GNU_SOURCE
@@ -333,9 +333,9 @@
#define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
#define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
/*
-** These #defines should enable >2GB file support on Posix if the
+** These #defines should enable >2GB file support on POSIX if the
** underlying operating system supports it. If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
@@ -343,15 +343,15 @@
** code in all source files.
**
** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
** on the compiler command line. This is necessary if you are compiling
-** on a recent machine (ex: RedHat 7.2) but you want your code to work
-** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
+** on a recent machine (ex: Red Hat 7.2) but you want your code to work
+** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
** without this option, LFS is enable. But LFS does not exist in the kernel
-** in RedHat 6.0, so the code won't work. Hence, for maximum binary
+** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
** portability you should omit LFS.
**
-** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
+** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
*/
#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE 1
# ifndef _FILE_OFFSET_BITS
@@ -376,9 +376,9 @@
/*
** The SQLITE_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
** It determines whether or not the features related to
-** SQLITE_CONFIG_MEMSTATUS are availabe by default or not. This value can
+** SQLITE_CONFIG_MEMSTATUS are available by default or not. This value can
** be overridden at runtime using the sqlite3_config() API.
*/
#if !defined(SQLITE_DEFAULT_MEMSTATUS)
# define SQLITE_DEFAULT_MEMSTATUS 1
@@ -419,9 +419,9 @@
#endif
/*
** We need to define _XOPEN_SOURCE as follows in order to enable
-** recursive mutexes on most unix systems. But Mac OS X is different.
+** recursive mutexes on most Unix systems. But Mac OS X is different.
** The _XOPEN_SOURCE define causes problems for Mac OS X we are told,
** so it is omitted there. See ticket #2673.
**
** Later we learn that _XOPEN_SOURCE is poorly or incorrectly
@@ -486,9 +486,9 @@
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite3.h" as
** part of the build process.
**
-** @(#) $Id: sqlite.h.in,v 1.415 2008/11/19 01:20:26 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.420 2008/12/16 13:46:30 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h> /* Needed for the definition of va_list */
@@ -563,10 +563,10 @@
** {H10014} The SQLITE_VERSION_NUMBER #define shall resolve to an integer
** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z
** are the major version, minor version, and release number.
*/
-#define SQLITE_VERSION "3.6.6.2"
-#define SQLITE_VERSION_NUMBER 3006006
+#define SQLITE_VERSION "3.6.7"
+#define SQLITE_VERSION_NUMBER 3006007
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
** KEYWORDS: sqlite3_version
@@ -593,9 +593,9 @@
**
** {H10023} The [sqlite3_libversion()] function shall return
** a pointer to the [sqlite3_version] string constant.
*/
-SQLITE_API const char sqlite3_version[];
+SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
SQLITE_API const char *sqlite3_libversion(void);
SQLITE_API int sqlite3_libversion_number(void);
/*
@@ -963,8 +963,10 @@
#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))
+#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
+#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
/*
** CAPI3REF: Flags For File Open Operations {H10230} <H11120> <H12700>
**
@@ -1179,8 +1181,11 @@
** is used during testing and only needs to be supported when SQLITE_TEST
** is defined.
*/
#define SQLITE_FCNTL_LOCKSTATE 1
+#define SQLITE_GET_LOCKPROXYFILE 2
+#define SQLITE_SET_LOCKPROXYFILE 3
+#define SQLITE_LAST_ERRNO 4
/*
** CAPI3REF: Mutex Handle {H17110} <S20130>
**
@@ -1226,28 +1231,28 @@
**
** The zName field holds the name of the VFS module. The name must
** be unique across all VFS modules.
**
-** {H11141} SQLite will guarantee that the zFilename parameter to xOpen
+** SQLite will guarantee that the zFilename parameter to xOpen
** is either a NULL pointer or string obtained
** from xFullPathname(). SQLite further guarantees that
** the string will be valid and unchanged until xClose() is
-** called. {END} Because of the previous sentense,
+** called. Because of the previous sentense,
** the [sqlite3_file] can safely store a pointer to the
** filename if it needs to remember the filename for some reason.
** If the zFilename parameter is xOpen is a NULL pointer then xOpen
** must invite its own temporary name for the file. Whenever the
** xFilename parameter is NULL it will also be the case that the
** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
**
-** {H11142} The flags argument to xOpen() includes all bits set in
+** The flags argument to xOpen() includes all bits set in
** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
** or [sqlite3_open16()] is used, then flags includes at least
-** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]. {END}
+** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
** If xOpen() opens a file read-only then it sets *pOutFlags to
** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
**
-** {H11143} SQLite will also add one of the following flags to the xOpen()
+** SQLite will also add one of the following flags to the xOpen()
** call, depending on the object being opened:
**
** <ul>
** <li> [SQLITE_OPEN_MAIN_DB]
@@ -1256,9 +1261,9 @@
** <li> [SQLITE_OPEN_TEMP_JOURNAL]
** <li> [SQLITE_OPEN_TRANSIENT_DB]
** <li> [SQLITE_OPEN_SUBJOURNAL]
** <li> [SQLITE_OPEN_MASTER_JOURNAL]
-** </ul> {END}
+** </ul>
**
** The file I/O implementation can use the object type flags to
** change the way it deals with files. For example, an application
** that does not care about crash recovery or rollback might make
@@ -1274,30 +1279,30 @@
** <li> [SQLITE_OPEN_DELETEONCLOSE]
** <li> [SQLITE_OPEN_EXCLUSIVE]
** </ul>
**
-** {H11145} The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
-** deleted when it is closed. {H11146} The [SQLITE_OPEN_DELETEONCLOSE]
+** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
+** deleted when it is closed. The [SQLITE_OPEN_DELETEONCLOSE]
** will be set for TEMP databases, journals and for subjournals.
**
-** {H11147} The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened
+** The [SQLITE_OPEN_EXCLUSIVE] flag means the file should be opened
** for exclusive access. This flag is set for all files except
** for the main database file.
**
-** {H11148} At least szOsFile bytes of memory are allocated by SQLite
+** At least szOsFile bytes of memory are allocated by SQLite
** to hold the [sqlite3_file] structure passed as the third
-** argument to xOpen. {END} The xOpen method does not have to
+** argument to xOpen. The xOpen method does not have to
** allocate the structure; it should just fill it in.
**
-** {H11149} The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
+** The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
-** to test whether a file is at least readable. {END} The file can be a
+** to test whether a file is at least readable. The file can be a
** directory.
**
-** {H11150} SQLite will always allocate at least mxPathname+1 bytes for the
-** output buffer xFullPathname. {H11151} The exact size of the output buffer
-** is also passed as a parameter to both methods. {END} If the output buffer
+** SQLite will always allocate at least mxPathname+1 bytes for the
+** output buffer xFullPathname. The exact size of the output buffer
+** is also passed as a parameter to both methods. If the output buffer
** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is
** handled as a fatal error by SQLite, vfs implementations should endeavor
** to prevent this by setting mxPathname to a sufficiently large value.
**
@@ -1309,8 +1314,9 @@
** the actual number of bytes of randomness obtained.
** The xSleep() method causes the calling thread to sleep for at
** least the number of microseconds given. The xCurrentTime()
** method returns a Julian Day Number for the current date and time.
+**
*/
typedef struct sqlite3_vfs sqlite3_vfs;
struct sqlite3_vfs {
int iVersion; /* Structure version number */
@@ -1325,9 +1331,9 @@
int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
- void *(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol);
+ void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
void (*xDlClose)(sqlite3_vfs*, void*);
int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
int (*xSleep)(sqlite3_vfs*, int microseconds);
int (*xCurrentTime)(sqlite3_vfs*, double*);
@@ -1338,16 +1344,16 @@
/*
** CAPI3REF: Flags for the xAccess VFS method {H11190} <H11140>
**
-** {H11191} These integer constants can be used as the third parameter to
+** These integer constants can be used as the third parameter to
** the xAccess method of an [sqlite3_vfs] object. {END} They determine
** what kind of permissions the xAccess method is looking for.
-** {H11192} With SQLITE_ACCESS_EXISTS, the xAccess method
+** With SQLITE_ACCESS_EXISTS, the xAccess method
** simply checks whether the file exists.
-** {H11193} With SQLITE_ACCESS_READWRITE, the xAccess method
+** With SQLITE_ACCESS_READWRITE, the xAccess method
** checks whether the file is both readable and writable.
-** {H11194} With SQLITE_ACCESS_READ, the xAccess method
+** With SQLITE_ACCESS_READ, the xAccess method
** checks whether the file is readable.
*/
#define SQLITE_ACCESS_EXISTS 0
#define SQLITE_ACCESS_READWRITE 1
@@ -1500,9 +1506,9 @@
** where Z and N are non-negative integers and
** S is a pointer to an aligned memory buffer not less than
** Z*N bytes in size shall cause S to be used by the
** [scratch memory allocator] for as many as N simulataneous
-** allocations each of size Z.
+** allocations each of size (Z & ~7).
**
** {H14153} A successful call to [sqlite3_config]([SQLITE_CONFIG_SCRATCH],S,Z,N)
** where S is a NULL pointer shall disable the
** [scratch memory allocator].
@@ -1512,9 +1518,9 @@
** where Z and N are non-negative integers and
** S is a pointer to an aligned memory buffer not less than
** Z*N bytes in size shall cause S to be used by the
** [pagecache memory allocator] for as many as N simulataneous
-** allocations each of size Z.
+** allocations each of size (Z & ~7).
**
** {H14159} A successful call to
** [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],S,Z,N)
** where S is a NULL pointer shall disable the
@@ -1860,20 +1866,20 @@
/*
** CAPI3REF: Last Insert Rowid {H12220} <S10700>
**
** Each entry in an SQLite table has a unique 64-bit signed
-** integer key called the "rowid". The rowid is always available
+** integer key called the [ROWID | "rowid"]. The rowid is always available
** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
** names are not also used by explicitly declared columns. If
-** the table has a column of type INTEGER PRIMARY KEY then that column
+** the table has a column of type [INTEGER PRIMARY KEY] then that column
** is another alias for the rowid.
**
-** This routine returns the rowid of the most recent
+** This routine returns the [rowid] of the most recent
** successful [INSERT] into the database from the [database connection]
** in the first argument. If no successful [INSERT]s
** have ever occurred on that database connection, zero is returned.
**
-** If an [INSERT] occurs within a trigger, then the rowid of the inserted
+** If an [INSERT] occurs within a trigger, then the [rowid] of the inserted
** row is returned by this routine as long as the trigger is running.
** But once the trigger terminates, the value returned by this routine
** reverts to the last value inserted before the trigger fired.
**
@@ -1891,9 +1897,10 @@
** be successful even if it is subsequently rolled back.
**
** INVARIANTS:
**
-** {H12221} The [sqlite3_last_insert_rowid()] function shall return the rowid
+** {H12221} The [sqlite3_last_insert_rowid()] function shall return
+** the [rowid]
** of the most recent successful [INSERT] performed on the same
** [database connection] and within the same or higher level
** trigger context, or zero if there have been no qualifying
** [INSERT] statements.
@@ -1905,12 +1912,12 @@
** ASSUMPTIONS:
**
** {A12232} If a separate thread performs a new [INSERT] on the same
** database connection while the [sqlite3_last_insert_rowid()]
-** function is running and thus changes the last insert rowid,
+** function is running and thus changes the last insert [rowid],
** then the value returned by [sqlite3_last_insert_rowid()] is
** unpredictable and might not equal either the old or the new
-** last insert rowid.
+** last insert [rowid].
*/
SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
/*
@@ -2619,10 +2626,10 @@
/*
** CAPI3REF: Pseudo-Random Number Generator {H17390} <S20000>
**
** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
-** select random ROWIDs when inserting new records into a table that
-** already uses the largest possible ROWID. The PRNG is also used for
+** select random [ROWID | ROWIDs] when inserting new records into a table that
+** already uses the largest possible [ROWID]. The PRNG is also used for
** the build-in random() and randomblob() SQL functions. This interface allows
** applications to access the same PRNG for other purposes.
**
** A call to this routine stores N bytes of randomness into buffer P.
@@ -5569,10 +5576,10 @@
** or [SQLITE_UPDATE], depending on the operation that caused the callback
** to be invoked.
** The third and fourth arguments to the callback contain pointers to the
** database and table name containing the affected row.
-** The final callback parameter is the rowid of the row. In the case of
-** an update, this is the rowid after the update takes place.
+** The final callback parameter is the [rowid] of the row.
+** In the case of an update, this is the [rowid] after the update takes place.
**
** The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).
**
@@ -5613,9 +5620,9 @@
** {H12983} The third and fourth arguments to the callback contain pointers
** to zero-terminated UTF-8 strings which are the names of the
** database and table that is being updated.
-** {H12985} The final callback parameter is the rowid of the row after
+** {H12985} The final callback parameter is the [rowid] of the row after
** the change occurs.
*/
SQLITE_API void *sqlite3_update_hook(
sqlite3*,
@@ -5779,9 +5786,9 @@
** <tr><td> 5th <td> const char* <td> Data type
** <tr><td> 6th <td> const char* <td> Name of default collation sequence
** <tr><td> 7th <td> int <td> True if column has a NOT NULL constraint
** <tr><td> 8th <td> int <td> True if column is part of the PRIMARY KEY
-** <tr><td> 9th <td> int <td> True if column is AUTOINCREMENT
+** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
** </table>
** </blockquote>
**
** The memory pointed to by the character pointers returned for the
@@ -5790,11 +5797,11 @@
**
** If the specified table is actually a view, an [error code] is returned.
**
** If the specified column is "rowid", "oid" or "_rowid_" and an
-** INTEGER PRIMARY KEY column has been explicitly declared, then the output
+** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
** parameters are set for the explicitly declared column. If there is no
-** explicitly declared INTEGER PRIMARY KEY column, then the output
+** explicitly declared [INTEGER PRIMARY KEY] column, then the output
** parameters are set as follows:
**
** <pre>
** data type: "INTEGER"
@@ -5899,9 +5906,9 @@
** that is obtained from [sqlite3_malloc()].
**
** {H12644} Automatic extensions apply across all threads.
*/
-SQLITE_API int sqlite3_auto_extension(void *xEntryPoint);
+SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
/*
** CAPI3REF: Reset Automatic Extension Loading {H12660} <S20500>
**
@@ -6216,9 +6223,9 @@
** in row iRow, column zColumn, table zTable in database zDb;
** in other words, the same BLOB that would be selected by:
**
** <pre>
-** SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
+** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
** </pre> {END}
**
** If the flags parameter is non-zero, the the BLOB is opened for read
** and write access. If it is zero, the BLOB is opened for read access.
@@ -7578,9 +7585,9 @@
** Macros to determine whether the machine is big or little endian,
** evaluated at runtime.
*/
#ifdef SQLITE_AMALGAMATION
-SQLITE_PRIVATE const int sqlite3one;
+SQLITE_PRIVATE const int sqlite3one = 1;
#else
SQLITE_PRIVATE const int sqlite3one;
#endif
#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
@@ -7698,8 +7705,9 @@
*/
typedef struct AggInfo AggInfo;
typedef struct AuthContext AuthContext;
typedef struct Bitvec Bitvec;
+typedef struct RowSet RowSet;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct Db Db;
typedef struct Schema Schema;
@@ -8119,11 +8127,11 @@
#define OP_VNext 1
#define OP_Affinity 2
#define OP_Column 3
#define OP_SetCookie 4
+#define OP_Seek 5
#define OP_Real 126 /* same as TK_FLOAT */
-#define OP_Sequence 5
-#define OP_MoveGt 6
+#define OP_Sequence 6
#define OP_Ge 72 /* same as TK_GE */
#define OP_RowKey 7
#define OP_SCopy 8
#define OP_Eq 68 /* same as TK_EQ */
@@ -8177,41 +8185,41 @@
#define OP_Divide 81 /* same as TK_SLASH */
#define OP_Integer 48
#define OP_ToNumeric 141 /* same as TK_TO_NUMERIC*/
#define OP_Prev 49
+#define OP_RowSetRead 50
#define OP_Concat 83 /* same as TK_CONCAT */
+#define OP_RowSetAdd 51
#define OP_BitAnd 74 /* same as TK_BITAND */
-#define OP_VColumn 50
-#define OP_CreateTable 51
-#define OP_Last 52
+#define OP_VColumn 52
+#define OP_CreateTable 53
+#define OP_Last 54
+#define OP_SeekLe 55
#define OP_IsNull 65 /* same as TK_ISNULL */
-#define OP_IncrVacuum 53
-#define OP_IdxRowid 54
+#define OP_IncrVacuum 56
+#define OP_IdxRowid 57
#define OP_ShiftRight 77 /* same as TK_RSHIFT */
-#define OP_ResetCount 55
-#define OP_FifoWrite 56
-#define OP_ContextPush 57
-#define OP_Yield 58
-#define OP_DropTrigger 59
-#define OP_DropIndex 62
-#define OP_IdxGE 63
-#define OP_IdxDelete 64
-#define OP_Vacuum 73
-#define OP_MoveLe 84
-#define OP_IfNot 85
-#define OP_DropTable 86
-#define OP_MakeRecord 89
+#define OP_ResetCount 58
+#define OP_ContextPush 59
+#define OP_Yield 62
+#define OP_DropTrigger 63
+#define OP_DropIndex 64
+#define OP_IdxGE 73
+#define OP_IdxDelete 84
+#define OP_Vacuum 85
+#define OP_IfNot 86
+#define OP_DropTable 89
+#define OP_SeekLt 90
+#define OP_MakeRecord 91
#define OP_ToBlob 140 /* same as TK_TO_BLOB */
-#define OP_ResultRow 90
-#define OP_Delete 91
-#define OP_AggFinal 92
-#define OP_Compare 93
+#define OP_ResultRow 92
+#define OP_Delete 93
+#define OP_AggFinal 94
+#define OP_Compare 95
#define OP_ShiftLeft 76 /* same as TK_LSHIFT */
-#define OP_Goto 94
-#define OP_TableLock 95
-#define OP_FifoRead 96
-#define OP_Clear 97
-#define OP_MoveLt 98
+#define OP_Goto 96
+#define OP_TableLock 97
+#define OP_Clear 98
#define OP_Le 70 /* same as TK_LE */
#define OP_VerifyCookie 99
#define OP_AggStep 100
#define OP_ToText 139 /* same as TK_TO_TEXT */
@@ -8226,12 +8234,12 @@
#define OP_BitOr 75 /* same as TK_BITOR */
#define OP_Next 106
#define OP_IdxInsert 107
#define OP_Lt 71 /* same as TK_LT */
-#define OP_Insert 108
-#define OP_Destroy 109
-#define OP_ReadCookie 110
-#define OP_ForceInt 111
+#define OP_SeekGe 108
+#define OP_Insert 109
+#define OP_Destroy 110
+#define OP_ReadCookie 111
#define OP_LoadAnalysis 112
#define OP_Explain 113
#define OP_OpenPseudo 114
#define OP_OpenEphemeral 115
@@ -8239,9 +8247,9 @@
#define OP_Move 117
#define OP_Blob 118
#define OP_Add 78 /* same as TK_PLUS */
#define OP_Rewind 119
-#define OP_MoveGe 120
+#define OP_SeekGt 120
#define OP_VBegin 121
#define OP_VUpdate 122
#define OP_IfZero 123
#define OP_BitNot 87 /* same as TK_BITNOT */
@@ -8273,22 +8281,22 @@
#define OPFLG_IN2 0x0008 /* in2: P2 is an input */
#define OPFLG_IN3 0x0010 /* in3: P3 is an input */
#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
-/* 0 */ 0x00, 0x01, 0x00, 0x00, 0x10, 0x02, 0x11, 0x00,\
+/* 0 */ 0x00, 0x01, 0x00, 0x00, 0x10, 0x08, 0x02, 0x00,\
/* 8 */ 0x00, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00,\
/* 16 */ 0x04, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05,\
/* 24 */ 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00,\
/* 32 */ 0x00, 0x00, 0x02, 0x11, 0x11, 0x02, 0x05, 0x00,\
/* 40 */ 0x02, 0x11, 0x04, 0x00, 0x00, 0x0c, 0x11, 0x01,\
-/* 48 */ 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x02, 0x00,\
-/* 56 */ 0x04, 0x00, 0x00, 0x00, 0x2c, 0x2c, 0x00, 0x11,\
+/* 48 */ 0x02, 0x01, 0x21, 0x08, 0x00, 0x02, 0x01, 0x11,\
+/* 56 */ 0x01, 0x02, 0x00, 0x00, 0x2c, 0x2c, 0x00, 0x00,\
/* 64 */ 0x00, 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15,\
-/* 72 */ 0x15, 0x00, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\
-/* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x11, 0x05, 0x00, 0x04,\
-/* 88 */ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,\
-/* 96 */ 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01,\
-/* 104 */ 0x00, 0x00, 0x01, 0x08, 0x00, 0x02, 0x02, 0x05,\
+/* 72 */ 0x15, 0x11, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,\
+/* 80 */ 0x2c, 0x2c, 0x2c, 0x2c, 0x00, 0x00, 0x05, 0x04,\
+/* 88 */ 0x02, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 96 */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\
+/* 104 */ 0x00, 0x00, 0x01, 0x08, 0x11, 0x00, 0x02, 0x02,\
/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x01,\
/* 120 */ 0x11, 0x00, 0x00, 0x05, 0x00, 0x11, 0x02, 0x05,\
/* 128 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/* 136 */ 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,\
@@ -8374,9 +8382,9 @@
** This header file defines the interface that the sqlite page cache
** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
-** @(#) $Id: pager.h,v 1.87 2008/11/19 10:22:33 danielk1977 Exp $
+** @(#) $Id: pager.h,v 1.88 2008/12/10 16:45:51 drh Exp $
*/
#ifndef _PAGER_H_
#define _PAGER_H_
@@ -8454,9 +8462,9 @@
SQLITE_PRIVATE int sqlite3PagerBegin(DbPage*, int exFlag);
SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno, int);
SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
SQLITE_PRIVATE int sqlite3PagerRollback(Pager*);
-SQLITE_PRIVATE int sqlite3PagerIsreadonly(Pager*);
+SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
SQLITE_PRIVATE int sqlite3PagerStmtBegin(Pager*);
SQLITE_PRIVATE int sqlite3PagerStmtCommit(Pager*);
SQLITE_PRIVATE int sqlite3PagerStmtRollback(Pager*);
SQLITE_PRIVATE void sqlite3PagerDontRollback(DbPage*);
@@ -8688,9 +8696,9 @@
**
** This header file is #include-ed by sqliteInt.h and thus ends up
** being included by every source file.
**
-** $Id: os.h,v 1.105 2008/06/26 10:41:19 danielk1977 Exp $
+** $Id: os.h,v 1.106 2008/12/08 18:19:18 drh Exp $
*/
#ifndef _SQLITE_OS_H_
#define _SQLITE_OS_H_
@@ -8929,9 +8937,9 @@
SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
#ifndef SQLITE_OMIT_LOAD_EXTENSION
SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *);
-SQLITE_PRIVATE void *sqlite3OsDlSym(sqlite3_vfs *, void *, const char *);
+void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *);
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int);
@@ -9038,9 +9046,9 @@
struct Db {
char *zName; /* Name of this database */
Btree *pBt; /* The B*Tree structure for this database file */
u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */
- u8 safety_level; /* How aggressive at synching data to disk */
+ u8 safety_level; /* How aggressive at syncing data to disk */
void *pAux; /* Auxiliary data. Usually NULL */
void (*xFreeAux)(void*); /* Routine to free pAux */
Schema *pSchema; /* Pointer to database schema (possibly shared) */
};
@@ -9102,9 +9110,9 @@
#define SQLITE_N_LIMIT (SQLITE_LIMIT_VARIABLE_NUMBER+1)
/*
** Lookaside malloc is a set of fixed-size buffers that can be used
-** to satisify small transient memory allocation requests for objects
+** to satisfy small transient memory allocation requests for objects
** associated with a particular database connection. The use of
** lookaside malloc provides a significant performance enhancement
** (approx 10%) by avoiding numerous malloc/free requests while parsing
** SQL statements.
@@ -9167,9 +9175,9 @@
struct sqlite3 {
sqlite3_vfs *pVfs; /* OS Interface */
int nDb; /* Number of backends currently in use */
Db *aDb; /* All backends */
- int flags; /* Miscellanous flags. See below */
+ int flags; /* Miscellaneous flags. See below */
int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
u8 autoCommit; /* The auto-commit flag. */
@@ -9193,11 +9201,11 @@
int newTnum; /* Rootpage of table being initialized */
u8 busy; /* TRUE if currently initializing */
} init;
int nExtension; /* Number of loaded extensions */
- void **aExtension; /* Array of shared libraray handles */
+ void **aExtension; /* Array of shared library handles */
struct Vdbe *pVdbe; /* List of active virtual machines */
- int activeVdbeCnt; /* Number of vdbes currently executing */
+ int activeVdbeCnt; /* Number of VDBEs currently executing */
int writeVdbeCnt; /* Number of active VDBEs that are writing */
void (*xTrace)(void*,const char*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
void (*xProfile)(void*,const char*,u64); /* Profiling function */
@@ -9306,9 +9314,9 @@
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */
void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */
- void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */
+ void (*xFinalize)(sqlite3_context*); /* Aggregate finalizer */
char *zName; /* SQL name of the function. */
FuncDef *pHash; /* Next with a different name but the same hash */
};
@@ -9316,9 +9324,9 @@
** Possible values for FuncDef.flags
*/
#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */
-#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */
+#define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -9388,9 +9396,9 @@
** A "Collating Sequence" is defined by an instance of the following
** structure. Conceptually, a collating sequence consists of a name and
** a comparison routine that defines the order of that sequence.
**
-** There may two seperate implementations of the collation function, one
+** There may two separate implementations of the collation function, one
** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that
** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
** native byte order. When a collation sequence is invoked, SQLite selects
** the version that will require the least expensive encoding
@@ -9527,9 +9535,9 @@
/*
** Allowed values for Tabe.tabFlags.
*/
#define TF_Readonly 0x01 /* Read-only system table */
-#define TF_Ephemeral 0x02 /* An emphermal table */
+#define TF_Ephemeral 0x02 /* An ephemeral 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 */
@@ -9565,9 +9573,9 @@
** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2".
**
** Each REFERENCES clause generates an instance of the following structure
** which is attached to the from-table. The to-table need not exist when
-** the from-table is created. The existance of the to-table is not checked
+** the from-table is created. The existence of the to-table is not checked
** until an attempt is made to insert data into the from-table.
**
** The sqlite.aFKey hash table stores pointers to this structure
** given the name of a to-table. For each to-table, all foreign keys
@@ -9574,9 +9582,9 @@
** associated with that table are on a linked list using the FKey.pNextTo
** field.
*/
struct FKey {
- Table *pFrom; /* The table that constains the REFERENCES clause */
+ Table *pFrom; /* The table that contains the REFERENCES clause */
FKey *pNextFrom; /* Next foreign key in pFrom */
char *zTo; /* Name of table that the key points to */
FKey *pNextTo; /* Next foreign key that points to zTo */
int nCol; /* Number of columns in this key */
@@ -9650,13 +9658,13 @@
**
** 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
+** the OP_MakeRecord opcode of the VDBE and is disassembled by the
** OP_Column opcode.
**
** This structure holds a record that has already been disassembled
-** into its constitutent fields.
+** into its constituent fields.
*/
struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
u16 nField; /* Number of entries in apMem[] */
@@ -9719,9 +9727,9 @@
** Each token coming out of the lexer is an instance of
** this structure. Tokens are also used as part of an expression.
**
** Note if Token.z==0 then Token.dyn and Token.n are undefined and
-** may contain random values. Do not make any assuptions about Token.dyn
+** may contain random values. Do not make any assumptions about Token.dyn
** and Token.n when Token.z==0.
*/
struct Token {
const unsigned char *z; /* Text of the token. Not NULL-terminated! */
@@ -9766,9 +9774,9 @@
struct AggInfo_func { /* For each aggregate function */
Expr *pExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
- int iDistinct; /* Ephermeral table used to enforce DISTINCT */
+ int iDistinct; /* Ephemeral table used to enforce DISTINCT */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
int nFuncAlloc; /* Number of slots allocated for aFunc[] */
};
@@ -9994,24 +10002,25 @@
**
*/
struct WhereLevel {
int iFrom; /* Which entry in the FROM clause */
- int flags; /* Flags associated with this level */
+ int wsFlags; /* "Where-Scan" flags show the choosen scan strategy */
int iMem; /* First memory cell used by this level */
int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */
Index *pIdx; /* Index used. NULL if no index */
int iTabCur; /* The VDBE cursor used to access the table */
- int iIdxCur; /* The VDBE cursor used to acesss pIdx */
- int brk; /* Jump here to break out of the loop */
- int nxt; /* Jump here to start the next IN combination */
- int cont; /* Jump here to continue with the next loop cycle */
- int top; /* First instruction of interior of the loop */
- int op, p1, p2, p5; /* Opcode used to terminate the loop */
+ int iIdxCur; /* The VDBE cursor used to access pIdx */
+ int addrBrk; /* Jump here to break out of the loop */
+ int addrNxt; /* Jump here to start the next IN combination */
+ int addrCont; /* Jump here to continue with the next loop cycle */
+ int addrFirst; /* First instruction of interior of the loop */
+ int op, p1, p2; /* Opcode used to terminate the loop */
+ u8 p5; /* P5 operand of the opcode that terminates the loop */
int nEq; /* Number of == or IN constraints on this loop */
int nIn; /* Number of IN operators constraining this loop */
struct InLoop {
int iCur; /* The VDBE cursor used by this IN operator */
- int topAddr; /* Top of the IN loop */
+ int addrInTop; /* Top of the IN loop */
} *aInLoop; /* Information about each nested IN operator */
sqlite3_index_info *pBestIdx; /* Index information for this level */
/* The following field is really not part of the current level. But
@@ -10021,9 +10030,9 @@
sqlite3_index_info *pIdxInfo; /* Index info for n-th source table */
};
/*
-** Flags appropriate for the wflags parameter of sqlite3WhereBegin().
+** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin().
*/
#define WHERE_ORDERBY_NORMAL 0 /* No-op */
#define WHERE_ORDERBY_MIN 1 /* ORDER BY processing for min() func */
#define WHERE_ORDERBY_MAX 2 /* ORDER BY processing for max() func */
@@ -10153,9 +10162,9 @@
#define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine 10 /* Generate a single row of result */
/*
-** A structure used to customize the behaviour of sqlite3Select(). See
+** A structure used to customize the behavior of sqlite3Select(). See
** comments above sqlite3Select() for details.
*/
typedef struct SelectDest SelectDest;
struct SelectDest {
@@ -10229,8 +10238,9 @@
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 nAliasAlloc; /* Number of allocated slots for aAlias[] */
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 */
@@ -10293,9 +10303,9 @@
char *name; /* The name of the trigger */
char *table; /* The table or view to which the trigger applies */
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
- Expr *pWhen; /* The WHEN clause of the expresion (may be NULL) */
+ Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
the <column-list> is stored here */
Token nameToken; /* Token containing zName. Use during parsing only */
Schema *pSchema; /* Schema containing the trigger */
@@ -10431,9 +10441,9 @@
int nChar; /* Length of the string so far */
int nAlloc; /* Amount of space allocated in zText */
int mxAlloc; /* Maximum allowed string length */
u8 mallocFailed; /* Becomes true if any memory allocation fails */
- u8 useMalloc; /* True if zText is enlargable using realloc */
+ u8 useMalloc; /* True if zText is enlargeable using realloc */
u8 tooBig; /* Becomes true if string size exceeds limits */
};
/*
@@ -10470,15 +10480,17 @@
int nScratch; /* Number of scratch buffers */
void *pPage; /* Page cache memory */
int szPage; /* Size of each page in pPage[] */
int nPage; /* Number of pages in pPage[] */
+ int mxParserStack; /* maximum depth of the parser stack */
+ int sharedCacheEnabled; /* true if shared-cache mode enabled */
+ /* The above might be initialized to non-zero. The following need to always
+ ** initially be zero, however. */
int isInit; /* True after initialization has finished */
int inProgress; /* True while initialization in progress */
int isMallocInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
- int mxParserStack; /* maximum depth of the parser stack */
- int sharedCacheEnabled; /* true if shared-cache mode enabled */
};
/*
** Context pointer passed down through the tree-walk.
@@ -10503,11 +10515,11 @@
/*
** Return code from the parse-tree walking primitives and their
** callbacks.
*/
-#define WRC_Continue 0
-#define WRC_Prune 1
-#define WRC_Abort 2
+#define WRC_Continue 0 /* Continue down into children */
+#define WRC_Prune 1 /* Omit children but continue walking siblings */
+#define WRC_Abort 2 /* Abandon the tree walk */
/*
** 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.
@@ -10537,8 +10549,9 @@
SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *);
SQLITE_PRIVATE int sqlite3StrNICmp(const char *, const char *, int);
SQLITE_PRIVATE int sqlite3IsNumber(const char*, int*, u8);
SQLITE_PRIVATE int sqlite3Strlen(sqlite3*, const char*);
+SQLITE_PRIVATE int sqlite3Strlen30(const char*);
SQLITE_PRIVATE int sqlite3MallocInit(void);
SQLITE_PRIVATE void sqlite3MallocEnd(void);
SQLITE_PRIVATE void *sqlite3Malloc(int);
@@ -10638,8 +10651,13 @@
SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32);
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*);
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
+
+SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
+SQLITE_PRIVATE void sqlite3RowSetClear(RowSet*);
+SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64);
+SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*);
SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
@@ -10821,10 +10839,10 @@
** the MACRO form does).
*/
SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64);
SQLITE_PRIVATE int sqlite3PutVarint32(unsigned char*, u32);
-SQLITE_PRIVATE int sqlite3GetVarint(const unsigned char *, u64 *);
-SQLITE_PRIVATE int sqlite3GetVarint32(const unsigned char *, u32 *);
+SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *, u64 *);
+SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *, u32 *);
SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
/*
** The header of a record consists of a sequence variable-length integers.
@@ -10842,10 +10860,10 @@
** x = getVarint32( A, B );
** x = putVarint32( A, B );
**
*/
-#define getVarint32(A,B) ((*(A)<(unsigned char)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), (u32 *)&(B)))
-#define putVarint32(A,B) (((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B)))
+#define getVarint32(A,B) (u8)((*(A)<(u8)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), (u32 *)&(B)))
+#define putVarint32(A,B) (u8)(((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B)))
#define getVarint sqlite3GetVarint
#define putVarint sqlite3PutVarint
@@ -11070,9 +11088,9 @@
*************************************************************************
**
** This file contains definitions of global variables and contants.
**
-** $Id: global.c,v 1.8 2008/09/04 17:17:39 danielk1977 Exp $
+** $Id: global.c,v 1.9 2008/12/08 18:19:18 drh Exp $
*/
/* An array to map all upper-case characters into their corresponding
@@ -11130,9 +11148,28 @@
SQLITE_THREADSAFE==1, /* bFullMutex */
0x7ffffffe, /* mxStrlen */
100, /* szLookaside */
500, /* nLookaside */
- /* Other fields all default to zero */
+ {0,0,0,0,0,0,0,0}, /* m */
+ {0,0,0,0,0,0,0,0,0}, /* mutex */
+ {0,0,0,0,0,0,0,0,0,0,0}, /* pcache */
+ (void*)0, /* pHeap */
+ 0, /* nHeap */
+ 0, 0, /* mnHeap, mxHeap */
+ (void*)0, /* pScratch */
+ 0, /* szScratch */
+ 0, /* nScratch */
+ (void*)0, /* pPage */
+ 0, /* szPage */
+ 0, /* nPage */
+ 0, /* mxParserStack */
+ 0, /* sharedCacheEnabled */
+ /* All the rest need to always be zero */
+ 0, /* isInit */
+ 0, /* inProgress */
+ 0, /* isMallocInit */
+ 0, /* pInitMutex */
+ 0, /* nRefInitMutex */
};
/*
@@ -11285,9 +11322,9 @@
** There is only one exported symbol in this file - the function
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: date.c,v 1.94 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: date.c,v 1.98 2008/12/10 22:30:25 shane Exp $
**
** SQLite processes all times and dates as Julian Day numbers. The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
@@ -11346,12 +11383,12 @@
int Y, M, D; /* Year, month, and day */
int h, m; /* Hour and minutes */
int tz; /* Timezone offset in minutes */
double s; /* Seconds */
- char validYMD; /* True if Y,M,D are valid */
- char validHMS; /* True if h,m,s are valid */
- char validJD; /* True if iJD is valid */
- char validTZ; /* True if tz is valid */
+ char validYMD; /* True (1) if Y,M,D are valid */
+ char validHMS; /* True (1) if h,m,s are valid */
+ char validJD; /* True (1) if iJD is valid */
+ char validTZ; /* True (1) if tz is valid */
};
/*
@@ -11491,9 +11528,9 @@
p->h = h;
p->m = m;
p->s = s + ms;
if( parseTimezone(zDate, p) ) return 1;
- p->validTZ = p->tz!=0;
+ p->validTZ = (p->tz!=0)?1:0;
return 0;
}
/*
@@ -11520,14 +11557,14 @@
M += 12;
}
A = Y/100;
B = 2 - A + (A/4);
- X1 = 365.25*(Y+4716);
- X2 = 30.6001*(M+1);
- p->iJD = (X1 + X2 + D + B - 1524.5)*86400000;
+ X1 = 36525*(Y+4716)/100;
+ X2 = 306001*(M+1)/10000;
+ p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
p->validJD = 1;
if( p->validHMS ){
- p->iJD += p->h*3600000 + p->m*60000 + p->s*1000;
+ p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000);
if( p->validTZ ){
p->iJD -= p->tz*60000;
p->validYMD = 0;
p->validHMS = 0;
@@ -11639,16 +11676,16 @@
p->Y = 2000;
p->M = 1;
p->D = 1;
}else{
- Z = (p->iJD + 43200000)/86400000;
- A = (Z - 1867216.25)/36524.25;
+ Z = (int)((p->iJD + 43200000)/86400000);
+ A = (int)((Z - 1867216.25)/36524.25);
A = Z + 1 + A - (A/4);
B = A + 1524;
- C = (B - 122.1)/365.25;
- D = 365.25*C;
- E = (B-D)/30.6001;
- X1 = 30.6001*E;
+ C = (int)((B - 122.1)/365.25);
+ D = (36525*C)/100;
+ E = (int)((B-D)/30.6001);
+ X1 = (int)(30.6001*E);
p->D = B - D - X1;
p->M = E<14 ? E-1 : E-13;
p->Y = p->M>2 ? C - 4716 : C - 4715;
}
@@ -11661,11 +11698,11 @@
static void computeHMS(DateTime *p){
int s;
if( p->validHMS ) return;
computeJD(p);
- s = (p->iJD + 43200000) % 86400000;
+ s = (int)((p->iJD + 43200000) % 86400000);
p->s = s/1000.0;
- s = p->s;
+ s = (int)p->s;
p->s -= s;
p->h = s/3600;
s -= p->h*3600;
p->m = s/60;
@@ -11695,9 +11732,9 @@
** Compute the difference (in milliseconds)
** between localtime and UTC (a.k.a. GMT)
** for the time value p where p is in UTC.
*/
-static int localtimeOffset(DateTime *p){
+static sqlite3_int64 localtimeOffset(DateTime *p){
DateTime x, y;
time_t t;
x = *p;
computeYMD_HMS(&x);
@@ -11708,15 +11745,15 @@
x.h = 0;
x.m = 0;
x.s = 0.0;
} else {
- int s = x.s + 0.5;
+ int s = (int)(x.s + 0.5);
x.s = s;
}
x.tz = 0;
x.validJD = 0;
computeJD(&x);
- t = x.iJD/1000 - 2440587.5*86400.0;
+ t = x.iJD/1000 - 210866760000LL;
#ifdef HAVE_LOCALTIME_R
{
struct tm sLocal;
localtime_r(&t, &sLocal);
@@ -11788,9 +11825,9 @@
double r;
char *z, zBuf[30];
z = zBuf;
for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
- z[n] = tolower(zMod[n]);
+ z[n] = (char)sqlite3UpperToLower[(u8)zMod[n]];
}
z[n] = 0;
switch( z[0] ){
#ifndef SQLITE_OMIT_LOCALTIME
@@ -11816,15 +11853,15 @@
** Treat the current value of p->iJD as the number of
** seconds since 1970. Convert to a real julian day number.
*/
if( strcmp(z, "unixepoch")==0 && p->validJD ){
- p->iJD = p->iJD/86400.0 + 2440587.5*86400000.0;
+ p->iJD = p->iJD/86400 + 210866760000000LL;
clearYMD_HMS_TZ(p);
rc = 0;
}
#ifndef SQLITE_OMIT_LOCALTIME
else if( strcmp(z, "utc")==0 ){
- int c1;
+ sqlite3_int64 c1;
computeJD(p);
c1 = localtimeOffset(p);
p->iJD -= c1;
clearYMD_HMS_TZ(p);
@@ -11842,9 +11879,9 @@
** weekday N where 0==Sunday, 1==Monday, and so forth. If the
** date is already on the appropriate weekday, this is a no-op.
*/
if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
- && (n=r)==r && n>=0 && r<7 ){
+ && (n=(int)r)==r && n>=0 && r<7 ){
sqlite3_int64 Z;
computeYMD_HMS(p);
p->validTZ = 0;
p->validJD = 0;
@@ -11923,37 +11960,37 @@
break;
}
z += n;
while( isspace(*(u8*)z) ) z++;
- n = strlen(z);
+ n = sqlite3Strlen30(z);
if( n>10 || n<3 ) break;
if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
computeJD(p);
rc = 0;
if( n==3 && strcmp(z,"day")==0 ){
- p->iJD += r*86400000.0 + 0.5;
+ p->iJD += (sqlite3_int64)(r*86400000.0 + 0.5);
}else if( n==4 && strcmp(z,"hour")==0 ){
- p->iJD += r*(86400000.0/24.0) + 0.5;
+ p->iJD += (sqlite3_int64)(r*(86400000.0/24.0) + 0.5);
}else if( n==6 && strcmp(z,"minute")==0 ){
- p->iJD += r*(86400000.0/(24.0*60.0)) + 0.5;
+ p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0)) + 0.5);
}else if( n==6 && strcmp(z,"second")==0 ){
- p->iJD += r*(86400000.0/(24.0*60.0*60.0)) + 0.5;
+ p->iJD += (sqlite3_int64)(r*(86400000.0/(24.0*60.0*60.0)) + 0.5);
}else if( n==5 && strcmp(z,"month")==0 ){
int x, y;
computeYMD_HMS(p);
- p->M += r;
+ p->M += (int)r;
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
p->Y += x;
p->M -= x*12;
p->validJD = 0;
computeJD(p);
- y = r;
+ y = (int)r;
if( y!=r ){
- p->iJD += (r - y)*30.0*86400000.0 + 0.5;
+ p->iJD += (sqlite3_int64)((r - y)*30.0*86400000.0 + 0.5);
}
}else if( n==4 && strcmp(z,"year")==0 ){
computeYMD_HMS(p);
- p->Y += r;
+ p->Y += (int)r;
p->validJD = 0;
computeJD(p);
}else{
rc = 1;
@@ -11990,9 +12027,9 @@
if( argc==0 ){
setDateTimeToCurrent(context, p);
}else if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
|| eType==SQLITE_INTEGER ){
- p->iJD = sqlite3_value_double(argv[0])*86400000.0 + 0.5;
+ p->iJD = (sqlite3_int64)(sqlite3_value_double(argv[0])*86400000.0 + 0.5);
p->validJD = 1;
}else{
z = sqlite3_value_text(argv[0]);
if( !z || parseDateOrTime(context, (char*)z, p) ){
@@ -12113,9 +12150,9 @@
sqlite3_value **argv
){
DateTime x;
u64 n;
- int i, j;
+ size_t i,j;
char *z;
sqlite3 *db;
const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
char zBuf[100];
@@ -12159,9 +12196,9 @@
}else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
return;
}else{
- z = sqlite3DbMallocRaw(db, n);
+ z = sqlite3DbMallocRaw(db, (int)n);
if( z==0 ){
sqlite3_result_error_nomem(context);
return;
}
@@ -12178,9 +12215,9 @@
case 'f': {
double s = x.s;
if( s>59.999 ) s = 59.999;
sqlite3_snprintf(7, &z[j],"%06.3f", s);
- j += strlen(&z[j]);
+ j += sqlite3Strlen30(&z[j]);
break;
}
case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
case 'W': /* Fall thru */
@@ -12190,12 +12227,12 @@
y.validJD = 0;
y.M = 1;
y.D = 1;
computeJD(&y);
- nDay = (x.iJD - y.iJD)/86400000.0 + 0.5;
+ nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
if( zFmt[i]=='W' ){
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
- wd = ((x.iJD+43200000)/86400000) % 7;
+ wd = (int)(((x.iJD+43200000)/86400000)%7);
sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
j += 2;
}else{
sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
@@ -12204,22 +12241,28 @@
break;
}
case 'J': {
sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
- j+=strlen(&z[j]);
+ j+=sqlite3Strlen30(&z[j]);
break;
}
case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
case 's': {
sqlite3_snprintf(30,&z[j],"%d",
(int)(x.iJD/1000.0 - 210866760000.0));
- j += strlen(&z[j]);
+ j += sqlite3Strlen30(&z[j]);
break;
}
case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
- case 'w': z[j++] = (((x.iJD+129600000)/86400000) % 7) + '0'; break;
- case 'Y': sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=strlen(&z[j]);break;
+ case 'w': {
+ z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
+ break;
+ }
+ case 'Y': {
+ sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlite3Strlen30(&z[j]);
+ break;
+ }
default: z[j++] = '%'; break;
}
}
}
@@ -12364,9 +12407,9 @@
**
** This file contains OS interface code that is common to all
** architectures.
**
-** $Id: os.c,v 1.124 2008/10/07 15:25:48 drh Exp $
+** $Id: os.c,v 1.125 2008/12/08 18:19:18 drh Exp $
*/
#define _SQLITE_OS_C_ 1
#undef _SQLITE_OS_C_
@@ -12492,10 +12535,10 @@
}
SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
pVfs->xDlError(pVfs, nByte, zBufOut);
}
-SQLITE_PRIVATE void *sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
- return pVfs->xDlSym(pVfs, pHandle, zSymbol);
+void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
+ return pVfs->xDlSym(pVfs, pHdle, zSym);
}
SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
pVfs->xDlClose(pVfs, pHandle);
}
@@ -12804,9 +12847,9 @@
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
-** $Id: mem1.c,v 1.28 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: mem1.c,v 1.29 2008/12/10 21:19:57 drh Exp $
*/
/*
** This version of the memory allocator is the default. It is
@@ -12882,9 +12925,9 @@
sqlite3_int64 *p;
if( pPrior==0 ) return 0;
p = (sqlite3_int64*)pPrior;
p--;
- return p[0];
+ return (int)p[0];
}
/*
** Round up a request size to the next valid allocation size.
@@ -12953,9 +12996,9 @@
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
-** $Id: mem2.c,v 1.40 2008/10/28 18:58:20 drh Exp $
+** $Id: mem2.c,v 1.42 2008/12/10 19:26:24 drh Exp $
*/
/*
** This version of the memory allocator is used only if the
@@ -13090,13 +13133,13 @@
int nReserve;
p = (struct MemBlockHdr*)pAllocation;
p--;
- assert( p->iForeGuard==FOREGUARD );
+ assert( p->iForeGuard==(int)FOREGUARD );
nReserve = (p->iSize+7)&~7;
pInt = (int*)pAllocation;
pU8 = (u8*)pAllocation;
- assert( pInt[nReserve/sizeof(int)]==REARGUARD );
+ assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
assert( (nReserve-0)<=p->iSize || pU8[nReserve-1]==0x65 );
assert( (nReserve-1)<=p->iSize || pU8[nReserve-2]==0x65 );
assert( (nReserve-2)<=p->iSize || pU8[nReserve-3]==0x65 );
return p;
@@ -13117,8 +13160,9 @@
/*
** Initialize the memory allocation subsystem.
*/
static int sqlite3MemInit(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
if( !sqlite3GlobalConfig.bMemstat ){
/* If memory status is enabled, then the malloc.c wrapper will already
** hold the STATIC_MEM mutex when the routines here are invoked. */
mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
@@ -13129,8 +13173,9 @@
/*
** Deinitialize the memory allocation subsystem.
*/
static void sqlite3MemShutdown(void *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
mem.mutex = 0;
}
/*
@@ -13293,9 +13338,9 @@
/*
** Set the title string for subsequent allocations.
*/
SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){
- int n = strlen(zTitle) + 1;
+ unsigned int n = sqlite3Strlen30(zTitle) + 1;
sqlite3_mutex_enter(mem.mutex);
if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
memcpy(mem.zTitle, zTitle, n);
mem.zTitle[n] = 0;
@@ -14727,9 +14772,9 @@
** If compiled with SQLITE_DEBUG, then additional logic is inserted
** that does error checking on mutexes to make sure they are being
** called correctly.
**
-** $Id: mutex_noop.c,v 1.2 2008/10/15 19:03:03 drh Exp $
+** $Id: mutex_noop.c,v 1.3 2008/12/05 17:17:08 drh Exp $
*/
#if defined(SQLITE_MUTEX_NOOP) && !defined(SQLITE_DEBUG)
@@ -14817,9 +14862,9 @@
break;
}
default: {
assert( id-2 >= 0 );
- assert( id-2 < sizeof(aStatic)/sizeof(aStatic[0]) );
+ assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
pNew = &aStatic[id-2];
pNew->id = id;
break;
}
@@ -14901,9 +14946,9 @@
**
*************************************************************************
** This file contains the C functions that implement mutexes for OS/2
**
-** $Id: mutex_os2.c,v 1.10 2008/06/23 22:13:28 pweilbacher Exp $
+** $Id: mutex_os2.c,v 1.11 2008/11/22 19:50:54 pweilbacher Exp $
*/
/*
** The code in this file is only used if SQLITE_MUTEX_OS2 is defined.
@@ -15011,9 +15056,9 @@
while( !isInit ){
mutex = 0;
rc = DosCreateMutexSem( name, &mutex, 0, FALSE);
if( rc == NO_ERROR ){
- int i;
+ unsigned int i;
if( !isInit ){
for( i = 0; i < sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++ ){
DosCreateMutexSem( 0, &staticMutexes[i].mutex, 0, FALSE );
}
@@ -15176,9 +15221,9 @@
**
*************************************************************************
** This file contains the C functions that implement mutexes for pthreads
**
-** $Id: mutex_unix.c,v 1.15 2008/11/17 19:18:55 danielk1977 Exp $
+** $Id: mutex_unix.c,v 1.16 2008/12/08 18:19:18 drh Exp $
*/
/*
** The code in this file is only used if we are compiling threadsafe
@@ -15480,8 +15525,11 @@
pthreadMutexLeave,
#ifdef SQLITE_DEBUG
pthreadMutexHeld,
pthreadMutexNotheld
+#else
+ 0,
+ 0
#endif
};
return &sMutex;
@@ -15503,9 +15551,9 @@
**
*************************************************************************
** This file contains the C functions that implement mutexes for win32
**
-** $Id: mutex_w32.c,v 1.12 2008/11/10 20:01:41 shane Exp $
+** $Id: mutex_w32.c,v 1.13 2008/12/08 18:19:18 drh Exp $
*/
/*
** The code in this file is only used if we are compiling multithreaded
@@ -15734,8 +15782,11 @@
winMutexLeave,
#ifdef SQLITE_DEBUG
winMutexHeld,
winMutexNotheld
+#else
+ 0,
+ 0
#endif
};
return &sMutex;
@@ -15757,9 +15808,9 @@
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
**
-** $Id: malloc.c,v 1.48 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: malloc.c,v 1.53 2008/12/16 17:20:38 shane Exp $
*/
/*
** This routine runs when the memory allocator sees that the
@@ -15792,9 +15843,9 @@
sqlite3MemoryAlarm(softHeapLimitEnforcer, 0, iLimit);
}else{
sqlite3MemoryAlarm(0, 0, 0);
}
- overage = sqlite3_memory_used() - n;
+ overage = (int)(sqlite3_memory_used() - (i64)n);
if( overage>0 ){
sqlite3_release_memory(overage);
}
}
@@ -15864,9 +15915,9 @@
}
if( sqlite3GlobalConfig.pScratch && sqlite3GlobalConfig.szScratch>=100
&& sqlite3GlobalConfig.nScratch>=0 ){
int i;
- sqlite3GlobalConfig.szScratch -= 4;
+ sqlite3GlobalConfig.szScratch = (sqlite3GlobalConfig.szScratch - 4) & ~7;
mem0.aScratchFree = (u32*)&((char*)sqlite3GlobalConfig.pScratch)
[sqlite3GlobalConfig.szScratch*sqlite3GlobalConfig.nScratch];
for(i=0; i<sqlite3GlobalConfig.nScratch; i++){ mem0.aScratchFree[i] = i; }
mem0.nScratchFree = sqlite3GlobalConfig.nScratch;
@@ -15877,9 +15928,9 @@
if( sqlite3GlobalConfig.pPage && sqlite3GlobalConfig.szPage>=512
&& sqlite3GlobalConfig.nPage>=1 ){
int i;
int overhead;
- int sz = sqlite3GlobalConfig.szPage;
+ int sz = sqlite3GlobalConfig.szPage & ~7;
int n = sqlite3GlobalConfig.nPage;
overhead = (4*n + sz - 1)/sz;
sqlite3GlobalConfig.nPage -= overhead;
mem0.aPageFree = (u32*)&((char*)sqlite3GlobalConfig.pPage)
@@ -16077,8 +16128,9 @@
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
sqlite3_mutex_leave(mem0.mutex);
p = (void*)&((char*)sqlite3GlobalConfig.pScratch)[i];
+ assert( (((u8*)p - (u8*)0) & 7)==0 );
}
}
#if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
scratchAllocOut = p!=0;
@@ -16127,9 +16179,9 @@
sqlite3GlobalConfig.m.xFree(p);
}
}else{
int i;
- i = (u8 *)p - (u8 *)sqlite3GlobalConfig.pScratch;
+ i = (int)((u8*)p - (u8*)sqlite3GlobalConfig.pScratch);
i /= sqlite3GlobalConfig.szScratch;
assert( i>=0 && i<sqlite3GlobalConfig.nScratch );
sqlite3_mutex_enter(mem0.mutex);
assert( mem0.nScratchFree<(u32)sqlite3GlobalConfig.nScratch );
@@ -16247,9 +16299,11 @@
SQLITE_PRIVATE int sqlite3MallocSize(void *p){
return sqlite3GlobalConfig.m.xSize(p);
}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
- if( isLookaside(db, p) ){
+ if( p==0 ){
+ return 0;
+ }else if( isLookaside(db, p) ){
return db->lookaside.sz;
}else{
return sqlite3GlobalConfig.m.xSize(p);
}
@@ -16464,9 +16518,9 @@
size_t n;
if( z==0 ){
return 0;
}
- n = strlen(z)+1;
+ n = (db ? sqlite3Strlen(db, z) : sqlite3Strlen30(z))+1;
assert( (n&0x7fffffff)==n );
zNew = sqlite3DbMallocRaw(db, (int)n);
if( zNew ){
memcpy(zNew, z, n);
@@ -16539,9 +16593,9 @@
** completeness. They are very out-of-date but might be useful as
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
-** $Id: printf.c,v 1.96 2008/11/20 18:20:28 drh Exp $
+** $Id: printf.c,v 1.99 2008/12/10 19:26:24 drh Exp $
**
**************************************************************************
**
** The following modules is an enhanced replacement for the "printf" subroutines
@@ -16689,17 +16743,17 @@
** The counter *cnt is incremented each time. After counter exceeds
** 16 (the number of significant digits in a 64-bit float) '0' is
** always returned.
*/
-static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
+static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
int digit;
LONGDOUBLE_TYPE d;
if( (*cnt)++ >= 16 ) return '0';
digit = (int)*val;
d = digit;
digit += '0';
*val = (*val - d)*10.0;
- return digit;
+ return (char)digit;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
/*
@@ -16778,9 +16832,9 @@
LONGDOUBLE_TYPE realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
- etByte xtype; /* Conversion paradigm */
+ etByte xtype = 0; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
#ifndef SQLITE_OMIT_FLOATING_POINT
int exp, e2; /* exponent of real numbers */
double rounder; /* Used for rounding floating point values */
@@ -16946,9 +17000,9 @@
}
bufpt = &buf[etBUFSIZE-1];
if( xtype==etORDINAL ){
static const char zOrd[] = "thstndrd";
- int x = longvalue % 10;
+ int x = (int)(longvalue % 10);
if( x>=4 || (longvalue/10)%10==1 ){
x = 0;
}
buf[etBUFSIZE-3] = zOrd[x*2];
@@ -16964,9 +17018,9 @@
*(--bufpt) = cset[longvalue%base];
longvalue = longvalue/base;
}while( longvalue>0 );
}
- length = &buf[etBUFSIZE-1]-bufpt;
+ length = (int)(&buf[etBUFSIZE-1]-bufpt);
for(idx=precision-length; idx>0; idx--){
*(--bufpt) = '0'; /* Zero pad */
}
if( prefix ) *(--bufpt) = prefix; /* Add sign */
@@ -16975,9 +17029,9 @@
char x;
pre = &aPrefix[infop->prefix];
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
}
- length = &buf[etBUFSIZE-1]-bufpt;
+ length = (int)(&buf[etBUFSIZE-1]-bufpt);
break;
case etFLOAT:
case etEXP:
case etGENERIC:
@@ -17003,9 +17057,9 @@
#endif
if( xtype==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
- if( sqlite3IsNaN(realvalue) ){
+ if( sqlite3IsNaN((double)realvalue) ){
bufpt = "NaN";
length = 3;
break;
}
@@ -17022,9 +17076,9 @@
bufpt = "+Inf";
}else{
bufpt = "Inf";
}
- length = strlen(bufpt);
+ length = sqlite3Strlen30(bufpt);
break;
}
}
bufpt = buf;
@@ -17053,9 +17107,9 @@
}else{
e2 = exp;
}
nsd = 0;
- flag_dp = (precision>0) | flag_alternateform | flag_altform2;
+ flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
if( prefix ){
*(bufpt++) = prefix;
}
@@ -17101,20 +17155,20 @@
}else{
*(bufpt++) = '+';
}
if( exp>=100 ){
- *(bufpt++) = (exp/100)+'0'; /* 100's digit */
+ *(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */
exp %= 100;
}
- *(bufpt++) = exp/10+'0'; /* 10's digit */
- *(bufpt++) = exp%10+'0'; /* 1's digit */
+ *(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
+ *(bufpt++) = (char)(exp%10+'0'); /* 1's digit */
}
*bufpt = 0;
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
- length = bufpt-buf;
+ length = (int)(bufpt-buf);
bufpt = buf;
/* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */
@@ -17139,11 +17193,12 @@
bufpt = buf;
length = 1;
break;
case etCHARX:
- c = buf[0] = va_arg(ap,int);
+ c = va_arg(ap,int);
+ buf[0] = (char)c;
if( precision>=0 ){
- for(idx=1; idx<precision; idx++) buf[idx] = c;
+ for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
length = precision;
}else{
length =1;
}
@@ -17159,16 +17214,17 @@
}
if( precision>=0 ){
for(length=0; length<precision && bufpt[length]; length++){}
}else{
- length = strlen(bufpt);
+ length = sqlite3Strlen30(bufpt);
}
break;
case etSQLESCAPE:
case etSQLESCAPE2:
case etSQLESCAPE3: {
- int i, j, n, ch, isnull;
+ int i, j, n, isnull;
int needQuote;
+ char ch;
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg = va_arg(ap,char*);
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
@@ -17256,11 +17312,11 @@
if( p->tooBig | p->mallocFailed ){
return;
}
if( N<0 ){
- N = strlen(z);
- }
- if( N==0 ){
+ N = sqlite3Strlen30(z);
+ }
+ if( N==0 || z==0 ){
return;
}
if( p->nChar+N >= p->nAlloc ){
char *zNew;
@@ -17277,9 +17333,9 @@
sqlite3StrAccumReset(p);
p->tooBig = 1;
return;
}else{
- p->nAlloc = szNew;
+ p->nAlloc = (int)szNew;
}
zNew = sqlite3DbMallocRaw(p->db, p->nAlloc );
if( zNew ){
memcpy(zNew, p->zText, p->nChar);
@@ -17485,9 +17541,9 @@
**
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
-** $Id: random.c,v 1.27 2008/10/07 15:25:48 drh Exp $
+** $Id: random.c,v 1.29 2008/12/10 19:26:24 drh Exp $
*/
/* All threads share a single random number generator.
@@ -17496,9 +17552,9 @@
static SQLITE_WSD struct sqlite3PrngType {
unsigned char isInit; /* True if initialized */
unsigned char i, j; /* State variables */
unsigned char s[256]; /* State variables */
-} sqlite3Prng = { 0, };
+} sqlite3Prng;
/*
** Get a single 8-bit random value from the RC4 PRNG. The Mutex
** must be held while executing this routine.
@@ -17514,9 +17570,9 @@
**
** (Later): Actually, OP_NewRowid does not depend on a good source of
** randomness any more. But we will leave this code in all the same.
*/
-static int randomByte(void){
+static u8 randomByte(void){
unsigned char t;
/* The "wsdPrng" macro will resolve to the pseudo-random number generator
@@ -17548,9 +17604,9 @@
wsdPrng.j = 0;
wsdPrng.i = 0;
sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
for(i=0; i<256; i++){
- wsdPrng.s[i] = i;
+ wsdPrng.s[i] = (u8)i;
}
for(i=0; i<256; i++){
wsdPrng.j += wsdPrng.s[i] + k[i];
t = wsdPrng.s[wsdPrng.j];
@@ -17595,9 +17651,9 @@
**
** The sqlite3_test_control() interface calls these routines to
** control the PRNG.
*/
-static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng = { 0, };
+static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
SQLITE_PRIVATE void sqlite3PrngSaveState(void){
memcpy(
&GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
&GLOBAL(struct sqlite3PrngType, sqlite3Prng),
@@ -17631,9 +17687,9 @@
*************************************************************************
** This file contains routines used to translate between UTF-8,
** UTF-16, UTF-16BE, and UTF-16LE.
**
-** $Id: utf.c,v 1.66 2008/11/07 03:29:34 drh Exp $
+** $Id: utf.c,v 1.70 2008/12/10 22:30:25 shane Exp $
**
** Notes on UTF-8:
**
** Byte-0 Byte-1 Byte-2 Byte-3 Value
@@ -17673,9 +17729,9 @@
** source code file "vdbe.c". When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
**
-** $Id: vdbeInt.h,v 1.158 2008/11/17 15:31:48 danielk1977 Exp $
+** $Id: vdbeInt.h,v 1.160 2008/12/09 02:51:24 drh Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_
@@ -17771,10 +17827,12 @@
** SQLITE_BLOB.
*/
struct Mem {
union {
- i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */
+ i64 i; /* Integer value. */
+ int nZero; /* Used when bit MEM_Zero is set in flags */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
+ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */
} u;
double r; /* Real value */
sqlite3 *db; /* The associated database connection */
char *z; /* String or BLOB value */
@@ -17805,28 +17863,33 @@
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
-
-#define MemSetTypeFlag(p, f) \
- ((p)->flags = ((p)->flags&~(MEM_Int|MEM_Real|MEM_Null|MEM_Blob|MEM_Str))|f)
+#define MEM_RowSet 0x0020 /* Value is a RowSet object */
+#define MEM_TypeMask 0x00ff /* Mask of type bits */
/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
** policy for Mem.z. The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
-#define MEM_Term 0x0020 /* String rep is nul terminated */
-#define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */
-#define MEM_Static 0x0080 /* Mem.z points to a static string */
-#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */
-#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */
-#define MEM_Zero 0x0800 /* Mem.i contains count of 0s appended to blob */
+#define MEM_Term 0x0200 /* String rep is nul terminated */
+#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
+#define MEM_Static 0x0800 /* Mem.z points to a static string */
+#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
+#define MEM_Agg 0x2000 /* Mem.z points to an agg function context */
+#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
#ifdef SQLITE_OMIT_INCRBLOB
#undef MEM_Zero
#define MEM_Zero 0x0000
#endif
+
+
+/*
+** Clear any existing type flags from a Mem and replace them with f
+*/
+#define MemSetTypeFlag(p, f) ((p)->flags = ((p)->flags&~(MEM_TypeMask))|f)
/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
** additional information about auxiliary information bound to arguments
@@ -17880,35 +17943,8 @@
HashElem *prev; /* Previously accessed hash elemen */
};
/*
-** A FifoPage structure holds a single page of valves. Pages are arranged
-** in a list.
-*/
-typedef struct FifoPage FifoPage;
-struct FifoPage {
- int nSlot; /* Number of entries aSlot[] */
- int iWrite; /* Push the next value into this entry in aSlot[] */
- int iRead; /* Read the next value from this entry in aSlot[] */
- FifoPage *pNext; /* Next page in the fifo */
- i64 aSlot[1]; /* One or more slots for rowid values */
-};
-
-/*
-** The Fifo structure is typedef-ed in vdbeInt.h. But the implementation
-** of that structure is private to this file.
-**
-** The Fifo structure describes the entire fifo.
-*/
-typedef struct Fifo Fifo;
-struct Fifo {
- int nEntry; /* Total number of entries */
- sqlite3 *db; /* The associated database connection */
- FifoPage *pFirst; /* First page on the list */
- FifoPage *pLast; /* Last page on the list */
-};
-
-/*
** A Context stores the last insert rowid, the last statement change count,
** and the current statement change count (i.e. changes since last statement).
** The current keylist is also stored in the context.
** Elements of Context structure type make up the ContextStack, which is
@@ -17919,9 +17955,8 @@
typedef struct Context Context;
struct Context {
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
int nChange; /* Statement changes (Vdbe.nChanges) */
- Fifo sFifo; /* Records that will participate in a DELETE or UPDATE */
};
/*
** An instance of the virtual machine. This structure contains the complete
@@ -17959,9 +17994,8 @@
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
int nCallback; /* Number of callbacks invoked so far */
int cacheCtr; /* VdbeCursor row cache generation counter */
- Fifo sFifo; /* A list of ROWIDs */
int contextStackTop; /* Index of top element in the context stack */
int contextStackDepth; /* The size of the "context" stack */
Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
int pc; /* The program counter */
@@ -18041,8 +18075,9 @@
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
+SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, int);
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(Mem*);
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
@@ -18069,12 +18104,8 @@
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
#endif
SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
-SQLITE_PRIVATE void sqlite3VdbeFifoInit(Fifo*, sqlite3*);
-SQLITE_PRIVATE int sqlite3VdbeFifoPush(Fifo*, i64);
-SQLITE_PRIVATE int sqlite3VdbeFifoPop(Fifo*, i64*);
-SQLITE_PRIVATE void sqlite3VdbeFifoClear(Fifo*);
#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *);
#else
@@ -18085,19 +18116,21 @@
/************** End of vdbeInt.h *********************************************/
/************** Continuing where we left off in utf.c ************************/
+#ifndef SQLITE_AMALGAMATION
/*
** The following constant value is used by the SQLITE_BIGENDIAN and
** SQLITE_LITTLEENDIAN macros.
*/
SQLITE_PRIVATE const int sqlite3one = 1;
+#endif /* SQLITE_AMALGAMATION */
/*
** This lookup table is used to help decode the first byte of
** a multi-byte UTF8 character.
*/
-static const unsigned char sqlite3UtfTrans1[] = {
+static const unsigned char sqlite3Utf8Trans1[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
@@ -18109,48 +18142,48 @@
#define WRITE_UTF8(zOut, c) { \
if( c<0x00080 ){ \
- *zOut++ = (c&0xFF); \
+ *zOut++ = (u8)(c&0xFF); \
} \
else if( c<0x00800 ){ \
- *zOut++ = 0xC0 + ((c>>6)&0x1F); \
- *zOut++ = 0x80 + (c & 0x3F); \
+ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
} \
else if( c<0x10000 ){ \
- *zOut++ = 0xE0 + ((c>>12)&0x0F); \
- *zOut++ = 0x80 + ((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (c & 0x3F); \
+ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
}else{ \
- *zOut++ = 0xF0 + ((c>>18) & 0x07); \
- *zOut++ = 0x80 + ((c>>12) & 0x3F); \
- *zOut++ = 0x80 + ((c>>6) & 0x3F); \
- *zOut++ = 0x80 + (c & 0x3F); \
+ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
+ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
+ *zOut++ = 0x80 + (u8)(c & 0x3F); \
} \
}
-#define WRITE_UTF16LE(zOut, c) { \
- if( c<=0xFFFF ){ \
- *zOut++ = (c&0x00FF); \
- *zOut++ = ((c>>8)&0x00FF); \
- }else{ \
- *zOut++ = (((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
- *zOut++ = (0x00D8 + (((c-0x10000)>>18)&0x03)); \
- *zOut++ = (c&0x00FF); \
- *zOut++ = (0x00DC + ((c>>8)&0x03)); \
- } \
-}
-
-#define WRITE_UTF16BE(zOut, c) { \
- if( c<=0xFFFF ){ \
- *zOut++ = ((c>>8)&0x00FF); \
- *zOut++ = (c&0x00FF); \
- }else{ \
- *zOut++ = (0x00D8 + (((c-0x10000)>>18)&0x03)); \
- *zOut++ = (((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
- *zOut++ = (0x00DC + ((c>>8)&0x03)); \
- *zOut++ = (c&0x00FF); \
- } \
+#define WRITE_UTF16LE(zOut, c) { \
+ if( c<=0xFFFF ){ \
+ *zOut++ = (u8)(c&0x00FF); \
+ *zOut++ = (u8)((c>>8)&0x00FF); \
+ }else{ \
+ *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
+ *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
+ *zOut++ = (u8)(c&0x00FF); \
+ *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
+ } \
+}
+
+#define WRITE_UTF16BE(zOut, c) { \
+ if( c<=0xFFFF ){ \
+ *zOut++ = (u8)((c>>8)&0x00FF); \
+ *zOut++ = (u8)(c&0x00FF); \
+ }else{ \
+ *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
+ *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
+ *zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
+ *zOut++ = (u8)(c&0x00FF); \
+ } \
}
#define READ_UTF16LE(zIn, c){ \
c = (*zIn++); \
@@ -18203,9 +18236,9 @@
*/
#define READ_UTF8(zIn, zTerm, c) \
c = *(zIn++); \
if( c>=0xc0 ){ \
- c = sqlite3UtfTrans1[c-0xc0]; \
+ c = sqlite3Utf8Trans1[c-0xc0]; \
while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
c = (c<<6) + (0x3f & *(zIn++)); \
} \
if( c<0x80 \
@@ -18332,9 +18365,9 @@
READ_UTF8(zIn, zTerm, c);
WRITE_UTF16BE(z, c);
}
}
- pMem->n = z - zOut;
+ pMem->n = (int)(z - zOut);
*z++ = 0;
}else{
assert( desiredEnc==SQLITE_UTF8 );
if( pMem->enc==SQLITE_UTF16LE ){
@@ -18349,9 +18382,9 @@
READ_UTF16BE(zIn, c);
WRITE_UTF8(z, c);
}
}
- pMem->n = z - zOut;
+ pMem->n = (int)(z - zOut);
}
*z = 0;
assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
@@ -18451,9 +18484,9 @@
*/
SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
unsigned char *zOut = zIn;
unsigned char *zStart = zIn;
- unsigned char *zTerm = &zIn[strlen((char *)zIn)];
+ unsigned char *zTerm = &zIn[sqlite3Strlen30((char *)zIn)];
u32 c;
while( zIn[0] ){
c = sqlite3Utf8Read(zIn, zTerm, (const u8**)&zIn);
@@ -18519,9 +18552,9 @@
READ_UTF16LE(z, c);
n++;
}
}
- return (z-(char const *)zIn)-((c==0)?2:0);
+ return (int)(z-(char const *)zIn)-((c==0)?2:0);
}
#if defined(SQLITE_TEST)
/*
@@ -18539,9 +18572,10 @@
for(i=0; i<0x00110000; i++){
z = zBuf;
WRITE_UTF8(z, i);
- n = z-zBuf;
+ n = (int)(z-zBuf);
+ assert( n>0 && n<=4 );
z[0] = 0;
zTerm = z;
z = zBuf;
c = sqlite3Utf8Read(z, zTerm, (const u8**)&z);
@@ -18554,9 +18588,10 @@
for(i=0; i<0x00110000; i++){
if( i>=0xD800 && i<0xE000 ) continue;
z = zBuf;
WRITE_UTF16LE(z, i);
- n = z-zBuf;
+ n = (int)(z-zBuf);
+ assert( n>0 && n<=4 );
z[0] = 0;
z = zBuf;
READ_UTF16LE(z, c);
assert( c==i );
@@ -18565,9 +18600,10 @@
for(i=0; i<0x00110000; i++){
if( i>=0xD800 && i<0xE000 ) continue;
z = zBuf;
WRITE_UTF16BE(z, i);
- n = z-zBuf;
+ n = (int)(z-zBuf);
+ assert( n>0 && n<=4 );
z[0] = 0;
z = zBuf;
READ_UTF16BE(z, c);
assert( c==i );
@@ -18594,9 +18630,9 @@
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.242 2008/11/17 19:18:55 danielk1977 Exp $
+** $Id: util.c,v 1.245 2008/12/10 22:15:00 drh Exp $
*/
/*
@@ -18628,8 +18664,18 @@
return y!=z;
}
/*
+** Compute a string length that is limited to what can be stored in
+** lower 30 bits of a 32-bit signed integer.
+*/
+SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
+ const char *z2 = z;
+ while( *z2 ){ z2++; }
+ return 0x3fffffff & (int)(z2 - z);
+}
+
+/*
** Return the length of a string, except do not allow the string length
** to exceed the SQLITE_LIMIT_LENGTH setting.
*/
SQLITE_PRIVATE int sqlite3Strlen(sqlite3 *db, const char *z){
@@ -18636,9 +18682,9 @@
const char *z2 = z;
int len;
int x;
while( *z2 ){ z2++; }
- x = z2 - z;
+ x = (int)(z2 - z);
len = 0x7fffffff & x;
if( len!=x || len > db->aLimit[SQLITE_LIMIT_LENGTH] ){
return db->aLimit[SQLITE_LIMIT_LENGTH];
}else{
@@ -18732,9 +18778,9 @@
** brackets from around identifers. For example: "[a-b-c]" becomes
** "a-b-c".
*/
SQLITE_PRIVATE void sqlite3Dequote(char *z){
- int quote;
+ char quote;
int i, j;
if( z==0 ) return;
quote = z[0];
switch( quote ){
@@ -18891,10 +18937,10 @@
}else{
v1 *= scale;
}
}
- *pResult = sign<0 ? -v1 : v1;
- return z - zBegin;
+ *pResult = (double)(sign<0 ? -v1 : v1);
+ return (int)(z - zBegin);
#else
return sqlite3Atoi64(z, pResult);
#endif /* SQLITE_OMIT_FLOATING_POINT */
}
@@ -19078,19 +19124,19 @@
SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
int i, j, n;
u8 buf[10];
if( v & (((u64)0xff000000)<<32) ){
- p[8] = v;
+ p[8] = (u8)v;
v >>= 8;
for(i=7; i>=0; i--){
- p[i] = (v & 0x7f) | 0x80;
+ p[i] = (u8)((v & 0x7f) | 0x80);
v >>= 7;
}
return 9;
}
n = 0;
do{
- buf[n++] = (v & 0x7f) | 0x80;
+ buf[n++] = (u8)((v & 0x7f) | 0x80);
v >>= 7;
}while( v!=0 );
buf[0] &= 0x7f;
assert( n<=9 );
@@ -19115,10 +19161,10 @@
return 1;
}
#endif
if( (v & ~0x3fff)==0 ){
- p[0] = (v>>7) | 0x80;
- p[1] = v & 0x7f;
+ p[0] = (u8)((v>>7) | 0x80);
+ p[1] = (u8)(v & 0x7f);
return 2;
}
return sqlite3PutVarint(p, v);
}
@@ -19126,9 +19172,9 @@
/*
** Read a 64-bit variable-length integer from memory starting at p[0].
** Return the number of bytes read. The value is stored in *v.
*/
-SQLITE_PRIVATE int sqlite3GetVarint(const unsigned char *p, u64 *v){
+SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
u32 a,b,s;
a = *p;
/* a: p0 (unmasked) */
@@ -19288,9 +19334,9 @@
** A MACRO version, getVarint32, is provided which inlines the
** single-byte case. All code should use the MACRO version as
** this function assumes the single-byte case has already been handled.
*/
-SQLITE_PRIVATE int sqlite3GetVarint32(const unsigned char *p, u32 *v){
+SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
u32 a,b;
a = *p;
/* a: p0 (unmasked) */
@@ -19357,9 +19403,9 @@
** slow) general-purpose sqlite3GetVarint() routine to extract the
** value. */
{
u64 v64;
- int n;
+ u8 n;
p -= 4;
n = sqlite3GetVarint(p, &v64);
assert( n>5 && n<=9 );
@@ -19388,12 +19434,12 @@
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
- p[0] = v>>24;
- p[1] = v>>16;
- p[2] = v>>8;
- p[3] = v;
+ p[0] = (u8)(v>>24);
+ p[1] = (u8)(v>>16);
+ p[2] = (u8)(v>>8);
+ p[3] = (u8)v;
}
@@ -19402,17 +19448,17 @@
** Translate a single byte of Hex into an integer.
** This routinen only works if h really is a valid hexadecimal
** character: 0..9a..fA..F
*/
-static int hexToInt(int h){
+static u8 hexToInt(int h){
assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
#ifdef SQLITE_ASCII
h += 9*(1&(h>>6));
#endif
#ifdef SQLITE_EBCDIC
h += 9*(1&~(h>>4));
#endif
- return h & 0xf;
+ return (u8)(h & 0xf);
}
#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
@@ -19544,9 +19590,9 @@
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
**
-** $Id: hash.c,v 1.31 2008/10/10 17:41:29 drh Exp $
+** $Id: hash.c,v 1.32 2008/12/10 19:26:24 drh Exp $
*/
/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
@@ -19593,9 +19639,9 @@
*/
static int strHash(const void *pKey, int nKey){
const char *z = (const char *)pKey;
int h = 0;
- if( nKey<=0 ) nKey = strlen(z);
+ if( nKey<=0 ) nKey = sqlite3Strlen30(z);
while( nKey > 0 ){
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
nKey--;
}
@@ -19843,10 +19889,10 @@
/* 1 */ "VNext",
/* 2 */ "Affinity",
/* 3 */ "Column",
/* 4 */ "SetCookie",
- /* 5 */ "Sequence",
- /* 6 */ "MoveGt",
+ /* 5 */ "Seek",
+ /* 6 */ "Sequence",
/* 7 */ "RowKey",
/* 8 */ "SCopy",
/* 9 */ "OpenWrite",
/* 10 */ "If",
@@ -19888,23 +19934,23 @@
/* 46 */ "NotExists",
/* 47 */ "Gosub",
/* 48 */ "Integer",
/* 49 */ "Prev",
- /* 50 */ "VColumn",
- /* 51 */ "CreateTable",
- /* 52 */ "Last",
- /* 53 */ "IncrVacuum",
- /* 54 */ "IdxRowid",
- /* 55 */ "ResetCount",
- /* 56 */ "FifoWrite",
- /* 57 */ "ContextPush",
- /* 58 */ "Yield",
- /* 59 */ "DropTrigger",
+ /* 50 */ "RowSetRead",
+ /* 51 */ "RowSetAdd",
+ /* 52 */ "VColumn",
+ /* 53 */ "CreateTable",
+ /* 54 */ "Last",
+ /* 55 */ "SeekLe",
+ /* 56 */ "IncrVacuum",
+ /* 57 */ "IdxRowid",
+ /* 58 */ "ResetCount",
+ /* 59 */ "ContextPush",
/* 60 */ "Or",
/* 61 */ "And",
- /* 62 */ "DropIndex",
- /* 63 */ "IdxGE",
- /* 64 */ "IdxDelete",
+ /* 62 */ "Yield",
+ /* 63 */ "DropTrigger",
+ /* 64 */ "DropIndex",
/* 65 */ "IsNull",
/* 66 */ "NotNull",
/* 67 */ "Ne",
/* 68 */ "Eq",
@@ -19911,9 +19957,9 @@
/* 69 */ "Gt",
/* 70 */ "Le",
/* 71 */ "Lt",
/* 72 */ "Ge",
- /* 73 */ "Vacuum",
+ /* 73 */ "IdxGE",
/* 74 */ "BitAnd",
/* 75 */ "BitOr",
/* 76 */ "ShiftLeft",
/* 77 */ "ShiftRight",
@@ -19922,23 +19968,23 @@
/* 80 */ "Multiply",
/* 81 */ "Divide",
/* 82 */ "Remainder",
/* 83 */ "Concat",
- /* 84 */ "MoveLe",
- /* 85 */ "IfNot",
- /* 86 */ "DropTable",
+ /* 84 */ "IdxDelete",
+ /* 85 */ "Vacuum",
+ /* 86 */ "IfNot",
/* 87 */ "BitNot",
/* 88 */ "String8",
- /* 89 */ "MakeRecord",
- /* 90 */ "ResultRow",
- /* 91 */ "Delete",
- /* 92 */ "AggFinal",
- /* 93 */ "Compare",
- /* 94 */ "Goto",
- /* 95 */ "TableLock",
- /* 96 */ "FifoRead",
- /* 97 */ "Clear",
- /* 98 */ "MoveLt",
+ /* 89 */ "DropTable",
+ /* 90 */ "SeekLt",
+ /* 91 */ "MakeRecord",
+ /* 92 */ "ResultRow",
+ /* 93 */ "Delete",
+ /* 94 */ "AggFinal",
+ /* 95 */ "Compare",
+ /* 96 */ "Goto",
+ /* 97 */ "TableLock",
+ /* 98 */ "Clear",
/* 99 */ "VerifyCookie",
/* 100 */ "AggStep",
/* 101 */ "SetNumColumns",
/* 102 */ "Transaction",
@@ -19946,12 +19992,12 @@
/* 104 */ "VDestroy",
/* 105 */ "ContextPop",
/* 106 */ "Next",
/* 107 */ "IdxInsert",
- /* 108 */ "Insert",
- /* 109 */ "Destroy",
- /* 110 */ "ReadCookie",
- /* 111 */ "ForceInt",
+ /* 108 */ "SeekGe",
+ /* 109 */ "Insert",
+ /* 110 */ "Destroy",
+ /* 111 */ "ReadCookie",
/* 112 */ "LoadAnalysis",
/* 113 */ "Explain",
/* 114 */ "OpenPseudo",
/* 115 */ "OpenEphemeral",
@@ -19958,9 +20004,9 @@
/* 116 */ "Null",
/* 117 */ "Move",
/* 118 */ "Blob",
/* 119 */ "Rewind",
- /* 120 */ "MoveGe",
+ /* 120 */ "SeekGt",
/* 121 */ "VBegin",
/* 122 */ "VUpdate",
/* 123 */ "IfZero",
/* 124 */ "VCreate",
@@ -20003,9 +20049,9 @@
******************************************************************************
**
** This file contains code that is specific to OS/2.
**
-** $Id: os_os2.c,v 1.59 2008/11/18 23:03:40 pweilbacher Exp $
+** $Id: os_os2.c,v 1.63 2008/12/10 19:26:24 drh Exp $
*/
#if SQLITE_OS_OS2
@@ -20422,8 +20468,9 @@
/* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
** no-op
*/
#ifdef SQLITE_NO_SYNC
+ UNUSED_PARAMETER(pFile);
return SQLITE_OK;
#else
return DosResetBuffer( pFile->h ) == NO_ERROR ? SQLITE_OK : SQLITE_IOERR;
#endif
@@ -20915,9 +20962,9 @@
}
/* Strip off a trailing slashes or backslashes, otherwise we would get *
* multiple (back)slashes which causes DosOpen() to fail. *
* Trailing spaces are not allowed, either. */
- j = strlen(zTempPath);
+ j = sqlite3Strlen30(zTempPath);
while( j > 0 && ( zTempPath[j-1] == '\\' || zTempPath[j-1] == '/'
|| zTempPath[j-1] == ' ' ) ){
j--;
}
@@ -20930,9 +20977,9 @@
}else{
sqlite3_snprintf( nBuf-30, zBuf,
"%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath );
}
- j = strlen( zBuf );
+ j = sqlite3Strlen30( zBuf );
sqlite3_randomness( 20, &zBuf[j] );
for( i = 0; i < 20; i++, j++ ){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
@@ -21188,11 +21235,15 @@
/*
** Write up to nBuf bytes of randomness into zBuf.
*/
static int os2Randomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf ){
- ULONG sizeofULong = sizeof(ULONG);
int n = 0;
- if( sizeof(DATETIME) <= nBuf - n ){
+#if defined(SQLITE_TEST)
+ n = nBuf;
+ memset(zBuf, 0, nBuf);
+#else
+ int sizeofULong = sizeof(ULONG);
+ if( (int)sizeof(DATETIME) <= nBuf - n ){
DATETIME x;
DosGetDateTime(&x);
memcpy(&zBuf[n], &x, sizeof(x));
n += sizeof(x);
@@ -21237,8 +21288,9 @@
memcpy(&zBuf[n], &ulSysInfo[QSV_TOTAVAILMEM - 1], sizeofULong);
n += sizeofULong;
}
}
+#endif
return n;
}
@@ -21356,27 +21408,61 @@
** May you share freely, never taking more than you give.
**
******************************************************************************
**
-** This file contains code that is specific to Unix systems.
-**
-** $Id: os_unix.c,v 1.216 2008/11/19 16:52:44 danielk1977 Exp $
+** This file contains the VFS implementation for unix-like operating systems
+** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
+**
+** There are actually several different VFS implementations in this file.
+** The differences are in the way that file locking is done. The default
+** implementation uses Posix Advisory Locks. Alternative implementations
+** use flock(), dot-files, various proprietary locking schemas, or simply
+** skip locking all together.
+**
+** This source file is organized into divisions where the logic for various
+** subfunctions is contained within the appropriate division. PLEASE
+** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed
+** in the correct division and should be clearly labeled.
+**
+** The layout of divisions is as follows:
+**
+** * General-purpose declarations and utility functions.
+** * Unique file ID logic used by VxWorks.
+** * Various locking primitive implementations (all except proxy locking):
+** + for Posix Advisory Locks
+** + for no-op locks
+** + for dot-file locks
+** + for flock() locking
+** + for named semaphore locks (VxWorks only)
+** + for AFP filesystem locks (MacOSX only)
+** * sqlite3_file methods not associated with locking.
+** * Definitions of sqlite3_io_methods objects for all locking
+** methods plus "finder" functions for each locking method.
+** * sqlite3_vfs method implementations.
+** * Locking primitives for the proxy uber-locking-method. (MacOSX only)
+** * Definitions of sqlite3_vfs objects for all locking methods
+** plus implementations of sqlite3_os_init() and sqlite3_os_end().
+**
+** $Id: os_unix.c,v 1.232 2008/12/11 02:56:07 drh Exp $
*/
#if SQLITE_OS_UNIX /* This file is used on unix only */
/*
-** If SQLITE_ENABLE_LOCKING_STYLE is defined and is non-zero, then several
-** alternative locking implementations are provided:
-**
-** * POSIX locking (the default),
-** * No locking,
-** * Dot-file locking,
-** * flock() locking,
-** * AFP locking (OSX only),
-** * Named POSIX semaphores (VXWorks only).
-**
-** SQLITE_ENABLE_LOCKING_STYLE only works on a Mac. It is turned on by
-** default on a Mac and disabled on all other posix platforms.
+** There are various methods for file locking used for concurrency
+** control:
+**
+** 1. POSIX locking (the default),
+** 2. No locking,
+** 3. Dot-file locking,
+** 4. flock() locking,
+** 5. AFP locking (OSX only),
+** 6. Named POSIX semaphores (VXWorks only),
+** 7. proxy locking. (OSX only)
+**
+** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
+** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
+** selection of the appropriate locking style based on the filesystem
+** where the database is located.
*/
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
# if defined(__DARWIN__)
# define SQLITE_ENABLE_LOCKING_STYLE 1
@@ -21385,15 +21471,17 @@
# endif
#endif
/*
-** Define the IS_VXWORKS pre-processor macro to 1 if building on
+** Define the OS_VXWORKS pre-processor macro to 1 if building on
** vxworks, or 0 otherwise.
*/
-#if defined(__RTP__) || defined(_WRS_KERNEL)
-# define IS_VXWORKS 1
-#else
-# define IS_VXWORKS 0
+#ifndef OS_VXWORKS
+# if defined(__RTP__) || defined(_WRS_KERNEL)
+# define OS_VXWORKS 1
+# else
+# define OS_VXWORKS 0
+# endif
#endif
/*
** These #defines should enable >2GB file support on Posix if the
@@ -21406,8 +21494,13 @@
** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
** without this option, LFS is enable. But LFS does not exist in the kernel
** in RedHat 6.0, so the code won't work. Hence, for maximum binary
** portability you should omit LFS.
+**
+** The previous paragraph was written in 2005. (This paragraph is written
+** on 2008-11-28.) These days, all Linux kernels support large files, so
+** you should probably leave LFS enabled. But some embedded platforms might
+** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
*/
#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE 1
# ifndef _FILE_OFFSET_BITS
@@ -21427,13 +21520,13 @@
#include <errno.h>
#if SQLITE_ENABLE_LOCKING_STYLE
# include <sys/ioctl.h>
-# if IS_VXWORKS
-# define lstat stat
+# if OS_VXWORKS
# include <semaphore.h>
# include <limits.h>
# else
+# include <sys/file.h>
# include <sys/param.h>
# include <sys/mount.h>
# endif
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
@@ -21453,41 +21546,53 @@
# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
#endif
/*
+ ** Default permissions when creating auto proxy dir
+ */
+#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
+#endif
+
+/*
** Maximum supported path-length.
*/
#define MAX_PATHNAME 512
-
-/*
-** The unixFile structure is subclass of sqlite3_file specific for the unix
-** protability layer.
+/*
+** 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))
+
+
+/*
+** The unixFile structure is subclass of sqlite3_file specific to the unix
+** VFS implementations.
*/
typedef struct unixFile unixFile;
struct unixFile {
sqlite3_io_methods const *pMethod; /* Always the first entry */
+ struct unixOpenCnt *pOpen; /* Info about all open fd's on this inode */
+ struct unixLockInfo *pLock; /* Info about locks on this inode */
+ int h; /* The file descriptor */
+ int dirfd; /* File descriptor for the directory */
+ unsigned char locktype; /* The type of lock held on this fd */
+ int lastErrno; /* The unix errno from the last I/O error */
+ void *lockingContext; /* Locking style specific state */
+ int openFlags; /* The flags specified at open */
+#if SQLITE_THREADSAFE && defined(__linux__)
+ pthread_t tid; /* The thread that "owns" this unixFile */
+#endif
+#if OS_VXWORKS
+ int isDelete; /* Delete on close if true */
+ struct vxworksFileId *pId; /* Unique file ID */
+#endif
#ifdef SQLITE_TEST
/* In test mode, increase the size of this structure a bit so that
** it is larger than the struct CrashFile defined in test6.c.
*/
char aPadding[32];
-#endif
- struct openCnt *pOpen; /* Info about all open fd's on this inode */
- struct lockInfo *pLock; /* Info about locks on this inode */
-#if SQLITE_ENABLE_LOCKING_STYLE
- void *lockingContext; /* Locking style specific state */
-#endif
- int h; /* The file descriptor */
- unsigned char locktype; /* The type of lock held on this fd */
- int dirfd; /* File descriptor for the directory */
-#if SQLITE_THREADSAFE
- pthread_t tid; /* The thread that "owns" this unixFile */
-#endif
- int lastErrno; /* The unix errno from the last I/O error */
-#if IS_VXWORKS
- int isDelete; /* Delete on close if true */
- char *zRealpath;
#endif
};
/*
@@ -21763,301 +21868,37 @@
#else
#define threadid 0
#endif
-/*
-** Set or check the unixFile.tid field. This field is set when an unixFile
-** is first opened. All subsequent uses of the unixFile verify that the
-** same thread is operating on the unixFile. Some operating systems do
-** not allow locks to be overridden by other threads and that restriction
-** means that sqlite3* database handles cannot be moved from one thread
-** to another. This logic makes sure a user does not try to do that
-** by mistake.
-**
-** Version 3.3.1 (2006-01-15): unixFile can be moved from one thread to
-** another as long as we are running on a system that supports threads
-** overriding each others locks (which now the most common behavior)
-** or if no locks are held. But the unixFile.pLock field needs to be
-** recomputed because its key includes the thread-id. See the
-** transferOwnership() function below for additional information
-*/
-#if SQLITE_THREADSAFE
-# define SET_THREADID(X) (X)->tid = pthread_self()
-# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \
- !pthread_equal((X)->tid, pthread_self()))
-#else
-# define SET_THREADID(X)
-# define CHECK_THREADID(X) 0
-#endif
-
-/*
-** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996)
-** section 6.5.2.2 lines 483 through 490 specify that when a process
-** sets or clears a lock, that operation overrides any prior locks set
-** by the same process. It does not explicitly say so, but this implies
-** that it overrides locks set by the same process using a different
-** file descriptor. Consider this test case:
-** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
-**
-** Suppose ./file1 and ./file2 are really the same file (because
-** one is a hard or symbolic link to the other) then if you set
-** an exclusive lock on fd1, then try to get an exclusive lock
-** on fd2, it works. I would have expected the second lock to
-** fail since there was already a lock on the file due to fd1.
-** But not so. Since both locks came from the same process, the
-** second overrides the first, even though they were on different
-** file descriptors opened on different file names.
-**
-** Bummer. If you ask me, this is broken. Badly broken. It means
-** that we cannot use POSIX locks to synchronize file access among
-** competing threads of the same process. POSIX locks will work fine
-** to synchronize access for threads in separate processes, but not
-** threads within the same process.
-**
-** To work around the problem, SQLite has to manage file locks internally
-** on its own. Whenever a new database is opened, we have to find the
-** specific inode of the database file (the inode is determined by the
-** st_dev and st_ino fields of the stat structure that fstat() fills in)
-** and check for locks already existing on that inode. When locks are
-** created or removed, we have to look at our own internal record of the
-** locks to see if another thread has previously set a lock on that same
-** inode.
-**
-** The sqlite3_file structure for POSIX is no longer just an integer file
-** descriptor. It is now a structure that holds the integer file
-** descriptor and a pointer to a structure that describes the internal
-** locks on the corresponding inode. There is one locking structure
-** per inode, so if the same inode is opened twice, both unixFile structures
-** point to the same locking structure. The locking structure keeps
-** a reference count (so we will know when to delete it) and a "cnt"
-** field that tells us its internal lock status. cnt==0 means the
-** file is unlocked. cnt==-1 means the file has an exclusive lock.
-** cnt>0 means there are cnt shared locks on the file.
-**
-** Any attempt to lock or unlock a file first checks the locking
-** structure. The fcntl() system call is only invoked to set a
-** POSIX lock if the internal lock structure transitions between
-** a locked and an unlocked state.
-**
-** 2004-Jan-11:
-** More recent discoveries about POSIX advisory locks. (The more
-** I discover, the more I realize the a POSIX advisory locks are
-** an abomination.)
-**
-** If you close a file descriptor that points to a file that has locks,
-** all locks on that file that are owned by the current process are
-** released. To work around this problem, each unixFile structure contains
-** a pointer to an openCnt structure. There is one openCnt structure
-** per open inode, which means that multiple unixFile can point to a single
-** openCnt. When an attempt is made to close an unixFile, if there are
-** other unixFile open on the same inode that are holding locks, the call
-** to close() the file descriptor is deferred until all of the locks clear.
-** The openCnt structure keeps a list of file descriptors that need to
-** be closed and that list is walked (and cleared) when the last lock
-** clears.
-**
-** First, under Linux threads, because each thread has a separate
-** process ID, lock operations in one thread do not override locks
-** to the same file in other threads. Linux threads behave like
-** separate processes in this respect. But, if you close a file
-** descriptor in linux threads, all locks are cleared, even locks
-** on other threads and even though the other threads have different
-** process IDs. Linux threads is inconsistent in this respect.
-** (I'm beginning to think that linux threads is an abomination too.)
-** The consequence of this all is that the hash table for the lockInfo
-** structure has to include the process id as part of its key because
-** locks in different threads are treated as distinct. But the
-** openCnt structure should not include the process id in its
-** key because close() clears lock on all threads, not just the current
-** thread. Were it not for this goofiness in linux threads, we could
-** combine the lockInfo and openCnt structures into a single structure.
-**
-** 2004-Jun-28:
-** On some versions of linux, threads can override each others locks.
-** On others not. Sometimes you can change the behavior on the same
-** system by setting the LD_ASSUME_KERNEL environment variable. The
-** POSIX standard is silent as to which behavior is correct, as far
-** as I can tell, so other versions of unix might show the same
-** inconsistency. There is no little doubt in my mind that posix
-** advisory locks and linux threads are profoundly broken.
-**
-** To work around the inconsistencies, we have to test at runtime
-** whether or not threads can override each others locks. This test
-** is run once, the first time any lock is attempted. A static
-** variable is set to record the results of this test for future
-** use.
-*/
-
-/*
-** An instance of the following structure serves as the key used
-** to locate a particular lockInfo structure given its inode.
-**
-** If threads cannot override each others locks, then we set the
-** lockKey.tid field to the thread ID. If threads can override
-** each others locks then tid is always set to zero. tid is omitted
-** if we compile without threading support.
-*/
-struct lockKey {
- dev_t dev; /* Device number */
-#if IS_VXWORKS
- void *rnam; /* Realname since inode unusable */
-#else
- ino_t ino; /* Inode number */
-#endif
-#if SQLITE_THREADSAFE
- pthread_t tid; /* Thread ID or zero if threads can override each other */
-#endif
-};
-
-/*
-** An instance of the following structure is allocated for each open
-** inode on each thread with a different process ID. (Threads have
-** different process IDs on linux, but not on most other unixes.)
-**
-** A single inode can have multiple file descriptors, so each unixFile
-** structure contains a pointer to an instance of this object and this
-** object keeps a count of the number of unixFile pointing to it.
-*/
-struct lockInfo {
- struct lockKey key; /* The lookup key */
- int cnt; /* Number of SHARED locks held */
- int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
- int nRef; /* Number of pointers to this structure */
- struct lockInfo *pNext, *pPrev; /* List of all lockInfo objects */
-};
-
-/*
-** An instance of the following structure serves as the key used
-** to locate a particular openCnt structure given its inode. This
-** is the same as the lockKey except that the thread ID is omitted.
-*/
-struct openKey {
- dev_t dev; /* Device number */
-#if IS_VXWORKS
- void *rnam; /* Realname since inode unusable */
-#else
- ino_t ino; /* Inode number */
-#endif
-};
-
-/*
-** An instance of the following structure is allocated for each open
-** inode. This structure keeps track of the number of locks on that
-** inode. If a close is attempted against an inode that is holding
-** locks, the close is deferred until all locks clear by adding the
-** file descriptor to be closed to the pending list.
-*/
-struct openCnt {
- struct openKey key; /* The lookup key */
- int nRef; /* Number of pointers to this structure */
- int nLock; /* Number of outstanding locks */
- int nPending; /* Number of pending close() operations */
- int *aPending; /* Malloced space holding fd's awaiting a close() */
-#if IS_VXWORKS
- sem_t *pSem; /* Named POSIX semaphore */
- char aSemName[MAX_PATHNAME+1]; /* Name of that semaphore */
-#endif
- struct openCnt *pNext, *pPrev; /* List of all openCnt objects */
-};
-
-/*
-** List of all lockInfo and openCnt objects. This used to be a hash
-** table. But the number of objects is rarely more than a dozen and
-** never exceeds a few thousand. And lookup is not on a critical
-** path oo a simple linked list will suffice.
-*/
-static struct lockInfo *lockList = 0;
-static struct openCnt *openList = 0;
-
-#if IS_VXWORKS
-/*
-** This hash table is used to bind the canonical file name to a
-** unixFile structure and use the hash key (= canonical name)
-** instead of the Inode number of the file to find the matching
-** lockInfo and openCnt structures. It also helps to make the
-** name of the semaphore when LOCKING_STYLE_NAMEDSEM is used
-** for the file.
-*/
-static Hash nameHash;
-#endif
-
-/*
-** The locking styles are associated with the different file locking
-** capabilities supported by different file systems.
-**
-** POSIX locking style fully supports shared and exclusive byte-range locks
-** AFP locking only supports exclusive byte-range locks
-** FLOCK only supports a single file-global exclusive lock
-** DOTLOCK isn't a true locking style, it refers to the use of a special
-** file named the same as the database file with a '.lock' extension, this
-** can be used on file systems that do not offer any reliable file locking
-** NO locking means that no locking will be attempted, this is only used for
-** read-only file systems currently
-** NAMEDSEM is similar to DOTLOCK but uses a named semaphore instead of an
-** indicator file.
-** UNSUPPORTED means that no locking will be attempted, this is only used for
-** file systems that are known to be unsupported
-*/
-#define LOCKING_STYLE_POSIX 1
-#define LOCKING_STYLE_NONE 2
-#define LOCKING_STYLE_DOTFILE 3
-#define LOCKING_STYLE_FLOCK 4
-#define LOCKING_STYLE_AFP 5
-#define LOCKING_STYLE_NAMEDSEM 6
-
-/*
-** Only set the lastErrno if the error code is a real error and not
-** a normal expected return code of SQLITE_BUSY or SQLITE_OK
-*/
-#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
/*
** Helper functions to obtain and relinquish the global mutex.
*/
-static void enterMutex(void){
+static void unixEnterMutex(void){
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
-static void leaveMutex(void){
+static void unixLeaveMutex(void){
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
-#if SQLITE_THREADSAFE
-/*
-** This variable records whether or not threads can override each others
-** locks.
-**
-** 0: No. Threads cannot override each others locks.
-** 1: Yes. Threads can override each others locks.
-** -1: We don't know yet.
-**
-** On some systems, we know at compile-time if threads can override each
-** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro
-** will be set appropriately. On other systems, we have to check at
-** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is
-** undefined.
-**
-** This variable normally has file scope only. But during testing, we make
-** it a global so that the test code can change its value in order to verify
-** that the right stuff happens in either case.
-*/
-#ifndef SQLITE_THREAD_OVERRIDE_LOCK
-# define SQLITE_THREAD_OVERRIDE_LOCK -1
-#endif
-#ifdef SQLITE_TEST
-int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
-#else
-static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
-#endif
-
-/*
-** This structure holds information passed into individual test
-** threads by the testThreadLockingBehavior() routine.
-*/
-struct threadTestData {
- int fd; /* File to be locked */
- struct flock lock; /* The locking operation */
- int result; /* Result of the locking operation */
-};
+
+#ifdef SQLITE_DEBUG
+/*
+** Helper function for printing out trace information from debugging
+** binaries. This returns the string represetation of the supplied
+** integer lock-type.
+*/
+static const char *locktypeName(int locktype){
+ switch( locktype ){
+ case NO_LOCK: return "NONE";
+ case SHARED_LOCK: return "SHARED";
+ case RESERVED_LOCK: return "RESERVED";
+ case PENDING_LOCK: return "PENDING";
+ case EXCLUSIVE_LOCK: return "EXCLUSIVE";
+ }
+ return "ERROR";
+}
+#endif
#ifdef SQLITE_LOCK_TRACE
/*
** Print out information about all locking operations.
@@ -22116,9 +21957,455 @@
}
#define fcntl lockTrace
#endif /* SQLITE_LOCK_TRACE */
-#ifdef __linux__
+
+
+/*
+** This routine translates a standard POSIX errno code into something
+** useful to the clients of the sqlite3 functions. Specifically, it is
+** intended to translate a variety of "try again" errors into SQLITE_BUSY
+** and a variety of "please close the file descriptor NOW" errors into
+** SQLITE_IOERR
+**
+** Errors during initialization of locks, or file system support for locks,
+** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
+*/
+static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
+ switch (posixError) {
+ case 0:
+ return SQLITE_OK;
+
+ case EAGAIN:
+ case ETIMEDOUT:
+ case EBUSY:
+ case EINTR:
+ case ENOLCK:
+ /* random NFS retry error, unless during file system support
+ * introspection, in which it actually means what it says */
+ return SQLITE_BUSY;
+
+ case EACCES:
+ /* EACCES is like EAGAIN during locking operations, but not any other time*/
+ if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
+ (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
+ return SQLITE_BUSY;
+ }
+ /* else fall through */
+ case EPERM:
+ return SQLITE_PERM;
+
+ case EDEADLK:
+ return SQLITE_IOERR_BLOCKED;
+
+#if EOPNOTSUPP!=ENOTSUP
+ case EOPNOTSUPP:
+ /* something went terribly awry, unless during file system support
+ * introspection, in which it actually means what it says */
+#endif
+#ifdef ENOTSUP
+ case ENOTSUP:
+ /* invalid fd, unless during file system support introspection, in which
+ * it actually means what it says */
+#endif
+ case EIO:
+ case EBADF:
+ case EINVAL:
+ case ENOTCONN:
+ case ENODEV:
+ case ENXIO:
+ case ENOENT:
+ case ESTALE:
+ case ENOSYS:
+ /* these should force the client to close the file and reconnect */
+
+ default:
+ return sqliteIOErr;
+ }
+}
+
+
+
+/******************************************************************************
+****************** Begin Unique File ID Utility Used By VxWorks ***************
+**
+** On most versions of unix, we can get a unique ID for a file by concatenating
+** the device number and the inode number. But this does not work on VxWorks.
+** On VxWorks, a unique file id must be based on the canonical filename.
+**
+** A pointer to an instance of the following structure can be used as a
+** unique file ID in VxWorks. Each instance of this structure contains
+** a copy of the canonical filename. There is also a reference count.
+** The structure is reclaimed when the number of pointers to it drops to
+** zero.
+**
+** There are never very many files open at one time and lookups are not
+** a performance-critical path, so it is sufficient to put these
+** structures on a linked list.
+*/
+struct vxworksFileId {
+ struct vxworksFileId *pNext; /* Next in a list of them all */
+ int nRef; /* Number of references to this one */
+ int nName; /* Length of the zCanonicalName[] string */
+ char *zCanonicalName; /* Canonical filename */
+};
+
+#if OS_VXWORKS
+/*
+** All unique filenames are held on a linked list headed by this
+** variable:
+*/
+static struct vxworksFileId *vxworksFileList = 0;
+
+/*
+** Simplify a filename into its canonical form
+** by making the following changes:
+**
+** * removing any trailing and duplicate /
+** * convert /./ into just /
+** * convert /A/../ where A is any simple name into just /
+**
+** Changes are made in-place. Return the new name length.
+**
+** The original filename is in z[0..n-1]. Return the number of
+** characters in the simplified name.
+*/
+static int vxworksSimplifyName(char *z, int n){
+ int i, j;
+ while( n>1 && z[n-1]=='/' ){ n--; }
+ for(i=j=0; i<n; i++){
+ if( z[i]=='/' ){
+ if( z[i+1]=='/' ) continue;
+ if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
+ i += 1;
+ continue;
+ }
+ if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
+ while( j>0 && z[j-1]!='/' ){ j--; }
+ if( j>0 ){ j--; }
+ i += 2;
+ continue;
+ }
+ }
+ z[j++] = z[i];
+ }
+ z[j] = 0;
+ return j;
+}
+
+/*
+** Find a unique file ID for the given absolute pathname. Return
+** a pointer to the vxworksFileId object. This pointer is the unique
+** file ID.
+**
+** The nRef field of the vxworksFileId object is incremented before
+** the object is returned. A new vxworksFileId object is created
+** and added to the global list if necessary.
+**
+** If a memory allocation error occurs, return NULL.
+*/
+static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
+ struct vxworksFileId *pNew; /* search key and new file ID */
+ struct vxworksFileId *pCandidate; /* For looping over existing file IDs */
+ int n; /* Length of zAbsoluteName string */
+
+ assert( zAbsoluteName[0]=='/' );
+ n = (int)strlen(zAbsoluteName);
+ pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
+ if( pNew==0 ) return 0;
+ pNew->zCanonicalName = (char*)&pNew[1];
+ memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
+ n = vxworksSimplifyName(pNew->zCanonicalName, n);
+
+ /* Search for an existing entry that matching the canonical name.
+ ** If found, increment the reference count and return a pointer to
+ ** the existing file ID.
+ */
+ unixEnterMutex();
+ for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
+ if( pCandidate->nName==n
+ && memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
+ ){
+ sqlite3_free(pNew);
+ pCandidate->nRef++;
+ unixLeaveMutex();
+ return pCandidate;
+ }
+ }
+
+ /* No match was found. We will make a new file ID */
+ pNew->nRef = 1;
+ pNew->nName = n;
+ pNew->pNext = vxworksFileList;
+ vxworksFileList = pNew;
+ unixLeaveMutex();
+ return pNew;
+}
+
+/*
+** Decrement the reference count on a vxworksFileId object. Free
+** the object when the reference count reaches zero.
+*/
+static void vxworksReleaseFileId(struct vxworksFileId *pId){
+ unixEnterMutex();
+ assert( pId->nRef>0 );
+ pId->nRef--;
+ if( pId->nRef==0 ){
+ struct vxworksFileId **pp;
+ for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
+ assert( *pp==pId );
+ *pp = pId->pNext;
+ sqlite3_free(pId);
+ }
+ unixLeaveMutex();
+}
+#endif /* OS_VXWORKS */
+/*************** End of Unique File ID Utility Used By VxWorks ****************
+******************************************************************************/
+
+
+/******************************************************************************
+*************************** Posix Advisory Locking ****************************
+**
+** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996)
+** section 6.5.2.2 lines 483 through 490 specify that when a process
+** sets or clears a lock, that operation overrides any prior locks set
+** by the same process. It does not explicitly say so, but this implies
+** that it overrides locks set by the same process using a different
+** file descriptor. Consider this test case:
+**
+** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644);
+** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
+**
+** Suppose ./file1 and ./file2 are really the same file (because
+** one is a hard or symbolic link to the other) then if you set
+** an exclusive lock on fd1, then try to get an exclusive lock
+** on fd2, it works. I would have expected the second lock to
+** fail since there was already a lock on the file due to fd1.
+** But not so. Since both locks came from the same process, the
+** second overrides the first, even though they were on different
+** file descriptors opened on different file names.
+**
+** This means that we cannot use POSIX locks to synchronize file access
+** among competing threads of the same process. POSIX locks will work fine
+** to synchronize access for threads in separate processes, but not
+** threads within the same process.
+**
+** To work around the problem, SQLite has to manage file locks internally
+** on its own. Whenever a new database is opened, we have to find the
+** specific inode of the database file (the inode is determined by the
+** st_dev and st_ino fields of the stat structure that fstat() fills in)
+** and check for locks already existing on that inode. When locks are
+** created or removed, we have to look at our own internal record of the
+** locks to see if another thread has previously set a lock on that same
+** inode.
+**
+** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
+** For VxWorks, we have to use the alternative unique ID system based on
+** canonical filename and implemented in the previous division.)
+**
+** The sqlite3_file structure for POSIX is no longer just an integer file
+** descriptor. It is now a structure that holds the integer file
+** descriptor and a pointer to a structure that describes the internal
+** locks on the corresponding inode. There is one locking structure
+** per inode, so if the same inode is opened twice, both unixFile structures
+** point to the same locking structure. The locking structure keeps
+** a reference count (so we will know when to delete it) and a "cnt"
+** field that tells us its internal lock status. cnt==0 means the
+** file is unlocked. cnt==-1 means the file has an exclusive lock.
+** cnt>0 means there are cnt shared locks on the file.
+**
+** Any attempt to lock or unlock a file first checks the locking
+** structure. The fcntl() system call is only invoked to set a
+** POSIX lock if the internal lock structure transitions between
+** a locked and an unlocked state.
+**
+** But wait: there are yet more problems with POSIX advisory locks.
+**
+** If you close a file descriptor that points to a file that has locks,
+** all locks on that file that are owned by the current process are
+** released. To work around this problem, each unixFile structure contains
+** a pointer to an unixOpenCnt structure. There is one unixOpenCnt structure
+** per open inode, which means that multiple unixFile can point to a single
+** unixOpenCnt. When an attempt is made to close an unixFile, if there are
+** other unixFile open on the same inode that are holding locks, the call
+** to close() the file descriptor is deferred until all of the locks clear.
+** The unixOpenCnt structure keeps a list of file descriptors that need to
+** be closed and that list is walked (and cleared) when the last lock
+** clears.
+**
+** Yet another problem: LinuxThreads do not play well with posix locks.
+**
+** Many older versions of linux use the LinuxThreads library which is
+** not posix compliant. Under LinuxThreads, a lock created by thread
+** A cannot be modified or overridden by a different thread B.
+** Only thread A can modify the lock. Locking behavior is correct
+** if the appliation uses the newer Native Posix Thread Library (NPTL)
+** on linux - with NPTL a lock created by thread A can override locks
+** in thread B. But there is no way to know at compile-time which
+** threading library is being used. So there is no way to know at
+** compile-time whether or not thread A can override locks on thread B.
+** We have to do a run-time check to discover the behavior of the
+** current process.
+**
+** On systems where thread A is unable to modify locks created by
+** thread B, we have to keep track of which thread created each
+** lock. Hence there is an extra field in the key to the unixLockInfo
+** structure to record this information. And on those systems it
+** is illegal to begin a transaction in one thread and finish it
+** in another. For this latter restriction, there is no work-around.
+** It is a limitation of LinuxThreads.
+*/
+
+/*
+** Set or check the unixFile.tid field. This field is set when an unixFile
+** is first opened. All subsequent uses of the unixFile verify that the
+** same thread is operating on the unixFile. Some operating systems do
+** not allow locks to be overridden by other threads and that restriction
+** means that sqlite3* database handles cannot be moved from one thread
+** to another while locks are held.
+**
+** Version 3.3.1 (2006-01-15): unixFile can be moved from one thread to
+** another as long as we are running on a system that supports threads
+** overriding each others locks (which is now the most common behavior)
+** or if no locks are held. But the unixFile.pLock field needs to be
+** recomputed because its key includes the thread-id. See the
+** transferOwnership() function below for additional information
+*/
+#if SQLITE_THREADSAFE && defined(__linux__)
+# define SET_THREADID(X) (X)->tid = pthread_self()
+# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \
+ !pthread_equal((X)->tid, pthread_self()))
+#else
+# define SET_THREADID(X)
+# define CHECK_THREADID(X) 0
+#endif
+
+/*
+** An instance of the following structure serves as the key used
+** to locate a particular unixOpenCnt structure given its inode. This
+** is the same as the unixLockKey except that the thread ID is omitted.
+*/
+struct unixFileId {
+ dev_t dev; /* Device number */
+#if OS_VXWORKS
+ struct vxworksFileId *pId; /* Unique file ID for vxworks. */
+#else
+ ino_t ino; /* Inode number */
+#endif
+};
+
+/*
+** An instance of the following structure serves as the key used
+** to locate a particular unixLockInfo structure given its inode.
+**
+** If threads cannot override each others locks (LinuxThreads), then we
+** set the unixLockKey.tid field to the thread ID. If threads can override
+** each others locks (Posix and NPTL) then tid is always set to zero.
+** tid is omitted if we compile without threading support or on an OS
+** other than linux.
+*/
+struct unixLockKey {
+ struct unixFileId fid; /* Unique identifier for the file */
+#if SQLITE_THREADSAFE && defined(__linux__)
+ pthread_t tid; /* Thread ID of lock owner. Zero if not using LinuxThreads */
+#endif
+};
+
+/*
+** An instance of the following structure is allocated for each open
+** inode. Or, on LinuxThreads, there is one of these structures for
+** each inode opened by each thread.
+**
+** A single inode can have multiple file descriptors, so each unixFile
+** structure contains a pointer to an instance of this object and this
+** object keeps a count of the number of unixFile pointing to it.
+*/
+struct unixLockInfo {
+ struct unixLockKey lockKey; /* The lookup key */
+ int cnt; /* Number of SHARED locks held */
+ int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
+ int nRef; /* Number of pointers to this structure */
+ struct unixLockInfo *pNext; /* List of all unixLockInfo objects */
+ struct unixLockInfo *pPrev; /* .... doubly linked */
+};
+
+/*
+** An instance of the following structure is allocated for each open
+** inode. This structure keeps track of the number of locks on that
+** inode. If a close is attempted against an inode that is holding
+** locks, the close is deferred until all locks clear by adding the
+** file descriptor to be closed to the pending list.
+**
+** TODO: Consider changing this so that there is only a single file
+** descriptor for each open file, even when it is opened multiple times.
+** The close() system call would only occur when the last database
+** using the file closes.
+*/
+struct unixOpenCnt {
+ struct unixFileId fileId; /* The lookup key */
+ int nRef; /* Number of pointers to this structure */
+ int nLock; /* Number of outstanding locks */
+ int nPending; /* Number of pending close() operations */
+ int *aPending; /* Malloced space holding fd's awaiting a close() */
+#if OS_VXWORKS
+ sem_t *pSem; /* Named POSIX semaphore */
+ char aSemName[MAX_PATHNAME+1]; /* Name of that semaphore */
+#endif
+ struct unixOpenCnt *pNext, *pPrev; /* List of all unixOpenCnt objects */
+};
+
+/*
+** Lists of all unixLockInfo and unixOpenCnt objects. These used to be hash
+** tables. But the number of objects is rarely more than a dozen and
+** never exceeds a few thousand. And lookup is not on a critical
+** path so a simple linked list will suffice.
+*/
+static struct unixLockInfo *lockList = 0;
+static struct unixOpenCnt *openList = 0;
+
+/*
+** This variable remembers whether or not threads can override each others
+** locks.
+**
+** 0: No. Threads cannot override each others locks. (LinuxThreads)
+** 1: Yes. Threads can override each others locks. (Posix & NLPT)
+** -1: We don't know yet.
+**
+** On some systems, we know at compile-time if threads can override each
+** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro
+** will be set appropriately. On other systems, we have to check at
+** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is
+** undefined.
+**
+** This variable normally has file scope only. But during testing, we make
+** it a global so that the test code can change its value in order to verify
+** that the right stuff happens in either case.
+*/
+#if SQLITE_THREADSAFE && defined(__linux__)
+# ifndef SQLITE_THREAD_OVERRIDE_LOCK
+# define SQLITE_THREAD_OVERRIDE_LOCK -1
+# endif
+# ifdef SQLITE_TEST
+int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
+# else
+static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
+# endif
+#endif
+
+/*
+** This structure holds information passed into individual test
+** threads by the testThreadLockingBehavior() routine.
+*/
+struct threadTestData {
+ int fd; /* File to be locked */
+ struct flock lock; /* The locking operation */
+ int result; /* Result of the locking operation */
+};
+
+#if SQLITE_THREADSAFE && defined(__linux__)
/*
** This function is used as the main routine for a thread launched by
** testThreadLockingBehavior(). It tests whether the shared-lock obtained
** by the main thread in testThreadLockingBehavior() conflicts with a
@@ -22131,9 +22418,12 @@
struct threadTestData *pData = (struct threadTestData*)pArg;
pData->result = fcntl(pData->fd, F_GETLK, &pData->lock);
return pArg;
}
-
+#endif /* SQLITE_THREADSAFE && defined(__linux__) */
+
+
+#if SQLITE_THREADSAFE && defined(__linux__)
/*
** This procedure attempts to determine whether or not threads
** can override each others locks then sets the
** threadsOverrideEachOthersLocks variable appropriately.
@@ -22163,23 +22453,14 @@
close(fd);
if( d.result!=0 ) return;
threadsOverrideEachOthersLocks = (d.lock.l_type==F_UNLCK);
}
-#else
-/*
-** On anything other than linux, assume threads override each others locks.
-*/
-static void testThreadLockingBehavior(int fd_orig){
- threadsOverrideEachOthersLocks = 1;
-}
-#endif /* __linux__ */
-
-#endif /* SQLITE_THREADSAFE */
-
-/*
-** Release a lockInfo structure previously allocated by findLockInfo().
-*/
-static void releaseLockInfo(struct lockInfo *pLock){
+#endif /* SQLITE_THERADSAFE && defined(__linux__) */
+
+/*
+** Release a unixLockInfo structure previously allocated by findLockInfo().
+*/
+static void releaseLockInfo(struct unixLockInfo *pLock){
if( pLock ){
pLock->nRef--;
if( pLock->nRef==0 ){
if( pLock->pPrev ){
@@ -22198,11 +22479,11 @@
}
}
/*
-** Release a openCnt structure previously allocated by findLockInfo().
-*/
-static void releaseOpenCnt(struct openCnt *pOpen){
+** Release a unixOpenCnt structure previously allocated by findLockInfo().
+*/
+static void releaseOpenCnt(struct unixOpenCnt *pOpen){
if( pOpen ){
pOpen->nRef--;
if( pOpen->nRef==0 ){
if( pOpen->pPrev ){
@@ -22221,227 +22502,37 @@
}
}
}
-#if IS_VXWORKS
-/*
-** Implementation of a realpath() like function for vxWorks
-** to determine canonical path name from given name. It does
-** not support symlinks. Neither does it handle volume prefixes.
-*/
-char *
-vxrealpath(const char *pathname, int dostat)
-{
- struct stat sbuf;
- int len;
- char *where, *ptr, *last;
- char *result, *curpath, *workpath, *namebuf;
-
- len = pathconf(pathname, _PC_PATH_MAX);
- if( len<0 ){
- len = PATH_MAX;
- }
- result = sqlite3_malloc(len * 4);
- if( !result ){
- return 0;
- }
- curpath = result + len;
- workpath = curpath + len;
- namebuf = workpath + len;
- strcpy(curpath, pathname);
- if( *pathname!='/' ){
- if( !getcwd(workpath, len) ){
- sqlite3_free(result);
- return 0;
- }
- }else{
- *workpath = '\0';
- }
- where = curpath;
- while( *where ){
- if( !strcmp(where, ".") ){
- where++;
- continue;
- }
- if( !strncmp(where, "./", 2) ){
- where += 2;
- continue;
- }
- if( !strncmp(where, "../", 3) ){
- where += 3;
- ptr = last = workpath;
- while( *ptr ){
- if( *ptr=='/' ){
- last = ptr;
- }
- ptr++;
- }
- *last = '\0';
- continue;
- }
- ptr = strchr(where, '/');
- if( !ptr ){
- ptr = where + strlen(where) - 1;
- }else{
- *ptr = '\0';
- }
- strcpy(namebuf, workpath);
- for( last = namebuf; *last; last++ ){
- continue;
- }
- if( *--last!='/' ){
- strcat(namebuf, "/");
- }
- strcat(namebuf, where);
- where = ++ptr;
- if( dostat ){
- if( stat(namebuf, &sbuf)==-1 ){
- sqlite3_free(result);
- return 0;
- }
- if( (sbuf.st_mode & S_IFDIR)==S_IFDIR ){
- strcpy(workpath, namebuf);
- continue;
- }
- if( *where ){
- sqlite3_free(result);
- return 0;
- }
- }
- strcpy(workpath, namebuf);
- }
- strcpy(result, workpath);
- return result;
-}
-#endif
-
-#if SQLITE_ENABLE_LOCKING_STYLE
-/*
-** Tests a byte-range locking query to see if byte range locks are
-** supported, if not we fall back to dotlockLockingStyle.
-** On vxWorks we fall back to namedsemLockingStyle.
-*/
-static int testLockingStyle(int fd){
- struct flock lockInfo;
-
- /* Test byte-range lock using fcntl(). If the call succeeds,
- ** assume that the file-system supports POSIX style locks.
- */
- lockInfo.l_len = 1;
- lockInfo.l_start = 0;
- lockInfo.l_whence = SEEK_SET;
- lockInfo.l_type = F_RDLCK;
- if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
- return LOCKING_STYLE_POSIX;
- }
-
- /* Testing for flock() can give false positives. So if if the above
- ** test fails, then we fall back to using dot-file style locking (or
- ** named-semaphore locking on vxworks).
- */
- return (IS_VXWORKS ? LOCKING_STYLE_NAMEDSEM : LOCKING_STYLE_DOTFILE);
-}
-#endif
-
-/*
-** If SQLITE_ENABLE_LOCKING_STYLE is defined, this function Examines the
-** f_fstypename entry in the statfs structure as returned by stat() for
-** the file system hosting the database file and selects the appropriate
-** locking style based on its value. These values and assignments are
-** based on Darwin/OSX behavior and have not been thoroughly tested on
-** other systems.
-**
-** If SQLITE_ENABLE_LOCKING_STYLE is not defined, this function always
-** returns LOCKING_STYLE_POSIX.
-*/
-#if SQLITE_ENABLE_LOCKING_STYLE
-static int detectLockingStyle(
- sqlite3_vfs *pVfs,
- const char *filePath,
- int fd
-){
-#if IS_VXWORKS
- if( !filePath ){
- return LOCKING_STYLE_NONE;
- }
- if( pVfs->pAppData ){
- return SQLITE_PTR_TO_INT(pVfs->pAppData);
- }
- if (access(filePath, 0) != -1){
- return testLockingStyle(fd);
- }
-#else
- struct Mapping {
- const char *zFilesystem;
- int eLockingStyle;
- } aMap[] = {
- { "hfs", LOCKING_STYLE_POSIX },
- { "ufs", LOCKING_STYLE_POSIX },
- { "afpfs", LOCKING_STYLE_AFP },
-#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
- { "smbfs", LOCKING_STYLE_AFP },
-#else
- { "smbfs", LOCKING_STYLE_FLOCK },
-#endif
- { "msdos", LOCKING_STYLE_DOTFILE },
- { "webdav", LOCKING_STYLE_NONE },
- { 0, 0 }
- };
- int i;
- struct statfs fsInfo;
-
- if( !filePath ){
- return LOCKING_STYLE_NONE;
- }
- if( pVfs->pAppData ){
- return SQLITE_PTR_TO_INT(pVfs->pAppData);
- }
-
- if( statfs(filePath, &fsInfo) != -1 ){
- if( fsInfo.f_flags & MNT_RDONLY ){
- return LOCKING_STYLE_NONE;
- }
- for(i=0; aMap[i].zFilesystem; i++){
- if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
- return aMap[i].eLockingStyle;
- }
- }
- }
-
- /* Default case. Handles, amongst others, "nfs". */
- return testLockingStyle(fd);
-#endif /* if IS_VXWORKS */
- return LOCKING_STYLE_POSIX;
-}
-#else
- #define detectLockingStyle(x,y,z) LOCKING_STYLE_POSIX
-#endif /* ifdef SQLITE_ENABLE_LOCKING_STYLE */
-
-/*
-** Given a file descriptor, locate lockInfo and openCnt structures that
+/*
+** Given a file descriptor, locate unixLockInfo and unixOpenCnt structures that
** describes that file descriptor. Create new ones if necessary. The
** return values might be uninitialized if an error occurs.
**
** Return an appropriate error code.
*/
static int findLockInfo(
- int fd, /* The file descriptor used in the key */
-#if IS_VXWORKS
- void *rnam, /* vxWorks realname */
-#endif
- struct lockInfo **ppLock, /* Return the lockInfo structure here */
- struct openCnt **ppOpen /* Return the openCnt structure here */
-){
- int rc;
- struct lockKey key1;
- struct openKey key2;
- struct stat statbuf;
- struct lockInfo *pLock;
- struct openCnt *pOpen;
+ unixFile *pFile, /* Unix file with file desc used in the key */
+ struct unixLockInfo **ppLock, /* Return the unixLockInfo structure here */
+ struct unixOpenCnt **ppOpen /* Return the unixOpenCnt structure here */
+){
+ int rc; /* System call return code */
+ int fd; /* The file descriptor for pFile */
+ struct unixLockKey lockKey; /* Lookup key for the unixLockInfo structure */
+ struct unixFileId fileId; /* Lookup key for the unixOpenCnt struct */
+ struct stat statbuf; /* Low-level file information */
+ struct unixLockInfo *pLock; /* Candidate unixLockInfo object */
+ struct unixOpenCnt *pOpen; /* Candidate unixOpenCnt object */
+
+ /* Get low-level information about the file that we can used to
+ ** create a unique name for the file.
+ */
+ fd = pFile->h;
rc = fstat(fd, &statbuf);
if( rc!=0 ){
+ pFile->lastErrno = errno;
#ifdef EOVERFLOW
- if( errno==EOVERFLOW ) return SQLITE_NOLFS;
+ if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
#endif
return SQLITE_IOERR;
}
@@ -22458,57 +22549,54 @@
if( statbuf.st_size==0 ){
write(fd, "S", 1);
rc = fstat(fd, &statbuf);
if( rc!=0 ){
+ pFile->lastErrno = errno;
return SQLITE_IOERR;
}
}
- memset(&key1, 0, sizeof(key1));
- key1.dev = statbuf.st_dev;
-#if IS_VXWORKS
- key1.rnam = rnam;
-#else
- key1.ino = statbuf.st_ino;
-#endif
-#if SQLITE_THREADSAFE
+ memset(&lockKey, 0, sizeof(lockKey));
+ lockKey.fid.dev = statbuf.st_dev;
+#if OS_VXWORKS
+ lockKey.fid.pId = pFile->pId;
+#else
+ lockKey.fid.ino = statbuf.st_ino;
+#endif
+#if SQLITE_THREADSAFE && defined(__linux__)
if( threadsOverrideEachOthersLocks<0 ){
testThreadLockingBehavior(fd);
}
- key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();
-#endif
- memset(&key2, 0, sizeof(key2));
- key2.dev = statbuf.st_dev;
-#if IS_VXWORKS
- key2.rnam = rnam;
-#else
- key2.ino = statbuf.st_ino;
-#endif
- pLock = lockList;
- while( pLock && memcmp(&key1, &pLock->key, sizeof(key1)) ){
- pLock = pLock->pNext;
- }
- if( pLock==0 ){
- pLock = sqlite3_malloc( sizeof(*pLock) );
+ lockKey.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self();
+#endif
+ fileId = lockKey.fid;
+ if( ppLock!=0 ){
+ pLock = lockList;
+ while( pLock && memcmp(&lockKey, &pLock->lockKey, sizeof(lockKey)) ){
+ pLock = pLock->pNext;
+ }
if( pLock==0 ){
- rc = SQLITE_NOMEM;
- goto exit_findlockinfo;
- }
- pLock->key = key1;
- pLock->nRef = 1;
- pLock->cnt = 0;
- pLock->locktype = 0;
- pLock->pNext = lockList;
- pLock->pPrev = 0;
- if( lockList ) lockList->pPrev = pLock;
- lockList = pLock;
- }else{
- pLock->nRef++;
- }
- *ppLock = pLock;
+ pLock = sqlite3_malloc( sizeof(*pLock) );
+ if( pLock==0 ){
+ rc = SQLITE_NOMEM;
+ goto exit_findlockinfo;
+ }
+ pLock->lockKey = lockKey;
+ pLock->nRef = 1;
+ pLock->cnt = 0;
+ pLock->locktype = 0;
+ pLock->pNext = lockList;
+ pLock->pPrev = 0;
+ if( lockList ) lockList->pPrev = pLock;
+ lockList = pLock;
+ }else{
+ pLock->nRef++;
+ }
+ *ppLock = pLock;
+ }
if( ppOpen!=0 ){
pOpen = openList;
- while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){
+ while( pOpen && memcmp(&fileId, &pOpen->fileId, sizeof(fileId)) ){
pOpen = pOpen->pNext;
}
if( pOpen==0 ){
pOpen = sqlite3_malloc( sizeof(*pOpen) );
@@ -22516,9 +22604,9 @@
releaseLockInfo(pLock);
rc = SQLITE_NOMEM;
goto exit_findlockinfo;
}
- pOpen->key = key2;
+ pOpen->fileId = fileId;
pOpen->nRef = 1;
pOpen->nLock = 0;
pOpen->nPending = 0;
pOpen->aPending = 0;
@@ -22525,9 +22613,9 @@
pOpen->pNext = openList;
pOpen->pPrev = 0;
if( openList ) openList->pPrev = pOpen;
openList = pOpen;
-#if IS_VXWORKS
+#if OS_VXWORKS
pOpen->pSem = NULL;
pOpen->aSemName[0] = '\0';
#endif
}else{
@@ -22539,40 +22627,20 @@
exit_findlockinfo:
return rc;
}
-#ifdef SQLITE_DEBUG
-/*
-** Helper function for printing out trace information from debugging
-** binaries. This returns the string represetation of the supplied
-** integer lock-type.
-*/
-static const char *locktypeName(int locktype){
- switch( locktype ){
- case NO_LOCK: return "NONE";
- case SHARED_LOCK: return "SHARED";
- case RESERVED_LOCK: return "RESERVED";
- case PENDING_LOCK: return "PENDING";
- case EXCLUSIVE_LOCK: return "EXCLUSIVE";
- }
- return "ERROR";
-}
-#endif
-
/*
** If we are currently in a different thread than the thread that the
** unixFile argument belongs to, then transfer ownership of the unixFile
** over to the current thread.
**
-** A unixFile is only owned by a thread on systems where one thread is
-** unable to override locks created by a different thread. RedHat9 is
-** an example of such a system.
+** A unixFile is only owned by a thread on systems that use LinuxThreads.
**
** Ownership transfer is only allowed if the unixFile is currently unlocked.
** If the unixFile is locked and an ownership is wrong, then return
** SQLITE_MISUSE. SQLITE_OK is returned if everything works.
*/
-#if SQLITE_THREADSAFE
+#if SQLITE_THREADSAFE && defined(__linux__)
static int transferOwnership(unixFile *pFile){
int rc;
pthread_t hSelf;
if( threadsOverrideEachOthersLocks ){
@@ -22593,13 +22661,9 @@
pFile->h, pFile->tid, hSelf);
pFile->tid = hSelf;
if (pFile->pLock != NULL) {
releaseLockInfo(pFile->pLock);
-#if IS_VXWORKS
- rc = findLockInfo(pFile->h, pFile->zRealpath, &pFile->pLock, 0);
-#else
- rc = findLockInfo(pFile->h, &pFile->pLock, 0);
-#endif
+ rc = findLockInfo(pFile, &pFile->pLock, 0);
OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
locktypeName(pFile->locktype),
locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
return rc;
@@ -22606,398 +22670,13 @@
} else {
return SQLITE_OK;
}
}
-#else
+#else /* if not SQLITE_THREADSAFE */
/* On single-threaded builds, ownership transfer is a no-op */
# define transferOwnership(X) SQLITE_OK
-#endif
-
-/*
-** Seek to the offset passed as the second argument, then read cnt
-** bytes into pBuf. Return the number of bytes actually read.
-**
-** NB: If you define USE_PREAD or USE_PREAD64, then it might also
-** be necessary to define _XOPEN_SOURCE to be 500. This varies from
-** one system to another. Since SQLite does not define USE_PREAD
-** any any form by default, we will not attempt to define _XOPEN_SOURCE.
-** See tickets #2741 and #2681.
-*/
-static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
- int got;
- i64 newOffset;
- TIMER_START;
-#if defined(USE_PREAD)
- got = pread(id->h, pBuf, cnt, offset);
- SimulateIOError( got = -1 );
-#elif defined(USE_PREAD64)
- got = pread64(id->h, pBuf, cnt, offset);
- SimulateIOError( got = -1 );
-#else
- newOffset = lseek(id->h, offset, SEEK_SET);
- SimulateIOError( newOffset-- );
- if( newOffset!=offset ){
- return -1;
- }
- got = read(id->h, pBuf, cnt);
-#endif
- TIMER_END;
- OSTRACE5("READ %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);
- return got;
-}
-
-/*
-** Read data from a file into a buffer. Return SQLITE_OK if all
-** bytes were read successfully and SQLITE_IOERR if anything goes
-** wrong.
-*/
-static int unixRead(
- sqlite3_file *id,
- void *pBuf,
- int amt,
- sqlite3_int64 offset
-){
- int got;
- assert( id );
- got = seekAndRead((unixFile*)id, offset, pBuf, amt);
- if( got==amt ){
- return SQLITE_OK;
- }else if( got<0 ){
- return SQLITE_IOERR_READ;
- }else{
- /* Unread parts of the buffer must be zero-filled */
- memset(&((char*)pBuf)[got], 0, amt-got);
- return SQLITE_IOERR_SHORT_READ;
- }
-}
-
-/*
-** Seek to the offset in id->offset then read cnt bytes into pBuf.
-** Return the number of bytes actually read. Update the offset.
-*/
-static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
- int got;
- i64 newOffset;
- TIMER_START;
-#if defined(USE_PREAD)
- got = pwrite(id->h, pBuf, cnt, offset);
-#elif defined(USE_PREAD64)
- got = pwrite64(id->h, pBuf, cnt, offset);
-#else
- newOffset = lseek(id->h, offset, SEEK_SET);
- if( newOffset!=offset ){
- return -1;
- }
- got = write(id->h, pBuf, cnt);
-#endif
- TIMER_END;
- OSTRACE5("WRITE %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);
- return got;
-}
-
-
-/*
-** Write data from a buffer into a file. Return SQLITE_OK on success
-** or some other error code on failure.
-*/
-static int unixWrite(
- sqlite3_file *id,
- const void *pBuf,
- int amt,
- sqlite3_int64 offset
-){
- int wrote = 0;
- assert( id );
- assert( amt>0 );
- while( amt>0 && (wrote = seekAndWrite((unixFile*)id, offset, pBuf, amt))>0 ){
- amt -= wrote;
- offset += wrote;
- pBuf = &((char*)pBuf)[wrote];
- }
- SimulateIOError(( wrote=(-1), amt=1 ));
- SimulateDiskfullError(( wrote=0, amt=1 ));
- if( amt>0 ){
- if( wrote<0 ){
- return SQLITE_IOERR_WRITE;
- }else{
- return SQLITE_FULL;
- }
- }
- return SQLITE_OK;
-}
-
-#ifdef SQLITE_TEST
-/*
-** Count the number of fullsyncs and normal syncs. This is used to test
-** that syncs and fullsyncs are occuring at the right times.
-*/
-SQLITE_API int sqlite3_sync_count = 0;
-SQLITE_API int sqlite3_fullsync_count = 0;
-#endif
-
-/*
-** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined.
-** Otherwise use fsync() in its place.
-*/
-#ifndef HAVE_FDATASYNC
-# define fdatasync fsync
-#endif
-
-/*
-** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
-** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently
-** only available on Mac OS X. But that could change.
-*/
-#ifdef F_FULLFSYNC
-# define HAVE_FULLFSYNC 1
-#else
-# define HAVE_FULLFSYNC 0
-#endif
-
-
-/*
-** The fsync() system call does not work as advertised on many
-** unix systems. The following procedure is an attempt to make
-** it work better.
-**
-** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
-** for testing when we want to run through the test suite quickly.
-** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
-** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
-** or power failure will likely corrupt the database file.
-*/
-static int full_fsync(int fd, int fullSync, int dataOnly){
- int rc;
-
- /* The following "ifdef/elif/else/" block has the same structure as
- ** the one below. It is replicated here solely to avoid cluttering
- ** up the real code with the UNUSED_PARAMETER() macros.
- */
-#ifdef SQLITE_NO_SYNC
- UNUSED_PARAMETER(fd);
- UNUSED_PARAMETER(fullSync);
- UNUSED_PARAMETER(dataOnly);
-#elif HAVE_FULLFSYNC
- UNUSED_PARAMETER(dataOnly);
-#else
- UNUSED_PARAMETER(fullSync);
-#endif
-
- /* Record the number of times that we do a normal fsync() and
- ** FULLSYNC. This is used during testing to verify that this procedure
- ** gets called with the correct arguments.
- */
-#ifdef SQLITE_TEST
- if( fullSync ) sqlite3_fullsync_count++;
- sqlite3_sync_count++;
-#endif
-
- /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
- ** no-op
- */
-#ifdef SQLITE_NO_SYNC
- rc = SQLITE_OK;
-#elif HAVE_FULLFSYNC
- if( fullSync ){
- rc = fcntl(fd, F_FULLFSYNC, 0);
- }else{
- rc = 1;
- }
- /* If the FULLFSYNC failed, fall back to attempting an fsync().
- * It shouldn't be possible for fullfsync to fail on the local
- * file system (on OSX), so failure indicates that FULLFSYNC
- * isn't supported for this file system. So, attempt an fsync
- * and (for now) ignore the overhead of a superfluous fcntl call.
- * It'd be better to detect fullfsync support once and avoid
- * the fcntl call every time sync is called.
- */
- if( rc ) rc = fsync(fd);
-
-#else
- if( dataOnly ){
- rc = fdatasync(fd);
- if( IS_VXWORKS && rc==-1 && errno==ENOTSUP ){
- rc = fsync(fd);
- }
- }else{
- rc = fsync(fd);
- }
-#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
-
- if( IS_VXWORKS && rc!= -1 ){
- rc = 0;
- }
- return rc;
-}
-
-/*
-** Make sure all writes to a particular file are committed to disk.
-**
-** If dataOnly==0 then both the file itself and its metadata (file
-** size, access time, etc) are synced. If dataOnly!=0 then only the
-** file data is synced.
-**
-** Under Unix, also make sure that the directory entry for the file
-** has been created by fsync-ing the directory that contains the file.
-** If we do not do this and we encounter a power failure, the directory
-** entry for the journal might not exist after we reboot. The next
-** SQLite to access the file will not know that the journal exists (because
-** the directory entry for the journal was never created) and the transaction
-** will not roll back - possibly leading to database corruption.
-*/
-static int unixSync(sqlite3_file *id, int flags){
- int rc;
- unixFile *pFile = (unixFile*)id;
-
- int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
- int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
-
- /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
- assert((flags&0x0F)==SQLITE_SYNC_NORMAL
- || (flags&0x0F)==SQLITE_SYNC_FULL
- );
-
- /* Unix cannot, but some systems may return SQLITE_FULL from here. This
- ** line is to test that doing so does not cause any problems.
- */
- SimulateDiskfullError( return SQLITE_FULL );
-
- assert( pFile );
- OSTRACE2("SYNC %-3d\n", pFile->h);
- rc = full_fsync(pFile->h, isFullsync, isDataOnly);
- SimulateIOError( rc=1 );
- if( rc ){
- return SQLITE_IOERR_FSYNC;
- }
- if( pFile->dirfd>=0 ){
- OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
- HAVE_FULLFSYNC, isFullsync);
-#ifndef SQLITE_DISABLE_DIRSYNC
- /* The directory sync is only attempted if full_fsync is
- ** turned off or unavailable. If a full_fsync occurred above,
- ** then the directory sync is superfluous.
- */
- if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
- /*
- ** We have received multiple reports of fsync() returning
- ** errors when applied to directories on certain file systems.
- ** A failed directory sync is not a big deal. So it seems
- ** better to ignore the error. Ticket #1657
- */
- /* return SQLITE_IOERR; */
- }
-#endif
- close(pFile->dirfd); /* Only need to sync once, so close the directory */
- pFile->dirfd = -1; /* when we are done. */
- }
- return SQLITE_OK;
-}
-
-/*
-** Truncate an open file to a specified size
-*/
-static int unixTruncate(sqlite3_file *id, i64 nByte){
- int rc;
- assert( id );
- SimulateIOError( return SQLITE_IOERR_TRUNCATE );
- rc = ftruncate(((unixFile*)id)->h, (off_t)nByte);
- if( rc ){
- return SQLITE_IOERR_TRUNCATE;
- }else{
- return SQLITE_OK;
- }
-}
-
-/*
-** Determine the current size of a file in bytes
-*/
-static int unixFileSize(sqlite3_file *id, i64 *pSize){
- int rc;
- struct stat buf;
- assert( id );
- rc = fstat(((unixFile*)id)->h, &buf);
- SimulateIOError( rc=1 );
- if( rc!=0 ){
- return SQLITE_IOERR_FSTAT;
- }
- *pSize = buf.st_size;
-
- /* When opening a zero-size database, the findLockInfo() procedure
- ** writes a single byte into that file in order to work around a bug
- ** in the OS-X msdos filesystem. In order to avoid problems with upper
- ** layers, we need to report this file size as zero even though it is
- ** really 1. Ticket #3260.
- */
- if( *pSize==1 ) *pSize = 0;
-
-
- return SQLITE_OK;
-}
-
-/*
-** This routine translates a standard POSIX errno code into something
-** useful to the clients of the sqlite3 functions. Specifically, it is
-** intended to translate a variety of "try again" errors into SQLITE_BUSY
-** and a variety of "please close the file descriptor NOW" errors into
-** SQLITE_IOERR
-**
-** Errors during initialization of locks, or file system support for locks,
-** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
-*/
-static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
- switch (posixError) {
- case 0:
- return SQLITE_OK;
-
- case EAGAIN:
- case ETIMEDOUT:
- case EBUSY:
- case EINTR:
- case ENOLCK:
- /* random NFS retry error, unless during file system support
- * introspection, in which it actually means what it says */
- return SQLITE_BUSY;
-
- case EACCES:
- /* EACCES is like EAGAIN during locking operations, but not any other time*/
- if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
- (sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
- (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
- return SQLITE_BUSY;
- }
- /* else fall through */
- case EPERM:
- return SQLITE_PERM;
-
- case EDEADLK:
- return SQLITE_IOERR_BLOCKED;
-
-#if EOPNOTSUPP!=ENOTSUP
- case EOPNOTSUPP:
- /* something went terribly awry, unless during file system support
- * introspection, in which it actually means what it says */
-#endif
-#ifdef ENOTSUP
- case ENOTSUP:
- /* invalid fd, unless during file system support introspection, in which
- * it actually means what it says */
-#endif
- case EIO:
- case EBADF:
- case EINVAL:
- case ENOTCONN:
- case ENODEV:
- case ENXIO:
- case ENOENT:
- case ESTALE:
- case ENOSYS:
- /* these should force the client to close the file and reconnect */
-
- default:
- return sqliteIOErr;
- }
-}
+#endif /* SQLITE_THREADSAFE */
+
/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
@@ -23011,9 +22690,9 @@
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
- enterMutex(); /* Because pFile->pLock is shared across threads */
+ unixEnterMutex(); /* Because pFile->pLock is shared across threads */
/* Check if a thread in this process holds such a lock */
if( pFile->pLock->locktype>SHARED_LOCK ){
reserved = 1;
@@ -23035,9 +22714,9 @@
reserved = 1;
}
}
- leaveMutex();
+ unixLeaveMutex();
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
@@ -23107,9 +22786,9 @@
** even if the locking primitive used is always a write-lock.
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
- struct lockInfo *pLock = pFile->pLock;
+ struct unixLockInfo *pLock = pFile->pLock;
struct flock lock;
int s;
assert( pFile );
@@ -23118,9 +22797,9 @@
locktypeName(pLock->locktype), pLock->cnt , getpid());
/* If there is already a lock of this type or more restrictive on the
** unixFile, do nothing. Don't use the end_lock: exit path, as
- ** enterMutex() hasn't been called yet.
+ ** unixEnterMutex() hasn't been called yet.
*/
if( pFile->locktype>=locktype ){
OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
locktypeName(locktype));
@@ -23134,15 +22813,15 @@
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
/* This mutex is needed because pFile->pLock is shared across threads
*/
- enterMutex();
+ unixEnterMutex();
/* Make sure the current thread owns the pFile.
*/
rc = transferOwnership(pFile);
if( rc!=SQLITE_OK ){
- leaveMutex();
+ unixLeaveMutex();
return rc;
}
pLock = pFile->pLock;
@@ -23275,9 +22954,9 @@
pLock->locktype = PENDING_LOCK;
}
end_lock:
- leaveMutex();
+ unixLeaveMutex();
OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
rc==SQLITE_OK ? "ok" : "failed");
return rc;
}
@@ -23289,9 +22968,9 @@
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
static int unixUnlock(sqlite3_file *id, int locktype){
- struct lockInfo *pLock;
+ struct unixLockInfo *pLock;
struct flock lock;
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
int h;
@@ -23306,9 +22985,9 @@
}
if( CHECK_THREADID(pFile) ){
return SQLITE_MISUSE;
}
- enterMutex();
+ unixEnterMutex();
h = pFile->h;
pLock = pFile->pLock;
assert( pLock->cnt!=0 );
if( pFile->locktype>SHARED_LOCK ){
@@ -23345,9 +23024,9 @@
goto end_unlock;
}
}
if( locktype==NO_LOCK ){
- struct openCnt *pOpen;
+ struct unixOpenCnt *pOpen;
/* Decrement the shared lock counter. Release the lock using an
** OS call only when all threads in this same process have released
** the lock.
@@ -23383,19 +23062,30 @@
assert( pOpen->nLock>=0 );
if( pOpen->nLock==0 && pOpen->nPending>0 ){
int i;
for(i=0; i<pOpen->nPending; i++){
- close(pOpen->aPending[i]);
- }
- sqlite3_free(pOpen->aPending);
- pOpen->nPending = 0;
- pOpen->aPending = 0;
+ /* close pending fds, but if closing fails don't free the array
+ ** assign -1 to the successfully closed descriptors and record the
+ ** error. The next attempt to unlock will try again. */
+ if( pOpen->aPending[i] < 0 ) continue;
+ if( close(pOpen->aPending[i]) ){
+ pFile->lastErrno = errno;
+ rc = SQLITE_IOERR_CLOSE;
+ }else{
+ pOpen->aPending[i] = -1;
+ }
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3_free(pOpen->aPending);
+ pOpen->nPending = 0;
+ pOpen->aPending = 0;
+ }
}
}
}
end_unlock:
- leaveMutex();
+ unixLeaveMutex();
if( rc==SQLITE_OK ) pFile->locktype = locktype;
return rc;
}
@@ -23403,35 +23093,39 @@
** This function performs the parts of the "close file" operation
** common to all locking schemes. It closes the directory and file
** handles, if they are valid, and sets all fields of the unixFile
** structure to 0.
+**
+** It is *not* necessary to hold the mutex when this routine is called,
+** even on VxWorks. A mutex will be acquired on VxWorks by the
+** vxworksReleaseFileId() routine.
*/
static int closeUnixFile(sqlite3_file *id){
unixFile *pFile = (unixFile*)id;
if( pFile ){
if( pFile->dirfd>=0 ){
- close(pFile->dirfd);
+ int err = close(pFile->dirfd);
+ if( err ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR_DIR_CLOSE;
+ }else{
+ pFile->dirfd=-1;
+ }
}
if( pFile->h>=0 ){
- close(pFile->h);
- }
-#if IS_VXWORKS
- if( pFile->isDelete && pFile->zRealpath ){
- unlink(pFile->zRealpath);
- }
- if( pFile->zRealpath ){
- HashElem *pElem;
- int n = strlen(pFile->zRealpath) + 1;
- pElem = sqlite3HashFindElem(&nameHash, pFile->zRealpath, n);
- if( pElem ){
- long cnt = (long)pElem->data;
- cnt--;
- if( cnt==0 ){
- sqlite3HashInsert(&nameHash, pFile->zRealpath, n, 0);
- }else{
- pElem->data = (void*)cnt;
- }
- }
+ int err = close(pFile->h);
+ if( err ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR_CLOSE;
+ }
+ }
+#if OS_VXWORKS
+ if( pFile->pId ){
+ if( pFile->isDelete ){
+ unlink(pFile->pId->zCanonicalName);
+ }
+ vxworksReleaseFileId(pFile->pId);
+ pFile->pId = 0;
}
#endif
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
@@ -23443,20 +23137,21 @@
/*
** Close a file.
*/
static int unixClose(sqlite3_file *id){
+ int rc = SQLITE_OK;
if( id ){
unixFile *pFile = (unixFile *)id;
unixUnlock(id, NO_LOCK);
- enterMutex();
+ unixEnterMutex();
if( pFile->pOpen && pFile->pOpen->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
** descriptor to pOpen->aPending. It will be automatically closed when
** the last lock is cleared.
*/
int *aNew;
- struct openCnt *pOpen = pFile->pOpen;
+ struct unixOpenCnt *pOpen = pFile->pOpen;
aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
if( aNew==0 ){
/* If a malloc fails, just leak the file descriptor */
}else{
@@ -23467,246 +23162,188 @@
}
}
releaseLockInfo(pFile->pLock);
releaseOpenCnt(pFile->pOpen);
- closeUnixFile(id);
- leaveMutex();
- }
- return SQLITE_OK;
-}
-
-
-#if SQLITE_ENABLE_LOCKING_STYLE
-
-#if !IS_VXWORKS
-#pragma mark AFP Support
-
-/*
- ** The afpLockingContext structure contains all afp lock specific state
- */
-typedef struct afpLockingContext afpLockingContext;
-struct afpLockingContext {
- unsigned long long sharedLockByte;
- const char *filePath;
-};
-
-struct ByteRangeLockPB2
-{
- unsigned long long offset; /* offset to first byte to lock */
- unsigned long long length; /* nbr of bytes to lock */
- unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
- unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
- unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
- int fd; /* file desc to assoc this lock with */
-};
-
-#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
-
-/*
- ** Return SQLITE_OK on success, SQLITE_BUSY on failure.
- */
-static int _AFPFSSetLock(
- const char *path,
- unixFile *pFile,
- unsigned long long offset,
- unsigned long long length,
- int setLockFlag
-){
- struct ByteRangeLockPB2 pb;
- int err;
-
- pb.unLockFlag = setLockFlag ? 0 : 1;
- pb.startEndFlag = 0;
- pb.offset = offset;
- pb.length = length;
- pb.fd = pFile->h;
- OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n",
- (setLockFlag?"ON":"OFF"), pFile->h, offset, length);
- err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
- if ( err==-1 ) {
- int rc;
- int tErrno = errno;
- OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, tErrno, strerror(tErrno));
- rc = sqliteErrorFromPosixError(tErrno, setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK); /* error */
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- return rc;
- } else {
- return SQLITE_OK;
- }
-}
-
-/* AFP-style reserved lock checking following the behavior of
-** unixCheckReservedLock, see the unixCheckReservedLock function comments */
-static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
+ rc = closeUnixFile(id);
+ unixLeaveMutex();
+ }
+ return rc;
+}
+
+/************** End of the posix advisory lock implementation *****************
+******************************************************************************/
+
+/******************************************************************************
+****************************** No-op Locking **********************************
+**
+** Of the various locking implementations available, this is by far the
+** simplest: locking is ignored. No attempt is made to lock the database
+** file for reading or writing.
+**
+** This locking mode is appropriate for use on read-only databases
+** (ex: databases that are burned into CD-ROM, for example.) It can
+** also be used if the application employs some external mechanism to
+** prevent simultaneous access of the same database by two or more
+** database connections. But there is a serious risk of database
+** corruption if this locking mode is used in situations where multiple
+** database connections are accessing the same database file at the same
+** time and one or more of those connections are writing.
+*/
+
+static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
+ UNUSED_PARAMETER(NotUsed);
+ *pResOut = 0;
+ return SQLITE_OK;
+}
+static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ return SQLITE_OK;
+}
+static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
+ return SQLITE_OK;
+}
+
+/*
+** Close the file.
+*/
+static int nolockClose(sqlite3_file *id) {
+ return closeUnixFile(id);
+}
+
+/******************* End of the no-op lock implementation *********************
+******************************************************************************/
+
+/******************************************************************************
+************************* Begin dot-file Locking ******************************
+**
+** The dotfile locking implementation uses the existing of separate lock
+** files in order to control access to the database. This works on just
+** about every filesystem imaginable. But there are serious downsides:
+**
+** (1) There is zero concurrency. A single reader blocks all other
+** connections from reading or writing the database.
+**
+** (2) An application crash or power loss can leave stale lock files
+** sitting around that need to be cleared manually.
+**
+** Nevertheless, a dotlock is an appropriate locking mode for use if no
+** other locking strategy is available.
+**
+** Dotfile locking works by creating a file in the same directory as the
+** database and with the same name but with a ".lock" extension added.
+** The existance of a lock file implies an EXCLUSIVE lock. All other lock
+** types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
+*/
+
+/*
+** The file suffix added to the data base filename in order to create the
+** lock file.
+*/
+#define DOTLOCK_SUFFIX ".lock"
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+**
+** In dotfile locking, either a lock exists or it does not. So in this
+** variation of CheckReservedLock(), *pResOut is set to true if any lock
+** is held on the file and false if the file is unlocked.
+*/
+static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
/* Check if a thread in this process holds such a lock */
if( pFile->locktype>SHARED_LOCK ){
+ /* Either this connection or some other connection in the same process
+ ** holds a lock on the file. No need to check further. */
reserved = 1;
- }
-
- /* Otherwise see if some other process holds it.
- */
- if( !reserved ){
- /* lock the RESERVED byte */
- int lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);
- if( SQLITE_OK==lrc ){
- /* if we succeeded in taking the reserved lock, unlock it to restore
- ** the original state */
- lrc = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1, 0);
- } else {
- /* if we failed to get the lock then someone else must have it */
- reserved = 1;
- }
- if( IS_LOCK_ERROR(lrc) ){
- rc=lrc;
- }
- }
-
- OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
-
+ }else{
+ /* The lock is held if and only if the lockfile exists */
+ const char *zLockFile = (const char*)pFile->lockingContext;
+ reserved = access(zLockFile, 0)==0;
+ }
+ OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
*pResOut = reserved;
return rc;
}
-/* AFP-style locking following the behavior of unixLock, see the unixLock
-** function comments for details of lock management. */
-static int afpLock(sqlite3_file *id, int locktype){
- int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
-
- assert( pFile );
- OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h,
- locktypeName(locktype), locktypeName(pFile->locktype), getpid());
-
- /* If there is already a lock of this type or more restrictive on the
- ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
- ** enterMutex() hasn't been called yet.
- */
- if( pFile->locktype>=locktype ){
- OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
- locktypeName(locktype));
- return SQLITE_OK;
- }
-
- /* Make sure the locking sequence is correct
- */
- assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
- assert( locktype!=PENDING_LOCK );
- assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
-
- /* This mutex is needed because pFile->pLock is shared across threads
- */
- enterMutex();
-
- /* Make sure the current thread owns the pFile.
- */
- rc = transferOwnership(pFile);
- if( rc!=SQLITE_OK ){
- leaveMutex();
- return rc;
- }
-
- /* A PENDING lock is needed before acquiring a SHARED lock and before
- ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
- ** be released.
- */
- if( locktype==SHARED_LOCK
- || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
- ){
- int failed;
- failed = _AFPFSSetLock(context->filePath, pFile, PENDING_BYTE, 1, 1);
- if (failed) {
- rc = failed;
- goto afp_end_lock;
- }
- }
-
- /* If control gets to this point, then actually go ahead and make
- ** operating system calls for the specified lock.
- */
- if( locktype==SHARED_LOCK ){
- int lk, lrc1, lrc2, lrc1Errno;
-
- /* Now get the read-lock SHARED_LOCK */
- /* note that the quality of the randomness doesn't matter that much */
- lk = random();
- context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
- 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( 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;
+/*
+** Lock the file with the lock specified by parameter locktype - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+**
+** With dotfile locking, we really only support state (4): EXCLUSIVE.
+** But we track the other locking levels internally.
+*/
+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 have any lock, then the lock file already exists. All we have
+ ** to do is adjust our internal record of the lock level.
+ */
+ if( pFile->locktype > NO_LOCK ){
+ pFile->locktype = locktype;
+#if !OS_VXWORKS
+ /* Always update the timestamp on the old file */
+ utimes(zLockFile, NULL);
+#endif
+ return SQLITE_OK;
+ }
+
+ /* grab an exclusive lock */
+ fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
+ if( fd<0 ){
+ /* failed to open/create the file, someone else may have stolen the lock */
+ int tErrno = errno;
+ if( EEXIST == tErrno ){
+ rc = SQLITE_BUSY;
} else {
- pFile->locktype = SHARED_LOCK;
- }
- }else{
- /* The request was for a RESERVED or EXCLUSIVE lock. It is
- ** assumed that there is a SHARED or greater lock on the file
- ** already.
- */
- int failed = 0;
- assert( 0!=pFile->locktype );
- if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
- /* Acquire a RESERVED lock */
- failed = _AFPFSSetLock(context->filePath, pFile, RESERVED_BYTE, 1,1);
- }
- if (!failed && locktype == EXCLUSIVE_LOCK) {
- /* Acquire an EXCLUSIVE lock */
-
- /* Remove the shared lock before trying the range. we'll need to
- ** reestablish the shared lock if we can't get the afpUnlock
- */
- if (!(failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST +
- context->sharedLockByte, 1, 0))) {
- /* now attemmpt to get the exclusive lock range */
- failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST,
- SHARED_SIZE, 1);
- if (failed && (failed = _AFPFSSetLock(context->filePath, pFile,
- SHARED_FIRST + context->sharedLockByte, 1, 1))) {
- rc = failed;
- }
- } else {
- rc = failed;
- }
- }
- if( failed ){
- rc = failed;
- }
- }
-
- if( rc==SQLITE_OK ){
- pFile->locktype = locktype;
- }else if( locktype==EXCLUSIVE_LOCK ){
- pFile->locktype = PENDING_LOCK;
- }
-
-afp_end_lock:
- leaveMutex();
- OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
- rc==SQLITE_OK ? "ok" : "failed");
+ rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ }
+ return rc;
+ }
+ if( close(fd) ){
+ pFile->lastErrno = errno;
+ rc = SQLITE_IOERR_CLOSE;
+ }
+
+ /* got it, set the type and return ok */
+ pFile->locktype = locktype;
return rc;
}
/*
@@ -23714,96 +23351,88 @@
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
-*/
-static int afpUnlock(sqlite3_file *id, int locktype) {
- int rc = SQLITE_OK;
- unixFile *pFile = (unixFile*)id;
- afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+**
+** When the locking level reaches NO_LOCK, delete the lock file.
+*/
+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());
-
+ pFile->locktype, getpid());
assert( locktype<=SHARED_LOCK );
- if( pFile->locktype<=locktype ){
- return SQLITE_OK;
- }
- if( CHECK_THREADID(pFile) ){
- return SQLITE_MISUSE;
- }
- enterMutex();
- int failed = SQLITE_OK;
- if( pFile->locktype>SHARED_LOCK ){
- if( locktype==SHARED_LOCK ){
-
- /* unlock the exclusive range - then re-establish the shared lock */
- if (pFile->locktype==EXCLUSIVE_LOCK) {
- failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST,
- SHARED_SIZE, 0);
- if (!failed) {
- /* successfully removed the exclusive lock */
- if ((failed = _AFPFSSetLock(context->filePath, pFile, SHARED_FIRST+
- context->sharedLockByte, 1, 1))) {
- /* failed to re-establish our shared lock */
- rc = failed;
- }
- } else {
- rc = failed;
- }
- }
- }
- if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) {
- if ((failed = _AFPFSSetLock(context->filePath, pFile,
- PENDING_BYTE, 1, 0))){
- /* failed to release the pending lock */
- rc = failed;
- }
- }
- if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) {
- if ((failed = _AFPFSSetLock(context->filePath, pFile,
- RESERVED_BYTE, 1, 0))) {
- /* failed to release the reserved lock */
- rc = failed;
- }
- }
- }
- if( locktype==NO_LOCK ){
- int failed = _AFPFSSetLock(context->filePath, pFile,
- SHARED_FIRST + context->sharedLockByte, 1, 0);
- if (failed) {
- rc = failed;
- }
- }
- if (rc == SQLITE_OK)
- pFile->locktype = locktype;
- leaveMutex();
- return rc;
-}
-
-/*
-** Close a file & cleanup AFP specific locking context
-*/
-static int afpClose(sqlite3_file *id) {
+
+ /* no-op if possible */
+ if( pFile->locktype==locktype ){
+ return SQLITE_OK;
+ }
+
+ /* To downgrade to shared, simply update our internal notion of the
+ ** lock state. No need to mess with the file on disk.
+ */
+ if( locktype==SHARED_LOCK ){
+ pFile->locktype = SHARED_LOCK;
+ return SQLITE_OK;
+ }
+
+ /* To fully unlock the database, delete the lock file */
+ assert( locktype==NO_LOCK );
+ 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;
+}
+
+/*
+** Close a file. Make sure the lock has been released before closing.
+*/
+static int dotlockClose(sqlite3_file *id) {
+ int rc;
if( id ){
unixFile *pFile = (unixFile*)id;
- afpUnlock(id, NO_LOCK);
+ dotlockUnlock(id, NO_LOCK);
sqlite3_free(pFile->lockingContext);
}
- return closeUnixFile(id);
-}
-
-
-#pragma mark flock() style locking
-
-/*
-** The flockLockingContext is not used
-*/
-typedef void flockLockingContext;
-
-/* flock-style reserved lock checking following the behavior of
- ** unixCheckReservedLock, see the unixCheckReservedLock function comments */
+ rc = closeUnixFile(id);
+ return rc;
+}
+/****************** End of the dot-file lock implementation *******************
+******************************************************************************/
+
+/******************************************************************************
+************************** Begin flock Locking ********************************
+**
+** Use the flock() system call to do file locking.
+**
+** flock() locking is like dot-file locking in that the various
+** fine-grain locking levels supported by SQLite are collapsed into
+** a single exclusive lock. In other words, SHARED, RESERVED, and
+** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
+** still works when you do this, but concurrency is reduced since
+** only a single process can be reading the database at a time.
+**
+** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
+** compiling for VXWORKS.
+*/
+#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+*/
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
@@ -23845,12 +23474,47 @@
}
}
OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+ rc = SQLITE_OK;
+ reserved=1;
+ }
+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
*pResOut = reserved;
return rc;
}
+/*
+** Lock the file with the lock specified by parameter locktype - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** flock() only really support EXCLUSIVE locks. We track intermediate
+** lock states in the sqlite3_file structure, but all locks SHARED or
+** above are really EXCLUSIVE locks and exclude all other processes from
+** access the file.
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
static int flockLock(sqlite3_file *id, int locktype) {
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
@@ -23877,11 +23541,24 @@
pFile->locktype = locktype;
}
OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
rc==SQLITE_OK ? "ok" : "failed");
- return rc;
-}
-
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ if( (rc & SQLITE_IOERR) == SQLITE_IOERR ){
+ rc = SQLITE_BUSY;
+ }
+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
+ return rc;
+}
+
+
+/*
+** Lower the locking level on file descriptor pFile to locktype. locktype
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
static int flockUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
assert( pFile );
@@ -23907,8 +23584,14 @@
r = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(r) ){
pFile->lastErrno = tErrno;
}
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ if( (r & SQLITE_IOERR) == SQLITE_IOERR ){
+ r = SQLITE_BUSY;
+ }
+#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
+
return r;
} else {
pFile->locktype = NO_LOCK;
return SQLITE_OK;
@@ -23924,158 +23607,32 @@
}
return closeUnixFile(id);
}
-#endif /* !IS_VXWORKS */
-
-#pragma mark Old-School .lock file based locking
-
-/* Dotlock-style reserved lock checking following the behavior of
-** unixCheckReservedLock, see the unixCheckReservedLock function comments */
-static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
- int rc = SQLITE_OK;
- int reserved = 0;
- unixFile *pFile = (unixFile*)id;
-
- SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
-
- assert( pFile );
-
- /* Check if a thread in this process holds such a lock */
- if( pFile->locktype>SHARED_LOCK ){
- reserved = 1;
- }
-
- /* Otherwise see if some other process holds it. */
- if( !reserved ){
- char *zLockFile = (char *)pFile->lockingContext;
- struct stat statBuf;
-
- 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 */
- int tErrno = errno;
- if( ENOENT != tErrno ){
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
- pFile->lastErrno = tErrno;
- }
- }
- }
- OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
-
- *pResOut = reserved;
- return rc;
-}
-
-static int dotlockLock(sqlite3_file *id, int locktype) {
- unixFile *pFile = (unixFile*)id;
- int fd;
- char *zLockFile = (char *)pFile->lockingContext;
- int rc=SQLITE_OK;
-
- /* if we already have a lock, it is exclusive.
- ** Just adjust level and punt on outta here. */
- if (pFile->locktype > NO_LOCK) {
- pFile->locktype = locktype;
-#if !IS_VXWORKS
- /* Always update the timestamp on the old file */
- utimes(zLockFile, NULL);
-#endif
- rc = SQLITE_OK;
- goto dotlock_end_lock;
- }
-
- /* check to see if lock file already exists */
- struct stat statBuf;
- if (lstat(zLockFile,&statBuf) == 0){
- rc = SQLITE_BUSY; /* it does, busy */
- goto dotlock_end_lock;
- }
-
- /* grab an exclusive lock */
- fd = open(zLockFile,O_RDONLY|O_CREAT|O_EXCL,0600);
- if( fd<0 ){
- /* failed to open/create the file, someone else may have stolen the lock */
- int tErrno = errno;
- if( EEXIST == tErrno ){
- rc = SQLITE_BUSY;
- } else {
- rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
- if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
- }
- }
- goto dotlock_end_lock;
- }
- close(fd);
-
- /* got it, set the type and return ok */
- pFile->locktype = locktype;
-
- dotlock_end_lock:
- return rc;
-}
-
-static int dotlockUnlock(sqlite3_file *id, int locktype) {
- unixFile *pFile = (unixFile*)id;
- char *zLockFile = (char *)pFile->lockingContext;
-
- assert( pFile );
- OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype,
- pFile->locktype, getpid());
- assert( locktype<=SHARED_LOCK );
-
- /* no-op if possible */
- if( pFile->locktype==locktype ){
- return SQLITE_OK;
- }
-
- /* shared can just be set because we always have an exclusive */
- if (locktype==SHARED_LOCK) {
- pFile->locktype = locktype;
- return SQLITE_OK;
- }
-
- /* no, really, unlock. */
- if (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;
-}
-
-/*
- ** Close a file.
- */
-static int dotlockClose(sqlite3_file *id) {
- int rc;
- if( id ){
- unixFile *pFile = (unixFile*)id;
- dotlockUnlock(id, NO_LOCK);
- sqlite3_free(pFile->lockingContext);
- }
- if( IS_VXWORKS ) enterMutex();
- rc = closeUnixFile(id);
- if( IS_VXWORKS ) leaveMutex();
- return rc;
-}
-
-#if IS_VXWORKS
-
-#pragma mark POSIX/vxWorks named semaphore based locking
-
-/* Namedsem-style reserved lock checking following the behavior of
-** unixCheckReservedLock, see the unixCheckReservedLock function comments */
-static int namedsemCheckReservedLock(sqlite3_file *id, int *pResOut) {
+#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
+
+/******************* End of the flock lock implementation *********************
+******************************************************************************/
+
+/******************************************************************************
+************************ Begin Named Semaphore Locking ************************
+**
+** Named semaphore locking is only supported on VxWorks.
+**
+** Semaphore locking is like dot-lock and flock in that it really only
+** supports EXCLUSIVE locking. Only a single process can read or write
+** the database file at a time. This reduces potential concurrency, but
+** makes the lock implementation much easier.
+*/
+#if OS_VXWORKS
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+*/
+static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
@@ -24098,10 +23655,10 @@
if( EAGAIN != tErrno ){
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
pFile->lastErrno = tErrno;
} else {
- /* someone else has the lock when we are in NO_LOCK */
- reserved = (pFile->locktype < SHARED_LOCK);
+ /* someone else has the lock when we are in NO_LOCK */
+ reserved = (pFile->locktype < SHARED_LOCK);
}
}else{
/* we could have it if we want it */
sem_post(pSem);
@@ -24112,9 +23669,38 @@
*pResOut = reserved;
return rc;
}
-static int namedsemLock(sqlite3_file *id, int locktype) {
+/*
+** Lock the file with the lock specified by parameter locktype - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
+** lock states in the sqlite3_file structure, but all locks SHARED or
+** above are really EXCLUSIVE locks and exclude all other processes from
+** access the file.
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
+static int semLock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
int fd;
sem_t *pSem = pFile->pOpen->pSem;
int rc = SQLITE_OK;
@@ -24123,25 +23709,32 @@
** Just adjust level and punt on outta here. */
if (pFile->locktype > NO_LOCK) {
pFile->locktype = locktype;
rc = SQLITE_OK;
- goto namedsem_end_lock;
+ goto sem_end_lock;
}
/* lock semaphore now but bail out when already locked. */
if( sem_trywait(pSem)==-1 ){
rc = SQLITE_BUSY;
- goto namedsem_end_lock;
+ goto sem_end_lock;
}
/* got it, set the type and return ok */
pFile->locktype = locktype;
- namedsem_end_lock:
- return rc;
-}
-
-static int namedsemUnlock(sqlite3_file *id, int locktype) {
+ sem_end_lock:
+ return rc;
+}
+
+/*
+** Lower the locking level on file descriptor pFile to locktype. locktype
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
+static int semUnlock(sqlite3_file *id, int locktype) {
unixFile *pFile = (unixFile*)id;
sem_t *pSem = pFile->pOpen->pSem;
assert( pFile );
@@ -24176,57 +23769,809 @@
/*
** Close a file.
*/
-static int namedsemClose(sqlite3_file *id) {
+static int semClose(sqlite3_file *id) {
if( id ){
unixFile *pFile = (unixFile*)id;
- namedsemUnlock(id, NO_LOCK);
+ semUnlock(id, NO_LOCK);
assert( pFile );
- enterMutex();
+ unixEnterMutex();
releaseLockInfo(pFile->pLock);
releaseOpenCnt(pFile->pOpen);
closeUnixFile(id);
- leaveMutex();
- }
- return SQLITE_OK;
-}
-
-#endif /* IS_VXWORKS */
-
-#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-
-/*
-** The nolockLockingContext is void
-*/
-typedef void nolockLockingContext;
-
-static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
- UNUSED_PARAMETER(NotUsed);
- *pResOut = 0;
- return SQLITE_OK;
-}
-
-static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return SQLITE_OK;
-}
-
-static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
- return SQLITE_OK;
-}
-
-/*
-** Close a file.
-*/
-static int nolockClose(sqlite3_file *id) {
- int rc;
- if( IS_VXWORKS ) enterMutex();
- rc = closeUnixFile(id);
- if( IS_VXWORKS ) leaveMutex();
- return rc;
-}
+ unixLeaveMutex();
+ }
+ return SQLITE_OK;
+}
+
+#endif /* OS_VXWORKS */
+/*
+** Named semaphore locking is only available on VxWorks.
+**
+*************** End of the named semaphore lock implementation ****************
+******************************************************************************/
+
+
+/******************************************************************************
+*************************** Begin AFP Locking *********************************
+**
+** AFP is the Apple Filing Protocol. AFP is a network filesystem found
+** on Apple Macintosh computers - both OS9 and OSX.
+**
+** Third-party implementations of AFP are available. But this code here
+** only works on OSX.
+*/
+
+#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
+/*
+** The afpLockingContext structure contains all afp lock specific state
+*/
+typedef struct afpLockingContext afpLockingContext;
+struct afpLockingContext {
+ unsigned long long sharedByte;
+ const char *dbPath; /* Name of the open file */
+};
+
+struct ByteRangeLockPB2
+{
+ unsigned long long offset; /* offset to first byte to lock */
+ unsigned long long length; /* nbr of bytes to lock */
+ unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
+ unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
+ unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
+ int fd; /* file desc to assoc this lock with */
+};
+
+#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
+
+/*
+** This is a utility for setting or clearing a bit-range lock on an
+** AFP filesystem.
+**
+** Return SQLITE_OK on success, SQLITE_BUSY on failure.
+*/
+static int afpSetLock(
+ const char *path, /* Name of the file to be locked or unlocked */
+ unixFile *pFile, /* Open file descriptor on path */
+ unsigned long long offset, /* First byte to be locked */
+ unsigned long long length, /* Number of bytes to lock */
+ int setLockFlag /* True to set lock. False to clear lock */
+){
+ struct ByteRangeLockPB2 pb;
+ int err;
+
+ pb.unLockFlag = setLockFlag ? 0 : 1;
+ pb.startEndFlag = 0;
+ pb.offset = offset;
+ pb.length = length;
+ pb.fd = pFile->h;
+
+ OSTRACE6("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
+ (setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
+ offset, length);
+ err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
+ if ( err==-1 ) {
+ int rc;
+ int tErrno = errno;
+ OSTRACE4("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
+ path, tErrno, strerror(tErrno));
+#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
+ rc = SQLITE_BUSY;
+#else
+ rc = sqliteErrorFromPosixError(tErrno,
+ setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
+#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
+ if( IS_LOCK_ERROR(rc) ){
+ pFile->lastErrno = tErrno;
+ }
+ return rc;
+ } else {
+ 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, 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 afpCheckReservedLock(sqlite3_file *id, int *pResOut){
+ int rc = SQLITE_OK;
+ int reserved = 0;
+ unixFile *pFile = (unixFile*)id;
+
+ SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
+
+ assert( pFile );
+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+
+ /* Check if a thread in this process holds such a lock */
+ if( pFile->locktype>SHARED_LOCK ){
+ reserved = 1;
+ }
+
+ /* Otherwise see if some other process holds it.
+ */
+ if( !reserved ){
+ /* lock the RESERVED byte */
+ int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
+ if( SQLITE_OK==lrc ){
+ /* if we succeeded in taking the reserved lock, unlock it to restore
+ ** the original state */
+ lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
+ } else {
+ /* if we failed to get the lock then someone else must have it */
+ reserved = 1;
+ }
+ if( IS_LOCK_ERROR(lrc) ){
+ rc=lrc;
+ }
+ }
+
+ OSTRACE4("TEST WR-LOCK %d %d %d\n", pFile->h, rc, reserved);
+
+ *pResOut = reserved;
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter locktype - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
+static int afpLock(sqlite3_file *id, int locktype){
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile*)id;
+ afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
+
+ assert( pFile );
+ OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h,
+ locktypeName(locktype), locktypeName(pFile->locktype), getpid());
+
+ /* If there is already a lock of this type or more restrictive on the
+ ** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
+ ** unixEnterMutex() hasn't been called yet.
+ */
+ if( pFile->locktype>=locktype ){
+ OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
+ locktypeName(locktype));
+ return SQLITE_OK;
+ }
+
+ /* Make sure the locking sequence is correct
+ */
+ assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
+ assert( locktype!=PENDING_LOCK );
+ assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
+
+ /* This mutex is needed because pFile->pLock is shared across threads
+ */
+ unixEnterMutex();
+
+ /* Make sure the current thread owns the pFile.
+ */
+ rc = transferOwnership(pFile);
+ if( rc!=SQLITE_OK ){
+ unixLeaveMutex();
+ return rc;
+ }
+
+ /* A PENDING lock is needed before acquiring a SHARED lock and before
+ ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will
+ ** be released.
+ */
+ if( locktype==SHARED_LOCK
+ || (locktype==EXCLUSIVE_LOCK && pFile->locktype<PENDING_LOCK)
+ ){
+ int failed;
+ failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
+ if (failed) {
+ rc = failed;
+ goto afp_end_lock;
+ }
+ }
+
+ /* If control gets to this point, then actually go ahead and make
+ ** operating system calls for the specified lock.
+ */
+ if( locktype==SHARED_LOCK ){
+ int lk, lrc1, lrc2, lrc1Errno;
+
+ /* Now get the read-lock SHARED_LOCK */
+ /* note that the quality of the randomness doesn't matter that much */
+ lk = random();
+ context->sharedByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
+ lrc1 = afpSetLock(context->dbPath, pFile,
+ SHARED_FIRST+context->sharedByte, 1, 1);
+ if( IS_LOCK_ERROR(lrc1) ){
+ lrc1Errno = pFile->lastErrno;
+ }
+ /* Drop the temporary PENDING lock */
+ lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
+
+ if( IS_LOCK_ERROR(lrc1) ) {
+ pFile->lastErrno = lrc1Errno;
+ rc = lrc1;
+ goto afp_end_lock;
+ } else if( IS_LOCK_ERROR(lrc2) ){
+ rc = lrc2;
+ goto afp_end_lock;
+ } else if( lrc1 != SQLITE_OK ) {
+ rc = lrc1;
+ } else {
+ pFile->locktype = SHARED_LOCK;
+ pFile->pOpen->nLock++;
+ }
+ }else{
+ /* The request was for a RESERVED or EXCLUSIVE lock. It is
+ ** assumed that there is a SHARED or greater lock on the file
+ ** already.
+ */
+ int failed = 0;
+ assert( 0!=pFile->locktype );
+ if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) {
+ /* Acquire a RESERVED lock */
+ failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
+ }
+ if (!failed && locktype == EXCLUSIVE_LOCK) {
+ /* Acquire an EXCLUSIVE lock */
+
+ /* Remove the shared lock before trying the range. we'll need to
+ ** reestablish the shared lock if we can't get the afpUnlock
+ */
+ if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
+ context->sharedByte, 1, 0)) ){
+ int failed2 = SQLITE_OK;
+ /* now attemmpt to get the exclusive lock range */
+ failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
+ SHARED_SIZE, 1);
+ if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
+ SHARED_FIRST + context->sharedByte, 1, 1)) ){
+ /* Can't reestablish the shared lock. Sqlite can't deal, this is
+ ** a critical I/O error
+ */
+ rc = ((failed & SQLITE_IOERR) == SQLITE_IOERR) ? failed2 :
+ SQLITE_IOERR_LOCK;
+ goto afp_end_lock;
+ }
+ }else{
+ rc = failed;
+ }
+ }
+ if( failed ){
+ rc = failed;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ pFile->locktype = locktype;
+ }else if( locktype==EXCLUSIVE_LOCK ){
+ pFile->locktype = PENDING_LOCK;
+ }
+
+afp_end_lock:
+ unixLeaveMutex();
+ OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype),
+ rc==SQLITE_OK ? "ok" : "failed");
+ return rc;
+}
+
+/*
+** Lower the locking level on file descriptor pFile to locktype. locktype
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
+static int afpUnlock(sqlite3_file *id, int locktype) {
+ int rc = SQLITE_OK;
+ unixFile *pFile = (unixFile*)id;
+ afpLockingContext *pCtx = (afpLockingContext *) pFile->lockingContext;
+
+ 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;
+ }
+ if( CHECK_THREADID(pFile) ){
+ return SQLITE_MISUSE;
+ }
+ unixEnterMutex();
+ if( pFile->locktype>SHARED_LOCK ){
+
+ if( pFile->locktype==EXCLUSIVE_LOCK ){
+ rc = afpSetLock(pCtx->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
+ if( rc==SQLITE_OK && locktype==SHARED_LOCK ){
+ /* only re-establish the shared lock if necessary */
+ int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
+ rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 1);
+ }
+ }
+ if( rc==SQLITE_OK && pFile->locktype>=PENDING_LOCK ){
+ rc = afpSetLock(pCtx->dbPath, pFile, PENDING_BYTE, 1, 0);
+ }
+ if( rc==SQLITE_OK && pFile->locktype>=RESERVED_LOCK ){
+ rc = afpSetLock(pCtx->dbPath, pFile, RESERVED_BYTE, 1, 0);
+ }
+ }else if( locktype==NO_LOCK ){
+ /* clear the shared lock */
+ int sharedLockByte = SHARED_FIRST+pCtx->sharedByte;
+ rc = afpSetLock(pCtx->dbPath, pFile, sharedLockByte, 1, 0);
+ }
+
+ if( rc==SQLITE_OK ){
+ if( locktype==NO_LOCK ){
+ struct unixOpenCnt *pOpen = pFile->pOpen;
+ pOpen->nLock--;
+ assert( pOpen->nLock>=0 );
+ if( pOpen->nLock==0 && pOpen->nPending>0 ){
+ int i;
+ for(i=0; i<pOpen->nPending; i++){
+ if( pOpen->aPending[i] < 0 ) continue;
+ if( close(pOpen->aPending[i]) ){
+ pFile->lastErrno = errno;
+ rc = SQLITE_IOERR_CLOSE;
+ }else{
+ pOpen->aPending[i] = -1;
+ }
+ }
+ if( rc==SQLITE_OK ){
+ sqlite3_free(pOpen->aPending);
+ pOpen->nPending = 0;
+ pOpen->aPending = 0;
+ }
+ }
+ }
+ }
+ unixLeaveMutex();
+ if( rc==SQLITE_OK ) pFile->locktype = locktype;
+ return rc;
+}
+
+/*
+** Close a file & cleanup AFP specific locking context
+*/
+static int afpClose(sqlite3_file *id) {
+ if( id ){
+ unixFile *pFile = (unixFile*)id;
+ afpUnlock(id, NO_LOCK);
+ unixEnterMutex();
+ if( pFile->pOpen && pFile->pOpen->nLock ){
+ /* If there are outstanding locks, do not actually close the file just
+ ** yet because that would clear those locks. Instead, add the file
+ ** descriptor to pOpen->aPending. It will be automatically closed when
+ ** the last lock is cleared.
+ */
+ int *aNew;
+ struct unixOpenCnt *pOpen = pFile->pOpen;
+ aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
+ if( aNew==0 ){
+ /* If a malloc fails, just leak the file descriptor */
+ }else{
+ pOpen->aPending = aNew;
+ pOpen->aPending[pOpen->nPending] = pFile->h;
+ pOpen->nPending++;
+ pFile->h = -1;
+ }
+ }
+ releaseOpenCnt(pFile->pOpen);
+ sqlite3_free(pFile->lockingContext);
+ closeUnixFile(id);
+ unixLeaveMutex();
+ }
+ return SQLITE_OK;
+}
+
+#endif /* defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE */
+/*
+** The code above is the AFP lock implementation. The code is specific
+** to MacOSX and does not work on other unix platforms. No alternative
+** is available. If you don't compile for a mac, then the "unix-afp"
+** VFS is not available.
+**
+********************* End of the AFP lock implementation **********************
+******************************************************************************/
+
+
+/******************************************************************************
+**************** Non-locking sqlite3_file methods *****************************
+**
+** The next division contains implementations for all methods of the
+** sqlite3_file object other than the locking methods. The locking
+** methods were defined in divisions above (one locking method per
+** division). Those methods that are common to all locking modes
+** are gather together into this division.
+*/
+
+/*
+** Seek to the offset passed as the second argument, then read cnt
+** bytes into pBuf. Return the number of bytes actually read.
+**
+** NB: If you define USE_PREAD or USE_PREAD64, then it might also
+** be necessary to define _XOPEN_SOURCE to be 500. This varies from
+** one system to another. Since SQLite does not define USE_PREAD
+** any any form by default, we will not attempt to define _XOPEN_SOURCE.
+** See tickets #2741 and #2681.
+**
+** To avoid stomping the errno value on a failed read the lastErrno value
+** is set before returning.
+*/
+static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
+ int got;
+ i64 newOffset;
+ TIMER_START;
+#if defined(USE_PREAD)
+ got = pread(id->h, pBuf, cnt, offset);
+ SimulateIOError( got = -1 );
+#elif defined(USE_PREAD64)
+ got = pread64(id->h, pBuf, cnt, offset);
+ SimulateIOError( got = -1 );
+#else
+ newOffset = lseek(id->h, offset, SEEK_SET);
+ SimulateIOError( newOffset-- );
+ if( newOffset!=offset ){
+ if( newOffset == -1 ){
+ ((unixFile*)id)->lastErrno = errno;
+ }else{
+ ((unixFile*)id)->lastErrno = 0;
+ }
+ return -1;
+ }
+ got = read(id->h, pBuf, cnt);
+#endif
+ TIMER_END;
+ if( got<0 ){
+ ((unixFile*)id)->lastErrno = errno;
+ }
+ OSTRACE5("READ %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);
+ return got;
+}
+
+/*
+** Read data from a file into a buffer. Return SQLITE_OK if all
+** bytes were read successfully and SQLITE_IOERR if anything goes
+** wrong.
+*/
+static int unixRead(
+ sqlite3_file *id,
+ void *pBuf,
+ int amt,
+ sqlite3_int64 offset
+){
+ int got;
+ assert( id );
+ got = seekAndRead((unixFile*)id, offset, pBuf, amt);
+ if( got==amt ){
+ return SQLITE_OK;
+ }else if( got<0 ){
+ /* lastErrno set by seekAndRead */
+ return SQLITE_IOERR_READ;
+ }else{
+ ((unixFile*)id)->lastErrno = 0; /* not a system error */
+ /* Unread parts of the buffer must be zero-filled */
+ memset(&((char*)pBuf)[got], 0, amt-got);
+ return SQLITE_IOERR_SHORT_READ;
+ }
+}
+
+/*
+** Seek to the offset in id->offset then read cnt bytes into pBuf.
+** Return the number of bytes actually read. Update the offset.
+**
+** To avoid stomping the errno value on a failed write the lastErrno value
+** is set before returning.
+*/
+static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
+ int got;
+ i64 newOffset;
+ TIMER_START;
+#if defined(USE_PREAD)
+ got = pwrite(id->h, pBuf, cnt, offset);
+#elif defined(USE_PREAD64)
+ got = pwrite64(id->h, pBuf, cnt, offset);
+#else
+ newOffset = lseek(id->h, offset, SEEK_SET);
+ if( newOffset!=offset ){
+ if( newOffset == -1 ){
+ ((unixFile*)id)->lastErrno = errno;
+ }else{
+ ((unixFile*)id)->lastErrno = 0;
+ }
+ return -1;
+ }
+ got = write(id->h, pBuf, cnt);
+#endif
+ TIMER_END;
+ if( got<0 ){
+ ((unixFile*)id)->lastErrno = errno;
+ }
+
+ OSTRACE5("WRITE %-3d %5d %7lld %llu\n", id->h, got, offset, TIMER_ELAPSED);
+ return got;
+}
+
+
+/*
+** Write data from a buffer into a file. Return SQLITE_OK on success
+** or some other error code on failure.
+*/
+static int unixWrite(
+ sqlite3_file *id,
+ const void *pBuf,
+ int amt,
+ sqlite3_int64 offset
+){
+ int wrote = 0;
+ assert( id );
+ assert( amt>0 );
+ while( amt>0 && (wrote = seekAndWrite((unixFile*)id, offset, pBuf, amt))>0 ){
+ amt -= wrote;
+ offset += wrote;
+ pBuf = &((char*)pBuf)[wrote];
+ }
+ SimulateIOError(( wrote=(-1), amt=1 ));
+ SimulateDiskfullError(( wrote=0, amt=1 ));
+ if( amt>0 ){
+ if( wrote<0 ){
+ /* lastErrno set by seekAndWrite */
+ return SQLITE_IOERR_WRITE;
+ }else{
+ ((unixFile*)id)->lastErrno = 0; /* not a system error */
+ return SQLITE_FULL;
+ }
+ }
+ return SQLITE_OK;
+}
+
+#ifdef SQLITE_TEST
+/*
+** Count the number of fullsyncs and normal syncs. This is used to test
+** that syncs and fullsyncs are occurring at the right times.
+*/
+SQLITE_API int sqlite3_sync_count = 0;
+SQLITE_API int sqlite3_fullsync_count = 0;
+#endif
+
+/*
+** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined.
+** Otherwise use fsync() in its place.
+*/
+#ifndef HAVE_FDATASYNC
+# define fdatasync fsync
+#endif
+
+/*
+** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not
+** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently
+** only available on Mac OS X. But that could change.
+*/
+#ifdef F_FULLFSYNC
+# define HAVE_FULLFSYNC 1
+#else
+# define HAVE_FULLFSYNC 0
+#endif
+
+
+/*
+** The fsync() system call does not work as advertised on many
+** unix systems. The following procedure is an attempt to make
+** it work better.
+**
+** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful
+** for testing when we want to run through the test suite quickly.
+** You are strongly advised *not* to deploy with SQLITE_NO_SYNC
+** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash
+** or power failure will likely corrupt the database file.
+*/
+static int full_fsync(int fd, int fullSync, int dataOnly){
+ int rc;
+
+ /* The following "ifdef/elif/else/" block has the same structure as
+ ** the one below. It is replicated here solely to avoid cluttering
+ ** up the real code with the UNUSED_PARAMETER() macros.
+ */
+#ifdef SQLITE_NO_SYNC
+ UNUSED_PARAMETER(fd);
+ UNUSED_PARAMETER(fullSync);
+ UNUSED_PARAMETER(dataOnly);
+#elif HAVE_FULLFSYNC
+ UNUSED_PARAMETER(dataOnly);
+#else
+ UNUSED_PARAMETER(fullSync);
+#endif
+
+ /* Record the number of times that we do a normal fsync() and
+ ** FULLSYNC. This is used during testing to verify that this procedure
+ ** gets called with the correct arguments.
+ */
+#ifdef SQLITE_TEST
+ if( fullSync ) sqlite3_fullsync_count++;
+ sqlite3_sync_count++;
+#endif
+
+ /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
+ ** no-op
+ */
+#ifdef SQLITE_NO_SYNC
+ rc = SQLITE_OK;
+#elif HAVE_FULLFSYNC
+ if( fullSync ){
+ rc = fcntl(fd, F_FULLFSYNC, 0);
+ }else{
+ rc = 1;
+ }
+ /* If the FULLFSYNC failed, fall back to attempting an fsync().
+ ** It shouldn't be possible for fullfsync to fail on the local
+ ** file system (on OSX), so failure indicates that FULLFSYNC
+ ** isn't supported for this file system. So, attempt an fsync
+ ** and (for now) ignore the overhead of a superfluous fcntl call.
+ ** It'd be better to detect fullfsync support once and avoid
+ ** the fcntl call every time sync is called.
+ */
+ if( rc ) rc = fsync(fd);
+
+#else
+ if( dataOnly ){
+ rc = fdatasync(fd);
+ if( OS_VXWORKS && rc==-1 && errno==ENOTSUP ){
+ rc = fsync(fd);
+ }
+ }else{
+ rc = fsync(fd);
+ }
+#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
+
+ if( OS_VXWORKS && rc!= -1 ){
+ rc = 0;
+ }
+ return rc;
+}
+
+/*
+** Make sure all writes to a particular file are committed to disk.
+**
+** If dataOnly==0 then both the file itself and its metadata (file
+** size, access time, etc) are synced. If dataOnly!=0 then only the
+** file data is synced.
+**
+** Under Unix, also make sure that the directory entry for the file
+** has been created by fsync-ing the directory that contains the file.
+** If we do not do this and we encounter a power failure, the directory
+** entry for the journal might not exist after we reboot. The next
+** SQLite to access the file will not know that the journal exists (because
+** the directory entry for the journal was never created) and the transaction
+** will not roll back - possibly leading to database corruption.
+*/
+static int unixSync(sqlite3_file *id, int flags){
+ int rc;
+ unixFile *pFile = (unixFile*)id;
+
+ int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
+ int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
+
+ /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
+ assert((flags&0x0F)==SQLITE_SYNC_NORMAL
+ || (flags&0x0F)==SQLITE_SYNC_FULL
+ );
+
+ /* Unix cannot, but some systems may return SQLITE_FULL from here. This
+ ** line is to test that doing so does not cause any problems.
+ */
+ SimulateDiskfullError( return SQLITE_FULL );
+
+ assert( pFile );
+ OSTRACE2("SYNC %-3d\n", pFile->h);
+ rc = full_fsync(pFile->h, isFullsync, isDataOnly);
+ SimulateIOError( rc=1 );
+ if( rc ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR_FSYNC;
+ }
+ if( pFile->dirfd>=0 ){
+ int err;
+ OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd,
+ HAVE_FULLFSYNC, isFullsync);
+#ifndef SQLITE_DISABLE_DIRSYNC
+ /* The directory sync is only attempted if full_fsync is
+ ** turned off or unavailable. If a full_fsync occurred above,
+ ** then the directory sync is superfluous.
+ */
+ if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
+ /*
+ ** We have received multiple reports of fsync() returning
+ ** errors when applied to directories on certain file systems.
+ ** A failed directory sync is not a big deal. So it seems
+ ** better to ignore the error. Ticket #1657
+ */
+ /* pFile->lastErrno = errno; */
+ /* return SQLITE_IOERR; */
+ }
+#endif
+ err = close(pFile->dirfd); /* Only need to sync once, so close the */
+ if( err==0 ){ /* directory when we are done */
+ pFile->dirfd = -1;
+ }else{
+ pFile->lastErrno = errno;
+ rc = SQLITE_IOERR_DIR_CLOSE;
+ }
+ }
+ return rc;
+}
+
+/*
+** Truncate an open file to a specified size
+*/
+static int unixTruncate(sqlite3_file *id, i64 nByte){
+ int rc;
+ assert( id );
+ SimulateIOError( return SQLITE_IOERR_TRUNCATE );
+ rc = ftruncate(((unixFile*)id)->h, (off_t)nByte);
+ if( rc ){
+ ((unixFile*)id)->lastErrno = errno;
+ return SQLITE_IOERR_TRUNCATE;
+ }else{
+ return SQLITE_OK;
+ }
+}
+
+/*
+** Determine the current size of a file in bytes
+*/
+static int unixFileSize(sqlite3_file *id, i64 *pSize){
+ int rc;
+ struct stat buf;
+ assert( id );
+ rc = fstat(((unixFile*)id)->h, &buf);
+ SimulateIOError( rc=1 );
+ if( rc!=0 ){
+ ((unixFile*)id)->lastErrno = errno;
+ return SQLITE_IOERR_FSTAT;
+ }
+ *pSize = buf.st_size;
+
+ /* When opening a zero-size database, the findLockInfo() procedure
+ ** writes a single byte into that file in order to work around a bug
+ ** in the OS-X msdos filesystem. In order to avoid problems with upper
+ ** layers, we need to report this file size as zero even though it is
+ ** really 1. Ticket #3260.
+ */
+ if( *pSize==1 ) *pSize = 0;
+
+
+ return SQLITE_OK;
+}
+
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
+/*
+** Handler for proxy-locking file-control verbs. Defined below in the
+** proxying locking division.
+*/
+static int proxyFileControl(sqlite3_file*,int,void*);
+#endif
/*
** Information and control of an open file handle.
@@ -24236,8 +24581,18 @@
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = ((unixFile*)id)->locktype;
return SQLITE_OK;
}
+ case SQLITE_LAST_ERRNO: {
+ *(int*)pArg = ((unixFile*)id)->lastErrno;
+ return SQLITE_OK;
+ }
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
+ case SQLITE_SET_LOCKPROXYFILE:
+ case SQLITE_GET_LOCKPROXYFILE: {
+ return proxyFileControl(id,op,pArg);
+ }
+#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__) */
}
return SQLITE_ERROR;
}
@@ -24264,227 +24619,370 @@
return 0;
}
/*
-** Initialize the contents of the unixFile structure pointed to by pId.
-**
-** When locking extensions are enabled, the filepath and locking style
-** are needed to determine the unixFile pMethod to use for locking operations.
-** The locking-style specific lockingContext data structure is created
-** and assigned here also.
-*/
-static int fillInUnixFile(
- sqlite3_vfs *pVfs, /* Pointer to vfs object */
- int h, /* Open file descriptor of file being opened */
- int dirfd, /* Directory file descriptor */
- sqlite3_file *pId, /* Write to the unixFile structure here */
- const char *zFilename, /* Name of the file being opened */
- int noLock, /* Omit locking if true */
- int isDelete /* Delete on close if true */
-){
- int eLockingStyle;
- unixFile *pNew = (unixFile *)pId;
- int rc = SQLITE_OK;
-
- /* Macro to define the static contents of an sqlite3_io_methods
- ** structure for a unix backend file. Different locking methods
- ** require different functions for the xClose, xLock, xUnlock and
- ** xCheckReservedLock methods.
- */
- #define IOMETHODS(xClose, xLock, xUnlock, xCheckReservedLock) { \
- 1, /* iVersion */ \
- xClose, /* xClose */ \
- unixRead, /* xRead */ \
- unixWrite, /* xWrite */ \
- unixTruncate, /* xTruncate */ \
- unixSync, /* xSync */ \
- unixFileSize, /* xFileSize */ \
- xLock, /* xLock */ \
- xUnlock, /* xUnlock */ \
- xCheckReservedLock, /* xCheckReservedLock */ \
- unixFileControl, /* xFileControl */ \
- unixSectorSize, /* xSectorSize */ \
- unixDeviceCharacteristics /* xDeviceCapabilities */ \
- }
- static sqlite3_io_methods aIoMethod[] = {
- IOMETHODS(unixClose, unixLock, unixUnlock, unixCheckReservedLock)
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
+** Here ends the implementation of all sqlite3_file methods.
+**
+********************** End sqlite3_file Methods *******************************
+******************************************************************************/
+
+/*
+** This division contains definitions of sqlite3_io_methods objects that
+** implement various file locking strategies. It also contains definitions
+** of "finder" functions. A finder-function is used to locate the appropriate
+** sqlite3_io_methods object for a particular database file. The pAppData
+** field of the sqlite3_vfs VFS objects are initialized to be pointers to
+** the correct finder-function for that VFS.
+**
+** Most finder functions return a pointer to a fixed sqlite3_io_methods
+** object. The only interesting finder-function is autolockIoFinder, which
+** looks at the filesystem type and tries to guess the best locking
+** strategy from that.
+**
+** For finder-funtion F, two objects are created:
+**
+** (1) The real finder-function named "FImpt()".
+**
+** (2) A constant pointer to this functio named just "F".
+**
+**
+** A pointer to the F pointer is used as the pAppData value for VFS
+** objects. We have to do this instead of letting pAppData point
+** directly at the finder-function since C90 rules prevent a void*
+** from be cast into a function pointer.
+**
+**
+** Each instance of this macro generates two objects:
+**
+** * A constant sqlite3_io_methods object call METHOD that has locking
+** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
+**
+** * An I/O method finder function called FINDER that returns a pointer
+** to the METHOD object in the previous bullet.
+*/
+#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK) \
+static const sqlite3_io_methods METHOD = { \
+ 1, /* iVersion */ \
+ CLOSE, /* xClose */ \
+ unixRead, /* xRead */ \
+ unixWrite, /* xWrite */ \
+ unixTruncate, /* xTruncate */ \
+ unixSync, /* xSync */ \
+ unixFileSize, /* xFileSize */ \
+ LOCK, /* xLock */ \
+ UNLOCK, /* xUnlock */ \
+ CKLOCK, /* xCheckReservedLock */ \
+ unixFileControl, /* xFileControl */ \
+ unixSectorSize, /* xSectorSize */ \
+ unixDeviceCharacteristics /* xDeviceCapabilities */ \
+}; \
+static const sqlite3_io_methods *FINDER##Impl(const char *z, int h){ \
+ UNUSED_PARAMETER(z); UNUSED_PARAMETER(h); \
+ return &METHOD; \
+} \
+static const sqlite3_io_methods *(*const FINDER)(const char*,int) \
+ = FINDER##Impl;
+
+/*
+** Here are all of the sqlite3_io_methods objects for each of the
+** locking strategies. Functions that return pointers to these methods
+** are also created.
+*/
+IOMETHODS(
+ posixIoFinder, /* Finder function name */
+ posixIoMethods, /* sqlite3_io_methods object name */
+ unixClose, /* xClose method */
+ unixLock, /* xLock method */
+ unixUnlock, /* xUnlock method */
+ unixCheckReservedLock /* xCheckReservedLock method */
+)
+IOMETHODS(
+ nolockIoFinder, /* Finder function name */
+ nolockIoMethods, /* sqlite3_io_methods object name */
+ nolockClose, /* xClose method */
+ nolockLock, /* xLock method */
+ nolockUnlock, /* xUnlock method */
+ nolockCheckReservedLock /* xCheckReservedLock method */
+)
+IOMETHODS(
+ dotlockIoFinder, /* Finder function name */
+ dotlockIoMethods, /* sqlite3_io_methods object name */
+ dotlockClose, /* xClose method */
+ dotlockLock, /* xLock method */
+ dotlockUnlock, /* xUnlock method */
+ dotlockCheckReservedLock /* xCheckReservedLock method */
+)
+
#if SQLITE_ENABLE_LOCKING_STYLE
- ,IOMETHODS(dotlockClose, dotlockLock, dotlockUnlock,dotlockCheckReservedLock)
-#if IS_VXWORKS
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
- ,IOMETHODS(namedsemClose, namedsemLock, namedsemUnlock, namedsemCheckReservedLock)
-#else
- ,IOMETHODS(flockClose, flockLock, flockUnlock, flockCheckReservedLock)
- ,IOMETHODS(afpClose, afpLock, afpUnlock, afpCheckReservedLock)
- ,IOMETHODS(nolockClose, nolockLock, nolockUnlock, nolockCheckReservedLock)
-#endif
-#endif
- };
- /* The order of the IOMETHODS macros above is important. It must be the
- ** same order as the LOCKING_STYLE numbers
- */
- assert(LOCKING_STYLE_POSIX==1);
- assert(LOCKING_STYLE_NONE==2);
- assert(LOCKING_STYLE_DOTFILE==3);
- assert(LOCKING_STYLE_FLOCK==4);
- assert(LOCKING_STYLE_AFP==5);
- assert(LOCKING_STYLE_NAMEDSEM==6);
+IOMETHODS(
+ flockIoFinder, /* Finder function name */
+ flockIoMethods, /* sqlite3_io_methods object name */
+ flockClose, /* xClose method */
+ flockLock, /* xLock method */
+ flockUnlock, /* xUnlock method */
+ flockCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+#if OS_VXWORKS
+IOMETHODS(
+ semIoFinder, /* Finder function name */
+ semIoMethods, /* sqlite3_io_methods object name */
+ semClose, /* xClose method */
+ semLock, /* xLock method */
+ semUnlock, /* xUnlock method */
+ semCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
+IOMETHODS(
+ afpIoFinder, /* Finder function name */
+ afpIoMethods, /* sqlite3_io_methods object name */
+ afpClose, /* xClose method */
+ afpLock, /* xLock method */
+ afpUnlock, /* xUnlock method */
+ afpCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+/*
+** The proxy locking method is a "super-method" in the sense that it
+** opens secondary file descriptors for the conch and lock files and
+** it uses proxy, dot-file, AFP, and flock() locking methods on those
+** secondary files. For this reason, the division that implements
+** proxy locking is located much further down in the file. But we need
+** to go ahead and define the sqlite3_io_methods and finder function
+** for proxy locking here. So we forward declare the I/O methods.
+*/
+#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
+static int proxyClose(sqlite3_file*);
+static int proxyLock(sqlite3_file*, int);
+static int proxyUnlock(sqlite3_file*, int);
+static int proxyCheckReservedLock(sqlite3_file*, int*);
+IOMETHODS(
+ proxyIoFinder, /* Finder function name */
+ proxyIoMethods, /* sqlite3_io_methods object name */
+ proxyClose, /* xClose method */
+ proxyLock, /* xLock method */
+ proxyUnlock, /* xUnlock method */
+ proxyCheckReservedLock /* xCheckReservedLock method */
+)
+#endif
+
+
+#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
+/*
+** This "finder" function attempts to determine the best locking strategy
+** for the database file "filePath". It then returns the sqlite3_io_methods
+** object that implements that strategy.
+**
+** This is for MacOSX only.
+*/
+static const sqlite3_io_methods *autolockIoFinderImpl(
+ const char *filePath, /* name of the database file */
+ int fd /* file descriptor open on the database file */
+){
+ static const struct Mapping {
+ const char *zFilesystem; /* Filesystem type name */
+ const sqlite3_io_methods *pMethods; /* Appropriate locking method */
+ } aMap[] = {
+ { "hfs", &posixIoMethods },
+ { "ufs", &posixIoMethods },
+ { "afpfs", &afpIoMethods },
+#ifdef SQLITE_ENABLE_AFP_LOCKING_SMB
+ { "smbfs", &afpIoMethods },
+#else
+ { "smbfs", &flockIoMethods },
+#endif
+ { "webdav", &nolockIoMethods },
+ { 0, 0 }
+ };
+ int i;
+ struct statfs fsInfo;
+ struct flock lockInfo;
+
+ if( !filePath ){
+ /* If filePath==NULL that means we are dealing with a transient file
+ ** that does not need to be locked. */
+ return &nolockIoMethods;
+ }
+ if( statfs(filePath, &fsInfo) != -1 ){
+ if( fsInfo.f_flags & MNT_RDONLY ){
+ return &nolockIoMethods;
+ }
+ for(i=0; aMap[i].zFilesystem; i++){
+ if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
+ return aMap[i].pMethods;
+ }
+ }
+ }
+
+ /* Default case. Handles, amongst others, "nfs".
+ ** Test byte-range lock using fcntl(). If the call succeeds,
+ ** assume that the file-system supports POSIX style locks.
+ */
+ lockInfo.l_len = 1;
+ lockInfo.l_start = 0;
+ lockInfo.l_whence = SEEK_SET;
+ lockInfo.l_type = F_RDLCK;
+ if( fcntl(fd, F_GETLK, &lockInfo)!=-1 ) {
+ return &posixIoMethods;
+ }else{
+ return &dotlockIoMethods;
+ }
+}
+static const sqlite3_io_methods (*const autolockIoFinder)(const char*,int)
+ = autolockIoFinderImpl;
+
+#endif /* defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE */
+
+/*
+** An abstract type for a pointer to a IO method finder function:
+*/
+typedef const sqlite3_io_methods *(*finder_type)(const char*,int);
+
+
+/****************************************************************************
+**************************** sqlite3_vfs methods ****************************
+**
+** This division contains the implementation of methods on the
+** sqlite3_vfs object.
+*/
+
+/*
+** Initialize the contents of the unixFile structure pointed to by pId.
+*/
+static int fillInUnixFile(
+ sqlite3_vfs *pVfs, /* Pointer to vfs object */
+ int h, /* Open file descriptor of file being opened */
+ int dirfd, /* Directory file descriptor */
+ sqlite3_file *pId, /* Write to the unixFile structure here */
+ const char *zFilename, /* Name of the file being opened */
+ int noLock, /* Omit locking if true */
+ int isDelete /* Delete on close if true */
+){
+ const sqlite3_io_methods *pLockingStyle;
+ unixFile *pNew = (unixFile *)pId;
+ int rc = SQLITE_OK;
assert( pNew->pLock==NULL );
assert( pNew->pOpen==NULL );
- /* Parameter isDelete is only used on vxworks. Parameter pVfs is only
- ** used if ENABLE_LOCKING_STYLE is defined. Express this explicitly
- ** here to prevent compiler warnings about unused parameters.
- */
- if( !IS_VXWORKS ) UNUSED_PARAMETER(isDelete);
- if( !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(pVfs);
- if( !IS_VXWORKS && !SQLITE_ENABLE_LOCKING_STYLE ) UNUSED_PARAMETER(zFilename);
+ /* Parameter isDelete is only used on vxworks.
+ ** Express this explicitly here to prevent compiler warnings
+ ** about unused parameters.
+ */
+#if !OS_VXWORKS
+ UNUSED_PARAMETER(isDelete);
+#endif
OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->h = h;
pNew->dirfd = dirfd;
SET_THREADID(pNew);
-#if IS_VXWORKS
- {
- HashElem *pElem;
- char *zRealname = vxrealpath(zFilename, 1);
- int n;
- pNew->zRealpath = 0;
- if( !zRealname ){
- rc = SQLITE_NOMEM;
- eLockingStyle = LOCKING_STYLE_NONE;
- }else{
- n = strlen(zRealname) + 1;
- enterMutex();
- pElem = sqlite3HashFindElem(&nameHash, zRealname, n);
- if( pElem ){
- long cnt = (long)pElem->data;
- cnt++;
- pNew->zRealpath = pElem->pKey;
- pElem->data = (void*)cnt;
- }else{
- if( sqlite3HashInsert(&nameHash, zRealname, n, (void*)1)==0 ){
- pElem = sqlite3HashFindElem(&nameHash, zRealname, n);
- if( pElem ){
- pNew->zRealpath = pElem->pKey;
- }else{
- sqlite3HashInsert(&nameHash, zRealname, n, 0);
- rc = SQLITE_NOMEM;
- eLockingStyle = LOCKING_STYLE_NONE;
- }
- }
- }
- leaveMutex();
- sqlite3_free(zRealname);
- }
+#if OS_VXWORKS
+ pNew->pId = vxworksFindFileId(zFilename);
+ if( pNew->pId==0 ){
+ noLock = 1;
+ rc = SQLITE_NOMEM;
}
#endif
if( noLock ){
- eLockingStyle = LOCKING_STYLE_NONE;
- }else{
- eLockingStyle = detectLockingStyle(pVfs, zFilename, h);
- }
-
- switch( eLockingStyle ){
-
- case LOCKING_STYLE_POSIX: {
- enterMutex();
-#if IS_VXWORKS
- rc = findLockInfo(h, pNew->zRealpath, &pNew->pLock, &pNew->pOpen);
-#else
- rc = findLockInfo(h, &pNew->pLock, &pNew->pOpen);
-#endif
- leaveMutex();
- break;
- }
-
+ pLockingStyle = &nolockIoMethods;
+ }else{
+ pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, h);
#if SQLITE_ENABLE_LOCKING_STYLE
-
-#if !IS_VXWORKS
- case LOCKING_STYLE_AFP: {
- /* AFP locking uses the file path so it needs to be included in
- ** the afpLockingContext.
- */
- afpLockingContext *pCtx;
- pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
- if( pCtx==0 ){
- rc = SQLITE_NOMEM;
- }else{
- /* NB: zFilename exists and remains valid until the file is closed
- ** according to requirement F11141. So we do not need to make a
- ** copy of the filename. */
- pCtx->filePath = zFilename;
- srandomdev();
- }
- break;
- }
-#endif
-
- case LOCKING_STYLE_DOTFILE: {
- /* Dotfile locking uses the file path so it needs to be included in
- ** the dotlockLockingContext
- */
- char *zLockFile;
- int nFilename;
- nFilename = strlen(zFilename) + 6;
- zLockFile = (char *)sqlite3_malloc(nFilename);
- if( zLockFile==0 ){
+ /* Cache zFilename in the locking context (AFP and dotlock override) for
+ ** proxyLock activation is possible (remote proxy is based on db name)
+ ** zFilename remains valid until file is closed, to support */
+ pNew->lockingContext = (void*)zFilename;
+#endif
+ }
+
+ if( pLockingStyle == &posixIoMethods ){
+ unixEnterMutex();
+ rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
+ unixLeaveMutex();
+ }
+
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
+ else if( pLockingStyle == &afpIoMethods ){
+ /* AFP locking uses the file path so it needs to be included in
+ ** the afpLockingContext.
+ */
+ afpLockingContext *pCtx;
+ pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
+ if( pCtx==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ /* NB: zFilename exists and remains valid until the file is closed
+ ** according to requirement F11141. So we do not need to make a
+ ** copy of the filename. */
+ pCtx->dbPath = zFilename;
+ srandomdev();
+ unixEnterMutex();
+ rc = findLockInfo(pNew, NULL, &pNew->pOpen);
+ unixLeaveMutex();
+ }
+ }
+#endif
+
+ else if( pLockingStyle == &dotlockIoMethods ){
+ /* Dotfile locking uses the file path so it needs to be included in
+ ** the dotlockLockingContext
+ */
+ char *zLockFile;
+ int nFilename;
+ nFilename = (int)strlen(zFilename) + 6;
+ zLockFile = (char *)sqlite3_malloc(nFilename);
+ if( zLockFile==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
+ }
+ pNew->lockingContext = zLockFile;
+ }
+
+#if OS_VXWORKS
+ else if( pLockingStyle == &semIoMethods ){
+ /* Named semaphore locking uses the file path so it needs to be
+ ** included in the semLockingContext
+ */
+ unixEnterMutex();
+ rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
+ if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
+ char *zSemName = pNew->pOpen->aSemName;
+ int n;
+ sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem",
+ pNew->pId->zCanonicalName);
+ for( n=0; zSemName[n]; n++ )
+ if( zSemName[n]=='/' ) zSemName[n] = '_';
+ pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
+ if( pNew->pOpen->pSem == SEM_FAILED ){
rc = SQLITE_NOMEM;
- }else{
- sqlite3_snprintf(nFilename, zLockFile, "%s.lock", zFilename);
- }
- pNew->lockingContext = zLockFile;
- break;
- }
-
-#if IS_VXWORKS
- case LOCKING_STYLE_NAMEDSEM: {
- /* Named semaphore locking uses the file path so it needs to be
- ** included in the namedsemLockingContext
- */
- enterMutex();
- rc = findLockInfo(h, pNew->zRealpath, &pNew->pLock, &pNew->pOpen);
- if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
- char *zSemName = pNew->pOpen->aSemName;
- int n;
- sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", pNew->zRealpath);
- for( n=0; zSemName[n]; n++ )
- if( zSemName[n]=='/' ) zSemName[n] = '_';
- pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
- if( pNew->pOpen->pSem == SEM_FAILED ){
- rc = SQLITE_NOMEM;
- pNew->pOpen->aSemName[0] = '\0';
- }
- }
- leaveMutex();
- break;
- }
-#endif
-
- case LOCKING_STYLE_FLOCK:
- case LOCKING_STYLE_NONE:
- break;
-#endif
- }
+ pNew->pOpen->aSemName[0] = '\0';
+ }
+ }
+ unixLeaveMutex();
+ }
+#endif
pNew->lastErrno = 0;
-#if IS_VXWORKS
+#if OS_VXWORKS
if( rc!=SQLITE_OK ){
unlink(zFilename);
isDelete = 0;
}
pNew->isDelete = isDelete;
#endif
if( rc!=SQLITE_OK ){
- if( dirfd>=0 ) close(dirfd);
+ if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */
close(h);
}else{
- pNew->pMethod = &aIoMethod[eLockingStyle-1];
+ pNew->pMethod = pLockingStyle;
OpenCounter(+1);
}
return rc;
}
@@ -24504,9 +25002,9 @@
int fd = -1;
char zDirname[MAX_PATHNAME+1];
sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
- for(ii=strlen(zDirname); ii>=0 && zDirname[ii]!='/'; ii--);
+ for(ii=(int)strlen(zDirname); ii>=0 && zDirname[ii]!='/'; ii--);
if( ii>0 ){
zDirname[ii] = '\0';
fd = open(zDirname, O_RDONLY|O_BINARY, 0);
if( fd>=0 ){
@@ -24527,8 +25025,9 @@
*/
static int getTempname(int nBuf, char *zBuf){
static const char *azDirs[] = {
0,
+ 0,
"/var/tmp",
"/usr/tmp",
"/tmp",
".",
@@ -24536,9 +25035,9 @@
static const unsigned char zChars[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
- int i, j;
+ unsigned int i, j;
struct stat buf;
const char *zDir = ".";
/* It's odd to simulate an io-error here, but really this is just
@@ -24547,9 +25046,13 @@
*/
SimulateIOError( return SQLITE_IOERR );
azDirs[0] = sqlite3_temp_directory;
- for(i=0; i<ArraySize(azDirs); i++){
+ if (NULL == azDirs[1]) {
+ azDirs[1] = getenv("TMPDIR");
+ }
+
+ for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); i++){
if( azDirs[i]==0 ) continue;
if( stat(azDirs[i], &buf) ) continue;
if( !S_ISDIR(buf.st_mode) ) continue;
if( access(azDirs[i], 07) ) continue;
@@ -24565,9 +25068,9 @@
}
do{
sqlite3_snprintf(nBuf-17, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX, zDir);
- j = strlen(zBuf);
+ j = (int)strlen(zBuf);
sqlite3_randomness(15, &zBuf[j]);
for(i=0; i<15; i++, j++){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
@@ -24574,8 +25077,17 @@
zBuf[j] = 0;
}while( access(zBuf,0)==0 );
return SQLITE_OK;
}
+
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
+/*
+** Routine to transform a unixFile into a proxy-locking unixFile.
+** Implementation in the proxy-lock division, but used by unixOpen()
+** if SQLITE_PREFER_PROXY_LOCKING is defined.
+*/
+static int proxyTransformUnixFile(unixFile*, const char*);
+#endif
/*
** Open the file zPath.
@@ -24599,19 +25111,20 @@
** interface, add the DELETEONCLOSE flag to those specified above for
** OpenExclusive().
*/
static int unixOpen(
- sqlite3_vfs *pVfs,
- const char *zPath,
- sqlite3_file *pFile,
- int flags,
- int *pOutFlags
+ sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */
+ const char *zPath, /* Pathname of file to be opened */
+ sqlite3_file *pFile, /* The file descriptor to be filled in */
+ int flags, /* Input flags to control the opening */
+ int *pOutFlags /* Output flags returned to SQLite core */
){
int fd = 0; /* File descriptor returned by open() */
int dirfd = -1; /* Directory file descriptor */
- int oflags = 0; /* Flags to pass to open() */
+ int openFlags = 0; /* Flags to pass to open() */
int eType = flags&0xFFFFFF00; /* Type of file to open */
int noLock; /* True to omit locking primitives */
+ int rc = SQLITE_OK;
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
@@ -24660,9 +25173,8 @@
memset(pFile, 0, sizeof(unixFile));
if( !zName ){
- int rc;
assert(isDelete && !isOpenDirectory);
rc = getTempname(MAX_PATHNAME+1, zTmpname);
if( rc!=SQLITE_OK ){
return rc;
@@ -24669,16 +25181,16 @@
}
zName = zTmpname;
}
- if( isReadonly ) oflags |= O_RDONLY;
- if( isReadWrite ) oflags |= O_RDWR;
- if( isCreate ) oflags |= O_CREAT;
- if( isExclusive ) oflags |= (O_EXCL|O_NOFOLLOW);
- oflags |= (O_LARGEFILE|O_BINARY);
-
- fd = open(zName, oflags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS);
- OSTRACE4("OPENX %-3d %s 0%o\n", fd, zName, oflags);
+ if( isReadonly ) openFlags |= O_RDONLY;
+ if( isReadWrite ) openFlags |= O_RDWR;
+ if( isCreate ) openFlags |= O_CREAT;
+ if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
+ openFlags |= (O_LARGEFILE|O_BINARY);
+
+ fd = open(zName, openFlags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS);
+ OSTRACE4("OPENX %-3d %s 0%o\n", fd, zName, openFlags);
if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
/* Failed to open the file for read/write access. Try read-only. */
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
flags |= SQLITE_OPEN_READONLY;
@@ -24687,23 +25199,28 @@
if( fd<0 ){
return SQLITE_CANTOPEN;
}
if( isDelete ){
-#if IS_VXWORKS
+#if OS_VXWORKS
zPath = zName;
#else
unlink(zName);
#endif
}
+#if SQLITE_ENABLE_LOCKING_STYLE
+ else{
+ ((unixFile*)pFile)->openFlags = openFlags;
+ }
+#endif
if( pOutFlags ){
*pOutFlags = flags;
}
assert(fd!=0);
if( isOpenDirectory ){
- int rc = openDirectory(zPath, &dirfd);
- if( rc!=SQLITE_OK ){
- close(fd);
+ rc = openDirectory(zPath, &dirfd);
+ if( rc!=SQLITE_OK ){
+ close(fd); /* silently leak if fail, already in error */
return rc;
}
}
@@ -24711,16 +25228,52 @@
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
noLock = eType!=SQLITE_OPEN_MAIN_DB;
+
+#if SQLITE_PREFER_PROXY_LOCKING
+ if( zPath!=NULL && !noLock ){
+ char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
+ int useProxy = 0;
+
+ /* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy,
+ ** 0 means never use proxy, NULL means use proxy for non-local files only
+ */
+ if( envforce!=NULL ){
+ useProxy = atoi(envforce)>0;
+ }else{
+ struct statfs fsInfo;
+
+ if( statfs(zPath, &fsInfo) == -1 ){
+ ((unixFile*)pFile)->lastErrno = errno;
+ if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */
+ close(fd); /* silently leak if fail, in error */
+ return SQLITE_IOERR_ACCESS;
+ }
+ useProxy = !(fsInfo.f_flags&MNT_LOCAL);
+ }
+ if( useProxy ){
+ rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
+ if( rc==SQLITE_OK ){
+ rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
+ }
+ return rc;
+ }
+ }
+#endif
+
return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
}
/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file.
*/
-static int unixDelete(sqlite3_vfs *NotUsed, const char *zPath, int dirSync){
+static int unixDelete(
+ sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */
+ const char *zPath, /* Name of file to be deleted */
+ int dirSync /* If true, fsync() directory after deleting file */
+){
int rc = SQLITE_OK;
UNUSED_PARAMETER(NotUsed);
SimulateIOError(return SQLITE_IOERR_DELETE);
unlink(zPath);
@@ -24728,17 +25281,19 @@
if( dirSync ){
int fd;
rc = openDirectory(zPath, &fd);
if( rc==SQLITE_OK ){
-#if IS_VXWORKS
+#if OS_VXWORKS
if( fsync(fd)==-1 )
#else
if( fsync(fd) )
#endif
{
rc = SQLITE_IOERR_DIR_FSYNC;
}
- close(fd);
+ if( close(fd)&&!rc ){
+ rc = SQLITE_IOERR_DIR_CLOSE;
+ }
}
}
#endif
return rc;
@@ -24754,12 +25309,12 @@
**
** Otherwise return 0.
*/
static int unixAccess(
- sqlite3_vfs *NotUsed,
- const char *zPath,
- int flags,
- int *pResOut
+ sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */
+ const char *zPath, /* Path of the file to examine */
+ int flags, /* What do we want to learn about the zPath file? */
+ int *pResOut /* Write result boolean here */
){
int amode = 0;
UNUSED_PARAMETER(NotUsed);
SimulateIOError( return SQLITE_IOERR_ACCESS; );
@@ -24800,27 +25355,15 @@
/* It's odd to simulate an io-error here, but really this is just
** using the io-error infrastructure to test that SQLite handles this
** function failing. This function could fail if, for example, the
- ** current working directly has been unlinked.
+ ** current working directory has been unlinked.
*/
SimulateIOError( return SQLITE_ERROR );
assert( pVfs->mxPathname==MAX_PATHNAME );
UNUSED_PARAMETER(pVfs);
-#if IS_VXWORKS
- {
- char *zRealname = vxrealpath(zPath, 0);
- zOut[0] = '\0';
- if( !zRealname ){
- return SQLITE_CANTOPEN;
- }
- sqlite3_snprintf(nOut, zOut, "%s", zRealname);
- sqlite3_free(zRealname);
- return SQLITE_OK;
- }
-#else
zOut[nOut-1] = '\0';
if( zPath[0]=='/' ){
sqlite3_snprintf(nOut, zOut, "%s", zPath);
}else{
@@ -24827,39 +25370,12 @@
int nCwd;
if( getcwd(zOut, nOut-1)==0 ){
return SQLITE_CANTOPEN;
}
- nCwd = strlen(zOut);
+ nCwd = (int)strlen(zOut);
sqlite3_snprintf(nOut-nCwd, &zOut[nCwd], "/%s", zPath);
}
return SQLITE_OK;
-
-#if 0
- /*
- ** Remove "/./" path elements and convert "/A/./" path elements
- ** to just "/".
- */
- if( zFull ){
- int i, j;
- for(i=j=0; zFull[i]; i++){
- if( zFull[i]=='/' ){
- if( zFull[i+1]=='/' ) continue;
- if( zFull[i+1]=='.' && zFull[i+2]=='/' ){
- i += 1;
- continue;
- }
- if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){
- while( j>0 && zFull[j-1]!='/' ){ j--; }
- i += 3;
- continue;
- }
- }
- zFull[j++] = zFull[i];
- }
- zFull[j] = 0;
- }
-#endif
-#endif
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
@@ -24882,18 +25398,37 @@
*/
static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
char *zErr;
UNUSED_PARAMETER(NotUsed);
- enterMutex();
+ unixEnterMutex();
zErr = dlerror();
if( zErr ){
sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
}
- leaveMutex();
-}
-static void *unixDlSym(sqlite3_vfs *NotUsed, void *pHandle, const char*zSymbol){
- UNUSED_PARAMETER(NotUsed);
- return dlsym(pHandle, zSymbol);
+ unixLeaveMutex();
+}
+static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
+ /*
+ ** GCC with -pedantic-errors says that C90 does not allow a void* to be
+ ** cast into a pointer to a function. And yet the library dlsym() routine
+ ** returns a void* which is really a pointer to a function. So how do we
+ ** use dlsym() with -pedantic-errors?
+ **
+ ** Variable x below is defined to be a pointer to a function taking
+ ** parameters void* and const char* and returning a pointer to a function.
+ ** We initialize x by assigning it a pointer to the dlsym() function.
+ ** (That assignment requires a cast.) Then we call the function that
+ ** x points to.
+ **
+ ** This work-around is unlikely to work correctly on any system where
+ ** you really cannot cast a function pointer into void*. But then, on the
+ ** other hand, dlsym() will not work on such a system either, so we have
+ ** not really lost anything.
+ */
+ void (*(*x)(void*,const char*))(void);
+ UNUSED_PARAMETER(NotUsed);
+ x = (void(*(*)(void*,const char*))(void))dlsym;
+ return (*x)(p, zSym);
}
static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
UNUSED_PARAMETER(NotUsed);
dlclose(pHandle);
@@ -24955,9 +25490,9 @@
** might be greater than or equal to the argument, but not less
** than the argument.
*/
static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
-#if IS_VXWORKS
+#if OS_VXWORKS
struct timespec sp;
sp.tv_sec = microseconds / 1000000;
sp.tv_nsec = (microseconds % 1000000) * 1000;
@@ -24974,13 +25509,14 @@
UNUSED_PARAMETER(NotUsed);
}
/*
-** The following variable, if set to a non-zero value, becomes the result
-** returned from sqlite3OsCurrentTime(). This is used for testing.
-*/
-#ifdef SQLITE_TEST
-SQLITE_API int sqlite3_current_time = 0;
+** The following variable, if set to a non-zero value, is interpreted as
+** the number of seconds since 1970 and is used to set the result of
+** sqlite3OsCurrentTime() during testing.
+*/
+#ifdef SQLITE_TEST
+SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
#endif
/*
** Find the current time (in Universal Coordinated Time). Write the
@@ -24987,16 +25523,16 @@
** current time and date as a Julian Day number into *prNow and
** return 0. Return 1 if the time and date cannot be found.
*/
static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
-#if IS_VXWORKS
+#if defined(NO_GETTOD)
+ time_t t;
+ time(&t);
+ *prNow = t/86400.0 + 2440587.5;
+#elif OS_VXWORKS
struct timespec sNow;
clock_gettime(CLOCK_REALTIME, &sNow);
*prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_nsec/86400000000000.0;
-#elif defined(NO_GETTOD)
- time_t t;
- time(&t);
- *prNow = t/86400.0 + 2440587.5;
#else
struct timeval sNow;
gettimeofday(&sNow, 0);
*prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0;
@@ -25010,8 +25546,15 @@
UNUSED_PARAMETER(NotUsed);
return 0;
}
+/*
+** We added the xGetLastError() method with the intention of providing
+** better low-level error messages when operating-system problems come up
+** during SQLite operation. But so far, none of that has been implemented
+** in the core. So this routine is never called. For now, it is merely
+** a place-holder.
+*/
static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
UNUSED_PARAMETER(NotUsed);
UNUSED_PARAMETER(NotUsed2);
UNUSED_PARAMETER(NotUsed3);
@@ -25018,23 +25561,982 @@
return 0;
}
/*
+************************ End of sqlite3_vfs methods ***************************
+******************************************************************************/
+
+/******************************************************************************
+************************** Begin Proxy Locking ********************************
+**
+** Proxy locking is a "uber-locking-method" in this sense: It uses the
+** other locking methods on secondary lock files. Proxy locking is a
+** meta-layer over top of the primitive locking implemented above. For
+** this reason, the division that implements of proxy locking is deferred
+** until late in the file (here) after all of the other I/O methods have
+** been defined - so that the primitive locking methods are available
+** as services to help with the implementation of proxy locking.
+**
+****
+**
+** The default locking schemes in SQLite use byte-range locks on the
+** database file to coordinate safe, concurrent access by multiple readers
+** and writers [http://sqlite.org/lockingv3.html]. The five file locking
+** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
+** as POSIX read & write locks over fixed set of locations (via fsctl),
+** on AFP and SMB only exclusive byte-range locks are available via fsctl
+** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
+** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
+** address in the shared range is taken for a SHARED lock, the entire
+** shared range is taken for an EXCLUSIVE lock):
+**
+** PENDING_BYTE 0x40000000
+** RESERVED_BYTE 0x40000001
+** SHARED_RANGE 0x40000002 -> 0x40000200
+**
+** This works well on the local file system, but shows a nearly 100x
+** slowdown in read performance on AFP because the AFP client disables
+** the read cache when byte-range locks are present. Enabling the read
+** cache exposes a cache coherency problem that is present on all OS X
+** supported network file systems. NFS and AFP both observe the
+** close-to-open semantics for ensuring cache coherency
+** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
+** address the requirements for concurrent database access by multiple
+** readers and writers
+** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
+**
+** To address the performance and cache coherency issues, proxy file locking
+** changes the way database access is controlled by limiting access to a
+** single host at a time and moving file locks off of the database file
+** and onto a proxy file on the local file system.
+**
+**
+** Using proxy locks
+** -----------------
+**
+** C APIs
+**
+** sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE,
+** <proxy_path> | ":auto:");
+** sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &<proxy_path>);
+**
+**
+** SQL pragmas
+**
+** PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
+** PRAGMA [database.]lock_proxy_file
+**
+** Specifying ":auto:" means that if there is a conch file with a matching
+** host ID in it, the proxy path in the conch file will be used, otherwise
+** a proxy path based on the user's temp dir
+** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
+** actual proxy file name is generated from the name and path of the
+** database file. For example:
+**
+** For database path "/Users/me/foo.db"
+** The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
+**
+** Once a lock proxy is configured for a database connection, it can not
+** be removed, however it may be switched to a different proxy path via
+** the above APIs (assuming the conch file is not being held by another
+** connection or process).
+**
+**
+** How proxy locking works
+** -----------------------
+**
+** Proxy file locking relies primarily on two new supporting files:
+**
+** * conch file to limit access to the database file to a single host
+** at a time
+**
+** * proxy file to act as a proxy for the advisory locks normally
+** taken on the database
+**
+** The conch file - to use a proxy file, sqlite must first "hold the conch"
+** by taking an sqlite-style shared lock on the conch file, reading the
+** contents and comparing the host's unique host ID (see below) and lock
+** proxy path against the values stored in the conch. The conch file is
+** stored in the same directory as the database file and the file name
+** is patterned after the database file name as ".<databasename>-conch".
+** If the conch file does not exist, or it's contents do not match the
+** host ID and/or proxy path, then the lock is escalated to an exclusive
+** lock and the conch file contents is updated with the host ID and proxy
+** path and the lock is downgraded to a shared lock again. If the conch
+** is held by another process (with a shared lock), the exclusive lock
+** will fail and SQLITE_BUSY is returned.
+**
+** The proxy file - a single-byte file used for all advisory file locks
+** normally taken on the database file. This allows for safe sharing
+** of the database file for multiple readers and writers on the same
+** host (the conch ensures that they all use the same local lock file).
+**
+** There is a third file - the host ID file - used as a persistent record
+** of a unique identifier for the host, a 128-byte unique host id file
+** in the path defined by the HOSTIDPATH macro (default value is
+** /Library/Caches/.com.apple.sqliteConchHostId).
+**
+** Requesting the lock proxy does not immediately take the conch, it is
+** only taken when the first request to lock database file is made.
+** This matches the semantics of the traditional locking behavior, where
+** opening a connection to a database file does not take a lock on it.
+** The shared lock and an open file descriptor are maintained until
+** the connection to the database is closed.
+**
+** The proxy file and the lock file are never deleted so they only need
+** to be created the first time they are used.
+**
+** Configuration options
+** ---------------------
+**
+** SQLITE_PREFER_PROXY_LOCKING
+**
+** Database files accessed on non-local file systems are
+** automatically configured for proxy locking, lock files are
+** named automatically using the same logic as
+** PRAGMA lock_proxy_file=":auto:"
+**
+** SQLITE_PROXY_DEBUG
+**
+** Enables the logging of error messages during host id file
+** retrieval and creation
+**
+** HOSTIDPATH
+**
+** Overrides the default host ID file path location
+**
+** LOCKPROXYDIR
+**
+** Overrides the default directory used for lock proxy files that
+** are named automatically via the ":auto:" setting
+**
+** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+**
+** Permissions to use when creating a directory for storing the
+** lock proxy files, only used when LOCKPROXYDIR is not set.
+**
+**
+** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
+** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
+** force proxy locking to be used for every database file opened, and 0
+** will force automatic proxy locking to be disabled for all database
+** files (explicity calling the SQLITE_SET_LOCKPROXYFILE pragma or
+** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
+*/
+
+/*
+** Proxy locking is only available on MacOSX
+*/
+#if defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE
+
+#ifdef SQLITE_TEST
+/* simulate multiple hosts by creating unique hostid file paths */
+SQLITE_API int sqlite3_hostid_num = 0;
+#endif
+
+/*
+** The proxyLockingContext has the path and file structures for the remote
+** and local proxy files in it
+*/
+typedef struct proxyLockingContext proxyLockingContext;
+struct proxyLockingContext {
+ unixFile *conchFile; /* Open conch file */
+ char *conchFilePath; /* Name of the conch file */
+ unixFile *lockProxy; /* Open proxy lock file */
+ char *lockProxyPath; /* Name of the proxy lock file */
+ char *dbPath; /* Name of the open file */
+ int conchHeld; /* True if the conch is currently held */
+ void *oldLockingContext; /* Original lockingcontext to restore on close */
+ sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
+};
+
+/* HOSTIDLEN and CONCHLEN both include space for the string
+** terminating nul
+*/
+#define HOSTIDLEN 128
+#define CONCHLEN (MAXPATHLEN+HOSTIDLEN+1)
+#ifndef HOSTIDPATH
+# define HOSTIDPATH "/Library/Caches/.com.apple.sqliteConchHostId"
+#endif
+
+/* basically a copy of unixRandomness with different
+** test behavior built in */
+static int proxyGenerateHostID(char *pHostID){
+ int pid, fd, len;
+ unsigned char *key = (unsigned char *)pHostID;
+
+ memset(key, 0, HOSTIDLEN);
+ len = 0;
+ fd = open("/dev/urandom", O_RDONLY);
+ if( fd>=0 ){
+ len = read(fd, key, HOSTIDLEN);
+ close(fd); /* silently leak the fd if it fails */
+ }
+ if( len < HOSTIDLEN ){
+ time_t t;
+ time(&t);
+ memcpy(key, &t, sizeof(t));
+ pid = getpid();
+ memcpy(&key[sizeof(t)], &pid, sizeof(pid));
+ }
+
+#ifdef MAKE_PRETTY_HOSTID
+ {
+ int i;
+ /* filter the bytes into printable ascii characters and NUL terminate */
+ key[(HOSTIDLEN-1)] = 0x00;
+ for( i=0; i<(HOSTIDLEN-1); i++ ){
+ unsigned char pa = key[i]&0x7F;
+ if( pa<0x20 ){
+ key[i] = (key[i]&0x80 == 0x80) ? pa+0x40 : pa+0x20;
+ }else if( pa==0x7F ){
+ key[i] = (key[i]&0x80 == 0x80) ? pa=0x20 : pa+0x7E;
+ }
+ }
+ }
+#endif
+ return SQLITE_OK;
+}
+
+/* writes the host id path to path, path should be an pre-allocated buffer
+** with enough space for a path
+*/
+static void proxyGetHostIDPath(char *path, size_t len){
+ strlcpy(path, HOSTIDPATH, len);
+#ifdef SQLITE_TEST
+ if( sqlite3_hostid_num>0 ){
+ char suffix[2] = "1";
+ suffix[0] = suffix[0] + sqlite3_hostid_num;
+ strlcat(path, suffix, len);
+ }
+#endif
+ OSTRACE3("GETHOSTIDPATH %s pid=%d\n", path, getpid());
+}
+
+/* get the host ID from a sqlite hostid file stored in the
+** user-specific tmp directory, create the ID if it's not there already
+*/
+static int proxyGetHostID(char *pHostID, int *pError){
+ int fd;
+ char path[MAXPATHLEN];
+ size_t len;
+ int rc=SQLITE_OK;
+
+ proxyGetHostIDPath(path, MAXPATHLEN);
+ /* try to create the host ID file, if it already exists read the contents */
+ fd = open(path, O_CREAT|O_WRONLY|O_EXCL, 0644);
+ if( fd<0 ){
+ int err=errno;
+
+ if( err!=EEXIST ){
+#ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */
+ fprintf(stderr, "sqlite error creating host ID file %s: %s\n",
+ path, strerror(err));
+#endif
+ return SQLITE_PERM;
+ }
+ /* couldn't create the file, read it instead */
+ fd = open(path, O_RDONLY|O_EXCL);
+ if( fd<0 ){
+#ifdef SQLITE_PROXY_DEBUG /* set the sqlite error message instead */
+ int err = errno;
+ fprintf(stderr, "sqlite error opening host ID file %s: %s\n",
+ path, strerror(err));
+#endif
+ return SQLITE_PERM;
+ }
+ len = pread(fd, pHostID, HOSTIDLEN, 0);
+ if( len<0 ){
+ *pError = errno;
+ rc = SQLITE_IOERR_READ;
+ }else if( len<HOSTIDLEN ){
+ *pError = 0;
+ rc = SQLITE_IOERR_SHORT_READ;
+ }
+ close(fd); /* silently leak the fd if it fails */
+ OSTRACE3("GETHOSTID read %s pid=%d\n", pHostID, getpid());
+ return rc;
+ }else{
+ /* we're creating the host ID file (use a random string of bytes) */
+ proxyGenerateHostID(pHostID);
+ len = pwrite(fd, pHostID, HOSTIDLEN, 0);
+ if( len<0 ){
+ *pError = errno;
+ rc = SQLITE_IOERR_WRITE;
+ }else if( len<HOSTIDLEN ){
+ *pError = 0;
+ rc = SQLITE_IOERR_WRITE;
+ }
+ close(fd); /* silently leak the fd if it fails */
+ OSTRACE3("GETHOSTID wrote %s pid=%d\n", pHostID, getpid());
+ return rc;
+ }
+}
+
+static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
+ int len;
+ int dbLen;
+ int i;
+
+#ifdef LOCKPROXYDIR
+ len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
+#else
+# ifdef _CS_DARWIN_USER_TEMP_DIR
+ {
+ confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen);
+ len = strlcat(lPath, "sqliteplocks", maxLen);
+ if( mkdir(lPath, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
+ /* if mkdir fails, handle as lock file creation failure */
+ int err = errno;
+# ifdef SQLITE_DEBUG
+ if( err!=EEXIST ){
+ fprintf(stderr, "proxyGetLockPath: mkdir(%s,0%o) error %d %s\n", lPath,
+ SQLITE_DEFAULT_PROXYDIR_PERMISSIONS, err, strerror(err));
+ }
+# endif
+ }else{
+ OSTRACE3("GETLOCKPATH mkdir %s pid=%d\n", lPath, getpid());
+ }
+
+ }
+# else
+ len = strlcpy(lPath, "/tmp/", maxLen);
+# endif
+#endif
+
+ if( lPath[len-1]!='/' ){
+ len = strlcat(lPath, "/", maxLen);
+ }
+
+ /* transform the db path to a unique cache name */
+ dbLen = (int)strlen(dbPath);
+ for( i=0; i<dbLen && (i+len+7)<maxLen; i++){
+ char c = dbPath[i];
+ lPath[i+len] = (c=='/')?'_':c;
+ }
+ lPath[i+len]='\0';
+ strlcat(lPath, ":auto:", maxLen);
+ return SQLITE_OK;
+}
+
+/*
+** Create a new VFS file descriptor (stored in memory obtained from
+** sqlite3_malloc) and open the file named "path" in the file descriptor.
+**
+** The caller is responsible not only for closing the file descriptor
+** but also for freeing the memory associated with the file descriptor.
+*/
+static int proxyCreateUnixFile(const char *path, unixFile **ppFile) {
+ int fd;
+ int dirfd = -1;
+ unixFile *pNew;
+ int rc = SQLITE_OK;
+ sqlite3_vfs dummyVfs;
+
+ fd = open(path, O_RDWR | O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
+ if( fd<0 ){
+ return SQLITE_CANTOPEN;
+ }
+
+ pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile));
+ if( pNew==NULL ){
+ rc = SQLITE_NOMEM;
+ goto end_create_proxy;
+ }
+ memset(pNew, 0, sizeof(unixFile));
+
+ dummyVfs.pAppData = (void*)&autolockIoFinder;
+ rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0);
+ if( rc==SQLITE_OK ){
+ *ppFile = pNew;
+ return SQLITE_OK;
+ }
+end_create_proxy:
+ close(fd); /* silently leak fd if error, we're already in error */
+ sqlite3_free(pNew);
+ return rc;
+}
+
+/* takes the conch by taking a shared lock and read the contents conch, if
+** lockPath is non-NULL, the host ID and lock file path must match. A NULL
+** lockPath means that the lockPath in the conch file will be used if the
+** host IDs match, or a new lock path will be generated automatically
+** and written to the conch file.
+*/
+static int proxyTakeConch(unixFile *pFile){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+
+ if( pCtx->conchHeld>0 ){
+ return SQLITE_OK;
+ }else{
+ unixFile *conchFile = pCtx->conchFile;
+ char testValue[CONCHLEN];
+ char conchValue[CONCHLEN];
+ char lockPath[MAXPATHLEN];
+ char *tLockPath = NULL;
+ int rc = SQLITE_OK;
+ int readRc = SQLITE_OK;
+ int syncPerms = 0;
+
+ OSTRACE4("TAKECONCH %d for %s pid=%d\n", conchFile->h,
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid());
+
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
+ if( rc==SQLITE_OK ){
+ int pError = 0;
+ memset(testValue, 0, CONCHLEN); /* conch is fixed size */
+ rc = proxyGetHostID(testValue, &pError);
+ if( (rc&0xff)==SQLITE_IOERR ){
+ pFile->lastErrno = pError;
+ }
+ if( pCtx->lockProxyPath ){
+ strlcpy(&testValue[HOSTIDLEN], pCtx->lockProxyPath, MAXPATHLEN);
+ }
+ }
+ if( rc!=SQLITE_OK ){
+ goto end_takeconch;
+ }
+
+ readRc = unixRead((sqlite3_file *)conchFile, conchValue, CONCHLEN, 0);
+ if( readRc!=SQLITE_IOERR_SHORT_READ ){
+ if( readRc!=SQLITE_OK ){
+ if( (rc&0xff)==SQLITE_IOERR ){
+ pFile->lastErrno = conchFile->lastErrno;
+ }
+ rc = readRc;
+ goto end_takeconch;
+ }
+ /* if the conch has data compare the contents */
+ if( !pCtx->lockProxyPath ){
+ /* for auto-named local lock file, just check the host ID and we'll
+ ** use the local lock file path that's already in there */
+ if( !memcmp(testValue, conchValue, HOSTIDLEN) ){
+ tLockPath = (char *)&conchValue[HOSTIDLEN];
+ goto end_takeconch;
+ }
+ }else{
+ /* we've got the conch if conchValue matches our path and host ID */
+ if( !memcmp(testValue, conchValue, CONCHLEN) ){
+ goto end_takeconch;
+ }
+ }
+ }else{
+ /* a short read means we're "creating" the conch (even though it could
+ ** have been user-intervention), if we acquire the exclusive lock,
+ ** we'll try to match the current on-disk permissions of the database
+ */
+ syncPerms = 1;
+ }
+
+ /* either conch was emtpy or didn't match */
+ if( !pCtx->lockProxyPath ){
+ proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
+ tLockPath = lockPath;
+ strlcpy(&testValue[HOSTIDLEN], lockPath, MAXPATHLEN);
+ }
+
+ /* update conch with host and path (this will fail if other process
+ ** has a shared lock already) */
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
+ if( rc==SQLITE_OK ){
+ rc = unixWrite((sqlite3_file *)conchFile, testValue, CONCHLEN, 0);
+ if( rc==SQLITE_OK && syncPerms ){
+ struct stat buf;
+ int err = fstat(pFile->h, &buf);
+ if( err==0 ){
+ /* try to match the database file permissions, ignore failure */
+#ifndef SQLITE_PROXY_DEBUG
+ fchmod(conchFile->h, buf.st_mode);
+#else
+ if( fchmod(conchFile->h, buf.st_mode)!=0 ){
+ int code = errno;
+ fprintf(stderr, "fchmod %o FAILED with %d %s\n",
+ buf.st_mode, code, strerror(code));
+ } else {
+ fprintf(stderr, "fchmod %o SUCCEDED\n",buf.st_mode);
+ }
+ }else{
+ int code = errno;
+ fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
+ err, code, strerror(code));
+#endif
+ }
+ }
+ }
+ conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
+
+end_takeconch:
+ OSTRACE2("TRANSPROXY: CLOSE %d\n", pFile->h);
+ if( rc==SQLITE_OK && pFile->openFlags ){
+ if( pFile->h>=0 ){
+#ifdef STRICT_CLOSE_ERROR
+ if( close(pFile->h) ){
+ pFile->lastErrno = errno;
+ return SQLITE_IOERR_CLOSE;
+ }
+#else
+ close(pFile->h); /* silently leak fd if fail */
+#endif
+ }
+ pFile->h = -1;
+ int fd = open(pCtx->dbPath, pFile->openFlags,
+ SQLITE_DEFAULT_FILE_PERMISSIONS);
+ OSTRACE2("TRANSPROXY: OPEN %d\n", fd);
+ if( fd>=0 ){
+ pFile->h = fd;
+ }else{
+ rc=SQLITE_CANTOPEN; /* SQLITE_BUSY? proxyTakeConch called
+ during locking */
+ }
+ }
+ if( rc==SQLITE_OK && !pCtx->lockProxy ){
+ char *path = tLockPath ? tLockPath : pCtx->lockProxyPath;
+ /* ACS: Need to make a copy of path sometimes */
+ rc = proxyCreateUnixFile(path, &pCtx->lockProxy);
+ }
+ if( rc==SQLITE_OK ){
+ pCtx->conchHeld = 1;
+
+ if( tLockPath ){
+ pCtx->lockProxyPath = sqlite3DbStrDup(0, tLockPath);
+ if( pCtx->lockProxy->pMethod == &afpIoMethods ){
+ ((afpLockingContext *)pCtx->lockProxy->lockingContext)->dbPath =
+ pCtx->lockProxyPath;
+ }
+ }
+ } else {
+ conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
+ }
+ OSTRACE3("TAKECONCH %d %s\n", conchFile->h, rc==SQLITE_OK?"ok":"failed");
+ return rc;
+ }
+}
+
+/*
+** If pFile holds a lock on a conch file, then release that lock.
+*/
+static int proxyReleaseConch(unixFile *pFile){
+ int rc; /* Subroutine return code */
+ proxyLockingContext *pCtx; /* The locking context for the proxy lock */
+ unixFile *conchFile; /* Name of the conch file */
+
+ pCtx = (proxyLockingContext *)pFile->lockingContext;
+ conchFile = pCtx->conchFile;
+ OSTRACE4("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
+ getpid());
+ pCtx->conchHeld = 0;
+ rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
+ OSTRACE3("RELEASECONCH %d %s\n", conchFile->h,
+ (rc==SQLITE_OK ? "ok" : "failed"));
+ return rc;
+}
+
+/*
+** Given the name of a database file, compute the name of its conch file.
+** Store the conch filename in memory obtained from sqlite3_malloc().
+** Make *pConchPath point to the new name. Return SQLITE_OK on success
+** or SQLITE_NOMEM if unable to obtain memory.
+**
+** The caller is responsible for ensuring that the allocated memory
+** space is eventually freed.
+**
+** *pConchPath is set to NULL if a memory allocation error occurs.
+*/
+static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
+ int i; /* Loop counter */
+ int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
+ char *conchPath; /* buffer in which to construct conch name */
+
+ /* Allocate space for the conch filename and initialize the name to
+ ** the name of the original database file. */
+ *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
+ if( conchPath==0 ){
+ return SQLITE_NOMEM;
+ }
+ memcpy(conchPath, dbPath, len+1);
+
+ /* now insert a "." before the last / character */
+ for( i=(len-1); i>=0; i-- ){
+ if( conchPath[i]=='/' ){
+ i++;
+ break;
+ }
+ }
+ conchPath[i]='.';
+ while ( i<len ){
+ conchPath[i+1]=dbPath[i];
+ i++;
+ }
+
+ /* append the "-conch" suffix to the file */
+ memcpy(&conchPath[i+1], "-conch", 7);
+ assert( (int)strlen(conchPath) == len+7 );
+
+ return SQLITE_OK;
+}
+
+
+/* Takes a fully configured proxy locking-style unix file and switches
+** the local lock file path
+*/
+static int switchLockProxyPath(unixFile *pFile, const char *path) {
+ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
+ char *oldPath = pCtx->lockProxyPath;
+ int rc = SQLITE_OK;
+
+ if( pFile->locktype!=NO_LOCK ){
+ return SQLITE_BUSY;
+ }
+
+ /* nothing to do if the path is NULL, :auto: or matches the existing path */
+ if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
+ (oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
+ return SQLITE_OK;
+ }else{
+ unixFile *lockProxy = pCtx->lockProxy;
+ pCtx->lockProxy=NULL;
+ pCtx->conchHeld = 0;
+ if( lockProxy!=NULL ){
+ rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
+ if( rc ) return rc;
+ sqlite3_free(lockProxy);
+ }
+ sqlite3_free(oldPath);
+ pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
+ }
+
+ return rc;
+}
+
+/*
+** pFile is a file that has been opened by a prior xOpen call. dbPath
+** is a string buffer at least MAXPATHLEN+1 characters in size.
+**
+** This routine find the filename associated with pFile and writes it
+** int dbPath.
+*/
+static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
+#if defined(__DARWIN__)
+ if( pFile->pMethod == &afpIoMethods ){
+ /* afp style keeps a reference to the db path in the filePath field
+ ** of the struct */
+ assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
+ strcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath);
+ }else
+#endif
+ if( pFile->pMethod == &dotlockIoMethods ){
+ /* dot lock style uses the locking context to store the dot lock
+ ** file path */
+ int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
+ memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
+ }else{
+ /* all other styles use the locking context to store the db file path */
+ assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
+ strcpy(dbPath, (char *)pFile->lockingContext);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Takes an already filled in unix file and alters it so all file locking
+** will be performed on the local proxy lock file. The following fields
+** are preserved in the locking context so that they can be restored and
+** the unix structure properly cleaned up at close time:
+** ->lockingContext
+** ->pMethod
+*/
+static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
+ proxyLockingContext *pCtx;
+ char dbPath[MAXPATHLEN+1]; /* Name of the database file */
+ char *lockPath=NULL;
+ int rc = SQLITE_OK;
+
+ if( pFile->locktype!=NO_LOCK ){
+ return SQLITE_BUSY;
+ }
+ proxyGetDbPathForUnixFile(pFile, dbPath);
+ if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
+ lockPath=NULL;
+ }else{
+ lockPath=(char *)path;
+ }
+
+ OSTRACE4("TRANSPROXY %d for %s pid=%d\n", pFile->h,
+ (lockPath ? lockPath : ":auto:"), getpid());
+
+ pCtx = sqlite3_malloc( sizeof(*pCtx) );
+ if( pCtx==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(pCtx, 0, sizeof(*pCtx));
+
+ rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
+ if( rc==SQLITE_OK ){
+ rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile);
+ }
+ if( rc==SQLITE_OK && lockPath ){
+ pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
+ }
+
+ if( rc==SQLITE_OK ){
+ /* all memory is allocated, proxys are created and assigned,
+ ** switch the locking context and pMethod then return.
+ */
+ pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
+ pCtx->oldLockingContext = pFile->lockingContext;
+ pFile->lockingContext = pCtx;
+ pCtx->pOldMethod = pFile->pMethod;
+ pFile->pMethod = &proxyIoMethods;
+ }else{
+ if( pCtx->conchFile ){
+ rc = pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
+ if( rc ) return rc;
+ sqlite3_free(pCtx->conchFile);
+ }
+ sqlite3_free(pCtx->conchFilePath);
+ sqlite3_free(pCtx);
+ }
+ OSTRACE3("TRANSPROXY %d %s\n", pFile->h,
+ (rc==SQLITE_OK ? "ok" : "failed"));
+ return rc;
+}
+
+
+/*
+** This routine handles sqlite3_file_control() calls that are specific
+** to proxy locking.
+*/
+static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
+ switch( op ){
+ case SQLITE_GET_LOCKPROXYFILE: {
+ unixFile *pFile = (unixFile*)id;
+ if( pFile->pMethod == &proxyIoMethods ){
+ proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
+ proxyTakeConch(pFile);
+ if( pCtx->lockProxyPath ){
+ *(const char **)pArg = pCtx->lockProxyPath;
+ }else{
+ *(const char **)pArg = ":auto: (not held)";
+ }
+ } else {
+ *(const char **)pArg = NULL;
+ }
+ return SQLITE_OK;
+ }
+ case SQLITE_SET_LOCKPROXYFILE: {
+ unixFile *pFile = (unixFile*)id;
+ int rc = SQLITE_OK;
+ int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
+ if( pArg==NULL || (const char *)pArg==0 ){
+ if( isProxyStyle ){
+ /* turn off proxy locking - not supported */
+ rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
+ }else{
+ /* turn off proxy locking - already off - NOOP */
+ rc = SQLITE_OK;
+ }
+ }else{
+ const char *proxyPath = (const char *)pArg;
+ if( isProxyStyle ){
+ proxyLockingContext *pCtx =
+ (proxyLockingContext*)pFile->lockingContext;
+ if( !strcmp(pArg, ":auto:")
+ || (pCtx->lockProxyPath &&
+ !strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
+ ){
+ rc = SQLITE_OK;
+ }else{
+ rc = switchLockProxyPath(pFile, proxyPath);
+ }
+ }else{
+ /* turn on proxy file locking */
+ rc = proxyTransformUnixFile(pFile, proxyPath);
+ }
+ }
+ return rc;
+ }
+ default: {
+ assert( 0 ); /* The call assures that only valid opcodes are sent */
+ }
+ }
+ /*NOTREACHED*/
+ return SQLITE_ERROR;
+}
+
+/*
+** Within this division (the proxying locking implementation) the procedures
+** above this point are all utilities. The lock-related methods of the
+** proxy-locking sqlite3_io_method object follow.
+*/
+
+
+/*
+** This routine checks if there is a RESERVED lock held on the specified
+** file by this or any other process. If such a lock is held, set *pResOut
+** to a non-zero value otherwise *pResOut is set to zero. The return value
+** is set to SQLITE_OK unless an I/O error occurs during lock checking.
+*/
+static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
+ unixFile *pFile = (unixFile*)id;
+ int rc = proxyTakeConch(pFile);
+ if( rc==SQLITE_OK ){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ unixFile *proxy = pCtx->lockProxy;
+ return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
+ }
+ return rc;
+}
+
+/*
+** Lock the file with the lock specified by parameter locktype - one
+** of the following:
+**
+** (1) SHARED_LOCK
+** (2) RESERVED_LOCK
+** (3) PENDING_LOCK
+** (4) EXCLUSIVE_LOCK
+**
+** Sometimes when requesting one lock state, additional lock states
+** are inserted in between. The locking might fail on one of the later
+** transitions leaving the lock state different from what it started but
+** still short of its goal. The following chart shows the allowed
+** transitions and the inserted intermediate states:
+**
+** UNLOCKED -> SHARED
+** SHARED -> RESERVED
+** SHARED -> (PENDING) -> EXCLUSIVE
+** RESERVED -> (PENDING) -> EXCLUSIVE
+** PENDING -> EXCLUSIVE
+**
+** This routine will only increase a lock. Use the sqlite3OsUnlock()
+** routine to lower a locking level.
+*/
+static int proxyLock(sqlite3_file *id, int locktype) {
+ unixFile *pFile = (unixFile*)id;
+ int rc = proxyTakeConch(pFile);
+ if( rc==SQLITE_OK ){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ unixFile *proxy = pCtx->lockProxy;
+ rc = proxy->pMethod->xLock((sqlite3_file*)proxy, locktype);
+ pFile->locktype = proxy->locktype;
+ }
+ return rc;
+}
+
+
+/*
+** Lower the locking level on file descriptor pFile to locktype. locktype
+** must be either NO_LOCK or SHARED_LOCK.
+**
+** If the locking level of the file descriptor is already at or below
+** the requested locking level, this routine is a no-op.
+*/
+static int proxyUnlock(sqlite3_file *id, int locktype) {
+ unixFile *pFile = (unixFile*)id;
+ int rc = proxyTakeConch(pFile);
+ if( rc==SQLITE_OK ){
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ unixFile *proxy = pCtx->lockProxy;
+ rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, locktype);
+ pFile->locktype = proxy->locktype;
+ }
+ return rc;
+}
+
+/*
+** Close a file that uses proxy locks.
+*/
+static int proxyClose(sqlite3_file *id) {
+ if( id ){
+ unixFile *pFile = (unixFile*)id;
+ proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
+ unixFile *lockProxy = pCtx->lockProxy;
+ unixFile *conchFile = pCtx->conchFile;
+ int rc = SQLITE_OK;
+
+ if( lockProxy ){
+ rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
+ if( rc ) return rc;
+ rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
+ if( rc ) return rc;
+ sqlite3_free(lockProxy);
+ pCtx->lockProxy = 0;
+ }
+ if( conchFile ){
+ if( pCtx->conchHeld ){
+ rc = proxyReleaseConch(pFile);
+ if( rc ) return rc;
+ }
+ rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
+ if( rc ) return rc;
+ sqlite3_free(conchFile);
+ }
+ sqlite3_free(pCtx->lockProxyPath);
+ sqlite3_free(pCtx->conchFilePath);
+ sqlite3_free(pCtx->dbPath);
+ /* restore the original locking context and pMethod then close it */
+ pFile->lockingContext = pCtx->oldLockingContext;
+ pFile->pMethod = pCtx->pOldMethod;
+ sqlite3_free(pCtx);
+ return pFile->pMethod->xClose(id);
+ }
+ return SQLITE_OK;
+}
+
+
+
+#endif /* defined(__DARWIN__) && SQLITE_ENABLE_LOCKING_STYLE */
+/*
+** The proxy locking style is intended for use with AFP filesystems.
+** And since AFP is only supported on MacOSX, the proxy locking is also
+** restricted to MacOSX.
+**
+**
+******************* End of the proxy lock implementation **********************
+******************************************************************************/
+
+/*
** Initialize the operating system interface.
+**
+** This routine registers all VFS implementations for unix-like operating
+** systems. This routine, and the sqlite3_os_end() routine that follows,
+** should be the only routines in this file that are visible from other
+** files.
+**
+** This routine is called once during SQLite initialization and by a
+** single thread. The memory allocation and mutex subsystems have not
+** necessarily been initialized when this routine is called, and so they
+** should not be used.
*/
SQLITE_API int sqlite3_os_init(void){
- /* Macro to define the static contents of an sqlite3_vfs structure for
- ** the unix backend. The two parameters are the values to use for
- ** the sqlite3_vfs.zName and sqlite3_vfs.pAppData fields, respectively.
- **
- */
- #define UNIXVFS(zVfsName, pVfsAppData) { \
+ /*
+ ** The following macro defines an initializer for an sqlite3_vfs object.
+ ** The name of the VFS is NAME. The pAppData is a pointer to a pointer
+ ** to the "finder" function. (pAppData is a pointer to a pointer because
+ ** silly C90 rules prohibit a void* from being cast to a function pointer
+ ** and so we have to go through the intermediate pointer to avoid problems
+ ** when compiling with -pedantic-errors on GCC.)
+ **
+ ** The FINDER parameter to this macro is the name of the pointer to the
+ ** finder-function. The finder-function returns a pointer to the
+ ** sqlite_io_methods object that implements the desired locking
+ ** behaviors. See the division above that contains the IOMETHODS
+ ** macro for addition information on finder-functions.
+ **
+ ** Most finders simply return a pointer to a fixed sqlite3_io_methods
+ ** object. But the "autolockIoFinder" available on MacOSX does a little
+ ** more than that; it looks at the filesystem type that hosts the
+ ** database file and tries to choose an locking method appropriate for
+ ** that filesystem time.
+ */
+ #define UNIXVFS(VFSNAME, FINDER) { \
1, /* iVersion */ \
sizeof(unixFile), /* szOsFile */ \
MAX_PATHNAME, /* mxPathname */ \
0, /* pNext */ \
- zVfsName, /* zName */ \
- (void *)pVfsAppData, /* pAppData */ \
+ VFSNAME, /* zName */ \
+ (void*)&FINDER, /* pAppData */ \
unixOpen, /* xOpen */ \
unixDelete, /* xDelete */ \
unixAccess, /* xAccess */ \
unixFullPathname, /* xFullPathname */ \
@@ -25047,32 +26549,50 @@
unixCurrentTime, /* xCurrentTime */ \
unixGetLastError /* xGetLastError */ \
}
- static sqlite3_vfs unixVfs = UNIXVFS("unix", 0);
-#if SQLITE_ENABLE_LOCKING_STYLE
- int i;
+ /*
+ ** All default VFSes for unix are contained in the following array.
+ **
+ ** Note that the sqlite3_vfs.pNext field of the VFS object is modified
+ ** by the SQLite core when the VFS is registered. So the following
+ ** array cannot be const.
+ */
static sqlite3_vfs aVfs[] = {
- UNIXVFS("unix-posix", LOCKING_STYLE_POSIX),
- UNIXVFS("unix-afp", LOCKING_STYLE_AFP),
- UNIXVFS("unix-flock", LOCKING_STYLE_FLOCK),
- UNIXVFS("unix-dotfile", LOCKING_STYLE_DOTFILE),
- UNIXVFS("unix-none", LOCKING_STYLE_NONE),
- UNIXVFS("unix-namedsem",LOCKING_STYLE_NAMEDSEM),
- };
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
+ UNIXVFS("unix", autolockIoFinder ),
+#else
+ UNIXVFS("unix", posixIoFinder ),
+#endif
+ UNIXVFS("unix-none", nolockIoFinder ),
+ UNIXVFS("unix-dotfile", dotlockIoFinder ),
+#if OS_VXWORKS
+ UNIXVFS("unix-namedsem", semIoFinder ),
+#endif
+#if SQLITE_ENABLE_LOCKING_STYLE
+ UNIXVFS("unix-posix", posixIoFinder ),
+ UNIXVFS("unix-flock", flockIoFinder ),
+#endif
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__DARWIN__)
+ UNIXVFS("unix-afp", afpIoFinder ),
+ UNIXVFS("unix-proxy", proxyIoFinder ),
+#endif
+ };
+ unsigned int i; /* Loop counter */
+
+ /* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
- sqlite3_vfs_register(&aVfs[i], 0);
- }
-#endif
-#if IS_VXWORKS
- sqlite3HashInit(&nameHash, 1);
-#endif
- sqlite3_vfs_register(&unixVfs, 1);
- return SQLITE_OK;
-}
-
-/*
-** Shutdown the operating system interface. This is a no-op for unix.
+ sqlite3_vfs_register(&aVfs[i], i==0);
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Shutdown the operating system interface.
+**
+** Some operating systems might need to do some cleanup in this routine,
+** to release dynamically allocated objects. But not on unix.
+** This routine is a no-op for unix.
*/
SQLITE_API int sqlite3_os_end(void){
return SQLITE_OK;
}
@@ -25094,9 +26614,9 @@
******************************************************************************
**
** This file contains code that is specific to windows.
**
-** $Id: os_win.c,v 1.140 2008/11/19 21:35:47 shane Exp $
+** $Id: os_win.c,v 1.145 2008/12/11 02:58:27 shane Exp $
*/
#if SQLITE_OS_WIN /* This file is used for windows only */
@@ -25960,10 +27480,10 @@
void *pBuf, /* Write content into this buffer */
int amt, /* Number of bytes to read */
sqlite3_int64 offset /* Begin reading at this offset */
){
- LONG upperBits = (offset>>32) & 0x7fffffff;
- LONG lowerBits = offset & 0xffffffff;
+ LONG upperBits = (LONG)((offset>>32) & 0x7fffffff);
+ LONG lowerBits = (LONG)(offset & 0xffffffff);
DWORD rc;
DWORD got;
winFile *pFile = (winFile*)id;
assert( id!=0 );
@@ -25994,12 +27514,12 @@
const void *pBuf, /* The bytes to be written */
int amt, /* Number of bytes to write */
sqlite3_int64 offset /* Offset into the file to begin writing at */
){
- LONG upperBits = (offset>>32) & 0x7fffffff;
- LONG lowerBits = offset & 0xffffffff;
+ LONG upperBits = (LONG)((offset>>32) & 0x7fffffff);
+ LONG lowerBits = (LONG)(offset & 0xffffffff);
DWORD rc;
- DWORD wrote;
+ DWORD wrote = 0;
winFile *pFile = (winFile*)id;
assert( id!=0 );
SimulateIOError(return SQLITE_IOERR_WRITE);
SimulateDiskfullError(return SQLITE_FULL);
@@ -26027,10 +27547,10 @@
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
DWORD rc;
- LONG upperBits = (nByte>>32) & 0x7fffffff;
- LONG lowerBits = nByte & 0xffffffff;
+ LONG upperBits = (LONG)((nByte>>32) & 0x7fffffff);
+ LONG lowerBits = (LONG)(nByte & 0xffffffff);
winFile *pFile = (winFile*)id;
OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte);
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
@@ -26055,11 +27575,17 @@
/*
** Make sure all writes to a particular file are committed to disk.
*/
static int winSync(sqlite3_file *id, int flags){
+#ifndef SQLITE_NO_SYNC
winFile *pFile = (winFile*)id;
+#else
+ UNUSED_PARAMETER(id);
+#endif
OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype);
-#ifdef SQLITE_TEST
+#ifndef SQLITE_TEST
+ UNUSED_PARAMETER(flags);
+#else
if( flags & SQLITE_SYNC_FULL ){
sqlite3_fullsync_count++;
}
sqlite3_sync_count++;
@@ -26116,9 +27642,9 @@
#if SQLITE_OS_WINCE==0
}else{
int lk;
sqlite3_randomness(sizeof(lk), &lk);
- pFile->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
+ pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
#endif
}
return res;
@@ -26269,9 +27795,9 @@
OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
locktype, newLocktype);
rc = SQLITE_BUSY;
}
- pFile->locktype = newLocktype;
+ pFile->locktype = (u8)newLocktype;
return rc;
}
/*
@@ -26334,9 +27860,9 @@
}
if( type>=PENDING_LOCK ){
UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
}
- pFile->locktype = locktype;
+ pFile->locktype = (u8)locktype;
return rc;
}
/*
@@ -26362,15 +27888,17 @@
** a database and its journal file) that the sector size will be the
** same for both.
*/
static int winSectorSize(sqlite3_file *id){
+ UNUSED_PARAMETER(id);
return SQLITE_DEFAULT_SECTOR_SIZE;
}
/*
** Return a vector of device characteristics.
*/
static int winDeviceCharacteristics(sqlite3_file *id){
+ UNUSED_PARAMETER(id);
return 0;
}
/*
@@ -26461,13 +27989,13 @@
return SQLITE_NOMEM;
}
#endif
}
- for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
+ for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
zTempPath[i] = 0;
sqlite3_snprintf(nBuf-30, zBuf,
"%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
- j = strlen(zBuf);
+ j = sqlite3Strlen30(zBuf);
sqlite3_randomness(20, &zBuf[j]);
for(i=0; i<20; i++, j++){
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
}
@@ -26528,8 +28056,10 @@
winFile *pFile = (winFile*)id;
void *zConverted; /* Filename in OS encoding */
const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */
+
+ UNUSED_PARAMETER(pVfs);
/* If the second argument to this function is NULL, generate a
** temporary file name to use
*/
@@ -26662,10 +28192,12 @@
int syncDir /* Not used on win32 */
){
int cnt = 0;
DWORD rc;
- DWORD error;
+ DWORD error = 0;
void *zConverted = convertUtf8Filename(zFilename);
+ UNUSED_PARAMETER(pVfs);
+ UNUSED_PARAMETER(syncDir);
if( zConverted==0 ){
return SQLITE_NOMEM;
}
SimulateIOError(return SQLITE_IOERR_DELETE);
@@ -26705,10 +28237,11 @@
int flags, /* Type of test to make on this file */
int *pResOut /* OUT: Result */
){
DWORD attr;
- int rc;
+ int rc = 0;
void *zConverted = convertUtf8Filename(zFilename);
+ UNUSED_PARAMETER(pVfs);
if( zConverted==0 ){
return SQLITE_NOMEM;
}
if( isNT() ){
@@ -26751,13 +28284,15 @@
char *zFull /* Output buffer */
){
#if defined(__CYGWIN__)
+ UNUSED_PARAMETER(nFull);
cygwin_conv_to_full_win32_path(zRelative, zFull);
return SQLITE_OK;
#endif
#if SQLITE_OS_WINCE
+ UNUSED_PARAMETER(nFull);
/* WinCE has no concept of a relative pathname, or so I am told. */
sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative);
return SQLITE_OK;
#endif
@@ -26765,8 +28300,9 @@
#if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
int nByte;
void *zConverted;
char *zOut;
+ UNUSED_PARAMETER(nFull);
zConverted = convertUtf8Filename(zRelative);
if( isNT() ){
WCHAR *zTemp;
nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3;
@@ -26819,8 +28355,9 @@
*/
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
HANDLE h;
void *zConverted = convertUtf8Filename(zFilename);
+ UNUSED_PARAMETER(pVfs);
if( zConverted==0 ){
return 0;
}
if( isNT() ){
@@ -26837,21 +28374,24 @@
free(zConverted);
return (void*)h;
}
static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
+ UNUSED_PARAMETER(pVfs);
getLastErrorMsg(nBuf, zBufOut);
}
-void *winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
+void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
+ UNUSED_PARAMETER(pVfs);
#if SQLITE_OS_WINCE
/* The GetProcAddressA() routine is only available on wince. */
- return GetProcAddressA((HANDLE)pHandle, zSymbol);
+ return (void(*)(void))GetProcAddressA((HANDLE)pHandle, zSymbol);
#else
/* All other windows platforms expect GetProcAddress() to take
** an Ansi string regardless of the _UNICODE setting */
- return GetProcAddress((HANDLE)pHandle, zSymbol);
+ return (void(*)(void))GetProcAddress((HANDLE)pHandle, zSymbol);
#endif
}
void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
+ UNUSED_PARAMETER(pVfs);
FreeLibrary((HANDLE)pHandle);
}
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
#define winDlOpen 0
@@ -26902,8 +28442,9 @@
** Sleep for a little while. Return the amount of time slept.
*/
static int winSleep(sqlite3_vfs *pVfs, int microsec){
Sleep((microsec+999)/1000);
+ UNUSED_PARAMETER(pVfs);
return ((microsec+999)/1000)*1000;
}
/*
@@ -26934,8 +28475,9 @@
}
#else
GetSystemTimeAsFileTime( &ft );
#endif
+ UNUSED_PARAMETER(pVfs);
now = ((double)ft.dwHighDateTime) * 4294967296.0;
*prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
#ifdef SQLITE_TEST
if( sqlite3_current_time ){
@@ -26975,8 +28517,9 @@
** by sqlite into the error message available to the user using
** sqlite3_errmsg(), possibly making IO errors easier to debug.
*/
static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
+ UNUSED_PARAMETER(pVfs);
return getLastErrorMsg(nBuf, zBuf);
}
/*
@@ -27417,9 +28960,9 @@
**
*************************************************************************
** This file implements that page cache.
**
-** @(#) $Id: pcache.c,v 1.38 2008/11/19 16:52:44 danielk1977 Exp $
+** @(#) $Id: pcache.c,v 1.39 2008/12/04 20:40:10 drh Exp $
*/
/*
** A complete page cache is an instance of this structure.
@@ -27984,9 +29527,8 @@
}
}
#endif
-
/************** End of pcache.c **********************************************/
/************** Begin file pcache1.c *****************************************/
/*
** 2008 November 05
@@ -28005,9 +29547,9 @@
** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
** If the default page cache implementation is overriden, then neither of
** these two features are available.
**
-** @(#) $Id: pcache1.c,v 1.3 2008/11/19 09:05:27 danielk1977 Exp $
+** @(#) $Id: pcache1.c,v 1.6 2008/12/10 18:03:46 drh Exp $
*/
typedef struct PCache1 PCache1;
@@ -28096,9 +29638,9 @@
**
** assert( PGHDR1_TO_PAGE(PAGE_TO_PGHDR1(X))==X );
*/
#define PGHDR1_TO_PAGE(p) (void *)(&((unsigned char *)p)[sizeof(PgHdr1)])
-#define PAGE_TO_PGHDR1(p) (PgHdr1 *)(&((unsigned char *)p)[-1*sizeof(PgHdr1)])
+#define PAGE_TO_PGHDR1(p) (PgHdr1 *)(&((unsigned char *)p)[-1*(int)sizeof(PgHdr1)])
/*
** Macros to enter and leave the global LRU mutex.
*/
@@ -28251,16 +29793,18 @@
nNew = 256;
}
pcache1LeaveMutex();
+ if( p->nHash ){ sqlite3BeginBenignMalloc(); }
apNew = (PgHdr1 **)sqlite3_malloc(sizeof(PgHdr1 *)*nNew);
+ if( p->nHash ){ sqlite3EndBenignMalloc(); }
pcache1EnterMutex();
if( apNew ){
memset(apNew, 0, sizeof(PgHdr1 *)*nNew);
for(i=0; i<p->nHash; i++){
PgHdr1 *pPage;
PgHdr1 *pNext = p->apHash[i];
- while( (pPage = pNext) ){
+ while( (pPage = pNext)!=0 ){
unsigned int h = pPage->iKey % nNew;
pNext = pPage->pNext;
pPage->pNext = apNew[h];
apNew[h] = pPage;
@@ -28350,9 +29894,9 @@
assert( sqlite3_mutex_held(pcache1.mutex) );
for(h=0; h<pCache->nHash; h++){
PgHdr1 **pp = &pCache->apHash[h];
PgHdr1 *pPage;
- while( (pPage = *pp) ){
+ while( (pPage = *pp)!=0 ){
if( pPage->iKey>=iLimit ){
pcache1PinPage(pPage);
*pp = pPage->pNext;
pcache1FreePage(pPage);
@@ -28725,8 +30269,248 @@
}
#endif
/************** End of pcache1.c *********************************************/
+/************** Begin file rowset.c ******************************************/
+/*
+** 2008 December 3
+**
+** 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 module implements an object we call a "Row Set".
+**
+** The RowSet object is a bag of rowids. Rowids
+** are inserted into the bag in an arbitrary order. Then they are
+** pulled from the bag in sorted order. Rowids only appear in the
+** bag once. If the same rowid is inserted multiple times, the
+** second and subsequent inserts make no difference on the output.
+**
+** This implementation accumulates rowids in a linked list. For
+** output, it first sorts the linked list (removing duplicates during
+** the sort) then returns elements one by one by walking the list.
+**
+** Big chunks of rowid/next-ptr pairs are allocated at a time, to
+** reduce the malloc overhead.
+*/
+
+/*
+** The number of rowset entries per allocation chunk.
+*/
+#define ROWSET_ENTRY_PER_CHUNK 63
+
+/*
+** Each entry in a RowSet is an instance of the following
+** structure:
+*/
+struct RowSetEntry {
+ i64 v; /* ROWID value for this entry */
+ struct RowSetEntry *pNext; /* Next entry on a list of all entries */
+};
+
+/*
+** Index entries are allocated in large chunks (instances of the
+** following structure) to reduce memory allocation overhead. The
+** chunks are kept on a linked list so that they can be deallocated
+** when the RowSet is destroyed.
+*/
+struct RowSetChunk {
+ struct RowSetChunk *pNext; /* Next chunk on list of them all */
+ struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
+};
+
+/*
+** A RowSet in an instance of the following structure.
+**
+** A typedef of this structure if found in sqliteInt.h.
+*/
+struct RowSet {
+ struct RowSetChunk *pChunk; /* List of all chunk allocations */
+ sqlite3 *db; /* The database connection */
+ struct RowSetEntry *pEntry; /* List of entries in the rowset */
+ struct RowSetEntry *pLast; /* Last entry on the pEntry list */
+ struct RowSetEntry *pFresh; /* Source of new entry objects */
+ u16 nFresh; /* Number of objects on pFresh */
+ u8 isSorted; /* True if content is sorted */
+};
+
+/*
+** Turn bulk memory into a RowSet object. N bytes of memory
+** are available at pSpace. The db pointer is used as a memory context
+** for any subsequent allocations that need to occur.
+** Return a pointer to the new RowSet object.
+**
+** If N is not sufficient memory to make even a minimum RowSet,
+** then return NULL. If N is larger than the minimum, use
+** the surplus as an initial allocation of entries available to
+** be filled.
+*/
+SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int N){
+ RowSet *p;
+ if( N<sizeof(*p) ){
+ p = 0;
+ }else{
+ p = pSpace;
+ p->pChunk = 0;
+ p->db = db;
+ p->pEntry = 0;
+ p->pLast = 0;
+ p->pFresh = (struct RowSetEntry*)&p[1];
+ p->nFresh = (u16)((N - sizeof(*p))/sizeof(struct RowSetEntry));
+ p->isSorted = 1;
+ }
+ return p;
+}
+
+/*
+** Deallocate all chunks from a RowSet.
+*/
+SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){
+ struct RowSetChunk *pChunk, *pNextChunk;
+ for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
+ pNextChunk = pChunk->pNext;
+ sqlite3DbFree(p->db, pChunk);
+ }
+ p->pChunk = 0;
+ p->nFresh = 0;
+ p->pEntry = 0;
+ p->pLast = 0;
+ p->isSorted = 1;
+}
+
+/*
+** Insert a new value into a RowSet.
+**
+** The mallocFailed flag of the database connection is set if a
+** memory allocation fails.
+*/
+SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
+ struct RowSetEntry *pEntry;
+ struct RowSetEntry *pLast;
+ if( p==0 ) return; /* Must have been a malloc failure */
+ if( p->nFresh==0 ){
+ struct RowSetChunk *pNew;
+ pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew));
+ if( pNew==0 ){
+ return;
+ }
+ pNew->pNext = p->pChunk;
+ p->pChunk = pNew;
+ p->pFresh = pNew->aEntry;
+ p->nFresh = ROWSET_ENTRY_PER_CHUNK;
+ }
+ pEntry = p->pFresh++;
+ p->nFresh--;
+ pEntry->v = rowid;
+ pEntry->pNext = 0;
+ pLast = p->pLast;
+ if( pLast ){
+ if( p->isSorted && rowid<=pLast->v ){
+ p->isSorted = 0;
+ }
+ pLast->pNext = pEntry;
+ }else{
+ assert( p->pEntry==0 );
+ p->pEntry = pEntry;
+ }
+ p->pLast = pEntry;
+}
+
+/*
+** Merge two lists of RowSet entries. Remove duplicates.
+**
+** The input lists are assumed to be in sorted order.
+*/
+static struct RowSetEntry *boolidxMerge(
+ struct RowSetEntry *pA, /* First sorted list to be merged */
+ struct RowSetEntry *pB /* Second sorted list to be merged */
+){
+ struct RowSetEntry head;
+ struct RowSetEntry *pTail;
+
+ pTail = &head;
+ while( pA && pB ){
+ assert( pA->pNext==0 || pA->v<=pA->pNext->v );
+ assert( pB->pNext==0 || pB->v<=pB->pNext->v );
+ if( pA->v<pB->v ){
+ pTail->pNext = pA;
+ pA = pA->pNext;
+ pTail = pTail->pNext;
+ }else if( pB->v<pA->v ){
+ pTail->pNext = pB;
+ pB = pB->pNext;
+ pTail = pTail->pNext;
+ }else{
+ pA = pA->pNext;
+ }
+ }
+ if( pA ){
+ assert( pA->pNext==0 || pA->v<=pA->pNext->v );
+ pTail->pNext = pA;
+ }else{
+ assert( pB==0 || pB->pNext==0 || pB->v<=pB->pNext->v );
+ pTail->pNext = pB;
+ }
+ return head.pNext;
+}
+
+/*
+** Sort all elements of the RowSet into ascending order.
+*/
+static void sqlite3RowSetSort(RowSet *p){
+ unsigned int i;
+ struct RowSetEntry *pEntry;
+ struct RowSetEntry *aBucket[40];
+
+ assert( p->isSorted==0 );
+ memset(aBucket, 0, sizeof(aBucket));
+ while( p->pEntry ){
+ pEntry = p->pEntry;
+ p->pEntry = pEntry->pNext;
+ pEntry->pNext = 0;
+ for(i=0; aBucket[i]; i++){
+ pEntry = boolidxMerge(aBucket[i],pEntry);
+ aBucket[i] = 0;
+ }
+ aBucket[i] = pEntry;
+ }
+ pEntry = 0;
+ for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
+ pEntry = boolidxMerge(pEntry,aBucket[i]);
+ }
+ p->pEntry = pEntry;
+ p->pLast = 0;
+ p->isSorted = 1;
+}
+
+/*
+** Extract the next (smallest) element from the RowSet.
+** Write the element into *pRowid. Return 1 on success. Return
+** 0 if the RowSet is already empty.
+*/
+SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
+ if( !p->isSorted ){
+ sqlite3RowSetSort(p);
+ }
+ if( p->pEntry ){
+ *pRowid = p->pEntry->v;
+ p->pEntry = p->pEntry->pNext;
+ if( p->pEntry==0 ){
+ sqlite3RowSetClear(p);
+ }
+ return 1;
+ }else{
+ return 0;
+ }
+}
+
+/************** End of rowset.c **********************************************/
/************** Begin file pager.c *******************************************/
/*
** 2001 September 15
**
@@ -28746,9 +30530,9 @@
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.506.2.1 2008/11/26 14:55:02 drh Exp $
+** @(#) $Id: pager.c,v 1.514 2008/12/10 22:15:00 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
/*
@@ -29408,8 +31192,17 @@
/* The initial database size */
put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize);
/* The assumed sector size for this process */
put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
+
+ /* Initializing the tail of the buffer is not necessary. Everything
+ ** works find if the following memset() is omitted. But initializing
+ ** the memory prevents valgrind from complaining, so we are willing to
+ ** take the performance hit.
+ */
+ memset(&zHeader[sizeof(aJournalMagic)+16], 0,
+ nHeader-(sizeof(aJournalMagic)+16));
+
if( pPager->journalHdr==0 ){
/* The page size */
put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
}
@@ -29478,9 +31271,9 @@
&& iPageSize>=512
&& iPageSize<=SQLITE_MAX_PAGE_SIZE
&& ((iPageSize-1)&iPageSize)==0
){
- u16 pagesize = iPageSize;
+ u16 pagesize = (u16)iPageSize;
rc = sqlite3PagerSetPagesize(pPager, &pagesize);
}
if( rc ) return rc;
@@ -29533,9 +31326,9 @@
if( !zMaster || pPager->setMaster ) return SQLITE_OK;
if( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ) return SQLITE_OK;
pPager->setMaster = 1;
- len = strlen(zMaster);
+ len = sqlite3Strlen30(zMaster);
for(i=0; i<len; i++){
cksum += zMaster[i];
}
@@ -29965,15 +31758,15 @@
/* Load the entire master journal file into space obtained from
** sqlite3_malloc() and pointed to by zMasterJournal.
*/
- zMasterJournal = (char *)sqlite3Malloc(nMasterJournal + nMasterPtr);
+ zMasterJournal = (char *)sqlite3Malloc((int)nMasterJournal + nMasterPtr);
if( !zMasterJournal ){
rc = SQLITE_NOMEM;
goto delmaster_out;
}
zMasterPtr = &zMasterJournal[nMasterJournal];
- rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0);
+ rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
if( rc!=SQLITE_OK ) goto delmaster_out;
zJournal = zMasterJournal;
while( (zJournal-zMasterJournal)<nMasterJournal ){
@@ -30005,9 +31798,9 @@
/* We have a match. Do not delete the master journal file. */
goto delmaster_out;
}
}
- zJournal += (strlen(zJournal)+1);
+ zJournal += (sqlite3Strlen30(zJournal)+1);
}
}
rc = sqlite3OsDelete(pVfs, zMaster, 0);
@@ -30194,9 +31987,9 @@
** the value of nRec based on this assumption.
*/
if( nRec==0xffffffff ){
assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) );
- nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager);
+ nRec = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
}
/* If nRec is 0 and this rollback is of a transaction created by this
** process and if this is the final header in the journal, then it means
@@ -30207,9 +32000,9 @@
** The third term of the test was added to fix ticket #2565.
*/
if( nRec==0 && !isHot &&
pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
- nRec = (szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager);
+ nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
}
/* If this is the first header read from the journal, truncate the
** database file back to its original size.
@@ -30331,9 +32124,9 @@
** If it is not zero, then Pager.stmtHdrOff is the offset to the start
** of the first journal header written during this statement transaction.
*/
pPager->journalOff = pPager->stmtJSize;
- pPager->cksumInit = pPager->stmtCksum;
+ pPager->cksumInit = (int)(pPager->stmtCksum & 0xffffffff);
while( pPager->journalOff < hdrOff ){
rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
assert( rc!=SQLITE_DONE );
if( rc!=SQLITE_OK ) goto end_stmt_playback;
@@ -30347,9 +32140,9 @@
assert( rc!=SQLITE_DONE );
goto end_stmt_playback;
}
if( nJRec==0 ){
- nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8);
+ nJRec = (int)((szJ - pPager->journalOff) / (pPager->pageSize+8));
}
for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){
rc = pager_playback_one_page(pPager, pPager->jfd, pPager->journalOff, 1);
assert( rc!=SQLITE_DONE );
@@ -30401,10 +32194,10 @@
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int bFullFsync){
- pPager->noSync = level==1 || pPager->tempFile;
- pPager->fullSync = level==3 && !pPager->tempFile;
+ pPager->noSync = (level==1 || pPager->tempFile) ?1:0;
+ pPager->fullSync = (level==3 && !pPager->tempFile) ?1:0;
pPager->sync_flags = (bFullFsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
if( pPager->noSync ) pPager->needSync = 0;
}
#endif
@@ -30513,9 +32306,9 @@
if( rc!=SQLITE_OK ){
sqlite3_free(zPathname);
return rc;
}
- nPathname = strlen(zPathname);
+ nPathname = sqlite3Strlen30(zPathname);
}
/* Allocate memory for the pager structure */
pPager = sqlite3MallocZero(
@@ -30621,9 +32414,10 @@
IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename))
/* Fill in Pager.zDirectory[] */
memcpy(pPager->zDirectory, pPager->zFilename, nPathname+1);
- for(i=strlen(pPager->zDirectory); i>0 && pPager->zDirectory[i-1]!='/'; i--){}
+ for(i=sqlite3Strlen30(pPager->zDirectory);
+ i>0 && pPager->zDirectory[i-1]!='/'; i--){}
if( i>0 ) pPager->zDirectory[i-1] = 0;
/* Fill in Pager.zJournal[] */
if( zPathname ){
@@ -30633,14 +32427,14 @@
pPager->zJournal = 0;
}
/* pPager->journalOpen = 0; */
- pPager->useJournal = useJournal;
- pPager->noReadlock = noReadlock && readOnly;
+ pPager->useJournal = (u8)useJournal;
+ pPager->noReadlock = (noReadlock && readOnly) ?1:0;
/* pPager->stmtOpen = 0; */
/* pPager->stmtInUse = 0; */
/* pPager->nRef = 0; */
- pPager->dbSizeValid = memDb;
+ pPager->dbSizeValid = (u8)memDb;
pPager->pageSize = szPageDflt;
/* pPager->stmtSize = 0; */
/* pPager->stmtJSize = 0; */
/* pPager->nPage = 0; */
@@ -30648,18 +32442,18 @@
pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
/* pPager->state = PAGER_UNLOCK; */
assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
/* pPager->errMask = 0; */
- pPager->tempFile = tempFile;
+ pPager->tempFile = (u8)tempFile;
assert( tempFile==PAGER_LOCKINGMODE_NORMAL
|| tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
- pPager->exclusiveMode = tempFile;
- pPager->memDb = memDb;
- pPager->readOnly = readOnly;
+ pPager->exclusiveMode = (u8)tempFile;
+ pPager->memDb = (u8)memDb;
+ pPager->readOnly = (u8)readOnly;
/* pPager->needSync = 0; */
- pPager->noSync = pPager->tempFile || !useJournal;
- pPager->fullSync = (pPager->noSync?0:1);
+ pPager->noSync = (pPager->tempFile || !useJournal) ?1:0;
+ pPager->fullSync = pPager->noSync ?0:1;
pPager->sync_flags = SQLITE_SYNC_NORMAL;
/* pPager->pFirst = 0; */
/* pPager->pFirstSynced = 0; */
/* pPager->pLast = 0; */
@@ -30725,9 +32519,9 @@
pPager->pTmpSpace = pNew;
sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
}
}
- *pPageSize = pPager->pageSize;
+ *pPageSize = (u16)pPager->pageSize;
}
return rc;
}
@@ -30837,20 +32631,20 @@
}else{
n /= pPager->pageSize;
}
if( pPager->state!=PAGER_UNLOCK ){
- pPager->dbSize = n;
+ pPager->dbSize = (int)n;
pPager->dbSizeValid = 1;
}
}
if( n==(PENDING_BYTE/pPager->pageSize) ){
n++;
}
if( n>pPager->mxPgno ){
- pPager->mxPgno = n;
+ pPager->mxPgno = (Pgno)n;
}
if( pnPage ){
- *pnPage = n;
+ *pnPage = (int)n;
}
return SQLITE_OK;
}
@@ -30900,9 +32694,9 @@
do {
rc = sqlite3OsLock(pPager->fd, locktype);
}while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
if( rc==SQLITE_OK ){
- pPager->state = locktype;
+ pPager->state = (u8)locktype;
IOTRACE(("LOCK %p %d\n", pPager, locktype))
}
}
return rc;
@@ -31222,10 +33016,10 @@
*/
static int hasHotJournal(Pager *pPager, int *pExists){
sqlite3_vfs *pVfs = pPager->pVfs;
int rc = SQLITE_OK;
- int exists;
- int locked;
+ int exists = 0;
+ int locked = 0;
assert( pPager!=0 );
assert( pPager->useJournal );
assert( pPager->fd->pMethods );
*pExists = 0;
@@ -31311,9 +33105,9 @@
}
if( pPager->state==PAGER_UNLOCK || isErrorReset ){
sqlite3_vfs *pVfs = pPager->pVfs;
- int isHotJournal;
+ int isHotJournal = 0;
assert( !MEMDB );
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
if( !pPager->noReadlock ){
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
@@ -32543,9 +34337,9 @@
/*
** Return TRUE if the database file is opened read-only. Return FALSE
** if the database is (in theory) writable.
*/
-SQLITE_PRIVATE int sqlite3PagerIsreadonly(Pager *pPager){
+SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager *pPager){
return pPager->readOnly;
}
/*
@@ -32877,9 +34671,9 @@
|| eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
assert( PAGER_LOCKINGMODE_QUERY<0 );
assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
if( eMode>=0 && !pPager->tempFile ){
- pPager->exclusiveMode = eMode;
+ pPager->exclusiveMode = (u8)eMode;
}
return (int)pPager->exclusiveMode;
}
@@ -32907,9 +34701,9 @@
|| eMode==PAGER_JOURNALMODE_OFF
|| eMode==PAGER_JOURNALMODE_MEMORY );
assert( PAGER_JOURNALMODE_QUERY<0 );
if( eMode>=0 ){
- pPager->journalMode = eMode;
+ pPager->journalMode = (u8)eMode;
}else{
assert( eMode==PAGER_JOURNALMODE_QUERY );
}
}
@@ -32961,9 +34755,9 @@
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btreeInt.h,v 1.36 2008/11/19 10:22:33 danielk1977 Exp $
+** $Id: btreeInt.h,v 1.37 2008/12/10 16:45:51 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
@@ -33322,12 +35116,12 @@
Pgno nTrunc; /* Non-zero if the db will be truncated (incr vacuum) */
#endif
u16 pageSize; /* Total number of bytes on a page */
u16 usableSize; /* Number of usable bytes on each page */
- int maxLocal; /* Maximum local payload in non-LEAFDATA tables */
- int minLocal; /* Minimum local payload in non-LEAFDATA tables */
- int maxLeaf; /* Maximum local payload in a LEAFDATA table */
- int minLeaf; /* Minimum local payload in a LEAFDATA table */
+ u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
+ u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
+ u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
+ u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
u8 inTransaction; /* Transaction state */
int nTransaction; /* Number of open transactions (read + write) */
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
@@ -33567,9 +35361,9 @@
/*
** Read or write a two- and four-byte big-endian integer values.
*/
#define get2byte(x) ((x)[0]<<8 | (x)[1])
-#define put2byte(p,v) ((p)[0] = (v)>>8, (p)[1] = (v))
+#define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v))
#define get4byte sqlite3Get4byte
#define put4byte sqlite3Put4byte
/*
@@ -33894,9 +35688,9 @@
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.539.2.2 2008/11/26 14:55:02 drh Exp $
+** $Id: btree.c,v 1.548 2008/12/16 13:46:30 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
@@ -34200,11 +35994,11 @@
** table, then malloc space for and store the pCur->nKey bytes of key
** data.
*/
if( rc==SQLITE_OK && 0==pCur->apPage[0]->intKey){
- void *pKey = sqlite3Malloc(pCur->nKey);
+ void *pKey = sqlite3Malloc( (int)pCur->nKey );
if( pKey ){
- rc = sqlite3BtreeKey(pCur, 0, pCur->nKey, pKey);
+ rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey);
if( rc==SQLITE_OK ){
pCur->pKey = pKey;
}else{
sqlite3_free(pKey);
@@ -34459,9 +36253,9 @@
MemPage *pPage, /* Page containing the cell */
u8 *pCell, /* Pointer to the cell text. */
CellInfo *pInfo /* Fill in this structure */
){
- int n; /* Number bytes in cell content header */
+ u16 n; /* Number bytes in cell content header */
u32 nPayload; /* Number of bytes of cell payload */
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
@@ -34489,14 +36283,14 @@
** on the local page. No overflow is required.
*/
int nSize; /* Total size of cell content in bytes */
nSize = nPayload + n;
- pInfo->nLocal = nPayload;
+ pInfo->nLocal = (u16)nPayload;
pInfo->iOverflow = 0;
if( (nSize & ~3)==0 ){
nSize = 4; /* Minimum cell size is 4 */
}
- pInfo->nSize = nSize;
+ pInfo->nSize = (u16)nSize;
}else{
/* If the payload will not fit completely on the local page, we have
** to decide how much to store locally and how much to spill onto
** overflow pages. The strategy is to minimize the amount of unused
@@ -34513,13 +36307,13 @@
minLocal = pPage->minLocal;
maxLocal = pPage->maxLocal;
surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4);
if( surplus <= maxLocal ){
- pInfo->nLocal = surplus;
- }else{
- pInfo->nLocal = minLocal;
- }
- pInfo->iOverflow = pInfo->nLocal + n;
+ pInfo->nLocal = (u16)surplus;
+ }else{
+ pInfo->nLocal = (u16)minLocal;
+ }
+ pInfo->iOverflow = (u16)(pInfo->nLocal + n);
pInfo->nSize = pInfo->iOverflow + 4;
}
}
#define parseCell(pPage, iCell, pInfo) \
@@ -34638,8 +36432,9 @@
data[hdr+2] = 0;
data[hdr+7] = 0;
addr = cellOffset+2*nCell;
memset(&data[addr], 0, cbrk-addr);
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
if( cbrk-addr!=pPage->nFree ){
return SQLITE_CORRUPT_BKPT;
}
return SQLITE_OK;
@@ -34672,9 +36467,9 @@
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( nByte>=0 ); /* Minimum cell size is 4 */
assert( pPage->nFree>=nByte );
assert( pPage->nOverflow==0 );
- pPage->nFree -= nByte;
+ pPage->nFree -= (u16)nByte;
hdr = pPage->hdrOffset;
nFrag = data[hdr+7];
if( nFrag<60 ){
@@ -34683,15 +36478,16 @@
addr = hdr+1;
while( (pc = get2byte(&data[addr]))>0 ){
size = get2byte(&data[pc+2]);
if( size>=nByte ){
+ int x = size - nByte;
if( size<nByte+4 ){
memcpy(&data[addr], &data[pc], 2);
- data[hdr+7] = nFrag + size - nByte;
+ data[hdr+7] = (u8)(nFrag + x);
return pc;
}else{
- put2byte(&data[pc+2], size-nByte);
- return pc + size - nByte;
+ put2byte(&data[pc+2], x);
+ return pc + x;
}
}
addr = pc;
}
@@ -34709,8 +36505,9 @@
}
top -= nByte;
assert( cellOffset + 2*nCell <= top );
put2byte(&data[hdr+5], top);
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
return top;
}
/*
@@ -34754,26 +36551,28 @@
assert( pbegin>addr || pbegin==0 );
put2byte(&data[addr], start);
put2byte(&data[start], pbegin);
put2byte(&data[start+2], size);
- pPage->nFree += size;
+ pPage->nFree += (u16)size;
/* Coalesce adjacent free blocks */
addr = pPage->hdrOffset + 1;
while( (pbegin = get2byte(&data[addr]))>0 ){
- int pnext, psize;
+ int pnext, psize, x;
assert( pbegin>addr );
assert( pbegin<=pPage->pBt->usableSize-4 );
pnext = get2byte(&data[pbegin]);
psize = get2byte(&data[pbegin+2]);
if( pbegin + psize + 3 >= pnext && pnext>0 ){
int frag = pnext - (pbegin+psize);
- if( (frag<0) || (frag>data[pPage->hdrOffset+7]) ){
+ if( (frag<0) || (frag>(int)data[pPage->hdrOffset+7]) ){
return SQLITE_CORRUPT_BKPT;
}
- data[pPage->hdrOffset+7] -= frag;
- put2byte(&data[pbegin], get2byte(&data[pnext]));
- put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin);
+ data[pPage->hdrOffset+7] -= (u8)frag;
+ x = get2byte(&data[pnext]);
+ put2byte(&data[pbegin], x);
+ x = pnext + get2byte(&data[pnext+2]) - pbegin;
+ put2byte(&data[pbegin+2], x);
}else{
addr = pbegin;
}
}
@@ -34782,11 +36581,12 @@
if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){
int top;
pbegin = get2byte(&data[hdr+1]);
memcpy(&data[hdr+1], &data[pbegin], 2);
- top = get2byte(&data[hdr+5]);
- put2byte(&data[hdr+5], top + get2byte(&data[pbegin+2]));
- }
+ top = get2byte(&data[hdr+5]) + get2byte(&data[pbegin+2]);
+ put2byte(&data[hdr+5], top);
+ }
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
return SQLITE_OK;
}
/*
@@ -34805,9 +36605,9 @@
BtShared *pBt; /* A copy of pPage->pBt */
assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->leaf = flagByte>>3; assert( PTF_LEAF == 1<<3 );
+ pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
flagByte &= ~PTF_LEAF;
pPage->childPtrSize = 4-4*pPage->leaf;
pBt = pPage->pBt;
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
@@ -34843,16 +36643,16 @@
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
if( !pPage->isInit ){
- int pc; /* Address of a freeblock within pPage->aData[] */
- int hdr; /* Offset to beginning of page header */
+ u16 pc; /* Address of a freeblock within pPage->aData[] */
+ u8 hdr; /* Offset to beginning of page header */
u8 *data; /* Equal to pPage->aData */
BtShared *pBt; /* The main btree structure */
- int usableSize; /* Amount of usable space on each page */
- int cellOffset; /* Offset from start of page to first cell pointer */
- int nFree; /* Number of unused bytes on the page */
- int top; /* First byte of the cell content area */
+ u16 usableSize; /* Amount of usable space on each page */
+ u16 cellOffset; /* Offset from start of page to first cell pointer */
+ u16 nFree; /* Number of unused bytes on the page */
+ u16 top; /* First byte of the cell content area */
pBt = pPage->pBt;
hdr = pPage->hdrOffset;
@@ -34873,9 +36673,9 @@
/* Compute the total free space on the page */
pc = get2byte(&data[hdr+1]);
nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell);
while( pc>0 ){
- int next, size;
+ u16 next, size;
if( pc>usableSize-4 ){
/* Free block is off the page */
return SQLITE_CORRUPT_BKPT;
}
@@ -34887,9 +36687,9 @@
}
nFree += size;
pc = next;
}
- pPage->nFree = nFree;
+ pPage->nFree = (u16)nFree;
if( nFree>=usableSize ){
/* Free space cannot exceed total page size */
return SQLITE_CORRUPT_BKPT;
}
@@ -34925,19 +36725,19 @@
*/
static void zeroPage(MemPage *pPage, int flags){
unsigned char *data = pPage->aData;
BtShared *pBt = pPage->pBt;
- int hdr = pPage->hdrOffset;
- int first;
+ u8 hdr = pPage->hdrOffset;
+ u16 first;
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlite3_mutex_held(pBt->mutex) );
/*memset(&data[hdr], 0, pBt->usableSize - hdr);*/
- data[hdr] = flags;
- first = hdr + 8 + 4*((flags&PTF_LEAF)==0);
+ data[hdr] = (char)flags;
+ first = hdr + 8 + 4*((flags&PTF_LEAF)==0 ?1:0);
memset(&data[hdr+1], 0, 4);
data[hdr+7] = 0;
put2byte(&data[hdr+5], pBt->usableSize);
pPage->nFree = pBt->usableSize - first;
@@ -35118,9 +36918,9 @@
sqlite3_vfs *pVfs; /* The VFS to use for this btree */
BtShared *pBt = 0; /* Shared part of btree structure */
Btree *p; /* Handle to return */
int rc = SQLITE_OK;
- int nReserve;
+ u8 nReserve;
unsigned char zDbHeader[100];
/* Set the variable isMemdb to true for an in-memory database, or
** false for a file-based database. This symbol is only required if
@@ -35515,8 +37315,9 @@
*/
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){
int rc = SQLITE_OK;
BtShared *pBt = p->pBt;
+ assert( nReserve>=-1 && nReserve<=255 );
sqlite3BtreeEnter(p);
if( pBt->pageSizeFixed ){
sqlite3BtreeLeave(p);
return SQLITE_READONLY;
@@ -35523,17 +37324,18 @@
}
if( nReserve<0 ){
nReserve = pBt->pageSize - pBt->usableSize;
}
+ assert( nReserve>=0 && nReserve<=255 );
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pPage1 && !pBt->pCursor );
- pBt->pageSize = pageSize;
+ pBt->pageSize = (u16)pageSize;
freeTempSpace(pBt);
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
}
- pBt->usableSize = pBt->pageSize - nReserve;
+ pBt->usableSize = pBt->pageSize - (u16)nReserve;
sqlite3BtreeLeave(p);
return rc;
}
@@ -35576,9 +37378,9 @@
return SQLITE_READONLY;
#else
BtShared *pBt = p->pBt;
int rc = SQLITE_OK;
- int av = (autoVacuum?1:0);
+ u8 av = autoVacuum ?1:0;
sqlite3BtreeEnter(p);
if( pBt->pageSizeFixed && av!=pBt->autoVacuum ){
rc = SQLITE_READONLY;
@@ -35674,19 +37476,19 @@
** zero and return SQLITE_OK. The caller will call this function
** again with the correct page-size.
*/
releasePage(pPage1);
- pBt->usableSize = usableSize;
- pBt->pageSize = pageSize;
+ pBt->usableSize = (u16)usableSize;
+ pBt->pageSize = (u16)pageSize;
freeTempSpace(pBt);
sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
return SQLITE_OK;
}
if( usableSize<500 ){
goto page1_init_failed;
}
- pBt->pageSize = pageSize;
- pBt->usableSize = usableSize;
+ pBt->pageSize = (u16)pageSize;
+ pBt->usableSize = (u16)usableSize;
#ifndef SQLITE_OMIT_AUTOVACUUM
pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0);
pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0);
#endif
@@ -35796,9 +37598,10 @@
assert( sizeof(zMagicHeader)==16 );
put2byte(&data[16], pBt->pageSize);
data[18] = 1;
data[19] = 1;
- data[20] = pBt->pageSize - pBt->usableSize;
+ assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize);
+ data[20] = (u8)(pBt->pageSize - pBt->usableSize);
data[21] = 64;
data[22] = 32;
data[23] = 32;
memset(&data[24], 0, 100-24);
@@ -35951,9 +37754,9 @@
int i; /* Counter variable */
int nCell; /* Number of cells in page pPage */
int rc; /* Return code */
BtShared *pBt = pPage->pBt;
- int isInitOrig = pPage->isInit;
+ u8 isInitOrig = pPage->isInit;
Pgno pgno = pPage->pgno;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
rc = sqlite3BtreeInitPage(pPage);
@@ -36003,16 +37806,17 @@
** overflow page in the list.
*/
static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
if( eType==PTRMAP_OVERFLOW2 ){
/* The pointer is always the first 4 bytes of the page in this case. */
if( get4byte(pPage->aData)!=iFrom ){
return SQLITE_CORRUPT_BKPT;
}
put4byte(pPage->aData, iTo);
}else{
- int isInitOrig = pPage->isInit;
+ u8 isInitOrig = pPage->isInit;
int i;
int nCell;
sqlite3BtreeInitPage(pPage);
@@ -36693,8 +38497,9 @@
Pgno nPage;
BtShared *pBt = p->pBt;
assert( sqlite3BtreeHoldsMutex(p) );
+ assert( wrFlag==0 || wrFlag==1 );
if( wrFlag ){
if( pBt->readOnly ){
return SQLITE_READONLY;
}
@@ -36732,9 +38537,9 @@
*/
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
- pCur->wrFlag = wrFlag;
+ pCur->wrFlag = (u8)wrFlag;
pCur->pNext = pBt->pCursor;
if( pCur->pNext ){
pCur->pNext->pPrev = pCur;
}
@@ -36950,9 +38755,9 @@
MemPage **ppPage, /* OUT: MemPage handle */
Pgno *pPgnoNext /* OUT: Next overflow page number */
){
Pgno next = 0;
- int rc;
+ int rc = SQLITE_OK;
assert( sqlite3_mutex_held(pBt->mutex) );
/* One of these must not be NULL. Otherwise, why call this function? */
assert(ppPage || pPgnoNext);
@@ -37095,9 +38900,9 @@
assert( cursorHoldsMutex(pCur) );
getCellInfo(pCur);
aPayload = pCur->info.pCell + pCur->info.nHeader;
- nKey = (pPage->intKey ? 0 : pCur->info.nKey);
+ nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
if( skipKey ){
offset += nKey;
}
@@ -37302,9 +39107,9 @@
aPayload += pCur->info.nHeader;
if( pPage->intKey ){
nKey = 0;
}else{
- nKey = pCur->info.nKey;
+ nKey = (int)pCur->info.nKey;
}
if( skipKey ){
aPayload += nKey;
nLocal = pCur->info.nLocal - nKey;
@@ -37512,9 +39317,9 @@
*/
static int moveToRightmost(BtCursor *pCur){
Pgno pgno;
int rc = SQLITE_OK;
- MemPage *pPage;
+ MemPage *pPage = 0;
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
@@ -37572,9 +39377,9 @@
assert( pCur->eState==CURSOR_VALID );
*pRes = 0;
rc = moveToRightmost(pCur);
getCellInfo(pCur);
- pCur->atLast = rc==SQLITE_OK;
+ pCur->atLast = rc==SQLITE_OK ?1:0;
}
}
return rc;
}
@@ -37656,11 +39461,11 @@
rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
if( biasRight ){
- pCur->aiIdx[pCur->iPage] = upr;
- }else{
- pCur->aiIdx[pCur->iPage] = (upr+lwr)/2;
+ pCur->aiIdx[pCur->iPage] = (u16)upr;
+ }else{
+ pCur->aiIdx[pCur->iPage] = (u16)((upr+lwr)/2);
}
if( lwr<=upr ) for(;;){
void *pCellKey;
i64 nCellKey;
@@ -37687,17 +39492,17 @@
int available;
pCellKey = (void *)fetchPayload(pCur, &available, 0);
nCellKey = pCur->info.nKey;
if( available>=nCellKey ){
- c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
- }else{
- pCellKey = sqlite3Malloc( nCellKey );
+ c = sqlite3VdbeRecordCompare((int)nCellKey, pCellKey, pIdxKey);
+ }else{
+ pCellKey = sqlite3Malloc( (int)nCellKey );
if( pCellKey==0 ){
rc = SQLITE_NOMEM;
goto moveto_finish;
}
- rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
- c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
+ rc = sqlite3BtreeKey(pCur, 0, (int)nCellKey, (void*)pCellKey);
+ c = sqlite3VdbeRecordCompare((int)nCellKey, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
if( rc ) goto moveto_finish;
}
}
@@ -37721,9 +39526,9 @@
if( lwr>upr ){
pCur->info.nKey = nCellKey;
break;
}
- pCur->aiIdx[pCur->iPage] = (lwr+upr)/2;
+ pCur->aiIdx[pCur->iPage] = (u16)((lwr+upr)/2);
}
assert( lwr==upr+1 );
assert( pPage->isInit );
if( pPage->leaf ){
@@ -37738,9 +39543,9 @@
if( pRes ) *pRes = c;
rc = SQLITE_OK;
goto moveto_finish;
}
- pCur->aiIdx[pCur->iPage] = lwr;
+ pCur->aiIdx[pCur->iPage] = (u16)lwr;
pCur->info.nSize = 0;
pCur->validNKey = 0;
rc = moveToChild(pCur, chldPg);
if( rc ) goto moveto_finish;
@@ -37765,9 +39570,10 @@
UnpackedRecord *pIdxKey; /* Unpacked index key */
UnpackedRecord aSpace[16]; /* Temp space for pIdxKey - to avoid a malloc */
if( pKey ){
- pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
+ assert( nKey==(i64)(int)nKey );
+ pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey,
aSpace, sizeof(aSpace));
if( pIdxKey==0 ) return SQLITE_NOMEM;
}else{
pIdxKey = 0;
@@ -38074,8 +39880,9 @@
put4byte(&pNewTrunk->aData[4], k-1);
memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
releasePage(pNewTrunk);
if( !pPrevTrunk ){
+ assert( sqlite3PagerIswriteable(pPage1->pDbPage) );
put4byte(&pPage1->aData[32], iNewTrunk);
}else{
rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
if( rc ){
@@ -38129,8 +39936,9 @@
if( closest<k-1 ){
memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
}
put4byte(&aData[4], k-1);
+ assert( sqlite3PagerIswriteable(pTrunk->pDbPage) );
rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, 1);
if( rc==SQLITE_OK ){
sqlite3PagerDontRollback((*ppPage)->pDbPage);
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
@@ -38364,8 +40172,13 @@
CellInfo info;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ /* pPage is not necessarily writeable since pCell might be auxiliary
+ ** buffer space that is separate from the pPage buffer area */
+ assert( pCell<pPage->aData || pCell>=&pPage->aData[pBt->pageSize]
+ || sqlite3PagerIswriteable(pPage->pDbPage) );
+
/* Fill in the header. */
nHeader = 0;
if( !pPage->leaf ){
nHeader += 4;
@@ -38387,11 +40200,12 @@
pSrc = pData;
nSrc = nData;
nData = 0;
}else{
- nPayload += nKey;
+ /* TBD: Perhaps raise SQLITE_CORRUPT if nKey is larger than 31 bits? */
+ nPayload += (int)nKey;
pSrc = pKey;
- nSrc = nKey;
+ nSrc = (int)nKey;
}
*pnSize = info.nSize;
spaceLeft = info.nLocal;
pPayload = &pCell[nHeader];
@@ -38398,9 +40212,8 @@
pPrior = &pCell[info.iOverflow];
while( nPayload>0 ){
if( spaceLeft==0 ){
- int isExact = 0;
#ifndef SQLITE_OMIT_AUTOVACUUM
Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */
if( pBt->autoVacuum ){
do{
@@ -38407,14 +40220,11 @@
pgnoOvfl++;
} while(
PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt)
);
- if( pgnoOvfl>1 ){
- /* isExact = 1; */
- }
- }
-#endif
- rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, isExact);
+ }
+#endif
+ rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);
#ifndef SQLITE_OMIT_AUTOVACUUM
/* If the database supports auto-vacuum, and the second or subsequent
** overflow page is being allocated, add an entry to the pointer-map
** for that page now.
@@ -38436,8 +40246,18 @@
if( rc ){
releasePage(pToRelease);
return rc;
}
+
+ /* If pToRelease is not zero than pPrior points into the data area
+ ** of pToRelease. Make sure pToRelease is still writeable. */
+ assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
+
+ /* If pPrior is part of the data area of pPage, then make sure pPage
+ ** is still writeable */
+ assert( pPrior<pPage->aData || pPrior>=&pPage->aData[pBt->pageSize]
+ || sqlite3PagerIswriteable(pPage->pDbPage) );
+
put4byte(pPrior, pgnoOvfl);
releasePage(pToRelease);
pToRelease = pOvfl;
pPrior = pOvfl->aData;
@@ -38446,8 +40266,18 @@
spaceLeft = pBt->usableSize - 4;
}
n = nPayload;
if( n>spaceLeft ) n = spaceLeft;
+
+ /* If pToRelease is not zero than pPayload points into the data area
+ ** of pToRelease. Make sure pToRelease is still writeable. */
+ assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
+
+ /* If pPayload is part of the data area of pPage, then make sure pPage
+ ** is still writeable */
+ assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
+ || sqlite3PagerIswriteable(pPage->pDbPage) );
+
if( nSrc>0 ){
if( n>nSrc ) n = nSrc;
assert( pSrc );
memcpy(pPayload, pSrc, n);
@@ -38489,9 +40319,10 @@
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
data = pPage->aData;
ptr = &data[pPage->cellOffset + 2*idx];
pc = get2byte(ptr);
- if ( (pc<pPage->hdrOffset+6+(pPage->leaf?0:4)) || (pc+sz>pPage->pBt->usableSize) ) {
+ if( (pc<pPage->hdrOffset+6+(pPage->leaf?0:4))
+ || (pc+sz>pPage->pBt->usableSize) ){
return SQLITE_CORRUPT_BKPT;
}
rc = freeSpace(pPage, pc, sz);
if( rc!=SQLITE_OK ){
@@ -38542,8 +40373,10 @@
u8 *data; /* The content of the whole page */
u8 *ptr; /* Used for moving information around in data[] */
assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
+ assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 );
+ assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) );
assert( sz==cellSizePtr(pPage, pCell) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
if( pPage->nOverflow || sz+2>pPage->nFree ){
if( pTemp ){
@@ -38552,9 +40385,9 @@
}
j = pPage->nOverflow++;
assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) );
pPage->aOvfl[j].pCell = pCell;
- pPage->aOvfl[j].idx = i;
+ pPage->aOvfl[j].idx = (u16)i;
pPage->nFree = 0;
}else{
int rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc!=SQLITE_OK ){
@@ -38628,14 +40461,16 @@
u8 *data; /* Data for the page */
assert( pPage->nOverflow==0 );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( nCell>=0 && nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 );
totalSize = 0;
for(i=0; i<nCell; i++){
totalSize += aSize[i];
}
assert( totalSize+2*nCell<=pPage->nFree );
assert( pPage->nCell==0 );
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
cellptr = pPage->cellOffset;
data = pPage->aData;
hdr = pPage->hdrOffset;
put2byte(&data[hdr+3], nCell);
@@ -38651,9 +40486,9 @@
cellbody += aSize[i];
}
assert( cellbody==pPage->pBt->usableSize );
}
- pPage->nCell = nCell;
+ pPage->nCell = (u16)nCell;
}
/*
** The following parameters determine how many adjacent pages get involved
@@ -38713,8 +40548,9 @@
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
if( rc==SQLITE_OK ){
pCell = pPage->aOvfl[0].pCell;
szCell = cellSizePtr(pPage, pCell);
+ assert( sqlite3PagerIswriteable(pNew->pDbPage) );
zeroPage(pNew, pPage->aData[0]);
assemblePage(pNew, 1, &pCell, &szCell);
pPage->nOverflow = 0;
@@ -38966,15 +40802,15 @@
goto balance_cleanup;
}
szCell = (u16*)&apCell[nMaxCells];
aCopy[0] = (u8*)&szCell[nMaxCells];
- assert( ((aCopy[0] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
+ assert( ((aCopy[0] - (u8*)0) & 7)==0 ); /* 8-byte alignment required */
for(i=1; i<NB; i++){
aCopy[i] = &aCopy[i-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
- assert( ((aCopy[i] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
+ assert( ((aCopy[i] - (u8*)0) & 7)==0 ); /* 8-byte alignment required */
}
aSpace1 = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
- assert( ((aSpace1 - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */
+ assert( ((aSpace1 - (u8*)0) & 7)==0 ); /* 8-byte alignment required */
if( ISAUTOVACUUM ){
aFrom = &aSpace1[pBt->pageSize];
}
aSpace2 = sqlite3PageMalloc(pBt->pageSize);
@@ -39023,9 +40859,9 @@
apCell[nCell] = findOverflowCell(pOld, j);
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
if( ISAUTOVACUUM ){
int a;
- aFrom[nCell] = i;
+ aFrom[nCell] = (u8)i; assert( i>=0 && i<6 );
for(a=0; a<pOld->nOverflow; a++){
if( pOld->aOvfl[a].pCell==apCell[nCell] ){
aFrom[nCell] = 0xFF;
break;
@@ -39056,9 +40892,10 @@
if( ISAUTOVACUUM ){
aFrom[nCell] = 0xFF;
}
dropCell(pParent, nxDiv, sz);
- szCell[nCell] -= leafCorrection;
+ assert( leafCorrection==0 || leafCorrection==4 );
+ szCell[nCell] -= (u16)leafCorrection;
assert( get4byte(pTemp)==pgnoOld[i] );
if( !pOld->leaf ){
assert( leafCorrection==0 );
/* The right pointer of the child page pOld becomes the left
@@ -39315,8 +41152,9 @@
assert( sz<=pBt->pageSize/4 );
assert( iSpace2<=pBt->pageSize );
rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4);
if( rc!=SQLITE_OK ) goto balance_cleanup;
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno);
/* If this is an auto-vacuum database, and not a leaf-data tree,
** then update the pointer map with an entry for the overflow page
@@ -39352,8 +41190,9 @@
goto balance_cleanup;
}
}
}
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
if( nxDiv==pParent->nCell+pParent->nOverflow ){
/* Right-most sibling is the right-most child of pParent */
put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew[nNew-1]);
}else{
@@ -39385,8 +41224,9 @@
}
for(i=0; i<nNew; i++){
releasePage(apNew[i]);
}
+ pPage->nOverflow = 0;
/* releasePage(pParent); */
TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n",
pPage->pgno, nOld, nNew, nCell));
@@ -39455,11 +41295,12 @@
szCell[i] = cellSizePtr(pChild, apCell[i]);
}
assemblePage(pPage, pChild->nCell, apCell, szCell);
/* Copy the right-pointer of the child to the parent. */
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
put4byte(&pPage->aData[pPage->hdrOffset+8],
get4byte(&pChild->aData[pChild->hdrOffset+8]));
- freePage(pChild);
+ rc = freePage(pChild);
TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno));
}else{
/* The child has more information that will fit on the root.
** The tree is already balanced. Do nothing. */
@@ -39475,9 +41316,9 @@
pChild->pgno, pPage->pgno));
}
assert( pPage->nOverflow==0 );
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( ISAUTOVACUUM ){
+ if( ISAUTOVACUUM && rc==SQLITE_OK ){
rc = setChildPtrmaps(pPage);
}
#endif
releasePage(pChild);
@@ -39515,8 +41356,9 @@
VVA_ONLY( pCur->pagesShuffled = 1 );
pPage = pCur->apPage[0];
pBt = pPage->pBt;
assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0);
if( rc ) return rc;
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
usableSize = pBt->usableSize;
@@ -39536,8 +41378,9 @@
if( pChild->nOverflow ){
pChild->nFree = 0;
}
assert( pChild->nCell==pPage->nCell );
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF);
put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild);
TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno));
if( ISAUTOVACUUM ){
@@ -39579,16 +41422,19 @@
if( pCur->iPage==0 ){
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc==SQLITE_OK && pPage->nOverflow>0 ){
rc = balance_deeper(pCur);
+ assert( pPage->nOverflow==0 || rc!=SQLITE_OK );
}
if( rc==SQLITE_OK && pPage->nCell==0 ){
rc = balance_shallower(pCur);
+ assert( pPage->nOverflow==0 || rc!=SQLITE_OK );
}
}else{
if( pPage->nOverflow>0 ||
(!isInsert && pPage->nFree>pPage->pBt->usableSize*2/3) ){
rc = balance_nonroot(pCur);
+ assert( pPage->nOverflow==0 || rc!=SQLITE_OK );
}
}
return rc;
}
@@ -39755,10 +41601,17 @@
}else{
assert( pPage->leaf );
}
rc = insertCell(pPage, idx, newCell, szNew, 0, 0);
- if( rc!=SQLITE_OK ) goto end_insert;
- rc = balance(pCur, 1);
+ if( rc==SQLITE_OK ){
+ rc = balance(pCur, 1);
+ }
+
+ /* Must make sure nOverflow is reset to zero even if the balance()
+ ** fails. Internal data structure corruption will result otherwise. */
+ assert( pPage->nOverflow==0 || rc!=SQLITE_OK );
+ pPage->nOverflow = 0;
+
if( rc==SQLITE_OK ){
moveToRoot(pCur);
}
end_insert:
@@ -39834,9 +41687,9 @@
** next Cell after the one to be deleted is guaranteed to exist and
** to be a leaf so we can use it.
*/
BtCursor leafCur;
- MemPage *pLeafPage;
+ MemPage *pLeafPage = 0;
unsigned char *pNext;
int notUsed;
unsigned char *tempCell = 0;
@@ -39905,8 +41758,9 @@
leafCursorInvalid = 1;
}
if( rc==SQLITE_OK ){
+ assert( sqlite3PagerIswriteable(pPage->pDbPage) );
put4byte(findOverflowCell(pPage, idx), pgnoChild);
VVA_ONLY( pCur->pagesShuffled = 0 );
rc = balance(pCur, 0);
}
@@ -39944,12 +41798,11 @@
assert( pLeafPage->pgno==leafPgno );
assert( leafCur.aiIdx[leafCur.iPage]==0 );
}
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pLeafPage->pDbPage);
- }
- if( rc==SQLITE_OK ){
+ if( SQLITE_OK==rc
+ && SQLITE_OK==(rc = sqlite3PagerWrite(pLeafPage->pDbPage))
+ ){
dropCell(pLeafPage, 0, szNext);
VVA_ONLY( leafCur.pagesShuffled = 0 );
rc = balance(&leafCur, 0);
assert( leafCursorInvalid || !leafCur.pagesShuffled
@@ -40349,9 +42202,9 @@
** layer (and the SetCookie and ReadCookie opcodes) the number of
** free pages is not visible. So Cookie[0] is the same as Meta[1].
*/
SQLITE_PRIVATE int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
- DbPage *pDbPage;
+ DbPage *pDbPage = 0;
int rc;
unsigned char *pP1;
BtShared *pBt = p->pBt;
@@ -40432,9 +42285,9 @@
#ifndef SQLITE_OMIT_AUTOVACUUM
if( idx==7 ){
assert( pBt->autoVacuum || iMeta==0 );
assert( iMeta==0 || iMeta==1 );
- pBt->incrVacuum = iMeta;
+ pBt->incrVacuum = (u8)iMeta;
}
#endif
}
}
@@ -40536,8 +42389,9 @@
Pgno iPtrmapParent;
rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
if( rc!=SQLITE_OK ){
+ if( rc==SQLITE_NOMEM ) pCheck->mallocFailed = 1;
checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild);
return;
}
@@ -40662,13 +42516,15 @@
usableSize = pBt->usableSize;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
if( (rc = sqlite3BtreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
+ if( rc==SQLITE_NOMEM ) pCheck->mallocFailed = 1;
checkAppendMsg(pCheck, zContext,
"unable to get the page. error code=%d", rc);
return 0;
}
if( (rc = sqlite3BtreeInitPage(pPage))!=0 ){
+ if( rc==SQLITE_NOMEM ) pCheck->mallocFailed = 1;
checkAppendMsg(pCheck, zContext,
"sqlite3BtreeInitPage() returns error code %d", rc);
releasePage(pPage);
return 0;
@@ -40688,9 +42544,9 @@
"On tree page %d cell %d: ", iPage, i);
pCell = findCell(pPage,i);
sqlite3BtreeParseCellPtr(pPage, pCell, &info);
sz = info.nData;
- if( !pPage->intKey ) sz += info.nKey;
+ if( !pPage->intKey ) sz += (int)info.nKey;
assert( sz==info.nPayload );
if( sz>info.nLocal ){
int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4);
Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
@@ -40803,11 +42659,11 @@
** an array of pages numbers were each page number is the root page of
** a table. nRoot is the number of entries in aRoot.
**
** Write the number of error seen in *pnErr. Except for some memory
-** allocation errors, nn error message is held in memory obtained from
+** allocation errors, an error message held in memory obtained from
** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is
-** returned.
+** returned. If a memory allocation error occurs, NULL is returned.
*/
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
Btree *p, /* The btree to be checked */
int *aRoot, /* An array of root pages numbers for individual trees */
@@ -41004,10 +42860,10 @@
/* Variable nNewPage is the number of pages required to store the
** contents of pFrom using the current page-size of pTo.
*/
- nNewPage = ((i64)nFromPage * (i64)nFromPageSize + (i64)nToPageSize - 1) /
- (i64)nToPageSize;
+ nNewPage = (Pgno)
+ (((i64)nFromPage*(i64)nFromPageSize+(i64)nToPageSize-1)/(i64)nToPageSize);
for(i=1; rc==SQLITE_OK && (i<=nToPage || i<=nNewPage); i++){
/* Journal the original page.
@@ -41054,9 +42910,9 @@
rc==SQLITE_OK && iOff<i*nToPageSize;
iOff += nFromPageSize
){
DbPage *pFromPage = 0;
- Pgno iFrom = (iOff/nFromPageSize)+1;
+ Pgno iFrom = (Pgno)(iOff/nFromPageSize)+1;
if( iFrom==PENDING_BYTE_PAGE(pBtFrom) ){
continue;
}
@@ -41135,9 +42991,9 @@
rc==SQLITE_OK && iOff<(iPending+nToPageSize);
iOff += nFromPageSize
){
DbPage *pFromPage = 0;
- Pgno iFrom = (iOff/nFromPageSize)+1;
+ Pgno iFrom = (Pgno)(iOff/nFromPageSize)+1;
if( iFrom==PENDING_BYTE_PAGE(pBtFrom) || iFrom>nFromPage ){
continue;
}
@@ -41331,139 +43187,8 @@
}
#endif
/************** End of btree.c ***********************************************/
-/************** Begin file vdbefifo.c ****************************************/
-/*
-** 2005 June 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 implements a FIFO queue of rowids used for processing
-** UPDATE and DELETE statements.
-**
-** $Id: vdbefifo.c,v 1.9 2008/11/17 19:18:55 danielk1977 Exp $
-*/
-
-/*
-** Constants FIFOSIZE_FIRST and FIFOSIZE_MAX are the initial
-** number of entries in a fifo page and the maximum number of
-** entries in a fifo page.
-*/
-#define FIFOSIZE_FIRST (((128-sizeof(FifoPage))/8)+1)
-#ifdef SQLITE_MALLOC_SOFT_LIMIT
-# define FIFOSIZE_MAX (int)(((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1)
-#else
-# define FIFOSIZE_MAX (int)(((262144-sizeof(FifoPage))/8)+1)
-#endif
-
-/*
-** Allocate a new FifoPage and return a pointer to it. Return NULL if
-** we run out of memory. Leave space on the page for nEntry entries.
-*/
-static FifoPage *allocateFifoPage(sqlite3 *db, int nEntry){
- FifoPage *pPage;
- if( nEntry>FIFOSIZE_MAX ){
- nEntry = FIFOSIZE_MAX;
- }
- pPage = sqlite3DbMallocRaw(db, sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
- if( pPage ){
- pPage->nSlot = nEntry;
- pPage->iWrite = 0;
- pPage->iRead = 0;
- pPage->pNext = 0;
- }
- return pPage;
-}
-
-/*
-** Initialize a Fifo structure.
-*/
-SQLITE_PRIVATE void sqlite3VdbeFifoInit(Fifo *pFifo, sqlite3 *db){
- memset(pFifo, 0, sizeof(*pFifo));
- pFifo->db = db;
-}
-
-/*
-** Push a single 64-bit integer value into the Fifo. Return SQLITE_OK
-** normally. SQLITE_NOMEM is returned if we are unable to allocate
-** memory.
-*/
-SQLITE_PRIVATE int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){
- FifoPage *pPage;
- pPage = pFifo->pLast;
- if( pPage==0 ){
- pPage = pFifo->pLast = pFifo->pFirst =
- allocateFifoPage(pFifo->db, FIFOSIZE_FIRST);
- if( pPage==0 ){
- return SQLITE_NOMEM;
- }
- }else if( pPage->iWrite>=pPage->nSlot ){
- pPage->pNext = allocateFifoPage(pFifo->db, pFifo->nEntry);
- if( pPage->pNext==0 ){
- return SQLITE_NOMEM;
- }
- pPage = pFifo->pLast = pPage->pNext;
- }
- pPage->aSlot[pPage->iWrite++] = val;
- pFifo->nEntry++;
- return SQLITE_OK;
-}
-
-/*
-** Extract a single 64-bit integer value from the Fifo. The integer
-** extracted is the one least recently inserted. If the Fifo is empty
-** return SQLITE_DONE.
-*/
-SQLITE_PRIVATE int sqlite3VdbeFifoPop(Fifo *pFifo, i64 *pVal){
- FifoPage *pPage;
- if( pFifo->nEntry==0 ){
- return SQLITE_DONE;
- }
- assert( pFifo->nEntry>0 );
- pPage = pFifo->pFirst;
- assert( pPage!=0 );
- assert( pPage->iWrite>pPage->iRead );
- assert( pPage->iWrite<=pPage->nSlot );
- assert( pPage->iRead<pPage->nSlot );
- assert( pPage->iRead>=0 );
- *pVal = pPage->aSlot[pPage->iRead++];
- pFifo->nEntry--;
- if( pPage->iRead>=pPage->iWrite ){
- pFifo->pFirst = pPage->pNext;
- sqlite3DbFree(pFifo->db, pPage);
- if( pFifo->nEntry==0 ){
- assert( pFifo->pLast==pPage );
- pFifo->pLast = 0;
- }else{
- assert( pFifo->pFirst!=0 );
- }
- }else{
- assert( pFifo->nEntry>0 );
- }
- return SQLITE_OK;
-}
-
-/*
-** Delete all information from a Fifo object. Free all memory held
-** by the Fifo.
-*/
-SQLITE_PRIVATE void sqlite3VdbeFifoClear(Fifo *pFifo){
- FifoPage *pPage, *pNextPage;
- for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){
- pNextPage = pPage->pNext;
- sqlite3DbFree(pFifo->db, pPage);
- }
- sqlite3VdbeFifoInit(pFifo, pFifo->db);
-}
-
-/************** End of vdbefifo.c ********************************************/
/************** Begin file vdbemem.c *****************************************/
/*
** 2004 May 26
**
@@ -41480,9 +43205,9 @@
** stores a single value in the VDBE. Mem is an opaque structure visible
** only within the VDBE. Interface routines refer to a Mem using the
** name sqlite_value
**
-** $Id: vdbemem.c,v 1.126 2008/11/11 00:21:30 drh Exp $
+** $Id: vdbemem.c,v 1.133 2008/12/10 19:26:24 drh Exp $
*/
/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
@@ -41504,8 +43229,11 @@
** between formats.
*/
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
int rc;
+ assert( (pMem->flags&MEM_RowSet)==0 );
+ assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
+ || desiredEnc==SQLITE_UTF16BE );
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
return SQLITE_OK;
}
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
@@ -41515,9 +43243,9 @@
/* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
** then the encoding of the value may not have changed.
*/
- rc = sqlite3VdbeMemTranslate(pMem, desiredEnc);
+ rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc);
assert(rc==SQLITE_OK || rc==SQLITE_NOMEM);
assert(rc==SQLITE_OK || pMem->enc!=desiredEnc);
assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
return rc;
@@ -41543,8 +43271,9 @@
(((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
((pMem->flags&MEM_Ephem) ? 1 : 0) +
((pMem->flags&MEM_Static) ? 1 : 0)
);
+ assert( (pMem->flags&MEM_RowSet)==0 );
if( n<32 ) n = 32;
if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
if( preserve && pMem->z==pMem->zMalloc ){
@@ -41583,8 +43312,9 @@
*/
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
int f;
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( (pMem->flags&MEM_RowSet)==0 );
expandBlob(pMem);
f = pMem->flags;
if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){
if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
@@ -41606,21 +43336,22 @@
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *pMem){
if( pMem->flags & MEM_Zero ){
int nByte;
assert( pMem->flags&MEM_Blob );
+ assert( (pMem->flags&MEM_RowSet)==0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
/* Set nByte to the number of bytes required to store the expanded blob. */
- nByte = pMem->n + pMem->u.i;
+ nByte = pMem->n + pMem->u.nZero;
if( nByte<=0 ){
nByte = 1;
}
if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
return SQLITE_NOMEM;
}
- memset(&pMem->z[pMem->n], 0, pMem->u.i);
- pMem->n += pMem->u.i;
+ memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
+ pMem->n += pMem->u.nZero;
pMem->flags &= ~(MEM_Zero|MEM_Term);
}
return SQLITE_OK;
}
@@ -41665,8 +43396,10 @@
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( !(fg&MEM_Zero) );
assert( !(fg&(MEM_Str|MEM_Blob)) );
assert( fg&(MEM_Int|MEM_Real) );
+ assert( (pMem->flags&MEM_RowSet)==0 );
+
if( sqlite3VdbeMemGrow(pMem, nByte, 0) ){
return SQLITE_NOMEM;
}
@@ -41682,9 +43415,9 @@
}else{
assert( fg & MEM_Real );
sqlite3_snprintf(nByte, pMem->z, "%!.15g", pMem->r);
}
- pMem->n = strlen(pMem->z);
+ pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
pMem->flags |= MEM_Str|MEM_Term;
sqlite3VdbeChangeEncoding(pMem, enc);
return rc;
@@ -41711,9 +43444,9 @@
ctx.pFunc = pFunc;
pFunc->xFinalize(&ctx);
assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
sqlite3DbFree(pMem->db, pMem->zMalloc);
- *pMem = ctx.s;
+ memcpy(pMem, &ctx.s, sizeof(ctx.s));
rc = (ctx.isError?SQLITE_ERROR:SQLITE_OK);
}
return rc;
}
@@ -41729,10 +43462,13 @@
sqlite3VdbeMemFinalize(p, p->u.pDef);
assert( (p->flags & MEM_Agg)==0 );
sqlite3VdbeMemRelease(p);
}else if( p->flags&MEM_Dyn && p->xDel ){
+ assert( (p->flags&MEM_RowSet)==0 );
p->xDel((void *)p->z);
p->xDel = 0;
+ }else if( p->flags&MEM_RowSet ){
+ sqlite3RowSetClear(p->u.pRowSet);
}
}
/*
@@ -41845,8 +43581,9 @@
** MEM_Int if we can.
*/
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){
assert( pMem->flags & MEM_Real );
+ assert( (pMem->flags & MEM_RowSet)==0 );
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->u.i = doubleToInt64(pMem->r);
if( pMem->r==(double)pMem->u.i ){
@@ -41853,19 +43590,16 @@
pMem->flags |= MEM_Int;
}
}
-static void setTypeFlag(Mem *pMem, int f){
- MemSetTypeFlag(pMem, f);
-}
-
/*
** Convert pMem to type integer. Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( (pMem->flags & MEM_RowSet)==0 );
pMem->u.i = sqlite3VdbeIntValue(pMem);
- setTypeFlag(pMem, MEM_Int);
+ MemSetTypeFlag(pMem, MEM_Int);
return SQLITE_OK;
}
/*
@@ -41874,9 +43608,9 @@
*/
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem *pMem){
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
pMem->r = sqlite3VdbeRealValue(pMem);
- setTypeFlag(pMem, MEM_Real);
+ MemSetTypeFlag(pMem, MEM_Real);
return SQLITE_OK;
}
/*
@@ -41895,9 +43629,9 @@
if( r1==r2 ){
sqlite3VdbeMemIntegerify(pMem);
}else{
pMem->r = r1;
- setTypeFlag(pMem, MEM_Real);
+ MemSetTypeFlag(pMem, MEM_Real);
}
return SQLITE_OK;
}
@@ -41904,9 +43638,12 @@
/*
** Delete any previous value and set the value stored in *pMem to NULL.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem *pMem){
- setTypeFlag(pMem, MEM_Null);
+ if( pMem->flags & MEM_RowSet ){
+ sqlite3RowSetClear(pMem->u.pRowSet);
+ }
+ MemSetTypeFlag(pMem, MEM_Null);
pMem->type = SQLITE_NULL;
}
/*
@@ -41914,14 +43651,14 @@
** n containing all zeros.
*/
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem);
- setTypeFlag(pMem, MEM_Blob);
+ MemSetTypeFlag(pMem, MEM_Blob);
pMem->flags = MEM_Blob|MEM_Zero;
pMem->type = SQLITE_BLOB;
pMem->n = 0;
if( n<0 ) n = 0;
- pMem->u.i = n;
+ pMem->u.nZero = n;
pMem->enc = SQLITE_UTF8;
}
/*
@@ -41950,8 +43687,32 @@
}
}
/*
+** Delete any previous value and set the value of pMem to be an
+** empty boolean index.
+*/
+SQLITE_PRIVATE void sqlite3VdbeMemSetRowSet(Mem *pMem){
+ sqlite3 *db = pMem->db;
+ assert( db!=0 );
+ if( pMem->flags & MEM_RowSet ){
+ sqlite3RowSetClear(pMem->u.pRowSet);
+ }else{
+ sqlite3VdbeMemRelease(pMem);
+ pMem->zMalloc = sqlite3DbMallocRaw(db, 64);
+ }
+ if( db->mallocFailed ){
+ pMem->flags = MEM_Null;
+ }else{
+ assert( pMem->zMalloc );
+ pMem->u.pRowSet = sqlite3RowSetInit(db, pMem->zMalloc,
+ sqlite3DbMallocSize(db, pMem->zMalloc));
+ assert( pMem->u.pRowSet!=0 );
+ pMem->flags = MEM_RowSet;
+ }
+}
+
+/*
** Return true if the Mem object contains a TEXT or BLOB that is
** too large - whose size exceeds SQLITE_MAX_LENGTH.
*/
SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem *p){
@@ -41958,9 +43719,9 @@
assert( p->db!=0 );
if( p->flags & (MEM_Str|MEM_Blob) ){
int n = p->n;
if( p->flags & MEM_Zero ){
- n += p->u.i;
+ n += p->u.nZero;
}
return n>p->db->aLimit[SQLITE_LIMIT_LENGTH];
}
return 0;
@@ -41977,8 +43738,9 @@
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
+ assert( (pFrom->flags & MEM_RowSet)==0 );
sqlite3VdbeMemReleaseExternal(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->xDel = 0;
if( (pFrom->flags&MEM_Dyn)!=0 || pFrom->z==pFrom->zMalloc ){
@@ -41994,8 +43756,9 @@
*/
SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
int rc = SQLITE_OK;
+ assert( (pFrom->flags & MEM_RowSet)==0 );
sqlite3VdbeMemReleaseExternal(pTo);
memcpy(pTo, pFrom, MEMCELLSIZE);
pTo->flags &= ~MEM_Dyn;
@@ -42044,11 +43807,12 @@
void (*xDel)(void*) /* Destructor function */
){
int nByte = n; /* New value for pMem->n */
int iLimit; /* Maximum allowed string or blob size */
- int flags = 0; /* New value for pMem->flags */
+ u16 flags = 0; /* New value for pMem->flags */
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+ assert( (pMem->flags & MEM_RowSet)==0 );
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){
sqlite3VdbeMemSetNull(pMem);
@@ -42134,8 +43898,9 @@
*/
f1 = pMem1->flags;
f2 = pMem2->flags;
combined_flags = f1|f2;
+ assert( (combined_flags & MEM_RowSet)==0 );
/* If one value is NULL, it is less than the other. If both values
** are NULL, return 0.
*/
@@ -42156,14 +43921,14 @@
}
if( (f1 & f2 & MEM_Int)==0 ){
double r1, r2;
if( (f1&MEM_Real)==0 ){
- r1 = pMem1->u.i;
+ r1 = (double)pMem1->u.i;
}else{
r1 = pMem1->r;
}
if( (f2&MEM_Real)==0 ){
- r2 = pMem2->u.i;
+ r2 = (double)pMem2->u.i;
}else{
r2 = pMem2->r;
}
if( r1<r2 ) return -1;
@@ -42261,8 +44026,9 @@
int rc = SQLITE_OK;
db = sqlite3BtreeCursorDb(pCur);
assert( sqlite3_mutex_held(db->mutex) );
+ assert( (pMem->flags & MEM_RowSet)==0 );
if( key ){
zData = (char *)sqlite3BtreeKeyFetch(pCur, &available);
}else{
zData = (char *)sqlite3BtreeDataFetch(pCur, &available);
@@ -42319,13 +44085,13 @@
);
/* If the string is UTF-8 encoded and nul terminated, then pMem->n
** must be the length of the string. (Later:) If the database file
** has been corrupted, '\000' characters might have been inserted
- ** into the middle of the string. In that case, the strlen() might
- ** be less.
+ ** into the middle of the string. In that case, the sqlite3Strlen30()
+ ** might be less.
*/
if( pMem->enc==SQLITE_UTF8 && (flags & MEM_Term) ){
- assert( strlen(pMem->z)<=pMem->n );
+ assert( sqlite3Strlen30(pMem->z)<=pMem->n );
assert( pMem->z[pMem->n]==0 );
}
}
}else{
@@ -42356,8 +44122,9 @@
if( !pVal ) return 0;
assert( pVal->db==0 || sqlite3_mutex_held(pVal->db->mutex) );
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
+ assert( (pVal->flags & MEM_RowSet)==0 );
if( pVal->flags&MEM_Null ){
return 0;
}
@@ -42375,9 +44142,9 @@
sqlite3VdbeMemNulTerminate(pVal);
}else{
assert( (pVal->flags&MEM_Blob)==0 );
sqlite3VdbeMemStringify(pVal, enc);
- assert( 0==(1&(int)pVal->z) );
+ assert( 0==(1&SQLITE_PTR_TO_INT(pVal->z)) );
}
assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || pVal->db==0
|| pVal->db->mallocFailed );
if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
@@ -42500,9 +44267,9 @@
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
Mem *p = (Mem*)pVal;
if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){
if( p->flags & MEM_Zero ){
- return p->n+p->u.i;
+ return p->n + p->u.nZero;
}else{
return p->n;
}
}
@@ -42526,9 +44293,9 @@
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.) Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
-** $Id: vdbeaux.c,v 1.420 2008/11/17 19:18:55 danielk1977 Exp $
+** $Id: vdbeaux.c,v 1.428 2008/12/16 17:20:38 shane Exp $
*/
@@ -42650,16 +44417,17 @@
VdbeOp *pOp;
i = p->nOp;
assert( p->magic==VDBE_MAGIC_INIT );
+ assert( op>0 && op<0xff );
if( p->nOpAlloc<=i ){
if( growOpArray(p) ){
return 0;
}
}
p->nOp++;
pOp = &p->aOp[i];
- pOp->opcode = op;
+ pOp->opcode = (u8)op;
pOp->p5 = 0;
pOp->p1 = p1;
pOp->p2 = p2;
pOp->p3 = p3;
@@ -42722,11 +44490,12 @@
int i;
i = p->nLabel++;
assert( p->magic==VDBE_MAGIC_INIT );
if( i>=p->nLabelAlloc ){
- p->nLabelAlloc = p->nLabelAlloc*2 + 10;
+ int n = p->nLabelAlloc*2 + 5;
p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
- p->nLabelAlloc*sizeof(p->aLabel[0]));
+ n*sizeof(p->aLabel[0]));
+ p->nLabelAlloc = sqlite3DbMallocSize(p->db, p->aLabel)/sizeof(p->aLabel[0]);
}
if( p->aLabel ){
p->aLabel[i] = -1;
}
@@ -43051,9 +44820,9 @@
if( n==P4_INT32 ){
/* Note: this cast is safe, because the origin data point was an int
** that was cast to a (const char *). */
pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
- pOp->p4type = n;
+ pOp->p4type = P4_INT32;
}else if( zP4==0 ){
pOp->p4.p = 0;
pOp->p4type = P4_NOTUSED;
}else if( n==P4_KEYINFO ){
@@ -43081,11 +44850,11 @@
pOp->p4.p = (void*)zP4;
pOp->p4type = P4_KEYINFO;
}else if( n<0 ){
pOp->p4.p = (void*)zP4;
- pOp->p4type = n;
- }else{
- if( n==0 ) n = strlen(zP4);
+ pOp->p4type = (signed char)n;
+ }else{
+ if( n==0 ) n = sqlite3Strlen30(zP4);
pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
pOp->p4type = P4_DYNAMIC;
}
}
@@ -43147,13 +44916,13 @@
case P4_KEYINFO: {
int i, j;
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
- i = strlen(zTemp);
+ i = sqlite3Strlen30(zTemp);
for(j=0; j<pKeyInfo->nField; j++){
CollSeq *pColl = pKeyInfo->aColl[j];
if( pColl ){
- int n = strlen(pColl->zName);
+ int n = sqlite3Strlen30(pColl->zName);
if( i+n>nTemp-6 ){
memcpy(&zTemp[i],",...",4);
break;
}
@@ -43275,9 +45044,9 @@
static void releaseMemArray(Mem *p, int N){
if( p && N ){
Mem *pEnd;
sqlite3 *db = p->db;
- int malloc_failed = db->mallocFailed;
+ u8 malloc_failed = db->mallocFailed;
for(pEnd=&p[N]; p<pEnd; p++){
assert( (&p[1])==pEnd || p[0].db==p[1].db );
/* This block is really an inlined version of sqlite3VdbeMemRelease()
@@ -43311,8 +45080,11 @@
int nFree = 0;
assert( sqlite3_mutex_held(p->db->mutex) );
for(ii=1; ii<=p->nMem; ii++){
Mem *pMem = &p->aMem[ii];
+ if( pMem->flags & MEM_RowSet ){
+ sqlite3RowSetClear(pMem->u.pRowSet);
+ }
if( pMem->z && pMem->flags&MEM_Dyn ){
assert( !pMem->xDel );
nFree += sqlite3DbMallocSize(pMem->db, pMem->z);
sqlite3VdbeMemRelease(pMem);
@@ -43345,15 +45117,22 @@
assert( p->explain );
if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
assert( db->magic==SQLITE_MAGIC_BUSY );
- assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
+ assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
/* Even though this opcode does not use dynamic strings for
** the result, result columns may become dynamic if the user calls
** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
*/
releaseMemArray(pMem, p->nMem);
+
+ if( p->rc==SQLITE_NOMEM ){
+ /* This happens if a malloc() inside a call to sqlite3_column_text() or
+ ** sqlite3_column_text16() failed. */
+ db->mallocFailed = 1;
+ return SQLITE_ERROR;
+ }
do{
i = p->pc++;
}while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
@@ -43375,9 +45154,9 @@
pMem->flags = MEM_Static|MEM_Str|MEM_Term;
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
- pMem->n = strlen(pMem->z);
+ pMem->n = sqlite3Strlen30(pMem->z);
pMem->type = SQLITE_TEXT;
pMem->enc = SQLITE_UTF8;
pMem++;
}
@@ -43408,9 +45187,9 @@
if( z!=pMem->z ){
sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, 0);
}else{
assert( pMem->z!=0 );
- pMem->n = strlen(pMem->z);
+ pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
}
pMem->type = SQLITE_TEXT;
pMem++;
@@ -43430,9 +45209,9 @@
#ifdef SQLITE_DEBUG
if( pOp->zComment ){
pMem->flags = MEM_Str|MEM_Term;
pMem->z = pOp->zComment;
- pMem->n = strlen(pMem->z);
+ pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
pMem->type = SQLITE_TEXT;
}else
#endif
@@ -43658,18 +45437,18 @@
*/
static void Cleanup(Vdbe *p){
int i;
sqlite3 *db = p->db;
+ Mem *pMem;
closeAllCursorsExceptActiveVtabs(p);
- for(i=1; i<=p->nMem; i++){
- MemSetTypeFlag(&p->aMem[i], MEM_Null);
+ for(pMem=&p->aMem[1], i=1; i<=p->nMem; i++, pMem++){
+ if( pMem->flags & MEM_RowSet ){
+ sqlite3RowSetClear(pMem->u.pRowSet);
+ }
+ MemSetTypeFlag(pMem, MEM_Null);
}
releaseMemArray(&p->aMem[1], p->nMem);
- sqlite3VdbeFifoClear(&p->sFifo);
- if( p->contextStack ){
- for(i=0; i<p->contextStackTop; i++){
- sqlite3VdbeFifoClear(&p->contextStack[i].sFifo);
- }
+ if( p->contextStack ){
sqlite3DbFree(db, p->contextStack);
}
p->contextStack = 0;
p->contextStackDepth = 0;
@@ -43790,9 +45569,11 @@
** string, it means the main database is :memory: or a temp file. In
** that case we do not support atomic multi-file commits, so use the
** simple case then too.
*/
- if( 0==strlen(sqlite3BtreeGetFilename(db->aDb[0].pBt)) || nTrans<=1 ){
+ if( 0==sqlite3Strlen30(sqlite3BtreeGetFilename(db->aDb[0].pBt))
+ || nTrans<=1
+ ){
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
rc = sqlite3BtreeCommitPhaseOne(pBt, 0);
@@ -43830,12 +45611,12 @@
int res;
/* Select a master journal file name */
do {
- u32 random;
+ u32 iRandom;
sqlite3DbFree(db, zMaster);
- sqlite3_randomness(sizeof(random), &random);
- zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, random&0x7fffffff);
+ sqlite3_randomness(sizeof(iRandom), &iRandom);
+ zMaster = sqlite3MPrintf(db, "%s-mj%08X", zMainFile, iRandom&0x7fffffff);
if( !zMaster ){
return SQLITE_NOMEM;
}
rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
@@ -43866,10 +45647,10 @@
if( zFile[0]==0 ) continue; /* Ignore :memory: databases */
if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){
needSync = 1;
}
- rc = sqlite3OsWrite(pMaster, zFile, strlen(zFile)+1, offset);
- offset += strlen(zFile)+1;
+ rc = sqlite3OsWrite(pMaster, zFile, sqlite3Strlen30(zFile)+1, offset);
+ offset += sqlite3Strlen30(zFile)+1;
if( rc!=SQLITE_OK ){
sqlite3OsCloseFree(pMaster);
sqlite3OsDelete(pVfs, zMaster, 0);
sqlite3DbFree(db, zMaster);
@@ -44366,9 +46147,9 @@
assert( p->isTable );
rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
p->lastRowid = keyToInt(p->movetoTarget);
- p->rowidIsValid = res==0;
+ p->rowidIsValid = res==0 ?1:0;
if( res<0 ){
rc = sqlite3BtreeNext(p->pCursor, &res);
if( rc ) return rc;
}
@@ -44446,9 +46227,9 @@
# define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
i64 i = pMem->u.i;
u64 u;
if( file_format>=4 && (i&1)==i ){
- return 8+i;
+ return 8+(u32)i;
}
u = i<0 ? -i : i;
if( u<=127 ) return 1;
if( u<=32767 ) return 2;
@@ -44462,9 +46243,9 @@
}
assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
n = pMem->n;
if( flags & MEM_Zero ){
- n += pMem->u.i;
+ n += pMem->u.nZero;
}
assert( n>=0 );
return ((n*2) + 12 + ((flags&MEM_Str)!=0));
}
@@ -44569,23 +46350,23 @@
}
len = i = sqlite3VdbeSerialTypeLen(serial_type);
assert( len<=nBuf );
while( i-- ){
- buf[i] = (v&0xFF);
+ buf[i] = (u8)(v&0xFF);
v >>= 8;
}
return len;
}
/* String or blob */
if( serial_type>=12 ){
- assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.i:0)
+ assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
== sqlite3VdbeSerialTypeLen(serial_type) );
assert( pMem->n<=nBuf );
len = pMem->n;
memcpy(buf, pMem->z, len);
if( pMem->flags & MEM_Zero ){
- len += pMem->u.i;
+ len += pMem->u.nZero;
if( len>nBuf ){
len = nBuf;
}
memset(&buf[pMem->n], 0, len-pMem->n);
@@ -44879,8 +46660,11 @@
/*
** pCur points at an index entry created using the OP_MakeRecord opcode.
** Read the rowid (the last field in the record) and store it in *rowid.
** Return SQLITE_OK if everything works, or an error code otherwise.
+**
+** pCur might be pointing to text obtained from a corrupt database file.
+** So the content cannot be trusted. Do appropriate checks on the content.
*/
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
i64 nCellKey = 0;
int rc;
@@ -44888,26 +46672,64 @@
u32 typeRowid; /* Serial type of the rowid */
u32 lenRowid; /* Size of the rowid */
Mem m, v;
+ /* Get the size of the index entry. Only indices entries of less
+ ** than 2GiB are support - anything large must be database corruption */
sqlite3BtreeKeySize(pCur, &nCellKey);
- if( nCellKey<=0 ){
+ if( unlikely(nCellKey<=0 || nCellKey>0x7fffffff) ){
return SQLITE_CORRUPT_BKPT;
}
+
+ /* Read in the complete content of the index entry */
m.flags = 0;
m.db = 0;
m.zMalloc = 0;
- rc = sqlite3VdbeMemFromBtree(pCur, 0, nCellKey, 1, &m);
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m);
if( rc ){
return rc;
}
+
+ /* The index entry must begin with a header size */
(void)getVarint32((u8*)m.z, szHdr);
+ testcase( szHdr==2 );
+ testcase( szHdr==m.n );
+ if( unlikely(szHdr<2 || (int)szHdr>m.n) ){
+ goto idx_rowid_corruption;
+ }
+
+ /* The last field of the index should be an integer - the ROWID.
+ ** Verify that the last entry really is an integer. */
(void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
+ testcase( typeRowid==1 );
+ testcase( typeRowid==2 );
+ testcase( typeRowid==3 );
+ testcase( typeRowid==4 );
+ testcase( typeRowid==5 );
+ testcase( typeRowid==6 );
+ testcase( typeRowid==8 );
+ testcase( typeRowid==9 );
+ if( unlikely(typeRowid<1 || typeRowid>9 || typeRowid==7) ){
+ goto idx_rowid_corruption;
+ }
lenRowid = sqlite3VdbeSerialTypeLen(typeRowid);
+ testcase( m.n-lenRowid==szHdr );
+ if( unlikely(m.n-lenRowid<szHdr) ){
+ goto idx_rowid_corruption;
+ }
+
+ /* Fetch the integer off the end of the index record */
sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
*rowid = v.u.i;
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
+
+ /* Jump here if database corruption is detected after m has been
+ ** allocated. Free the m object and return SQLITE_CORRUPT. */
+idx_rowid_corruption:
+ testcase( m.zMalloc!=0 );
+ sqlite3VdbeMemRelease(&m);
+ return SQLITE_CORRUPT_BKPT;
}
/*
** Compare the key of the index entry that cursor pC is point to against
@@ -44933,16 +46755,16 @@
BtCursor *pCur = pC->pCursor;
Mem m;
sqlite3BtreeKeySize(pCur, &nCellKey);
- if( nCellKey<=0 ){
+ if( nCellKey<=0 || nCellKey>0x7fffffff ){
*res = 0;
return SQLITE_OK;
}
m.db = 0;
m.flags = 0;
m.zMalloc = 0;
- rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, nCellKey, 1, &m);
+ rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
if( rc ){
return rc;
}
assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID );
@@ -45009,9 +46831,9 @@
**
** This file contains code use to implement APIs that are part of the
** VDBE.
**
-** $Id: vdbeapi.c,v 1.149 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: vdbeapi.c,v 1.150 2008/12/10 18:03:47 drh Exp $
*/
#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
/*
@@ -45278,9 +47100,9 @@
SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){
return sqlite3VdbeRealValue((Mem*)pVal);
}
SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){
- return sqlite3VdbeIntValue((Mem*)pVal);
+ return (int)sqlite3VdbeIntValue((Mem*)pVal);
}
SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
return sqlite3VdbeIntValue((Mem*)pVal);
}
@@ -45457,9 +47279,9 @@
#ifndef SQLITE_OMIT_TRACE
if( db->xProfile && !db->init.busy ){
double rNow;
sqlite3OsCurrentTime(db->pVfs, &rNow);
- p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0;
+ p->startTime = (u64)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
}
#endif
db->activeVdbeCnt++;
@@ -45488,9 +47310,10 @@
double rNow;
u64 elapseTime;
sqlite3OsCurrentTime(db->pVfs, &rNow);
- elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime;
+ elapseTime = (u64)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
+ elapseTime -= p->startTime;
db->xProfile(db->pProfileArg, p->aOp[0].p4.z, elapseTime);
}
#endif
@@ -46046,9 +47869,9 @@
int i, /* Index of the parameter to bind */
const void *zData, /* Pointer to the data to be bound */
int nData, /* Number of bytes of data to be bound */
void (*xDel)(void*), /* Destructor for the data */
- int encoding /* Encoding for the data */
+ u8 encoding /* Encoding for the data */
){
Vdbe *p = (Vdbe *)pStmt;
Mem *pVar;
int rc;
@@ -46349,14 +48172,14 @@
** of the code in this file is, therefore, important. See other comments
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.788 2008/11/17 15:31:48 danielk1977 Exp $
+** $Id: vdbe.c,v 1.803 2008/12/15 15:27:52 drh Exp $
*/
/*
** The following global variable is incremented every time a cursor
-** moves, either by the OP_MoveXX, OP_Next, or OP_Prev opcodes. The test
+** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes. The test
** procedures use this information to make sure that indices are
** working correctly. This variable has no function other than to
** help verify the correct operation of the library.
*/
@@ -46492,9 +48315,9 @@
static VdbeCursor *allocateCursor(
Vdbe *p, /* The virtual machine */
int iCur, /* Index of the new VdbeCursor */
Op *pOp, /* */
- int iDb, /* */
+ int iDb, /* When database the cursor belongs to, or -1 */
int isBtreeCursor /* */
){
/* Find the memory cell that will be used to store the blob of memory
** required for this VdbeCursor structure. It is convenient to use a
@@ -46673,14 +48496,14 @@
c = 's';
}
sqlite3_snprintf(100, zCsr, "%c", c);
- zCsr += strlen(zCsr);
+ zCsr += sqlite3Strlen30(zCsr);
sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
- zCsr += strlen(zCsr);
+ zCsr += sqlite3Strlen30(zCsr);
for(i=0; i<16 && i<pMem->n; i++){
sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
- zCsr += strlen(zCsr);
+ zCsr += sqlite3Strlen30(zCsr);
}
for(i=0; i<16 && i<pMem->n; i++){
char z = pMem->z[i];
if( z<32 || z>126 ) *zCsr++ = '.';
@@ -46687,12 +48510,12 @@
else *zCsr++ = z;
}
sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]);
- zCsr += strlen(zCsr);
+ zCsr += sqlite3Strlen30(zCsr);
if( f & MEM_Zero ){
- sqlite3_snprintf(100, zCsr,"+%lldz",pMem->u.i);
- zCsr += strlen(zCsr);
+ sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
+ zCsr += sqlite3Strlen30(zCsr);
}
*zCsr = '\0';
}else if( f & MEM_Str ){
int j, k;
@@ -46710,9 +48533,9 @@
zBuf[1] = 's';
}
k = 2;
sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
- k += strlen(&zBuf[k]);
+ k += sqlite3Strlen30(&zBuf[k]);
zBuf[k++] = '[';
for(j=0; j<15 && j<pMem->n; j++){
u8 c = pMem->z[j];
if( c>=0x20 && c<0x7f ){
@@ -46722,9 +48545,9 @@
}
}
zBuf[k++] = ']';
sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);
- k += strlen(&zBuf[k]);
+ k += sqlite3Strlen30(&zBuf[k]);
zBuf[k++] = 0;
}
}
#endif
@@ -46932,10 +48755,12 @@
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
u8 encoding = ENC(db); /* The database encoding */
- Mem *pIn1, *pIn2, *pIn3; /* Input operands */
- Mem *pOut; /* Output operand */
+ Mem *pIn1 = 0; /* 1st input operand */
+ Mem *pIn2 = 0; /* 2nd input operand */
+ Mem *pIn3 = 0; /* 3rd input operand */
+ Mem *pOut = 0; /* Output operand */
u8 opProperty;
int iCompare = 0; /* Result of last OP_Compare operation */
int *aPermute = 0; /* Permuation of columns for OP_Compare */
#ifdef VDBE_PROFILE
@@ -47173,9 +48998,9 @@
** Jump to the next instruction after the address in register P1.
*/
case OP_Return: { /* in1 */
assert( pIn1->flags & MEM_Int );
- pc = pIn1->u.i;
+ pc = (int)pIn1->u.i;
break;
}
/* Opcode: Yield P1 * * * *
@@ -47188,9 +49013,9 @@
assert( pOp->p1<=p->nMem );
pIn1 = &p->aMem[pOp->p1];
assert( (pIn1->flags & MEM_Dyn)==0 );
pIn1->flags = MEM_Int;
- pcDest = pIn1->u.i;
+ pcDest = (int)pIn1->u.i;
pIn1->u.i = pc;
REGISTER_TRACE(pOp->p1, pIn1);
pc = pcDest;
break;
@@ -47198,9 +49023,9 @@
/* Opcode: Halt P1 P2 * P4 *
**
-** Exit immediately. All open cursors, Fifos, etc are closed
+** Exit immediately. All open cursors, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(),
** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0).
@@ -47274,9 +49099,9 @@
*/
case OP_String8: { /* same as TK_STRING, out2-prerelease */
assert( pOp->p4.z!=0 );
pOp->opcode = OP_String;
- pOp->p1 = strlen(pOp->p4.z);
+ pOp->p1 = sqlite3Strlen30(pOp->p4.z);
#ifndef SQLITE_OMIT_UTF16
if( encoding!=SQLITE_UTF8 ){
sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
@@ -47326,9 +49151,8 @@
break;
}
-#ifndef SQLITE_OMIT_BLOB_LITERAL
/* Opcode: Blob P1 P2 * P4
**
** P4 points to a blob of data P1 bytes long. Store this
** blob in register P2. This instruction is not coded directly
@@ -47343,9 +49167,8 @@
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
-#endif /* SQLITE_OMIT_BLOB_LITERAL */
/* Opcode: Variable P1 P2 * * *
**
** The value of variable P1 is written into register P2. A variable is
@@ -47514,9 +49337,9 @@
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
MemSetTypeFlag(pOut, MEM_Str);
- if( sqlite3VdbeMemGrow(pOut, nByte+2, pOut==pIn2) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
goto no_mem;
}
if( pOut!=pIn2 ){
memcpy(pOut->z, pIn2->z, pIn2->n);
@@ -47524,9 +49347,9 @@
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
pOut->z[nByte] = 0;
pOut->z[nByte+1] = 0;
pOut->flags |= MEM_Term;
- pOut->n = nByte;
+ pOut->n = (int)nByte;
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
@@ -47621,9 +49444,9 @@
i64 ia = (i64)a;
i64 ib = (i64)b;
if( ia==0 ) goto arithmetic_result_is_null;
if( ia==-1 ) ia = 1;
- b = ib % ia;
+ b = (double)(ib % ia);
break;
}
}
if( sqlite3IsNaN(b) ){
@@ -47828,38 +49651,8 @@
*/
case OP_AddImm: { /* in1 */
sqlite3VdbeMemIntegerify(pIn1);
pIn1->u.i += pOp->p2;
- break;
-}
-
-/* Opcode: ForceInt P1 P2 P3 * *
-**
-** Convert value in register P1 into an integer. If the value
-** in P1 is not numeric (meaning that is is a NULL or a string that
-** does not look like an integer or floating point number) then
-** jump to P2. If the value in P1 is numeric then
-** convert it into the least integer that is greater than or equal to its
-** current value if P3==0, or to the least integer that is strictly
-** greater than its current value if P3==1.
-*/
-case OP_ForceInt: { /* jump, in1 */
- i64 v;
- applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
- if( (pIn1->flags & (MEM_Int|MEM_Real))==0 ){
- pc = pOp->p2 - 1;
- break;
- }
- if( pIn1->flags & MEM_Int ){
- v = pIn1->u.i + (pOp->p3!=0);
- }else{
- assert( pIn1->flags & MEM_Real );
- v = (sqlite3_int64)pIn1->r;
- if( pIn1->r>(double)v ) v++;
- if( pOp->p3 && pIn1->r==(double)v ) v++;
- }
- pIn1->u.i = v;
- MemSetTypeFlag(pIn1, MEM_Int);
break;
}
/* Opcode: MustBeInt P1 P2 * * *
@@ -48083,8 +49876,9 @@
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity ){
applyAffinity(pIn1, affinity, encoding);
applyAffinity(pIn3, affinity, encoding);
+ if( db->mallocFailed ) goto no_mem;
}
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
ExpandBlob(pIn1);
@@ -48233,33 +50027,37 @@
}
break;
}
-/* Opcode: Not P1 * * * *
-**
-** Interpret the value in register P1 as a boolean value. Replace it
-** with its complement. If the value in register P1 is NULL its value
-** is unchanged.
+/* Opcode: Not P1 P2 * * *
+**
+** Interpret the value in register P1 as a boolean value. Store the
+** boolean complement in register P2. If the value in register P1 is
+** NULL, then a NULL is stored in P2.
*/
case OP_Not: { /* same as TK_NOT, in1 */
- if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */
- sqlite3VdbeMemIntegerify(pIn1);
- pIn1->u.i = !pIn1->u.i;
- assert( pIn1->flags&MEM_Int );
- break;
-}
-
-/* Opcode: BitNot P1 * * * *
-**
-** Interpret the content of register P1 as an integer. Replace it
-** with its ones-complement. If the value is originally NULL, leave
-** it unchanged.
+ pOut = &p->aMem[pOp->p2];
+ if( pIn1->flags & MEM_Null ){
+ sqlite3VdbeMemSetNull(pOut);
+ }else{
+ sqlite3VdbeMemSetInt64(pOut, !sqlite3VdbeIntValue(pIn1));
+ }
+ break;
+}
+
+/* Opcode: BitNot P1 P2 * * *
+**
+** Interpret the content of register P1 as an integer. Store the
+** ones-complement of the P1 value into register P2. If P1 holds
+** a NULL then store a NULL in P2.
*/
case OP_BitNot: { /* same as TK_BITNOT, in1 */
- if( pIn1->flags & MEM_Null ) break; /* Do nothing to NULLs */
- sqlite3VdbeMemIntegerify(pIn1);
- pIn1->u.i = ~pIn1->u.i;
- assert( pIn1->flags&MEM_Int );
+ pOut = &p->aMem[pOp->p2];
+ if( pIn1->flags & MEM_Null ){
+ sqlite3VdbeMemSetNull(pOut);
+ }else{
+ sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1));
+ }
break;
}
/* Opcode: If P1 P2 P3 * *
@@ -48372,11 +50170,9 @@
char *zData; /* Part of the record being decoded */
Mem *pDest; /* Where to write the extracted value */
Mem sMem; /* For storing the record being decoded */
- sMem.flags = 0;
- sMem.db = 0;
- sMem.zMalloc = 0;
+ memset(&sMem, 0, sizeof(sMem));
assert( p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &p->aMem[pOp->p3];
MemSetTypeFlag(pDest, MEM_Null);
@@ -48411,9 +50207,9 @@
zRec = (char*)pC->aRow;
}else if( pC->isIndex ){
i64 payloadSize64;
sqlite3BtreeKeySize(pCrsr, &payloadSize64);
- payloadSize = payloadSize64;
+ payloadSize = (int)payloadSize64;
}else{
sqlite3BtreeDataSize(pCrsr, (u32 *)&payloadSize);
}
nField = pC->nField;
@@ -48449,9 +50245,9 @@
u8 *zIdx; /* Index into header */
u8 *zEndHdr; /* Pointer to first byte after the header */
int offset; /* Offset into the data */
int szHdrSz; /* Size of the header size field at start of record */
- int avail; /* Number of bytes of available data */
+ int avail = 0; /* Number of bytes of available data */
assert(aType);
pC->aOffset = aOffset = &aType[nField];
pC->payloadSize = payloadSize;
@@ -48685,9 +50481,9 @@
nHdr += sqlite3VarintLen(serial_type);
if( pRec->flags & MEM_Zero ){
/* Only pure zero-filled BLOBs can be input to this Opcode.
** We do not allow blobs with a prefix and a zero-filled tail. */
- nZero += pRec->u.i;
+ nZero += pRec->u.nZero;
}else if( len ){
nZero = 0;
}
}
@@ -48708,9 +50504,9 @@
** sqlite3VdbeMemGrow() could clobber the value before it is used).
*/
assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
pOut = &p->aMem[pOp->p3];
- if( sqlite3VdbeMemGrow(pOut, nByte, 0) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){
goto no_mem;
}
zNewRecord = (u8 *)pOut->z;
@@ -48720,18 +50516,18 @@
serial_type = sqlite3VdbeSerialType(pRec, file_format);
i += putVarint32(&zNewRecord[i], serial_type); /* serial type */
}
for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */
- i += sqlite3VdbeSerialPut(&zNewRecord[i], nByte-i, pRec, file_format);
+ i += sqlite3VdbeSerialPut(&zNewRecord[i], (int)(nByte-i), pRec,file_format);
}
assert( i==nByte );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pOut->n = nByte;
+ pOut->n = (int)nByte;
pOut->flags = MEM_Blob | MEM_Dyn;
pOut->xDel = 0;
if( nZero ){
- pOut->u.i = nZero;
+ pOut->u.nZero = nZero;
pOut->flags |= MEM_Zero;
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
REGISTER_TRACE(pOp->p3, pOut);
@@ -48816,12 +50612,12 @@
assert( desiredAutoCommit==1 );
sqlite3RollbackAll(db);
db->autoCommit = 1;
}else{
- db->autoCommit = desiredAutoCommit;
+ db->autoCommit = (u8)desiredAutoCommit;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pc = pc;
- db->autoCommit = 1-desiredAutoCommit;
+ db->autoCommit = (u8)(1-desiredAutoCommit);
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
}
@@ -48950,13 +50746,13 @@
/* See note about index shifting on OP_ReadCookie */
rc = sqlite3BtreeUpdateMeta(pDb->pBt, 1+pOp->p2, (int)pIn3->u.i);
if( pOp->p2==0 ){
/* When the schema cookie changes, record the new cookie internally */
- pDb->pSchema->schema_cookie = pIn3->u.i;
+ pDb->pSchema->schema_cookie = (int)pIn3->u.i;
db->flags |= SQLITE_InternChanges;
}else if( pOp->p2==1 ){
/* Record changes in the file format */
- pDb->pSchema->file_format = pIn3->u.i;
+ pDb->pSchema->file_format = (u8)pIn3->u.i;
}
if( pOp->p1==1 ){
/* Invalidate all prepared statements whenever the TEMP database
** schema is changed. Ticket #1644 */
@@ -49090,9 +50886,9 @@
assert( p2>0 );
assert( p2<=p->nMem );
pIn2 = &p->aMem[p2];
sqlite3VdbeMemIntegerify(pIn2);
- p2 = pIn2->u.i;
+ p2 = (int)pIn2->u.i;
if( p2<2 ) {
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
@@ -49125,10 +50921,10 @@
if( (flags & 0xf0)!=0 || ((flags & 0x07)!=5 && (flags & 0x07)!=2) ){
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
- pCur->isTable = (flags & BTREE_INTKEY)!=0;
- pCur->isIndex = (flags & BTREE_ZERODATA)!=0;
+ pCur->isTable = (flags & BTREE_INTKEY)!=0 ?1:0;
+ pCur->isIndex = (flags & BTREE_ZERODATA)!=0 ?1:0;
/* If P4==0 it means we are expected to open a table. If P4!=0 then
** we expect to be opening an index. If this is not what happened,
** then the database is corrupt
*/
@@ -49244,9 +51040,9 @@
pCx = allocateCursor(p, i, &pOp[-1], -1, 0);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->pseudoTable = 1;
- pCx->ephemPseudoTable = pOp->p2;
+ pCx->ephemPseudoTable = (u8)pOp->p2;
pCx->isTable = 1;
pCx->isIndex = 0;
break;
}
@@ -49263,104 +51059,142 @@
p->apCsr[i] = 0;
break;
}
-/* Opcode: MoveGe P1 P2 P3 P4 *
+/* Opcode: SeekGe P1 P2 P3 P4 *
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the integer value in register P3 as a key. If cursor P1 refers
+** use the value in register P3 as the key. If cursor P1 refers
** to an SQL index, then P3 is the first in an array of P4 registers
** that are used as an unpacked index key.
**
** Reposition cursor P1 so that it points to the smallest entry that
** is greater than or equal to the key value. If there are no records
** greater than or equal to the key and P2 is not zero, then jump to P2.
**
-** A special feature of this opcode (and different from the
-** related OP_MoveGt, OP_MoveLt, and OP_MoveLe) is that if P2 is
-** zero and P1 is an SQL table (a b-tree with integer keys) then
-** the seek is deferred until it is actually needed. It might be
-** the case that the cursor is never accessed. By deferring the
-** seek, we avoid unnecessary seeks.
-**
-** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe
-*/
-/* Opcode: MoveGt P1 P2 P3 P4 *
+** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
+*/
+/* Opcode: SeekGt P1 P2 P3 P4 *
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the integer value in register P3 as a key. If cursor P1 refers
+** use the value in register P3 as a key. If cursor P1 refers
** to an SQL index, then P3 is the first in an array of P4 registers
** that are used as an unpacked index key.
**
** Reposition cursor P1 so that it points to the smallest entry that
** is greater than the key value. If there are no records greater than
** the key and P2 is not zero, then jump to P2.
**
-** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe
-*/
-/* Opcode: MoveLt P1 P2 P3 P4 *
+** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
+*/
+/* Opcode: SeekLt P1 P2 P3 P4 *
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the integer value in register P3 as a key. If cursor P1 refers
+** use the value in register P3 as a key. If cursor P1 refers
** to an SQL index, then P3 is the first in an array of P4 registers
** that are used as an unpacked index key.
**
** Reposition cursor P1 so that it points to the largest entry that
** is less than the key value. If there are no records less than
** the key and P2 is not zero, then jump to P2.
**
-** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe
-*/
-/* Opcode: MoveLe P1 P2 P3 P4 *
+** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
+*/
+/* Opcode: SeekLe P1 P2 P3 P4 *
**
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
-** use the integer value in register P3 as a key. If cursor P1 refers
+** use the value in register P3 as a key. If cursor P1 refers
** to an SQL index, then P3 is the first in an array of P4 registers
** that are used as an unpacked index key.
**
** Reposition cursor P1 so that it points to the largest entry that
** is less than or equal to the key value. If there are no records
** less than or equal to the key and P2 is not zero, then jump to P2.
**
-** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
-*/
-case OP_MoveLt: /* jump, in3 */
-case OP_MoveLe: /* jump, in3 */
-case OP_MoveGe: /* jump, in3 */
-case OP_MoveGt: { /* jump, in3 */
- int i = pOp->p1;
- VdbeCursor *pC;
-
- assert( i>=0 && i<p->nCursor );
+** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
+*/
+case OP_SeekLt: /* jump, in3 */
+case OP_SeekLe: /* jump, in3 */
+case OP_SeekGe: /* jump, in3 */
+case OP_SeekGt: { /* jump, in3 */
+ int i = pOp->p1;
+ VdbeCursor *pC;
+
+ assert( i>=0 && i<p->nCursor );
+ assert( pOp->p2!=0 );
pC = p->apCsr[i];
assert( pC!=0 );
if( pC->pCursor!=0 ){
int res, oc;
oc = pOp->opcode;
pC->nullRow = 0;
if( pC->isTable ){
- i64 iKey = sqlite3VdbeIntValue(pIn3);
- if( pOp->p2==0 ){
- assert( pOp->opcode==OP_MoveGe );
- pC->movetoTarget = iKey;
- pC->rowidIsValid = 0;
- pC->deferredMoveto = 1;
- break;
+ i64 iKey; /* The rowid we are to seek to */
+
+ /* The input value in P3 might be of any type: integer, real, string,
+ ** blob, or NULL. But it needs to be an integer before we can do
+ ** the seek, so covert it. */
+ applyNumericAffinity(pIn3);
+ iKey = sqlite3VdbeIntValue(pIn3);
+ pC->rowidIsValid = 0;
+
+ /* If the P3 value could not be converted into an integer without
+ ** loss of information, then special processing is required... */
+ if( (pIn3->flags & MEM_Int)==0 ){
+ if( (pIn3->flags & MEM_Real)==0 ){
+ /* If the P3 value cannot be converted into any kind of a number,
+ ** then the seek is not possible, so jump to P2 */
+ pc = pOp->p2 - 1;
+ break;
+ }
+ /* If we reach this point, then the P3 value must be a floating
+ ** point number. */
+ assert( (pIn3->flags & MEM_Real)!=0 );
+
+ if( iKey==SMALLEST_INT64 && (pIn3->r<(double)iKey || pIn3->r>0) ){
+ /* The P3 value is to large in magnitude to be expressed as an
+ ** integer. */
+ res = 1;
+ if( pIn3->r<0 ){
+ if( oc==OP_SeekGt || oc==OP_SeekGe ){
+ rc = sqlite3BtreeFirst(pC->pCursor, &res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ }
+ }else{
+ if( oc==OP_SeekLt || oc==OP_SeekLe ){
+ rc = sqlite3BtreeLast(pC->pCursor, &res);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ }
+ }
+ if( res ){
+ pc = pOp->p2 - 1;
+ }
+ break;
+ }else if( oc==OP_SeekLt || oc==OP_SeekGe ){
+ /* Use the ceiling() function to convert real->int */
+ if( pIn3->r > (double)iKey ) iKey++;
+ }else{
+ /* Use the floor() function to convert real->int */
+ assert( oc==OP_SeekLe || oc==OP_SeekGt );
+ if( pIn3->r < (double)iKey ) iKey--;
+ }
}
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- pC->lastRowid = iKey;
- pC->rowidIsValid = res==0;
+ if( res==0 ){
+ pC->rowidIsValid = 1;
+ pC->lastRowid = iKey;
+ }
}else{
UnpackedRecord r;
int nField = pOp->p4.i;
assert( pOp->p4type==P4_INT32 );
assert( nField>0 );
r.pKeyInfo = pC->pKeyInfo;
- r.nField = nField;
- if( oc==OP_MoveGt || oc==OP_MoveLe ){
+ r.nField = (u16)nField;
+ if( oc==OP_SeekGt || oc==OP_SeekLe ){
r.flags = UNPACKED_INCRKEY;
}else{
r.flags = 0;
}
@@ -49375,19 +51209,19 @@
pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
- if( oc==OP_MoveGe || oc==OP_MoveGt ){
- if( res<0 ){
+ if( oc==OP_SeekGe || oc==OP_SeekGt ){
+ if( res<0 || (res==0 && oc==OP_SeekGt) ){
rc = sqlite3BtreeNext(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->rowidIsValid = 0;
}else{
res = 0;
}
}else{
- assert( oc==OP_MoveLt || oc==OP_MoveLe );
- if( res>=0 ){
+ assert( oc==OP_SeekLt || oc==OP_SeekLe );
+ if( res>0 || (res==0 && oc==OP_SeekLt) ){
rc = sqlite3BtreePrevious(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->rowidIsValid = 0;
}else{
@@ -49409,8 +51243,35 @@
pc = pOp->p2 - 1;
}
break;
}
+
+/* Opcode: Seek P1 P2 * * *
+**
+** P1 is an open table cursor and P2 is a rowid integer. Arrange
+** for P1 to move so that it points to the rowid given by P2.
+**
+** This is actually a deferred seek. Nothing actually happens until
+** the cursor is used to read a record. That way, if no reads
+** occur, no unnecessary I/O happens.
+*/
+case OP_Seek: { /* in2 */
+ int i = pOp->p1;
+ VdbeCursor *pC;
+
+ assert( i>=0 && i<p->nCursor );
+ pC = p->apCsr[i];
+ assert( pC!=0 );
+ if( pC->pCursor!=0 ){
+ assert( pC->isTable );
+ pC->nullRow = 0;
+ pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+ pC->rowidIsValid = 0;
+ pC->deferredMoveto = 1;
+ }
+ break;
+}
+
/* Opcode: Found P1 P2 P3 * *
**
** Register P3 holds a blob constructed by MakeRecord. P1 is an index.
@@ -49602,23 +51463,18 @@
BtCursor *pCrsr;
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
- int res;
+ int res = 0;
u64 iKey;
assert( pIn3->flags & MEM_Int );
assert( p->apCsr[i]->isTable );
iKey = intToKey(pIn3->u.i);
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0,&res);
pC->lastRowid = pIn3->u.i;
- pC->rowidIsValid = res==0;
+ pC->rowidIsValid = res==0 ?1:0;
pC->nullRow = 0;
pC->cacheStatus = CACHE_STALE;
- /* res might be uninitialized if rc!=SQLITE_OK. But if rc!=SQLITE_OK
- ** processing is about to abort so we really do not care whether or not
- ** the following jump is taken. (In other words, do not stress over
- ** the error that valgrind sometimes shows on the next statement when
- ** running ioerr.test and similar failure-recovery test scripts.) */
if( res!=0 ){
pc = pOp->p2 - 1;
assert( pC->rowidIsValid==0 );
}
@@ -49880,9 +51736,9 @@
pC->nullRow = 0;
}else{
int nZero;
if( pData->flags & MEM_Zero ){
- nZero = pData->u.i;
+ nZero = pData->u.nZero;
}else{
nZero = 0;
}
rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey,
@@ -50024,9 +51880,9 @@
sqlite3BtreeKeySize(pCrsr, &n64);
if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- n = n64;
+ n = (int)n64;
}else{
sqlite3BtreeDataSize(pCrsr, &n);
if( (int)n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
@@ -50119,9 +51975,9 @@
assert( pC!=0 );
pCrsr = pC->pCursor;
assert( pCrsr!=0 );
rc = sqlite3BtreeLast(pCrsr, &res);
- pC->nullRow = res;
+ pC->nullRow = (u8)res;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
@@ -50168,15 +52024,15 @@
pC = p->apCsr[i];
assert( pC!=0 );
if( (pCrsr = pC->pCursor)!=0 ){
rc = sqlite3BtreeFirst(pCrsr, &res);
- pC->atFirst = res==0;
+ pC->atFirst = res==0 ?1:0;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
}else{
res = 1;
}
- pC->nullRow = res;
+ pC->nullRow = (u8)res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
if( res ){
pc = pOp->p2 - 1;
}
@@ -50220,9 +52076,9 @@
res = 1;
assert( pC->deferredMoveto==0 );
rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
sqlite3BtreePrevious(pCrsr, &res);
- pC->nullRow = res;
+ pC->nullRow = (u8)res;
pC->cacheStatus = CACHE_STALE;
if( res==0 ){
pc = pOp->p2 - 1;
if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
@@ -50284,9 +52140,9 @@
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
int res;
UnpackedRecord r;
r.pKeyInfo = pC->pKeyInfo;
- r.nField = pOp->p3;
+ r.nField = (u16)pOp->p3;
r.flags = 0;
r.aMem = &p->aMem[pOp->p2];
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
if( rc==SQLITE_OK && res==0 ){
@@ -50369,9 +52225,9 @@
assert( pC->deferredMoveto==0 );
assert( pOp->p5==0 || pOp->p5==1 );
assert( pOp->p4type==P4_INT32 );
r.pKeyInfo = pC->pKeyInfo;
- r.nField = pOp->p4.i;
+ r.nField = (u16)pOp->p4.i;
if( pOp->p5 ){
r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
}else{
r.flags = UNPACKED_IGNORE_ROWID;
@@ -50500,9 +52356,9 @@
** See documentation on OP_CreateTable for additional information.
*/
case OP_CreateIndex: /* out2-prerelease */
case OP_CreateTable: { /* out2-prerelease */
- int pgno;
+ int pgno = 0;
int flags;
Db *pDb;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
@@ -50514,12 +52370,10 @@
}else{
flags = BTREE_ZERODATA;
}
rc = sqlite3BtreeCreateTable(pDb->pBt, &pgno, flags);
- if( rc==SQLITE_OK ){
- pOut->u.i = pgno;
- MemSetTypeFlag(pOut, MEM_Int);
- }
+ pOut->u.i = pgno;
+ MemSetTypeFlag(pOut, MEM_Int);
break;
}
/* Opcode: ParseSchema P1 P2 * P4 *
@@ -50658,15 +52512,15 @@
assert( (pnErr->flags & MEM_Int)!=0 );
assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
pIn1 = &p->aMem[pOp->p1];
for(j=0; j<nRoot; j++){
- aRoot[j] = sqlite3VdbeIntValue(&pIn1[j]);
+ aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
}
aRoot[j] = 0;
assert( pOp->p5<db->nDb );
assert( (p->btreeMask & (1<<pOp->p5))!=0 );
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
- pnErr->u.i, &nErr);
+ (int)pnErr->u.i, &nErr);
sqlite3DbFree(db, aRoot);
pnErr->u.i -= nErr;
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
@@ -50681,37 +52535,58 @@
break;
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
-/* Opcode: FifoWrite P1 * * * *
-**
-** Write the integer from register P1 into the Fifo.
-*/
-case OP_FifoWrite: { /* in1 */
- p->sFifo.db = db;
- if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){
- goto no_mem;
- }
- break;
-}
-
-/* Opcode: FifoRead P1 P2 * * *
-**
-** Attempt to read a single integer from the Fifo. Store that
-** integer in register P1.
-**
-** If the Fifo is empty jump to P2.
-*/
-case OP_FifoRead: { /* jump */
- CHECK_FOR_INTERRUPT;
+/* Opcode: RowSetAdd P1 P2 * * *
+**
+** Insert the integer value held by register P2 into a boolean index
+** held in register P1.
+**
+** An assertion fails if P2 is not an integer.
+*/
+case OP_RowSetAdd: { /* in2 */
+ Mem *pIdx;
+ Mem *pVal;
+ assert( pOp->p1>0 && pOp->p1<=p->nMem );
+ pIdx = &p->aMem[pOp->p1];
+ assert( pOp->p2>0 && pOp->p2<=p->nMem );
+ pVal = &p->aMem[pOp->p2];
+ assert( (pVal->flags & MEM_Int)!=0 );
+ if( (pIdx->flags & MEM_RowSet)==0 ){
+ sqlite3VdbeMemSetRowSet(pIdx);
+ if( (pIdx->flags & MEM_RowSet)==0 ) goto no_mem;
+ }
+ sqlite3RowSetInsert(pIdx->u.pRowSet, pVal->u.i);
+ break;
+}
+
+/* Opcode: RowSetRead P1 P2 P3 * *
+**
+** Extract the smallest value from boolean index P1 and put that value into
+** register P3. Or, if boolean index P1 is initially empty, leave P3
+** unchanged and jump to instruction P2.
+*/
+case OP_RowSetRead: { /* jump, out3 */
+ Mem *pIdx;
+ i64 val;
assert( pOp->p1>0 && pOp->p1<=p->nMem );
- pOut = &p->aMem[pOp->p1];
- MemSetTypeFlag(pOut, MEM_Int);
- if( sqlite3VdbeFifoPop(&p->sFifo, &pOut->u.i)==SQLITE_DONE ){
+ CHECK_FOR_INTERRUPT;
+ pIdx = &p->aMem[pOp->p1];
+ if( (pIdx->flags & MEM_RowSet)==0
+ || sqlite3RowSetNext(pIdx->u.pRowSet, &val)==0
+ ){
+ /* The boolean index is empty */
+ sqlite3VdbeMemSetNull(pIdx);
pc = pOp->p2 - 1;
- }
- break;
-}
+ }else{
+ /* A value was pulled from the index */
+ assert( pOp->p3>0 && pOp->p3<=p->nMem );
+ pOut = &p->aMem[pOp->p3];
+ sqlite3VdbeMemSetInt64(pOut, val);
+ }
+ break;
+}
+
#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: ContextPush * * *
**
@@ -50733,10 +52608,8 @@
}
pContext = &p->contextStack[i];
pContext->lastRowid = db->lastRowid;
pContext->nChange = p->nChange;
- pContext->sFifo = p->sFifo;
- sqlite3VdbeFifoInit(&p->sFifo, db);
break;
}
/* Opcode: ContextPop * * *
@@ -50749,10 +52622,8 @@
Context *pContext = &p->contextStack[--p->contextStackTop];
assert( p->contextStackTop>=0 );
db->lastRowid = pContext->lastRowid;
p->nChange = pContext->nChange;
- sqlite3VdbeFifoClear(&p->sFifo);
- p->sFifo = pContext->sFifo;
break;
}
#endif /* #ifndef SQLITE_OMIT_TRIGGER */
@@ -50972,9 +52843,9 @@
** used to generate an error message if the lock cannot be obtained.
*/
case OP_TableLock: {
int p1 = pOp->p1;
- u8 isWriteLock = pOp->p3;
+ u8 isWriteLock = (u8)pOp->p3;
assert( p1>=0 && p1<db->nDb );
assert( (p->btreeMask & (1<<p1))!=0 );
assert( isWriteLock==0 || isWriteLock==1 );
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
@@ -51110,10 +52981,10 @@
pModule = pVtab->pModule;
/* Grab the index number and argc parameters */
assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
- nArg = pArgc->u.i;
- iQuery = pQuery->u.i;
+ nArg = (int)pArgc->u.i;
+ iQuery = (int)pQuery->u.i;
/* Invoke the xFilter method */
{
int res = 0;
@@ -52141,9 +54012,9 @@
** This file contains code use to implement an in-memory rollback journal.
** The in-memory rollback journal is used to journal transactions for
** ":memory:" databases and when the journal_mode=MEMORY pragma is used.
**
-** @(#) $Id: memjournal.c,v 1.5 2008/11/19 16:52:44 danielk1977 Exp $
+** @(#) $Id: memjournal.c,v 1.7 2008/12/10 21:19:57 drh Exp $
*/
/* Forward references to internal structures */
typedef struct MemJournal MemJournal;
@@ -52217,17 +54088,17 @@
}else{
pChunk = p->readpoint.pChunk;
}
- iChunkOffset = (iOfst%JOURNAL_CHUNKSIZE);
+ iChunkOffset = (int)(iOfst%JOURNAL_CHUNKSIZE);
do {
int iSpace = JOURNAL_CHUNKSIZE - iChunkOffset;
int nCopy = MIN(nRead, (JOURNAL_CHUNKSIZE - iChunkOffset));
memcpy(zOut, &pChunk->zChunk[iChunkOffset], nCopy);
zOut += nCopy;
nRead -= iSpace;
iChunkOffset = 0;
- } while( nRead>=0 && (pChunk=pChunk->pNext) && nRead>0 );
+ } while( nRead>=0 && (pChunk=pChunk->pNext)!=0 && nRead>0 );
p->readpoint.iOffset = iOfst+iAmt;
p->readpoint.pChunk = pChunk;
return SQLITE_OK;
@@ -52253,9 +54124,9 @@
UNUSED_PARAMETER(iOfst);
while( nWrite>0 ){
FileChunk *pChunk = p->endpoint.pChunk;
- int iChunkOffset = p->endpoint.iOffset%JOURNAL_CHUNKSIZE;
+ int iChunkOffset = (int)(p->endpoint.iOffset%JOURNAL_CHUNKSIZE);
int iSpace = MIN(nWrite, JOURNAL_CHUNKSIZE - iChunkOffset);
if( iChunkOffset==0 ){
/* New chunk is required to extend the file. */
@@ -52522,9 +54393,9 @@
** This file contains routines used for walking the parser tree and
** resolve all identifiers by associating them with a particular
** table and column.
**
-** $Id: resolve.c,v 1.11 2008/11/17 19:18:55 danielk1977 Exp $
+** $Id: resolve.c,v 1.15 2008/12/10 19:26:24 drh Exp $
*/
/*
** Turn the pExpr expression into an alias for the iCol-th column of the
@@ -52574,9 +54445,9 @@
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;
+ pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
}
pDup->iTable = pEList->a[iCol].iAlias;
}
if( pExpr->flags & EP_ExpCollate ){
@@ -52724,9 +54595,9 @@
*/
if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
TriggerStack *pTriggerStack = pParse->trigStack;
Table *pTab = 0;
- u32 *piColMask;
+ u32 *piColMask = 0;
if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
pExpr->iTable = pTriggerStack->newIdx;
assert( pTriggerStack->pTab );
pTab = pTriggerStack->pTab;
@@ -52988,9 +54859,9 @@
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 */
+ u8 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);
@@ -53261,9 +55132,9 @@
if( pE==0 ) return 1;
pE->pColl = pColl;
pE->flags |= EP_IntValue | flags;
pE->iTable = iCol;
- pItem->iCol = iCol;
+ pItem->iCol = (u16)iCol;
pItem->done = 1;
}else{
moreToDo = 1;
}
@@ -53365,9 +55236,9 @@
/* 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;
+ pItem->iCol = (u16)iCol;
continue;
}
if( sqlite3ExprIsInteger(pE, &iCol) ){
/* The ORDER BY term is an integer constant. Again, set the column
@@ -53376,9 +55247,9 @@
if( iCol<1 ){
resolveOutOfRangeError(pParse, zType, i+1, nResult);
return 1;
}
- pItem->iCol = iCol;
+ pItem->iCol = (u16)iCol;
continue;
}
/* Otherwise, treat the ORDER BY term as an ordinary expression */
@@ -53468,9 +55339,9 @@
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);
+ sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
}
}
@@ -53689,9 +55560,9 @@
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.404 2008/11/19 16:52:44 danielk1977 Exp $
+** $Id: expr.c,v 1.408 2008/12/15 15:27:52 drh Exp $
*/
/*
** Return the 'affinity' of the expression pExpr if any.
@@ -53865,9 +55736,9 @@
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
*/
static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
u8 aff = (char)sqlite3ExprAffinity(pExpr2);
- aff = sqlite3CompareAffinity(pExpr1, aff) | jumpIfNull;
+ aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
return aff;
}
/*
@@ -53947,9 +55818,9 @@
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
- sqlite3VdbeChangeP5(pParse->pVdbe, p5);
+ sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
if( (p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_NONE ){
sqlite3ExprCacheAffinityChange(pParse, in1, 1);
sqlite3ExprCacheAffinityChange(pParse, in2, 1);
}
@@ -54072,9 +55943,9 @@
sqlite3ExprDelete(db, pLeft);
sqlite3ExprDelete(db, pRight);
return 0;
}
- pNew->op = op;
+ pNew->op = (u8)op;
pNew->pLeft = pLeft;
pNew->pRight = pRight;
pNew->iAgg = -1;
pNew->span.z = (u8*)"";
@@ -54244,9 +56115,10 @@
/* Wildcards of the form ":aaa" or "$aaa". Reuse the same variable
** number as the prior appearance of the same name, or if the name
** has never appeared before, reuse the same variable number
*/
- int i, n;
+ int i;
+ u32 n;
n = pToken->n;
for(i=0; i<pParse->nVarExpr; i++){
Expr *pE;
if( (pE = pParse->apVarExpr[i])!=0
@@ -54510,9 +56382,9 @@
if( a==0 ){
goto no_mem;
}
pList->a = a;
- pList->nAlloc = n;
+ pList->nAlloc = sqlite3DbMallocSize(db, a)/sizeof(a[0]);
}
assert( pList->a!=0 );
if( pExpr || pName ){
struct ExprList_item *pItem = &pList->a[pList->nExpr++];
@@ -55006,9 +56878,9 @@
ExprList *pEList;
assert( !isRowid );
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
- dest.affinity = (int)affinity;
+ dest.affinity = (u8)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
if( sqlite3Select(pParse, pExpr->pSelect, &dest) ){
return;
}
@@ -55400,12 +57272,16 @@
*/
static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr, int target){
sqlite3 *db = pParse->db;
int iReg;
- if( pParse->aAlias==0 ){
- pParse->aAlias = sqlite3DbMallocZero(db,
+ if( pParse->nAliasAlloc<pParse->nAlias ){
+ pParse->aAlias = sqlite3DbReallocOrFree(db, pParse->aAlias,
sizeof(pParse->aAlias[0])*pParse->nAlias );
+ testcase( db->mallocFailed && pParse->nAliasAlloc>0 );
if( db->mallocFailed ) return 0;
+ memset(&pParse->aAlias[pParse->nAliasAlloc], 0,
+ (pParse->nAlias-pParse->nAliasAlloc)*sizeof(pParse->aAlias[0]));
+ pParse->nAliasAlloc = pParse->nAlias;
}
assert( iAlias>0 && iAlias<=pParse->nAlias );
iReg = pParse->aAlias[iAlias-1];
if( iReg==0 ){
@@ -55645,13 +57521,12 @@
assert( TK_BITNOT==OP_BitNot );
assert( TK_NOT==OP_Not );
testcase( op==TK_BITNOT );
testcase( op==TK_NOT );
- inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
- testcase( inReg==target );
- testcase( usedAsColumnCache(pParse, inReg, inReg) );
- inReg = sqlite3ExprWritableRegister(pParse, inReg, target);
- sqlite3VdbeAddOp1(v, op, inReg);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
+ testcase( regFree1==0 );
+ inReg = target;
+ sqlite3VdbeAddOp2(v, op, r1, inReg);
break;
}
case TK_ISNULL:
case TK_NOTNULL: {
@@ -55735,9 +57610,9 @@
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
(char*)pDef, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, nExpr);
+ sqlite3VdbeChangeP5(v, (u8)nExpr);
if( nExpr ){
sqlite3ReleaseTempRange(pParse, r1, nExpr);
}
sqlite3ExprCacheAffinityChange(pParse, r1, nExpr);
@@ -55914,9 +57789,9 @@
struct ExprList_item *aListelem; /* Array of WHEN terms */
Expr opCompare; /* The X==Ei expression */
Expr cacheX; /* Cached expression X */
Expr *pX; /* The X expression */
- Expr *pTest; /* X==Ei (form A) or just Ei (form B) */
+ Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
assert(pExpr->pList);
assert((pExpr->pList->nExpr % 2) == 0);
assert(pExpr->pList->nExpr > 0);
@@ -55936,8 +57811,9 @@
}
pParse->disableColCache++;
for(i=0; i<nExpr; i=i+2){
if( pX ){
+ assert( pTest!=0 );
opCompare.pRight = aListelem[i].pExpr;
}else{
pTest = aListelem[i].pExpr;
}
@@ -56791,9 +58667,9 @@
*************************************************************************
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
-** $Id: alter.c,v 1.50 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: alter.c,v 1.51 2008/12/10 19:26:22 drh Exp $
*/
/*
** The code in this file only exists if we are not omitting the
@@ -57082,9 +58958,11 @@
/* Make sure it is not a system table being altered, or a reserved name
** that the table is being renamed to.
*/
- if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){
+ if( sqlite3Strlen30(pTab->zName)>6
+ && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
+ ){
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
goto exit_rename_table;
}
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
@@ -57415,9 +59293,9 @@
**
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
-** @(#) $Id: analyze.c,v 1.46 2008/11/19 16:52:44 danielk1977 Exp $
+** @(#) $Id: analyze.c,v 1.47 2008/12/10 16:45:51 drh Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
/*
@@ -57436,9 +59314,9 @@
){
sqlite3 *db = pParse->db;
Db *pDb;
int iRootPage;
- int createStat1 = 0;
+ u8 createStat1 = 0;
Table *pStat;
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
@@ -57844,9 +59722,9 @@
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
-** $Id: attach.c,v 1.80 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: attach.c,v 1.81 2008/12/10 16:45:51 drh Exp $
*/
#ifndef SQLITE_OMIT_ATTACH
/*
@@ -58167,9 +60045,10 @@
assert( v || db->mallocFailed );
if( v ){
sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3);
- sqlite3VdbeChangeP5(v, pFunc->nArg);
+ assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
+ sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);
/* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
** statement only). For DETACH, set it to false (expire all existing
@@ -58631,17 +60510,17 @@
** BEGIN TRANSACTION
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.503 2008/11/17 19:18:55 danielk1977 Exp $
+** $Id: build.c,v 1.508 2008/12/10 22:30:25 shane Exp $
*/
/*
** This routine is called when a new SQL statement is beginning to
** be parsed. Initialize the pParse structure as needed.
*/
SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){
- pParse->explain = explainFlag;
+ pParse->explain = (u8)explainFlag;
pParse->nVar = 0;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
@@ -58794,9 +60673,10 @@
** an OP_Trace) to be the complete text of the current SQL statement.
*/
VdbeOp *pOp = sqlite3VdbeGetOp(v, 0);
if( pOp && pOp->opcode==OP_Trace ){
- sqlite3VdbeChangeP4(v, 0, pParse->zSql, pParse->zTail-pParse->zSql);
+ sqlite3VdbeChangeP4(v, 0, pParse->zSql,
+ (int)(pParse->zTail - pParse->zSql));
}
}
#endif /* SQLITE_OMIT_TRACE */
}
@@ -58976,9 +60856,10 @@
static void sqliteDeleteIndex(Index *p){
Index *pOld;
const char *zName = p->zName;
- pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen(zName)+1, 0);
+ pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName,
+ sqlite3Strlen30(zName)+1, 0);
assert( pOld==0 || pOld==p );
freeIndex(p);
}
@@ -59141,9 +61022,9 @@
*/
for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
pNextFKey = pFKey->pNextFrom;
assert( sqlite3HashFind(&pTable->pSchema->aFKey,
- pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
+ pFKey->zTo, sqlite3Strlen30(pFKey->zTo)+1)!=pFKey );
sqlite3DbFree(db, pFKey);
}
#endif
@@ -59172,13 +61053,14 @@
assert( db!=0 );
assert( iDb>=0 && iDb<db->nDb );
assert( zTabName && zTabName[0] );
pDb = &db->aDb[iDb];
- p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, strlen(zTabName)+1,0);
+ p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
+ sqlite3Strlen30(zTabName)+1,0);
if( p ){
#ifndef SQLITE_OMIT_FOREIGN_KEY
for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
- int nTo = strlen(pF1->zTo) + 1;
+ int nTo = sqlite3Strlen30(pF1->zTo) + 1;
pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo);
if( pF2==pF1 ){
sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo);
}else{
@@ -59233,17 +61115,17 @@
** does not exist.
*/
SQLITE_PRIVATE int sqlite3FindDb(sqlite3 *db, Token *pName){
int i = -1; /* Database number */
- size_t n; /* Number of characters in the name */
+ int n; /* Number of characters in the name */
Db *pDb; /* A database whose name space is being searched */
char *zName; /* Name we are searching for */
zName = sqlite3NameFromToken(db, pName);
if( zName ){
- n = strlen(zName);
+ n = sqlite3Strlen30(zName);
for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
- if( (!OMIT_TEMPDB || i!=1 ) && n==strlen(pDb->zName) &&
+ if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite3Strlen30(pDb->zName) &&
0==sqlite3StrICmp(pDb->zName, zName) ){
break;
}
}
@@ -59600,9 +61482,9 @@
Table *p;
int i;
if( (p = pParse->pNewTable)==0 ) return;
i = p->nCol-1;
- if( i>=0 ) p->aCol[i].notNull = onError;
+ if( i>=0 ) p->aCol[i].notNull = (u8)onError;
}
/*
** Scan the column type name zType (length nType) and return the
@@ -59779,9 +61661,9 @@
}
if( zType && sqlite3StrICmp(zType, "INTEGER")==0
&& sortOrder==SQLITE_SO_ASC ){
pTab->iPKey = iCol;
- pTab->keyConf = onError;
+ pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
@@ -59972,9 +61854,9 @@
for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
n += identLength(pCol->zName);
z = pCol->zType;
if( z ){
- n += (strlen(z) + 1);
+ n += (sqlite3Strlen30(z) + 1);
}
}
n += identLength(p->zName);
if( n<50 ){
@@ -59993,21 +61875,21 @@
return 0;
}
sqlite3_snprintf(n, zStmt,
!OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE ");
- k = strlen(zStmt);
+ k = sqlite3Strlen30(zStmt);
identPut(zStmt, &k, p->zName);
zStmt[k++] = '(';
for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
sqlite3_snprintf(n-k, &zStmt[k], zSep);
- k += strlen(&zStmt[k]);
+ k += sqlite3Strlen30(&zStmt[k]);
zSep = zSep2;
identPut(zStmt, &k, pCol->zName);
if( (z = pCol->zType)!=0 ){
zStmt[k++] = ' ';
- assert( (int)(strlen(z)+k+1)<=n );
+ assert( (int)(sqlite3Strlen30(z)+k+1)<=n );
sqlite3_snprintf(n-k, &zStmt[k], "%s", z);
- k += strlen(z);
+ k += sqlite3Strlen30(z);
}
}
sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);
return zStmt;
@@ -60159,9 +62041,9 @@
/* Compute the complete text of the CREATE statement */
if( pSelect ){
zStmt = createTableStmt(db, p, p->pSchema==db->aDb[1].pSchema);
}else{
- n = pEnd->z - pParse->sNameToken.z + 1;
+ n = (int)(pEnd->z - pParse->sNameToken.z) + 1;
zStmt = sqlite3MPrintf(db,
"CREATE %s %.*s", zType2, n, pParse->sNameToken.z
);
}
@@ -60213,9 +62095,10 @@
if( db->init.busy && pParse->nErr==0 ){
Table *pOld;
FKey *pFKey;
Schema *pSchema = p->pSchema;
- pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, strlen(p->zName)+1,p);
+ pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName,
+ sqlite3Strlen30(p->zName)+1,p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
db->mallocFailed = 1;
return;
@@ -60222,9 +62105,9 @@
}
#ifndef SQLITE_OMIT_FOREIGN_KEY
for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
void *data;
- int nTo = strlen(pFKey->zTo) + 1;
+ int nTo = sqlite3Strlen30(pFKey->zTo) + 1;
pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo);
data = sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey);
if( data==(void *)pFKey ){
db->mallocFailed = 1;
@@ -60242,9 +62125,9 @@
assert( !pSelect && pCons && pEnd );
if( pCons->z==0 ){
pCons = pEnd;
}
- nName = (const char *)pCons->z - zName;
+ nName = (int)((const char *)pCons->z - zName);
p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);
}
#endif
}
@@ -60313,9 +62196,9 @@
if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
sEnd.z += sEnd.n;
}
sEnd.n = 0;
- n = sEnd.z - pBegin->z;
+ n = (int)(sEnd.z - pBegin->z);
z = (const unsigned char*)pBegin->z;
while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }
sEnd.z = &z[n-1];
sEnd.n = 1;
@@ -60653,9 +62536,8 @@
sqlite3BeginWriteOperation(pParse, 1, iDb);
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
- Vdbe *v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp0(v, OP_VBegin);
}
}
@@ -60780,9 +62662,9 @@
}
nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;
if( pToCol ){
for(i=0; i<pToCol->nExpr; i++){
- nByte += strlen(pToCol->a[i].zName) + 1;
+ nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
}
}
pFKey = sqlite3DbMallocZero(db, nByte );
if( pFKey==0 ){
@@ -60819,19 +62701,19 @@
}
}
if( pToCol ){
for(i=0; i<nCol; i++){
- int n = strlen(pToCol->a[i].zName);
+ int n = sqlite3Strlen30(pToCol->a[i].zName);
pFKey->aCol[i].zCol = z;
memcpy(z, pToCol->a[i].zName, n);
z[n] = 0;
z += n+1;
}
}
pFKey->isDeferred = 0;
- pFKey->deleteConf = flags & 0xff;
- pFKey->updateConf = (flags >> 8 ) & 0xff;
- pFKey->insertConf = (flags >> 16 ) & 0xff;
+ pFKey->deleteConf = (u8)(flags & 0xff);
+ pFKey->updateConf = (u8)((flags >> 8 ) & 0xff);
+ pFKey->insertConf = (u8)((flags >> 16 ) & 0xff);
/* Link the foreign key to the table as the last step.
*/
p->pFKey = pFKey;
@@ -60855,9 +62737,10 @@
#ifndef SQLITE_OMIT_FOREIGN_KEY
Table *pTab;
FKey *pFKey;
if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
- pFKey->isDeferred = isDeferred;
+ assert( isDeferred==0 || isDeferred==1 );
+ pFKey->isDeferred = (u8)isDeferred;
#endif
}
/*
@@ -61105,12 +62988,12 @@
** So create a fake list to simulate this.
*/
if( pList==0 ){
nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName;
- nullId.n = strlen((char*)nullId.z);
+ nullId.n = sqlite3Strlen30((char*)nullId.z);
pList = sqlite3ExprListAppend(pParse, 0, 0, &nullId);
if( pList==0 ) goto exit_create_index;
- pList->a[0].sortOrder = sortOrder;
+ pList->a[0].sortOrder = (u8)sortOrder;
}
/* Figure out how many bytes of space are required to store explicitly
** specified collation sequence names.
@@ -61118,16 +63001,16 @@
for(i=0; i<pList->nExpr; i++){
Expr *pExpr;
CollSeq *pColl;
if( (pExpr = pList->a[i].pExpr)!=0 && (pColl = pExpr->pColl)!=0 ){
- nExtra += (1 + strlen(pColl->zName));
+ nExtra += (1 + sqlite3Strlen30(pColl->zName));
}
}
/*
** Allocate the index structure.
*/
- nName = strlen(zName);
+ nName = sqlite3Strlen30(zName);
nCol = pList->nExpr;
pIndex = sqlite3DbMallocZero(db,
sizeof(Index) + /* Index structure */
sizeof(int)*nCol + /* Index.aiColumn */
@@ -61148,10 +63031,10 @@
zExtra = (char *)(&pIndex->zName[nName+1]);
memcpy(pIndex->zName, zName, nName+1);
pIndex->pTable = pTab;
pIndex->nColumn = pList->nExpr;
- pIndex->onError = onError;
- pIndex->autoIndex = pName==0;
+ pIndex->onError = (u8)onError;
+ pIndex->autoIndex = (u8)(pName==0);
pIndex->pSchema = db->aDb[iDb].pSchema;
/* Check to see if we should honor DESC requests on index columns
*/
@@ -61189,9 +63072,9 @@
if( pListItem->pExpr && pListItem->pExpr->pColl ){
assert( pListItem->pExpr->pColl );
zColl = zExtra;
sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName);
- zExtra += (strlen(zColl) + 1);
+ zExtra += (sqlite3Strlen30(zColl) + 1);
}else{
zColl = pTab->aCol[j].zColl;
if( !zColl ){
zColl = db->pDfltColl->zName;
@@ -61201,9 +63084,9 @@
goto exit_create_index;
}
pIndex->azColl[i] = zColl;
requestedSortOrder = pListItem->sortOrder & sortOrderMask;
- pIndex->aSortOrder[i] = requestedSortOrder;
+ pIndex->aSortOrder[i] = (u8)requestedSortOrder;
}
sqlite3DefaultRowEst(pIndex);
if( pTab==pParse->pNewTable ){
@@ -61262,9 +63145,10 @@
*/
if( db->init.busy ){
Index *p;
p = sqlite3HashInsert(&pIndex->pSchema->idxHash,
- pIndex->zName, strlen(pIndex->zName)+1, pIndex);
+ pIndex->zName, sqlite3Strlen30(pIndex->zName)+1,
+ pIndex);
if( p ){
assert( p==pIndex ); /* Malloc must have failed */
db->mallocFailed = 1;
goto exit_create_index;
@@ -61536,9 +63420,9 @@
if( pNew==0 ){
*pIdx = -1;
return pArray;
}
- *pnAlloc = newSize;
+ *pnAlloc = sqlite3DbMallocSize(db, pNew)/szEntry;
pArray = pNew;
}
z = (char*)pArray;
memset(&z[*pnEntry * szEntry], 0, szEntry);
@@ -61641,24 +63525,26 @@
/* Allocate additional space if needed */
if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
SrcList *pNew;
int nAlloc = pSrc->nSrc+nExtra;
+ int nGot;
pNew = sqlite3DbRealloc(db, pSrc,
sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
if( pNew==0 ){
assert( db->mallocFailed );
return pSrc;
}
pSrc = pNew;
- pSrc->nAlloc = nAlloc;
+ nGot = (sqlite3DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
+ pSrc->nAlloc = (u16)nGot;
}
/* Move existing slots that come after the newly inserted slots
** out of the way */
for(i=pSrc->nSrc-1; i>=iStart; i--){
pSrc->a[i+nExtra] = pSrc->a[i];
}
- pSrc->nSrc += nExtra;
+ pSrc->nSrc += (i16)nExtra;
/* Zero the newly allocated slots */
memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
for(i=iStart; i<iStart+nExtra; i++){
@@ -62176,9 +64062,9 @@
assert( zColl );
pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1);
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
}
- pKey->nField = nCol;
+ pKey->nField = (u16)nCol;
}
if( pParse->nErr ){
sqlite3DbFree(db, pKey);
@@ -62203,9 +64089,9 @@
**
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
-** $Id: callback.c,v 1.32 2008/10/10 17:41:29 drh Exp $
+** $Id: callback.c,v 1.34 2008/12/10 21:19:57 drh Exp $
*/
/*
@@ -62245,9 +64131,9 @@
*/
static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
CollSeq *pColl2;
char *z = pColl->zName;
- int n = strlen(z);
+ int n = sqlite3Strlen30(z);
int i;
static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };
for(i=0; i<3; i++){
pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0);
@@ -62476,9 +64362,9 @@
FuncDefHash *pHash, /* The hash table into which to insert */
FuncDef *pDef /* The function definition to insert */
){
FuncDef *pOther;
- int nName = strlen(pDef->zName);
+ int nName = sqlite3Strlen30(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 ){
@@ -62570,9 +64456,9 @@
*/
if( createFlag && (bestScore<6 || pBest->nArg!=nArg) &&
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
pBest->zName = (char *)&pBest[1];
- pBest->nArg = nArg;
+ pBest->nArg = (u16)nArg;
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
sqlite3FuncDefInsert(&db->aFunc, pBest);
@@ -62655,9 +64541,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.187 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: delete.c,v 1.190 2008/12/10 21:19:57 drh Exp $
*/
/*
** Look up every table that is named in pSrc. If any table is not found,
@@ -62718,9 +64604,9 @@
Vdbe *v;
if( IsVirtual(pTab) ) return;
v = sqlite3GetVdbe(p);
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
- sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
+ sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);
sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);
VdbeComment((v, "%s", pTab->zName));
}
@@ -62748,9 +64634,9 @@
Token viewName;
pWhere = sqlite3ExprDup(db, pWhere);
viewName.z = (u8*)pView->zName;
- viewName.n = (unsigned int)strlen((const char*)viewName.z);
+ viewName.n = (unsigned int)sqlite3Strlen30((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);
@@ -62882,12 +64768,12 @@
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
int triggers_exist = 0; /* True if any triggers exist */
#endif
- int iBeginAfterTrigger; /* Address of after trigger program */
- int iEndAfterTrigger; /* Exit of after trigger program */
- int iBeginBeforeTrigger; /* Address of before trigger program */
- int iEndBeforeTrigger; /* Exit of before trigger program */
+ int iBeginAfterTrigger = 0; /* Address of after trigger program */
+ int iEndAfterTrigger = 0; /* Exit of after trigger program */
+ int iBeginBeforeTrigger = 0; /* Address of before trigger program */
+ int iEndBeforeTrigger = 0; /* Exit of before trigger program */
u32 old_col_mask = 0; /* Mask of OLD.* columns in use */
sContext.pParse = 0;
db = pParse->db;
@@ -63032,8 +64918,9 @@
** the table and pick which records to delete.
*/
{
int iRowid = ++pParse->nMem; /* Used for storing rowid values. */
+ int iRowSet = ++pParse->nMem; /* Register for rowset of rows to delete */
/* Begin the database scan
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
@@ -63041,9 +64928,9 @@
/* Remember the rowid of every item to be deleted.
*/
sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, iRowid);
- sqlite3VdbeAddOp1(v, OP_FifoWrite, iRowid);
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iRowid);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
}
@@ -63076,9 +64963,9 @@
*/
if( triggers_exist ){
sqlite3VdbeResolveLabel(v, addr);
}
- addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end);
+ addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);
if( triggers_exist ){
int iData = ++pParse->nMem; /* For storing row data of OLD table */
@@ -63296,9 +65183,9 @@
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: func.c,v 1.206 2008/11/19 16:52:44 danielk1977 Exp $
+** $Id: func.c,v 1.209 2008/12/10 23:04:13 drh Exp $
*/
/*
** Return the collating function associated with a function.
@@ -63487,12 +65374,12 @@
}
for(z2=z; *z2 && p2; p2--){
SQLITE_SKIP_UTF8(z2);
}
- sqlite3_result_text(context, (char*)z, z2-z, SQLITE_TRANSIENT);
+ sqlite3_result_text(context, (char*)z, (int)(z2-z), SQLITE_TRANSIENT);
}else{
if( p2<0 ) p2 = 0;
- sqlite3_result_blob(context, (char*)&z[p1], p2, SQLITE_TRANSIENT);
+ sqlite3_result_blob(context, (char*)&z[p1], (int)p2, SQLITE_TRANSIENT);
}
}
/*
@@ -63526,9 +65413,9 @@
if( nByte>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
z = 0;
}else{
- z = sqlite3Malloc(nByte);
+ z = sqlite3Malloc((int)nByte);
if( !z && nByte>0 ){
sqlite3_result_error_nomem(context);
}
}
@@ -63551,9 +65438,9 @@
z1 = contextMalloc(context, ((i64)n)+1);
if( z1 ){
memcpy(z1, z2, n+1);
for(i=0; z1[i]; i++){
- z1[i] = toupper(z1[i]);
+ z1[i] = (char)toupper(z1[i]);
}
sqlite3_result_text(context, z1, -1, sqlite3_free);
}
}
@@ -63571,9 +65458,9 @@
z1 = contextMalloc(context, ((i64)n)+1);
if( z1 ){
memcpy(z1, z2, n+1);
for(i=0; z1[i]; i++){
- z1[i] = tolower(z1[i]);
+ z1[i] = (char)tolower(z1[i]);
}
sqlite3_result_text(context, z1, -1, sqlite3_free);
}
}
@@ -64063,9 +65950,9 @@
n = sqlite3_value_int64(argv[0]);
if( n>SQLITE_MAX_LENGTH ){
sqlite3_result_error_toobig(context);
}else{
- sqlite3_result_zeroblob(context, n);
+ sqlite3_result_zeroblob(context, (int)n);
}
}
/*
@@ -64156,10 +66043,10 @@
const unsigned char *zCharSet; /* Set of characters to trim */
int nIn; /* Number of bytes in input */
int flags; /* 1: trimleft 2: trimright 3: trim */
int i; /* Loop counter */
- unsigned char *aLen; /* Length of each character in zCharSet */
- unsigned char **azChar; /* Individual characters in zCharSet */
+ unsigned char *aLen = 0; /* Length of each character in zCharSet */
+ unsigned char **azChar = 0; /* Individual characters in zCharSet */
int nChar; /* Number of characters in zCharSet */
if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
return;
@@ -64190,17 +66077,17 @@
aLen = (unsigned char*)&azChar[nChar];
for(z=zCharSet, nChar=0; *z; nChar++){
azChar[nChar] = (unsigned char *)z;
SQLITE_SKIP_UTF8(z);
- aLen[nChar] = z - azChar[nChar];
+ aLen[nChar] = (u8)(z - azChar[nChar]);
}
}
}
if( nChar>0 ){
flags = SQLITE_PTR_TO_INT(sqlite3_user_data(context));
if( flags & 1 ){
while( nIn>0 ){
- int len;
+ int len = 0;
for(i=0; i<nChar; i++){
len = aLen[i];
if( memcmp(zIn, azChar[i], len)==0 ) break;
}
@@ -64210,9 +66097,9 @@
}
}
if( flags & 2 ){
while( nIn>0 ){
- int len;
+ int len = 0;
for(i=0; i<nChar; i++){
len = aLen[i];
if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
}
@@ -64338,12 +66225,12 @@
i64 v = sqlite3_value_int64(argv[0]);
p->rSum += v;
if( (p->approx|p->overflow)==0 ){
i64 iNewSum = p->iSum + v;
- int s1 = p->iSum >> (sizeof(i64)*8-1);
- int s2 = v >> (sizeof(i64)*8-1);
- int s3 = iNewSum >> (sizeof(i64)*8-1);
- p->overflow = (s1&s2&~s3) | (~s1&~s2&s3);
+ int s1 = (int)(p->iSum >> (sizeof(i64)*8-1));
+ int s2 = (int)(v >> (sizeof(i64)*8-1));
+ int s3 = (int)(iNewSum >> (sizeof(i64)*8-1));
+ p->overflow = ((s1&s2&~s3) | (~s1&~s2&s3))?1:0;
p->iSum = iNewSum;
}
}else{
p->rSum += sqlite3_value_double(argv[0]);
@@ -64526,11 +66413,12 @@
/*
** Set the LIKEOPT flag on the 2-argument function with the given name.
*/
-static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){
+static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
FuncDef *pDef;
- pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0);
+ pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName),
+ 2, SQLITE_UTF8, 0);
if( pDef ){
pDef->flags = flagVal;
}
}
@@ -64691,9 +66579,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.253 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: insert.c,v 1.256 2008/12/10 21:19:57 drh Exp $
*/
/*
** Set P4 of the most recently inserted opcode to a column affinity
@@ -65066,16 +66954,16 @@
Db *pDb; /* The database containing table being inserted into */
int appendFlag = 0; /* True if the insert is likely to be an append */
/* Register allocations */
- int regFromSelect; /* Base register for data coming from SELECT */
+ int regFromSelect = 0;/* Base register for data coming from SELECT */
int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */
int regRowCount = 0; /* Memory cell used for the row counter */
int regIns; /* Block of regs holding rowid+data being inserted */
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int regRecord; /* Holds the assemblied row record */
- int regEof; /* Register recording end of SELECT data */
+ int regEof = 0; /* Register recording end of SELECT data */
int *aRegIdx = 0; /* One register allocated to each index */
#ifndef SQLITE_OMIT_TRIGGER
@@ -65083,8 +66971,9 @@
int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */
#endif
db = pParse->db;
+ memset(&dest, 0, sizeof(dest));
if( pParse->nErr || db->mallocFailed ){
goto insert_cleanup;
}
@@ -65250,26 +67139,26 @@
** insert row from R..R+n into temp table
** goto L
** M: ...
*/
- int regRec; /* Register to hold packed record */
- int regRowid; /* Register to hold temp table ROWID */
- int addrTop; /* Label "L" */
- int addrIf; /* Address of jump to M */
+ int regRec; /* Register to hold packed record */
+ int regTempRowid; /* Register to hold temp table ROWID */
+ int addrTop; /* Label "L" */
+ int addrIf; /* Address of jump to M */
srcTab = pParse->nTab++;
regRec = sqlite3GetTempReg(pParse);
- regRowid = sqlite3GetTempReg(pParse);
+ regTempRowid = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);
addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
- sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid);
- sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid);
+ sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
sqlite3VdbeJumpHere(v, addrIf);
sqlite3ReleaseTempReg(pParse, regRec);
- sqlite3ReleaseTempReg(pParse, regRowid);
+ sqlite3ReleaseTempReg(pParse, regTempRowid);
}
}else{
/* This is the case if the data for the INSERT is coming from a VALUES
** clause
@@ -65368,9 +67257,8 @@
/* If this is not a view, open the table and and all indices */
if( !isView ){
int nIdx;
- int i;
baseCur = pParse->nTab;
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite);
aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));
@@ -65424,9 +67312,9 @@
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqlite3VdbeMakeLabel(v);
if( triggers_exist & TRIGGER_BEFORE ){
- int regRowid;
+ int regTrigRowid;
int regCols;
int regRec;
/* build the NEW.* reference row. Note that if there is an INTEGER
@@ -65434,21 +67322,21 @@
** translated into a unique ID for the row. But on a BEFORE trigger,
** we do not know what the unique ID will be (because the insert has
** not happened yet) so we substitute a rowid of -1
*/
- regRowid = sqlite3GetTempReg(pParse);
+ regTrigRowid = sqlite3GetTempReg(pParse);
if( keyColumn<0 ){
- sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regTrigRowid);
}else if( useTempTable ){
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regTrigRowid);
}else{
int j1;
assert( pSelect==0 ); /* Otherwise useTempTable is true */
- sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);
- j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid);
- sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
+ sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regTrigRowid);
+ j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regTrigRowid);
+ sqlite3VdbeAddOp2(v, OP_Integer, -1, regTrigRowid);
sqlite3VdbeJumpHere(v, j1);
- sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);
+ sqlite3VdbeAddOp1(v, OP_MustBeInt, regTrigRowid);
}
/* Cannot have triggers on a virtual table. If it were possible,
** this block would have to account for hidden column.
@@ -65485,11 +67373,11 @@
*/
if( !isView ){
sqlite3TableAffinityStr(v, pTab);
}
- sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid);
+ sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regTrigRowid);
sqlite3ReleaseTempReg(pParse, regRec);
- sqlite3ReleaseTempReg(pParse, regRowid);
+ sqlite3ReleaseTempReg(pParse, regTrigRowid);
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol);
/* Fire BEFORE or INSTEAD OF triggers */
if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab,
@@ -65772,9 +67660,10 @@
int i;
Vdbe *v;
int nCol;
int onError;
- int j1, j2, j3; /* Addresses of jump instructions */
+ int j1; /* Addresss of jump instruction */
+ int j2 = 0, j3; /* Addresses of jump instructions */
int regData; /* Register containing first data column */
int iCur;
Index *pIdx;
int seenReplace = 0;
@@ -65951,12 +67840,12 @@
int j, n1, n2;
char zErrMsg[200];
sqlite3_snprintf(ArraySize(zErrMsg), zErrMsg,
pIdx->nColumn>1 ? "columns " : "column ");
- n1 = strlen(zErrMsg);
+ n1 = sqlite3Strlen30(zErrMsg);
for(j=0; j<pIdx->nColumn && n1<ArraySize(zErrMsg)-30; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
- n2 = strlen(zCol);
+ n2 = sqlite3Strlen30(zCol);
if( j>0 ){
sqlite3_snprintf(ArraySize(zErrMsg)-n1, &zErrMsg[n1], ", ");
n1 += 2;
}
@@ -66013,9 +67902,9 @@
int i;
Vdbe *v;
int nIdx;
Index *pIdx;
- int pik_flags;
+ u8 pik_flags;
int regData;
int regRec;
v = sqlite3GetVdbe(pParse);
@@ -66431,9 +68320,9 @@
** implement the programmer interface to the library. Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: legacy.c,v 1.29 2008/08/02 03:50:39 drh Exp $
+** $Id: legacy.c,v 1.30 2008/12/10 19:26:24 drh Exp $
*/
/*
@@ -66546,9 +68435,9 @@
sqlite3DbFree(db, azCols);
rc = sqlite3ApiExit(db, rc);
if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
- int nErrMsg = 1 + strlen(sqlite3_errmsg(db));
+ int nErrMsg = 1 + sqlite3Strlen30(sqlite3_errmsg(db));
*pzErrMsg = sqlite3Malloc(nErrMsg);
if( *pzErrMsg ){
memcpy(*pzErrMsg, sqlite3_errmsg(db), nErrMsg);
}
@@ -66576,9 +68465,9 @@
*************************************************************************
** This file contains code used to dynamically load extensions into
** the SQLite library.
**
-** $Id: loadext.c,v 1.56 2008/10/12 00:27:53 shane Exp $
+** $Id: loadext.c,v 1.57 2008/12/08 18:19:18 drh Exp $
*/
#ifndef SQLITE_CORE
#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
@@ -67426,12 +69315,12 @@
**
** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER
** mutex must be held while accessing this list.
*/
-typedef struct sqlite3ExtType sqlite3ExtType;
-static SQLITE_WSD struct sqlite3ExtType {
- int nExt; /* Number of entries in aExt[] */
- void **aExt; /* Pointers to the extension init functions */
+typedef struct sqlite3AutoExtList sqlite3AutoExtList;
+static SQLITE_WSD struct sqlite3AutoExtList {
+ int nExt; /* Number of entries in aExt[] */
+ void (**aExt)(void); /* Pointers to the extension init functions */
} sqlite3Autoext = { 0, 0 };
/* The "wsdAutoext" macro will resolve to the autoextension
** state vector. If writable static data is unsupported on the target,
@@ -67440,9 +69329,9 @@
** to the "sqlite3Autoext" state vector declared above.
*/
#ifdef SQLITE_OMIT_WSD
# define wsdAutoextInit \
- sqlite3ExtType *x = &GLOBAL(sqlite3ExtType,sqlite3Autoext)
+ sqlite3AutoExtList *x = &GLOBAL(sqlite3AutoExtList,sqlite3Autoext)
# define wsdAutoext x[0]
#else
# define wsdAutoextInit
# define wsdAutoext sqlite3Autoext
@@ -67452,9 +69341,9 @@
/*
** Register a statically linked extension that is automatically
** loaded by every new database connection.
*/
-SQLITE_API int sqlite3_auto_extension(void *xInit){
+SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
if( rc ){
@@ -67472,9 +69361,9 @@
if( wsdAutoext.aExt[i]==xInit ) break;
}
if( i==wsdAutoext.nExt ){
int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
- void **aNew;
+ void (**aNew)(void);
aNew = sqlite3_realloc(wsdAutoext.aExt, nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -67562,9 +69451,9 @@
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.194 2008/11/17 19:18:55 danielk1977 Exp $
+** $Id: pragma.c,v 1.199 2008/12/10 23:04:13 drh Exp $
*/
/* Ignore this whole file if pragmas are disabled
*/
@@ -67579,19 +69468,19 @@
** should be passed into sqlite3BtreeSetSafetyLevel(). The is done
** to support legacy SQL code. The safety level used to be boolean
** and older scripts may have used numbers 0 for OFF and 1 for ON.
*/
-static int getSafetyLevel(const char *z){
+static u8 getSafetyLevel(const char *z){
/* 123456789 123456789 */
static const char zText[] = "onoffalseyestruefull";
static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16};
static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4};
static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2};
int i, n;
if( isdigit(*z) ){
- return atoi(z);
- }
- n = strlen(z);
+ return (u8)atoi(z);
+ }
+ n = sqlite3Strlen30(z);
for(i=0; i<ArraySize(iLength); i++){
if( iLength[i]==n && sqlite3StrNICmp(&zText[iOffset[i]],z,n)==0 ){
return iValue[i];
}
@@ -67601,9 +69490,9 @@
/*
** Interpret the given string as a boolean value.
*/
-static int getBoolean(const char *z){
+static u8 getBoolean(const char *z){
return getSafetyLevel(z)&1;
}
/*
@@ -67629,9 +69518,9 @@
if( 0==sqlite3StrICmp(z, "none") ) return BTREE_AUTOVACUUM_NONE;
if( 0==sqlite3StrICmp(z, "full") ) return BTREE_AUTOVACUUM_FULL;
if( 0==sqlite3StrICmp(z, "incremental") ) return BTREE_AUTOVACUUM_INCR;
i = atoi(z);
- return ((i>=0&&i<=2)?i:0);
+ return (u8)((i>=0&&i<=2)?i:0);
}
#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
@@ -67686,9 +69575,9 @@
if( db->temp_store==ts ) return SQLITE_OK;
if( invalidateTempStorage( pParse ) != SQLITE_OK ){
return SQLITE_ERROR;
}
- db->temp_store = ts;
+ db->temp_store = (u8)ts;
return SQLITE_OK;
}
#endif /* SQLITE_PAGER_PRAGMAS */
@@ -67943,11 +69832,9 @@
**
** Return the number of pages in the specified database.
*/
if( sqlite3StrICmp(zLeft,"page_count")==0 ){
- Vdbe *v;
- int iReg;
- v = sqlite3GetVdbe(pParse);
+ int iReg;
if( !v || sqlite3ReadSchema(pParse) ) goto pragma_out;
sqlite3CodeVerifySchema(pParse, iDb);
iReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
@@ -67986,9 +69873,9 @@
for(ii=2; ii<db->nDb; ii++){
pPager = sqlite3BtreePager(db->aDb[ii].pBt);
sqlite3PagerLockingMode(pPager, eMode);
}
- db->dfltLockMode = eMode;
+ db->dfltLockMode = (u8)eMode;
}
pPager = sqlite3BtreePager(pDb->pBt);
eMode = sqlite3PagerLockingMode(pPager, eMode);
}
@@ -68015,9 +69902,9 @@
if( zRight==0 ){
eMode = PAGER_JOURNALMODE_QUERY;
}else{
- int n = strlen(zRight);
+ int n = sqlite3Strlen30(zRight);
eMode = sizeof(azModeName)/sizeof(azModeName[0]) - 1;
while( eMode>=0 && sqlite3StrNICmp(zRight, azModeName[eMode], n)!=0 ){
eMode--;
}
@@ -68046,9 +69933,9 @@
pPager = sqlite3BtreePager(db->aDb[ii].pBt);
sqlite3PagerJournalMode(pPager, eMode);
}
}
- db->dfltJournalMode = eMode;
+ db->dfltJournalMode = (u8)eMode;
}
pPager = sqlite3BtreePager(pDb->pBt);
eMode = sqlite3PagerJournalMode(pPager, eMode);
}
@@ -68103,9 +69990,9 @@
pBt ? sqlite3BtreeGetAutoVacuum(pBt) : SQLITE_DEFAULT_AUTOVACUUM;
returnSingleInt(pParse, "auto_vacuum", auto_vacuum);
}else{
int eAuto = getAutoVacuum(zRight);
- db->nextAutovac = eAuto;
+ db->nextAutovac = (u8)eAuto;
if( eAuto>=0 ){
/* Call SetAutoVacuum() to set initialize the internal auto and
** incr-vacuum flags. This is required in case this connection
** creates the database file. It is important that it is created
@@ -68254,8 +70141,50 @@
}
#endif /* SQLITE_OMIT_WSD */
}
}else
+
+ /*
+ ** PRAGMA [database.]lock_proxy_file
+ ** PRAGMA [database.]lock_proxy_file = ":auto:"|"lock_file_path"
+ **
+ ** Return or set the value of the lock_proxy_file flag. Changing
+ ** the value sets a specific file to be used for database access locks.
+ **
+ */
+ if( sqlite3StrICmp(zLeft, "lock_proxy_file")==0 ){
+ if( !zRight ){
+ Pager *pPager = sqlite3BtreePager(pDb->pBt);
+ char *proxy_file_path = NULL;
+ sqlite3_file *pFile = sqlite3PagerFile(pPager);
+ sqlite3OsFileControl(pFile, SQLITE_GET_LOCKPROXYFILE,
+ &proxy_file_path);
+
+ if( proxy_file_path ){
+ sqlite3VdbeSetNumCols(v, 1);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME,
+ "lock_proxy_file", SQLITE_STATIC);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, proxy_file_path, 0);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }
+ }else{
+ Pager *pPager = sqlite3BtreePager(pDb->pBt);
+ sqlite3_file *pFile = sqlite3PagerFile(pPager);
+ int res;
+ if( zRight[0] ){
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
+ zRight);
+ } else {
+ res=sqlite3OsFileControl(pFile, SQLITE_SET_LOCKPROXYFILE,
+ NULL);
+ }
+ if( res!=SQLITE_OK ){
+ sqlite3ErrorMsg(pParse, "failed to set lock proxy file");
+ goto pragma_out;
+ }
+ }
+ }else
+
/*
** PRAGMA [database.]synchronous
** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL
@@ -68572,9 +70501,9 @@
}
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp3(v, OP_IntegrityCk, 2, cnt, 1);
- sqlite3VdbeChangeP5(v, i);
+ sqlite3VdbeChangeP5(v, (u8)i);
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC);
@@ -68816,9 +70745,8 @@
static const char *const azLockName[] = {
"unlocked", "shared", "reserved", "pending", "exclusive"
};
int i;
- Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3VdbeSetNumCols(v, 2);
pParse->nMem = 2;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
@@ -68855,9 +70783,9 @@
#endif
#if SQLITE_HAS_CODEC
if( sqlite3StrICmp(zLeft, "key")==0 ){
- sqlite3_key(db, zRight, strlen(zRight));
+ sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
}else
#endif
#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD)
if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
@@ -68919,9 +70847,9 @@
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
-** $Id: prepare.c,v 1.101 2008/11/19 16:52:44 danielk1977 Exp $
+** $Id: prepare.c,v 1.103 2008/12/10 19:26:24 drh Exp $
*/
/*
** Fill the InitData structure with an error message that indicates
@@ -69199,9 +71127,9 @@
** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN
** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults
** file_format==4 Version 3.3.0. // DESC indices. Boolean constants
*/
- pDb->pSchema->file_format = meta[1];
+ pDb->pSchema->file_format = (u8)meta[1];
if( pDb->pSchema->file_format==0 ){
pDb->pSchema->file_format = 1;
}
if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
@@ -69451,9 +71379,8 @@
*/
for(i=0; i<db->nDb; i++) {
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
- int rc;
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb);
@@ -69528,9 +71455,9 @@
rc = SQLITE_MISUSE;
}
if( saveSqlFlag ){
- sqlite3VdbeSetSql(sParse.pVdbe, zSql, sParse.zTail - zSql);
+ sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail - zSql));
}
if( rc!=SQLITE_OK || db->mallocFailed ){
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
assert(!(*ppStmt));
@@ -69671,9 +71598,9 @@
** equivalent pointer into the UTF-16 string by counting the unicode
** characters between zSql8 and zTail8, and then returning a pointer
** the same number of characters into the UTF-16 string.
*/
- int chars_parsed = sqlite3Utf8CharLen(zSql8, zTail8-zSql8);
+ int chars_parsed = sqlite3Utf8CharLen(zSql8, (int)(zTail8-zSql8));
*pzTail = (u8 *)zSql + sqlite3Utf16ByteLen(zSql, chars_parsed);
}
sqlite3DbFree(db, zSql8);
rc = sqlite3ApiExit(db, rc);
@@ -69731,9 +71658,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.486 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: select.c,v 1.494 2008/12/10 22:15:00 drh Exp $
*/
/*
@@ -69755,9 +71682,9 @@
/*
** Initialize a SelectDest structure.
*/
SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
- pDest->eDest = eDest;
+ pDest->eDest = (u8)eDest;
pDest->iParm = iParm;
pDest->affinity = 0;
pDest->iMem = 0;
pDest->nMem = 0;
@@ -69909,9 +71836,9 @@
** Set the value of a token to a '\000'-terminated string.
*/
static void setToken(Token *p, const char *z){
p->z = (u8*)z;
- p->n = z ? strlen(z) : 0;
+ p->n = z ? sqlite3Strlen30(z) : 0;
p->dyn = 0;
}
/*
@@ -69938,15 +71865,15 @@
if( *z2 ){
/* String contains " characters - copy and quote the string. */
p->z = (u8 *)sqlite3MPrintf(pParse->db, "\"%w\"", z);
if( p->z ){
- p->n = strlen((char *)p->z);
+ p->n = sqlite3Strlen30((char *)p->z);
p->dyn = 1;
}
}else{
/* String contains no " characters - copy the pointer. */
p->z = (u8*)z;
- p->n = (z2 - z);
+ p->n = (int)(z2 - z);
p->dyn = 0;
}
}
@@ -70474,10 +72401,11 @@
nExpr = pList->nExpr;
pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );
if( pInfo ){
pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];
- pInfo->nField = nExpr;
+ pInfo->nField = (u16)nExpr;
pInfo->enc = ENC(db);
+ pInfo->db = db;
for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){
CollSeq *pColl;
pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
if( !pColl ){
@@ -70503,10 +72431,10 @@
Vdbe *v, /* Generate code into this VDBE */
int nColumn, /* Number of columns of data */
SelectDest *pDest /* Write the sorted results here */
){
- int brk = sqlite3VdbeMakeLabel(v);
- int cont = sqlite3VdbeMakeLabel(v);
+ int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */
+ int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
int addr;
int iTab;
int pseudoTab = 0;
ExprList *pOrderBy = p->pOrderBy;
@@ -70522,10 +72450,10 @@
pseudoTab = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn);
sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Output);
}
- addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
- codeOffset(v, p, cont);
+ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak);
+ codeOffset(v, p, addrContinue);
regRow = sqlite3GetTempReg(pParse);
regRowid = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);
switch( eDest ){
@@ -70581,15 +72509,14 @@
assert( p->iLimit==0 );
/* The bottom of the loop
*/
- sqlite3VdbeResolveLabel(v, cont);
+ sqlite3VdbeResolveLabel(v, addrContinue);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr);
- sqlite3VdbeResolveLabel(v, brk);
+ sqlite3VdbeResolveLabel(v, addrBreak);
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
}
-
}
/*
** Return a pointer to a string containing the 'declaration type' of the
@@ -70868,15 +72795,16 @@
ExprList *pEList, /* Expr list from which to derive column names */
int *pnCol, /* Write the number of columns here */
Column **paCol /* Write the new column list here */
){
- sqlite3 *db = pParse->db;
- int i, j, cnt;
- Column *aCol, *pCol;
- int nCol;
- Expr *p;
- char *zName;
- int nName;
+ sqlite3 *db = pParse->db; /* Database connection */
+ int i, j; /* Loop counters */
+ int cnt; /* Index added to make the name unique */
+ Column *aCol, *pCol; /* For looping over result columns */
+ int nCol; /* Number of columns in the result set */
+ Expr *p; /* Expression for a single result column */
+ char *zName; /* Column name */
+ int nName; /* Size of name in zName[] */
*pnCol = nCol = pEList->nExpr;
aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
if( aCol==0 ) return SQLITE_NOMEM;
@@ -70888,20 +72816,21 @@
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{
- Expr *pCol = p;
- Table *pTab;
- while( pCol->op==TK_DOT ) pCol = pCol->pRight;
- if( pCol->op==TK_COLUMN && (pTab = pCol->pTab)!=0 ){
+ Expr *pColExpr = p; /* The expression that is the result column name */
+ Table *pTab; /* Table associated with this expression */
+ while( pColExpr->op==TK_DOT ) pColExpr = pColExpr->pRight;
+ if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->pTab)!=0 ){
/* For columns use the column name name */
- int iCol = pCol->iColumn;
+ int iCol = pColExpr->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);
+ Token *pToken = (pColExpr->span.z?&pColExpr->span:&pColExpr->token);
+ zName = sqlite3MPrintf(db, "%T", pToken);
}
}
if( db->mallocFailed ){
sqlite3DbFree(db, zName);
@@ -70911,9 +72840,9 @@
/* Make sure the column name is unique. If the name is not unique,
** append a integer to the name so that it becomes unique.
*/
- nName = strlen(zName);
+ nName = sqlite3Strlen30(zName);
for(j=cnt=0; j<i; j++){
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
char *zNewName;
zName[nName] = 0;
@@ -70926,9 +72855,8 @@
}
pCol->zName = zName;
}
if( db->mallocFailed ){
- int j;
for(j=0; j<i; j++){
sqlite3DbFree(db, aCol[j].zName);
}
sqlite3DbFree(db, aCol);
@@ -71255,9 +73183,9 @@
}
case TK_EXCEPT:
case TK_UNION: {
int unionTab; /* Cursor number of the temporary table holding result */
- int op = 0; /* One of the SRT_ operations to apply to self */
+ u8 op = 0; /* One of the SRT_ operations to apply to self */
int priorOp; /* The SRT_ operation to apply to prior selects */
Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */
int addr;
SelectDest uniondest;
@@ -71450,9 +73378,9 @@
goto multi_select_end;
}
pKeyInfo->enc = ENC(db);
- pKeyInfo->nField = nCol;
+ pKeyInfo->nField = (u16)nCol;
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
*apColl = multiSelectCollSeq(pParse, p, i);
if( 0==*apColl ){
@@ -71751,9 +73679,9 @@
int addrSelectB; /* Address of the select-B coroutine */
int regOutA; /* Address register for the output-A subroutine */
int regOutB; /* Address register for the output-B subroutine */
int addrOutA; /* Address of the output-A subroutine */
- int addrOutB; /* Address of the output-B subroutine */
+ int addrOutB = 0; /* Address of the output-B subroutine */
int addrEofA; /* Address of the select-A-exhausted subroutine */
int addrEofB; /* Address of the select-B-exhausted subroutine */
int addrAltB; /* Address of the A<B subroutine */
int addrAeqB; /* Address of the A==B subroutine */
@@ -71808,9 +73736,9 @@
if( pNew==0 ) return SQLITE_NOMEM;
pNew->flags |= EP_IntValue;
pNew->iTable = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0);
- pOrderBy->a[nOrderBy++].iCol = i;
+ pOrderBy->a[nOrderBy++].iCol = (u16)i;
}
}
}
@@ -71831,9 +73759,9 @@
pKeyMerge =
sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
if( pKeyMerge ){
pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy];
- pKeyMerge->nField = nOrderBy;
+ pKeyMerge->nField = (u16)nOrderBy;
pKeyMerge->enc = ENC(db);
for(i=0; i<nOrderBy; i++){
CollSeq *pColl;
Expr *pTerm = pOrderBy->a[i].pExpr;
@@ -71871,9 +73799,9 @@
pKeyDup = sqlite3DbMallocZero(db,
sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
if( pKeyDup ){
pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr];
- pKeyDup->nField = nExpr;
+ pKeyDup->nField = (u16)nExpr;
pKeyDup->enc = ENC(db);
for(i=0; i<nExpr; i++){
pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
pKeyDup->aSortOrder[i] = 0;
@@ -72503,9 +74431,9 @@
** elements we are now copying in.
*/
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
- int jointype = 0;
+ u8 jointype = 0;
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
@@ -72639,9 +74567,9 @@
**
** 2. There is a single expression in the result set, and it is
** either min(x) or max(x), where x is a column reference.
*/
-static int minMaxQuery(Select *p){
+static u8 minMaxQuery(Select *p){
Expr *pExpr;
ExprList *pEList = p->pEList;
if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
@@ -72869,9 +74797,9 @@
assert(IsVirtual(pTab));
continue;
}
- if( i>0 ){
+ if( i>0 && zTName==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
@@ -73147,9 +75075,9 @@
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
(void*)pF->pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, nArg);
+ sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
@@ -73256,19 +75184,15 @@
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
p->selFlags &= ~SF_Distinct;
}
sqlite3SelectPrep(pParse, p, 0);
- if( pParse->nErr ){
+ pTabList = p->pSrc;
+ pEList = p->pEList;
+ if( pParse->nErr || db->mallocFailed ){
goto select_end;
}
p->pOrderBy = pOrderBy;
-
-
- /* Make local copies of the parameters for this query.
- */
- pTabList = p->pSrc;
- isAgg = (p->selFlags & SF_Aggregate)!=0;
- pEList = p->pEList;
+ isAgg = (p->selFlags & SF_Aggregate)!=0;
if( pEList==0 ) goto select_end;
/*
** Do not even attempt to generate any code if we have already seen
@@ -73463,15 +75387,15 @@
/* Remove any and all aliases between the result set and the
** GROUP BY clause.
*/
if( pGroupBy ){
- int i; /* Loop counter */
+ int k; /* Loop counter */
struct ExprList_item *pItem; /* For looping over expression in a list */
- for(i=p->pEList->nExpr, pItem=p->pEList->a; i>0; i--, pItem++){
+ for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
pItem->iAlias = 0;
}
- for(i=pGroupBy->nExpr, pItem=pGroupBy->a; i>0; i--, pItem++){
+ for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
pItem->iAlias = 0;
}
}
@@ -73735,9 +75659,9 @@
flag = minMaxQuery(p);
if( flag ){
pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList);
if( pMinMax && !db->mallocFailed ){
- pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN;
+ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
pMinMax->a[0].pExpr->op = TK_COLUMN;
}
}
@@ -73918,9 +75842,9 @@
**
** These routines are in a separate files so that they will not be linked
** if they are not used.
**
-** $Id: table.c,v 1.36 2008/07/08 22:28:49 shane Exp $
+** $Id: table.c,v 1.38 2008/12/10 19:26:24 drh Exp $
*/
#ifndef SQLITE_OMIT_GET_TABLE
@@ -73991,9 +75915,9 @@
for(i=0; i<nCol; i++){
if( argv[i]==0 ){
z = 0;
}else{
- int n = strlen(argv[i])+1;
+ int n = sqlite3Strlen30(argv[i])+1;
z = sqlite3_malloc( n );
if( z==0 ) goto malloc_failed;
memcpy(z, argv[i], n);
}
@@ -74113,9 +76037,9 @@
**
*************************************************************************
**
**
-** $Id: trigger.c,v 1.130 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: trigger.c,v 1.132 2008/12/10 19:26:24 drh Exp $
*/
#ifndef SQLITE_OMIT_TRIGGER
/*
@@ -74166,8 +76090,10 @@
int iTabDb;
assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */
assert( pName2!=0 );
+ assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE );
+ assert( op>0 && op<0xff );
if( isTemp ){
/* If TEMP was specified, then the trigger name may not be qualified. */
if( pName2->n>0 ){
sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
@@ -74218,9 +76144,10 @@
zName = sqlite3NameFromToken(db, pName);
if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto trigger_cleanup;
}
- if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){
+ if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),
+ zName, sqlite3Strlen30(zName)) ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
}
goto trigger_cleanup;
@@ -74279,9 +76206,9 @@
zName = 0;
pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
pTrigger->pSchema = db->aDb[iDb].pSchema;
pTrigger->pTabSchema = pTab->pSchema;
- pTrigger->op = op;
+ pTrigger->op = (u8)op;
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
pTrigger->pWhen = sqlite3ExprDup(db, pWhen);
pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
sqlite3TokenCopy(db, &pTrigger->nameToken,pName);
@@ -74355,15 +76282,15 @@
int n;
Table *pTab;
Trigger *pDel;
pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash,
- pTrig->name, strlen(pTrig->name), pTrig);
+ pTrig->name, sqlite3Strlen30(pTrig->name), pTrig);
if( pDel ){
assert( pDel==pTrig );
db->mallocFailed = 1;
goto triggerfinish_cleanup;
}
- n = strlen(pTrig->table) + 1;
+ n = sqlite3Strlen30(pTrig->table) + 1;
pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n);
assert( pTab!=0 );
pTrig->pNext = pTab->pTrigger;
pTab->pTrigger = pTrig;
@@ -74564,9 +76491,9 @@
assert( pName->nSrc==1 );
zDb = pName->a[0].zDatabase;
zName = pName->a[0].zName;
- nName = strlen(zName);
+ nName = sqlite3Strlen30(zName);
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
@@ -74588,9 +76515,9 @@
** Return a pointer to the Table structure for the table that a trigger
** is set on.
*/
static Table *tableOfTrigger(Trigger *pTrigger){
- int n = strlen(pTrigger->table) + 1;
+ int n = sqlite3Strlen30(pTrigger->table) + 1;
return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
}
@@ -74653,9 +76580,9 @@
** Remove a trigger from the hash tables of the sqlite* pointer.
*/
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
Trigger *pTrigger;
- int nName = strlen(zName);
+ int nName = sqlite3Strlen30(zName);
pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash),
zName, nName, 0);
if( pTrigger ){
Table *pTable = tableOfTrigger(pTrigger);
@@ -74744,9 +76671,9 @@
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
if( iDb==0 || iDb>=2 ){
assert( iDb<pParse->db->nDb );
sDb.z = (u8*)pParse->db->aDb[iDb].zName;
- sDb.n = strlen((char*)sDb.z);
+ sDb.n = sqlite3Strlen30((char*)sDb.z);
pSrc = sqlite3SrcListAppend(pParse->db, 0, &sDb, &pStep->target);
} else {
pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
}
@@ -74968,9 +76895,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.187 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: update.c,v 1.190 2008/12/10 22:15:00 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
@@ -75064,12 +76991,12 @@
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* Trying to update a view */
int triggers_exist = 0; /* True if any row triggers exist */
#endif
- int iBeginAfterTrigger; /* Address of after trigger program */
- int iEndAfterTrigger; /* Exit of after trigger program */
- int iBeginBeforeTrigger; /* Address of before trigger program */
- int iEndBeforeTrigger; /* Exit of before trigger program */
+ int iBeginAfterTrigger = 0; /* Address of after trigger program */
+ int iEndAfterTrigger = 0; /* Exit of after trigger program */
+ int iBeginBeforeTrigger = 0; /* Address of before trigger program */
+ int iEndBeforeTrigger = 0; /* Exit of before trigger program */
u32 old_col_mask = 0; /* Mask of OLD.* columns in use */
u32 new_col_mask = 0; /* Mask of NEW.* columns in use */
int newIdx = -1; /* index of trigger "new" temp table */
@@ -75079,8 +77006,9 @@
int regRowCount = 0; /* A count of rows changed */
int regOldRowid; /* The old rowid */
int regNewRowid; /* The new rowid */
int regData; /* New data for the row */
+ int regRowSet = 0; /* Rowset of rows to be updated */
sContext.pParse = 0;
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
@@ -75307,9 +77235,12 @@
/* Remember the rowid of every item to be updated.
*/
sqlite3VdbeAddOp2(v, IsVirtual(pTab)?OP_VRowid:OP_Rowid, iCur, regOldRowid);
- if( !okOnePass ) sqlite3VdbeAddOp2(v, OP_FifoWrite, regOldRowid, 0);
+ if( !okOnePass ){
+ regRowSet = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
+ }
/* End the database scan loop.
*/
sqlite3WhereEnd(pWInfo);
@@ -75360,9 +77291,9 @@
int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
addr = sqlite3VdbeAddOp0(v, OP_Goto);
sqlite3VdbeJumpHere(v, a1);
}else{
- addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0);
+ addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid);
}
if( triggers_exist ){
int regRowid;
@@ -75951,9 +77882,9 @@
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
-** $Id: vtab.c,v 1.78 2008/11/13 19:12:36 danielk1977 Exp $
+** $Id: vtab.c,v 1.81 2008/12/10 19:26:24 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
static int createModule(
@@ -75966,9 +77897,9 @@
int rc, nName;
Module *pMod;
sqlite3_mutex_enter(db->mutex);
- nName = strlen(zName);
+ nName = sqlite3Strlen30(zName);
pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
if( pMod ){
Module *pDel;
char *zCopy = (char *)(&pMod[1]);
@@ -76132,9 +78063,9 @@
pTable->nModuleArg = 0;
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
- pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z;
+ pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z);
#ifndef SQLITE_OMIT_AUTHORIZATION
/* Creating a virtual table invokes the authorization callback twice.
** The first invocation, to obtain permission to INSERT a row into the
@@ -76180,9 +78111,10 @@
if( pTab==0 ) return;
db = pParse->db;
if( pTab->nModuleArg<1 ) return;
zModule = pTab->azModuleArg[0];
- pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule));
+ pMod = (Module*)sqlite3HashFind(&db->aModule, zModule,
+ sqlite3Strlen30(zModule));
pTab->pMod = pMod;
/* If the CREATE VIRTUAL TABLE statement is being entered for the
** first time (in other words if the virtual table is actually being
@@ -76197,9 +78129,9 @@
Vdbe *v;
/* Compute the complete text of the CREATE VIRTUAL TABLE statement */
if( pEnd ){
- pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n;
+ pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n;
}
zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
/* A slot for the record has already been allocated in the
@@ -76228,9 +78160,9 @@
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName);
sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 1, 0, zWhere, P4_DYNAMIC);
sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
- pTab->zName, strlen(pTab->zName) + 1);
+ pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
}
/* If we are rereading the sqlite_master table create the in-memory
** record of the table. If the module has already been registered,
@@ -76239,9 +78171,9 @@
else {
Table *pOld;
Schema *pSchema = pTab->pSchema;
const char *zName = pTab->zName;
- int nName = strlen(zName) + 1;
+ int nName = sqlite3Strlen30(zName) + 1;
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
if( pOld ){
db->mallocFailed = 1;
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
@@ -76272,9 +78204,9 @@
pArg->z = p->z;
pArg->n = p->n;
}else{
assert(pArg->z < p->z);
- pArg->n = (p->z + p->n - pArg->z);
+ pArg->n = (int)(&p->z[p->n] - pArg->z);
}
}
/*
@@ -76344,9 +78276,9 @@
char *zType = pTab->aCol[iCol].zType;
int nType;
int i = 0;
if( !zType ) continue;
- nType = strlen(zType);
+ nType = sqlite3Strlen30(zType);
if( sqlite3StrNICmp("hidden", zType, 6) || (zType[6] && zType[6]!=' ') ){
for(i=0; i<nType; i++){
if( (0==sqlite3StrNICmp(" hidden", &zType[i], 7))
&& (zType[i+7]=='\0' || zType[i+7]==' ')
@@ -76701,10 +78633,10 @@
){
Table *pTab;
sqlite3_vtab *pVtab;
sqlite3_module *pMod;
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
- void *pArg;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value**) = 0;
+ void *pArg = 0;
FuncDef *pNew;
int rc = 0;
char *zLowerName;
unsigned char *z;
@@ -76743,15 +78675,16 @@
}
/* Create a new ephemeral function definition for the overloaded
** function */
- pNew = sqlite3DbMallocZero(db, sizeof(*pNew) + strlen(pDef->zName) );
+ pNew = sqlite3DbMallocZero(db, sizeof(*pNew)
+ + sqlite3Strlen30(pDef->zName) );
if( pNew==0 ){
return pDef;
}
*pNew = *pDef;
pNew->zName = (char *)&pNew[1];
- memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1);
+ memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1);
pNew->xFunc = xFunc;
pNew->pUserData = pArg;
pNew->flags |= SQLITE_FUNC_EPHEM;
return pNew;
@@ -76799,9 +78732,9 @@
** rows. Indices are selected and used to speed the search when doing
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.330 2008/11/17 19:18:55 danielk1977 Exp $
+** $Id: where.c,v 1.337 2008/12/12 17:56:16 drh Exp $
*/
/*
** Trace output macros
@@ -76822,9 +78755,12 @@
/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause. Each WHERE
-** clause subexpression is separated from the others by an AND operator.
+** clause subexpression is separated from the others by AND operators.
+** (Note: the same data structure is also reused to hold a group of terms
+** separated by OR operators. But at the top-level, everything is AND
+** separated.)
**
** All WhereTerms are collected into a single WhereClause structure.
** The following identity holds:
**
@@ -76851,25 +78787,29 @@
** translates these sparse cursor numbers into consecutive integers
** beginning with 0 in order to make the best possible use of the available
** bits in the Bitmask. So, in the example above, the cursor numbers
** would be mapped into integers 0 through 7.
+**
+** The number of terms in a join is limited by the number of bits
+** in prereqRight and prereqAll. The default is 64 bits, hence SQLite
+** is only able to process joins with 64 or fewer tables.
*/
typedef struct WhereTerm WhereTerm;
struct WhereTerm {
- Expr *pExpr; /* Pointer to the subexpression */
- i16 iParent; /* Disable pWC->a[iParent] when this term disabled */
- i16 leftCursor; /* Cursor number of X in "X <op> <expr>" */
- i16 leftColumn; /* Column number of X in "X <op> <expr>" */
+ Expr *pExpr; /* Pointer to the subexpression that is this term */
+ int iParent; /* Disable pWC->a[iParent] when this term disabled */
+ int leftCursor; /* Cursor number of X in "X <op> <expr>" */
+ int leftColumn; /* Column number of X in "X <op> <expr>" */
u16 eOperator; /* A WO_xx value describing <op> */
- u8 flags; /* Bit flags. See below */
+ u8 wtFlags; /* TERM_xxx bit flags. See below */
u8 nChild; /* Number of children that must disable us */
WhereClause *pWC; /* The clause this term is part of */
- Bitmask prereqRight; /* Bitmask of tables used by pRight */
- Bitmask prereqAll; /* Bitmask of tables referenced by p */
-};
-
-/*
-** Allowed values of WhereTerm.flags
+ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
+ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
+};
+
+/*
+** Allowed values of WhereTerm.wtFlags
*/
#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */
#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */
#define TERM_CODED 0x04 /* This term is already coded */
@@ -76885,9 +78825,9 @@
ExprMaskSet *pMaskSet; /* Mapping of table indices to bitmasks */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
- WhereTerm aStatic[10]; /* Initial static space for a[] */
+ WhereTerm aStatic[4]; /* Initial static space for a[] */
};
/*
** An instance of the following structure keeps track of a mapping
@@ -76925,40 +78865,45 @@
** Bitmasks for the operators that indices are able to exploit. An
** OR-ed combination of these values can be used when searching for
** terms in the where clause.
*/
-#define WO_IN 1
-#define WO_EQ 2
+#define WO_IN 0x001
+#define WO_EQ 0x002
#define WO_LT (WO_EQ<<(TK_LT-TK_EQ))
#define WO_LE (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE (WO_EQ<<(TK_GE-TK_EQ))
-#define WO_MATCH 64
-#define WO_ISNULL 128
-
-/*
-** Value for flags returned by bestIndex().
-**
-** The least significant byte is reserved as a mask for WO_ values above.
-** The WhereLevel.flags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
-** But if the table is the right table of a left join, WhereLevel.flags
-** is set to WO_IN|WO_EQ. The WhereLevel.flags field can then be used as
+#define WO_MATCH 0x040
+#define WO_ISNULL 0x080
+#define WO_OR 0x100
+
+#define WO_ALL 0xfff /* Mask of all possible WO_* values */
+
+/*
+** Value for wsFlags returned by bestIndex(). These flags determine which
+** search strategies are appropriate.
+**
+** The least significant 12 bits is reserved as a mask for WO_ values above.
+** The WhereLevel.wtFlags field is usually set to WO_IN|WO_EQ|WO_ISNULL.
+** But if the table is the right table of a left join, WhereLevel.wtFlags
+** is set to WO_IN|WO_EQ. The WhereLevel.wtFlags field can then be used as
** the "op" parameter to findTerm when we are resolving equality constraints.
** ISNULL constraints will then not be used on the right table of a left
** join. Tickets #2177 and #2189.
*/
-#define WHERE_ROWID_EQ 0x000100 /* rowid=EXPR or rowid IN (...) */
-#define WHERE_ROWID_RANGE 0x000200 /* rowid<EXPR and/or rowid>EXPR */
-#define WHERE_COLUMN_EQ 0x001000 /* x=EXPR or x IN (...) */
-#define WHERE_COLUMN_RANGE 0x002000 /* x<EXPR and/or x>EXPR */
-#define WHERE_COLUMN_IN 0x004000 /* x IN (...) */
-#define WHERE_TOP_LIMIT 0x010000 /* x<EXPR or x<=EXPR constraint */
-#define WHERE_BTM_LIMIT 0x020000 /* x>EXPR or x>=EXPR constraint */
-#define WHERE_IDX_ONLY 0x080000 /* Use index only - omit table */
-#define WHERE_ORDERBY 0x100000 /* Output will appear in correct order */
-#define WHERE_REVERSE 0x200000 /* Scan in reverse order */
-#define WHERE_UNIQUE 0x400000 /* Selects no more than one row */
-#define WHERE_VIRTUALTABLE 0x800000 /* Use virtual-table processing */
+#define WHERE_ROWID_EQ 0x00001000 /* rowid=EXPR or rowid IN (...) */
+#define WHERE_ROWID_RANGE 0x00002000 /* rowid<EXPR and/or rowid>EXPR */
+#define WHERE_COLUMN_EQ 0x00010000 /* x=EXPR or x IN (...) */
+#define WHERE_COLUMN_RANGE 0x00020000 /* x<EXPR and/or x>EXPR */
+#define WHERE_COLUMN_IN 0x00040000 /* x IN (...) */
+#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
+#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
+#define WHERE_IDX_ONLY 0x00800000 /* Use index only - omit table */
+#define WHERE_ORDERBY 0x01000000 /* Output will appear in correct order */
+#define WHERE_REVERSE 0x02000000 /* Scan in reverse order */
+#define WHERE_UNIQUE 0x04000000 /* Selects no more than one row */
+#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
+#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
/*
** Initialize a preallocated WhereClause structure.
*/
@@ -76982,9 +78927,9 @@
int i;
WhereTerm *a;
sqlite3 *db = pWC->pParse->db;
for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
- if( a->flags & TERM_DYNAMIC ){
+ if( a->wtFlags & TERM_DYNAMIC ){
sqlite3ExprDelete(db, a->pExpr);
}
}
if( pWC->a!=pWC->aStatic ){
@@ -76992,28 +78937,35 @@
}
}
/*
-** Add a new entries to the WhereClause structure. Increase the allocated
-** space as necessary.
-**
-** If the flags argument includes TERM_DYNAMIC, then responsibility
-** for freeing the expression p is assumed by the WhereClause object.
+** Add a single new WhereTerm entry to the WhereClause object pWC.
+** The new WhereTerm object is constructed from Expr p and with wtFlags.
+** The index in pWC->a[] of the new WhereTerm is returned on success.
+** 0 is returned if the new WhereTerm could not be added due to a memory
+** allocation error. The memory allocation failure will be recorded in
+** the db->mallocFailed flag so that higher-level functions can detect it.
+**
+** This routine will increase the size of the pWC->a[] array as necessary.
+**
+** If the wtFlags argument includes TERM_DYNAMIC, then responsibility
+** for freeing the expression p is assumed by the WhereClause object pWC.
+** This is true even if this routine fails to allocate a new WhereTerm.
**
** WARNING: This routine might reallocate the space used to store
** WhereTerms. All pointers to WhereTerms should be invalidated after
** calling this routine. Such pointers may be reinitialized by referencing
** the pWC->a[] array.
*/
-static int whereClauseInsert(WhereClause *pWC, Expr *p, int flags){
+static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
WhereTerm *pTerm;
int idx;
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
sqlite3 *db = pWC->pParse->db;
pWC->a = sqlite3DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ){
- if( flags & TERM_DYNAMIC ){
+ if( wtFlags & TERM_DYNAMIC ){
sqlite3ExprDelete(db, p);
}
pWC->a = pOld;
return 0;
@@ -77021,14 +78973,13 @@
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
if( pOld!=pWC->aStatic ){
sqlite3DbFree(db, pOld);
}
- pWC->nSlot *= 2;
- }
- pTerm = &pWC->a[idx = pWC->nTerm];
- pWC->nTerm++;
+ pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
+ }
+ pTerm = &pWC->a[idx = pWC->nTerm++];
pTerm->pExpr = p;
- pTerm->flags = flags;
+ pTerm->wtFlags = wtFlags;
pTerm->pWC = pWC;
pTerm->iParent = -1;
return idx;
}
@@ -77046,9 +78997,9 @@
** The original WHERE clause in pExpr is unaltered. All this routine
** does is make slot[] entries point to substructure within pExpr.
**
** In the previous sentence and in the diagram, "slot[]" refers to
-** the WhereClause.a[] array. This array grows as needed to contain
+** the WhereClause.a[] array. The slot[] array grows as needed to contain
** all terms of the WHERE clause.
*/
static void whereSplit(WhereClause *pWC, Expr *pExpr, int op){
if( pExpr==0 ) return;
@@ -77157,9 +79108,9 @@
return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL;
}
/*
-** Swap two objects of type T.
+** Swap two objects of type TYPE.
*/
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
/*
@@ -77196,19 +79147,23 @@
/*
** Translate from TK_xx operator to WO_xx bitmask.
*/
-static int operatorMask(int op){
- int c;
+static u16 operatorMask(int op){
+ u16 c;
assert( allowedOp(op) );
if( op==TK_IN ){
c = WO_IN;
}else if( op==TK_ISNULL ){
c = WO_ISNULL;
- }else{
- c = WO_EQ<<(op-TK_EQ);
+ }else if( op==TK_OR ){
+ c = WO_OR;
+ }else{
+ assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
+ c = (u16)(WO_EQ<<(op-TK_EQ));
}
assert( op!=TK_ISNULL || c==WO_ISNULL );
+ assert( op!=TK_OR || c==WO_OR );
assert( op!=TK_IN || c==WO_IN );
assert( op!=TK_EQ || c==WO_EQ );
assert( op!=TK_LT || c==WO_LT );
assert( op!=TK_LE || c==WO_LE );
@@ -77227,14 +79182,15 @@
WhereClause *pWC, /* The WHERE clause to be searched */
int iCur, /* Cursor number of LHS */
int iColumn, /* Column number of LHS */
Bitmask notReady, /* RHS must not overlap with this mask */
- u16 op, /* Mask of WO_xx values describing operator */
+ u32 op, /* Mask of WO_xx values describing operator */
Index *pIdx /* Must be compatible with this index, if not NULL */
){
WhereTerm *pTerm;
int k;
assert( iCur>=0 );
+ op &= WO_ALL;
for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
if( pTerm->leftCursor==iCur
&& (pTerm->prereqRight & notReady)==0
&& pTerm->leftColumn==iColumn
@@ -77464,15 +79420,15 @@
** disqualified, then return true. If there are no duplicates, or
** the duplicate has also been disqualified, return false.
*/
static int orTermHasOkDuplicate(WhereClause *pOr, WhereTerm *pOrTerm){
- if( pOrTerm->flags & TERM_COPIED ){
+ if( pOrTerm->wtFlags & TERM_COPIED ){
/* This is the original term. The duplicate is to the left had
** has not yet been analyzed and thus has not yet been disqualified. */
return 1;
}
- if( (pOrTerm->flags & TERM_VIRTUAL)!=0
- && (pOr->a[pOrTerm->iParent].flags & TERM_OR_OK)!=0 ){
+ if( (pOrTerm->wtFlags & TERM_VIRTUAL)!=0
+ && (pOr->a[pOrTerm->iParent].wtFlags & TERM_OR_OK)!=0 ){
/* This is a duplicate term. The original qualified so this one
** does not have to. */
return 1;
}
@@ -77563,9 +79519,9 @@
pNew = &pWC->a[idxNew];
pNew->iParent = idxTerm;
pTerm = &pWC->a[idxTerm];
pTerm->nChild = 1;
- pTerm->flags |= TERM_COPIED;
+ pTerm->wtFlags |= TERM_COPIED;
}else{
pDup = pExpr;
pNew = pTerm;
}
@@ -77594,8 +79550,9 @@
int idxNew;
pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft),
sqlite3ExprDup(db, pList->a[i].pExpr), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
pWC->a[idxNew].iParent = idxTerm;
}
@@ -77622,9 +79579,9 @@
int iColumn, iCursor;
WhereClause sOr;
WhereTerm *pOrTerm;
- assert( (pTerm->flags & TERM_DYNAMIC)==0 );
+ assert( (pTerm->wtFlags & TERM_DYNAMIC)==0 );
whereClauseInit(&sOr, pWC->pParse, pMaskSet);
whereSplit(&sOr, pExpr, TK_OR);
exprAnalyzeAll(pSrc, &sOr);
assert( sOr.nTerm>=2 );
@@ -77639,22 +79596,22 @@
if( pOrTerm->eOperator!=WO_EQ ){
goto or_not_possible;
}
if( orTermIsOptCandidate(pOrTerm, iCursor, iColumn) ){
- pOrTerm->flags |= TERM_OR_OK;
+ pOrTerm->wtFlags |= TERM_OR_OK;
}else if( orTermHasOkDuplicate(&sOr, pOrTerm) ){
- pOrTerm->flags &= ~TERM_OR_OK;
+ pOrTerm->wtFlags &= ~TERM_OR_OK;
}else{
ok = 0;
}
}
- }while( !ok && (sOr.a[j++].flags & TERM_COPIED)!=0 && j<2 );
+ }while( !ok && (sOr.a[j++].wtFlags & TERM_COPIED)!=0 && j<2 );
if( ok ){
ExprList *pList = 0;
Expr *pNew, *pDup;
Expr *pLeft = 0;
for(i=sOr.nTerm-1, pOrTerm=sOr.a; i>=0; i--, pOrTerm++){
- if( (pOrTerm->flags & TERM_OR_OK)==0 ) continue;
+ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight);
pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0);
pLeft = pOrTerm->pExpr->pLeft;
}
@@ -77665,8 +79622,9 @@
int idxNew;
transferJoinMarkings(pNew, pExpr);
pNew->pList = pList;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
pTerm = &pWC->a[idxTerm];
pWC->a[idxNew].iParent = idxTerm;
pTerm->nChild = 1;
@@ -77717,11 +79675,13 @@
*pC = c + 1;
}
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew1==0 );
exprAnalyze(pSrc, pWC, idxNew1);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft), pStr2, 0);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew2==0 );
exprAnalyze(pSrc, pWC, idxNew2);
pTerm = &pWC->a[idxTerm];
if( isComplete ){
pWC->a[idxNew1].iParent = idxTerm;
@@ -77751,8 +79711,9 @@
if( (prereqExpr & prereqColumn)==0 ){
Expr *pNewExpr;
pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = prereqExpr;
pNewTerm->leftCursor = pLeft->iTable;
pNewTerm->leftColumn = pLeft->iColumn;
@@ -77759,9 +79720,9 @@
pNewTerm->eOperator = WO_MATCH;
pNewTerm->iParent = idxTerm;
pTerm = &pWC->a[idxTerm];
pTerm->nChild = 1;
- pTerm->flags |= TERM_COPIED;
+ pTerm->wtFlags |= TERM_COPIED;
pNewTerm->prereqAll = pTerm->prereqAll;
}
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -78055,9 +80016,8 @@
** and initialize it now
*/
pIdxInfo = *ppIdxInfo;
if( pIdxInfo==0 ){
- WhereTerm *pTerm;
int nTerm;
WHERETRACE(("Recomputing index info for %s...\n", pTab->zName));
/* Count the number of possible WHERE clause constraints referring
@@ -78119,9 +80079,9 @@
testcase( pTerm->eOperator==WO_ISNULL );
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
pIdxCons[j].iColumn = pTerm->leftColumn;
pIdxCons[j].iTermOffset = i;
- pIdxCons[j].op = pTerm->eOperator;
+ pIdxCons[j].op = (u8)pTerm->eOperator;
/* The direct assignment in the previous line is possible only because
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
** following asserts verify this fact. */
assert( WO_EQ==SQLITE_INDEX_CONSTRAINT_EQ );
@@ -78185,9 +80145,9 @@
pUsage = pIdxInfo->aConstraintUsage;
for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
j = pIdxCons->iTermOffset;
pTerm = &pWC->a[j];
- pIdxCons->usable = (pTerm->prereqRight & notReady)==0;
+ pIdxCons->usable = (pTerm->prereqRight & notReady)==0 ?1:0;
}
memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
if( pIdxInfo->needToFreeIdxStr ){
sqlite3_free(pIdxInfo->idxStr);
@@ -78268,25 +80228,25 @@
struct SrcList_item *pSrc, /* The FROM clause term to search */
Bitmask notReady, /* Mask of cursors that are not available */
ExprList *pOrderBy, /* The order by clause */
Index **ppIndex, /* Make *ppIndex point to the best index */
- int *pFlags, /* Put flags describing this choice in *pFlags */
+ int *pWsFlags, /* Put wsFlags describing scan strategy here */
int *pnEq /* Put the number of == or IN constraints here */
){
WhereTerm *pTerm;
Index *bestIdx = 0; /* Index that gives the lowest cost */
double lowestCost; /* The cost of using bestIdx */
- int bestFlags = 0; /* Flags associated with bestIdx */
+ int bestWsFlags = 0; /* Flags associated with bestIdx */
int bestNEq = 0; /* Best value for nEq */
int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
Index *pProbe; /* An index we are evaluating */
int rev; /* True to scan in reverse order */
- int flags; /* Flags associated with pProbe */
+ int wsFlags; /* Flags associated with pProbe */
int nEq; /* Number of == or IN constraints */
int eqTermMask; /* Mask of valid equality operators */
double cost; /* Cost of using pProbe */
- WHERETRACE(("bestIndex: tbl=%s notReady=%llx\n", pSrc->pTab->zName, notReady));
+ WHERETRACE(("bestIndex: tbl=%s notReady=%llx\n", pSrc->pTab->zName,notReady));
lowestCost = SQLITE_BIG_DBL;
pProbe = pSrc->pTab->pIndex;
if( pSrc->notIndexed ){
pProbe = 0;
@@ -78300,9 +80260,9 @@
*/
if( pProbe==0 &&
findTerm(pWC, iCur, -1, 0, WO_EQ|WO_IN|WO_LT|WO_LE|WO_GT|WO_GE,0)==0 &&
(pOrderBy==0 || !sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev)) ){
- *pFlags = 0;
+ *pWsFlags = 0;
*ppIndex = 0;
*pnEq = 0;
return 0.0;
}
@@ -78314,13 +80274,13 @@
pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
if( pTerm ){
Expr *pExpr;
*ppIndex = 0;
- bestFlags = WHERE_ROWID_EQ;
+ bestWsFlags = WHERE_ROWID_EQ;
if( pTerm->eOperator & WO_EQ ){
/* Rowid== is always the best pick. Look no further. Because only
** a single row is generated, output is always in sorted order */
- *pFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
+ *pWsFlags = WHERE_ROWID_EQ | WHERE_UNIQUE;
*pnEq = 1;
WHERETRACE(("... best is rowid\n"));
return 0.0;
}else if( (pExpr = pTerm->pExpr)->pList!=0 ){
@@ -78341,34 +80301,34 @@
** entries are in the table, use 1 million as a guess.
*/
cost = pProbe ? pProbe->aiRowEst[0] : 1000000;
WHERETRACE(("... table scan base cost: %.9g\n", cost));
- flags = WHERE_ROWID_RANGE;
+ wsFlags = WHERE_ROWID_RANGE;
/* Check for constraints on a range of rowids in a table scan.
*/
pTerm = findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE|WO_GT|WO_GE, 0);
if( pTerm ){
if( findTerm(pWC, iCur, -1, notReady, WO_LT|WO_LE, 0) ){
- flags |= WHERE_TOP_LIMIT;
+ wsFlags |= WHERE_TOP_LIMIT;
cost /= 3; /* Guess that rowid<EXPR eliminates two-thirds or rows */
}
if( findTerm(pWC, iCur, -1, notReady, WO_GT|WO_GE, 0) ){
- flags |= WHERE_BTM_LIMIT;
+ wsFlags |= WHERE_BTM_LIMIT;
cost /= 3; /* Guess that rowid>EXPR eliminates two-thirds of rows */
}
WHERETRACE(("... rowid range reduces cost to %.9g\n", cost));
}else{
- flags = 0;
+ wsFlags = 0;
}
/* If the table scan does not satisfy the ORDER BY clause, increase
** the cost by NlogN to cover the expense of sorting. */
if( pOrderBy ){
if( sortableByRowid(iCur, pOrderBy, pWC->pMaskSet, &rev) ){
- flags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
+ wsFlags |= WHERE_ORDERBY|WHERE_ROWID_RANGE;
if( rev ){
- flags |= WHERE_REVERSE;
+ wsFlags |= WHERE_REVERSE;
}
}else{
cost += cost*estLog(cost);
WHERETRACE(("... sorting increases cost to %.9g\n", cost));
@@ -78375,9 +80335,9 @@
}
}
if( cost<lowestCost ){
lowestCost = cost;
- bestFlags = flags;
+ bestWsFlags = wsFlags;
}
}
/* If the pSrc table is the right table of a LEFT JOIN then we may not
@@ -78404,17 +80364,17 @@
/* Count the number of columns in the index that are satisfied
** by x=EXPR constraints or x IN (...) constraints.
*/
- flags = 0;
+ wsFlags = 0;
for(i=0; i<pProbe->nColumn; i++){
int j = pProbe->aiColumn[i];
pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pProbe);
if( pTerm==0 ) break;
- flags |= WHERE_COLUMN_EQ;
+ wsFlags |= WHERE_COLUMN_EQ;
if( pTerm->eOperator & WO_IN ){
Expr *pExpr = pTerm->pExpr;
- flags |= WHERE_COLUMN_IN;
+ wsFlags |= WHERE_COLUMN_IN;
if( pExpr->pSelect!=0 ){
inMultiplier *= 25;
}else if( ALWAYS(pExpr->pList) ){
inMultiplier *= pExpr->pList->nExpr + 1;
@@ -78422,11 +80382,11 @@
}
}
cost = pProbe->aiRowEst[i] * inMultiplier * estLog(inMultiplier);
nEq = i;
- if( pProbe->onError!=OE_None && (flags & WHERE_COLUMN_IN)==0
+ if( pProbe->onError!=OE_None && (wsFlags & WHERE_COLUMN_IN)==0
&& nEq==pProbe->nColumn ){
- flags |= WHERE_UNIQUE;
+ wsFlags |= WHERE_UNIQUE;
}
WHERETRACE(("...... nEq=%d inMult=%.9g cost=%.9g\n",nEq,inMultiplier,cost));
/* Look for range constraints
@@ -78434,15 +80394,15 @@
if( nEq<pProbe->nColumn ){
int j = pProbe->aiColumn[nEq];
pTerm = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pProbe);
if( pTerm ){
- flags |= WHERE_COLUMN_RANGE;
+ wsFlags |= WHERE_COLUMN_RANGE;
if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pProbe) ){
- flags |= WHERE_TOP_LIMIT;
+ wsFlags |= WHERE_TOP_LIMIT;
cost /= 3;
}
if( findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pProbe) ){
- flags |= WHERE_BTM_LIMIT;
+ wsFlags |= WHERE_BTM_LIMIT;
cost /= 3;
}
WHERETRACE(("...... range reduces cost to %.9g\n", cost));
}
@@ -78450,16 +80410,16 @@
/* Add the additional cost of sorting if that is a factor.
*/
if( pOrderBy ){
- if( (flags & WHERE_COLUMN_IN)==0 &&
+ if( (wsFlags & WHERE_COLUMN_IN)==0 &&
isSortingIndex(pParse,pWC->pMaskSet,pProbe,iCur,pOrderBy,nEq,&rev) ){
- if( flags==0 ){
- flags = WHERE_COLUMN_RANGE;
- }
- flags |= WHERE_ORDERBY;
+ if( wsFlags==0 ){
+ wsFlags = WHERE_COLUMN_RANGE;
+ }
+ wsFlags |= WHERE_ORDERBY;
if( rev ){
- flags |= WHERE_REVERSE;
+ wsFlags |= WHERE_REVERSE;
}
}else{
cost += cost*estLog(cost);
WHERETRACE(("...... orderby increases cost to %.9g\n", cost));
@@ -78469,9 +80429,9 @@
/* Check to see if we can get away with using just the index without
** ever reading the table. If that is the case, then halve the
** cost of this index.
*/
- if( flags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){
+ if( wsFlags && pSrc->colUsed < (((Bitmask)1)<<(BMS-1)) ){
Bitmask m = pSrc->colUsed;
int j;
for(j=0; j<pProbe->nColumn; j++){
int x = pProbe->aiColumn[j];
@@ -78479,30 +80439,30 @@
m &= ~(((Bitmask)1)<<x);
}
}
if( m==0 ){
- flags |= WHERE_IDX_ONLY;
+ wsFlags |= WHERE_IDX_ONLY;
cost /= 2;
WHERETRACE(("...... idx-only reduces cost to %.9g\n", cost));
}
}
/* If this index has achieved the lowest cost so far, then use it.
*/
- if( flags && cost < lowestCost ){
+ if( wsFlags && cost < lowestCost ){
bestIdx = pProbe;
lowestCost = cost;
- bestFlags = flags;
+ bestWsFlags = wsFlags;
bestNEq = nEq;
}
}
/* Report the best result
*/
*ppIndex = bestIdx;
- WHERETRACE(("best index is %s, cost=%.9g, flags=%x, nEq=%d\n",
- bestIdx ? bestIdx->zName : "(none)", lowestCost, bestFlags, bestNEq));
- *pFlags = bestFlags | eqTermMask;
+ WHERETRACE(("best index is %s, cost=%.9g, wsFlags=%x, nEq=%d\n",
+ bestIdx ? bestIdx->zName : "(none)", lowestCost, bestWsFlags, bestNEq));
+ *pWsFlags = bestWsFlags | eqTermMask;
*pnEq = bestNEq;
return lowestCost;
}
@@ -78531,12 +80491,12 @@
** the wrong answer. See ticket #813.
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
if( pTerm
- && ALWAYS((pTerm->flags & TERM_CODED)==0)
+ && ALWAYS((pTerm->wtFlags & TERM_CODED)==0)
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){
- pTerm->flags |= TERM_CODED;
+ pTerm->wtFlags |= TERM_CODED;
if( pTerm->iParent>=0 ){
WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
if( (--pOther->nChild)==0 ){
disableTerm(pLevel, pOther);
@@ -78599,9 +80559,9 @@
iTab = pX->iTable;
sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
VdbeComment((v, "%.*s", pX->span.n, pX->span.z));
if( pLevel->nIn==0 ){
- pLevel->nxt = sqlite3VdbeMakeLabel(v);
+ pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
}
pLevel->nIn++;
pLevel->aInLoop = sqlite3DbReallocOrFree(pParse->db, pLevel->aInLoop,
sizeof(pLevel->aInLoop[0])*pLevel->nIn);
@@ -78609,11 +80569,11 @@
if( pIn ){
pIn += pLevel->nIn - 1;
pIn->iCur = iTab;
if( eType==IN_INDEX_ROWID ){
- pIn->topAddr = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
- }else{
- pIn->topAddr = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
+ pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
+ }else{
+ pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
}
sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
}else{
pLevel->nIn = 0;
@@ -78676,19 +80636,19 @@
assert( pIdx->nColumn>=nEq );
for(j=0; j<nEq; j++){
int r1;
int k = pIdx->aiColumn[j];
- pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
+ pTerm = findTerm(pWC, iCur, k, notReady, pLevel->wsFlags, pIdx);
if( NEVER(pTerm==0) ) break;
- assert( (pTerm->flags & TERM_CODED)==0 );
+ assert( (pTerm->wtFlags & TERM_CODED)==0 );
r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
if( r1!=regBase+j ){
sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
}
testcase( pTerm->eOperator & WO_ISNULL );
testcase( pTerm->eOperator & WO_IN );
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->brk);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
}
}
return regBase;
}
@@ -78816,22 +80776,22 @@
Parse *pParse, /* The parser context */
SrcList *pTabList, /* A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
- u8 wflags /* One of the WHERE_* flags defined in sqliteInt.h */
+ u8 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
){
int i; /* Loop counter */
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
- int brk, cont = 0; /* Addresses used during code generation */
+ int addrBrk, addrCont = 0; /* Addresses used during code generation */
Bitmask notReady; /* Cursors that are not yet positioned */
WhereTerm *pTerm; /* A single term in the WHERE clause */
ExprMaskSet maskSet; /* The expression mask set */
WhereClause wc; /* The WHERE clause is divided into these terms */
struct SrcList_item *pTabItem; /* A single entry from pTabList */
WhereLevel *pLevel; /* A single level in the pWInfo list */
int iFrom; /* First unused FROM clause element */
- int andFlags; /* AND-ed combination of all wc.a[].flags */
+ int andFlags; /* AND-ed combination of all wc.a[].wtFlags */
sqlite3 *db; /* Database connection */
ExprList *pOrderBy = 0;
/* The number of tables in the FROM clause is limited by the number of
@@ -78915,9 +80875,9 @@
**
** This loop fills in the following fields:
**
** pWInfo->a[].pIdx The index to use for this level of the loop.
- ** pWInfo->a[].flags WHERE_xxx flags associated with pIdx
+ ** pWInfo->a[].wsFlags WHERE_xxx flags associated with pIdx
** pWInfo->a[].nEq The number of == and IN constraints
** pWInfo->a[].iFrom Which term of the FROM clause is being coded
** pWInfo->a[].iTabCur The VDBE cursor for the database table
** pWInfo->a[].iIdxCur The VDBE cursor for the index
@@ -78931,14 +80891,14 @@
andFlags = ~0;
WHERETRACE(("*** Optimizer Start ***\n"));
for(i=iFrom=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
Index *pIdx; /* Index for FROM table at pTabItem */
- int flags; /* Flags asssociated with pIdx */
+ int wsFlags; /* Flags describing scan strategy */
int nEq; /* Number of == or IN constraints */
double cost; /* The cost for pIdx */
int j; /* For looping over FROM tables */
Index *pBest = 0; /* The best index seen so far */
- int bestFlags = 0; /* Flags associated with pBest */
+ int bestWsFlags = 0; /* Flags associated with pBest */
int bestNEq = 0; /* nEq associated with pBest */
double lowestCost; /* Cost of the pBest */
int bestJ = 0; /* The value of j */
Bitmask m; /* Bitmask value for j or bestJ */
@@ -78962,12 +80922,12 @@
sqlite3_index_info **ppIdxInfo = &pWInfo->a[j].pIdxInfo;
cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady,
ppOrderBy ? *ppOrderBy : 0, i==0,
ppIdxInfo);
- flags = WHERE_VIRTUALTABLE;
+ wsFlags = WHERE_VIRTUALTABLE;
pIndex = *ppIdxInfo;
if( pIndex && pIndex->orderByConsumed ){
- flags = WHERE_VIRTUALTABLE | WHERE_ORDERBY;
+ wsFlags = WHERE_VIRTUALTABLE | WHERE_ORDERBY;
}
pIdx = 0;
nEq = 0;
if( (SQLITE_BIG_DBL/2.0)<cost ){
@@ -78982,16 +80942,16 @@
#endif
{
cost = bestIndex(pParse, &wc, pTabItem, notReady,
(i==0 && ppOrderBy) ? *ppOrderBy : 0,
- &pIdx, &flags, &nEq);
+ &pIdx, &wsFlags, &nEq);
pIndex = 0;
}
if( cost<lowestCost ){
once = 1;
lowestCost = cost;
pBest = pIdx;
- bestFlags = flags;
+ bestWsFlags = wsFlags;
bestNEq = nEq;
bestJ = j;
pLevel->pBestIdx = pIndex;
}
@@ -78998,13 +80958,13 @@
if( doNotReorder ) break;
}
WHERETRACE(("*** Optimizer selects table %d for loop %d\n", bestJ,
pLevel-pWInfo->a));
- if( (bestFlags & WHERE_ORDERBY)!=0 ){
+ if( (bestWsFlags & WHERE_ORDERBY)!=0 ){
*ppOrderBy = 0;
}
- andFlags &= bestFlags;
- pLevel->flags = bestFlags;
+ andFlags &= bestWsFlags;
+ pLevel->wsFlags = bestWsFlags;
pLevel->pIdx = pBest;
pLevel->nEq = bestNEq;
pLevel->aInLoop = 0;
pLevel->nIn = 0;
@@ -79041,12 +81001,12 @@
** to use a one-pass algorithm, determine if this is appropriate.
** The one-pass algorithm only works if the WHERE clause constraints
** the statement to update a single row.
*/
- assert( (wflags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
- if( (wflags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
+ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
+ if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (andFlags & WHERE_UNIQUE)!=0 ){
pWInfo->okOnePass = 1;
- pWInfo->a[0].flags &= ~WHERE_IDX_ONLY;
+ pWInfo->a[0].wsFlags &= ~WHERE_IDX_ONLY;
}
/* Open all tables in the pTabList and any indices selected for
** searching those tables.
@@ -79067,9 +81027,9 @@
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
}
if( (pIx = pLevel->pIdx)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s WITH INDEX %s", zMsg, pIx->zName);
- }else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+ }else if( pLevel->wsFlags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
zMsg = sqlite3MAppendf(db, zMsg, "%s USING PRIMARY KEY", zMsg);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( pLevel->pBestIdx ){
@@ -79077,9 +81037,9 @@
zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
pBestIdx->idxNum, pBestIdx->idxStr);
}
#endif
- if( pLevel->flags & WHERE_ORDERBY ){
+ if( pLevel->wsFlags & WHERE_ORDERBY ){
zMsg = sqlite3MAppendf(db, zMsg, "%s ORDER BY", zMsg);
}
sqlite3VdbeAddOp4(v, OP_Explain, i, pLevel->iFrom, 0, zMsg, P4_DYNAMIC);
}
@@ -79094,9 +81054,9 @@
sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0,
(const char*)pTab->pVtab, P4_VTAB);
}else
#endif
- if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
+ if( (pLevel->wsFlags & WHERE_IDX_ONLY)==0 ){
int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op);
if( !pWInfo->okOnePass && pTab->nCol<BMS ){
Bitmask b = pTabItem->colUsed;
@@ -79129,9 +81089,9 @@
for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
int j, k;
int iCur = pTabItem->iCursor; /* The VDBE cursor for the table */
Index *pIdx; /* The index we will be using */
- int nxt; /* Where to jump to continue with the next IN case */
+ int addrNxt; /* Where to jump to continue with the next IN case */
int iIdxCur; /* The VDBE cursor for the index */
int omitTable; /* True if we use the index only */
int bRev; /* True if we need to scan in reverse order */
@@ -79138,23 +81098,23 @@
pTabItem = &pTabList->a[pLevel->iFrom];
iCur = pTabItem->iCursor;
pIdx = pLevel->pIdx;
iIdxCur = pLevel->iIdxCur;
- bRev = (pLevel->flags & WHERE_REVERSE)!=0;
- omitTable = (pLevel->flags & WHERE_IDX_ONLY)!=0;
+ bRev = (pLevel->wsFlags & WHERE_REVERSE)!=0;
+ omitTable = (pLevel->wsFlags & WHERE_IDX_ONLY)!=0;
/* Create labels for the "break" and "continue" instructions
- ** for the current loop. Jump to brk to break out of a loop.
+ ** for the current loop. Jump to addrBrk to break out of a loop.
** Jump to cont to go immediately to the next iteration of the
** loop.
**
- ** When there is an IN operator, we also have a "nxt" label that
+ ** When there is an IN operator, we also have a "addrNxt" label that
** means to continue with the next IN value combination. When
- ** there are no IN operators in the constraints, the "nxt" label
- ** is the same as "brk".
- */
- brk = pLevel->brk = pLevel->nxt = sqlite3VdbeMakeLabel(v);
- cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
+ ** there are no IN operators in the constraints, the "addrNxt" label
+ ** is the same as "addrBrk".
+ */
+ addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
+ addrCont = pLevel->addrCont = sqlite3VdbeMakeLabel(v);
/* If this is the right table of a LEFT OUTER JOIN, allocate and
** initialize a memory cell that records if this table matches any
** row of the left table of the join.
@@ -79169,9 +81129,8 @@
if( pLevel->pBestIdx ){
/* Case 0: The table is a virtual-table. Use the VFilter and VNext
** to access the data.
*/
- int j;
int iReg; /* P3 Value for OP_VFilter */
sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
int nConstraint = pBestIdx->nConstraint;
struct sqlite3_index_constraint_usage *aUsage =
@@ -79181,9 +81140,8 @@
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
pParse->disableColCache++;
for(j=1; j<=nConstraint; j++){
- int k;
for(k=0; k<nConstraint; k++){
if( aUsage[k].argvIndex==j ){
int iTerm = aConstraint[k].iTermOffset;
assert( pParse->disableColCache );
@@ -79196,9 +81154,9 @@
assert( pParse->disableColCache );
pParse->disableColCache--;
sqlite3VdbeAddOp2(v, OP_Integer, pBestIdx->idxNum, iReg);
sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
- sqlite3VdbeAddOp4(v, OP_VFilter, iCur, brk, iReg, pBestIdx->idxStr,
+ sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pBestIdx->idxStr,
pBestIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
pBestIdx->needToFreeIdxStr = 0;
for(j=0; j<nConstraint; j++){
@@ -79212,9 +81170,9 @@
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
}else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
- if( pLevel->flags & WHERE_ROWID_EQ ){
+ if( pLevel->wsFlags & WHERE_ROWID_EQ ){
/* Case 1: We can directly reference a single row using an
** equality comparison against the ROWID field. Or
** we reference multiple rows using a "rowid IN (...)"
** construct.
@@ -79226,15 +81184,15 @@
assert( pTerm->pExpr!=0 );
assert( pTerm->leftCursor==iCur );
assert( omitTable==0 );
r1 = codeEqualityTerm(pParse, pTerm, pLevel, rtmp);
- nxt = pLevel->nxt;
- sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt);
- sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
+ addrNxt = pLevel->addrNxt;
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, addrNxt);
+ sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, r1);
sqlite3ReleaseTempReg(pParse, rtmp);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
- }else if( pLevel->flags & WHERE_ROWID_RANGE ){
+ }else if( pLevel->wsFlags & WHERE_ROWID_RANGE ){
/* Case 2: We have an inequality comparison against the ROWID field.
*/
int testOp = OP_Noop;
int start;
@@ -79248,32 +81206,35 @@
pStart = pEnd;
pEnd = pTerm;
}
if( pStart ){
- Expr *pX;
- int r1;
+ Expr *pX; /* The expression that defines the start bound */
+ int r1, rTemp; /* Registers for holding the start boundary */
+
+ /* The following constant maps TK_xx codes into corresponding
+ ** seek opcodes. It depends on a particular ordering of TK_xx
+ */
+ const u8 aMoveOp[] = {
+ /* TK_GT */ OP_SeekGt,
+ /* TK_LE */ OP_SeekLe,
+ /* TK_LT */ OP_SeekLt,
+ /* TK_GE */ OP_SeekGe
+ };
+ assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */
+ assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */
+ assert( TK_GE==TK_GT+3 ); /* ... is correcct. */
+
pX = pStart->pExpr;
assert( pX!=0 );
assert( pStart->leftCursor==iCur );
-
- /* The ForceInt instruction may modify the register that it operates
- ** on. For example it may replace a real value with an integer one,
- ** or if p3 is true it may increment the register value. For this
- ** reason we need to make sure that register r1 is really a newly
- ** allocated temporary register, and not part of the column-cache.
- ** For this reason we cannot use sqlite3ExprCodeTemp() here.
- */
- r1 = sqlite3GetTempReg(pParse);
- sqlite3ExprCode(pParse, pX->pRight, r1);
-
- sqlite3VdbeAddOp3(v, OP_ForceInt, r1, brk,
- pX->op==TK_LE || pX->op==TK_GT);
- sqlite3VdbeAddOp3(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk, r1);
+ r1 = sqlite3ExprCodeTemp(pParse, pX->pRight, &rTemp);
+ sqlite3VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1);
VdbeComment((v, "pk"));
- sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3ExprCacheAffinityChange(pParse, r1, 1);
+ sqlite3ReleaseTempReg(pParse, rTemp);
disableTerm(pLevel, pStart);
}else{
- sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, brk);
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk);
}
if( pEnd ){
Expr *pX;
pX = pEnd->pExpr;
@@ -79295,13 +81256,13 @@
if( testOp!=OP_Noop ){
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
/* sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0); */
- sqlite3VdbeAddOp3(v, testOp, pLevel->iMem, brk, r1);
+ sqlite3VdbeAddOp3(v, testOp, pLevel->iMem, addrBrk, r1);
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
sqlite3ReleaseTempReg(pParse, r1);
}
- }else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
+ }else if( pLevel->wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
/* Case 3: A scan using an index.
**
** The WHERE clause may contain zero or more equality
** terms ("==" or "IN" operators) that refer to the N
@@ -79336,12 +81297,12 @@
0,
0,
OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */
OP_Last, /* 3: (!start_constraints && startEq && bRev) */
- OP_MoveGt, /* 4: (start_constraints && !startEq && !bRev) */
- OP_MoveLt, /* 5: (start_constraints && !startEq && bRev) */
- OP_MoveGe, /* 6: (start_constraints && startEq && !bRev) */
- OP_MoveLe /* 7: (start_constraints && startEq && bRev) */
+ OP_SeekGt, /* 4: (start_constraints && !startEq && !bRev) */
+ OP_SeekLt, /* 5: (start_constraints && !startEq && bRev) */
+ OP_SeekGe, /* 6: (start_constraints && startEq && !bRev) */
+ OP_SeekLe /* 7: (start_constraints && startEq && bRev) */
};
int aEndOp[] = {
OP_Noop, /* 0: (!end_constraints) */
OP_IdxGE, /* 1: (end_constraints && !bRev) */
@@ -79355,18 +81316,19 @@
WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */
int startEq; /* True if range start uses ==, >= or <= */
int endEq; /* True if range end uses ==, >= or <= */
int start_constraints; /* Start of range is constrained */
- int k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */
int nConstraint; /* Number of constraint terms */
int op;
+
+ k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */
/* Generate code to evaluate all constraint terms using == or IN
** and store the values of those terms in an array of registers
** starting at regBase.
*/
regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 2);
- nxt = pLevel->nxt;
+ addrNxt = pLevel->addrNxt;
/* If this loop satisfies a sort order (pOrderBy) request that
** was passed to this function to implement a "SELECT min(x) ..."
** query, then the caller will only allow the loop to run for
@@ -79374,10 +81336,10 @@
** should not have a NULL value stored in 'x'. If column 'x' is
** the first one after the nEq equality constraints in the index,
** this requires some special handling.
*/
- if( (wflags&WHERE_ORDERBY_MIN)!=0
- && (pLevel->flags&WHERE_ORDERBY)
+ if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
+ && (pLevel->wsFlags&WHERE_ORDERBY)
&& (pIdx->nColumn>nEq)
){
assert( pOrderBy->nExpr==1 );
assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] );
@@ -79386,12 +81348,12 @@
/* Find any inequality constraint terms for the start and end
** of the range.
*/
- if( pLevel->flags & WHERE_TOP_LIMIT ){
+ if( pLevel->wsFlags & WHERE_TOP_LIMIT ){
pRangeEnd = findTerm(&wc, iCur, k, notReady, (WO_LT|WO_LE), pIdx);
}
- if( pLevel->flags & WHERE_BTM_LIMIT ){
+ if( pLevel->wsFlags & WHERE_BTM_LIMIT ){
pRangeStart = findTerm(&wc, iCur, k, notReady, (WO_GT|WO_GE), pIdx);
}
/* If we are doing a reverse order scan on an ascending index, or
@@ -79418,9 +81380,9 @@
pParse->disableColCache++;
}
sqlite3ExprCode(pParse, pRangeStart->pExpr->pRight, regBase+nEq);
pParse->disableColCache = dcc;
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
nConstraint++;
}else if( isMinQuery ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
nConstraint++;
@@ -79431,13 +81393,13 @@
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
testcase( op==OP_Rewind );
testcase( op==OP_Last );
- testcase( op==OP_MoveGt );
- testcase( op==OP_MoveGe );
- testcase( op==OP_MoveLe );
- testcase( op==OP_MoveLt );
- sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase,
+ testcase( op==OP_SeekGt );
+ testcase( op==OP_SeekGe );
+ testcase( op==OP_SeekLe );
+ testcase( op==OP_SeekLt );
+ sqlite3VdbeAddOp4(v, op, iIdxCur, addrNxt, regBase,
SQLITE_INT_TO_PTR(nConstraint), P4_INT32);
/* Load the value for the inequality constraint at the end of the
** range (if any).
@@ -79444,9 +81406,9 @@
*/
nConstraint = nEq;
if( pRangeEnd ){
sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq);
- sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
codeApplyAffinity(pParse, regBase, nEq+1, pIdx);
nConstraint++;
}
@@ -79457,28 +81419,28 @@
op = aEndOp[(pRangeEnd || nEq) * (1 + bRev)];
testcase( op==OP_Noop );
testcase( op==OP_IdxGE );
testcase( op==OP_IdxLT );
- sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase,
+ sqlite3VdbeAddOp4(v, op, iIdxCur, addrNxt, regBase,
SQLITE_INT_TO_PTR(nConstraint), P4_INT32);
- sqlite3VdbeChangeP5(v, endEq!=bRev);
+ sqlite3VdbeChangeP5(v, endEq!=bRev ?1:0);
/* If there are inequality constraints, check that the value
** of the table column that the inequality contrains is not NULL.
** If it is, jump to the next iteration of the loop.
*/
r1 = sqlite3GetTempReg(pParse);
- testcase( pLevel->flags & WHERE_BTM_LIMIT );
- testcase( pLevel->flags & WHERE_TOP_LIMIT );
- if( pLevel->flags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){
+ testcase( pLevel->wsFlags & WHERE_BTM_LIMIT );
+ testcase( pLevel->wsFlags & WHERE_TOP_LIMIT );
+ if( pLevel->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT) ){
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, nEq, r1);
- sqlite3VdbeAddOp2(v, OP_IsNull, r1, cont);
+ sqlite3VdbeAddOp2(v, OP_IsNull, r1, addrCont);
}
/* Seek the table cursor, if required */
if( !omitTable ){
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
- sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1); /* Deferred seek */
+ sqlite3VdbeAddOp2(v, OP_Seek, iCur, r1); /* Deferred seek */
}
sqlite3ReleaseTempReg(pParse, r1);
/* Record the instruction used to terminate the loop. Disable
@@ -79495,9 +81457,9 @@
assert( omitTable==0 );
assert( bRev==0 );
pLevel->op = OP_Next;
pLevel->p1 = iCur;
- pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, brk);
+ pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addrBrk);
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}
notReady &= ~getMask(&maskSet, iCur);
@@ -79506,41 +81468,41 @@
*/
k = 0;
for(pTerm=wc.a, j=wc.nTerm; j>0; j--, pTerm++){
Expr *pE;
- testcase( pTerm->flags & TERM_VIRTUAL );
- testcase( pTerm->flags & TERM_CODED );
- if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
+ testcase( pTerm->wtFlags & TERM_CODED );
+ if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & notReady)!=0 ) continue;
pE = pTerm->pExpr;
assert( pE!=0 );
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
continue;
}
pParse->disableColCache += k;
- sqlite3ExprIfFalse(pParse, pE, cont, SQLITE_JUMPIFNULL);
+ sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
pParse->disableColCache -= k;
k = 1;
- pTerm->flags |= TERM_CODED;
+ pTerm->wtFlags |= TERM_CODED;
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
** at least one row of the right table has matched the left table.
*/
if( pLevel->iLeftJoin ){
- pLevel->top = sqlite3VdbeCurrentAddr(v);
+ pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
sqlite3ExprClearColumnCache(pParse, pLevel->iTabCur);
sqlite3ExprClearColumnCache(pParse, pLevel->iIdxCur);
for(pTerm=wc.a, j=0; j<wc.nTerm; j++, pTerm++){
- testcase( pTerm->flags & TERM_VIRTUAL );
- testcase( pTerm->flags & TERM_CODED );
- if( pTerm->flags & (TERM_VIRTUAL|TERM_CODED) ) continue;
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
+ testcase( pTerm->wtFlags & TERM_CODED );
+ if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & notReady)!=0 ) continue;
assert( pTerm->pExpr );
- sqlite3ExprIfFalse(pParse, pTerm->pExpr, cont, SQLITE_JUMPIFNULL);
- pTerm->flags |= TERM_CODED;
+ sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
+ pTerm->wtFlags |= TERM_CODED;
}
}
}
@@ -79557,11 +81519,11 @@
pLevel = &pWInfo->a[i];
pTabItem = &pTabList->a[pLevel->iFrom];
z = pTabItem->zAlias;
if( z==0 ) z = pTabItem->pTab->zName;
- n = strlen(z);
+ n = sqlite3Strlen30(z);
if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
- if( pLevel->flags & WHERE_IDX_ONLY ){
+ if( pLevel->wsFlags & WHERE_IDX_ONLY ){
memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
nQPlan += 2;
}else{
memcpy(&sqlite3_query_plan[nQPlan], z, n);
@@ -79568,18 +81530,18 @@
nQPlan += n;
}
sqlite3_query_plan[nQPlan++] = ' ';
}
- testcase( pLevel->flags & WHERE_ROWID_EQ );
- testcase( pLevel->flags & WHERE_ROWID_RANGE );
- if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+ testcase( pLevel->wsFlags & WHERE_ROWID_EQ );
+ testcase( pLevel->wsFlags & WHERE_ROWID_RANGE );
+ if( pLevel->wsFlags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
nQPlan += 2;
}else if( pLevel->pIdx==0 ){
memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3);
nQPlan += 3;
}else{
- n = strlen(pLevel->pIdx->zName);
+ n = sqlite3Strlen30(pLevel->pIdx->zName);
if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
memcpy(&sqlite3_query_plan[nQPlan], pLevel->pIdx->zName, n);
nQPlan += n;
sqlite3_query_plan[nQPlan++] = ' ';
@@ -79595,9 +81557,9 @@
/* Record the continuation address in the WhereInfo structure. Then
** clean up and return.
*/
- pWInfo->iContinue = cont;
+ pWInfo->iContinue = addrCont;
whereClauseClear(&wc);
return pWInfo;
/* Jump here if malloc fails */
@@ -79623,33 +81585,33 @@
*/
sqlite3ExprClearColumnCache(pParse, -1);
for(i=pTabList->nSrc-1; i>=0; i--){
pLevel = &pWInfo->a[i];
- sqlite3VdbeResolveLabel(v, pLevel->cont);
+ sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
sqlite3VdbeChangeP5(v, pLevel->p5);
}
if( pLevel->nIn ){
struct InLoop *pIn;
int j;
- sqlite3VdbeResolveLabel(v, pLevel->nxt);
+ sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->nIn, pIn=&pLevel->aInLoop[j-1]; j>0; j--, pIn--){
- sqlite3VdbeJumpHere(v, pIn->topAddr+1);
- sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->topAddr);
- sqlite3VdbeJumpHere(v, pIn->topAddr-1);
+ sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
+ sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->addrInTop);
+ sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
sqlite3DbFree(db, pLevel->aInLoop);
}
- sqlite3VdbeResolveLabel(v, pLevel->brk);
+ sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
if( pLevel->iLeftJoin ){
int addr;
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
if( pLevel->iIdxCur>=0 ){
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->top);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst);
sqlite3VdbeJumpHere(v, addr);
}
}
@@ -79664,9 +81626,9 @@
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ) continue;
- if( !pWInfo->okOnePass && (pLevel->flags & WHERE_IDX_ONLY)==0 ){
+ if( !pWInfo->okOnePass && (pLevel->wsFlags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
}
if( pLevel->pIdx!=0 ){
sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
@@ -79688,9 +81650,9 @@
if( pLevel->pIdx ){
int k, j, last;
VdbeOp *pOp;
Index *pIdx = pLevel->pIdx;
- int useIndexOnly = pLevel->flags & WHERE_IDX_ONLY;
+ int useIndexOnly = pLevel->wsFlags & WHERE_IDX_ONLY;
assert( pIdx!=0 );
pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
last = sqlite3VdbeCurrentAddr(v);
@@ -79813,25 +81775,26 @@
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
-#define YYNOCODE 249
+#define YYNOCODE 248
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 59
#define sqlite3ParserTOKENTYPE Token
typedef union {
+ int yyinit;
sqlite3ParserTOKENTYPE yy0;
- Select* yy43;
- TriggerStep* yy75;
- struct LimitVal yy84;
- struct LikeOp yy86;
- struct {int value; int mask;} yy207;
- ExprList* yy242;
- int yy316;
- IdList* yy352;
- struct TrigEvent yy354;
- SrcList* yy419;
- Expr* yy450;
+ int yy46;
+ struct LikeOp yy72;
+ Expr* yy172;
+ ExprList* yy174;
+ Select* yy219;
+ struct LimitVal yy234;
+ TriggerStep* yy243;
+ struct TrigEvent yy370;
+ SrcList* yy373;
+ struct {int value; int mask;} yy405;
+ IdList* yy432;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
#endif
@@ -79838,22 +81801,19 @@
#define sqlite3ParserARG_SDECL Parse *pParse;
#define sqlite3ParserARG_PDECL ,Parse *pParse
#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite3ParserARG_STORE yypParser->pParse = pParse
-#define YYNSTATE 598
-#define YYNRULE 315
+#define YYNSTATE 601
+#define YYNRULE 314
#define YYFALLBACK 1
#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
-#if 0
-static YYMINORTYPE yyzerominor;
-#else
-static const YYMINORTYPE yyzerominor;
-#endif
+static const YYMINORTYPE yyzerominor = { 0 };
+
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
** functions that take a state number and lookahead value and return an
@@ -79901,422 +81861,425 @@
** shifting non-terminals after a reduce.
** yy_default[] Default action for each state.
*/
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 296, 914, 120, 597, 2, 172, 425, 425, 62, 62,
- /* 10 */ 62, 62, 210, 64, 64, 64, 64, 65, 65, 66,
- /* 20 */ 66, 66, 67, 212, 398, 395, 432, 438, 69, 64,
- /* 30 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 212,
- /* 40 */ 458, 456, 327, 168, 61, 60, 301, 442, 443, 439,
- /* 50 */ 439, 63, 63, 62, 62, 62, 62, 256, 64, 64,
- /* 60 */ 64, 64, 65, 65, 66, 66, 66, 67, 212, 296,
- /* 70 */ 498, 425, 425, 212, 427, 83, 68, 469, 70, 154,
+ /* 0 */ 299, 916, 120, 600, 2, 175, 427, 427, 62, 62,
+ /* 10 */ 62, 62, 487, 64, 64, 64, 64, 65, 65, 66,
+ /* 20 */ 66, 66, 67, 213, 400, 397, 434, 440, 69, 64,
+ /* 30 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 213,
+ /* 40 */ 460, 458, 330, 171, 61, 60, 304, 444, 445, 441,
+ /* 50 */ 441, 63, 63, 62, 62, 62, 62, 259, 64, 64,
+ /* 60 */ 64, 64, 65, 65, 66, 66, 66, 67, 213, 299,
+ /* 70 */ 501, 427, 427, 306, 429, 83, 68, 471, 70, 155,
/* 80 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
- /* 90 */ 212, 68, 307, 70, 154, 432, 438, 454, 214, 59,
- /* 100 */ 65, 65, 66, 66, 66, 67, 212, 429, 429, 429,
- /* 110 */ 497, 583, 296, 61, 60, 301, 442, 443, 439, 439,
- /* 120 */ 63, 63, 62, 62, 62, 62, 321, 64, 64, 64,
- /* 130 */ 64, 65, 65, 66, 66, 66, 67, 212, 432, 438,
- /* 140 */ 95, 66, 66, 66, 67, 212, 403, 256, 421, 35,
- /* 150 */ 57, 67, 212, 175, 417, 499, 61, 60, 301, 442,
- /* 160 */ 443, 439, 439, 63, 63, 62, 62, 62, 62, 19,
+ /* 90 */ 213, 68, 310, 70, 155, 434, 440, 456, 215, 59,
+ /* 100 */ 65, 65, 66, 66, 66, 67, 213, 431, 431, 431,
+ /* 110 */ 211, 586, 299, 61, 60, 304, 444, 445, 441, 441,
+ /* 120 */ 63, 63, 62, 62, 62, 62, 324, 64, 64, 64,
+ /* 130 */ 64, 65, 65, 66, 66, 66, 67, 213, 434, 440,
+ /* 140 */ 95, 320, 402, 483, 598, 907, 210, 907, 423, 35,
+ /* 150 */ 57, 67, 213, 203, 419, 271, 61, 60, 304, 444,
+ /* 160 */ 445, 441, 441, 63, 63, 62, 62, 62, 62, 213,
/* 170 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
- /* 180 */ 212, 296, 225, 532, 299, 581, 109, 422, 242, 458,
- /* 190 */ 416, 335, 414, 21, 502, 503, 346, 403, 527, 176,
- /* 200 */ 160, 454, 214, 580, 579, 344, 500, 432, 438, 149,
- /* 210 */ 150, 404, 405, 539, 514, 418, 151, 541, 8, 498,
- /* 220 */ 538, 577, 578, 427, 296, 61, 60, 301, 442, 443,
- /* 230 */ 439, 439, 63, 63, 62, 62, 62, 62, 196, 64,
- /* 240 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 212,
- /* 250 */ 432, 438, 454, 598, 398, 395, 429, 429, 429, 369,
- /* 260 */ 558, 481, 404, 405, 372, 576, 213, 296, 61, 60,
- /* 270 */ 301, 442, 443, 439, 439, 63, 63, 62, 62, 62,
- /* 280 */ 62, 321, 64, 64, 64, 64, 65, 65, 66, 66,
- /* 290 */ 66, 67, 212, 432, 438, 555, 503, 304, 557, 532,
- /* 300 */ 218, 557, 552, 421, 36, 234, 397, 2, 542, 21,
- /* 310 */ 540, 61, 60, 301, 442, 443, 439, 439, 63, 63,
- /* 320 */ 62, 62, 62, 62, 388, 64, 64, 64, 64, 65,
- /* 330 */ 65, 66, 66, 66, 67, 212, 415, 530, 85, 381,
- /* 340 */ 78, 323, 296, 210, 304, 527, 493, 492, 379, 274,
- /* 350 */ 273, 379, 274, 273, 347, 463, 241, 387, 268, 210,
- /* 360 */ 533, 581, 210, 403, 20, 224, 144, 464, 432, 438,
- /* 370 */ 485, 164, 114, 248, 349, 253, 350, 177, 554, 580,
- /* 380 */ 465, 420, 331, 81, 257, 419, 61, 60, 301, 442,
- /* 390 */ 443, 439, 439, 63, 63, 62, 62, 62, 62, 391,
+ /* 180 */ 213, 299, 492, 535, 595, 584, 109, 424, 465, 460,
+ /* 190 */ 338, 500, 416, 20, 522, 348, 272, 405, 324, 68,
+ /* 200 */ 466, 70, 155, 583, 582, 542, 517, 434, 440, 150,
+ /* 210 */ 151, 388, 541, 467, 523, 334, 152, 544, 271, 501,
+ /* 220 */ 423, 42, 502, 429, 299, 61, 60, 304, 444, 445,
+ /* 230 */ 441, 441, 63, 63, 62, 62, 62, 62, 396, 64,
+ /* 240 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 213,
+ /* 250 */ 434, 440, 456, 601, 400, 397, 431, 431, 431, 569,
+ /* 260 */ 561, 217, 406, 407, 579, 214, 309, 299, 61, 60,
+ /* 270 */ 304, 444, 445, 441, 441, 63, 63, 62, 62, 62,
+ /* 280 */ 62, 324, 64, 64, 64, 64, 65, 65, 66, 66,
+ /* 290 */ 66, 67, 213, 434, 440, 405, 543, 307, 560, 505,
+ /* 300 */ 506, 560, 536, 423, 36, 195, 66, 66, 66, 67,
+ /* 310 */ 213, 61, 60, 304, 444, 445, 441, 441, 63, 63,
+ /* 320 */ 62, 62, 62, 62, 183, 64, 64, 64, 64, 65,
+ /* 330 */ 65, 66, 66, 66, 67, 213, 417, 533, 584, 424,
+ /* 340 */ 78, 271, 299, 259, 307, 530, 496, 236, 381, 277,
+ /* 350 */ 276, 381, 277, 276, 553, 242, 583, 153, 552, 211,
+ /* 360 */ 406, 407, 211, 379, 68, 225, 70, 155, 434, 440,
+ /* 370 */ 370, 167, 114, 251, 351, 256, 352, 178, 226, 175,
+ /* 380 */ 17, 427, 393, 81, 260, 382, 61, 60, 304, 444,
+ /* 390 */ 445, 441, 441, 63, 63, 62, 62, 62, 62, 514,
/* 400 */ 64, 64, 64, 64, 65, 65, 66, 66, 66, 67,
- /* 410 */ 212, 296, 224, 203, 249, 496, 403, 440, 837, 114,
- /* 420 */ 248, 349, 253, 350, 177, 250, 321, 152, 404, 405,
- /* 430 */ 321, 257, 303, 324, 155, 445, 445, 432, 438, 317,
- /* 440 */ 400, 389, 213, 68, 209, 70, 154, 422, 421, 35,
- /* 450 */ 393, 202, 421, 42, 481, 61, 60, 301, 442, 443,
- /* 460 */ 439, 439, 63, 63, 62, 62, 62, 62, 422, 64,
- /* 470 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 212,
- /* 480 */ 296, 404, 405, 183, 513, 422, 351, 354, 355, 403,
- /* 490 */ 77, 335, 79, 489, 216, 183, 334, 356, 351, 354,
- /* 500 */ 355, 433, 434, 406, 407, 408, 432, 438, 235, 356,
- /* 510 */ 386, 68, 291, 70, 154, 456, 531, 168, 198, 302,
- /* 520 */ 449, 450, 436, 437, 61, 60, 301, 442, 443, 439,
- /* 530 */ 439, 63, 63, 62, 62, 62, 62, 394, 64, 64,
- /* 540 */ 64, 64, 65, 65, 66, 66, 66, 67, 212, 296,
- /* 550 */ 321, 435, 422, 260, 404, 405, 321, 183, 153, 321,
- /* 560 */ 351, 354, 355, 446, 332, 321, 595, 905, 321, 905,
- /* 570 */ 1, 356, 421, 28, 403, 432, 438, 376, 421, 42,
- /* 580 */ 477, 421, 35, 213, 548, 366, 548, 421, 50, 159,
- /* 590 */ 421, 50, 422, 61, 60, 301, 442, 443, 439, 439,
- /* 600 */ 63, 63, 62, 62, 62, 62, 592, 64, 64, 64,
- /* 610 */ 64, 65, 65, 66, 66, 66, 67, 212, 296, 337,
- /* 620 */ 217, 463, 256, 94, 339, 326, 449, 450, 172, 340,
- /* 630 */ 425, 345, 532, 464, 312, 595, 904, 313, 904, 404,
- /* 640 */ 405, 588, 21, 226, 432, 438, 465, 243, 504, 324,
- /* 650 */ 322, 445, 445, 421, 3, 459, 230, 308, 505, 194,
- /* 660 */ 278, 296, 61, 60, 301, 442, 443, 439, 439, 63,
- /* 670 */ 63, 62, 62, 62, 62, 592, 64, 64, 64, 64,
- /* 680 */ 65, 65, 66, 66, 66, 67, 212, 432, 438, 213,
- /* 690 */ 179, 180, 181, 422, 324, 425, 445, 445, 281, 262,
- /* 700 */ 279, 402, 194, 481, 296, 61, 60, 301, 442, 443,
- /* 710 */ 439, 439, 63, 63, 62, 62, 62, 62, 377, 64,
- /* 720 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 212,
- /* 730 */ 432, 438, 591, 295, 115, 268, 422, 266, 211, 264,
- /* 740 */ 373, 324, 246, 445, 445, 56, 256, 296, 61, 71,
- /* 750 */ 301, 442, 443, 439, 439, 63, 63, 62, 62, 62,
- /* 760 */ 62, 377, 64, 64, 64, 64, 65, 65, 66, 66,
- /* 770 */ 66, 67, 212, 432, 438, 550, 269, 474, 18, 549,
- /* 780 */ 280, 309, 343, 380, 171, 160, 256, 268, 5, 268,
- /* 790 */ 296, 368, 60, 301, 442, 443, 439, 439, 63, 63,
- /* 800 */ 62, 62, 62, 62, 321, 64, 64, 64, 64, 65,
- /* 810 */ 65, 66, 66, 66, 67, 212, 432, 438, 403, 10,
- /* 820 */ 403, 310, 268, 403, 268, 485, 421, 29, 566, 22,
- /* 830 */ 568, 420, 428, 425, 376, 419, 301, 442, 443, 439,
- /* 840 */ 439, 63, 63, 62, 62, 62, 62, 321, 64, 64,
- /* 850 */ 64, 64, 65, 65, 66, 66, 66, 67, 212, 73,
- /* 860 */ 328, 485, 4, 569, 268, 570, 300, 268, 147, 421,
- /* 870 */ 24, 321, 359, 321, 325, 73, 328, 491, 4, 455,
- /* 880 */ 321, 342, 300, 404, 405, 404, 405, 367, 404, 405,
- /* 890 */ 325, 330, 321, 421, 33, 421, 54, 321, 425, 178,
- /* 900 */ 229, 458, 421, 53, 321, 227, 321, 330, 228, 478,
- /* 910 */ 165, 321, 315, 119, 421, 99, 333, 458, 321, 421,
- /* 920 */ 97, 76, 75, 311, 268, 519, 421, 102, 421, 103,
- /* 930 */ 74, 319, 320, 421, 108, 427, 467, 76, 75, 490,
- /* 940 */ 421, 110, 452, 452, 321, 520, 74, 319, 320, 73,
- /* 950 */ 328, 427, 4, 210, 298, 321, 300, 321, 156, 257,
- /* 960 */ 321, 210, 185, 182, 325, 284, 421, 17, 429, 429,
- /* 970 */ 429, 430, 431, 12, 593, 378, 188, 421, 100, 421,
- /* 980 */ 34, 330, 421, 98, 429, 429, 429, 430, 431, 12,
- /* 990 */ 475, 458, 422, 162, 480, 321, 422, 306, 231, 232,
- /* 1000 */ 233, 105, 484, 632, 476, 321, 486, 447, 321, 23,
- /* 1010 */ 422, 76, 75, 594, 207, 178, 286, 421, 25, 254,
- /* 1020 */ 74, 319, 320, 287, 321, 427, 321, 421, 55, 321,
- /* 1030 */ 421, 111, 321, 471, 321, 205, 515, 557, 511, 363,
- /* 1040 */ 472, 204, 321, 516, 206, 321, 421, 112, 421, 113,
- /* 1050 */ 321, 421, 26, 321, 421, 37, 421, 38, 429, 429,
- /* 1060 */ 429, 430, 431, 12, 421, 27, 521, 421, 39, 321,
- /* 1070 */ 298, 158, 421, 40, 255, 421, 41, 321, 483, 321,
- /* 1080 */ 173, 523, 321, 182, 321, 522, 321, 384, 283, 273,
- /* 1090 */ 321, 421, 43, 297, 534, 321, 476, 321, 210, 421,
- /* 1100 */ 44, 421, 45, 321, 421, 30, 421, 31, 421, 46,
- /* 1110 */ 508, 509, 421, 47, 259, 321, 182, 421, 48, 421,
- /* 1120 */ 49, 321, 358, 390, 182, 421, 32, 321, 261, 518,
- /* 1130 */ 517, 553, 561, 182, 173, 412, 191, 421, 11, 562,
- /* 1140 */ 573, 92, 92, 421, 51, 590, 263, 294, 265, 421,
- /* 1150 */ 52, 267, 272, 371, 146, 374, 375, 275, 276, 277,
- /* 1160 */ 565, 575, 285, 288, 289, 587, 470, 451, 236, 453,
- /* 1170 */ 329, 244, 473, 514, 251, 524, 560, 163, 401, 572,
- /* 1180 */ 426, 525, 282, 528, 409, 7, 410, 411, 385, 318,
- /* 1190 */ 85, 237, 338, 526, 84, 336, 353, 58, 80, 215,
- /* 1200 */ 170, 468, 121, 86, 341, 348, 305, 501, 506, 124,
- /* 1210 */ 511, 222, 360, 423, 252, 186, 512, 510, 221, 223,
- /* 1220 */ 238, 507, 239, 535, 240, 292, 424, 529, 536, 537,
- /* 1230 */ 293, 543, 187, 189, 245, 362, 482, 488, 247, 190,
- /* 1240 */ 364, 89, 545, 192, 117, 370, 132, 556, 563, 195,
- /* 1250 */ 382, 383, 314, 133, 134, 571, 138, 135, 136, 584,
- /* 1260 */ 589, 585, 142, 399, 101, 413, 220, 586, 270, 104,
- /* 1270 */ 141, 633, 634, 166, 167, 441, 444, 72, 460, 448,
- /* 1280 */ 457, 546, 143, 157, 6, 461, 14, 479, 169, 462,
- /* 1290 */ 93, 466, 82, 122, 13, 174, 487, 96, 123, 161,
- /* 1300 */ 494, 495, 87, 125, 126, 116, 258, 88, 127, 184,
- /* 1310 */ 250, 361, 219, 107, 544, 145, 128, 193, 365, 118,
- /* 1320 */ 352, 357, 173, 271, 130, 9, 316, 559, 197, 90,
- /* 1330 */ 547, 131, 129, 15, 199, 551, 564, 200, 567, 201,
- /* 1340 */ 139, 137, 582, 91, 16, 106, 140, 208, 574, 392,
- /* 1350 */ 396, 290, 148, 596,
+ /* 410 */ 213, 299, 225, 558, 506, 499, 405, 391, 214, 114,
+ /* 420 */ 251, 351, 256, 352, 178, 184, 324, 418, 353, 356,
+ /* 430 */ 357, 260, 395, 378, 156, 530, 405, 434, 440, 358,
+ /* 440 */ 184, 535, 243, 353, 356, 357, 427, 235, 423, 35,
+ /* 450 */ 545, 20, 399, 2, 358, 61, 60, 304, 444, 445,
+ /* 460 */ 441, 441, 63, 63, 62, 62, 62, 62, 424, 64,
+ /* 470 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 213,
+ /* 480 */ 299, 406, 407, 184, 516, 503, 353, 356, 357, 204,
+ /* 490 */ 338, 456, 215, 324, 420, 337, 422, 358, 227, 324,
+ /* 500 */ 421, 406, 407, 195, 535, 335, 434, 440, 305, 451,
+ /* 510 */ 452, 580, 581, 591, 20, 423, 42, 329, 451, 452,
+ /* 520 */ 162, 423, 35, 424, 61, 60, 304, 444, 445, 441,
+ /* 530 */ 441, 63, 63, 62, 62, 62, 62, 424, 64, 64,
+ /* 540 */ 64, 64, 65, 65, 66, 66, 66, 67, 213, 299,
+ /* 550 */ 324, 495, 465, 263, 424, 340, 218, 160, 154, 324,
+ /* 560 */ 343, 379, 448, 342, 466, 324, 163, 161, 461, 435,
+ /* 570 */ 436, 214, 423, 28, 21, 434, 440, 467, 427, 507,
+ /* 580 */ 214, 423, 50, 375, 408, 409, 410, 423, 50, 508,
+ /* 590 */ 438, 439, 424, 61, 60, 304, 444, 445, 441, 441,
+ /* 600 */ 63, 63, 62, 62, 62, 62, 347, 64, 64, 64,
+ /* 610 */ 64, 65, 65, 66, 66, 66, 67, 213, 299, 437,
+ /* 620 */ 281, 294, 555, 94, 458, 534, 171, 315, 423, 3,
+ /* 630 */ 1, 594, 298, 316, 405, 598, 906, 327, 906, 447,
+ /* 640 */ 447, 244, 212, 427, 434, 440, 123, 477, 327, 56,
+ /* 650 */ 447, 447, 174, 161, 327, 325, 447, 447, 284, 383,
+ /* 660 */ 282, 299, 61, 60, 304, 444, 445, 441, 441, 63,
+ /* 670 */ 63, 62, 62, 62, 62, 595, 64, 64, 64, 64,
+ /* 680 */ 65, 65, 66, 66, 66, 67, 213, 434, 440, 551,
+ /* 690 */ 368, 551, 124, 327, 478, 447, 447, 483, 557, 406,
+ /* 700 */ 407, 265, 302, 483, 299, 61, 60, 304, 444, 445,
+ /* 710 */ 441, 441, 63, 63, 62, 62, 62, 62, 405, 64,
+ /* 720 */ 64, 64, 64, 65, 65, 66, 66, 66, 67, 213,
+ /* 730 */ 434, 440, 327, 404, 447, 447, 219, 271, 839, 269,
+ /* 740 */ 283, 267, 247, 180, 181, 182, 483, 299, 61, 71,
+ /* 750 */ 304, 444, 445, 441, 441, 63, 63, 62, 62, 62,
+ /* 760 */ 62, 159, 64, 64, 64, 64, 65, 65, 66, 66,
+ /* 770 */ 66, 67, 213, 434, 440, 494, 371, 211, 571, 231,
+ /* 780 */ 271, 374, 346, 406, 407, 249, 478, 259, 271, 259,
+ /* 790 */ 299, 380, 60, 304, 444, 445, 441, 441, 63, 63,
+ /* 800 */ 62, 62, 62, 62, 349, 64, 64, 64, 64, 65,
+ /* 810 */ 65, 66, 66, 66, 67, 213, 434, 440, 405, 23,
+ /* 820 */ 405, 572, 311, 405, 312, 115, 487, 271, 259, 573,
+ /* 830 */ 5, 422, 19, 478, 145, 421, 304, 444, 445, 441,
+ /* 840 */ 441, 63, 63, 62, 62, 62, 62, 324, 64, 64,
+ /* 850 */ 64, 64, 65, 65, 66, 66, 66, 67, 213, 73,
+ /* 860 */ 331, 430, 4, 313, 271, 457, 303, 271, 228, 423,
+ /* 870 */ 29, 324, 361, 324, 328, 73, 331, 77, 4, 79,
+ /* 880 */ 324, 345, 303, 406, 407, 406, 407, 369, 406, 407,
+ /* 890 */ 328, 333, 336, 423, 24, 423, 33, 324, 378, 179,
+ /* 900 */ 159, 460, 423, 54, 324, 229, 324, 333, 287, 479,
+ /* 910 */ 179, 480, 476, 487, 168, 318, 119, 460, 324, 423,
+ /* 920 */ 53, 76, 75, 469, 199, 478, 423, 99, 423, 97,
+ /* 930 */ 74, 322, 323, 454, 454, 429, 473, 76, 75, 493,
+ /* 940 */ 423, 102, 390, 474, 324, 365, 74, 322, 323, 73,
+ /* 950 */ 331, 429, 4, 211, 301, 324, 303, 324, 424, 260,
+ /* 960 */ 324, 211, 157, 230, 328, 301, 423, 103, 431, 431,
+ /* 970 */ 431, 432, 433, 11, 314, 389, 186, 423, 108, 423,
+ /* 980 */ 110, 333, 423, 16, 431, 431, 431, 432, 433, 11,
+ /* 990 */ 326, 460, 189, 165, 197, 324, 424, 596, 232, 233,
+ /* 1000 */ 234, 105, 449, 148, 22, 324, 482, 635, 324, 486,
+ /* 1010 */ 424, 76, 75, 485, 208, 176, 289, 423, 100, 488,
+ /* 1020 */ 74, 322, 323, 290, 324, 429, 424, 423, 34, 324,
+ /* 1030 */ 423, 98, 324, 18, 324, 206, 597, 560, 511, 512,
+ /* 1040 */ 257, 205, 324, 519, 207, 324, 423, 25, 324, 518,
+ /* 1050 */ 324, 423, 55, 324, 423, 111, 423, 112, 431, 431,
+ /* 1060 */ 431, 432, 433, 11, 423, 113, 442, 423, 26, 324,
+ /* 1070 */ 423, 37, 423, 38, 258, 423, 27, 324, 524, 324,
+ /* 1080 */ 521, 520, 8, 526, 324, 183, 324, 386, 286, 276,
+ /* 1090 */ 324, 423, 39, 300, 85, 324, 525, 324, 211, 423,
+ /* 1100 */ 40, 423, 41, 324, 537, 324, 423, 43, 423, 44,
+ /* 1110 */ 264, 252, 423, 45, 262, 324, 183, 423, 30, 423,
+ /* 1120 */ 31, 324, 253, 392, 266, 423, 46, 423, 47, 324,
+ /* 1130 */ 360, 324, 183, 324, 556, 324, 183, 423, 48, 564,
+ /* 1140 */ 565, 176, 92, 423, 49, 268, 576, 593, 92, 297,
+ /* 1150 */ 270, 423, 32, 423, 10, 423, 51, 423, 52, 192,
+ /* 1160 */ 275, 373, 147, 376, 377, 278, 279, 428, 280, 568,
+ /* 1170 */ 578, 288, 291, 292, 590, 453, 332, 414, 237, 455,
+ /* 1180 */ 472, 475, 254, 245, 517, 355, 563, 166, 403, 575,
+ /* 1190 */ 411, 528, 412, 413, 531, 285, 7, 387, 85, 321,
+ /* 1200 */ 425, 527, 341, 529, 84, 339, 58, 173, 80, 216,
+ /* 1210 */ 470, 121, 308, 86, 344, 350, 125, 223, 514, 362,
+ /* 1220 */ 187, 504, 509, 546, 255, 222, 515, 513, 238, 224,
+ /* 1230 */ 239, 510, 240, 538, 241, 295, 426, 539, 540, 532,
+ /* 1240 */ 188, 190, 296, 364, 246, 191, 484, 490, 248, 548,
+ /* 1250 */ 366, 193, 117, 250, 89, 491, 372, 559, 196, 133,
+ /* 1260 */ 384, 385, 134, 135, 566, 317, 136, 137, 587, 588,
+ /* 1270 */ 592, 139, 401, 101, 221, 574, 104, 143, 589, 142,
+ /* 1280 */ 415, 636, 637, 169, 446, 170, 443, 72, 144, 273,
+ /* 1290 */ 450, 549, 459, 462, 158, 172, 463, 464, 468, 6,
+ /* 1300 */ 13, 82, 12, 481, 122, 164, 177, 497, 93, 498,
+ /* 1310 */ 489, 220, 87, 116, 126, 185, 261, 127, 96, 88,
+ /* 1320 */ 128, 253, 107, 363, 146, 547, 129, 354, 359, 194,
+ /* 1330 */ 367, 176, 274, 130, 118, 554, 131, 550, 9, 319,
+ /* 1340 */ 562, 132, 90, 198, 14, 200, 567, 202, 201, 570,
+ /* 1350 */ 138, 140, 141, 209, 15, 106, 585, 577, 293, 91,
+ /* 1360 */ 398, 394, 149, 599,
};
static const YYCODETYPE yy_lookahead[] = {
/* 0 */ 16, 140, 141, 142, 143, 21, 23, 23, 69, 70,
- /* 10 */ 71, 72, 110, 74, 75, 76, 77, 78, 79, 80,
+ /* 10 */ 71, 72, 148, 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 */ 58, 162, 163, 164, 60, 61, 62, 63, 64, 65,
/* 50 */ 66, 67, 68, 69, 70, 71, 72, 148, 74, 75,
/* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 70 */ 88, 88, 88, 84, 92, 22, 219, 220, 221, 222,
+ /* 70 */ 88, 88, 88, 209, 92, 22, 218, 219, 220, 221,
/* 80 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 90 */ 84, 219, 183, 221, 222, 42, 43, 78, 79, 46,
+ /* 90 */ 84, 218, 183, 220, 221, 42, 43, 78, 79, 46,
/* 100 */ 78, 79, 80, 81, 82, 83, 84, 125, 126, 127,
- /* 110 */ 170, 239, 16, 60, 61, 62, 63, 64, 65, 66,
+ /* 110 */ 110, 238, 16, 60, 61, 62, 63, 64, 65, 66,
/* 120 */ 67, 68, 69, 70, 71, 72, 148, 74, 75, 76,
/* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43,
- /* 140 */ 44, 80, 81, 82, 83, 84, 23, 148, 170, 171,
- /* 150 */ 19, 83, 84, 156, 23, 170, 60, 61, 62, 63,
- /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 19,
+ /* 140 */ 44, 144, 145, 162, 19, 20, 149, 22, 170, 171,
+ /* 150 */ 19, 83, 84, 156, 23, 148, 60, 61, 62, 63,
+ /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 84,
/* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 180 */ 84, 16, 183, 148, 151, 148, 21, 190, 148, 58,
- /* 190 */ 169, 213, 157, 158, 186, 187, 218, 23, 177, 202,
- /* 200 */ 203, 78, 79, 166, 167, 208, 161, 42, 43, 78,
- /* 210 */ 79, 88, 89, 177, 178, 170, 181, 182, 68, 88,
- /* 220 */ 184, 98, 99, 92, 16, 60, 61, 62, 63, 64,
- /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 22, 74,
+ /* 180 */ 84, 16, 201, 148, 59, 148, 21, 190, 12, 58,
+ /* 190 */ 212, 170, 157, 158, 30, 217, 189, 23, 148, 218,
+ /* 200 */ 24, 220, 221, 166, 167, 177, 178, 42, 43, 78,
+ /* 210 */ 79, 214, 184, 37, 50, 39, 181, 182, 148, 88,
+ /* 220 */ 170, 171, 170, 92, 16, 60, 61, 62, 63, 64,
+ /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 241, 74,
/* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 250 */ 42, 43, 78, 0, 1, 2, 125, 126, 127, 226,
- /* 260 */ 11, 162, 88, 89, 231, 228, 229, 16, 60, 61,
+ /* 250 */ 42, 43, 78, 0, 1, 2, 125, 126, 127, 189,
+ /* 260 */ 11, 211, 88, 89, 227, 228, 102, 16, 60, 61,
/* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
/* 280 */ 72, 148, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 290 */ 82, 83, 84, 42, 43, 186, 187, 16, 49, 148,
- /* 300 */ 201, 49, 18, 170, 171, 154, 142, 143, 157, 158,
- /* 310 */ 182, 60, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 320 */ 69, 70, 71, 72, 91, 74, 75, 76, 77, 78,
- /* 330 */ 79, 80, 81, 82, 83, 84, 168, 169, 122, 55,
- /* 340 */ 132, 16, 16, 110, 16, 177, 20, 20, 99, 100,
- /* 350 */ 101, 99, 100, 101, 80, 12, 223, 124, 148, 110,
- /* 360 */ 182, 148, 110, 23, 19, 84, 21, 24, 42, 43,
- /* 370 */ 148, 90, 91, 92, 93, 94, 95, 96, 94, 166,
- /* 380 */ 37, 107, 39, 132, 103, 111, 60, 61, 62, 63,
- /* 390 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 189,
+ /* 290 */ 82, 83, 84, 42, 43, 23, 182, 16, 49, 186,
+ /* 300 */ 187, 49, 182, 170, 171, 156, 80, 81, 82, 83,
+ /* 310 */ 84, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ /* 320 */ 69, 70, 71, 72, 22, 74, 75, 76, 77, 78,
+ /* 330 */ 79, 80, 81, 82, 83, 84, 168, 169, 148, 190,
+ /* 340 */ 132, 148, 16, 148, 16, 177, 20, 191, 99, 100,
+ /* 350 */ 101, 99, 100, 101, 25, 222, 166, 22, 29, 110,
+ /* 360 */ 88, 89, 110, 214, 218, 84, 220, 221, 42, 43,
+ /* 370 */ 41, 90, 91, 92, 93, 94, 95, 96, 183, 21,
+ /* 380 */ 231, 23, 189, 132, 103, 236, 60, 61, 62, 63,
+ /* 390 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 97,
/* 400 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
- /* 410 */ 84, 16, 84, 156, 92, 20, 23, 92, 134, 91,
- /* 420 */ 92, 93, 94, 95, 96, 103, 148, 22, 88, 89,
- /* 430 */ 148, 103, 210, 106, 156, 108, 109, 42, 43, 144,
- /* 440 */ 145, 228, 229, 219, 149, 221, 222, 190, 170, 171,
- /* 450 */ 240, 156, 170, 171, 162, 60, 61, 62, 63, 64,
+ /* 410 */ 84, 16, 84, 186, 187, 20, 23, 227, 228, 91,
+ /* 420 */ 92, 93, 94, 95, 96, 90, 148, 169, 93, 94,
+ /* 430 */ 95, 103, 239, 148, 156, 177, 23, 42, 43, 104,
+ /* 440 */ 90, 148, 148, 93, 94, 95, 88, 154, 170, 171,
+ /* 450 */ 157, 158, 142, 143, 104, 60, 61, 62, 63, 64,
/* 460 */ 65, 66, 67, 68, 69, 70, 71, 72, 190, 74,
/* 470 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 480 */ 16, 88, 89, 90, 20, 190, 93, 94, 95, 23,
- /* 490 */ 131, 213, 133, 201, 212, 90, 218, 104, 93, 94,
- /* 500 */ 95, 42, 43, 7, 8, 9, 42, 43, 191, 104,
- /* 510 */ 215, 219, 159, 221, 222, 162, 163, 164, 156, 165,
- /* 520 */ 166, 167, 63, 64, 60, 61, 62, 63, 64, 65,
- /* 530 */ 66, 67, 68, 69, 70, 71, 72, 242, 74, 75,
+ /* 480 */ 16, 88, 89, 90, 20, 161, 93, 94, 95, 156,
+ /* 490 */ 212, 78, 79, 148, 170, 217, 107, 104, 213, 148,
+ /* 500 */ 111, 88, 89, 156, 148, 187, 42, 43, 165, 166,
+ /* 510 */ 167, 98, 99, 157, 158, 170, 171, 165, 166, 167,
+ /* 520 */ 156, 170, 171, 190, 60, 61, 62, 63, 64, 65,
+ /* 530 */ 66, 67, 68, 69, 70, 71, 72, 190, 74, 75,
/* 540 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 550 */ 148, 92, 190, 20, 88, 89, 148, 90, 156, 148,
- /* 560 */ 93, 94, 95, 20, 187, 148, 19, 20, 148, 22,
- /* 570 */ 19, 104, 170, 171, 23, 42, 43, 148, 170, 171,
- /* 580 */ 114, 170, 171, 229, 99, 100, 101, 170, 171, 148,
- /* 590 */ 170, 171, 190, 60, 61, 62, 63, 64, 65, 66,
- /* 600 */ 67, 68, 69, 70, 71, 72, 59, 74, 75, 76,
- /* 610 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 211,
- /* 620 */ 212, 12, 148, 21, 213, 165, 166, 167, 21, 148,
- /* 630 */ 23, 148, 148, 24, 217, 19, 20, 217, 22, 88,
- /* 640 */ 89, 157, 158, 214, 42, 43, 37, 148, 39, 106,
- /* 650 */ 148, 108, 109, 170, 171, 20, 146, 183, 49, 156,
- /* 660 */ 14, 16, 60, 61, 62, 63, 64, 65, 66, 67,
+ /* 550 */ 148, 20, 12, 20, 190, 210, 211, 148, 156, 148,
+ /* 560 */ 148, 214, 20, 212, 24, 148, 202, 203, 20, 42,
+ /* 570 */ 43, 228, 170, 171, 19, 42, 43, 37, 23, 39,
+ /* 580 */ 228, 170, 171, 236, 7, 8, 9, 170, 171, 49,
+ /* 590 */ 63, 64, 190, 60, 61, 62, 63, 64, 65, 66,
+ /* 600 */ 67, 68, 69, 70, 71, 72, 148, 74, 75, 76,
+ /* 610 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 92,
+ /* 620 */ 14, 159, 18, 21, 162, 163, 164, 216, 170, 171,
+ /* 630 */ 19, 244, 245, 216, 23, 19, 20, 106, 22, 108,
+ /* 640 */ 109, 148, 193, 88, 42, 43, 20, 204, 106, 200,
+ /* 650 */ 108, 109, 202, 203, 106, 148, 108, 109, 52, 55,
+ /* 660 */ 54, 16, 60, 61, 62, 63, 64, 65, 66, 67,
/* 670 */ 68, 69, 70, 71, 72, 59, 74, 75, 76, 77,
- /* 680 */ 78, 79, 80, 81, 82, 83, 84, 42, 43, 229,
- /* 690 */ 99, 100, 101, 190, 106, 88, 108, 109, 52, 14,
- /* 700 */ 54, 148, 156, 162, 16, 60, 61, 62, 63, 64,
- /* 710 */ 65, 66, 67, 68, 69, 70, 71, 72, 215, 74,
+ /* 680 */ 78, 79, 80, 81, 82, 83, 84, 42, 43, 99,
+ /* 690 */ 100, 101, 20, 106, 22, 108, 109, 162, 94, 88,
+ /* 700 */ 89, 14, 151, 162, 16, 60, 61, 62, 63, 64,
+ /* 710 */ 65, 66, 67, 68, 69, 70, 71, 72, 23, 74,
/* 720 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
- /* 730 */ 42, 43, 245, 246, 148, 148, 190, 52, 193, 54,
- /* 740 */ 237, 106, 201, 108, 109, 200, 148, 16, 60, 61,
+ /* 730 */ 42, 43, 106, 148, 108, 109, 201, 148, 134, 52,
+ /* 740 */ 134, 54, 201, 99, 100, 101, 162, 16, 60, 61,
/* 750 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
- /* 760 */ 72, 215, 74, 75, 76, 77, 78, 79, 80, 81,
- /* 770 */ 82, 83, 84, 42, 43, 25, 189, 22, 232, 29,
- /* 780 */ 134, 183, 16, 237, 202, 203, 148, 148, 192, 148,
- /* 790 */ 16, 41, 61, 62, 63, 64, 65, 66, 67, 68,
- /* 800 */ 69, 70, 71, 72, 148, 74, 75, 76, 77, 78,
+ /* 760 */ 72, 89, 74, 75, 76, 77, 78, 79, 80, 81,
+ /* 770 */ 82, 83, 84, 42, 43, 80, 225, 110, 189, 146,
+ /* 780 */ 148, 230, 16, 88, 89, 201, 114, 148, 148, 148,
+ /* 790 */ 16, 124, 61, 62, 63, 64, 65, 66, 67, 68,
+ /* 800 */ 69, 70, 71, 72, 80, 74, 75, 76, 77, 78,
/* 810 */ 79, 80, 81, 82, 83, 84, 42, 43, 23, 19,
- /* 820 */ 23, 183, 148, 23, 148, 148, 170, 171, 189, 19,
- /* 830 */ 189, 107, 148, 23, 148, 111, 62, 63, 64, 65,
+ /* 820 */ 23, 189, 183, 23, 183, 148, 148, 148, 148, 189,
+ /* 830 */ 192, 107, 19, 22, 21, 111, 62, 63, 64, 65,
/* 840 */ 66, 67, 68, 69, 70, 71, 72, 148, 74, 75,
/* 850 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16,
- /* 860 */ 17, 148, 19, 189, 148, 189, 23, 148, 113, 170,
- /* 870 */ 171, 148, 16, 148, 31, 16, 17, 80, 19, 162,
- /* 880 */ 148, 115, 23, 88, 89, 88, 89, 210, 88, 89,
- /* 890 */ 31, 48, 148, 170, 171, 170, 171, 148, 88, 43,
- /* 900 */ 214, 58, 170, 171, 148, 189, 148, 48, 189, 114,
- /* 910 */ 19, 148, 243, 244, 170, 171, 148, 58, 148, 170,
- /* 920 */ 171, 78, 79, 210, 148, 30, 170, 171, 170, 171,
- /* 930 */ 87, 88, 89, 170, 171, 92, 148, 78, 79, 80,
- /* 940 */ 170, 171, 125, 126, 148, 50, 87, 88, 89, 16,
- /* 950 */ 17, 92, 19, 110, 98, 148, 23, 148, 156, 103,
- /* 960 */ 148, 110, 156, 22, 31, 189, 170, 171, 125, 126,
- /* 970 */ 127, 128, 129, 130, 20, 124, 156, 170, 171, 170,
+ /* 860 */ 17, 148, 19, 183, 148, 162, 23, 148, 189, 170,
+ /* 870 */ 171, 148, 16, 148, 31, 16, 17, 131, 19, 133,
+ /* 880 */ 148, 115, 23, 88, 89, 88, 89, 209, 88, 89,
+ /* 890 */ 31, 48, 148, 170, 171, 170, 171, 148, 148, 43,
+ /* 900 */ 89, 58, 170, 171, 148, 189, 148, 48, 189, 114,
+ /* 910 */ 43, 114, 22, 148, 19, 242, 243, 58, 148, 170,
+ /* 920 */ 171, 78, 79, 148, 156, 114, 170, 171, 170, 171,
+ /* 930 */ 87, 88, 89, 125, 126, 92, 27, 78, 79, 80,
+ /* 940 */ 170, 171, 91, 34, 148, 233, 87, 88, 89, 16,
+ /* 950 */ 17, 92, 19, 110, 98, 148, 23, 148, 190, 103,
+ /* 960 */ 148, 110, 156, 213, 31, 98, 170, 171, 125, 126,
+ /* 970 */ 127, 128, 129, 130, 209, 124, 156, 170, 171, 170,
/* 980 */ 171, 48, 170, 171, 125, 126, 127, 128, 129, 130,
- /* 990 */ 204, 58, 190, 5, 148, 148, 190, 102, 10, 11,
- /* 1000 */ 12, 13, 148, 112, 22, 148, 148, 20, 148, 22,
- /* 1010 */ 190, 78, 79, 59, 26, 43, 28, 170, 171, 148,
- /* 1020 */ 87, 88, 89, 35, 148, 92, 148, 170, 171, 148,
- /* 1030 */ 170, 171, 148, 27, 148, 47, 148, 49, 97, 234,
- /* 1040 */ 34, 53, 148, 179, 56, 148, 170, 171, 170, 171,
+ /* 990 */ 16, 58, 156, 5, 22, 148, 190, 20, 10, 11,
+ /* 1000 */ 12, 13, 20, 113, 22, 148, 148, 112, 148, 148,
+ /* 1010 */ 190, 78, 79, 20, 26, 22, 28, 170, 171, 148,
+ /* 1020 */ 87, 88, 89, 35, 148, 92, 190, 170, 171, 148,
+ /* 1030 */ 170, 171, 148, 19, 148, 47, 59, 49, 7, 8,
+ /* 1040 */ 148, 53, 148, 179, 56, 148, 170, 171, 148, 148,
/* 1050 */ 148, 170, 171, 148, 170, 171, 170, 171, 125, 126,
- /* 1060 */ 127, 128, 129, 130, 170, 171, 179, 170, 171, 148,
- /* 1070 */ 98, 89, 170, 171, 148, 170, 171, 148, 20, 148,
- /* 1080 */ 22, 20, 148, 22, 148, 179, 148, 99, 100, 101,
- /* 1090 */ 148, 170, 171, 105, 148, 148, 114, 148, 110, 170,
- /* 1100 */ 171, 170, 171, 148, 170, 171, 170, 171, 170, 171,
- /* 1110 */ 7, 8, 170, 171, 20, 148, 22, 170, 171, 170,
- /* 1120 */ 171, 148, 20, 135, 22, 170, 171, 148, 148, 91,
- /* 1130 */ 92, 20, 20, 22, 22, 150, 233, 170, 171, 20,
- /* 1140 */ 20, 22, 22, 170, 171, 20, 148, 22, 148, 170,
- /* 1150 */ 171, 148, 148, 148, 192, 148, 148, 148, 148, 148,
- /* 1160 */ 148, 148, 148, 148, 148, 148, 173, 230, 194, 230,
- /* 1170 */ 225, 205, 173, 178, 173, 173, 195, 6, 147, 195,
- /* 1180 */ 162, 162, 205, 162, 147, 22, 147, 147, 205, 155,
- /* 1190 */ 122, 195, 119, 173, 120, 118, 174, 121, 131, 224,
- /* 1200 */ 112, 153, 153, 98, 117, 98, 40, 172, 172, 19,
- /* 1210 */ 97, 84, 15, 190, 172, 152, 172, 174, 227, 227,
- /* 1220 */ 196, 180, 197, 172, 198, 175, 199, 180, 172, 172,
- /* 1230 */ 175, 153, 152, 152, 206, 153, 207, 207, 206, 153,
- /* 1240 */ 38, 131, 153, 152, 60, 153, 19, 185, 195, 185,
- /* 1250 */ 153, 15, 153, 188, 188, 195, 185, 188, 188, 33,
- /* 1260 */ 138, 153, 216, 1, 160, 20, 176, 153, 235, 176,
- /* 1270 */ 216, 112, 112, 112, 112, 92, 107, 19, 11, 20,
- /* 1280 */ 20, 236, 19, 19, 116, 20, 116, 114, 22, 20,
- /* 1290 */ 238, 20, 22, 19, 22, 116, 115, 238, 20, 112,
- /* 1300 */ 20, 20, 19, 19, 19, 32, 20, 19, 19, 96,
- /* 1310 */ 103, 16, 44, 241, 17, 21, 98, 98, 36, 244,
- /* 1320 */ 44, 44, 22, 134, 19, 5, 247, 1, 123, 68,
- /* 1330 */ 51, 102, 45, 19, 113, 45, 1, 14, 17, 117,
- /* 1340 */ 102, 113, 20, 68, 19, 14, 123, 136, 124, 57,
- /* 1350 */ 3, 137, 19, 4,
-};
-#define YY_SHIFT_USE_DFLT (-99)
-#define YY_SHIFT_MAX 396
+ /* 1060 */ 127, 128, 129, 130, 170, 171, 92, 170, 171, 148,
+ /* 1070 */ 170, 171, 170, 171, 148, 170, 171, 148, 179, 148,
+ /* 1080 */ 91, 92, 68, 20, 148, 22, 148, 99, 100, 101,
+ /* 1090 */ 148, 170, 171, 105, 122, 148, 179, 148, 110, 170,
+ /* 1100 */ 171, 170, 171, 148, 148, 148, 170, 171, 170, 171,
+ /* 1110 */ 148, 92, 170, 171, 20, 148, 22, 170, 171, 170,
+ /* 1120 */ 171, 148, 103, 135, 148, 170, 171, 170, 171, 148,
+ /* 1130 */ 20, 148, 22, 148, 20, 148, 22, 170, 171, 20,
+ /* 1140 */ 20, 22, 22, 170, 171, 148, 20, 20, 22, 22,
+ /* 1150 */ 148, 170, 171, 170, 171, 170, 171, 170, 171, 232,
+ /* 1160 */ 148, 148, 192, 148, 148, 148, 148, 162, 148, 148,
+ /* 1170 */ 148, 148, 148, 148, 148, 229, 224, 150, 194, 229,
+ /* 1180 */ 173, 173, 173, 205, 178, 174, 195, 6, 147, 195,
+ /* 1190 */ 147, 162, 147, 147, 162, 205, 22, 205, 122, 155,
+ /* 1200 */ 190, 173, 119, 173, 120, 118, 121, 112, 131, 223,
+ /* 1210 */ 153, 153, 40, 98, 117, 98, 19, 84, 97, 15,
+ /* 1220 */ 152, 172, 172, 153, 172, 226, 172, 174, 195, 226,
+ /* 1230 */ 196, 180, 197, 172, 198, 175, 199, 172, 172, 180,
+ /* 1240 */ 152, 152, 175, 153, 206, 153, 207, 207, 206, 153,
+ /* 1250 */ 38, 152, 60, 206, 131, 207, 153, 185, 185, 19,
+ /* 1260 */ 153, 15, 188, 188, 195, 153, 188, 188, 33, 153,
+ /* 1270 */ 138, 185, 1, 160, 176, 195, 176, 215, 153, 215,
+ /* 1280 */ 20, 112, 112, 112, 107, 112, 92, 19, 19, 234,
+ /* 1290 */ 20, 235, 20, 11, 19, 22, 20, 20, 20, 116,
+ /* 1300 */ 116, 22, 22, 114, 19, 112, 116, 20, 237, 20,
+ /* 1310 */ 115, 44, 19, 32, 19, 96, 20, 19, 237, 19,
+ /* 1320 */ 19, 103, 240, 16, 21, 17, 98, 44, 44, 98,
+ /* 1330 */ 36, 22, 134, 45, 243, 45, 19, 51, 5, 246,
+ /* 1340 */ 1, 102, 68, 123, 19, 113, 1, 117, 14, 17,
+ /* 1350 */ 113, 102, 123, 136, 19, 14, 20, 124, 137, 68,
+ /* 1360 */ 3, 57, 19, 4,
+};
+#define YY_SHIFT_USE_DFLT (-62)
+#define YY_SHIFT_MAX 398
static const short yy_shift_ofst[] = {
- /* 0 */ 23, 843, 988, -16, 843, 933, 933, 393, 123, 252,
- /* 10 */ -98, 96, 933, 933, 933, 933, 933, -45, 249, 174,
- /* 20 */ 340, -17, 19, 19, 53, 165, 208, 251, 326, 395,
+ /* 0 */ 23, 843, 988, -16, 843, 933, 933, 393, 413, 252,
+ /* 10 */ 96, 933, 933, 933, 933, 933, -45, 249, 174, 272,
+ /* 20 */ -17, 19, 19, 0, 53, 165, 208, 251, 326, 395,
/* 30 */ 464, 533, 602, 645, 688, 645, 645, 645, 645, 645,
/* 40 */ 645, 645, 645, 645, 645, 645, 645, 645, 645, 645,
/* 50 */ 645, 645, 645, 731, 774, 774, 859, 933, 933, 933,
/* 60 */ 933, 933, 933, 933, 933, 933, 933, 933, 933, 933,
/* 70 */ 933, 933, 933, 933, 933, 933, 933, 933, 933, 933,
/* 80 */ 933, 933, 933, 933, 933, 933, 933, 933, 933, 933,
/* 90 */ 933, 933, 933, 933, 933, 933, 933, -61, -61, 6,
- /* 100 */ 6, 281, 22, 61, 856, 284, 340, 340, 68, -17,
- /* 110 */ -11, -99, -99, -99, 131, 328, 609, 609, 547, 616,
- /* 120 */ 253, 607, 340, 607, 340, 340, 340, 340, 340, 340,
- /* 130 */ 340, 340, 340, 340, 340, 340, 340, 340, 340, 340,
- /* 140 */ 340, 233, 851, -98, -98, -98, -99, -99, -99, -18,
- /* 150 */ -18, 405, 467, 327, 551, 543, 635, 343, 466, 795,
- /* 160 */ 800, 797, 496, 340, 340, 274, 340, 340, 810, 340,
- /* 170 */ 340, 982, 340, 340, 340, 588, 982, 340, 340, 895,
- /* 180 */ 895, 895, 340, 340, 340, 588, 340, 340, 588, 340,
- /* 190 */ 750, 485, 340, 340, 588, 340, 340, 340, 588, 340,
- /* 200 */ 340, 340, 588, 588, 340, 340, 340, 340, 340, 345,
- /* 210 */ 724, 755, -17, 817, 817, 359, 1006, 1006, 766, 1006,
- /* 220 */ 972, 1006, -17, 1006, -17, 941, 216, 766, 766, 216,
- /* 230 */ 1171, 1171, 1171, 1171, 1163, -98, 1068, 1073, 1074, 1077,
- /* 240 */ 1076, 1067, 1088, 1088, 1105, 1087, 1105, 1087, 1107, 1107,
- /* 250 */ 1166, 1107, 1113, 1107, 1190, 1127, 1127, 1166, 1107, 1107,
- /* 260 */ 1107, 1190, 1197, 1088, 1197, 1088, 1197, 1088, 1088, 1202,
- /* 270 */ 1110, 1197, 1088, 1184, 1184, 1227, 1068, 1088, 1236, 1236,
- /* 280 */ 1236, 1236, 1068, 1184, 1227, 1088, 1226, 1226, 1088, 1088,
- /* 290 */ 1122, -99, -99, -99, -99, -99, 459, 646, 591, 685,
- /* 300 */ 891, 325, 987, 1058, 322, 1103, 1038, 1061, 1094, 1102,
- /* 310 */ 1111, 1112, 1119, 1120, 150, 1125, 954, 1262, 1245, 1159,
- /* 320 */ 1160, 1161, 1162, 1183, 1169, 1258, 1259, 1260, 1263, 1267,
- /* 330 */ 1264, 1265, 1266, 1269, 1271, 1270, 1168, 1272, 1170, 1270,
- /* 340 */ 1173, 1274, 1179, 1181, 1278, 1187, 1280, 1281, 1273, 1268,
- /* 350 */ 1283, 1276, 1284, 1286, 1285, 1288, 1277, 1289, 1213, 1207,
- /* 360 */ 1295, 1297, 1294, 1218, 1282, 1279, 1287, 1300, 1290, 1189,
- /* 370 */ 1219, 1305, 1320, 1326, 1229, 1261, 1275, 1205, 1314, 1221,
- /* 380 */ 1335, 1323, 1222, 1321, 1228, 1238, 1223, 1325, 1224, 1322,
- /* 390 */ 1331, 1292, 1211, 1214, 1333, 1347, 1349,
-};
-#define YY_REDUCE_USE_DFLT (-144)
-#define YY_REDUCE_MAX 295
+ /* 100 */ 6, 281, 22, 226, 856, 604, 272, 272, 68, -17,
+ /* 110 */ 85, -62, -62, -62, 131, 328, 540, 540, 125, 616,
+ /* 120 */ 253, 358, 272, 358, 358, 272, 272, 272, 272, 272,
+ /* 130 */ 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
+ /* 140 */ 272, 272, 851, 667, 0, 0, 0, -62, -62, -62,
+ /* 150 */ -18, -18, 335, 350, 531, 611, 542, 548, 176, 795,
+ /* 160 */ 797, 800, 626, 672, 695, 577, 272, 272, 724, 272,
+ /* 170 */ 272, 555, 272, 272, 811, 272, 272, 272, 272, 272,
+ /* 180 */ 164, 164, 164, 272, 272, 272, 587, 272, 272, 587,
+ /* 190 */ 272, 329, 590, 272, 272, 587, 272, 272, 272, 587,
+ /* 200 */ 272, 272, 272, 587, 587, 272, 272, 272, 272, 272,
+ /* 210 */ 813, 389, 890, -17, 808, 808, 746, 909, 909, 766,
+ /* 220 */ 909, 867, 909, -17, 909, -17, 302, 972, 766, 766,
+ /* 230 */ 972, 1181, 1181, 1181, 1181, 1174, 0, 1076, 1083, 1084,
+ /* 240 */ 1087, 1085, 1077, 1095, 1095, 1115, 1097, 1115, 1097, 1115,
+ /* 250 */ 1097, 1117, 1117, 1172, 1117, 1121, 1117, 1197, 1133, 1133,
+ /* 260 */ 1172, 1117, 1117, 1117, 1197, 1204, 1095, 1204, 1095, 1204,
+ /* 270 */ 1095, 1095, 1212, 1123, 1204, 1095, 1192, 1192, 1240, 1076,
+ /* 280 */ 1095, 1246, 1246, 1246, 1246, 1076, 1192, 1240, 1095, 1235,
+ /* 290 */ 1235, 1095, 1095, 1132, -62, -62, -62, -62, -62, 527,
+ /* 300 */ 606, 644, 687, 895, 974, 982, 993, 1019, 1031, 989,
+ /* 310 */ 1063, 1094, 1110, 1114, 1119, 1120, 1126, 1014, 1127, 977,
+ /* 320 */ 1271, 1260, 1169, 1170, 1171, 1173, 1194, 1177, 1268, 1270,
+ /* 330 */ 1272, 1269, 1282, 1275, 1276, 1273, 1277, 1278, 1279, 1183,
+ /* 340 */ 1280, 1184, 1279, 1189, 1285, 1190, 1195, 1193, 1287, 1289,
+ /* 350 */ 1281, 1267, 1293, 1283, 1295, 1296, 1298, 1300, 1284, 1301,
+ /* 360 */ 1219, 1218, 1307, 1308, 1303, 1228, 1294, 1286, 1288, 1309,
+ /* 370 */ 1290, 1198, 1231, 1317, 1333, 1339, 1239, 1274, 1291, 1220,
+ /* 380 */ 1325, 1232, 1345, 1334, 1230, 1332, 1237, 1249, 1229, 1335,
+ /* 390 */ 1233, 1336, 1341, 1304, 1217, 1221, 1343, 1357, 1359,
+};
+#define YY_REDUCE_USE_DFLT (-143)
+#define YY_REDUCE_MAX 298
static const short yy_reduce_ofst[] = {
- /* 0 */ -139, 278, 295, 292, 402, -22, 408, 35, 37, 546,
- /* 10 */ -3, -128, 133, 282, 411, 417, 420, -143, 503, 213,
- /* 20 */ 151, 353, 354, 460, 224, 224, 224, 224, 224, 224,
- /* 30 */ 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
- /* 40 */ 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
- /* 50 */ 224, 224, 224, 224, 224, 224, 483, 656, 699, 723,
- /* 60 */ 725, 732, 744, 749, 756, 758, 763, 770, 796, 807,
- /* 70 */ 809, 812, 847, 857, 860, 876, 878, 881, 884, 886,
- /* 80 */ 894, 897, 902, 905, 921, 929, 931, 934, 936, 938,
- /* 90 */ 942, 947, 949, 955, 967, 973, 979, 224, 224, 224,
- /* 100 */ 224, 168, 224, 224, 36, 33, 210, 484, 224, -121,
- /* 110 */ 224, 224, 224, 224, 45, 21, 8, 109, 487, 487,
- /* 120 */ 164, 99, 222, 541, -91, -1, 474, 598, 587, 677,
- /* 130 */ 638, 429, 713, 639, 641, 674, 676, 716, 719, 686,
- /* 140 */ 776, 257, 362, 802, 806, 820, 545, 582, 669, -60,
- /* 150 */ -15, 128, 178, 317, 40, 317, 317, 377, 441, 481,
- /* 160 */ 499, 502, 510, 553, 586, 596, 502, 684, 717, 768,
- /* 170 */ 788, 786, 846, 854, 858, 317, 786, 871, 888, 864,
- /* 180 */ 887, 906, 926, 946, 980, 317, 998, 1000, 317, 1003,
- /* 190 */ 903, 805, 1004, 1005, 317, 1007, 1008, 1009, 317, 1010,
- /* 200 */ 1011, 1012, 317, 317, 1013, 1014, 1015, 1016, 1017, 985,
- /* 210 */ 962, 974, 1018, 937, 939, 945, 993, 999, 966, 1001,
- /* 220 */ 995, 1002, 1019, 1020, 1021, 1022, 981, 977, 983, 984,
- /* 230 */ 1031, 1037, 1039, 1040, 1034, 1023, 996, 1024, 1025, 1026,
- /* 240 */ 1027, 975, 1048, 1049, 1028, 1029, 1032, 1030, 1035, 1036,
- /* 250 */ 1041, 1042, 1043, 1044, 1050, 991, 992, 1047, 1051, 1056,
- /* 260 */ 1057, 1055, 1063, 1078, 1080, 1082, 1081, 1086, 1089, 1033,
- /* 270 */ 1045, 1091, 1092, 1062, 1064, 1046, 1053, 1097, 1065, 1066,
- /* 280 */ 1069, 1070, 1060, 1071, 1054, 1099, 1052, 1059, 1108, 1114,
- /* 290 */ 1072, 1104, 1090, 1093, 1075, 1079,
+ /* 0 */ -139, 278, -3, -19, 402, -22, 345, 35, 37, 149,
+ /* 10 */ -127, 133, 50, 351, 411, 417, -142, 347, 190, 293,
+ /* 20 */ 462, 343, 352, 364, 146, 146, 146, 146, 146, 146,
+ /* 30 */ 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
+ /* 40 */ 146, 146, 146, 146, 146, 146, 146, 146, 146, 146,
+ /* 50 */ 146, 146, 146, 146, 146, 146, 458, 699, 723, 725,
+ /* 60 */ 732, 749, 756, 758, 770, 796, 807, 809, 812, 847,
+ /* 70 */ 857, 860, 876, 881, 884, 886, 894, 897, 900, 902,
+ /* 80 */ 905, 921, 929, 931, 936, 938, 942, 947, 949, 955,
+ /* 90 */ 957, 967, 973, 981, 983, 985, 987, 146, 146, 146,
+ /* 100 */ 146, 168, 146, 146, 28, 551, 193, 356, 146, -121,
+ /* 110 */ 146, 146, 146, 146, 324, 258, 113, 227, 387, 387,
+ /* 120 */ 310, 535, -136, 541, 584, -91, 195, 639, 641, 7,
+ /* 130 */ 678, 680, 285, 765, 70, 589, 632, 640, 679, 716,
+ /* 140 */ 750, 719, 333, 768, 806, 820, 836, 449, 450, 673,
+ /* 150 */ 21, 52, 114, 120, 156, 294, 156, 156, 318, 409,
+ /* 160 */ 412, 493, 156, 443, 507, 633, 585, 677, 638, 507,
+ /* 170 */ 713, 703, 744, 775, 443, 858, 861, 871, 892, 901,
+ /* 180 */ 864, 899, 917, 926, 956, 962, 156, 976, 997, 156,
+ /* 190 */ 1002, 927, 712, 1012, 1013, 156, 1015, 1016, 1017, 156,
+ /* 200 */ 1018, 1020, 1021, 156, 156, 1022, 1023, 1024, 1025, 1026,
+ /* 210 */ 1027, 970, 984, 1005, 946, 950, 952, 1007, 1008, 978,
+ /* 220 */ 1009, 1006, 1028, 1029, 1030, 1032, 1011, 991, 990, 992,
+ /* 230 */ 994, 1041, 1043, 1045, 1046, 1044, 1010, 1033, 1034, 1035,
+ /* 240 */ 1036, 1037, 986, 1057, 1058, 1038, 1039, 1042, 1040, 1047,
+ /* 250 */ 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1060, 999, 1003,
+ /* 260 */ 1059, 1061, 1065, 1066, 1067, 1068, 1070, 1088, 1090, 1089,
+ /* 270 */ 1092, 1096, 1055, 1056, 1099, 1103, 1072, 1073, 1062, 1069,
+ /* 280 */ 1107, 1074, 1075, 1078, 1079, 1080, 1086, 1064, 1112, 1071,
+ /* 290 */ 1081, 1116, 1125, 1082, 1113, 1098, 1100, 1091, 1093,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 603, 832, 913, 719, 913, 832, 913, 913, 859, 913,
- /* 10 */ 723, 888, 830, 913, 913, 913, 913, 804, 913, 859,
- /* 20 */ 913, 635, 859, 859, 755, 913, 913, 913, 913, 913,
- /* 30 */ 913, 913, 913, 756, 913, 834, 829, 825, 827, 826,
- /* 40 */ 833, 757, 746, 753, 760, 735, 872, 762, 763, 769,
- /* 50 */ 770, 889, 887, 792, 791, 810, 913, 913, 913, 913,
- /* 60 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 70 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 80 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 90 */ 913, 913, 913, 913, 913, 913, 913, 794, 816, 793,
- /* 100 */ 803, 628, 795, 796, 688, 623, 913, 913, 797, 913,
- /* 110 */ 798, 811, 812, 813, 913, 913, 913, 913, 913, 913,
- /* 120 */ 603, 719, 913, 719, 913, 913, 913, 913, 913, 913,
- /* 130 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 140 */ 913, 913, 913, 913, 913, 913, 713, 723, 906, 913,
- /* 150 */ 913, 679, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 160 */ 913, 913, 611, 609, 913, 711, 913, 913, 637, 913,
- /* 170 */ 913, 721, 913, 913, 913, 726, 727, 913, 913, 913,
- /* 180 */ 913, 913, 913, 913, 913, 625, 913, 913, 700, 913,
- /* 190 */ 865, 913, 913, 913, 879, 913, 913, 913, 877, 913,
- /* 200 */ 913, 913, 702, 765, 845, 913, 892, 894, 913, 913,
- /* 210 */ 711, 720, 913, 913, 913, 828, 749, 749, 737, 749,
- /* 220 */ 658, 749, 913, 749, 913, 661, 759, 737, 737, 759,
- /* 230 */ 608, 608, 608, 608, 678, 913, 759, 750, 752, 742,
- /* 240 */ 754, 913, 728, 728, 736, 741, 736, 741, 690, 690,
- /* 250 */ 675, 690, 661, 690, 838, 842, 842, 675, 690, 690,
- /* 260 */ 690, 838, 620, 728, 620, 728, 620, 728, 728, 869,
- /* 270 */ 871, 620, 728, 692, 692, 771, 759, 728, 699, 699,
- /* 280 */ 699, 699, 759, 692, 771, 728, 891, 891, 728, 728,
- /* 290 */ 899, 645, 663, 663, 906, 911, 913, 913, 913, 913,
- /* 300 */ 778, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 310 */ 913, 913, 913, 913, 852, 913, 913, 913, 913, 783,
- /* 320 */ 779, 913, 780, 913, 705, 913, 913, 913, 913, 913,
- /* 330 */ 913, 913, 913, 913, 913, 831, 913, 743, 913, 751,
- /* 340 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 350 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 360 */ 913, 913, 913, 913, 913, 913, 867, 868, 913, 913,
- /* 370 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 380 */ 913, 913, 913, 913, 913, 913, 913, 913, 913, 913,
- /* 390 */ 913, 898, 913, 913, 901, 604, 913, 599, 601, 602,
- /* 400 */ 606, 607, 610, 632, 633, 634, 612, 613, 614, 615,
- /* 410 */ 616, 617, 618, 624, 626, 644, 646, 630, 648, 709,
- /* 420 */ 710, 775, 703, 704, 708, 631, 786, 777, 781, 782,
- /* 430 */ 784, 785, 799, 800, 802, 808, 815, 818, 801, 806,
- /* 440 */ 807, 809, 814, 817, 706, 707, 821, 638, 639, 642,
- /* 450 */ 643, 855, 857, 856, 858, 641, 640, 787, 790, 823,
- /* 460 */ 824, 880, 881, 882, 883, 884, 819, 729, 822, 805,
- /* 470 */ 744, 747, 748, 745, 712, 722, 731, 732, 733, 734,
- /* 480 */ 717, 718, 724, 740, 773, 774, 738, 739, 725, 714,
- /* 490 */ 715, 716, 820, 776, 788, 789, 649, 650, 783, 651,
- /* 500 */ 652, 653, 691, 694, 695, 696, 654, 673, 676, 677,
- /* 510 */ 655, 662, 656, 657, 664, 665, 666, 669, 670, 671,
- /* 520 */ 672, 667, 668, 839, 840, 843, 841, 659, 660, 674,
- /* 530 */ 647, 636, 629, 680, 683, 684, 685, 686, 687, 689,
- /* 540 */ 681, 682, 627, 619, 621, 730, 861, 870, 866, 862,
- /* 550 */ 863, 864, 622, 835, 836, 693, 767, 768, 860, 873,
- /* 560 */ 875, 772, 876, 878, 874, 903, 697, 698, 701, 844,
- /* 570 */ 885, 758, 761, 764, 766, 846, 847, 848, 849, 850,
- /* 580 */ 853, 854, 851, 886, 890, 893, 895, 896, 897, 900,
- /* 590 */ 902, 907, 908, 909, 912, 910, 605, 600,
+ /* 0 */ 606, 834, 915, 722, 915, 834, 915, 915, 861, 915,
+ /* 10 */ 890, 832, 915, 915, 915, 915, 806, 915, 861, 915,
+ /* 20 */ 638, 861, 861, 726, 757, 915, 915, 915, 915, 915,
+ /* 30 */ 915, 915, 915, 758, 915, 836, 831, 827, 829, 828,
+ /* 40 */ 835, 759, 748, 755, 762, 737, 874, 764, 765, 771,
+ /* 50 */ 772, 891, 889, 794, 793, 812, 915, 915, 915, 915,
+ /* 60 */ 915, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ /* 70 */ 915, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ /* 80 */ 915, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ /* 90 */ 915, 915, 915, 915, 915, 915, 915, 796, 818, 795,
+ /* 100 */ 805, 631, 797, 798, 691, 626, 915, 915, 799, 915,
+ /* 110 */ 800, 813, 814, 815, 915, 915, 915, 915, 915, 915,
+ /* 120 */ 606, 722, 915, 722, 722, 915, 915, 915, 915, 915,
+ /* 130 */ 915, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ /* 140 */ 915, 915, 915, 915, 915, 915, 915, 716, 726, 908,
+ /* 150 */ 915, 915, 682, 915, 915, 915, 915, 915, 915, 915,
+ /* 160 */ 915, 915, 915, 915, 915, 614, 612, 915, 714, 915,
+ /* 170 */ 915, 640, 915, 915, 724, 915, 915, 915, 915, 915,
+ /* 180 */ 915, 915, 915, 915, 915, 915, 628, 915, 915, 703,
+ /* 190 */ 915, 867, 915, 915, 915, 881, 915, 915, 915, 879,
+ /* 200 */ 915, 915, 915, 705, 767, 847, 915, 894, 896, 915,
+ /* 210 */ 915, 714, 723, 915, 915, 915, 830, 751, 751, 739,
+ /* 220 */ 751, 661, 751, 915, 751, 915, 664, 761, 739, 739,
+ /* 230 */ 761, 611, 611, 611, 611, 681, 915, 761, 752, 754,
+ /* 240 */ 744, 756, 915, 730, 730, 738, 743, 738, 743, 738,
+ /* 250 */ 743, 693, 693, 678, 693, 664, 693, 840, 844, 844,
+ /* 260 */ 678, 693, 693, 693, 840, 623, 730, 623, 730, 623,
+ /* 270 */ 730, 730, 871, 873, 623, 730, 695, 695, 773, 761,
+ /* 280 */ 730, 702, 702, 702, 702, 761, 695, 773, 730, 893,
+ /* 290 */ 893, 730, 730, 901, 648, 666, 666, 908, 913, 915,
+ /* 300 */ 915, 915, 915, 780, 915, 915, 915, 915, 915, 915,
+ /* 310 */ 915, 915, 915, 915, 915, 915, 915, 854, 915, 915,
+ /* 320 */ 915, 915, 785, 781, 915, 782, 915, 708, 915, 915,
+ /* 330 */ 915, 915, 915, 915, 915, 915, 915, 915, 833, 915,
+ /* 340 */ 745, 915, 753, 915, 915, 915, 915, 915, 915, 915,
+ /* 350 */ 915, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ /* 360 */ 915, 915, 915, 915, 915, 915, 915, 915, 869, 870,
+ /* 370 */ 915, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ /* 380 */ 915, 915, 915, 915, 915, 915, 915, 915, 915, 915,
+ /* 390 */ 915, 915, 915, 900, 915, 915, 903, 607, 915, 602,
+ /* 400 */ 604, 605, 609, 610, 613, 635, 636, 637, 615, 616,
+ /* 410 */ 617, 618, 619, 620, 621, 627, 629, 647, 649, 633,
+ /* 420 */ 651, 712, 713, 777, 706, 707, 711, 634, 788, 779,
+ /* 430 */ 783, 784, 786, 787, 801, 802, 804, 810, 817, 820,
+ /* 440 */ 803, 808, 809, 811, 816, 819, 709, 710, 823, 641,
+ /* 450 */ 642, 645, 646, 857, 859, 858, 860, 644, 643, 789,
+ /* 460 */ 792, 825, 826, 882, 883, 884, 885, 886, 821, 731,
+ /* 470 */ 824, 807, 746, 749, 750, 747, 715, 725, 733, 734,
+ /* 480 */ 735, 736, 720, 721, 727, 742, 775, 776, 740, 741,
+ /* 490 */ 728, 729, 717, 718, 719, 822, 778, 790, 791, 652,
+ /* 500 */ 653, 785, 654, 655, 656, 694, 697, 698, 699, 657,
+ /* 510 */ 676, 679, 680, 658, 665, 659, 660, 667, 668, 669,
+ /* 520 */ 672, 673, 674, 675, 670, 671, 841, 842, 845, 843,
+ /* 530 */ 662, 663, 677, 650, 639, 632, 683, 686, 687, 688,
+ /* 540 */ 689, 690, 692, 684, 685, 630, 622, 624, 732, 863,
+ /* 550 */ 872, 868, 864, 865, 866, 625, 837, 838, 696, 769,
+ /* 560 */ 770, 862, 875, 877, 774, 878, 880, 876, 905, 700,
+ /* 570 */ 701, 704, 846, 887, 760, 763, 766, 768, 848, 849,
+ /* 580 */ 850, 851, 852, 855, 856, 853, 888, 892, 895, 897,
+ /* 590 */ 898, 899, 902, 904, 909, 910, 911, 914, 912, 608,
+ /* 600 */ 603,
};
#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0]))
/* The next table maps tokens into fallback tokens. If a construct
@@ -80598,18 +82561,18 @@
"distinct", "selcollist", "from", "where_opt",
"groupby_opt", "having_opt", "orderby_opt", "limit_opt",
"sclp", "as", "seltablist", "stl_prefix",
"joinop", "indexed_opt", "on_opt", "using_opt",
- "seltablist_paren", "joinop2", "inscollist", "sortlist",
- "sortitem", "nexprlist", "setlist", "insert_cmd",
- "inscollist_opt", "itemlist", "exprlist", "likeop",
- "escape", "between_op", "in_op", "case_operand",
- "case_exprlist", "case_else", "uniqueflag", "collate",
- "nmnum", "plus_opt", "number", "trigger_decl",
- "trigger_cmd_list", "trigger_time", "trigger_event", "foreach_clause",
- "when_clause", "trigger_cmd", "database_kw_opt", "key_opt",
- "add_column_fullname", "kwcolumn_opt", "create_vtab", "vtabarglist",
- "vtabarg", "vtabargtoken", "lp", "anylist",
+ "joinop2", "inscollist", "sortlist", "sortitem",
+ "nexprlist", "setlist", "insert_cmd", "inscollist_opt",
+ "itemlist", "exprlist", "likeop", "escape",
+ "between_op", "in_op", "case_operand", "case_exprlist",
+ "case_else", "uniqueflag", "collate", "nmnum",
+ "plus_opt", "number", "trigger_decl", "trigger_cmd_list",
+ "trigger_time", "trigger_event", "foreach_clause", "when_clause",
+ "trigger_cmd", "database_kw_opt", "key_opt", "add_column_fullname",
+ "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg",
+ "vtabargtoken", "lp", "anylist",
};
#endif /* NDEBUG */
#ifndef NDEBUG
@@ -80742,196 +82705,195 @@
/* 123 */ "from ::= FROM seltablist",
/* 124 */ "stl_prefix ::= seltablist joinop",
/* 125 */ "stl_prefix ::=",
/* 126 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
- /* 127 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt",
- /* 128 */ "seltablist_paren ::= select",
- /* 129 */ "seltablist_paren ::= seltablist",
- /* 130 */ "dbnm ::=",
- /* 131 */ "dbnm ::= DOT nm",
- /* 132 */ "fullname ::= nm dbnm",
- /* 133 */ "joinop ::= COMMA|JOIN",
- /* 134 */ "joinop ::= JOIN_KW JOIN",
- /* 135 */ "joinop ::= JOIN_KW nm JOIN",
- /* 136 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 137 */ "on_opt ::= ON expr",
- /* 138 */ "on_opt ::=",
- /* 139 */ "indexed_opt ::=",
- /* 140 */ "indexed_opt ::= INDEXED BY nm",
- /* 141 */ "indexed_opt ::= NOT INDEXED",
- /* 142 */ "using_opt ::= USING LP inscollist RP",
- /* 143 */ "using_opt ::=",
- /* 144 */ "orderby_opt ::=",
- /* 145 */ "orderby_opt ::= ORDER BY sortlist",
- /* 146 */ "sortlist ::= sortlist COMMA sortitem sortorder",
- /* 147 */ "sortlist ::= sortitem sortorder",
- /* 148 */ "sortitem ::= expr",
- /* 149 */ "sortorder ::= ASC",
- /* 150 */ "sortorder ::= DESC",
- /* 151 */ "sortorder ::=",
- /* 152 */ "groupby_opt ::=",
- /* 153 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 154 */ "having_opt ::=",
- /* 155 */ "having_opt ::= HAVING expr",
- /* 156 */ "limit_opt ::=",
- /* 157 */ "limit_opt ::= LIMIT expr",
- /* 158 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 159 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 160 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
- /* 161 */ "where_opt ::=",
- /* 162 */ "where_opt ::= WHERE expr",
- /* 163 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
- /* 164 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 165 */ "setlist ::= nm EQ expr",
- /* 166 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
- /* 167 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
- /* 168 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
- /* 169 */ "insert_cmd ::= INSERT orconf",
- /* 170 */ "insert_cmd ::= REPLACE",
- /* 171 */ "itemlist ::= itemlist COMMA expr",
- /* 172 */ "itemlist ::= expr",
- /* 173 */ "inscollist_opt ::=",
- /* 174 */ "inscollist_opt ::= LP inscollist RP",
- /* 175 */ "inscollist ::= inscollist COMMA nm",
- /* 176 */ "inscollist ::= nm",
- /* 177 */ "expr ::= term",
- /* 178 */ "expr ::= LP expr RP",
- /* 179 */ "term ::= NULL",
- /* 180 */ "expr ::= ID",
- /* 181 */ "expr ::= JOIN_KW",
- /* 182 */ "expr ::= nm DOT nm",
- /* 183 */ "expr ::= nm DOT nm DOT nm",
- /* 184 */ "term ::= INTEGER|FLOAT|BLOB",
- /* 185 */ "term ::= STRING",
- /* 186 */ "expr ::= REGISTER",
- /* 187 */ "expr ::= VARIABLE",
- /* 188 */ "expr ::= expr COLLATE ids",
- /* 189 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 190 */ "expr ::= ID LP distinct exprlist RP",
- /* 191 */ "expr ::= ID LP STAR RP",
- /* 192 */ "term ::= CTIME_KW",
- /* 193 */ "expr ::= expr AND expr",
- /* 194 */ "expr ::= expr OR expr",
- /* 195 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 196 */ "expr ::= expr EQ|NE expr",
- /* 197 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 198 */ "expr ::= expr PLUS|MINUS expr",
- /* 199 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 200 */ "expr ::= expr CONCAT expr",
- /* 201 */ "likeop ::= LIKE_KW",
- /* 202 */ "likeop ::= NOT LIKE_KW",
- /* 203 */ "likeop ::= MATCH",
- /* 204 */ "likeop ::= NOT MATCH",
- /* 205 */ "escape ::= ESCAPE expr",
- /* 206 */ "escape ::=",
- /* 207 */ "expr ::= expr likeop expr escape",
- /* 208 */ "expr ::= expr ISNULL|NOTNULL",
- /* 209 */ "expr ::= expr IS NULL",
- /* 210 */ "expr ::= expr NOT NULL",
- /* 211 */ "expr ::= expr IS NOT NULL",
- /* 212 */ "expr ::= NOT expr",
- /* 213 */ "expr ::= BITNOT expr",
- /* 214 */ "expr ::= MINUS expr",
- /* 215 */ "expr ::= PLUS expr",
- /* 216 */ "between_op ::= BETWEEN",
- /* 217 */ "between_op ::= NOT BETWEEN",
- /* 218 */ "expr ::= expr between_op expr AND expr",
- /* 219 */ "in_op ::= IN",
- /* 220 */ "in_op ::= NOT IN",
- /* 221 */ "expr ::= expr in_op LP exprlist RP",
- /* 222 */ "expr ::= LP select RP",
- /* 223 */ "expr ::= expr in_op LP select RP",
- /* 224 */ "expr ::= expr in_op nm dbnm",
- /* 225 */ "expr ::= EXISTS LP select RP",
- /* 226 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 227 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 228 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 229 */ "case_else ::= ELSE expr",
- /* 230 */ "case_else ::=",
- /* 231 */ "case_operand ::= expr",
- /* 232 */ "case_operand ::=",
- /* 233 */ "exprlist ::= nexprlist",
- /* 234 */ "exprlist ::=",
- /* 235 */ "nexprlist ::= nexprlist COMMA expr",
- /* 236 */ "nexprlist ::= expr",
- /* 237 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
- /* 238 */ "uniqueflag ::= UNIQUE",
- /* 239 */ "uniqueflag ::=",
- /* 240 */ "idxlist_opt ::=",
- /* 241 */ "idxlist_opt ::= LP idxlist RP",
- /* 242 */ "idxlist ::= idxlist COMMA nm collate sortorder",
- /* 243 */ "idxlist ::= nm collate sortorder",
- /* 244 */ "collate ::=",
- /* 245 */ "collate ::= COLLATE ids",
- /* 246 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 247 */ "cmd ::= VACUUM",
- /* 248 */ "cmd ::= VACUUM nm",
- /* 249 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 250 */ "cmd ::= PRAGMA nm dbnm EQ ON",
- /* 251 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
- /* 252 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 253 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 254 */ "cmd ::= PRAGMA nm dbnm",
- /* 255 */ "nmnum ::= plus_num",
- /* 256 */ "nmnum ::= nm",
- /* 257 */ "plus_num ::= plus_opt number",
- /* 258 */ "minus_num ::= MINUS number",
- /* 259 */ "number ::= INTEGER|FLOAT",
- /* 260 */ "plus_opt ::= PLUS",
- /* 261 */ "plus_opt ::=",
- /* 262 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
- /* 263 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 264 */ "trigger_time ::= BEFORE",
- /* 265 */ "trigger_time ::= AFTER",
- /* 266 */ "trigger_time ::= INSTEAD OF",
- /* 267 */ "trigger_time ::=",
- /* 268 */ "trigger_event ::= DELETE|INSERT",
- /* 269 */ "trigger_event ::= UPDATE",
- /* 270 */ "trigger_event ::= UPDATE OF inscollist",
- /* 271 */ "foreach_clause ::=",
- /* 272 */ "foreach_clause ::= FOR EACH ROW",
- /* 273 */ "when_clause ::=",
- /* 274 */ "when_clause ::= WHEN expr",
- /* 275 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 276 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 277 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
- /* 278 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
- /* 279 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
- /* 280 */ "trigger_cmd ::= DELETE FROM nm where_opt",
- /* 281 */ "trigger_cmd ::= select",
- /* 282 */ "expr ::= RAISE LP IGNORE RP",
- /* 283 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 284 */ "raisetype ::= ROLLBACK",
- /* 285 */ "raisetype ::= ABORT",
- /* 286 */ "raisetype ::= FAIL",
- /* 287 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 288 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 289 */ "cmd ::= DETACH database_kw_opt expr",
- /* 290 */ "key_opt ::=",
- /* 291 */ "key_opt ::= KEY expr",
- /* 292 */ "database_kw_opt ::= DATABASE",
- /* 293 */ "database_kw_opt ::=",
- /* 294 */ "cmd ::= REINDEX",
- /* 295 */ "cmd ::= REINDEX nm dbnm",
- /* 296 */ "cmd ::= ANALYZE",
- /* 297 */ "cmd ::= ANALYZE nm dbnm",
- /* 298 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 299 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
- /* 300 */ "add_column_fullname ::= fullname",
- /* 301 */ "kwcolumn_opt ::=",
- /* 302 */ "kwcolumn_opt ::= COLUMNKW",
- /* 303 */ "cmd ::= create_vtab",
- /* 304 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 305 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
- /* 306 */ "vtabarglist ::= vtabarg",
- /* 307 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 308 */ "vtabarg ::=",
- /* 309 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 310 */ "vtabargtoken ::= ANY",
- /* 311 */ "vtabargtoken ::= lp anylist RP",
- /* 312 */ "lp ::= LP",
- /* 313 */ "anylist ::=",
- /* 314 */ "anylist ::= anylist ANY",
+ /* 127 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
+ /* 128 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
+ /* 129 */ "dbnm ::=",
+ /* 130 */ "dbnm ::= DOT nm",
+ /* 131 */ "fullname ::= nm dbnm",
+ /* 132 */ "joinop ::= COMMA|JOIN",
+ /* 133 */ "joinop ::= JOIN_KW JOIN",
+ /* 134 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 135 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 136 */ "on_opt ::= ON expr",
+ /* 137 */ "on_opt ::=",
+ /* 138 */ "indexed_opt ::=",
+ /* 139 */ "indexed_opt ::= INDEXED BY nm",
+ /* 140 */ "indexed_opt ::= NOT INDEXED",
+ /* 141 */ "using_opt ::= USING LP inscollist RP",
+ /* 142 */ "using_opt ::=",
+ /* 143 */ "orderby_opt ::=",
+ /* 144 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 145 */ "sortlist ::= sortlist COMMA sortitem sortorder",
+ /* 146 */ "sortlist ::= sortitem sortorder",
+ /* 147 */ "sortitem ::= expr",
+ /* 148 */ "sortorder ::= ASC",
+ /* 149 */ "sortorder ::= DESC",
+ /* 150 */ "sortorder ::=",
+ /* 151 */ "groupby_opt ::=",
+ /* 152 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 153 */ "having_opt ::=",
+ /* 154 */ "having_opt ::= HAVING expr",
+ /* 155 */ "limit_opt ::=",
+ /* 156 */ "limit_opt ::= LIMIT expr",
+ /* 157 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 158 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 159 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
+ /* 160 */ "where_opt ::=",
+ /* 161 */ "where_opt ::= WHERE expr",
+ /* 162 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
+ /* 163 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 164 */ "setlist ::= nm EQ expr",
+ /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP",
+ /* 166 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
+ /* 167 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
+ /* 168 */ "insert_cmd ::= INSERT orconf",
+ /* 169 */ "insert_cmd ::= REPLACE",
+ /* 170 */ "itemlist ::= itemlist COMMA expr",
+ /* 171 */ "itemlist ::= expr",
+ /* 172 */ "inscollist_opt ::=",
+ /* 173 */ "inscollist_opt ::= LP inscollist RP",
+ /* 174 */ "inscollist ::= inscollist COMMA nm",
+ /* 175 */ "inscollist ::= nm",
+ /* 176 */ "expr ::= term",
+ /* 177 */ "expr ::= LP expr RP",
+ /* 178 */ "term ::= NULL",
+ /* 179 */ "expr ::= ID",
+ /* 180 */ "expr ::= JOIN_KW",
+ /* 181 */ "expr ::= nm DOT nm",
+ /* 182 */ "expr ::= nm DOT nm DOT nm",
+ /* 183 */ "term ::= INTEGER|FLOAT|BLOB",
+ /* 184 */ "term ::= STRING",
+ /* 185 */ "expr ::= REGISTER",
+ /* 186 */ "expr ::= VARIABLE",
+ /* 187 */ "expr ::= expr COLLATE ids",
+ /* 188 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 189 */ "expr ::= ID LP distinct exprlist RP",
+ /* 190 */ "expr ::= ID LP STAR RP",
+ /* 191 */ "term ::= CTIME_KW",
+ /* 192 */ "expr ::= expr AND expr",
+ /* 193 */ "expr ::= expr OR expr",
+ /* 194 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 195 */ "expr ::= expr EQ|NE expr",
+ /* 196 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 197 */ "expr ::= expr PLUS|MINUS expr",
+ /* 198 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 199 */ "expr ::= expr CONCAT expr",
+ /* 200 */ "likeop ::= LIKE_KW",
+ /* 201 */ "likeop ::= NOT LIKE_KW",
+ /* 202 */ "likeop ::= MATCH",
+ /* 203 */ "likeop ::= NOT MATCH",
+ /* 204 */ "escape ::= ESCAPE expr",
+ /* 205 */ "escape ::=",
+ /* 206 */ "expr ::= expr likeop expr escape",
+ /* 207 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 208 */ "expr ::= expr IS NULL",
+ /* 209 */ "expr ::= expr NOT NULL",
+ /* 210 */ "expr ::= expr IS NOT NULL",
+ /* 211 */ "expr ::= NOT expr",
+ /* 212 */ "expr ::= BITNOT expr",
+ /* 213 */ "expr ::= MINUS expr",
+ /* 214 */ "expr ::= PLUS expr",
+ /* 215 */ "between_op ::= BETWEEN",
+ /* 216 */ "between_op ::= NOT BETWEEN",
+ /* 217 */ "expr ::= expr between_op expr AND expr",
+ /* 218 */ "in_op ::= IN",
+ /* 219 */ "in_op ::= NOT IN",
+ /* 220 */ "expr ::= expr in_op LP exprlist RP",
+ /* 221 */ "expr ::= LP select RP",
+ /* 222 */ "expr ::= expr in_op LP select RP",
+ /* 223 */ "expr ::= expr in_op nm dbnm",
+ /* 224 */ "expr ::= EXISTS LP select RP",
+ /* 225 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 226 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 227 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 228 */ "case_else ::= ELSE expr",
+ /* 229 */ "case_else ::=",
+ /* 230 */ "case_operand ::= expr",
+ /* 231 */ "case_operand ::=",
+ /* 232 */ "exprlist ::= nexprlist",
+ /* 233 */ "exprlist ::=",
+ /* 234 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 235 */ "nexprlist ::= expr",
+ /* 236 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP",
+ /* 237 */ "uniqueflag ::= UNIQUE",
+ /* 238 */ "uniqueflag ::=",
+ /* 239 */ "idxlist_opt ::=",
+ /* 240 */ "idxlist_opt ::= LP idxlist RP",
+ /* 241 */ "idxlist ::= idxlist COMMA nm collate sortorder",
+ /* 242 */ "idxlist ::= nm collate sortorder",
+ /* 243 */ "collate ::=",
+ /* 244 */ "collate ::= COLLATE ids",
+ /* 245 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 246 */ "cmd ::= VACUUM",
+ /* 247 */ "cmd ::= VACUUM nm",
+ /* 248 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
+ /* 249 */ "cmd ::= PRAGMA nm dbnm EQ ON",
+ /* 250 */ "cmd ::= PRAGMA nm dbnm EQ DELETE",
+ /* 251 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
+ /* 252 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
+ /* 253 */ "cmd ::= PRAGMA nm dbnm",
+ /* 254 */ "nmnum ::= plus_num",
+ /* 255 */ "nmnum ::= nm",
+ /* 256 */ "plus_num ::= plus_opt number",
+ /* 257 */ "minus_num ::= MINUS number",
+ /* 258 */ "number ::= INTEGER|FLOAT",
+ /* 259 */ "plus_opt ::= PLUS",
+ /* 260 */ "plus_opt ::=",
+ /* 261 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END",
+ /* 262 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 263 */ "trigger_time ::= BEFORE",
+ /* 264 */ "trigger_time ::= AFTER",
+ /* 265 */ "trigger_time ::= INSTEAD OF",
+ /* 266 */ "trigger_time ::=",
+ /* 267 */ "trigger_event ::= DELETE|INSERT",
+ /* 268 */ "trigger_event ::= UPDATE",
+ /* 269 */ "trigger_event ::= UPDATE OF inscollist",
+ /* 270 */ "foreach_clause ::=",
+ /* 271 */ "foreach_clause ::= FOR EACH ROW",
+ /* 272 */ "when_clause ::=",
+ /* 273 */ "when_clause ::= WHEN expr",
+ /* 274 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 275 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 276 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt",
+ /* 277 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP",
+ /* 278 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select",
+ /* 279 */ "trigger_cmd ::= DELETE FROM nm where_opt",
+ /* 280 */ "trigger_cmd ::= select",
+ /* 281 */ "expr ::= RAISE LP IGNORE RP",
+ /* 282 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 283 */ "raisetype ::= ROLLBACK",
+ /* 284 */ "raisetype ::= ABORT",
+ /* 285 */ "raisetype ::= FAIL",
+ /* 286 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 287 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 288 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 289 */ "key_opt ::=",
+ /* 290 */ "key_opt ::= KEY expr",
+ /* 291 */ "database_kw_opt ::= DATABASE",
+ /* 292 */ "database_kw_opt ::=",
+ /* 293 */ "cmd ::= REINDEX",
+ /* 294 */ "cmd ::= REINDEX nm dbnm",
+ /* 295 */ "cmd ::= ANALYZE",
+ /* 296 */ "cmd ::= ANALYZE nm dbnm",
+ /* 297 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 298 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
+ /* 299 */ "add_column_fullname ::= fullname",
+ /* 300 */ "kwcolumn_opt ::=",
+ /* 301 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 302 */ "cmd ::= create_vtab",
+ /* 303 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 304 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm",
+ /* 305 */ "vtabarglist ::= vtabarg",
+ /* 306 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 307 */ "vtabarg ::=",
+ /* 308 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 309 */ "vtabargtoken ::= ANY",
+ /* 310 */ "vtabargtoken ::= lp anylist RP",
+ /* 311 */ "lp ::= LP",
+ /* 312 */ "anylist ::=",
+ /* 313 */ "anylist ::= anylist ANY",
};
#endif /* NDEBUG */
@@ -81010,26 +82972,25 @@
** inside the C code.
*/
case 156: /* select */
case 190: /* oneselect */
- case 208: /* seltablist_paren */
-{
-sqlite3SelectDelete(pParse->db, (yypminor->yy43));
+{
+sqlite3SelectDelete(pParse->db, (yypminor->yy219));
}
break;
case 170: /* term */
case 171: /* expr */
case 195: /* where_opt */
case 197: /* having_opt */
case 206: /* on_opt */
- case 212: /* sortitem */
- case 220: /* escape */
- case 223: /* case_operand */
- case 225: /* case_else */
- case 236: /* when_clause */
- case 239: /* key_opt */
-{
-sqlite3ExprDelete(pParse->db, (yypminor->yy450));
+ case 211: /* sortitem */
+ case 219: /* escape */
+ case 222: /* case_operand */
+ case 224: /* case_else */
+ case 235: /* when_clause */
+ case 238: /* key_opt */
+{
+sqlite3ExprDelete(pParse->db, (yypminor->yy172));
}
break;
case 175: /* idxlist_opt */
case 183: /* idxlist */
@@ -81036,42 +82997,42 @@
case 193: /* selcollist */
case 196: /* groupby_opt */
case 198: /* orderby_opt */
case 200: /* sclp */
- case 211: /* sortlist */
- case 213: /* nexprlist */
- case 214: /* setlist */
- case 217: /* itemlist */
- case 218: /* exprlist */
- case 224: /* case_exprlist */
-{
-sqlite3ExprListDelete(pParse->db, (yypminor->yy242));
+ case 210: /* sortlist */
+ case 212: /* nexprlist */
+ case 213: /* setlist */
+ case 216: /* itemlist */
+ case 217: /* exprlist */
+ case 223: /* case_exprlist */
+{
+sqlite3ExprListDelete(pParse->db, (yypminor->yy174));
}
break;
case 189: /* fullname */
case 194: /* from */
case 202: /* seltablist */
case 203: /* stl_prefix */
{
-sqlite3SrcListDelete(pParse->db, (yypminor->yy419));
+sqlite3SrcListDelete(pParse->db, (yypminor->yy373));
}
break;
case 207: /* using_opt */
- case 210: /* inscollist */
- case 216: /* inscollist_opt */
-{
-sqlite3IdListDelete(pParse->db, (yypminor->yy352));
-}
- break;
- case 232: /* trigger_cmd_list */
- case 237: /* trigger_cmd */
-{
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy75));
-}
- break;
- case 234: /* trigger_event */
-{
-sqlite3IdListDelete(pParse->db, (yypminor->yy354).b);
+ case 209: /* inscollist */
+ case 215: /* inscollist_opt */
+{
+sqlite3IdListDelete(pParse->db, (yypminor->yy432));
+}
+ break;
+ case 231: /* trigger_cmd_list */
+ case 236: /* trigger_cmd */
+{
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy243));
+}
+ break;
+ case 233: /* trigger_event */
+{
+sqlite3IdListDelete(pParse->db, (yypminor->yy370).b);
}
break;
default: break; /* If no destructor action specified: do nothing */
}
@@ -81160,9 +83121,9 @@
i += iLookAhead;
if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
if( iLookAhead>0 ){
#ifdef YYFALLBACK
- int iFallback; /* Fallback token */
+ YYCODETYPE iFallback; /* Fallback token */
if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
&& (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG
if( yyTraceFILE ){
@@ -81243,8 +83204,9 @@
while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
/* Here code is inserted which will execute if the parser
** stack every overflows */
+ UNUSED_PARAMETER(yypMinor); /* Silence some compiler warnings */
sqlite3ErrorMsg(pParse, "parser stack overflow");
pParse->parseError = 1;
sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */
}
@@ -81279,10 +83241,10 @@
}
}
#endif
yytos = &yypParser->yystack[yypParser->yyidx];
- yytos->stateno = yyNewState;
- yytos->major = yyMajor;
+ yytos->stateno = (YYACTIONTYPE)yyNewState;
+ yytos->major = (YYCODETYPE)yyMajor;
yytos->minor = *yypMinor;
#ifndef NDEBUG
if( yyTraceFILE && yypParser->yyidx>0 ){
int i;
@@ -81429,10 +83391,9 @@
{ 203, 2 },
{ 203, 0 },
{ 202, 7 },
{ 202, 7 },
- { 208, 1 },
- { 208, 1 },
+ { 202, 7 },
{ 153, 0 },
{ 153, 2 },
{ 189, 2 },
{ 204, 1 },
@@ -81447,11 +83408,11 @@
{ 207, 4 },
{ 207, 0 },
{ 198, 0 },
{ 198, 3 },
- { 211, 4 },
- { 211, 2 },
- { 212, 1 },
+ { 210, 4 },
+ { 210, 2 },
+ { 211, 1 },
{ 173, 1 },
{ 173, 1 },
{ 173, 0 },
{ 196, 0 },
@@ -81465,21 +83426,21 @@
{ 145, 5 },
{ 195, 0 },
{ 195, 2 },
{ 145, 7 },
- { 214, 5 },
- { 214, 3 },
+ { 213, 5 },
+ { 213, 3 },
{ 145, 8 },
{ 145, 5 },
{ 145, 6 },
- { 215, 2 },
- { 215, 1 },
- { 217, 3 },
- { 217, 1 },
- { 216, 0 },
+ { 214, 2 },
+ { 214, 1 },
{ 216, 3 },
- { 210, 3 },
- { 210, 1 },
+ { 216, 1 },
+ { 215, 0 },
+ { 215, 3 },
+ { 209, 3 },
+ { 209, 1 },
{ 171, 1 },
{ 171, 3 },
{ 170, 1 },
{ 171, 1 },
@@ -81502,14 +83463,14 @@
{ 171, 3 },
{ 171, 3 },
{ 171, 3 },
{ 171, 3 },
- { 219, 1 },
- { 219, 2 },
- { 219, 1 },
+ { 218, 1 },
+ { 218, 2 },
+ { 218, 1 },
+ { 218, 2 },
{ 219, 2 },
- { 220, 2 },
- { 220, 0 },
+ { 219, 0 },
{ 171, 4 },
{ 171, 2 },
{ 171, 3 },
{ 171, 3 },
@@ -81517,38 +83478,38 @@
{ 171, 2 },
{ 171, 2 },
{ 171, 2 },
{ 171, 2 },
+ { 220, 1 },
+ { 220, 2 },
+ { 171, 5 },
{ 221, 1 },
{ 221, 2 },
- { 171, 5 },
- { 222, 1 },
- { 222, 2 },
{ 171, 5 },
{ 171, 3 },
{ 171, 5 },
{ 171, 4 },
{ 171, 4 },
{ 171, 5 },
- { 224, 5 },
- { 224, 4 },
- { 225, 2 },
- { 225, 0 },
- { 223, 1 },
- { 223, 0 },
- { 218, 1 },
- { 218, 0 },
- { 213, 3 },
- { 213, 1 },
+ { 223, 5 },
+ { 223, 4 },
+ { 224, 2 },
+ { 224, 0 },
+ { 222, 1 },
+ { 222, 0 },
+ { 217, 1 },
+ { 217, 0 },
+ { 212, 3 },
+ { 212, 1 },
{ 145, 11 },
- { 226, 1 },
- { 226, 0 },
+ { 225, 1 },
+ { 225, 0 },
{ 175, 0 },
{ 175, 3 },
{ 183, 5 },
{ 183, 3 },
- { 227, 0 },
- { 227, 2 },
+ { 226, 0 },
+ { 226, 2 },
{ 145, 4 },
{ 145, 1 },
{ 145, 2 },
{ 145, 5 },
@@ -81556,35 +83517,35 @@
{ 145, 5 },
{ 145, 5 },
{ 145, 6 },
{ 145, 3 },
- { 228, 1 },
- { 228, 1 },
+ { 227, 1 },
+ { 227, 1 },
{ 166, 2 },
{ 167, 2 },
- { 230, 1 },
{ 229, 1 },
- { 229, 0 },
+ { 228, 1 },
+ { 228, 0 },
{ 145, 5 },
- { 231, 11 },
+ { 230, 11 },
+ { 232, 1 },
+ { 232, 1 },
+ { 232, 2 },
+ { 232, 0 },
{ 233, 1 },
{ 233, 1 },
- { 233, 2 },
- { 233, 0 },
- { 234, 1 },
- { 234, 1 },
+ { 233, 3 },
+ { 234, 0 },
{ 234, 3 },
{ 235, 0 },
- { 235, 3 },
- { 236, 0 },
- { 236, 2 },
- { 232, 3 },
- { 232, 2 },
- { 237, 6 },
- { 237, 8 },
- { 237, 5 },
- { 237, 4 },
- { 237, 1 },
+ { 235, 2 },
+ { 231, 3 },
+ { 231, 2 },
+ { 236, 6 },
+ { 236, 8 },
+ { 236, 5 },
+ { 236, 4 },
+ { 236, 1 },
{ 171, 4 },
{ 171, 6 },
{ 187, 1 },
{ 187, 1 },
@@ -81591,33 +83552,33 @@
{ 187, 1 },
{ 145, 4 },
{ 145, 6 },
{ 145, 3 },
- { 239, 0 },
- { 239, 2 },
- { 238, 1 },
{ 238, 0 },
+ { 238, 2 },
+ { 237, 1 },
+ { 237, 0 },
{ 145, 1 },
{ 145, 3 },
{ 145, 1 },
{ 145, 3 },
{ 145, 6 },
{ 145, 6 },
- { 240, 1 },
- { 241, 0 },
- { 241, 1 },
+ { 239, 1 },
+ { 240, 0 },
+ { 240, 1 },
{ 145, 1 },
{ 145, 4 },
- { 242, 7 },
- { 243, 1 },
- { 243, 3 },
- { 244, 0 },
- { 244, 2 },
+ { 241, 7 },
+ { 242, 1 },
+ { 242, 3 },
+ { 243, 0 },
+ { 243, 2 },
+ { 244, 1 },
+ { 244, 3 },
{ 245, 1 },
- { 245, 3 },
- { 246, 1 },
- { 247, 0 },
- { 247, 2 },
+ { 246, 0 },
+ { 246, 2 },
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -81693,20 +83654,20 @@
case 82: /* conslist ::= conslist COMMA tcons */
case 83: /* conslist ::= conslist tcons */
case 84: /* conslist ::= tcons */
case 85: /* tcons ::= CONSTRAINT nm */
- case 260: /* plus_opt ::= PLUS */
- case 261: /* plus_opt ::= */
- case 271: /* foreach_clause ::= */
- case 272: /* foreach_clause ::= FOR EACH ROW */
- case 292: /* database_kw_opt ::= DATABASE */
- case 293: /* database_kw_opt ::= */
- case 301: /* kwcolumn_opt ::= */
- case 302: /* kwcolumn_opt ::= COLUMNKW */
- case 306: /* vtabarglist ::= vtabarg */
- case 307: /* vtabarglist ::= vtabarglist COMMA vtabarg */
- case 309: /* vtabarg ::= vtabarg vtabargtoken */
- case 313: /* anylist ::= */
+ case 259: /* plus_opt ::= PLUS */
+ case 260: /* plus_opt ::= */
+ case 270: /* foreach_clause ::= */
+ case 271: /* foreach_clause ::= FOR EACH ROW */
+ case 291: /* database_kw_opt ::= DATABASE */
+ case 292: /* database_kw_opt ::= */
+ case 300: /* kwcolumn_opt ::= */
+ case 301: /* kwcolumn_opt ::= COLUMNKW */
+ case 305: /* vtabarglist ::= vtabarg */
+ case 306: /* vtabarglist ::= vtabarglist COMMA vtabarg */
+ case 308: /* vtabarg ::= vtabarg vtabargtoken */
+ case 312: /* anylist ::= */
{
}
break;
case 5: /* explain ::= */
@@ -81721,19 +83682,19 @@
case 8: /* cmdx ::= cmd */
{ sqlite3FinishCoding(pParse); }
break;
case 9: /* cmd ::= BEGIN transtype trans_opt */
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy316);}
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy46);}
break;
case 13: /* transtype ::= */
-{yygotominor.yy316 = TK_DEFERRED;}
+{yygotominor.yy46 = TK_DEFERRED;}
break;
case 14: /* transtype ::= DEFERRED */
case 15: /* transtype ::= IMMEDIATE */
case 16: /* transtype ::= EXCLUSIVE */
case 107: /* multiselect_op ::= UNION */
case 109: /* multiselect_op ::= EXCEPT|INTERSECT */
-{yygotominor.yy316 = yymsp[0].major;}
+{yygotominor.yy46 = yymsp[0].major;}
break;
case 17: /* cmd ::= COMMIT trans_opt */
case 18: /* cmd ::= END trans_opt */
{sqlite3CommitTransaction(pParse);}
@@ -81742,9 +83703,9 @@
{sqlite3RollbackTransaction(pParse);}
break;
case 21: /* create_table ::= CREATE temp TABLE ifnotexists nm dbnm */
{
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy316,0,0,yymsp[-2].minor.yy316);
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy46,0,0,yymsp[-2].minor.yy46);
}
break;
case 22: /* ifnotexists ::= */
case 25: /* temp ::= */
@@ -81754,21 +83715,21 @@
case 90: /* defer_subclause_opt ::= */
case 101: /* ifexists ::= */
case 112: /* distinct ::= ALL */
case 113: /* distinct ::= */
- case 216: /* between_op ::= BETWEEN */
- case 219: /* in_op ::= IN */
-{yygotominor.yy316 = 0;}
+ case 215: /* between_op ::= BETWEEN */
+ case 218: /* in_op ::= IN */
+{yygotominor.yy46 = 0;}
break;
case 23: /* ifnotexists ::= IF NOT EXISTS */
case 24: /* temp ::= TEMP */
case 64: /* autoinc ::= AUTOINCR */
case 78: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
case 100: /* ifexists ::= IF EXISTS */
case 111: /* distinct ::= DISTINCT */
- case 217: /* between_op ::= NOT BETWEEN */
- case 220: /* in_op ::= NOT IN */
-{yygotominor.yy316 = 1;}
+ case 216: /* between_op ::= NOT BETWEEN */
+ case 219: /* in_op ::= NOT IN */
+{yygotominor.yy46 = 1;}
break;
case 26: /* create_table_args ::= LP columnlist conslist_opt RP */
{
sqlite3EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
@@ -81775,16 +83736,16 @@
}
break;
case 27: /* create_table_args ::= AS select */
{
- sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy43);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43);
+ sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy219);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy219);
}
break;
case 30: /* column ::= columnid type carglist */
{
yygotominor.yy0.z = yymsp[-2].minor.yy0.z;
- yygotominor.yy0.n = (pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
+ yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
}
break;
case 31: /* columnid ::= nm */
{
@@ -81800,16 +83761,16 @@
case 39: /* typetoken ::= typename */
case 42: /* typename ::= ids */
case 119: /* as ::= AS nm */
case 120: /* as ::= ids */
- case 131: /* dbnm ::= DOT nm */
- case 140: /* indexed_opt ::= INDEXED BY nm */
- case 245: /* collate ::= COLLATE ids */
- case 255: /* nmnum ::= plus_num */
- case 256: /* nmnum ::= nm */
- case 257: /* plus_num ::= plus_opt number */
- case 258: /* minus_num ::= MINUS number */
- case 259: /* number ::= INTEGER|FLOAT */
+ case 130: /* dbnm ::= DOT nm */
+ case 139: /* indexed_opt ::= INDEXED BY nm */
+ case 244: /* collate ::= COLLATE ids */
+ case 254: /* nmnum ::= plus_num */
+ case 255: /* nmnum ::= nm */
+ case 256: /* plus_num ::= plus_opt number */
+ case 257: /* minus_num ::= MINUS number */
+ case 258: /* number ::= INTEGER|FLOAT */
{yygotominor.yy0 = yymsp[0].minor.yy0;}
break;
case 38: /* type ::= typetoken */
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
@@ -81816,31 +83777,31 @@
break;
case 40: /* typetoken ::= typename LP signed RP */
{
yygotominor.yy0.z = yymsp[-3].minor.yy0.z;
- yygotominor.yy0.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z;
+ yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
}
break;
case 41: /* typetoken ::= typename LP signed COMMA signed RP */
{
yygotominor.yy0.z = yymsp[-5].minor.yy0.z;
- yygotominor.yy0.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z;
+ yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
}
break;
case 43: /* typename ::= typename ids */
-{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
+{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
break;
case 50: /* ccons ::= DEFAULT term */
case 52: /* ccons ::= DEFAULT PLUS term */
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy450);}
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy172);}
break;
case 51: /* ccons ::= DEFAULT LP expr RP */
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy450);}
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy172);}
break;
case 53: /* ccons ::= DEFAULT MINUS term */
{
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy450, 0, 0);
- sqlite3ExprSpan(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy172, 0, 0);
+ sqlite3ExprSpan(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
sqlite3AddDefaultValue(pParse,p);
}
break;
case 54: /* ccons ::= DEFAULT id */
@@ -81849,66 +83810,66 @@
sqlite3AddDefaultValue(pParse,p);
}
break;
case 56: /* ccons ::= NOT NULL onconf */
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy316);}
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy46);}
break;
case 57: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy316,yymsp[0].minor.yy316,yymsp[-2].minor.yy316);}
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy46,yymsp[-2].minor.yy46);}
break;
case 58: /* ccons ::= UNIQUE onconf */
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy316,0,0,0,0);}
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy46,0,0,0,0);}
break;
case 59: /* ccons ::= CHECK LP expr RP */
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy450);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy172);}
break;
case 60: /* ccons ::= REFERENCES nm idxlist_opt refargs */
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy242,yymsp[0].minor.yy316);}
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy174,yymsp[0].minor.yy46);}
break;
case 61: /* ccons ::= defer_subclause */
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy316);}
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy46);}
break;
case 62: /* ccons ::= COLLATE ids */
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
case 65: /* refargs ::= */
-{ yygotominor.yy316 = OE_Restrict * 0x010101; }
+{ yygotominor.yy46 = OE_Restrict * 0x010101; }
break;
case 66: /* refargs ::= refargs refarg */
-{ yygotominor.yy316 = (yymsp[-1].minor.yy316 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
+{ yygotominor.yy46 = (yymsp[-1].minor.yy46 & ~yymsp[0].minor.yy405.mask) | yymsp[0].minor.yy405.value; }
break;
case 67: /* refarg ::= MATCH nm */
-{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; }
+{ yygotominor.yy405.value = 0; yygotominor.yy405.mask = 0x000000; }
break;
case 68: /* refarg ::= ON DELETE refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy316; yygotominor.yy207.mask = 0x0000ff; }
+{ yygotominor.yy405.value = yymsp[0].minor.yy46; yygotominor.yy405.mask = 0x0000ff; }
break;
case 69: /* refarg ::= ON UPDATE refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy316<<8; yygotominor.yy207.mask = 0x00ff00; }
+{ yygotominor.yy405.value = yymsp[0].minor.yy46<<8; yygotominor.yy405.mask = 0x00ff00; }
break;
case 70: /* refarg ::= ON INSERT refact */
-{ yygotominor.yy207.value = yymsp[0].minor.yy316<<16; yygotominor.yy207.mask = 0xff0000; }
+{ yygotominor.yy405.value = yymsp[0].minor.yy46<<16; yygotominor.yy405.mask = 0xff0000; }
break;
case 71: /* refact ::= SET NULL */
-{ yygotominor.yy316 = OE_SetNull; }
+{ yygotominor.yy46 = OE_SetNull; }
break;
case 72: /* refact ::= SET DEFAULT */
-{ yygotominor.yy316 = OE_SetDflt; }
+{ yygotominor.yy46 = OE_SetDflt; }
break;
case 73: /* refact ::= CASCADE */
-{ yygotominor.yy316 = OE_Cascade; }
+{ yygotominor.yy46 = OE_Cascade; }
break;
case 74: /* refact ::= RESTRICT */
-{ yygotominor.yy316 = OE_Restrict; }
+{ yygotominor.yy46 = OE_Restrict; }
break;
case 75: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
case 76: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
case 91: /* defer_subclause_opt ::= defer_subclause */
case 93: /* onconf ::= ON CONFLICT resolvetype */
case 95: /* orconf ::= OR resolvetype */
case 96: /* resolvetype ::= raisetype */
- case 169: /* insert_cmd ::= INSERT orconf */
-{yygotominor.yy316 = yymsp[0].minor.yy316;}
+ case 168: /* insert_cmd ::= INSERT orconf */
+{yygotominor.yy46 = yymsp[0].minor.yy46;}
break;
case 80: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
break;
@@ -81915,759 +83876,764 @@
case 81: /* conslist_opt ::= COMMA conslist */
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
break;
case 86: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy242,yymsp[0].minor.yy316,yymsp[-2].minor.yy316,0);}
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy174,yymsp[0].minor.yy46,yymsp[-2].minor.yy46,0);}
break;
case 87: /* tcons ::= UNIQUE LP idxlist RP onconf */
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy242,yymsp[0].minor.yy316,0,0,0,0);}
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy174,yymsp[0].minor.yy46,0,0,0,0);}
break;
case 88: /* tcons ::= CHECK LP expr RP onconf */
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy450);}
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy172);}
break;
case 89: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
{
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy242, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[-1].minor.yy316);
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy316);
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy174, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy174, yymsp[-1].minor.yy46);
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy46);
}
break;
case 92: /* onconf ::= */
case 94: /* orconf ::= */
-{yygotominor.yy316 = OE_Default;}
+{yygotominor.yy46 = OE_Default;}
break;
case 97: /* resolvetype ::= IGNORE */
-{yygotominor.yy316 = OE_Ignore;}
+{yygotominor.yy46 = OE_Ignore;}
break;
case 98: /* resolvetype ::= REPLACE */
- case 170: /* insert_cmd ::= REPLACE */
-{yygotominor.yy316 = OE_Replace;}
+ case 169: /* insert_cmd ::= REPLACE */
+{yygotominor.yy46 = OE_Replace;}
break;
case 99: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy419, 0, yymsp[-1].minor.yy316);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy373, 0, yymsp[-1].minor.yy46);
}
break;
case 102: /* cmd ::= CREATE temp VIEW ifnotexists nm dbnm AS select */
{
- sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy43, yymsp[-6].minor.yy316, yymsp[-4].minor.yy316);
+ sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy219, yymsp[-6].minor.yy46, yymsp[-4].minor.yy46);
}
break;
case 103: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlite3DropTable(pParse, yymsp[0].minor.yy419, 1, yymsp[-1].minor.yy316);
+ sqlite3DropTable(pParse, yymsp[0].minor.yy373, 1, yymsp[-1].minor.yy46);
}
break;
case 104: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0};
- sqlite3Select(pParse, yymsp[0].minor.yy43, &dest);
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy43);
+ sqlite3Select(pParse, yymsp[0].minor.yy219, &dest);
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy219);
}
break;
case 105: /* select ::= oneselect */
- case 128: /* seltablist_paren ::= select */
-{yygotominor.yy43 = yymsp[0].minor.yy43;}
+{yygotominor.yy219 = yymsp[0].minor.yy219;}
break;
case 106: /* select ::= select multiselect_op oneselect */
{
- if( yymsp[0].minor.yy43 ){
- yymsp[0].minor.yy43->op = yymsp[-1].minor.yy316;
- yymsp[0].minor.yy43->pPrior = yymsp[-2].minor.yy43;
- }else{
- sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy43);
- }
- yygotominor.yy43 = yymsp[0].minor.yy43;
+ if( yymsp[0].minor.yy219 ){
+ yymsp[0].minor.yy219->op = (u8)yymsp[-1].minor.yy46;
+ yymsp[0].minor.yy219->pPrior = yymsp[-2].minor.yy219;
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy219);
+ }
+ yygotominor.yy219 = yymsp[0].minor.yy219;
}
break;
case 108: /* multiselect_op ::= UNION ALL */
-{yygotominor.yy316 = TK_ALL;}
+{yygotominor.yy46 = TK_ALL;}
break;
case 110: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yygotominor.yy43 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy242,yymsp[-5].minor.yy419,yymsp[-4].minor.yy450,yymsp[-3].minor.yy242,yymsp[-2].minor.yy450,yymsp[-1].minor.yy242,yymsp[-7].minor.yy316,yymsp[0].minor.yy84.pLimit,yymsp[0].minor.yy84.pOffset);
+ yygotominor.yy219 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy174,yymsp[-5].minor.yy373,yymsp[-4].minor.yy172,yymsp[-3].minor.yy174,yymsp[-2].minor.yy172,yymsp[-1].minor.yy174,yymsp[-7].minor.yy46,yymsp[0].minor.yy234.pLimit,yymsp[0].minor.yy234.pOffset);
}
break;
case 114: /* sclp ::= selcollist COMMA */
- case 241: /* idxlist_opt ::= LP idxlist RP */
-{yygotominor.yy242 = yymsp[-1].minor.yy242;}
+ case 240: /* idxlist_opt ::= LP idxlist RP */
+{yygotominor.yy174 = yymsp[-1].minor.yy174;}
break;
case 115: /* sclp ::= */
- case 144: /* orderby_opt ::= */
- case 152: /* groupby_opt ::= */
- case 234: /* exprlist ::= */
- case 240: /* idxlist_opt ::= */
-{yygotominor.yy242 = 0;}
+ case 143: /* orderby_opt ::= */
+ case 151: /* groupby_opt ::= */
+ case 233: /* exprlist ::= */
+ case 239: /* idxlist_opt ::= */
+{yygotominor.yy174 = 0;}
break;
case 116: /* selcollist ::= sclp expr as */
{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[-1].minor.yy450,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy174,yymsp[-1].minor.yy172,yymsp[0].minor.yy0.n?&yymsp[0].minor.yy0:0);
}
break;
case 117: /* selcollist ::= sclp STAR */
{
Expr *p = sqlite3PExpr(pParse, TK_ALL, 0, 0, 0);
- yygotominor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy242, p, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy174, p, 0);
}
break;
case 118: /* selcollist ::= sclp nm DOT STAR */
{
Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242, pDot, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy174, pDot, 0);
}
break;
case 121: /* as ::= */
{yygotominor.yy0.n = 0;}
break;
case 122: /* from ::= */
-{yygotominor.yy419 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy419));}
+{yygotominor.yy373 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy373));}
break;
case 123: /* from ::= FROM seltablist */
{
- yygotominor.yy419 = yymsp[0].minor.yy419;
- sqlite3SrcListShiftJoinType(yygotominor.yy419);
+ yygotominor.yy373 = yymsp[0].minor.yy373;
+ sqlite3SrcListShiftJoinType(yygotominor.yy373);
}
break;
case 124: /* stl_prefix ::= seltablist joinop */
{
- yygotominor.yy419 = yymsp[-1].minor.yy419;
- if( yygotominor.yy419 && yygotominor.yy419->nSrc>0 ) yygotominor.yy419->a[yygotominor.yy419->nSrc-1].jointype = yymsp[0].minor.yy316;
+ yygotominor.yy373 = yymsp[-1].minor.yy373;
+ if( yygotominor.yy373 && yygotominor.yy373->nSrc>0 ) yygotominor.yy373->a[yygotominor.yy373->nSrc-1].jointype = (u8)yymsp[0].minor.yy46;
}
break;
case 125: /* stl_prefix ::= */
-{yygotominor.yy419 = 0;}
+{yygotominor.yy373 = 0;}
break;
case 126: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
- yygotominor.yy419 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy419,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy450,yymsp[0].minor.yy352);
- sqlite3SrcListIndexedBy(pParse, yygotominor.yy419, &yymsp[-2].minor.yy0);
-}
- break;
- case 127: /* seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt */
-{
- yygotominor.yy419 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy419,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy43,yymsp[-1].minor.yy450,yymsp[0].minor.yy352);
- }
- break;
- case 129: /* seltablist_paren ::= seltablist */
-{
- sqlite3SrcListShiftJoinType(yymsp[0].minor.yy419);
- yygotominor.yy43 = sqlite3SelectNew(pParse,0,yymsp[0].minor.yy419,0,0,0,0,0,0,0);
- }
- break;
- case 130: /* dbnm ::= */
- case 139: /* indexed_opt ::= */
+ yygotominor.yy373 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy373,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy172,yymsp[0].minor.yy432);
+ sqlite3SrcListIndexedBy(pParse, yygotominor.yy373, &yymsp[-2].minor.yy0);
+}
+ break;
+ case 127: /* seltablist ::= stl_prefix LP select 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);
+ }
+ break;
+ case 128: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+{
+ if( yymsp[-6].minor.yy373==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy172==0 && yymsp[0].minor.yy432==0 ){
+ yygotominor.yy373 = yymsp[-4].minor.yy373;
+ }else{
+ Select *pSubquery;
+ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy373);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy373,0,0,0,0,0,0,0);
+ yygotominor.yy373 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy373,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy172,yymsp[0].minor.yy432);
+ }
+ }
+ break;
+ case 129: /* dbnm ::= */
+ case 138: /* indexed_opt ::= */
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
break;
- case 132: /* fullname ::= nm dbnm */
-{yygotominor.yy419 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
- break;
- case 133: /* joinop ::= COMMA|JOIN */
-{ yygotominor.yy316 = JT_INNER; }
- break;
- case 134: /* joinop ::= JOIN_KW JOIN */
-{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
- break;
- case 135: /* joinop ::= JOIN_KW nm JOIN */
-{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
- break;
- case 136: /* joinop ::= JOIN_KW nm nm JOIN */
-{ yygotominor.yy316 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
- break;
- case 137: /* on_opt ::= ON expr */
- case 148: /* sortitem ::= expr */
- case 155: /* having_opt ::= HAVING expr */
- case 162: /* where_opt ::= WHERE expr */
- case 177: /* expr ::= term */
- case 205: /* escape ::= ESCAPE expr */
- case 229: /* case_else ::= ELSE expr */
- case 231: /* case_operand ::= expr */
-{yygotominor.yy450 = yymsp[0].minor.yy450;}
- break;
- case 138: /* on_opt ::= */
- case 154: /* having_opt ::= */
- case 161: /* where_opt ::= */
- case 206: /* escape ::= */
- case 230: /* case_else ::= */
- case 232: /* case_operand ::= */
-{yygotominor.yy450 = 0;}
- break;
- case 141: /* indexed_opt ::= NOT INDEXED */
+ case 131: /* fullname ::= nm dbnm */
+{yygotominor.yy373 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
+ break;
+ case 132: /* joinop ::= COMMA|JOIN */
+{ yygotominor.yy46 = JT_INNER; }
+ break;
+ case 133: /* joinop ::= JOIN_KW JOIN */
+{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
+ break;
+ case 134: /* joinop ::= JOIN_KW nm JOIN */
+{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
+ break;
+ case 135: /* joinop ::= JOIN_KW nm nm JOIN */
+{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
+ break;
+ case 136: /* on_opt ::= ON expr */
+ case 147: /* sortitem ::= expr */
+ case 154: /* having_opt ::= HAVING expr */
+ case 161: /* where_opt ::= WHERE expr */
+ case 176: /* expr ::= term */
+ case 204: /* escape ::= ESCAPE expr */
+ case 228: /* case_else ::= ELSE expr */
+ case 230: /* case_operand ::= expr */
+{yygotominor.yy172 = yymsp[0].minor.yy172;}
+ break;
+ case 137: /* on_opt ::= */
+ case 153: /* having_opt ::= */
+ case 160: /* where_opt ::= */
+ case 205: /* escape ::= */
+ case 229: /* case_else ::= */
+ case 231: /* case_operand ::= */
+{yygotominor.yy172 = 0;}
+ break;
+ case 140: /* indexed_opt ::= NOT INDEXED */
{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
break;
- case 142: /* using_opt ::= USING LP inscollist RP */
- case 174: /* inscollist_opt ::= LP inscollist RP */
-{yygotominor.yy352 = yymsp[-1].minor.yy352;}
- break;
- case 143: /* using_opt ::= */
- case 173: /* inscollist_opt ::= */
-{yygotominor.yy352 = 0;}
- break;
- case 145: /* orderby_opt ::= ORDER BY sortlist */
- case 153: /* groupby_opt ::= GROUP BY nexprlist */
- case 233: /* exprlist ::= nexprlist */
-{yygotominor.yy242 = yymsp[0].minor.yy242;}
- break;
- case 146: /* sortlist ::= sortlist COMMA sortitem sortorder */
-{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242,yymsp[-1].minor.yy450,0);
- if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
-}
- break;
- case 147: /* sortlist ::= sortitem sortorder */
-{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy450,0);
- if( yygotominor.yy242 && yygotominor.yy242->a ) yygotominor.yy242->a[0].sortOrder = yymsp[0].minor.yy316;
-}
- break;
- case 149: /* sortorder ::= ASC */
- case 151: /* sortorder ::= */
-{yygotominor.yy316 = SQLITE_SO_ASC;}
- break;
- case 150: /* sortorder ::= DESC */
-{yygotominor.yy316 = SQLITE_SO_DESC;}
- break;
- case 156: /* limit_opt ::= */
-{yygotominor.yy84.pLimit = 0; yygotominor.yy84.pOffset = 0;}
- break;
- case 157: /* limit_opt ::= LIMIT expr */
-{yygotominor.yy84.pLimit = yymsp[0].minor.yy450; yygotominor.yy84.pOffset = 0;}
- break;
- case 158: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yygotominor.yy84.pLimit = yymsp[-2].minor.yy450; yygotominor.yy84.pOffset = yymsp[0].minor.yy450;}
- break;
- case 159: /* limit_opt ::= LIMIT expr COMMA expr */
-{yygotominor.yy84.pOffset = yymsp[-2].minor.yy450; yygotominor.yy84.pLimit = yymsp[0].minor.yy450;}
- break;
- case 160: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
-{
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy419, &yymsp[-1].minor.yy0);
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy419,yymsp[0].minor.yy450);
-}
- break;
- case 163: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
-{
- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy419, &yymsp[-3].minor.yy0);
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy242,"set list");
- sqlite3Update(pParse,yymsp[-4].minor.yy419,yymsp[-1].minor.yy242,yymsp[0].minor.yy450,yymsp[-5].minor.yy316);
-}
- break;
- case 164: /* setlist ::= setlist COMMA nm EQ expr */
-{yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242,yymsp[0].minor.yy450,&yymsp[-2].minor.yy0);}
- break;
- case 165: /* setlist ::= nm EQ expr */
-{yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy450,&yymsp[-2].minor.yy0);}
- break;
- case 166: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */
-{sqlite3Insert(pParse, yymsp[-5].minor.yy419, yymsp[-1].minor.yy242, 0, yymsp[-4].minor.yy352, yymsp[-7].minor.yy316);}
- break;
- case 167: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
-{sqlite3Insert(pParse, yymsp[-2].minor.yy419, 0, yymsp[0].minor.yy43, yymsp[-1].minor.yy352, yymsp[-4].minor.yy316);}
- break;
- case 168: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
-{sqlite3Insert(pParse, yymsp[-3].minor.yy419, 0, 0, yymsp[-2].minor.yy352, yymsp[-5].minor.yy316);}
- break;
- case 171: /* itemlist ::= itemlist COMMA expr */
- case 235: /* nexprlist ::= nexprlist COMMA expr */
-{yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[0].minor.yy450,0);}
- break;
- case 172: /* itemlist ::= expr */
- case 236: /* nexprlist ::= expr */
-{yygotominor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy450,0);}
- break;
- case 175: /* inscollist ::= inscollist COMMA nm */
-{yygotominor.yy352 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy352,&yymsp[0].minor.yy0);}
- break;
- case 176: /* inscollist ::= nm */
-{yygotominor.yy352 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
- break;
- case 178: /* expr ::= LP expr RP */
-{yygotominor.yy450 = yymsp[-1].minor.yy450; sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
- break;
- case 179: /* term ::= NULL */
- case 184: /* term ::= INTEGER|FLOAT|BLOB */
- case 185: /* term ::= STRING */
-{yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
- break;
- case 180: /* expr ::= ID */
- case 181: /* expr ::= JOIN_KW */
-{yygotominor.yy450 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
- break;
- case 182: /* expr ::= nm DOT nm */
+ case 141: /* using_opt ::= USING LP inscollist RP */
+ case 173: /* inscollist_opt ::= LP inscollist RP */
+{yygotominor.yy432 = yymsp[-1].minor.yy432;}
+ break;
+ case 142: /* using_opt ::= */
+ case 172: /* inscollist_opt ::= */
+{yygotominor.yy432 = 0;}
+ break;
+ case 144: /* orderby_opt ::= ORDER BY sortlist */
+ case 152: /* groupby_opt ::= GROUP BY nexprlist */
+ case 232: /* exprlist ::= nexprlist */
+{yygotominor.yy174 = yymsp[0].minor.yy174;}
+ break;
+ case 145: /* 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 = (u8)yymsp[0].minor.yy46;
+}
+ break;
+ case 146: /* sortlist ::= sortitem sortorder */
+{
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy172,0);
+ if( yygotominor.yy174 && yygotominor.yy174->a ) yygotominor.yy174->a[0].sortOrder = (u8)yymsp[0].minor.yy46;
+}
+ break;
+ case 148: /* sortorder ::= ASC */
+ case 150: /* sortorder ::= */
+{yygotominor.yy46 = SQLITE_SO_ASC;}
+ break;
+ case 149: /* sortorder ::= DESC */
+{yygotominor.yy46 = SQLITE_SO_DESC;}
+ break;
+ case 155: /* limit_opt ::= */
+{yygotominor.yy234.pLimit = 0; yygotominor.yy234.pOffset = 0;}
+ break;
+ case 156: /* limit_opt ::= LIMIT expr */
+{yygotominor.yy234.pLimit = yymsp[0].minor.yy172; yygotominor.yy234.pOffset = 0;}
+ break;
+ case 157: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yygotominor.yy234.pLimit = yymsp[-2].minor.yy172; yygotominor.yy234.pOffset = yymsp[0].minor.yy172;}
+ break;
+ case 158: /* limit_opt ::= LIMIT expr COMMA expr */
+{yygotominor.yy234.pOffset = yymsp[-2].minor.yy172; yygotominor.yy234.pLimit = yymsp[0].minor.yy172;}
+ break;
+ case 159: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
+{
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy373, &yymsp[-1].minor.yy0);
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy373,yymsp[0].minor.yy172);
+}
+ break;
+ case 162: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
+{
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy373, &yymsp[-3].minor.yy0);
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy174,"set list");
+ sqlite3Update(pParse,yymsp[-4].minor.yy373,yymsp[-1].minor.yy174,yymsp[0].minor.yy172,yymsp[-5].minor.yy46);
+}
+ break;
+ case 163: /* setlist ::= setlist COMMA nm EQ expr */
+{yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
+ break;
+ case 164: /* setlist ::= nm EQ expr */
+{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,&yymsp[-2].minor.yy0);}
+ break;
+ case 165: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */
+{sqlite3Insert(pParse, yymsp[-5].minor.yy373, yymsp[-1].minor.yy174, 0, yymsp[-4].minor.yy432, yymsp[-7].minor.yy46);}
+ break;
+ case 166: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
+{sqlite3Insert(pParse, yymsp[-2].minor.yy373, 0, yymsp[0].minor.yy219, yymsp[-1].minor.yy432, yymsp[-4].minor.yy46);}
+ break;
+ case 167: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
+{sqlite3Insert(pParse, yymsp[-3].minor.yy373, 0, 0, yymsp[-2].minor.yy432, yymsp[-5].minor.yy46);}
+ break;
+ case 170: /* itemlist ::= itemlist COMMA expr */
+ case 234: /* nexprlist ::= nexprlist COMMA expr */
+{yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy174,yymsp[0].minor.yy172,0);}
+ break;
+ case 171: /* itemlist ::= expr */
+ case 235: /* nexprlist ::= expr */
+{yygotominor.yy174 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy172,0);}
+ break;
+ case 174: /* inscollist ::= inscollist COMMA nm */
+{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy432,&yymsp[0].minor.yy0);}
+ break;
+ case 175: /* inscollist ::= nm */
+{yygotominor.yy432 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
+ break;
+ case 177: /* expr ::= LP expr RP */
+{yygotominor.yy172 = yymsp[-1].minor.yy172; sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); }
+ break;
+ case 178: /* term ::= NULL */
+ case 183: /* term ::= INTEGER|FLOAT|BLOB */
+ case 184: /* term ::= STRING */
+{yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);}
+ break;
+ case 179: /* expr ::= ID */
+ case 180: /* expr ::= JOIN_KW */
+{yygotominor.yy172 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);}
+ break;
+ case 181: /* expr ::= nm DOT nm */
{
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
-}
- break;
- case 183: /* expr ::= nm DOT nm DOT nm */
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
+}
+ break;
+ case 182: /* expr ::= nm DOT nm DOT nm */
{
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
-}
- break;
- case 186: /* expr ::= REGISTER */
-{yygotominor.yy450 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
- break;
- case 187: /* expr ::= VARIABLE */
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
+}
+ break;
+ case 185: /* expr ::= REGISTER */
+{yygotominor.yy172 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);}
+ break;
+ case 186: /* expr ::= VARIABLE */
{
Token *pToken = &yymsp[0].minor.yy0;
- Expr *pExpr = yygotominor.yy450 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
+ Expr *pExpr = yygotominor.yy172 = sqlite3PExpr(pParse, TK_VARIABLE, 0, 0, pToken);
sqlite3ExprAssignVarNumber(pParse, pExpr);
}
break;
- case 188: /* expr ::= expr COLLATE ids */
-{
- yygotominor.yy450 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy450, &yymsp[0].minor.yy0);
-}
- break;
- case 189: /* expr ::= CAST LP expr AS typetoken RP */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy450, 0, &yymsp[-1].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
-}
- break;
- case 190: /* expr ::= ID LP distinct exprlist RP */
-{
- if( yymsp[-1].minor.yy242 && yymsp[-1].minor.yy242->nExpr>SQLITE_MAX_FUNCTION_ARG ){
+ case 187: /* expr ::= expr COLLATE ids */
+{
+ yygotominor.yy172 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy172, &yymsp[0].minor.yy0);
+}
+ break;
+ case 188: /* expr ::= CAST LP expr AS typetoken RP */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy172, 0, &yymsp[-1].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
+}
+ break;
+ case 189: /* expr ::= ID LP distinct exprlist RP */
+{
+ if( yymsp[-1].minor.yy174 && yymsp[-1].minor.yy174->nExpr>SQLITE_MAX_FUNCTION_ARG ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
}
- yygotominor.yy450 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
- if( yymsp[-2].minor.yy316 && yygotominor.yy450 ){
- yygotominor.yy450->flags |= EP_Distinct;
- }
-}
- break;
- case 191: /* expr ::= ID LP STAR RP */
-{
- yygotominor.yy450 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
-}
- break;
- case 192: /* term ::= CTIME_KW */
+ yygotominor.yy172 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy174, &yymsp[-4].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
+ if( yymsp[-2].minor.yy46 && yygotominor.yy172 ){
+ yygotominor.yy172->flags |= EP_Distinct;
+ }
+}
+ break;
+ case 190: /* expr ::= ID LP STAR RP */
+{
+ yygotominor.yy172 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
+}
+ break;
+ case 191: /* term ::= CTIME_KW */
{
/* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
** treated as functions that return constants */
- yygotominor.yy450 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->op = TK_CONST_FUNC;
- yygotominor.yy450->span = yymsp[0].minor.yy0;
- }
-}
- break;
- case 193: /* expr ::= expr AND expr */
- case 194: /* expr ::= expr OR expr */
- case 195: /* expr ::= expr LT|GT|GE|LE expr */
- case 196: /* expr ::= expr EQ|NE expr */
- case 197: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- case 198: /* expr ::= expr PLUS|MINUS expr */
- case 199: /* expr ::= expr STAR|SLASH|REM expr */
- case 200: /* expr ::= expr CONCAT expr */
-{yygotominor.yy450 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy450,yymsp[0].minor.yy450,0);}
- break;
- case 201: /* likeop ::= LIKE_KW */
- case 203: /* likeop ::= MATCH */
-{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 0;}
- break;
- case 202: /* likeop ::= NOT LIKE_KW */
- case 204: /* likeop ::= NOT MATCH */
-{yygotominor.yy86.eOperator = yymsp[0].minor.yy0; yygotominor.yy86.not = 1;}
- break;
- case 207: /* expr ::= expr likeop expr escape */
+ yygotominor.yy172 = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->op = TK_CONST_FUNC;
+ yygotominor.yy172->span = yymsp[0].minor.yy0;
+ }
+}
+ break;
+ case 192: /* expr ::= expr AND expr */
+ case 193: /* expr ::= expr OR expr */
+ case 194: /* expr ::= expr LT|GT|GE|LE expr */
+ case 195: /* expr ::= expr EQ|NE expr */
+ case 196: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ case 197: /* expr ::= expr PLUS|MINUS expr */
+ case 198: /* expr ::= expr STAR|SLASH|REM expr */
+ case 199: /* expr ::= expr CONCAT expr */
+{yygotominor.yy172 = sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy172,yymsp[0].minor.yy172,0);}
+ break;
+ case 200: /* likeop ::= LIKE_KW */
+ case 202: /* likeop ::= MATCH */
+{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 0;}
+ break;
+ case 201: /* likeop ::= NOT LIKE_KW */
+ case 203: /* likeop ::= NOT MATCH */
+{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 1;}
+ break;
+ case 206: /* expr ::= expr likeop expr escape */
{
ExprList *pList;
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy450, 0);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy450, 0);
- if( yymsp[0].minor.yy450 ){
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy450, 0);
- }
- yygotominor.yy450 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy86.eOperator);
- if( yymsp[-2].minor.yy86.not ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy450->span, &yymsp[-1].minor.yy450->span);
- if( yygotominor.yy450 ) yygotominor.yy450->flags |= EP_InfixFunc;
-}
- break;
- case 208: /* expr ::= expr ISNULL|NOTNULL */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy450->span,&yymsp[0].minor.yy0);
-}
- break;
- case 209: /* expr ::= expr IS NULL */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0);
-}
- break;
- case 210: /* expr ::= expr NOT NULL */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy450->span,&yymsp[0].minor.yy0);
-}
- break;
- case 211: /* expr ::= expr IS NOT NULL */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,&yymsp[0].minor.yy0);
-}
- break;
- case 212: /* expr ::= NOT expr */
- case 213: /* expr ::= BITNOT expr */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
-}
- break;
- case 214: /* expr ::= MINUS expr */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
-}
- break;
- case 215: /* expr ::= PLUS expr */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy450->span);
-}
- break;
- case 218: /* expr ::= expr between_op expr AND expr */
-{
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy450, 0);
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy450, 0);
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy450, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pList = pList;
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-1].minor.yy172, 0);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-3].minor.yy172, 0);
+ if( yymsp[0].minor.yy172 ){
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy172, 0);
+ }
+ yygotominor.yy172 = sqlite3ExprFunction(pParse, pList, &yymsp[-2].minor.yy72.eOperator);
+ if( yymsp[-2].minor.yy72.not ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy172->span, &yymsp[-1].minor.yy172->span);
+ if( yygotominor.yy172 ) yygotominor.yy172->flags |= EP_InfixFunc;
+}
+ break;
+ case 207: /* expr ::= expr ISNULL|NOTNULL */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[0].major, yymsp[-1].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy172->span,&yymsp[0].minor.yy0);
+}
+ break;
+ case 208: /* expr ::= expr IS NULL */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_ISNULL, yymsp[-2].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0);
+}
+ break;
+ case 209: /* expr ::= expr NOT NULL */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-2].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0);
+}
+ break;
+ case 210: /* expr ::= expr IS NOT NULL */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOTNULL, yymsp[-3].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,&yymsp[0].minor.yy0);
+}
+ break;
+ case 211: /* expr ::= NOT expr */
+ case 212: /* expr ::= BITNOT expr */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
+}
+ break;
+ case 213: /* expr ::= MINUS expr */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
+}
+ break;
+ case 214: /* expr ::= PLUS expr */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_UPLUS, yymsp[0].minor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span);
+}
+ break;
+ case 217: /* expr ::= expr between_op expr AND expr */
+{
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy172, 0);
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy172, 0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy172, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy450->span);
-}
- break;
- case 221: /* expr ::= expr in_op LP exprlist RP */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy450, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pList = yymsp[-1].minor.yy242;
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
- }else{
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242);
- }
- if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy0);
- }
- break;
- case 222: /* expr ::= LP select RP */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pSelect = yymsp[-1].minor.yy43;
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
- }else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
- }
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- }
- break;
- case 223: /* expr ::= expr in_op LP select RP */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy450, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pSelect = yymsp[-1].minor.yy43;
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
- }else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
- }
- if( yymsp[-3].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-4].minor.yy450->span,&yymsp[0].minor.yy0);
- }
- break;
- case 224: /* expr ::= expr in_op nm dbnm */
+ if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy172->span);
+}
+ break;
+ case 220: /* expr ::= expr in_op LP exprlist RP */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy172, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pList = yymsp[-1].minor.yy174;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+ }else{
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy174);
+ }
+ if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0);
+ }
+ break;
+ case 221: /* expr ::= LP select RP */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pSelect = yymsp[-1].minor.yy219;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+ }
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ }
+ break;
+ case 222: /* expr ::= expr in_op LP select RP */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy172, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pSelect = yymsp[-1].minor.yy219;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+ }
+ if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0);
+ }
+ break;
+ case 223: /* expr ::= expr in_op nm dbnm */
{
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy450, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
- }else{
- sqlite3SrcListDelete(pParse->db, pSrc);
- }
- if( yymsp[-2].minor.yy316 ) yygotominor.yy450 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy450, 0, 0);
- sqlite3ExprSpan(yygotominor.yy450,&yymsp[-3].minor.yy450->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
- }
- break;
- case 225: /* expr ::= EXISTS LP select RP */
-{
- Expr *p = yygotominor.yy450 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy172, 0, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+ }else{
+ sqlite3SrcListDelete(pParse->db, pSrc);
+ }
+ if( yymsp[-2].minor.yy46 ) yygotominor.yy172 = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy172, 0, 0);
+ sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,yymsp[0].minor.yy0.z?&yymsp[0].minor.yy0:&yymsp[-1].minor.yy0);
+ }
+ break;
+ case 224: /* expr ::= EXISTS LP select RP */
+{
+ Expr *p = yygotominor.yy172 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
if( p ){
- p->pSelect = yymsp[-1].minor.yy43;
+ p->pSelect = yymsp[-1].minor.yy219;
sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
- }else{
- sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy43);
- }
- }
- break;
- case 226: /* expr ::= CASE case_operand case_exprlist case_else END */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->pList = yymsp[-2].minor.yy242;
- sqlite3ExprSetHeight(pParse, yygotominor.yy450);
- }else{
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy242);
- }
- sqlite3ExprSpan(yygotominor.yy450, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
-}
- break;
- case 227: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
-{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[-2].minor.yy450, 0);
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yygotominor.yy242, yymsp[0].minor.yy450, 0);
-}
- break;
- case 228: /* case_exprlist ::= WHEN expr THEN expr */
-{
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy450, 0);
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,yygotominor.yy242, yymsp[0].minor.yy450, 0);
-}
- break;
- case 237: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+ }else{
+ sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy219);
+ }
+ }
+ break;
+ case 225: /* expr ::= CASE case_operand case_exprlist case_else END */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, 0);
+ if( yygotominor.yy172 ){
+ yygotominor.yy172->pList = yymsp[-2].minor.yy174;
+ sqlite3ExprSetHeight(pParse, yygotominor.yy172);
+ }else{
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy174);
+ }
+ sqlite3ExprSpan(yygotominor.yy172, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0);
+}
+ break;
+ case 226: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+{
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy174, yymsp[-2].minor.yy172, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yygotominor.yy174, yymsp[0].minor.yy172, 0);
+}
+ break;
+ case 227: /* case_exprlist ::= WHEN expr THEN expr */
+{
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy172, 0);
+ yygotominor.yy174 = sqlite3ExprListAppend(pParse,yygotominor.yy174, yymsp[0].minor.yy172, 0);
+}
+ break;
+ case 236: /* cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */
{
sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0,
- sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy242, yymsp[-9].minor.yy316,
- &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy316);
-}
- break;
- case 238: /* uniqueflag ::= UNIQUE */
- case 285: /* raisetype ::= ABORT */
-{yygotominor.yy316 = OE_Abort;}
- break;
- case 239: /* uniqueflag ::= */
-{yygotominor.yy316 = OE_None;}
- break;
- case 242: /* idxlist ::= idxlist COMMA nm collate sortorder */
+ sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy174, yymsp[-9].minor.yy46,
+ &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46);
+}
+ break;
+ case 237: /* uniqueflag ::= UNIQUE */
+ case 284: /* raisetype ::= ABORT */
+{yygotominor.yy46 = OE_Abort;}
+ break;
+ case 238: /* uniqueflag ::= */
+{yygotominor.yy46 = OE_None;}
+ break;
+ case 241: /* 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 = (u8)yymsp[0].minor.yy46;
+}
+ break;
+ case 242: /* 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.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, p, &yymsp[-2].minor.yy0);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy242, "index");
- if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
-}
- break;
- case 243: /* idxlist ::= nm collate sortorder */
-{
- Expr *p = 0;
- if( yymsp[-1].minor.yy0.n>0 ){
- p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
- sqlite3ExprSetColl(pParse, p, &yymsp[-1].minor.yy0);
- }
- yygotominor.yy242 = sqlite3ExprListAppend(pParse,0, p, &yymsp[-2].minor.yy0);
- sqlite3ExprListCheckLength(pParse, yygotominor.yy242, "index");
- if( yygotominor.yy242 ) yygotominor.yy242->a[yygotominor.yy242->nExpr-1].sortOrder = yymsp[0].minor.yy316;
-}
- break;
- case 244: /* collate ::= */
+ yygotominor.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 = (u8)yymsp[0].minor.yy46;
+}
+ break;
+ case 243: /* collate ::= */
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
break;
- case 246: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy419, yymsp[-1].minor.yy316);}
- break;
- case 247: /* cmd ::= VACUUM */
- case 248: /* cmd ::= VACUUM nm */
+ case 245: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy373, yymsp[-1].minor.yy46);}
+ break;
+ case 246: /* cmd ::= VACUUM */
+ case 247: /* cmd ::= VACUUM nm */
{sqlite3Vacuum(pParse);}
break;
- case 249: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
- case 250: /* cmd ::= PRAGMA nm dbnm EQ ON */
- case 251: /* cmd ::= PRAGMA nm dbnm EQ DELETE */
+ case 248: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 249: /* cmd ::= PRAGMA nm dbnm EQ ON */
+ case 250: /* cmd ::= PRAGMA nm dbnm EQ DELETE */
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 252: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 251: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{
sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);
}
break;
- case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 252: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 254: /* cmd ::= PRAGMA nm dbnm */
+ case 253: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 262: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
+ case 261: /* cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END */
{
Token all;
all.z = yymsp[-3].minor.yy0.z;
- all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy75, &all);
-}
- break;
- case 263: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy243, &all);
+}
+ break;
+ case 262: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy316, yymsp[-4].minor.yy354.a, yymsp[-4].minor.yy354.b, yymsp[-2].minor.yy419, yymsp[0].minor.yy450, yymsp[-10].minor.yy316, yymsp[-8].minor.yy316);
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[0].minor.yy172, yymsp[-10].minor.yy46, yymsp[-8].minor.yy46);
yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
}
break;
- case 264: /* trigger_time ::= BEFORE */
- case 267: /* trigger_time ::= */
-{ yygotominor.yy316 = TK_BEFORE; }
- break;
- case 265: /* trigger_time ::= AFTER */
-{ yygotominor.yy316 = TK_AFTER; }
- break;
- case 266: /* trigger_time ::= INSTEAD OF */
-{ yygotominor.yy316 = TK_INSTEAD;}
- break;
- case 268: /* trigger_event ::= DELETE|INSERT */
- case 269: /* trigger_event ::= UPDATE */
-{yygotominor.yy354.a = yymsp[0].major; yygotominor.yy354.b = 0;}
- break;
- case 270: /* trigger_event ::= UPDATE OF inscollist */
-{yygotominor.yy354.a = TK_UPDATE; yygotominor.yy354.b = yymsp[0].minor.yy352;}
- break;
- case 273: /* when_clause ::= */
- case 290: /* key_opt ::= */
-{ yygotominor.yy450 = 0; }
- break;
- case 274: /* when_clause ::= WHEN expr */
- case 291: /* key_opt ::= KEY expr */
-{ yygotominor.yy450 = yymsp[0].minor.yy450; }
- break;
- case 275: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 263: /* trigger_time ::= BEFORE */
+ case 266: /* trigger_time ::= */
+{ yygotominor.yy46 = TK_BEFORE; }
+ break;
+ case 264: /* trigger_time ::= AFTER */
+{ yygotominor.yy46 = TK_AFTER; }
+ break;
+ case 265: /* trigger_time ::= INSTEAD OF */
+{ yygotominor.yy46 = TK_INSTEAD;}
+ break;
+ case 267: /* trigger_event ::= DELETE|INSERT */
+ case 268: /* trigger_event ::= UPDATE */
+{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;}
+ break;
+ case 269: /* trigger_event ::= UPDATE OF inscollist */
+{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;}
+ break;
+ case 272: /* when_clause ::= */
+ case 289: /* key_opt ::= */
+{ yygotominor.yy172 = 0; }
+ break;
+ case 273: /* when_clause ::= WHEN expr */
+ case 290: /* key_opt ::= KEY expr */
+{ yygotominor.yy172 = yymsp[0].minor.yy172; }
+ break;
+ case 274: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+{
+/*
+ if( yymsp[-2].minor.yy243 ){
+ yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243;
+ }else{
+ yymsp[-2].minor.yy243 = yymsp[-1].minor.yy243;
+ }
+*/
+ assert( yymsp[-2].minor.yy243!=0 );
+ yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243;
+ yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243;
+ yygotominor.yy243 = yymsp[-2].minor.yy243;
+}
+ break;
+ case 275: /* trigger_cmd_list ::= trigger_cmd SEMI */
+{
+ /* if( yymsp[-1].minor.yy243 ) */
+ assert( yymsp[-1].minor.yy243!=0 );
+ yymsp[-1].minor.yy243->pLast = yymsp[-1].minor.yy243;
+ yygotominor.yy243 = yymsp[-1].minor.yy243;
+}
+ break;
+ case 276: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
+{ yygotominor.yy243 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); }
+ break;
+ case 277: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
+{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);}
+ break;
+ case 278: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
+{yygotominor.yy243 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);}
+ break;
+ case 279: /* trigger_cmd ::= DELETE FROM nm where_opt */
+{yygotominor.yy243 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy172);}
+ break;
+ case 280: /* trigger_cmd ::= select */
+{yygotominor.yy243 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy219); }
+ break;
+ case 281: /* 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);
+ }
+}
+ break;
+ case 282: /* expr ::= RAISE LP raisetype COMMA nm RP */
+{
+ yygotominor.yy172 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
+ if( yygotominor.yy172 ) {
+ yygotominor.yy172->iColumn = yymsp[-3].minor.yy46;
+ sqlite3ExprSpan(yygotominor.yy172, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
+ }
+}
+ break;
+ case 283: /* raisetype ::= ROLLBACK */
+{yygotominor.yy46 = OE_Rollback;}
+ break;
+ case 285: /* raisetype ::= FAIL */
+{yygotominor.yy46 = OE_Fail;}
+ break;
+ case 286: /* cmd ::= DROP TRIGGER ifexists fullname */
{
-/*
- if( yymsp[-2].minor.yy75 ){
- yymsp[-2].minor.yy75->pLast->pNext = yymsp[-1].minor.yy75;
- }else{
- yymsp[-2].minor.yy75 = yymsp[-1].minor.yy75;
- }
-*/
- assert( yymsp[-2].minor.yy75!=0 );
- yymsp[-2].minor.yy75->pLast->pNext = yymsp[-1].minor.yy75;
- yymsp[-2].minor.yy75->pLast = yymsp[-1].minor.yy75;
- yygotominor.yy75 = yymsp[-2].minor.yy75;
-}
- break;
- case 276: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46);
+}
+ break;
+ case 287: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- /* if( yymsp[-1].minor.yy75 ) */
- assert( yymsp[-1].minor.yy75!=0 );
- yymsp[-1].minor.yy75->pLast = yymsp[-1].minor.yy75;
- yygotominor.yy75 = yymsp[-1].minor.yy75;
-}
- break;
- case 277: /* trigger_cmd ::= UPDATE orconf nm SET setlist where_opt */
-{ yygotominor.yy75 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy242, yymsp[0].minor.yy450, yymsp[-4].minor.yy316); }
- break;
- case 278: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP */
-{yygotominor.yy75 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy352, yymsp[-1].minor.yy242, 0, yymsp[-7].minor.yy316);}
- break;
- case 279: /* trigger_cmd ::= insert_cmd INTO nm inscollist_opt select */
-{yygotominor.yy75 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy352, 0, yymsp[0].minor.yy43, yymsp[-4].minor.yy316);}
- break;
- case 280: /* trigger_cmd ::= DELETE FROM nm where_opt */
-{yygotominor.yy75 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-1].minor.yy0, yymsp[0].minor.yy450);}
- break;
- case 281: /* trigger_cmd ::= select */
-{yygotominor.yy75 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy43); }
- break;
- case 282: /* expr ::= RAISE LP IGNORE RP */
+ sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy172);
+}
+ break;
+ case 288: /* cmd ::= DETACH database_kw_opt expr */
{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
- if( yygotominor.yy450 ){
- yygotominor.yy450->iColumn = OE_Ignore;
- sqlite3ExprSpan(yygotominor.yy450, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
- }
-}
- break;
- case 283: /* expr ::= RAISE LP raisetype COMMA nm RP */
-{
- yygotominor.yy450 = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0);
- if( yygotominor.yy450 ) {
- yygotominor.yy450->iColumn = yymsp[-3].minor.yy316;
- sqlite3ExprSpan(yygotominor.yy450, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0);
- }
-}
- break;
- case 284: /* raisetype ::= ROLLBACK */
-{yygotominor.yy316 = OE_Rollback;}
- break;
- case 286: /* raisetype ::= FAIL */
-{yygotominor.yy316 = OE_Fail;}
- break;
- case 287: /* cmd ::= DROP TRIGGER ifexists fullname */
-{
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy419,yymsp[-1].minor.yy316);
-}
- break;
- case 288: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
-{
- sqlite3Attach(pParse, yymsp[-3].minor.yy450, yymsp[-1].minor.yy450, yymsp[0].minor.yy450);
-}
- break;
- case 289: /* cmd ::= DETACH database_kw_opt expr */
-{
- sqlite3Detach(pParse, yymsp[0].minor.yy450);
-}
- break;
- case 294: /* cmd ::= REINDEX */
+ sqlite3Detach(pParse, yymsp[0].minor.yy172);
+}
+ break;
+ case 293: /* cmd ::= REINDEX */
{sqlite3Reindex(pParse, 0, 0);}
break;
- case 295: /* cmd ::= REINDEX nm dbnm */
+ case 294: /* cmd ::= REINDEX nm dbnm */
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 296: /* cmd ::= ANALYZE */
+ case 295: /* cmd ::= ANALYZE */
{sqlite3Analyze(pParse, 0, 0);}
break;
- case 297: /* cmd ::= ANALYZE nm dbnm */
+ case 296: /* cmd ::= ANALYZE nm dbnm */
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 298: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 297: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy419,&yymsp[0].minor.yy0);
-}
- break;
- case 299: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy0);
+}
+ break;
+ case 298: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
break;
- case 300: /* add_column_fullname ::= fullname */
+ case 299: /* add_column_fullname ::= fullname */
{
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy419);
-}
- break;
- case 303: /* cmd ::= create_vtab */
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373);
+}
+ break;
+ case 302: /* cmd ::= create_vtab */
{sqlite3VtabFinishParse(pParse,0);}
break;
- case 304: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 303: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 305: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */
+ case 304: /* create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm */
{
sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 308: /* vtabarg ::= */
+ case 307: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
- case 310: /* vtabargtoken ::= ANY */
- case 311: /* vtabargtoken ::= lp anylist RP */
- case 312: /* lp ::= LP */
- case 314: /* anylist ::= anylist ANY */
+ case 309: /* vtabargtoken ::= ANY */
+ case 310: /* vtabargtoken ::= lp anylist RP */
+ case 311: /* lp ::= LP */
+ case 313: /* anylist ::= anylist ANY */
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
};
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
yypParser->yyidx -= yysize;
- yyact = yy_find_reduce_action(yymsp[-yysize].stateno,yygoto);
+ yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
if( yyact < YYNSTATE ){
#ifdef NDEBUG
/* If we are not debugging and the reduce action popped at least
** one element off the stack, then we can push the new element back
@@ -82718,8 +84684,9 @@
){
sqlite3ParserARG_FETCH;
#define TOKEN (yyminor.yy0)
+ UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */
assert( TOKEN.z[0] ); /* The tokenizer always gives us a token */
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
pParse->parseError = 1;
sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
@@ -82802,9 +84769,9 @@
}
#endif
do{
- yyact = yy_find_shift_action(yypParser,yymajor);
+ yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
if( yyact<YYNSTATE ){
assert( !yyendofinput ); /* Impossible to shift the $ token */
yy_shift(yypParser,yyact,yymajor,&yyminorunion);
yypParser->yyerrcnt--;
@@ -82851,9 +84818,9 @@
fprintf(yyTraceFILE,"%sDiscard input token %s\n",
yyTracePrompt,yyTokenName[yymajor]);
}
#endif
- yy_destructor(yypParser, yymajor,&yyminorunion);
+ yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
yymajor = YYNOCODE;
}else{
while(
yypParser->yyidx >= 0 &&
@@ -82864,9 +84831,9 @@
){
yy_pop_parser_stack(yypParser);
}
if( yypParser->yyidx < 0 || yymajor==0 ){
- yy_destructor(yypParser,yymajor,&yyminorunion);
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yy_parse_failed(yypParser);
yymajor = YYNOCODE;
}else if( yymx!=YYERRORSYMBOL ){
YYMINORTYPE u2;
@@ -82889,9 +84856,9 @@
if( yypParser->yyerrcnt<=0 ){
yy_syntax_error(yypParser,yymajor,yyminorunion);
}
yypParser->yyerrcnt = 3;
- yy_destructor(yypParser,yymajor,&yyminorunion);
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
if( yyendofinput ){
yy_parse_failed(yypParser);
}
yymajor = YYNOCODE;
@@ -82972,9 +84939,9 @@
/***** This file contains automatically generated code ******
**
** The code in this file has been automatically generated by
**
-** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.32 2008/10/06 05:32:19 danielk1977 Exp $
+** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.34 2008/12/10 20:11:01 shane Exp $
**
** The code in this file implements a function that determines whether
** or not a given identifier is really an SQL keyword. The same thing
** might be implemented more directly using a hand-written hash table.
@@ -82984,18 +84951,49 @@
*/
/* Hash score: 167 */
static int keywordCode(const char *z, int n){
/* zText[] encodes 783 bytes of keywords in 528 bytes */
- static const char zText[528] =
- "REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECTABLE"
- "FTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTSCONSTRAINT"
- "ERSECTRIGGEREFERENCESUNIQUERYATTACHAVINGROUPDATEMPORARYBEGINNER"
- "ENAMEBETWEENOTNULLIKECASCADELETECASECOLLATECREATECURRENT_DATE"
- "DETACHIMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMIT"
- "WHENWHEREPLACEAFTERESTRICTANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMIT"
- "CONFLICTCROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROM"
- "FULLGLOBYIFINTOFFSETISNULLORDERIGHTOUTEROLLBACKROWUNIONUSINGVACUUM"
- "VIEWINITIALLY";
+ /* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
+ /* ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE */
+ /* XISTSCONSTRAINTERSECTRIGGEREFERENCESUNIQUERYATTACHAVINGROUP */
+ /* DATEMPORARYBEGINNERENAMEBETWEENOTNULLIKECASCADELETECASECOLLATE */
+ /* CREATECURRENT_DATEDETACHIMMEDIATEJOINSERTMATCHPLANALYZEPRAGMA */
+ /* BORTVALUESVIRTUALIMITWHENWHEREPLACEAFTERESTRICTANDEFAULT */
+ /* AUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMP */
+ /* RIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOBYIFINTOFFSETISNULL */
+ /* ORDERIGHTOUTEROLLBACKROWUNIONUSINGVACUUMVIEWINITIALLY */
+ static const char zText[528] = {
+ 'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
+ 'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
+ 'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
+ 'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F',
+ 'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N',
+ 'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I',
+ 'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','C','O','N',
+ 'S','T','R','A','I','N','T','E','R','S','E','C','T','R','I','G','G','E',
+ 'R','E','F','E','R','E','N','C','E','S','U','N','I','Q','U','E','R','Y',
+ 'A','T','T','A','C','H','A','V','I','N','G','R','O','U','P','D','A','T',
+ 'E','M','P','O','R','A','R','Y','B','E','G','I','N','N','E','R','E','N',
+ 'A','M','E','B','E','T','W','E','E','N','O','T','N','U','L','L','I','K',
+ 'E','C','A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O',
+ 'L','L','A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T',
+ '_','D','A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A',
+ 'T','E','J','O','I','N','S','E','R','T','M','A','T','C','H','P','L','A',
+ 'N','A','L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A',
+ 'L','U','E','S','V','I','R','T','U','A','L','I','M','I','T','W','H','E',
+ 'N','W','H','E','R','E','P','L','A','C','E','A','F','T','E','R','E','S',
+ 'T','R','I','C','T','A','N','D','E','F','A','U','L','T','A','U','T','O',
+ 'I','N','C','R','E','M','E','N','T','C','A','S','T','C','O','L','U','M',
+ 'N','C','O','M','M','I','T','C','O','N','F','L','I','C','T','C','R','O',
+ 'S','S','C','U','R','R','E','N','T','_','T','I','M','E','S','T','A','M',
+ 'P','R','I','M','A','R','Y','D','E','F','E','R','R','E','D','I','S','T',
+ 'I','N','C','T','D','R','O','P','F','A','I','L','F','R','O','M','F','U',
+ 'L','L','G','L','O','B','Y','I','F','I','N','T','O','F','F','S','E','T',
+ 'I','S','N','U','L','L','O','R','D','E','R','I','G','H','T','O','U','T',
+ 'E','R','O','L','L','B','A','C','K','R','O','W','U','N','I','O','N','U',
+ 'S','I','N','G','V','A','C','U','U','M','V','I','E','W','I','N','I','T',
+ 'I','A','L','L','Y',0
+ };
static const unsigned char aHash[127] = {
65, 94, 110, 63, 0, 44, 0, 0, 71, 0, 66, 0, 0,
104, 12, 67, 15, 0, 108, 74, 105, 101, 0, 19, 0, 0,
114, 0, 112, 78, 0, 22, 82, 0, 9, 0, 0, 59, 60,
@@ -83829,9 +85827,9 @@
** implement the programmer interface to the library. Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.514 2008/11/19 09:05:27 danielk1977 Exp $
+** $Id: main.c,v 1.519 2008/12/10 23:04:13 drh Exp $
*/
#ifdef SQLITE_ENABLE_FTS3
/************** Include fts3.h in the middle of main.c ***********************/
@@ -83933,9 +85931,11 @@
/*
** The version of the library
*/
+#ifndef SQLITE_AMALGAMATION
SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
+#endif
SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; }
SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
@@ -84302,10 +86302,10 @@
sqlite3_free(db->lookaside.pStart);
}
db->lookaside.pStart = pStart;
db->lookaside.pFree = 0;
- db->lookaside.sz = sz;
- db->lookaside.bMalloced = pBuf==0;
+ db->lookaside.sz = (u16)sz;
+ db->lookaside.bMalloced = pBuf==0 ?1:0;
if( pStart ){
int i;
LookasideSlot *p;
p = (LookasideSlot*)pStart;
@@ -84819,9 +86819,9 @@
** and there are active VMs, then return SQLITE_BUSY. If a function
** is being overridden/deleted but there are no active VMs, allow the
** operation to continue but invalidate all precompiled statements.
*/
- p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0);
+ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0);
if( p && p->iPrefEnc==enc && p->nArg==nArg ){
if( db->activeVdbeCnt ){
sqlite3Error(db, SQLITE_BUSY,
"Unable to delete/modify user-function due to active statements");
@@ -84831,9 +86831,9 @@
sqlite3ExpirePreparedStatements(db);
}
}
- p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1);
+ p = sqlite3FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1);
assert(p || db->mallocFailed);
if( !p ){
return SQLITE_NOMEM;
}
@@ -84841,9 +86841,9 @@
p->xFunc = xFunc;
p->xStep = xStep;
p->xFinalize = xFinal;
p->pUserData = pUserData;
- p->nArg = nArg;
+ p->nArg = (u16)nArg;
return SQLITE_OK;
}
/*
@@ -85106,8 +87106,11 @@
}
if( !sqlite3SafetyCheckSickOrOk(db) ){
return sqlite3ErrStr(SQLITE_MISUSE);
}
+ if( db->mallocFailed ){
+ return sqlite3ErrStr(SQLITE_NOMEM);
+ }
sqlite3_mutex_enter(db->mutex);
assert( !db->mallocFailed );
z = (char*)sqlite3_value_text(db->pErr);
assert( !db->mallocFailed );
@@ -85261,9 +87264,9 @@
if( pColl ){
pColl->xCmp = xCompare;
pColl->pUser = pCtx;
pColl->xDel = xDel;
- pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED);
+ pColl->enc = (u8)(enc2 | (enc & SQLITE_UTF16_ALIGNED));
}
sqlite3Error(db, SQLITE_OK, 0);
return SQLITE_OK;
}