@@ -1,7 +1,7 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.6.14. By combining all the individual C code files into this
+** version 3.6.15. 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
-** 5605 lines past this header comment.) Additional code files may be
+** 5626 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 2009-06-07 12:34:52 UTC.
+** This amalgamation was generated on 2009-06-23 14:42:37 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.882 2009/06/05 14:17:23 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.886 2009/06/19 14:06:03 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -546,9 +546,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.455 2009/05/24 21:59:28 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.458 2009/06/19 22:50:31 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h> /* Needed for the definition of va_list */
@@ -615,10 +615,10 @@
** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()].
**
** Requirements: [H10011] [H10014]
*/
-#define SQLITE_VERSION "3.6.14"
-#define SQLITE_VERSION_NUMBER 3006014
+#define SQLITE_VERSION "3.6.15"
+#define SQLITE_VERSION_NUMBER 3006015
/*
** CAPI3REF: Run-Time Library Version Numbers {H10020} <S60100>
** KEYWORDS: sqlite3_version
@@ -1010,8 +1010,14 @@
** [sqlite3_file] object) with a pointer to an instance of this object.
** This object defines the methods used to perform various operations
** against the open file represented by the [sqlite3_file] object.
**
+** If the xOpen method sets the sqlite3_file.pMethods element
+** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
+** may be invoked even if the xOpen reported that it failed. The
+** only way to prevent a call to xClose following a failed xOpen
+** is for the xOpen to set the sqlite3_file.pMethods element to NULL.
+**
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
** flag may be ORed in to indicate that only the data of the file
@@ -1170,13 +1176,13 @@
** 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. Because of the previous sentense,
+** called. Because of the previous sentence,
** 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
+** must invent 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].
**
** The flags argument to xOpen() includes all bits set in
@@ -1230,9 +1236,14 @@
**
** At least szOsFile bytes of memory are allocated by SQLite
** to hold the [sqlite3_file] structure passed as the third
** argument to xOpen. The xOpen method does not have to
-** allocate the structure; it should just fill it in.
+** allocate the structure; it should just fill it in. Note that
+** the xOpen method must set the sqlite3_file.pMethods to either
+** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
+** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
+** element will be valid after xOpen returns regardless of the success
+** or failure of the xOpen call.
**
** 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]
@@ -1552,14 +1563,16 @@
** </dd>
**
** <dt>SQLITE_CONFIG_SCRATCH</dt>
** <dd>This option specifies a static memory buffer that SQLite can use for
-** scratch memory. There are three arguments: A pointer to the memory, the
-** size of each scratch buffer (sz), and the number of buffers (N). The sz
+** scratch memory. There are three arguments: A pointer an 8-byte
+** aligned memory buffer from which the scrach allocations will be
+** drawn, the size of each scratch allocation (sz),
+** and the maximum number of scratch allocations (N). The sz
** argument must be a multiple of 16. The sz parameter should be a few bytes
-** larger than the actual scratch space required due internal overhead.
-** The first
-** argument should point to an allocation of at least sz*N bytes of memory.
+** larger than the actual scratch space required due to internal overhead.
+** The first argument should pointer to an 8-byte aligned buffer
+** of at least sz*N bytes of memory.
** SQLite will use no more than one scratch buffer at once per thread, so
** N should be set to the expected maximum number of threads. The sz
** parameter should be 6 times the size of the largest database page size.
** Scratch buffers are used as part of the btree balance operation. If
@@ -1571,31 +1584,39 @@
** <dd>This option specifies a static memory buffer that SQLite can use for
** the database page cache with the default page cache implemenation.
** This configuration should not be used if an application-define page
** cache implementation is loaded using the SQLITE_CONFIG_PCACHE option.
-** There are three arguments to this option: A pointer to the
+** There are three arguments to this option: A pointer to 8-byte aligned
** memory, the size of each page buffer (sz), and the number of pages (N).
-** The sz argument must be a power of two between 512 and 32768. The first
+** The sz argument should be the size of the largest database page
+** (a power of two between 512 and 32768) plus a little extra for each
+** page header. The page header size is 20 to 40 bytes depending on
+** the host architecture. It is harmless, apart from the wasted memory,
+** to make sz a little too large. The first
** argument should point to an allocation of at least sz*N bytes of memory.
** SQLite will use the memory provided by the first argument to satisfy its
** memory needs for the first N pages that it adds to cache. If additional
** page cache memory is needed beyond what is provided by this option, then
** SQLite goes to [sqlite3_malloc()] for the additional storage space.
** The implementation might use one or more of the N buffers to hold
-** memory accounting information. </dd>
+** memory accounting information. The pointer in the first argument must
+** be aligned to an 8-byte boundary or subsequent behavior of SQLite
+** will be undefined.</dd>
**
** <dt>SQLITE_CONFIG_HEAP</dt>
** <dd>This option specifies a static memory buffer that SQLite will use
** for all of its dynamic memory allocation needs beyond those provided
** for by [SQLITE_CONFIG_SCRATCH] and [SQLITE_CONFIG_PAGECACHE].
-** There are three arguments: A pointer to the memory, the number of
-** bytes in the memory buffer, and the minimum allocation size. If
-** the first pointer (the memory pointer) is NULL, then SQLite reverts
+** There are three arguments: An 8-byte aligned pointer to the memory,
+** the number of bytes in the memory buffer, and the minimum allocation size.
+** If the first pointer (the memory pointer) is NULL, then SQLite reverts
** to using its default memory allocator (the system malloc() implementation),
** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. If the
** memory pointer is not NULL and either [SQLITE_ENABLE_MEMSYS3] or
** [SQLITE_ENABLE_MEMSYS5] are defined, then the alternative memory
-** allocator is engaged to handle all of SQLites memory allocation needs.</dd>
+** allocator is engaged to handle all of SQLites memory allocation needs.
+** The first pointer (the memory pointer) must be aligned to an 8-byte
+** boundary or subsequent behavior of SQLite will be undefined.</dd>
**
** <dt>SQLITE_CONFIG_MUTEX</dt>
** <dd>This option takes a single argument which is a pointer to an
** instance of the [sqlite3_mutex_methods] structure. The argument specifies
@@ -1664,11 +1685,11 @@
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
** <dd>This option takes three additional arguments that determine the
** [lookaside memory allocator] configuration for the [database connection].
** The first argument (the third parameter to [sqlite3_db_config()] is a
-** pointer to a memory buffer to use for lookaside memory. The first
-** argument may be NULL in which case SQLite will allocate the lookaside
-** buffer itself using [sqlite3_malloc()]. The second argument is the
+** pointer to an 8-byte aligned memory buffer to use for lookaside memory.
+** The first argument may be NULL in which case SQLite will allocate the
+** lookaside buffer itself using [sqlite3_malloc()]. The second argument is the
** size of each lookaside buffer slot and the third argument is the number of
** slots. The size of the buffer in the first argument must be greater than
** or equal to the product of the second and third arguments.</dd>
**
@@ -6398,13 +6419,14 @@
#ifdef SQLITE_OMIT_FLOATING_POINT
# define double sqlite_int64
# define LONGDOUBLE_TYPE sqlite_int64
# ifndef SQLITE_BIG_DBL
-# define SQLITE_BIG_DBL (0x7fffffffffffffff)
+# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<60)
# endif
# define SQLITE_OMIT_DATETIME_FUNCS 1
# define SQLITE_OMIT_TRACE 1
# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+# undef SQLITE_HAVE_ISNAN
#endif
#ifndef SQLITE_BIG_DBL
# define SQLITE_BIG_DBL (1e99)
#endif
@@ -7376,9 +7398,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.101 2009/04/30 09:10:38 danielk1977 Exp $
+** @(#) $Id: pager.h,v 1.102 2009/06/18 17:22:39 drh Exp $
*/
#ifndef _PAGER_H_
#define _PAGER_H_
@@ -7456,9 +7478,9 @@
/* Functions used to configure a Pager object. */
SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
SQLITE_PRIVATE void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*));
-SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*);
+SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u16*, int);
SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager*,int,int);
SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
@@ -7503,13 +7525,8 @@
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
/* Functions used to truncate the database file. */
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
-
-/* Used by encryption extensions. */
-#ifdef SQLITE_HAS_CODEC
-SQLITE_PRIVATE void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
-#endif
/* Functions to support testing and debugging. */
#if !defined(NDEBUG) || defined(SQLITE_TEST)
SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*);
@@ -8260,11 +8277,8 @@
Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */
int busyTimeout; /* Busy handler timeout, in msec */
Db aDbStatic[2]; /* Static space for the 2 default backends */
-#ifdef SQLITE_SSE
- sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */
-#endif
Savepoint *pSavepoint; /* List of active savepoints */
int nSavepoint; /* Number of non-transaction savepoints */
int nStatement; /* Number of nested statement-transactions */
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
@@ -10300,13 +10314,8 @@
#else
#define sqlite3ConnectionBlocked(x,y)
#define sqlite3ConnectionUnlocked(x)
#define sqlite3ConnectionClosed(x)
-#endif
-
-
-#ifdef SQLITE_SSE
-#include "sseInt.h"
#endif
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *);
@@ -17074,20 +17083,12 @@
** 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.171 2009/06/05 14:17:25 drh Exp $
+** $Id: vdbeInt.h,v 1.174 2009/06/23 14:15:04 drh Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_
-
-/*
-** intToKey() and keyToInt() used to transform the rowid. But with
-** the latest versions of the design they are no-ops.
-*/
-#define keyToInt(X) (X)
-#define intToKey(X) (X)
-
/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine. Each instruction is an instance
@@ -17321,24 +17322,27 @@
** malloc failure when SQLite is invoked recursively by a virtual table
** method function.
*/
struct Vdbe {
- sqlite3 *db; /* The whole database */
- Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
- int nOp; /* Number of instructions in the program */
- int nOpAlloc; /* Number of slots allocated for aOp[] */
- Op *aOp; /* Space to hold the virtual machine's program */
- int nLabel; /* Number of labels used */
- int nLabelAlloc; /* Number of slots allocated in aLabel[] */
- int *aLabel; /* Space to hold the labels */
- Mem **apArg; /* Arguments to currently executing user function */
- Mem *aColName; /* Column names to return */
- int nCursor; /* Number of slots in apCsr[] */
- VdbeCursor **apCsr; /* One element of this array for each open cursor */
- int nVar; /* Number of entries in aVar[] */
- Mem *aVar; /* Values for the OP_Variable opcode. */
- char **azVar; /* Name of variables */
- int okVar; /* True if azVar[] has been initialized */
+ sqlite3 *db; /* The database connection that owns this statement */
+ Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
+ int nOp; /* Number of instructions in the program */
+ int nOpAlloc; /* Number of slots allocated for aOp[] */
+ Op *aOp; /* Space to hold the virtual machine's program */
+ int nLabel; /* Number of labels used */
+ int nLabelAlloc; /* Number of slots allocated in aLabel[] */
+ int *aLabel; /* Space to hold the labels */
+ Mem **apArg; /* Arguments to currently executing user function */
+ Mem *aColName; /* Column names to return */
+ Mem *pResultSet; /* Pointer to an array of results */
+ u16 nResColumn; /* Number of columns in one row of the result set */
+ u16 nCursor; /* Number of slots in apCsr[] */
+ VdbeCursor **apCsr; /* One element of this array for each open cursor */
+ u8 errorAction; /* Recovery action to do in case of an error */
+ u8 okVar; /* True if azVar[] has been initialized */
+ u16 nVar; /* Number of entries in aVar[] */
+ Mem *aVar; /* Values for the OP_Variable opcode. */
+ char **azVar; /* Name of variables */
u32 magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
int cacheCtr; /* VdbeCursor row cache generation counter */
@@ -17346,13 +17350,9 @@
int contextStackDepth; /* The size of the "context" stack */
Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
int pc; /* The program counter */
int rc; /* Value to return */
- int errorAction; /* Recovery action to do in case of an error */
- int nResColumn; /* Number of columns in one row of the result set */
- char **azResColumn; /* Values for one row of result */
- char *zErrMsg; /* Error message written here */
- Mem *pResultSet; /* Pointer to an array of results */
+ char *zErrMsg; /* Error message written here */
u8 explain; /* True if EXPLAIN present on SQL command */
u8 changeCntOn; /* True to update the change-counter */
u8 expired; /* True if the VM needs to be recompiled */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
@@ -17360,25 +17360,17 @@
u8 usesStmtJournal; /* True if uses a statement journal */
u8 readOnly; /* True for read-only statements */
u8 isPrepareV2; /* True if prepared with prepare_v2() */
int nChange; /* Number of db changes made since last reset */
- i64 startTime; /* Time when query started - used for profiling */
int btreeMask; /* Bitmask of db->aDb[] entries referenced */
+ i64 startTime; /* Time when query started - used for profiling */
BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
int aCounter[2]; /* Counters used by sqlite3_stmt_status() */
- char *zSql; /* Text of the SQL statement that generated this */
- void *pFree; /* Free this when deleting the vdbe */
-#ifdef SQLITE_DEBUG
- FILE *trace; /* Write an execution trace here, if not NULL */
-#endif
+ char *zSql; /* Text of the SQL statement that generated this */
+ void *pFree; /* Free this when deleting the vdbe */
int iStatement; /* Statement number (or 0 if has not opened stmt) */
-#ifdef SQLITE_SSE
- int fetchId; /* Statement number used by sqlite3_fetch_statement */
- int lru; /* Counter used for LRU cache replacement */
-#endif
-#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
- Vdbe *pLruPrev;
- Vdbe *pLruNext;
+#ifdef SQLITE_DEBUG
+ FILE *trace; /* Write an execution trace here, if not NULL */
#endif
};
/*
@@ -17405,9 +17397,9 @@
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
-SQLITE_PRIVATE int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
+SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
@@ -17986,9 +17978,9 @@
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
-** $Id: util.c,v 1.258 2009/06/05 14:17:23 drh Exp $
+** $Id: util.c,v 1.260 2009/06/17 16:20:04 drh Exp $
*/
#ifdef SQLITE_HAVE_ISNAN
# include <math.h>
#endif
@@ -18078,9 +18070,9 @@
** than 1GiB) the value returned might be less than the true string length.
*/
SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
const char *z2 = z;
- if( NEVER(z==0) ) return 0;
+ if( z==0 ) return 0;
while( *z2 ){ z2++; }
return 0x3fffffff & (int)(z2 - z);
}
@@ -18362,9 +18354,9 @@
** will return -8.
*/
static int compare2pow63(const char *zNum){
int c;
- c = memcmp(zNum,"922337203685477580",18);
+ c = memcmp(zNum,"922337203685477580",18)*10;
if( c==0 ){
c = zNum[18] - '8';
}
return c;
@@ -20865,9 +20857,9 @@
** * 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.251 2009/05/08 11:34:37 danielk1977 Exp $
+** $Id: os_unix.c,v 1.253 2009/06/17 13:09:39 drh Exp $
*/
#if SQLITE_OS_UNIX /* This file is used on unix only */
/*
@@ -21953,9 +21945,9 @@
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 unixLockInfo *pLock = 0;/* 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.
@@ -22857,9 +22849,10 @@
/* To fully unlock the database, delete the lock file */
assert( locktype==NO_LOCK );
if( unlink(zLockFile) ){
- int rc, tErrno = errno;
+ int rc = 0;
+ int tErrno = errno;
if( ENOENT != tErrno ){
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
}
if( IS_LOCK_ERROR(rc) ){
@@ -25107,9 +25100,13 @@
** 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 defined(NO_GETTOD)
+#if defined(SQLITE_OMIT_FLOATING_POINT)
+ time_t t;
+ time(&t);
+ *prNow = (((sqlite3_int64)t)/8640 + 24405875)/10;
+#elif defined(NO_GETTOD)
time_t t;
time(&t);
*prNow = t/86400.0 + 2440587.5;
#elif OS_VXWORKS
@@ -29300,9 +29297,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.16 2009/06/03 21:04:36 drh Exp $
+** @(#) $Id: pcache1.c,v 1.17 2009/06/09 18:58:53 shane Exp $
*/
typedef struct PCache1 PCache1;
@@ -29651,9 +29648,9 @@
static void pcache1TruncateUnsafe(
PCache1 *pCache,
unsigned int iLimit
){
- TESTONLY( int nPage = 0; ) /* Used to assert pCache->nPage is correct */
+ TESTONLY( unsigned int nPage = 0; ) /* Used to assert pCache->nPage is correct */
unsigned int h;
assert( sqlite3_mutex_held(pcache1.mutex) );
for(h=0; h<pCache->nHash; h++){
PgHdr1 **pp = &pCache->apHash[h];
@@ -30499,9 +30496,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.591 2009/06/02 21:31:39 drh Exp $
+** @(#) $Id: pager.c,v 1.601 2009/06/22 05:43:24 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
/*
@@ -30583,13 +30580,16 @@
/*
** A macro used for invoking the codec if there is one
*/
#ifdef SQLITE_HAS_CODEC
-# define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); }
-# define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D))
-#else
-# define CODEC1(P,D,N,X) /* NO-OP */
-# define CODEC2(P,D,N,X) ((char*)D)
+# define CODEC1(P,D,N,X,E) \
+ if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
+# define CODEC2(P,D,N,X,E,O) \
+ if( P->xCodec==0 ){ O=(char*)D; }else \
+ if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
+#else
+# define CODEC1(P,D,N,X,E) /* NO-OP */
+# define CODEC2(P,D,N,X,E,O) O=(char*)D
#endif
/*
** The maximum allowed sector size. 16MB. If the xSectorsize() method
@@ -30767,9 +30767,10 @@
int nSavepoint; /* Number of elements in aSavepoint[] */
char dbFileVers[16]; /* Changes whenever database file changes */
u32 sectorSize; /* Assumed sector size during rollback */
- int nExtra; /* Add this many bytes to each in-memory page */
+ u16 nExtra; /* Add this many bytes to each in-memory page */
+ i16 nReserve; /* Number of unused bytes at end of each page */
u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
int pageSize; /* Number of bytes in a page */
Pgno mxPgno; /* Maximum allowed size of the database */
char *zFilename; /* Name of the database file */
@@ -30782,9 +30783,11 @@
#endif
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
#ifdef SQLITE_HAS_CODEC
void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
- void *pCodecArg; /* First argument to xCodec() */
+ void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
+ void (*xCodecFree)(void*); /* Destructor for the codec */
+ void *pCodec; /* First argument to xCodec... methods */
#endif
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
i64 journalSizeLimit; /* Size limit for persistent journal files */
PCache *pPCache; /* Pointer to page cache object */
@@ -31404,9 +31407,9 @@
** Use a testcase() macro to make sure that malloc failure within
** PagerSetPagesize() is tested.
*/
iPageSize16 = (u16)iPageSize;
- rc = sqlite3PagerSetPagesize(pPager, &iPageSize16);
+ rc = sqlite3PagerSetPagesize(pPager, &iPageSize16, -1);
testcase( rc!=SQLITE_OK );
assert( rc!=SQLITE_OK || iPageSize16==(u16)iPageSize );
/* Update the assumed sector-size to match the value used by
@@ -32006,9 +32009,13 @@
rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, ofst);
if( pgno>pPager->dbFileSize ){
pPager->dbFileSize = pgno;
}
- sqlite3BackupUpdate(pPager->pBackup, pgno, aData);
+ if( pPager->pBackup ){
+ CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM);
+ sqlite3BackupUpdate(pPager->pBackup, pgno, aData);
+ CODEC1(pPager, aData, pgno, 0, rc=SQLITE_NOMEM);
+ }
}else if( !isMainJrnl && pPg==0 ){
/* If this is a rollback of a savepoint and data was not written to
** the database and the page is not in-memory, there is a potential
** problem. When the page is next fetched by the b-tree layer, it
@@ -32075,9 +32082,9 @@
memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
}
/* Decode the page just read from disk */
- CODEC1(pPager, pData, pPg->pgno, 3);
+ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM);
sqlite3PcacheRelease(pPg);
}
return rc;
}
@@ -32839,8 +32846,23 @@
pPager->xReiniter = xReinit;
}
/*
+** Report the current page size and number of reserved bytes back
+** to the codec.
+*/
+#ifdef SQLITE_HAS_CODEC
+static void pagerReportSize(Pager *pPager){
+ if( pPager->xCodecSizeChng ){
+ pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
+ (int)pPager->nReserve);
+ }
+}
+#else
+# define pagerReportSize(X) /* No-op if we do not support a codec */
+#endif
+
+/*
** Change the page size used by the Pager object. The new page size
** is passed in *pPageSize.
**
** If the pager is in the error state when this function is called, it
@@ -32868,9 +32890,9 @@
** conditions above is not true, the pager was in error state when this
** function was called, or because the memory allocation attempt failed,
** then *pPageSize is set to the old, retained page size before returning.
*/
-SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize){
+SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nReserve){
int rc = pPager->errCode;
if( rc==SQLITE_OK ){
u16 pageSize = *pPageSize;
assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
@@ -32889,8 +32911,12 @@
sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
}
}
*pPageSize = (u16)pPager->pageSize;
+ if( nReserve<0 ) nReserve = pPager->nReserve;
+ assert( nReserve>=0 && nReserve<1000 );
+ pPager->nReserve = (i16)nReserve;
+ pagerReportSize(pPager);
}
return rc;
}
@@ -33137,8 +33163,12 @@
sqlite3OsClose(pPager->fd);
sqlite3PageFree(pPager->pTmpSpace);
sqlite3PcacheClose(pPager->pPCache);
+#ifdef SQLITE_HAS_CODEC
+ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
+#endif
+
assert( !pPager->aSavepoint && !pPager->pInJournal );
assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
sqlite3_free(pPager);
@@ -33367,10 +33397,13 @@
** Also, do not write out any page that has the PGHDR_DONT_WRITE flag
** set (set by sqlite3PagerDontWrite()).
*/
if( pgno<=pPager->dbSize && 0==(pList->flags&PGHDR_DONT_WRITE) ){
- i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
- char *pData = CODEC2(pPager, pList->pData, pgno, 6); /* Data to write */
+ i64 offset = (pgno-1)*(i64)pPager->pageSize; /* Offset to write */
+ char *pData; /* Data to write */
+
+ /* Encode the database */
+ CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
/* Write out the page data. */
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
@@ -33385,9 +33418,9 @@
pPager->dbFileSize = pgno;
}
/* Update any backup objects copying the contents of this pager. */
- sqlite3BackupUpdate(pPager->pBackup, pgno, (u8 *)pData);
+ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData);
PAGERTRACE(("STORE %d page %d hash(%08x)\n",
PAGERID(pPager), pgno, pager_pagehash(pList)));
IOTRACE(("PGOUT %p %d\n", pPager, pgno));
@@ -33423,10 +33456,11 @@
Pager *pPager = pPg->pPager;
if( isOpen(pPager->sjfd) ){
void *pData = pPg->pData;
i64 offset = pPager->nSubRec*(4+pPager->pageSize);
- char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
-
+ char *pData2;
+
+ CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
rc = write32bits(pPager->sjfd, offset, pPg->pgno);
@@ -33746,16 +33780,17 @@
** disk and uses an in-memory rollback journal.
*/
tempFile = 1;
pPager->state = PAGER_EXCLUSIVE;
+ readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
}
/* The following call to PagerSetPagesize() serves to set the value of
** Pager.pageSize and to allocate the Pager.pTmpSpace buffer.
*/
if( rc==SQLITE_OK ){
assert( pPager->memDb==0 );
- rc = sqlite3PagerSetPagesize(pPager, &szPageDflt);
+ rc = sqlite3PagerSetPagesize(pPager, &szPageDflt, -1);
testcase( rc!=SQLITE_OK );
}
/* If an error occurred in either of the blocks above, free the
@@ -33768,8 +33803,9 @@
return rc;
}
/* Initialize the PCache object. */
+ assert( nExtra<1000 );
nExtra = ROUND8(nExtra);
sqlite3PcacheOpen(szPageDflt, nExtra, !memDb,
!memDb?pagerStress:0, (void *)pPager, pPager->pPCache);
@@ -33803,9 +33839,9 @@
pPager->sync_flags = SQLITE_SYNC_NORMAL;
/* pPager->pFirst = 0; */
/* pPager->pFirstSynced = 0; */
/* pPager->pLast = 0; */
- pPager->nExtra = nExtra;
+ pPager->nExtra = (u16)nExtra;
pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT;
assert( isOpen(pPager->fd) || tempFile );
setSectorSize(pPager);
if( memDb ){
@@ -33967,9 +34003,9 @@
if( pgno==1 ){
u8 *dbFileVers = &((u8*)pPg->pData)[24];
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
}
- CODEC1(pPager, pPg->pData, pgno, 3);
+ CODEC1(pPager, pPg->pData, pgno, 3, rc = SQLITE_NOMEM);
PAGER_INCR(sqlite3_pager_readdb_count);
PAGER_INCR(pPager->nRead);
IOTRACE(("PGIN %p %d\n", pPager, pgno));
@@ -34012,17 +34048,15 @@
static int pagerSharedLock(Pager *pPager){
int rc = SQLITE_OK; /* Return code */
int isErrorReset = 0; /* True if recovering from error state */
- /* If this database is opened for exclusive access, has no outstanding
- ** page references and is in an error-state, this is a chance to clear
- ** the error. Discard the contents of the pager-cache and treat any
- ** open journal file as a hot-journal.
- */
- if( !MEMDB && pPager->exclusiveMode
- && sqlite3PcacheRefCount(pPager->pPCache)==0 && pPager->errCode
- ){
- if( isOpen(pPager->jfd) ){
+ /* If this database has no outstanding page references and is in an
+ ** error-state, this is a chance to clear the error. Discard the
+ ** contents of the pager-cache and rollback any hot journal in the
+ ** file-system.
+ */
+ if( !MEMDB && sqlite3PcacheRefCount(pPager->pPCache)==0 && pPager->errCode ){
+ if( isOpen(pPager->jfd) || pPager->zJournal ){
isErrorReset = 1;
}
pPager->errCode = SQLITE_OK;
pager_reset(pPager);
@@ -34103,11 +34137,14 @@
rc = SQLITE_CANTOPEN;
sqlite3OsClose(pPager->jfd);
}
}else{
- /* If the journal does not exist, that means some other process
- ** has already rolled it back */
- rc = SQLITE_BUSY;
+ /* If the journal does not exist, it usually means that some
+ ** other connection managed to get in and roll it back before
+ ** this connection obtained the exclusive lock above. Or, it
+ ** may mean that the pager was in the error-state when this
+ ** function was called and the journal file does not exist. */
+ rc = pager_end_transaction(pPager, 0);
}
}
}
if( rc!=SQLITE_OK ){
@@ -34124,12 +34161,14 @@
** lock and reacquire the read lock. Purge the cache before
** playing back the hot-journal so that we don't end up with
** an inconsistent cache.
*/
- rc = pager_playback(pPager, 1);
- if( rc!=SQLITE_OK ){
- rc = pager_error(pPager, rc);
- goto failed;
+ if( isOpen(pPager->jfd) ){
+ rc = pager_playback(pPager, 1);
+ if( rc!=SQLITE_OK ){
+ rc = pager_error(pPager, rc);
+ goto failed;
+ }
}
assert( (pPager->state==PAGER_SHARED)
|| (pPager->exclusiveMode && pPager->state>PAGER_SHARED)
);
@@ -34307,8 +34346,9 @@
assert( pPager->state!=PAGER_UNLOCK );
rc = sqlite3PcacheFetch(pPager->pPCache, pgno, 1, &pPg);
if( rc!=SQLITE_OK ){
+ pagerUnlockIfUnused(pPager);
return rc;
}
assert( pPg->pgno==pgno );
assert( pPg->pPager==pPager || pPg->pPager==0 );
@@ -34665,9 +34705,9 @@
/* We should never write to the journal file the page that
** contains the database locks. The following assert verifies
** that we do not. */
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
- pData2 = CODEC2(pPager, pData, pPg->pgno, 7);
+ CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
cksum = pager_cksum(pPager, (u8*)pData2);
rc = write32bits(pPager->jfd, pPager->journalOff, pPg->pgno);
if( rc==SQLITE_OK ){
rc = sqlite3OsWrite(pPager->jfd, pData2, pPager->pageSize,
@@ -35516,17 +35556,26 @@
}
#ifdef SQLITE_HAS_CODEC
/*
-** Set the codec for this pager
-*/
-SQLITE_PRIVATE void sqlite3PagerSetCodec(
+** Set or retrieve the codec for this pager
+*/
+static void sqlite3PagerSetCodec(
Pager *pPager,
void *(*xCodec)(void*,void*,Pgno,int),
- void *pCodecArg
-){
+ void (*xCodecSizeChng)(void*,int,int),
+ void (*xCodecFree)(void*),
+ void *pCodec
+){
+ if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
pPager->xCodec = xCodec;
- pPager->pCodecArg = pCodecArg;
+ pPager->xCodecSizeChng = xCodecSizeChng;
+ pPager->xCodecFree = xCodecFree;
+ pPager->pCodec = pCodec;
+ pagerReportSize(pPager);
+}
+static void *sqlite3PagerGetCodec(Pager *pPager){
+ return pPager->pCodec;
}
#endif
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -35816,9 +35865,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.46 2009/03/20 14:18:52 danielk1977 Exp $
+** $Id: btreeInt.h,v 1.48 2009/06/22 12:05:10 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
@@ -35877,8 +35926,19 @@
** 28 4 Reserved for future use
** 32 4 First freelist page
** 36 4 Number of freelist pages in the file
** 40 60 15 4-byte meta values passed to higher layers
+**
+** 40 4 Schema cookie
+** 44 4 File format of schema layer
+** 48 4 Size of page cache
+** 52 4 Largest root-page (auto/incr_vacuum)
+** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
+** 60 4 User version
+** 64 4 Incremental vacuum mode
+** 68 4 unused
+** 72 4 unused
+** 76 4 unused
**
** All of the integer values are big-endian (most significant byte first).
**
** The file change counter is incremented when the database is changed
@@ -36442,11 +36502,14 @@
SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage);
SQLITE_PRIVATE void sqlite3BtreeParseCellPtr(MemPage*, u8*, CellInfo*);
SQLITE_PRIVATE void sqlite3BtreeParseCell(MemPage*, int, CellInfo*);
SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur);
+SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur);
+
+#ifdef SQLITE_TEST
SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur);
SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur);
-SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur);
+#endif
/************** End of btreeInt.h ********************************************/
/************** Continuing where we left off in btmutex.c ********************/
#ifndef SQLITE_OMIT_SHARED_CACHE
@@ -36796,9 +36859,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.619 2009/06/05 18:44:15 drh Exp $
+** $Id: btree.c,v 1.639 2009/06/23 11:22:29 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
@@ -36814,9 +36877,9 @@
** Set this global variable to 1 to enable tracing using the TRACE
** macro.
*/
#if 0
-int sqlite3BtreeTrace=0; /* True to enable tracing */
+int sqlite3BtreeTrace=1; /* True to enable tracing */
# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);}
#else
# define TRACE(X)
#endif
@@ -37424,9 +37487,8 @@
#else /* if defined SQLITE_OMIT_AUTOVACUUM */
#define ptrmapPut(w,x,y,z) SQLITE_OK
#define ptrmapGet(w,x,y,z) SQLITE_OK
- #define ptrmapPutOvfl(y,z) SQLITE_OK
#endif
/*
** Given a btree page and a cell index (0 means the first cell on
@@ -37589,9 +37651,9 @@
nSize = minLocal;
}
nSize += 4;
}
- nSize += (pIter - pCell);
+ nSize += (u32)(pIter - pCell);
/* The minimum size of any cell is 4 bytes. */
if( nSize<4 ){
nSize = 4;
@@ -37616,24 +37678,13 @@
CellInfo info;
assert( pCell!=0 );
sqlite3BtreeParseCellPtr(pPage, pCell, &info);
assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload );
- if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){
+ if( info.iOverflow ){
Pgno ovfl = get4byte(&pCell[info.iOverflow]);
return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno);
}
return SQLITE_OK;
-}
-/*
-** If the cell with index iCell on page pPage contains a pointer
-** to an overflow page, insert an entry into the pointer-map
-** for the overflow page.
-*/
-static int ptrmapPutOvfl(MemPage *pPage, int iCell){
- u8 *pCell;
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pCell = findOverflowCell(pPage, iCell);
- return ptrmapPutOvflPtr(pPage, pCell);
}
#endif
@@ -37939,9 +37990,9 @@
** The following block of code checks early to see if a cell extends
** past the end of a page boundary and causes SQLITE_CORRUPT to be
** returned if it does.
*/
-#if defined(SQLITE_OVERREAD_CHECK) || 1
+#if defined(SQLITE_ENABLE_OVERSIZE_CELL_CHECK)
{
int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */
int i; /* Index into the cell pointer array */
@@ -37977,9 +38028,9 @@
if( next>0 && next<=pc+size+3 ){
/* Free blocks must be in accending order */
return SQLITE_CORRUPT_BKPT;
}
- nFree += size;
+ nFree = nFree + size;
pc = next;
}
/* At this point, nFree contains the sum of the offset to the start
@@ -38387,9 +38438,9 @@
pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0);
pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0);
#endif
}
- rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
+ rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
if( rc ) goto btree_open_out;
pBt->usableSize = pBt->pageSize - nReserve;
assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */
@@ -38678,10 +38729,10 @@
assert( (pageSize & 7)==0 );
assert( !pBt->pPage1 && !pBt->pCursor );
pBt->pageSize = (u16)pageSize;
freeTempSpace(pBt);
- rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
- }
+ }
+ rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
pBt->usableSize = pBt->pageSize - (u16)nReserve;
if( iFix ) pBt->pageSizeFixed = 1;
sqlite3BtreeLeave(p);
return rc;
@@ -38834,13 +38885,14 @@
releasePage(pPage1);
pBt->usableSize = (u16)usableSize;
pBt->pageSize = (u16)pageSize;
freeTempSpace(pBt);
- rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize);
+ rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize,
+ pageSize-usableSize);
if( rc ) goto page1_init_failed;
return SQLITE_OK;
}
- if( usableSize<500 ){
+ if( usableSize<480 ){
goto page1_init_failed;
}
pBt->pageSize = (u16)pageSize;
pBt->usableSize = (u16)usableSize;
@@ -39495,9 +39547,11 @@
assert( nRef==sqlite3PagerRefcount(pPager) );
return rc;
}
-#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */
+#else /* ifndef SQLITE_OMIT_AUTOVACUUM */
+# define setChildPtrmaps(x) SQLITE_OK
+#endif
/*
** This routine does the first phase of a two-phase commit. This routine
** causes a rollback journal to be created (if it does not already exist)
@@ -39992,8 +40046,9 @@
}
return SQLITE_OK;
}
+#ifdef SQLITE_TEST
/*
** Make a temporary cursor by filling in the fields of pTempCur.
** The temporary cursor is not on the cursor list for the Btree.
*/
@@ -40007,9 +40062,11 @@
sqlite3PagerRef(pTempCur->apPage[i]->pDbPage);
}
assert( pTempCur->pKey==0 );
}
-
+#endif /* SQLITE_TEST */
+
+#ifdef SQLITE_TEST
/*
** Delete a temporary cursor such as was made by the CreateTemporaryCursor()
** function above.
*/
@@ -40020,10 +40077,9 @@
sqlite3PagerUnref(pCur->apPage[i]->pDbPage);
}
sqlite3_free(pCur->pKey);
}
-
-
+#endif /* SQLITE_TEST */
/*
** Make sure the BtCursor* given in the argument has a valid
** BtCursor.info structure. If it is not already valid, call
@@ -41183,9 +41239,9 @@
){
MemPage *pPage1;
int rc;
u32 n; /* Number of pages on the freelist */
- int k; /* Number of leaves on the trunk of the freelist */
+ u32 k; /* Number of leaves on the trunk of the freelist */
MemPage *pTrunk = 0;
MemPage *pPrevTrunk = 0;
Pgno mxPage; /* Total size of the database file */
@@ -41261,9 +41317,9 @@
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
*ppPage = pTrunk;
pTrunk = 0;
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
- }else if( k>pBt->usableSize/4 - 2 ){
+ }else if( k>(u32)(pBt->usableSize/4 - 2) ){
/* Value of k is out of range. Database corruption */
rc = SQLITE_CORRUPT_BKPT;
goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
@@ -41321,19 +41377,20 @@
}
pTrunk = 0;
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
#endif
- }else{
+ }else if( k>0 ){
/* Extract a leaf from the trunk */
- int closest;
+ u32 closest;
Pgno iPage;
unsigned char *aData = pTrunk->aData;
rc = sqlite3PagerWrite(pTrunk->pDbPage);
if( rc ){
goto end_allocate_page;
}
if( nearby>0 ){
- int i, dist;
+ u32 i;
+ int dist;
closest = 0;
dist = get4byte(&aData[8]) - nearby;
if( dist<0 ) dist = -dist;
for(i=1; i<k; i++){
@@ -41357,9 +41414,9 @@
int noContent;
Pgno nPage;
*pPgno = iPage;
nPage = pagerPagecount(pBt);
- if( *pPgno>nPage ){
+ if( iPage>nPage ){
/* Free page off the end of the file */
rc = SQLITE_CORRUPT_BKPT;
goto end_allocate_page;
}
@@ -41435,8 +41492,10 @@
releasePage(*ppPage);
return SQLITE_CORRUPT_BKPT;
}
(*ppPage)->isInit = 0;
+ }else{
+ *ppPage = 0;
}
return rc;
}
@@ -41845,9 +41904,9 @@
int i, /* New cell becomes the i-th cell of the page */
u8 *pCell, /* Content of the new cell */
int sz, /* Bytes of content in pCell */
u8 *pTemp, /* Temp storage space for pCell, if needed */
- u8 nSkip /* Do not write the first nSkip bytes of the cell */
+ Pgno iChild /* If non-zero, replace first 4 bytes with this value */
){
int idx; /* Where to write new cell content in data[] */
int j; /* Loop counter */
int top; /* First byte of content for any cell in data[] */
@@ -41856,8 +41915,10 @@
int hdr; /* Offset into data[] of the page header */
int cellOffset; /* Address of first cell pointer in data[] */
u8 *data; /* The content of the whole page */
u8 *ptr; /* Used for moving information around in data[] */
+
+ int nSkip = (iChild ? 4 : 0);
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) );
@@ -41867,13 +41928,15 @@
if( pTemp ){
memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip);
pCell = pTemp;
}
+ if( iChild ){
+ put4byte(pCell, iChild);
+ }
j = pPage->nOverflow++;
assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) );
pPage->aOvfl[j].pCell = pCell;
pPage->aOvfl[j].idx = (u16)i;
- pPage->nFree = 0;
}else{
int rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc!=SQLITE_OK ){
return rc;
@@ -41901,8 +41964,11 @@
}
pPage->nCell++;
pPage->nFree -= 2;
memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip);
+ if( iChild ){
+ put4byte(&data[idx], iChild);
+ }
for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){
ptr[0] = ptr[-2];
ptr[1] = ptr[-1];
}
@@ -41912,16 +41978,9 @@
if( pPage->pBt->autoVacuum ){
/* The cell may contain a pointer to an overflow page. If so, write
** the entry for the overflow page into the pointer map.
*/
- CellInfo info;
- sqlite3BtreeParseCellPtr(pPage, pCell, &info);
- assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload );
- if( info.iOverflow ){
- Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]);
- rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno);
- if( rc!=SQLITE_OK ) return rc;
- }
+ rc = ptrmapPutOvflPtr(pPage, pCell);
}
#endif
}
@@ -41982,10 +42041,8 @@
*/
#define NN 1 /* Number of neighbors on either side of pPage */
#define NB (NN*2+1) /* Total pages involved in the balance */
-/* Forward reference */
-static int balance(BtCursor*, int);
#ifndef SQLITE_OMIT_QUICKBALANCE
/*
** This version of balance() handles the common special case where
@@ -42002,40 +42059,60 @@
**
** pPage is the leaf page which is the right-most page in the tree.
** pParent is its parent. pPage must have a single overflow entry
** which is also the right-most entry on the page.
-*/
-static int balance_quick(BtCursor *pCur){
- MemPage *const pPage = pCur->apPage[pCur->iPage];
- BtShared *const pBt = pCur->pBt;
- MemPage *pNew = 0; /* Newly allocated page */
+**
+** The pSpace buffer is used to store a temporary copy of the divider
+** cell that will be inserted into pParent. Such a cell consists of a 4
+** byte page number followed by a variable length integer. In other
+** words, at most 13 bytes. Hence the pSpace buffer must be at
+** least 13 bytes in size.
+*/
+static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
+ BtShared *const pBt = pPage->pBt; /* B-Tree Database */
+ MemPage *pNew; /* Newly allocated page */
int rc; /* Return Code */
Pgno pgnoNew; /* Page number of pNew */
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ assert( pPage->nOverflow==1 );
+
if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT;
- /* Allocate a new page. This page will become the right-sibling of pPage */
+ /* Allocate a new page. This page will become the right-sibling of
+ ** pPage. Make the parent page writable, so that the new divider cell
+ ** may be inserted. If both these operations are successful, proceed.
+ */
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
if( rc==SQLITE_OK ){
- /* The parentCell buffer is used to store a temporary copy of the divider
- ** cell that will be inserted into pParent. Such a cell consists of a 4
- ** byte page number followed by a variable length integer. In other
- ** words, at most 13 bytes. Hence the parentCell buffer must be at
- ** least 13 bytes in size.
- */
- MemPage * const pParent = pCur->apPage[pCur->iPage-1];
- u8 parentCell[13];
- u8 *pOut = &parentCell[4];
+
+ u8 *pOut = &pSpace[4];
u8 *pCell = pPage->aOvfl[0].pCell;
u16 szCell = cellSizePtr(pPage, pCell);
u8 *pStop;
assert( sqlite3PagerIswriteable(pNew->pDbPage) );
- zeroPage(pNew, pPage->aData[0]);
+ assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
+ zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
assemblePage(pNew, 1, &pCell, &szCell);
- pPage->nOverflow = 0;
+
+ /* If this is an auto-vacuum database, update the pointer map
+ ** with entries for the new page, and any pointer from the
+ ** cell on the page to an overflow page. If either of these
+ ** operations fails, the return code is set, but the contents
+ ** of the parent page are still manipulated by thh code below.
+ ** That is Ok, at this point the parent page is guaranteed to
+ ** be marked as dirty. Returning an error code will cause a
+ ** rollback, undoing any changes made to the parent page.
+ */
+ if( ISAUTOVACUUM ){
+ rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
+ if( szCell>pNew->minLocal && rc==SQLITE_OK ){
+ rc = ptrmapPutOvflPtr(pNew, pCell);
+ }
+ }
/* Create a divider cell to insert into pParent. The divider cell
** consists of a 4-byte page number (the page number of pPage) and
** a variable length key value (which must be the same value as the
@@ -42046,221 +42123,233 @@
** record-length (a variable length integer at most 32-bits in size)
** and the key value (a variable length integer, may have any value).
** The first of the while(...) loops below skips over the record-length
** field. The second while(...) loop copies the key value from the
- ** cell on pPage into the parentCell buffer.
- */
- put4byte(parentCell, pPage->pgno);
+ ** cell on pPage into the pSpace buffer.
+ */
pCell = findCell(pPage, pPage->nCell-1);
pStop = &pCell[9];
while( (*(pCell++)&0x80) && pCell<pStop );
pStop = &pCell[9];
while( ((*(pOut++) = *(pCell++))&0x80) && pCell<pStop );
- /* Insert the new divider cell into pParent */
- insertCell(pParent, pParent->nCell, parentCell, pOut-parentCell, 0, 0);
+ /* Insert the new divider cell into pParent. */
+ insertCell(pParent,pParent->nCell,pSpace,(int)(pOut-pSpace),0,pPage->pgno);
/* Set the right-child pointer of pParent to point to the new page. */
put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
-
- /* If this is an auto-vacuum database, update the pointer map
- ** with entries for the new page, and any pointer from the
- ** cell on the page to an overflow page.
- */
- if( ISAUTOVACUUM ){
- rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno);
- if( rc==SQLITE_OK ){
- rc = ptrmapPutOvfl(pNew, 0);
- }
- }
/* Release the reference to the new page. */
releasePage(pNew);
}
- /* At this point the pPage->nFree variable is not set correctly with
- ** respect to the content of the page (because it was set to 0 by
- ** insertCell). So call sqlite3BtreeInitPage() to make sure it is
- ** correct.
- **
- ** This has to be done even if an error will be returned. Normally, if
- ** an error occurs during tree balancing, the contents of MemPage are
- ** not important, as they will be recalculated when the page is rolled
- ** back. But here, in balance_quick(), it is possible that pPage has
- ** not yet been marked dirty or written into the journal file. Therefore
- ** it will not be rolled back and so it is important to make sure that
- ** the page data and contents of MemPage are consistent.
- */
- pPage->isInit = 0;
- sqlite3BtreeInitPage(pPage);
- assert( pPage->nOverflow==0 );
-
- /* If everything else succeeded, balance the parent page, in
- ** case the divider cell inserted caused it to become overfull.
- */
- if( rc==SQLITE_OK ){
- releasePage(pPage);
- pCur->iPage--;
- rc = balance(pCur, 0);
- }
return rc;
}
#endif /* SQLITE_OMIT_QUICKBALANCE */
-/*
-** This routine redistributes Cells on pPage and up to NN*2 siblings
-** of pPage so that all pages have about the same amount of free space.
-** Usually NN siblings on either side of pPage is used in the balancing,
-** though more siblings might come from one side if pPage is the first
-** or last child of its parent. If pPage has fewer than 2*NN siblings
-** (something which can only happen if pPage is the root page or a
-** child of root) then all available siblings participate in the balancing.
-**
-** The number of siblings of pPage might be increased or decreased by one or
-** two in an effort to keep pages nearly full but not over full. The root page
-** is special and is allowed to be nearly empty. If pPage is
-** the root page, then the depth of the tree might be increased
-** or decreased by one, as necessary, to keep the root page from being
-** overfull or completely empty.
-**
-** Note that when this routine is called, some of the Cells on pPage
-** might not actually be stored in pPage->aData[]. This can happen
-** if the page is overfull. Part of the job of this routine is to
-** make sure all Cells for pPage once again fit in pPage->aData[].
-**
-** In the course of balancing the siblings of pPage, the parent of pPage
-** might become overfull or underfull. If that happens, then this routine
-** is called recursively on the parent.
+#if 0
+/*
+** This function does not contribute anything to the operation of SQLite.
+** it is sometimes activated temporarily while debugging code responsible
+** for setting pointer-map entries.
+*/
+static int ptrmapCheckPages(MemPage **apPage, int nPage){
+ int i, j;
+ for(i=0; i<nPage; i++){
+ Pgno n;
+ u8 e;
+ MemPage *pPage = apPage[i];
+ BtShared *pBt = pPage->pBt;
+ assert( pPage->isInit );
+
+ for(j=0; j<pPage->nCell; j++){
+ CellInfo info;
+ u8 *z;
+
+ z = findCell(pPage, j);
+ sqlite3BtreeParseCellPtr(pPage, z, &info);
+ if( info.iOverflow ){
+ Pgno ovfl = get4byte(&z[info.iOverflow]);
+ ptrmapGet(pBt, ovfl, &e, &n);
+ assert( n==pPage->pgno && e==PTRMAP_OVERFLOW1 );
+ }
+ if( !pPage->leaf ){
+ Pgno child = get4byte(z);
+ ptrmapGet(pBt, child, &e, &n);
+ assert( n==pPage->pgno && e==PTRMAP_BTREE );
+ }
+ }
+ if( !pPage->leaf ){
+ Pgno child = get4byte(&pPage->aData[pPage->hdrOffset+8]);
+ ptrmapGet(pBt, child, &e, &n);
+ assert( n==pPage->pgno && e==PTRMAP_BTREE );
+ }
+ }
+ return 1;
+}
+#endif
+
+
+/*
+** This routine redistributes cells on the iParentIdx'th child of pParent
+** (hereafter "the page") and up to 2 siblings so that all pages have about the
+** same amount of free space. Usually a single sibling on either side of the
+** page are used in the balancing, though both siblings might come from one
+** side if the page is the first or last child of its parent. If the page
+** has fewer than 2 siblings (something which can only happen if the page
+** is a root page or a child of a root page) then all available siblings
+** participate in the balancing.
+**
+** The number of siblings of the page might be increased or decreased by
+** one or two in an effort to keep pages nearly full but not over full.
+**
+** Note that when this routine is called, some of the cells on the page
+** might not actually be stored in MemPage.aData[]. This can happen
+** if the page is overfull. This routine ensures that all cells allocated
+** to the page and its siblings fit into MemPage.aData[] before returning.
+**
+** In the course of balancing the page and its siblings, cells may be
+** inserted into or removed from the parent page (pParent). Doing so
+** may cause the parent page to become overfull or underfull. If this
+** happens, it is the responsibility of the caller to invoke the correct
+** balancing routine to fix this problem (see the balance() routine).
**
** If this routine fails for any reason, it might leave the database
-** in a corrupted state. So if this routine fails, the database should
+** in a corrupted state. So if this routine fails, the database should
** be rolled back.
-*/
-static int balance_nonroot(BtCursor *pCur){
- MemPage *pPage; /* The over or underfull page to balance */
- MemPage *pParent; /* The parent of pPage */
+**
+** The third argument to this function, aOvflSpace, is a pointer to a
+** buffer page-size bytes in size. If, in inserting cells into the parent
+** page (pParent), the parent page becomes overfull, this buffer is
+** used to store the parents overflow cells. Because this function inserts
+** a maximum of four divider cells into the parent page, and the maximum
+** size of a cell stored within an internal node is always less than 1/4
+** of the page-size, the aOvflSpace[] buffer is guaranteed to be large
+** enough for all overflow cells.
+**
+** If aOvflSpace is set to a null pointer, this function returns
+** SQLITE_NOMEM.
+*/
+static int balance_nonroot(
+ MemPage *pParent, /* Parent page of siblings being balanced */
+ int iParentIdx, /* Index of "the page" in pParent */
+ u8 *aOvflSpace /* page-size bytes of space for parent ovfl */
+){
BtShared *pBt; /* The whole database */
int nCell = 0; /* Number of cells in apCell[] */
int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */
- int nOld = 0; /* Number of pages in apOld[] */
int nNew = 0; /* Number of pages in apNew[] */
- int nDiv; /* Number of cells in apDiv[] */
+ int nOld; /* Number of pages in apOld[] */
int i, j, k; /* Loop counters */
- int idx; /* Index of pPage in pParent->aCell[] */
int nxDiv; /* Next divider slot in pParent->aCell[] */
- int rc; /* The return code */
+ int rc = SQLITE_OK; /* The return code */
int leafCorrection; /* 4 if pPage is a leaf. 0 if not */
int leafData; /* True if pPage is a leaf of a LEAFDATA tree */
int usableSpace; /* Bytes in pPage beyond the header */
int pageFlags; /* Value of pPage->aData[0] */
int subtotal; /* Subtotal of bytes in cells on one page */
int iSpace1 = 0; /* First unused byte of aSpace1[] */
- int iSpace2 = 0; /* First unused byte of aSpace2[] */
+ int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */
int szScratch; /* Size of scratch memory requested */
MemPage *apOld[NB]; /* pPage and up to two siblings */
- Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */
MemPage *apCopy[NB]; /* Private copies of apOld[] pages */
MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */
- Pgno pgnoNew[NB+2]; /* Page numbers for each page in apNew[] */
- u8 *apDiv[NB]; /* Divider cells in pParent */
+ u8 *pRight; /* Location in parent of right-sibling pointer */
+ u8 *apDiv[NB-1]; /* Divider cells in pParent */
int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */
int szNew[NB+2]; /* Combined size of cells place on i-th page */
u8 **apCell = 0; /* All cells begin balanced */
u16 *szCell; /* Local size of all cells in apCell[] */
- u8 *aCopy[NB]; /* Space for holding data of apCopy[] */
- u8 *aSpace1; /* Space for copies of dividers cells before balance */
- u8 *aSpace2 = 0; /* Space for overflow dividers cells after balance */
- u8 *aFrom = 0;
-
- pPage = pCur->apPage[pCur->iPage];
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- VVA_ONLY( pCur->pagesShuffled = 1 );
-
- /*
- ** Find the parent page.
- */
- assert( pCur->iPage>0 );
- assert( pPage->isInit );
- assert( sqlite3PagerIswriteable(pPage->pDbPage) || pPage->nOverflow==1 );
- pBt = pPage->pBt;
- pParent = pCur->apPage[pCur->iPage-1];
- assert( pParent );
- if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){
- goto balance_cleanup;
- }
-
+ u8 *aSpace1; /* Space for copies of dividers cells */
+ Pgno pgno; /* Temp var to store a page number in */
+
+ pBt = pParent->pBt;
+ assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+
+#if 0
TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno));
-
-#ifndef SQLITE_OMIT_QUICKBALANCE
- /*
- ** A special case: If a new entry has just been inserted into a
- ** table (that is, a btree with integer keys and all data at the leaves)
- ** and the new entry is the right-most entry in the tree (it has the
- ** largest key) then use the special balance_quick() routine for
- ** balancing. balance_quick() is much faster and results in a tighter
- ** packing of data in the common case.
- */
- if( pPage->leaf &&
- pPage->intKey &&
- pPage->nOverflow==1 &&
- pPage->aOvfl[0].idx==pPage->nCell &&
- pParent->pgno!=1 &&
- get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno
- ){
- assert( pPage->intKey );
- /*
- ** TODO: Check the siblings to the left of pPage. It may be that
- ** they are not full and no new page is required.
- */
- return balance_quick(pCur);
- }
-#endif
-
- if( SQLITE_OK!=(rc = sqlite3PagerWrite(pPage->pDbPage)) ){
- goto balance_cleanup;
- }
-
- /*
- ** Find the cell in the parent page whose left child points back
- ** to pPage. The "idx" variable is the index of that cell. If pPage
- ** is the rightmost child of pParent then set idx to pParent->nCell
- */
- idx = pCur->aiIdx[pCur->iPage-1];
- assertParentIndex(pParent, idx, pPage->pgno);
-
- /*
- ** Find sibling pages to pPage and the cells in pParent that divide
- ** the siblings. An attempt is made to find NN siblings on either
- ** side of pPage. More siblings are taken from one side, however, if
- ** pPage there are fewer than NN siblings on the other side. If pParent
+#endif
+
+ /* At this point pParent may have at most one overflow cell. And if
+ ** this overflow cell is present, it must be the cell with
+ ** index iParentIdx. This scenario comes about when this function
+ ** is called (indirectly) from sqlite3BtreeDelete(). */
+ assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
+ assert( pParent->nOverflow==0 || pParent->aOvfl[0].idx==iParentIdx );
+
+ if( !aOvflSpace ){
+ return SQLITE_NOMEM;
+ }
+
+ /* Find the sibling pages to balance. Also locate the cells in pParent
+ ** that divide the siblings. An attempt is made to find NN siblings on
+ ** either side of pPage. More siblings are taken from one side, however,
+ ** if there are fewer than NN siblings on the other side. If pParent
** has NB or fewer children then all children of pParent are taken.
- */
- nxDiv = idx - NN;
- if( nxDiv + NB > pParent->nCell ){
- nxDiv = pParent->nCell - NB + 1;
- }
- if( nxDiv<0 ){
+ **
+ ** This loop also drops the divider cells from the parent page. This
+ ** way, the remainder of the function does not have to deal with any
+ ** overflow cells in the parent page, as if one existed it has already
+ ** been removed. */
+ i = pParent->nOverflow + pParent->nCell;
+ if( i<2 ){
nxDiv = 0;
- }
- nDiv = 0;
- for(i=0, k=nxDiv; i<NB; i++, k++){
- if( k<pParent->nCell ){
- apDiv[i] = findCell(pParent, k);
- nDiv++;
- assert( !pParent->leaf );
- pgnoOld[i] = get4byte(apDiv[i]);
- }else if( k==pParent->nCell ){
- pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]);
- }else{
- break;
- }
- rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i]);
- if( rc ) goto balance_cleanup;
- /* apOld[i]->idxParent = k; */
- apCopy[i] = 0;
- assert( i==nOld );
- nOld++;
+ nOld = i+1;
+ }else{
+ nOld = 3;
+ if( iParentIdx==0 ){
+ nxDiv = 0;
+ }else if( iParentIdx==i ){
+ nxDiv = i-2;
+ }else{
+ nxDiv = iParentIdx-1;
+ }
+ i = 2;
+ }
+ if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
+ pRight = &pParent->aData[pParent->hdrOffset+8];
+ }else{
+ pRight = findCell(pParent, i+nxDiv-pParent->nOverflow);
+ }
+ pgno = get4byte(pRight);
+ while( 1 ){
+ rc = getAndInitPage(pBt, pgno, &apOld[i]);
+ if( rc ){
+ memset(apOld, 0, i*sizeof(MemPage*));
+ goto balance_cleanup;
+ }
nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow;
+ if( (i--)==0 ) break;
+
+ if( pParent->nOverflow && i+nxDiv==pParent->aOvfl[0].idx ){
+ apDiv[i] = pParent->aOvfl[0].pCell;
+ pgno = get4byte(apDiv[i]);
+ szNew[i] = cellSizePtr(pParent, apDiv[i]);
+ pParent->nOverflow = 0;
+ }else{
+ apDiv[i] = findCell(pParent, i+nxDiv-pParent->nOverflow);
+ pgno = get4byte(apDiv[i]);
+ szNew[i] = cellSizePtr(pParent, apDiv[i]);
+
+ /* Drop the cell from the parent page. apDiv[i] still points to
+ ** the cell within the parent, even though it has been dropped.
+ ** This is safe because dropping a cell only overwrites the first
+ ** four bytes of it, and this function does not need the first
+ ** four bytes of the divider cell. So the pointer is safe to use
+ ** later on.
+ **
+ ** Unless SQLite is compiled in secure-delete mode. In this case,
+ ** the dropCell() routine will overwrite the entire cell with zeroes.
+ ** In this case, temporarily copy the cell into the aOvflSpace[]
+ ** buffer. It will be copied out again as soon as the aSpace[] buffer
+ ** is allocated. */
+#ifdef SQLITE_SECURE_DELETE
+ memcpy(&aOvflSpace[apDiv[i]-pParent->aData], apDiv[i], szNew[i]);
+ apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
+#endif
+ dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i]);
+ }
}
/* Make nMaxCells a multiple of 4 in order to preserve 8-byte
** alignment */
@@ -42268,54 +42357,27 @@
/*
** Allocate space for memory structures
*/
+ k = pBt->pageSize + ROUND8(sizeof(MemPage));
szScratch =
nMaxCells*sizeof(u8*) /* apCell */
+ nMaxCells*sizeof(u16) /* szCell */
- + (ROUND8(sizeof(MemPage))+pBt->pageSize)*NB /* aCopy */
+ pBt->pageSize /* aSpace1 */
- + (ISAUTOVACUUM ? nMaxCells : 0); /* aFrom */
+ + k*nOld; /* Page copies (apCopy) */
apCell = sqlite3ScratchMalloc( szScratch );
if( apCell==0 ){
rc = SQLITE_NOMEM;
goto balance_cleanup;
}
szCell = (u16*)&apCell[nMaxCells];
- aCopy[0] = (u8*)&szCell[nMaxCells];
- assert( EIGHT_BYTE_ALIGNMENT(aCopy[0]) );
- for(i=1; i<NB; i++){
- aCopy[i] = &aCopy[i-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
- assert( ((aCopy[i] - (u8*)0) & 7)==0 ); /* 8-byte alignment required */
- }
- aSpace1 = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))];
- assert( EIGHT_BYTE_ALIGNMENT(aSpace1) );
- if( ISAUTOVACUUM ){
- aFrom = &aSpace1[pBt->pageSize];
- }
- aSpace2 = sqlite3PageMalloc(pBt->pageSize);
- if( aSpace2==0 ){
- rc = SQLITE_NOMEM;
- goto balance_cleanup;
- }
-
- /*
- ** Make copies of the content of pPage and its siblings into aOld[].
- ** The rest of this function will use data from the copies rather
- ** that the original pages since the original pages will be in the
- ** process of being overwritten.
- */
- for(i=0; i<nOld; i++){
- MemPage *p = apCopy[i] = (MemPage*)aCopy[i];
- memcpy(p, apOld[i], sizeof(MemPage));
- p->aData = (void*)&p[1];
- memcpy(p->aData, apOld[i]->aData, pBt->pageSize);
- }
+ aSpace1 = (u8*)&szCell[nMaxCells];
+ assert( EIGHT_BYTE_ALIGNMENT(aSpace1) );
/*
** Load pointers to all cells on sibling pages and the divider cells
** into the local apCell[] array. Make copies of the divider cells
- ** into space obtained form aSpace1[] and remove the the divider Cells
+ ** into space obtained from aSpace1[] and remove the the divider Cells
** from pParent.
**
** If the siblings are on leaf pages, then the child pointers of the
** divider cells are stripped from the cells before they are copied
@@ -42326,70 +42388,56 @@
**
** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf.
** leafData: 1 if pPage holds key+data and pParent holds only keys.
*/
- nCell = 0;
- leafCorrection = pPage->leaf*4;
- leafData = pPage->hasData;
+ leafCorrection = apOld[0]->leaf*4;
+ leafData = apOld[0]->hasData;
for(i=0; i<nOld; i++){
- MemPage *pOld = apCopy[i];
- int limit = pOld->nCell+pOld->nOverflow;
+ int limit;
+
+ /* Before doing anything else, take a copy of the i'th original sibling
+ ** The rest of this function will use data from the copies rather
+ ** that the original pages since the original pages will be in the
+ ** process of being overwritten. */
+ MemPage *pOld = apCopy[i] = (MemPage*)&aSpace1[pBt->pageSize + k*i];
+ memcpy(pOld, apOld[i], sizeof(MemPage));
+ pOld->aData = (void*)&pOld[1];
+ memcpy(pOld->aData, apOld[i]->aData, pBt->pageSize);
+
+ limit = pOld->nCell+pOld->nOverflow;
for(j=0; j<limit; j++){
assert( nCell<nMaxCells );
apCell[nCell] = findOverflowCell(pOld, j);
szCell[nCell] = cellSizePtr(pOld, apCell[nCell]);
- if( ISAUTOVACUUM ){
- int a;
- 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;
- }
- }
- }
nCell++;
}
- if( i<nOld-1 ){
- u16 sz = cellSizePtr(pParent, apDiv[i]);
- if( leafData ){
- /* With the LEAFDATA flag, pParent cells hold only INTKEYs that
- ** are duplicates of keys on the child pages. We need to remove
- ** the divider cells from pParent, but the dividers cells are not
- ** added to apCell[] because they are duplicates of child cells.
- */
- dropCell(pParent, nxDiv, sz);
- }else{
- u8 *pTemp;
- assert( nCell<nMaxCells );
- szCell[nCell] = sz;
- pTemp = &aSpace1[iSpace1];
- iSpace1 += sz;
- assert( sz<=pBt->pageSize/4 );
- assert( iSpace1<=pBt->pageSize );
- memcpy(pTemp, apDiv[i], sz);
- apCell[nCell] = pTemp+leafCorrection;
- if( ISAUTOVACUUM ){
- aFrom[nCell] = 0xFF;
- }
- dropCell(pParent, nxDiv, sz);
- 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
- ** pointer of the divider cell */
- memcpy(apCell[nCell], &pOld->aData[pOld->hdrOffset+8], 4);
- }else{
- assert( leafCorrection==4 );
- if( szCell[nCell]<4 ){
- /* Do not allow any cells smaller than 4 bytes. */
- szCell[nCell] = 4;
- }
- }
- nCell++;
- }
+ if( i<nOld-1 && !leafData){
+ u16 sz = szNew[i];
+ u8 *pTemp;
+ assert( nCell<nMaxCells );
+ szCell[nCell] = sz;
+ pTemp = &aSpace1[iSpace1];
+ iSpace1 += sz;
+ assert( sz<=pBt->pageSize/4 );
+ assert( iSpace1<=pBt->pageSize );
+ memcpy(pTemp, apDiv[i], sz);
+ apCell[nCell] = pTemp+leafCorrection;
+ assert( leafCorrection==0 || leafCorrection==4 );
+ szCell[nCell] -= (u16)leafCorrection;
+ if( !pOld->leaf ){
+ assert( leafCorrection==0 );
+ assert( pOld->hdrOffset==0 );
+ /* The right pointer of the child page pOld becomes the left
+ ** pointer of the divider cell */
+ memcpy(apCell[nCell], &pOld->aData[8], 4);
+ }else{
+ assert( leafCorrection==4 );
+ if( szCell[nCell]<4 ){
+ /* Do not allow any cells smaller than 4 bytes. */
+ szCell[nCell] = 4;
+ }
+ }
+ nCell++;
}
}
/*
@@ -42417,8 +42465,9 @@
cntNew[k] = i;
if( leafData ){ i--; }
subtotal = 0;
k++;
+ if( k>NB+1 ){ rc = SQLITE_CORRUPT; goto balance_cleanup; }
}
}
szNew[k] = subtotal;
cntNew[k] = nCell;
@@ -42460,28 +42509,44 @@
** page is page 1 and we are the only child of that page.
*/
assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) );
+ TRACE(("BALANCE: old: %d %d %d ",
+ apOld[0]->pgno,
+ nOld>=2 ? apOld[1]->pgno : 0,
+ nOld>=3 ? apOld[2]->pgno : 0
+ ));
+
/*
** Allocate k new pages. Reuse old pages where possible.
*/
- assert( pPage->pgno>1 );
- pageFlags = pPage->aData[0];
+ if( apOld[0]->pgno<=1 ){
+ rc = SQLITE_CORRUPT;
+ goto balance_cleanup;
+ }
+ pageFlags = apOld[0]->aData[0];
for(i=0; i<k; i++){
MemPage *pNew;
if( i<nOld ){
pNew = apNew[i] = apOld[i];
- pgnoNew[i] = pgnoOld[i];
apOld[i] = 0;
rc = sqlite3PagerWrite(pNew->pDbPage);
nNew++;
if( rc ) goto balance_cleanup;
}else{
assert( i>0 );
- rc = allocateBtreePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0);
+ rc = allocateBtreePage(pBt, &pNew, &pgno, pgno, 0);
if( rc ) goto balance_cleanup;
apNew[i] = pNew;
nNew++;
+
+ /* Set the pointer-map entry for the new sibling page. */
+ if( ISAUTOVACUUM ){
+ rc = ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno);
+ if( rc!=SQLITE_OK ){
+ goto balance_cleanup;
+ }
+ }
}
}
/* Free any old pages that were not reused as new pages.
@@ -42508,36 +42573,34 @@
** When NB==3, this one optimization makes the database
** about 25% faster for large insertions and deletions.
*/
for(i=0; i<k-1; i++){
- int minV = pgnoNew[i];
+ int minV = apNew[i]->pgno;
int minI = i;
for(j=i+1; j<k; j++){
- if( pgnoNew[j]<(unsigned)minV ){
+ if( apNew[j]->pgno<(unsigned)minV ){
minI = j;
- minV = pgnoNew[j];
+ minV = apNew[j]->pgno;
}
}
if( minI>i ){
int t;
MemPage *pT;
- t = pgnoNew[i];
+ t = apNew[i]->pgno;
pT = apNew[i];
- pgnoNew[i] = pgnoNew[minI];
- apNew[i] = apNew[minI];
- pgnoNew[minI] = t;
+ apNew[i] = apNew[minI];
apNew[minI] = pT;
}
}
- TRACE(("BALANCE: old: %d %d %d new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n",
- pgnoOld[0],
- nOld>=2 ? pgnoOld[1] : 0,
- nOld>=3 ? pgnoOld[2] : 0,
- pgnoNew[0], szNew[0],
- nNew>=2 ? pgnoNew[1] : 0, nNew>=2 ? szNew[1] : 0,
- nNew>=3 ? pgnoNew[2] : 0, nNew>=3 ? szNew[2] : 0,
- nNew>=4 ? pgnoNew[3] : 0, nNew>=4 ? szNew[3] : 0,
- nNew>=5 ? pgnoNew[4] : 0, nNew>=5 ? szNew[4] : 0));
+ TRACE(("new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n",
+ apNew[0]->pgno, szNew[0],
+ nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0,
+ nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0,
+ nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0,
+ nNew>=5 ? apNew[4]->pgno : 0, nNew>=5 ? szNew[4] : 0));
+
+ assert( sqlite3PagerIswriteable(pParent->pDbPage) );
+ put4byte(pRight, apNew[nNew-1]->pgno);
/*
** Evenly distribute the data in apCell[] across the new pages.
** Insert divider cells into pParent as necessary.
@@ -42546,33 +42609,12 @@
for(i=0; i<nNew; i++){
/* Assemble the new sibling page. */
MemPage *pNew = apNew[i];
assert( j<nMaxCells );
- assert( pNew->pgno==pgnoNew[i] );
zeroPage(pNew, pageFlags);
assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]);
assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) );
assert( pNew->nOverflow==0 );
-
- /* If this is an auto-vacuum database, update the pointer map entries
- ** that point to the siblings that were rearranged. These can be: left
- ** children of cells, the right-child of the page, or overflow pages
- ** pointed to by cells.
- */
- if( ISAUTOVACUUM ){
- for(k=j; k<cntNew[i]; k++){
- assert( k<nMaxCells );
- if( aFrom[k]==0xFF || apCopy[aFrom[k]]->pgno!=pNew->pgno ){
- rc = ptrmapPutOvfl(pNew, k-j);
- if( rc==SQLITE_OK && leafCorrection==0 ){
- rc = ptrmapPut(pBt, get4byte(apCell[k]), PTRMAP_BTREE, pNew->pgno);
- }
- if( rc!=SQLITE_OK ){
- goto balance_cleanup;
- }
- }
- }
- }
j = cntNew[i];
/* If the sibling page assembled above was not the right-most sibling,
@@ -42585,19 +42627,11 @@
assert( j<nMaxCells );
pCell = apCell[j];
sz = szCell[j] + leafCorrection;
- pTemp = &aSpace2[iSpace2];
+ pTemp = &aOvflSpace[iOvflSpace];
if( !pNew->leaf ){
memcpy(&pNew->aData[8], pCell, 4);
- if( ISAUTOVACUUM
- && (aFrom[j]==0xFF || apCopy[aFrom[j]]->pgno!=pNew->pgno)
- ){
- rc = ptrmapPut(pBt, get4byte(pCell), PTRMAP_BTREE, pNew->pgno);
- if( rc!=SQLITE_OK ){
- goto balance_cleanup;
- }
- }
}else if( leafData ){
/* If the tree is a leaf-data tree, and the siblings are leaves,
** then there is no divider cell in apCell[]. Instead, the divider
** cell consists of the integer key for the right-most cell of
@@ -42606,12 +42640,9 @@
CellInfo info;
j--;
sqlite3BtreeParseCellPtr(pNew, apCell[j], &info);
pCell = pTemp;
- rc = fillInCell(pParent, pCell, 0, info.nKey, 0, 0, 0, &sz);
- if( rc!=SQLITE_OK ){
- goto balance_cleanup;
- }
+ sz = 4 + putVarint(&pCell[4], info.nKey);
pTemp = 0;
}else{
pCell -= 4;
/* Obscure case for non-leaf-data trees: If the cell at pCell was
@@ -42629,36 +42660,17 @@
assert(leafCorrection==4);
sz = cellSizePtr(pParent, pCell);
}
}
- iSpace2 += sz;
+ iOvflSpace += sz;
assert( sz<=pBt->pageSize/4 );
- assert( iSpace2<=pBt->pageSize );
- rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4);
+ assert( iOvflSpace<=pBt->pageSize );
+ rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno);
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
- ** that the cell just inserted points to (if any).
- */
- if( ISAUTOVACUUM && !leafData ){
- rc = ptrmapPutOvfl(pParent, nxDiv);
- if( rc!=SQLITE_OK ){
- goto balance_cleanup;
- }
- }
+
j++;
nxDiv++;
- }
-
- /* Set the pointer-map entry for the new sibling page. */
- if( ISAUTOVACUUM ){
- rc = ptrmapPut(pBt, pNew->pgno, PTRMAP_BTREE, pParent->pgno);
- if( rc!=SQLITE_OK ){
- goto balance_cleanup;
- }
}
}
assert( j==nCell );
assert( nOld>0 );
@@ -42665,262 +42677,438 @@
assert( nNew>0 );
if( (pageFlags & PTF_LEAF)==0 ){
u8 *zChild = &apCopy[nOld-1]->aData[8];
memcpy(&apNew[nNew-1]->aData[8], zChild, 4);
- if( ISAUTOVACUUM ){
- rc = ptrmapPut(pBt, get4byte(zChild), PTRMAP_BTREE, apNew[nNew-1]->pgno);
- if( rc!=SQLITE_OK ){
- goto balance_cleanup;
- }
- }
- }
- 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{
- /* Right-most sibling is the left child of the first entry in pParent
- ** past the right-most divider entry */
- put4byte(findOverflowCell(pParent, nxDiv), pgnoNew[nNew-1]);
- }
-
- /*
- ** Balance the parent page. Note that the current page (pPage) might
- ** have been added to the freelist so it might no longer be initialized.
- ** But the parent page will always be initialized.
- */
+ }
+
+ /* Fix the pointer-map entries for all the cells that were shifted around.
+ ** There are several different types of pointer-map entries that need to
+ ** be dealt with by this routine. Some of these have been set already, but
+ ** many have not. The following is a summary:
+ **
+ ** 1) The entries associated with new sibling pages that were not
+ ** siblings when this function was called. These have already
+ ** been set. We don't need to worry about old siblings that were
+ ** moved to the free-list - the freePage() code has taken care
+ ** of those.
+ **
+ ** 2) The pointer-map entries associated with the first overflow
+ ** page in any overflow chains used by new divider cells. These
+ ** have also already been taken care of by the insertCell() code.
+ **
+ ** 3) If the sibling pages are not leaves, then the child pages of
+ ** cells stored on the sibling pages may need to be updated.
+ **
+ ** 4) If the sibling pages are not internal intkey nodes, then any
+ ** overflow pages used by these cells may need to be updated
+ ** (internal intkey nodes never contain pointers to overflow pages).
+ **
+ ** 5) If the sibling pages are not leaves, then the pointer-map
+ ** entries for the right-child pages of each sibling may need
+ ** to be updated.
+ **
+ ** Cases 1 and 2 are dealt with above by other code. The following
+ ** block deals with cases 3 and 4. Since setting a pointer map entry
+ ** is a relatively expensive operation, this code only sets pointer
+ ** map entries for child or overflow pages that have actually moved
+ ** between pages. */
+ if( ISAUTOVACUUM ){
+ MemPage *pNew = apNew[0];
+ MemPage *pOld = apCopy[0];
+ int nOverflow = pOld->nOverflow;
+ int iNextOld = pOld->nCell + nOverflow;
+ int iOverflow = (nOverflow ? pOld->aOvfl[0].idx : -1);
+ j = 0; /* Current 'old' sibling page */
+ k = 0; /* Current 'new' sibling page */
+ for(i=0; i<nCell && rc==SQLITE_OK; i++){
+ int isDivider = 0;
+ while( i==iNextOld ){
+ /* Cell i is the cell immediately following the last cell on old
+ ** sibling page j. If the siblings are not leaf pages of an
+ ** intkey b-tree, then cell i was a divider cell. */
+ pOld = apCopy[++j];
+ iNextOld = i + !leafData + pOld->nCell + pOld->nOverflow;
+ if( pOld->nOverflow ){
+ nOverflow = pOld->nOverflow;
+ iOverflow = i + !leafData + pOld->aOvfl[0].idx;
+ }
+ isDivider = !leafData;
+ }
+
+ assert(nOverflow>0 || iOverflow<i );
+ assert(nOverflow<2 || pOld->aOvfl[0].idx==pOld->aOvfl[1].idx-1);
+ assert(nOverflow<3 || pOld->aOvfl[1].idx==pOld->aOvfl[2].idx-1);
+ if( i==iOverflow ){
+ isDivider = 1;
+ if( (--nOverflow)>0 ){
+ iOverflow++;
+ }
+ }
+
+ if( i==cntNew[k] ){
+ /* Cell i is the cell immediately following the last cell on new
+ ** sibling page k. If the siblings are not leaf pages of an
+ ** intkey b-tree, then cell i is a divider cell. */
+ pNew = apNew[++k];
+ if( !leafData ) continue;
+ }
+ assert( rc==SQLITE_OK );
+ assert( j<nOld );
+ assert( k<nNew );
+
+ /* If the cell was originally divider cell (and is not now) or
+ ** an overflow cell, or if the cell was located on a different sibling
+ ** page before the balancing, then the pointer map entries associated
+ ** with any child or overflow pages need to be updated. */
+ if( isDivider || pOld->pgno!=pNew->pgno ){
+ if( !leafCorrection ){
+ rc = ptrmapPut(pBt, get4byte(apCell[i]), PTRMAP_BTREE, pNew->pgno);
+ }
+ if( szCell[i]>pNew->minLocal && rc==SQLITE_OK ){
+ rc = ptrmapPutOvflPtr(pNew, apCell[i]);
+ }
+ }
+ }
+
+ if( !leafCorrection ){
+ for(i=0; rc==SQLITE_OK && i<nNew; i++){
+ rc = ptrmapPut(
+ pBt, get4byte(&apNew[i]->aData[8]), PTRMAP_BTREE, apNew[i]->pgno);
+ }
+ }
+
+#if 0
+ /* The ptrmapCheckPages() contains assert() statements that verify that
+ ** all pointer map pages are set correctly. This is helpful while
+ ** debugging. This is usually disabled because a corrupt database may
+ ** cause an assert() statement to fail. */
+ ptrmapCheckPages(apNew, nNew);
+ ptrmapCheckPages(&pParent, 1);
+#endif
+ }
+
assert( pParent->isInit );
- sqlite3ScratchFree(apCell);
- apCell = 0;
- TRACE(("BALANCE: finished with %d: old=%d new=%d cells=%d\n",
- pPage->pgno, nOld, nNew, nCell));
- pPage->nOverflow = 0;
- releasePage(pPage);
- pCur->iPage--;
- rc = balance(pCur, 0);
+ TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n",
+ nOld, nNew, nCell));
/*
** Cleanup before returning.
*/
balance_cleanup:
- sqlite3PageFree(aSpace2);
sqlite3ScratchFree(apCell);
for(i=0; i<nOld; i++){
releasePage(apOld[i]);
}
for(i=0; i<nNew; i++){
releasePage(apNew[i]);
}
- pCur->apPage[pCur->iPage]->nOverflow = 0;
-
- return rc;
-}
-
-/*
-** This routine is called for the root page of a btree when the root
-** page contains no cells. This is an opportunity to make the tree
+
+ return rc;
+}
+
+/*
+** This function is used to copy the contents of the b-tree node stored
+** on page pFrom to page pTo. If page pFrom was not a leaf page, then
+** the pointer-map entries for each child page are updated so that the
+** parent page stored in the pointer map is page pTo. If pFrom contained
+** any cells with overflow page pointers, then the corresponding pointer
+** map entries are also updated so that the parent page is page pTo.
+**
+** If pFrom is currently carrying any overflow cells (entries in the
+** MemPage.aOvfl[] array), they are not copied to pTo.
+**
+** Before returning, page pTo is reinitialized using sqlite3BtreeInitPage().
+**
+** The performance of this function is not critical. It is only used by
+** the balance_shallower() and balance_deeper() procedures, neither of
+** which are called often under normal circumstances.
+*/
+static int copyNodeContent(MemPage *pFrom, MemPage *pTo){
+ BtShared * const pBt = pFrom->pBt;
+ u8 * const aFrom = pFrom->aData;
+ u8 * const aTo = pTo->aData;
+ int const iFromHdr = pFrom->hdrOffset;
+ int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
+ int rc = SQLITE_OK;
+ int iData;
+
+ assert( pFrom->isInit );
+ assert( pFrom->nFree>=iToHdr );
+ assert( get2byte(&aFrom[iFromHdr+5])<=pBt->usableSize );
+
+ /* Copy the b-tree node content from page pFrom to page pTo. */
+ iData = get2byte(&aFrom[iFromHdr+5]);
+ memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
+ memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
+
+ /* Reinitialize page pTo so that the contents of the MemPage structure
+ ** match the new data. The initialization of pTo "cannot" fail, as the
+ ** data copied from pFrom is known to be valid. */
+ pTo->isInit = 0;
+ TESTONLY(rc = ) sqlite3BtreeInitPage(pTo);
+ assert( rc==SQLITE_OK );
+
+ /* If this is an auto-vacuum database, update the pointer-map entries
+ ** for any b-tree or overflow pages that pTo now contains the pointers to. */
+ if( ISAUTOVACUUM ){
+ rc = setChildPtrmaps(pTo);
+ }
+ return rc;
+}
+
+/*
+** This routine is called on the root page of a btree when the root
+** page contains no cells. This is an opportunity to make the tree
** shallower by one level.
*/
-static int balance_shallower(BtCursor *pCur){
- MemPage *pPage; /* Root page of B-Tree */
- MemPage *pChild; /* The only child page of pPage */
- Pgno pgnoChild; /* Page number for pChild */
- int rc = SQLITE_OK; /* Return code from subprocedures */
- BtShared *pBt; /* The main BTree structure */
- int mxCellPerPage; /* Maximum number of cells per page */
- u8 **apCell; /* All cells from pages being balanced */
- u16 *szCell; /* Local size of all cells */
-
- assert( pCur->iPage==0 );
- pPage = pCur->apPage[0];
-
- assert( pPage->nCell==0 );
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- pBt = pPage->pBt;
- mxCellPerPage = MX_CELL(pBt);
- apCell = sqlite3Malloc( mxCellPerPage*(sizeof(u8*)+sizeof(u16)) );
- if( apCell==0 ) return SQLITE_NOMEM;
- szCell = (u16*)&apCell[mxCellPerPage];
- if( pPage->leaf ){
- /* The table is completely empty */
- TRACE(("BALANCE: empty table %d\n", pPage->pgno));
- }else{
- /* The root page is empty but has one child. Transfer the
- ** information from that one child into the root page if it
- ** will fit. This reduces the depth of the tree by one.
- **
- ** If the root page is page 1, it has less space available than
- ** its child (due to the 100 byte header that occurs at the beginning
- ** of the database fle), so it might not be able to hold all of the
- ** information currently contained in the child. If this is the
- ** case, then do not do the transfer. Leave page 1 empty except
- ** for the right-pointer to the child page. The child page becomes
- ** the virtual root of the tree.
- */
- VVA_ONLY( pCur->pagesShuffled = 1 );
- pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]);
- assert( pgnoChild>0 );
- assert( pgnoChild<=pagerPagecount(pPage->pBt) );
- rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0);
- if( rc ) goto end_shallow_balance;
- if( pPage->pgno==1 ){
- rc = sqlite3BtreeInitPage(pChild);
- if( rc ) goto end_shallow_balance;
- assert( pChild->nOverflow==0 );
- if( pChild->nFree>=100 ){
- /* The child information will fit on the root page, so do the
- ** copy */
- int i;
- zeroPage(pPage, pChild->aData[0]);
- for(i=0; i<pChild->nCell; i++){
- apCell[i] = findCell(pChild,i);
- 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]));
+static int balance_shallower(MemPage *pRoot){
+ /* The root page is empty but has one child. Transfer the
+ ** information from that one child into the root page if it
+ ** will fit. This reduces the depth of the tree by one.
+ **
+ ** If the root page is page 1, it has less space available than
+ ** its child (due to the 100 byte header that occurs at the beginning
+ ** of the database fle), so it might not be able to hold all of the
+ ** information currently contained in the child. If this is the
+ ** case, then do not do the transfer. Leave page 1 empty except
+ ** for the right-pointer to the child page. The child page becomes
+ ** the virtual root of the tree.
+ */
+ int rc = SQLITE_OK; /* Return code */
+ int const hdr = pRoot->hdrOffset; /* Offset of root page header */
+ MemPage *pChild; /* Only child of pRoot */
+ Pgno const pgnoChild = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
+
+ assert( pRoot->nCell==0 );
+ assert( sqlite3_mutex_held(pRoot->pBt->mutex) );
+ assert( !pRoot->leaf );
+ assert( pgnoChild>0 );
+ assert( pgnoChild<=pagerPagecount(pRoot->pBt) );
+ assert( hdr==0 || pRoot->pgno==1 );
+
+ rc = sqlite3BtreeGetPage(pRoot->pBt, pgnoChild, &pChild, 0);
+ if( rc==SQLITE_OK ){
+ if( pChild->nFree>=hdr ){
+ if( hdr ){
+ rc = defragmentPage(pChild);
+ }
+ if( rc==SQLITE_OK ){
+ rc = copyNodeContent(pChild, pRoot);
+ }
+ if( rc==SQLITE_OK ){
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. */
- TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno));
- }
- }else{
- memcpy(pPage->aData, pChild->aData, pPage->pBt->usableSize);
- pPage->isInit = 0;
- rc = sqlite3BtreeInitPage(pPage);
- assert( rc==SQLITE_OK );
- freePage(pChild);
- TRACE(("BALANCE: transfer child %d into root %d\n",
- pChild->pgno, pPage->pgno));
- }
- assert( pPage->nOverflow==0 );
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( ISAUTOVACUUM && rc==SQLITE_OK ){
- rc = setChildPtrmaps(pPage);
- }
-#endif
+ }
+ }else{
+ /* The child has more information that will fit on the root.
+ ** The tree is already balanced. Do nothing. */
+ TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno));
+ }
+ releasePage(pChild);
+ }
+
+ return rc;
+}
+
+
+/*
+** This function is called when the root page of a b-tree structure is
+** overfull (has one or more overflow pages).
+**
+** A new child page is allocated and the contents of the current root
+** page, including overflow cells, are copied into the child. The root
+** page is then overwritten to make it an empty page with the right-child
+** pointer pointing to the new page.
+**
+** Before returning, all pointer-map entries corresponding to pages
+** that the new child-page now contains pointers to are updated. The
+** entry corresponding to the new right-child pointer of the root
+** page is also updated.
+**
+** If successful, *ppChild is set to contain a reference to the child
+** page and SQLITE_OK is returned. In this case the caller is required
+** to call releasePage() on *ppChild exactly once. If an error occurs,
+** an error code is returned and *ppChild is set to 0.
+*/
+static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
+ int rc; /* Return value from subprocedures */
+ MemPage *pChild = 0; /* Pointer to a new child page */
+ Pgno pgnoChild; /* Page number of the new child page */
+ BtShared *pBt = pRoot->pBt; /* The BTree */
+
+ assert( pRoot->nOverflow>0 );
+ assert( sqlite3_mutex_held(pBt->mutex) );
+
+ /* Make pRoot, the root page of the b-tree, writable. Allocate a new
+ ** page that will become the new right-child of pPage. Copy the contents
+ ** of the node stored on pRoot into the new child page.
+ */
+ if( SQLITE_OK!=(rc = sqlite3PagerWrite(pRoot->pDbPage))
+ || SQLITE_OK!=(rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0))
+ || SQLITE_OK!=(rc = copyNodeContent(pRoot, pChild))
+ || (ISAUTOVACUUM &&
+ SQLITE_OK!=(rc = ptrmapPut(pBt, pgnoChild, PTRMAP_BTREE, pRoot->pgno)))
+ ){
+ *ppChild = 0;
releasePage(pChild);
- }
-end_shallow_balance:
- sqlite3_free(apCell);
- return rc;
-}
-
-
-/*
-** The root page is overfull
-**
-** When this happens, Create a new child page and copy the
-** contents of the root into the child. Then make the root
-** page an empty page with rightChild pointing to the new
-** child. Finally, call balance_internal() on the new child
-** to cause it to split.
-*/
-static int balance_deeper(BtCursor *pCur){
- int rc; /* Return value from subprocedures */
- MemPage *pPage; /* Pointer to the root page */
- MemPage *pChild; /* Pointer to a new child page */
- Pgno pgnoChild; /* Page number of the new child page */
- BtShared *pBt; /* The BTree */
- int usableSize; /* Total usable size of a page */
- u8 *data; /* Content of the parent page */
- u8 *cdata; /* Content of the child page */
- int hdr; /* Offset to page header in parent */
- int cbrk; /* Offset to content of first cell in parent */
-
- assert( pCur->iPage==0 );
- assert( pCur->apPage[0]->nOverflow>0 );
-
- VVA_ONLY( pCur->pagesShuffled = 1 );
- pPage = pCur->apPage[0];
- pBt = pPage->pBt;
- assert( sqlite3_mutex_held(pBt->mutex) );
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0);
- if( rc ) return rc;
+ return rc;
+ }
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
- usableSize = pBt->usableSize;
- data = pPage->aData;
- hdr = pPage->hdrOffset;
- cbrk = get2byte(&data[hdr+5]);
- cdata = pChild->aData;
- memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr);
- memcpy(&cdata[cbrk], &data[cbrk], usableSize-cbrk);
-
- assert( pChild->isInit==0 );
- rc = sqlite3BtreeInitPage(pChild);
- if( rc==SQLITE_OK ){
- int nCopy = pPage->nOverflow*sizeof(pPage->aOvfl[0]);
- memcpy(pChild->aOvfl, pPage->aOvfl, nCopy);
- pChild->nOverflow = pPage->nOverflow;
- if( pChild->nOverflow ){
- pChild->nFree = 0;
- }
- assert( pChild->nCell==pPage->nCell );
- 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 ){
- rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno);
-#ifndef SQLITE_OMIT_AUTOVACUUM
- if( rc==SQLITE_OK ){
- rc = setChildPtrmaps(pChild);
- }
- if( rc ){
- pChild->nOverflow = 0;
- }
-#endif
- }
- }
-
- if( rc==SQLITE_OK ){
- pCur->iPage++;
- pCur->apPage[1] = pChild;
- pCur->aiIdx[0] = 0;
- rc = balance_nonroot(pCur);
- }else{
- releasePage(pChild);
- }
-
- return rc;
+ assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
+ assert( pChild->nCell==pRoot->nCell );
+
+ TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno));
+
+ /* Copy the overflow cells from pRoot to pChild */
+ memcpy(pChild->aOvfl, pRoot->aOvfl, pRoot->nOverflow*sizeof(pRoot->aOvfl[0]));
+ pChild->nOverflow = pRoot->nOverflow;
+
+ /* Zero the contents of pRoot. Then install pChild as the right-child. */
+ zeroPage(pRoot, pChild->aData[0] & ~PTF_LEAF);
+ put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);
+
+ *ppChild = pChild;
+ return SQLITE_OK;
}
/*
** The page that pCur currently points to has just been modified in
** some way. This function figures out if this modification means the
** tree needs to be balanced, and if so calls the appropriate balancing
-** routine.
-**
-** Parameter isInsert is true if a new cell was just inserted into the
-** page, or false otherwise.
-*/
-static int balance(BtCursor *pCur, int isInsert){
- int rc = SQLITE_OK;
- MemPage *pPage = pCur->apPage[pCur->iPage];
-
- assert( sqlite3_mutex_held(pPage->pBt->mutex) );
- if( pCur->iPage==0 ){
- rc = sqlite3PagerWrite(pPage->pDbPage);
- if( rc==SQLITE_OK && pPage->nOverflow>0 ){
- rc = balance_deeper(pCur);
- assert( pCur->apPage[0]==pPage );
- assert( pPage->nOverflow==0 || rc!=SQLITE_OK );
- }
- if( rc==SQLITE_OK && pPage->nCell==0 ){
- rc = balance_shallower(pCur);
- assert( pCur->apPage[0]==pPage );
- assert( pPage->nOverflow==0 || rc!=SQLITE_OK );
- }
- }else{
- if( pPage->nOverflow>0 ||
- (!isInsert && pPage->nFree>pPage->pBt->usableSize*2/3) ){
- rc = balance_nonroot(pCur);
- }
+** routine. Balancing routines are:
+**
+** balance_quick()
+** balance_shallower()
+** balance_deeper()
+** balance_nonroot()
+**
+** If built with SQLITE_DEBUG, pCur->pagesShuffled is set to true if
+** balance_shallower(), balance_deeper() or balance_nonroot() is called.
+** If none of these functions are invoked, pCur->pagesShuffled is left
+** unmodified.
+*/
+static int balance(BtCursor *pCur){
+ int rc = SQLITE_OK;
+ const int nMin = pCur->pBt->usableSize * 2 / 3;
+ u8 aBalanceQuickSpace[13];
+ u8 *pFree = 0;
+
+ TESTONLY( int balance_quick_called = 0 );
+ TESTONLY( int balance_deeper_called = 0 );
+
+ do {
+ int iPage = pCur->iPage;
+ MemPage *pPage = pCur->apPage[iPage];
+
+ if( iPage==0 ){
+ if( pPage->nOverflow ){
+ /* The root page of the b-tree is overfull. In this case call the
+ ** balance_deeper() function to create a new child for the root-page
+ ** and copy the current contents of the root-page to it. The
+ ** next iteration of the do-loop will balance the child page.
+ */
+ assert( (balance_deeper_called++)==0 );
+ rc = balance_deeper(pPage, &pCur->apPage[1]);
+ if( rc==SQLITE_OK ){
+ pCur->iPage = 1;
+ pCur->aiIdx[0] = 0;
+ pCur->aiIdx[1] = 0;
+ assert( pCur->apPage[1]->nOverflow );
+ }
+ VVA_ONLY( pCur->pagesShuffled = 1 );
+ }else{
+ /* The root page of the b-tree is now empty. If the root-page is not
+ ** also a leaf page, it will have a single child page. Call
+ ** balance_shallower to attempt to copy the contents of the single
+ ** child-page into the root page (this may not be possible if the
+ ** root page is page 1).
+ **
+ ** Whether or not this is possible , the tree is now balanced.
+ ** Therefore is no next iteration of the do-loop.
+ */
+ if( pPage->nCell==0 && !pPage->leaf ){
+ rc = balance_shallower(pPage);
+ VVA_ONLY( pCur->pagesShuffled = 1 );
+ }
+ break;
+ }
+ }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
+ break;
+ }else{
+ MemPage * const pParent = pCur->apPage[iPage-1];
+ int const iIdx = pCur->aiIdx[iPage-1];
+
+ rc = sqlite3PagerWrite(pParent->pDbPage);
+ if( rc==SQLITE_OK ){
+#ifndef SQLITE_OMIT_QUICKBALANCE
+ if( pPage->hasData
+ && pPage->nOverflow==1
+ && pPage->aOvfl[0].idx==pPage->nCell
+ && pParent->pgno!=1
+ && pParent->nCell==iIdx
+ ){
+ /* Call balance_quick() to create a new sibling of pPage on which
+ ** to store the overflow cell. balance_quick() inserts a new cell
+ ** into pParent, which may cause pParent overflow. If this
+ ** happens, the next interation of the do-loop will balance pParent
+ ** use either balance_nonroot() or balance_deeper(). Until this
+ ** happens, the overflow cell is stored in the aBalanceQuickSpace[]
+ ** buffer.
+ **
+ ** The purpose of the following assert() is to check that only a
+ ** single call to balance_quick() is made for each call to this
+ ** function. If this were not verified, a subtle bug involving reuse
+ ** of the aBalanceQuickSpace[] might sneak in.
+ */
+ assert( (balance_quick_called++)==0 );
+ rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
+ }else
+#endif
+ {
+ /* In this case, call balance_nonroot() to redistribute cells
+ ** between pPage and up to 2 of its sibling pages. This involves
+ ** modifying the contents of pParent, which may cause pParent to
+ ** become overfull or underfull. The next iteration of the do-loop
+ ** will balance the parent page to correct this.
+ **
+ ** If the parent page becomes overfull, the overflow cell or cells
+ ** are stored in the pSpace buffer allocated immediately below.
+ ** A subsequent iteration of the do-loop will deal with this by
+ ** calling balance_nonroot() (balance_deeper() may be called first,
+ ** but it doesn't deal with overflow cells - just moves them to a
+ ** different page). Once this subsequent call to balance_nonroot()
+ ** has completed, it is safe to release the pSpace buffer used by
+ ** the previous call, as the overflow cell data will have been
+ ** copied either into the body of a database page or into the new
+ ** pSpace buffer passed to the latter call to balance_nonroot().
+ */
+ u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
+ rc = balance_nonroot(pParent, iIdx, pSpace);
+ if( pFree ){
+ /* If pFree is not NULL, it points to the pSpace buffer used
+ ** by a previous call to balance_nonroot(). Its contents are
+ ** now stored either on real database pages or within the
+ ** new pSpace buffer, so it may be safely freed here. */
+ sqlite3PageFree(pFree);
+ }
+
+ /* The pSpace buffer will be freed after the next call to
+ ** balance_nonroot(), or just before this function returns, whichever
+ ** comes first. */
+ pFree = pSpace;
+ VVA_ONLY( pCur->pagesShuffled = 1 );
+ }
+ }
+
+ pPage->nOverflow = 0;
+
+ /* The next iteration of the do-loop balances the parent page. */
+ releasePage(pPage);
+ pCur->iPage--;
+ }
+ }while( rc==SQLITE_OK );
+
+ if( pFree ){
+ sqlite3PageFree(pFree);
}
return rc;
}
@@ -43062,8 +43250,9 @@
SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
)){
return rc;
}
+ assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
pPage = pCur->apPage[pCur->iPage];
assert( pPage->intKey || nKey>=0 );
assert( pPage->leaf || !pPage->intKey );
@@ -43078,9 +43267,9 @@
if( rc ) goto end_insert;
assert( szNew==cellSizePtr(pPage, newCell) );
assert( szNew<=MX_CELL_SIZE(pBt) );
idx = pCur->aiIdx[pCur->iPage];
- if( loc==0 && CURSOR_VALID==pCur->eState ){
+ if( loc==0 ){
u16 szOld;
assert( idx<pPage->nCell );
rc = sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
@@ -43099,49 +43288,47 @@
}
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->leaf );
idx = ++pCur->aiIdx[pCur->iPage];
- pCur->info.nSize = 0;
- pCur->validNKey = 0;
}else{
assert( pPage->leaf );
}
rc = insertCell(pPage, idx, newCell, szNew, 0, 0);
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
- /* If no error has occured, call balance() to deal with any overflow and
- ** move the cursor to point at the root of the table (since balance may
- ** have rearranged the table in such a way as to invalidate BtCursor.apPage[]
- ** or BtCursor.aiIdx[]).
- **
- ** Except, if all of the following are true, do nothing:
- **
- ** * Inserting the new cell did not cause overflow,
- **
- ** * Before inserting the new cell the cursor was pointing at the
- ** largest key in an intkey B-Tree, and
- **
- ** * The key value associated with the new cell is now the largest
- ** in the B-Tree.
- **
- ** In this case the cursor can be safely left pointing at the (new)
- ** largest key value in the B-Tree. Doing so speeds up inserting a set
- ** of entries with increasing integer key values via a single cursor
- ** (comes up with "INSERT INTO ... SELECT ..." statements), as
- ** the next insert operation is not required to seek the cursor.
- */
- if( rc==SQLITE_OK
- && (pPage->nOverflow || !pCur->atLast || loc>=0 || !pCur->apPage[0]->intKey)
- ){
- rc = balance(pCur, 1);
- if( rc==SQLITE_OK ){
- moveToRoot(pCur);
- }
- }
-
- /* Must make sure nOverflow is reset to zero even if the balance()
- ** fails. Internal data structure corruption will result otherwise. */
- pCur->apPage[pCur->iPage]->nOverflow = 0;
+ /* If no error has occured and pPage has an overflow cell, call balance()
+ ** to redistribute the cells within the tree. Since balance() may move
+ ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
+ ** variables.
+ **
+ ** Previous versions of SQLite called moveToRoot() to move the cursor
+ ** back to the root page as balance() used to invalidate the contents
+ ** of BtCursor.apPage[] and BtCursor.aiIdx[]. Instead of doing that,
+ ** set the cursor state to "invalid". This makes common insert operations
+ ** slightly faster.
+ **
+ ** There is a subtle but important optimization here too. When inserting
+ ** multiple records into an intkey b-tree using a single cursor (as can
+ ** happen while processing an "INSERT INTO ... SELECT" statement), it
+ ** is advantageous to leave the cursor pointing to the last entry in
+ ** the b-tree if possible. If the cursor is left pointing to the last
+ ** entry in the table, and the next row inserted has an integer key
+ ** larger than the largest existing key, it is possible to insert the
+ ** row without seeking the cursor. This can be a big performance boost.
+ */
+ pCur->info.nSize = 0;
+ pCur->validNKey = 0;
+ if( rc==SQLITE_OK && pPage->nOverflow ){
+ rc = balance(pCur);
+
+ /* Must make sure nOverflow is reset to zero even if the balance()
+ ** fails. Internal data structure corruption will result otherwise.
+ ** Also, set the cursor state to invalid. This stops saveCursorPosition()
+ ** from trying to save the current position of the cursor. */
+ pCur->apPage[pCur->iPage]->nOverflow = 0;
+ pCur->eState = CURSOR_INVALID;
+ }
+ assert( pCur->apPage[pCur->iPage]->nOverflow==0 );
end_insert:
return rc;
}
@@ -43150,200 +43337,112 @@
** Delete the entry that the cursor is pointing to. The cursor
** is left pointing at a arbitrary location.
*/
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){
- MemPage *pPage = pCur->apPage[pCur->iPage];
- int idx;
- unsigned char *pCell;
- int rc;
- Pgno pgnoChild = 0;
Btree *p = pCur->pBtree;
BtShared *pBt = p->pBt;
+ int rc; /* Return code */
+ MemPage *pPage; /* Page to delete cell from */
+ unsigned char *pCell; /* Pointer to cell to delete */
+ int iCellIdx; /* Index of cell to delete */
+ int iCellDepth; /* Depth of node containing pCell */
assert( cursorHoldsMutex(pCur) );
- assert( pPage->isInit );
assert( pBt->inTransaction==TRANS_WRITE );
assert( !pBt->readOnly );
- if( pCur->eState==CURSOR_FAULT ){
- return pCur->skip;
- }
- if( NEVER(pCur->aiIdx[pCur->iPage]>=pPage->nCell) ){
- return SQLITE_ERROR; /* The cursor is not pointing to anything */
- }
assert( pCur->wrFlag );
+ if( NEVER(pCur->aiIdx[pCur->iPage]>=pCur->apPage[pCur->iPage]->nCell)
+ || NEVER(pCur->eState!=CURSOR_VALID)
+ ){
+ return SQLITE_ERROR; /* Something has gone awry. */
+ }
+
rc = checkForReadConflicts(p, pCur->pgnoRoot, pCur, pCur->info.nKey);
if( rc!=SQLITE_OK ){
- /* The table pCur points to has a read lock */
assert( rc==SQLITE_LOCKED_SHAREDCACHE );
- return rc;
- }
-
- /* Restore the current cursor position (a no-op if the cursor is not in
- ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors
- ** open on the same table. Then call sqlite3PagerWrite() on the page
- ** that the entry will be deleted from.
- */
- if(
- (rc = restoreCursorPosition(pCur))!=0 ||
- (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 ||
- (rc = sqlite3PagerWrite(pPage->pDbPage))!=0
- ){
- return rc;
- }
-
- /* Locate the cell within its page and leave pCell pointing to the
- ** data. The clearCell() call frees any overflow pages associated with the
- ** cell. The cell itself is still intact.
- */
- idx = pCur->aiIdx[pCur->iPage];
- pCell = findCell(pPage, idx);
+ return rc; /* The table pCur points to has a read lock */
+ }
+
+ iCellDepth = pCur->iPage;
+ iCellIdx = pCur->aiIdx[iCellDepth];
+ pPage = pCur->apPage[iCellDepth];
+ pCell = findCell(pPage, iCellIdx);
+
+ /* If the page containing the entry to delete is not a leaf page, move
+ ** the cursor to the largest entry in the tree that is smaller than
+ ** the entry being deleted. This cell will replace the cell being deleted
+ ** from the internal node. The 'previous' entry is used for this instead
+ ** of the 'next' entry, as the previous entry is always a part of the
+ ** sub-tree headed by the child page of the cell being deleted. This makes
+ ** balancing the tree following the delete operation easier. */
if( !pPage->leaf ){
- pgnoChild = get4byte(pCell);
- }
- rc = clearCell(pPage, pCell);
- if( rc ){
- return rc;
- }
-
+ int notUsed;
+ if( SQLITE_OK!=(rc = sqlite3BtreePrevious(pCur, ¬Used)) ){
+ return rc;
+ }
+ }
+
+ /* Save the positions of any other cursors open on this table before
+ ** making any modifications. Make the page containing the entry to be
+ ** deleted writable. Then free any overflow pages associated with the
+ ** entry and finally remove the cell itself from within the page. */
+ if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))
+ || SQLITE_OK!=(rc = sqlite3PagerWrite(pPage->pDbPage))
+ || SQLITE_OK!=(rc = clearCell(pPage, pCell))
+ || SQLITE_OK!=(rc = dropCell(pPage, iCellIdx, cellSizePtr(pPage, pCell)))
+ ){
+ return rc;
+ }
+
+ /* If the cell deleted was not located on a leaf page, then the cursor
+ ** is currently pointing to the largest entry in the sub-tree headed
+ ** by the child-page of the cell that was just deleted from an internal
+ ** node. The cell from the leaf node needs to be moved to the internal
+ ** node to replace the deleted cell. */
if( !pPage->leaf ){
- /*
- ** The entry we are about to delete is not a leaf so if we do not
- ** do something we will leave a hole on an internal page.
- ** We have to fill the hole by moving in a cell from a leaf. The
- ** 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 = 0;
-
- unsigned char *pNext;
- int notUsed;
- unsigned char *tempCell = 0;
- assert( !pPage->intKey );
- sqlite3BtreeGetTempCursor(pCur, &leafCur);
- rc = sqlite3BtreeNext(&leafCur, ¬Used);
- if( rc==SQLITE_OK ){
- assert( leafCur.aiIdx[leafCur.iPage]==0 );
- pLeafPage = leafCur.apPage[leafCur.iPage];
- rc = sqlite3PagerWrite(pLeafPage->pDbPage);
- }
- if( rc==SQLITE_OK ){
- int leafCursorInvalid = 0;
- u16 szNext;
- TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n",
- pCur->pgnoRoot, pPage->pgno, pLeafPage->pgno));
- dropCell(pPage, idx, cellSizePtr(pPage, pCell));
- pNext = findCell(pLeafPage, 0);
- szNext = cellSizePtr(pLeafPage, pNext);
- assert( MX_CELL_SIZE(pBt)>=szNext+4 );
- allocateTempSpace(pBt);
- tempCell = pBt->pTmpSpace;
- if( tempCell==0 ){
- rc = SQLITE_NOMEM;
- }
- if( rc==SQLITE_OK ){
- rc = insertCell(pPage, idx, pNext-4, szNext+4, tempCell, 0);
- }
-
-
- /* The "if" statement in the next code block is critical. The
- ** slightest error in that statement would allow SQLite to operate
- ** correctly most of the time but produce very rare failures. To
- ** guard against this, the following macros help to verify that
- ** the "if" statement is well tested.
- */
- testcase( pPage->nOverflow==0 && pPage->nFree<pBt->usableSize*2/3
- && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
- testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3
- && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
- testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3+1
- && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
- testcase( pPage->nOverflow>0 && pPage->nFree<=pBt->usableSize*2/3
- && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
- testcase( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3))
- && pLeafPage->nFree+2+szNext == pBt->usableSize*2/3 );
-
-
- if( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3)) &&
- (pLeafPage->nFree+2+szNext > pBt->usableSize*2/3)
- ){
- /* This branch is taken if the internal node is now either overflowing
- ** or underfull and the leaf node will be underfull after the just cell
- ** copied to the internal node is deleted from it. This is a special
- ** case because the call to balance() to correct the internal node
- ** may change the tree structure and invalidate the contents of
- ** the leafCur.apPage[] and leafCur.aiIdx[] arrays, which will be
- ** used by the balance() required to correct the underfull leaf
- ** node.
- **
- ** The formula used in the expression above are based on facets of
- ** the SQLite file-format that do not change over time.
- */
- testcase( pPage->nFree==pBt->usableSize*2/3+1 );
- testcase( pLeafPage->nFree+2+szNext==pBt->usableSize*2/3+1 );
- leafCursorInvalid = 1;
- }
-
- if( rc==SQLITE_OK ){
- assert( sqlite3PagerIswriteable(pPage->pDbPage) );
- put4byte(findOverflowCell(pPage, idx), pgnoChild);
- VVA_ONLY( pCur->pagesShuffled = 0 );
- rc = balance(pCur, 0);
- }
-
- if( rc==SQLITE_OK && leafCursorInvalid ){
- /* The leaf-node is now underfull and so the tree needs to be
- ** rebalanced. However, the balance() operation on the internal
- ** node above may have modified the structure of the B-Tree and
- ** so the current contents of leafCur.apPage[] and leafCur.aiIdx[]
- ** may not be trusted.
- **
- ** It is not possible to copy the ancestry from pCur, as the same
- ** balance() call has invalidated the pCur->apPage[] and aiIdx[]
- ** arrays.
- **
- ** The call to saveCursorPosition() below internally saves the
- ** key that leafCur is currently pointing to. Currently, there
- ** are two copies of that key in the tree - one here on the leaf
- ** page and one on some internal node in the tree. The copy on
- ** the leaf node is always the next key in tree-order after the
- ** copy on the internal node. So, the call to sqlite3BtreeNext()
- ** calls restoreCursorPosition() to point the cursor to the copy
- ** stored on the internal node, then advances to the next entry,
- ** which happens to be the copy of the key on the internal node.
- ** Net effect: leafCur is pointing back to the duplicate cell
- ** that needs to be removed, and the leafCur.apPage[] and
- ** leafCur.aiIdx[] arrays are correct.
- */
- VVA_ONLY( Pgno leafPgno = pLeafPage->pgno );
- rc = saveCursorPosition(&leafCur);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeNext(&leafCur, ¬Used);
- }
- pLeafPage = leafCur.apPage[leafCur.iPage];
- assert( rc!=SQLITE_OK || pLeafPage->pgno==leafPgno );
- assert( rc!=SQLITE_OK || leafCur.aiIdx[leafCur.iPage]==0 );
- }
-
- 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
- || !pCur->pagesShuffled );
- }
- }
- sqlite3BtreeReleaseTempCursor(&leafCur);
- }else{
- TRACE(("DELETE: table=%d delete from leaf %d\n",
- pCur->pgnoRoot, pPage->pgno));
- rc = dropCell(pPage, idx, cellSizePtr(pPage, pCell));
- if( rc==SQLITE_OK ){
- rc = balance(pCur, 0);
- }
- }
+ MemPage *pLeaf = pCur->apPage[pCur->iPage];
+ int nCell;
+ Pgno n = pCur->apPage[iCellDepth+1]->pgno;
+ unsigned char *pTmp;
+
+ pCell = findCell(pLeaf, pLeaf->nCell-1);
+ nCell = cellSizePtr(pLeaf, pCell);
+ assert( MX_CELL_SIZE(pBt)>=nCell );
+
+ allocateTempSpace(pBt);
+ pTmp = pBt->pTmpSpace;
+
+ if( SQLITE_OK!=(rc = sqlite3PagerWrite(pLeaf->pDbPage))
+ || SQLITE_OK!=(rc = insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n))
+ || SQLITE_OK!=(rc = dropCell(pLeaf, pLeaf->nCell-1, nCell))
+ ){
+ return rc;
+ }
+ }
+
+ /* Balance the tree. If the entry deleted was located on a leaf page,
+ ** then the cursor still points to that page. In this case the first
+ ** call to balance() repairs the tree, and the if(...) condition is
+ ** never true.
+ **
+ ** Otherwise, if the entry deleted was on an internal node page, then
+ ** pCur is pointing to the leaf page from which a cell was removed to
+ ** replace the cell deleted from the internal node. This is slightly
+ ** tricky as the leaf node may be underfull, and the internal node may
+ ** be either under or overfull. In this case run the balancing algorithm
+ ** on the leaf node first. If the balance proceeds far enough up the
+ ** tree that we can be sure that any problem in the internal node has
+ ** been corrected, so be it. Otherwise, after balancing the leaf node,
+ ** walk the cursor up the tree to the internal node and balance it as
+ ** well. */
+ rc = balance(pCur);
+ if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
+ while( pCur->iPage>iCellDepth ){
+ releasePage(pCur->apPage[pCur->iPage--]);
+ }
+ rc = balance(pCur);
+ }
+
if( rc==SQLITE_OK ){
moveToRoot(pCur);
}
return rc;
@@ -43432,9 +43531,12 @@
if( rc!=SQLITE_OK ){
return rc;
}
rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
- if( rc!=SQLITE_OK || eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
+ if( eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
+ if( rc!=SQLITE_OK ){
releasePage(pRoot);
return rc;
}
assert( eType!=PTRMAP_ROOTPAGE );
@@ -45189,9 +45291,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.147 2009/05/28 11:05:57 danielk1977 Exp $
+** $Id: vdbemem.c,v 1.149 2009/06/22 19:05:41 drh Exp $
*/
/*
** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
@@ -45583,9 +45685,20 @@
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
pMem->u.i = doubleToInt64(pMem->r);
- if( pMem->r==(double)pMem->u.i ){
+
+ /* Only mark the value as an integer if
+ **
+ ** (1) the round-trip conversion real->int->real is a no-op, and
+ ** (2) The integer is neither the largest nor the smallest
+ ** possible integer (ticket #3922)
+ **
+ ** The second term in the following conditional enforces the second
+ ** condition under the assumption that additional overflow causes
+ ** values to wrap around.
+ */
+ if( pMem->r==(double)pMem->u.i && (pMem->u.i-1) < (pMem->u.i+1) ){
pMem->flags |= MEM_Int;
}
}
@@ -45798,8 +45911,14 @@
** parameter. If the value passed is SQLITE_TRANSIENT, then the
** string is copied into a (possibly existing) buffer managed by the
** Mem structure. Otherwise, any existing buffer is freed and the
** pointer copied.
+**
+** If the string is too large (if it exceeds the SQLITE_LIMIT_LENGTH
+** size limit) then no memory allocation occurs. If the string can be
+** stored without allocating memory, then it is. If a memory allocation
+** is required to store the string, then value of pMem is unchanged. In
+** either case, SQLITE_TOOBIG is returned.
*/
SQLITE_PRIVATE int sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */
const char *z, /* String pointer */
@@ -45861,11 +45980,8 @@
pMem->z = (char *)z;
pMem->xDel = xDel;
flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
}
- if( nByte>iLimit ){
- return SQLITE_TOOBIG;
- }
pMem->n = nByte;
pMem->flags = flags;
pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
@@ -45875,8 +45991,12 @@
if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
return SQLITE_NOMEM;
}
#endif
+
+ if( nByte>iLimit ){
+ return SQLITE_TOOBIG;
+ }
return SQLITE_OK;
}
@@ -46251,9 +46371,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.459 2009/06/05 14:17:25 drh Exp $
+** $Id: vdbeaux.c,v 1.464 2009/06/23 14:15:04 drh Exp $
*/
@@ -46861,13 +46981,26 @@
** routine, then a pointer to a dummy VdbeOp will be returned. That opcode
** is readable and writable, but it has no effect. The return of a dummy
** opcode allows the call to continue functioning after a OOM fault without
** having to check to see if the return from this routine is a valid pointer.
+**
+** About the #ifdef SQLITE_OMIT_TRACE: Normally, this routine is never called
+** unless p->nOp>0. This is because in the absense of SQLITE_OMIT_TRACE,
+** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as
+** a new VDBE is created. So we are free to set addr to p->nOp-1 without
+** having to double-check to make sure that the result is non-negative. But
+** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
+** check the value of p->nOp-1 before continuing.
*/
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
static VdbeOp dummy;
assert( p->magic==VDBE_MAGIC_INIT );
- if( addr<0 ) addr = p->nOp - 1;
+ if( addr<0 ){
+#ifdef SQLITE_OMIT_TRACE
+ if( p->nOp==0 ) return &dummy;
+#endif
+ addr = p->nOp - 1;
+ }
assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
if( p->db->mallocFailed ){
return &dummy;
}else{
@@ -48236,11 +48369,19 @@
sqlite3DbFree(db, p);
}
/*
+** Make sure the cursor p is ready to read or write the row to which it
+** was last positioned. Return an error code if an OOM fault or I/O error
+** prevents us from positioning the cursor to its correct position.
+**
** If a MoveTo operation is pending on the given cursor, then do that
-** MoveTo now. Return an error code. If no MoveTo is pending, this
-** routine does nothing and returns SQLITE_OK.
+** MoveTo now. If no move is pending, check to see if the row has been
+** deleted out from under the cursor and if it has, mark the row as
+** a NULL row.
+**
+** If the cursor is already pointing to the correct row and that row has
+** not been deleted out from under the cursor, then this routine is a no-op.
*/
SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
if( p->deferredMoveto ){
int res, rc;
@@ -48249,9 +48390,9 @@
#endif
assert( p->isTable );
rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
- p->lastRowid = keyToInt(p->movetoTarget);
+ p->lastRowid = p->movetoTarget;
p->rowidIsValid = ALWAYS(res==0) ?1:0;
if( NEVER(res<0) ){
rc = sqlite3BtreeNext(p->pCursor, &res);
if( rc ) return rc;
@@ -48451,9 +48592,9 @@
}else{
v = pMem->u.i;
}
len = i = sqlite3VdbeSerialTypeLen(serial_type);
- assert( len<=nBuf );
+ assert( len<=(u32)nBuf );
while( i-- ){
buf[i] = (u8)(v&0xFF);
v >>= 8;
}
@@ -48462,9 +48603,9 @@
/* String or blob */
if( serial_type>=12 ){
assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
- == sqlite3VdbeSerialTypeLen(serial_type) );
+ == (int)sqlite3VdbeSerialTypeLen(serial_type) );
assert( pMem->n<=nBuf );
len = pMem->n;
memcpy(buf, pMem->z, len);
if( pMem->flags & MEM_Zero ){
@@ -48791,9 +48932,9 @@
**
** 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){
+SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
i64 nCellKey = 0;
int rc;
u32 szHdr; /* Size of the header */
u32 typeRowid; /* Serial type of the rowid */
@@ -48808,9 +48949,9 @@
}
/* Read in the complete content of the index entry */
m.flags = 0;
- m.db = 0;
+ m.db = db;
m.zMalloc = 0;
rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m);
if( rc ){
return rc;
@@ -48958,166 +49099,10 @@
**
** This file contains code use to implement APIs that are part of the
** VDBE.
**
-** $Id: vdbeapi.c,v 1.165 2009/06/06 14:13:27 danielk1977 Exp $
-*/
-
-#if 0 && defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
-/*
-** The following structure contains pointers to the end points of a
-** doubly-linked list of all compiled SQL statements that may be holding
-** buffers eligible for release when the sqlite3_release_memory() interface is
-** invoked. Access to this list is protected by the SQLITE_MUTEX_STATIC_LRU2
-** mutex.
-**
-** Statements are added to the end of this list when sqlite3_reset() is
-** called. They are removed either when sqlite3_step() or sqlite3_finalize()
-** is called. When statements are added to this list, the associated
-** register array (p->aMem[1..p->nMem]) may contain dynamic buffers that
-** can be freed using sqlite3VdbeReleaseMemory().
-**
-** When statements are added or removed from this list, the mutex
-** associated with the Vdbe being added or removed (Vdbe.db->mutex) is
-** already held. The LRU2 mutex is then obtained, blocking if necessary,
-** the linked-list pointers manipulated and the LRU2 mutex relinquished.
-*/
-struct StatementLruList {
- Vdbe *pFirst;
- Vdbe *pLast;
-};
-static struct StatementLruList sqlite3LruStatements;
-
-/*
-** Check that the list looks to be internally consistent. This is used
-** as part of an assert() statement as follows:
-**
-** assert( stmtLruCheck() );
-*/
-#ifndef NDEBUG
-static int stmtLruCheck(){
- Vdbe *p;
- for(p=sqlite3LruStatements.pFirst; p; p=p->pLruNext){
- assert(p->pLruNext || p==sqlite3LruStatements.pLast);
- assert(!p->pLruNext || p->pLruNext->pLruPrev==p);
- assert(p->pLruPrev || p==sqlite3LruStatements.pFirst);
- assert(!p->pLruPrev || p->pLruPrev->pLruNext==p);
- }
- return 1;
-}
-#endif
-
-/*
-** Add vdbe p to the end of the statement lru list. It is assumed that
-** p is not already part of the list when this is called. The lru list
-** is protected by the SQLITE_MUTEX_STATIC_LRU mutex.
-*/
-static void stmtLruAdd(Vdbe *p){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
-
- if( p->pLruPrev || p->pLruNext || sqlite3LruStatements.pFirst==p ){
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
- return;
- }
-
- assert( stmtLruCheck() );
-
- if( !sqlite3LruStatements.pFirst ){
- assert( !sqlite3LruStatements.pLast );
- sqlite3LruStatements.pFirst = p;
- sqlite3LruStatements.pLast = p;
- }else{
- assert( !sqlite3LruStatements.pLast->pLruNext );
- p->pLruPrev = sqlite3LruStatements.pLast;
- sqlite3LruStatements.pLast->pLruNext = p;
- sqlite3LruStatements.pLast = p;
- }
-
- assert( stmtLruCheck() );
-
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
-}
-
-/*
-** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is already held, remove
-** statement p from the least-recently-used statement list. If the
-** statement is not currently part of the list, this call is a no-op.
-*/
-static void stmtLruRemoveNomutex(Vdbe *p){
- if( p->pLruPrev || p->pLruNext || p==sqlite3LruStatements.pFirst ){
- assert( stmtLruCheck() );
- if( p->pLruNext ){
- p->pLruNext->pLruPrev = p->pLruPrev;
- }else{
- sqlite3LruStatements.pLast = p->pLruPrev;
- }
- if( p->pLruPrev ){
- p->pLruPrev->pLruNext = p->pLruNext;
- }else{
- sqlite3LruStatements.pFirst = p->pLruNext;
- }
- p->pLruNext = 0;
- p->pLruPrev = 0;
- assert( stmtLruCheck() );
- }
-}
-
-/*
-** Assuming the SQLITE_MUTEX_STATIC_LRU2 mutext is not held, remove
-** statement p from the least-recently-used statement list. If the
-** statement is not currently part of the list, this call is a no-op.
-*/
-static void stmtLruRemove(Vdbe *p){
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
- stmtLruRemoveNomutex(p);
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
-}
-
-/*
-** Try to release n bytes of memory by freeing buffers associated
-** with the memory registers of currently unused vdbes.
-*/
-SQLITE_PRIVATE int sqlite3VdbeReleaseMemory(int n){
- Vdbe *p;
- Vdbe *pNext;
- int nFree = 0;
-
- sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
- for(p=sqlite3LruStatements.pFirst; p && nFree<n; p=pNext){
- pNext = p->pLruNext;
-
- /* For each statement handle in the lru list, attempt to obtain the
- ** associated database mutex. If it cannot be obtained, continue
- ** to the next statement handle. It is not possible to block on
- ** the database mutex - that could cause deadlock.
- */
- if( SQLITE_OK==sqlite3_mutex_try(p->db->mutex) ){
- nFree += sqlite3VdbeReleaseBuffers(p);
- stmtLruRemoveNomutex(p);
- sqlite3_mutex_leave(p->db->mutex);
- }
- }
- sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU2));
-
- return nFree;
-}
-
-/*
-** Call sqlite3Reprepare() on the statement. Remove it from the
-** lru list before doing so, as Reprepare() will free all the
-** memory register buffers anyway.
-*/
-int vdbeReprepare(Vdbe *p){
- stmtLruRemove(p);
- return sqlite3Reprepare(p);
-}
-
-#else /* !SQLITE_ENABLE_MEMORY_MANAGEMENT */
- #define stmtLruRemove(x)
- #define stmtLruAdd(x)
- #define vdbeReprepare(x) sqlite3Reprepare(x)
-#endif
-
+** $Id: vdbeapi.c,v 1.166 2009/06/19 14:06:03 drh Exp $
+*/
#ifndef SQLITE_OMIT_DEPRECATED
/*
** Return TRUE (non-zero) of the statement supplied as an argument needs
@@ -49152,9 +49137,8 @@
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = v->db->mutex;
#endif
sqlite3_mutex_enter(mutex);
- stmtLruRemove(v);
rc = sqlite3VdbeFinalize(v);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(mutex);
}
@@ -49176,9 +49160,8 @@
}else{
Vdbe *v = (Vdbe*)pStmt;
sqlite3_mutex_enter(v->db->mutex);
rc = sqlite3VdbeReset(v);
- stmtLruAdd(v);
sqlite3VdbeMakeReady(v, -1, 0, 0, 0);
assert( (rc & (v->db->errMask))==rc );
rc = sqlite3ApiExit(v->db, rc);
sqlite3_mutex_leave(v->db->mutex);
@@ -49420,9 +49403,8 @@
db->activeVdbeCnt++;
if( p->readOnly==0 ) db->writeVdbeCnt++;
p->pc = 0;
- stmtLruRemove(p);
}
#ifndef SQLITE_OMIT_EXPLAIN
if( p->explain ){
rc = sqlite3VdbeList(p);
@@ -49480,21 +49462,8 @@
** This is the top-level implementation of sqlite3_step(). Call
** sqlite3Step() to do most of the work. If a schema error occurs,
** call sqlite3Reprepare() and try again.
*/
-#ifdef SQLITE_OMIT_PARSER
-SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
- int rc = SQLITE_MISUSE;
- if( pStmt ){
- Vdbe *v;
- v = (Vdbe*)pStmt;
- sqlite3_mutex_enter(v->db->mutex);
- rc = sqlite3Step(v);
- sqlite3_mutex_leave(v->db->mutex);
- }
- return rc;
-}
-#else
SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_MISUSE;
if( pStmt ){
int cnt = 0;
@@ -49502,9 +49471,9 @@
sqlite3 *db = v->db;
sqlite3_mutex_enter(db->mutex);
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < 5
- && (rc = vdbeReprepare(v))==SQLITE_OK ){
+ && (rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc==SQLITE_SCHEMA && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
@@ -49529,9 +49498,8 @@
sqlite3_mutex_leave(db->mutex);
}
return rc;
}
-#endif
/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
@@ -50352,9 +50320,9 @@
** of the code in this file is, therefore, important. See other comments
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.848 2009/06/05 16:46:53 drh Exp $
+** $Id: vdbe.c,v 1.862 2009/06/23 14:15:04 drh Exp $
*/
/*
** The following global variable is incremented every time a cursor
@@ -50496,9 +50464,9 @@
Vdbe *p, /* The virtual machine */
int iCur, /* Index of the new VdbeCursor */
int nField, /* Number of fields in the table or index */
int iDb, /* When database the cursor belongs to, or -1 */
- int isBtreeCursor /* */
+ int isBtreeCursor /* True for B-Tree vs. pseudo-table or vtab */
){
/* 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
** vdbe memory cell to manage the memory allocation required for a
@@ -50733,10 +50701,12 @@
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
fprintf(out, " si:%lld", p->u.i);
}else if( p->flags & MEM_Int ){
fprintf(out, " i:%lld", p->u.i);
+#ifndef SQLITE_OMIT_FLOATING_POINT
}else if( p->flags & MEM_Real ){
fprintf(out, " r:%g", p->r);
+#endif
}else if( p->flags & MEM_RowSet ){
fprintf(out, " (rowset)");
}else{
char zBuf[200];
@@ -51033,11 +51003,8 @@
} ak;
struct OP_IfNot_stack_vars {
int c;
} al;
- struct OP_IsNull_stack_vars {
- int n;
- } am;
struct OP_Column_stack_vars {
u32 payloadSize; /* Number of bytes in the record */
i64 payloadSize64; /* Number of bytes in the record */
int p1; /* P1 value of the opcode */
@@ -51058,15 +51025,15 @@
u32 offset; /* Offset into the data */
u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */
int szHdr; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
- } an;
+ } am;
struct OP_Affinity_stack_vars {
char *zAffinity; /* The affinity to be applied */
Mem *pData0; /* First register to which to apply affinity */
Mem *pLast; /* Last register to which to apply affinity */
Mem *pRec; /* Current register */
- } ao;
+ } an;
struct OP_MakeRecord_stack_vars {
u8 *zNewRecord; /* A buffer to hold the data for the new record */
Mem *pRec; /* The new record */
u64 nData; /* Number of bytes of data space */
@@ -51081,17 +51048,16 @@
char *zAffinity; /* The affinity string for the record */
int file_format; /* File format to use for encoding */
int i; /* Space used in zNewRecord[] */
int len; /* Length of a field */
- } ap;
+ } ao;
struct OP_Count_stack_vars {
i64 nEntry;
BtCursor *pCrsr;
- } aq;
+ } ap;
struct OP_Statement_stack_vars {
- int i;
Btree *pBt;
- } ar;
+ } aq;
struct OP_Savepoint_stack_vars {
int p1; /* Value of P1 operand */
char *zName; /* Name of savepoint */
int nName;
@@ -51099,74 +51065,64 @@
Savepoint *pSavepoint;
Savepoint *pTmp;
int iSavepoint;
int ii;
- } as;
+ } ar;
struct OP_AutoCommit_stack_vars {
int desiredAutoCommit;
- int rollback;
+ int iRollback;
int turnOnAC;
- } at;
+ } as;
struct OP_Transaction_stack_vars {
- int i;
Btree *pBt;
- } au;
+ } at;
struct OP_ReadCookie_stack_vars {
int iMeta;
int iDb;
int iCookie;
- } av;
+ } au;
struct OP_SetCookie_stack_vars {
Db *pDb;
- } aw;
+ } av;
struct OP_VerifyCookie_stack_vars {
int iMeta;
Btree *pBt;
- } ax;
+ } aw;
struct OP_OpenWrite_stack_vars {
int nField;
KeyInfo *pKeyInfo;
- int i;
int p2;
int iDb;
int wrFlag;
Btree *pX;
VdbeCursor *pCur;
Db *pDb;
int flags;
- } ay;
+ } ax;
struct OP_OpenEphemeral_stack_vars {
- int i;
+ VdbeCursor *pCx;
+ } ay;
+ struct OP_OpenPseudo_stack_vars {
VdbeCursor *pCx;
} az;
- struct OP_OpenPseudo_stack_vars {
- int i;
- VdbeCursor *pCx;
- } ba;
- struct OP_Close_stack_vars {
- int i;
- } bb;
- struct OP_SeekGt_stack_vars {
- int i;
+ struct OP_SeekGt_stack_vars {
int res;
int oc;
VdbeCursor *pC;
UnpackedRecord r;
int nField;
i64 iKey; /* The rowid we are to seek to */
- } bc;
+ } ba;
struct OP_Seek_stack_vars {
- int i;
- VdbeCursor *pC;
- } bd;
- struct OP_Found_stack_vars {
- int i;
+ VdbeCursor *pC;
+ } bb;
+ struct OP_Found_stack_vars {
int alreadyExists;
VdbeCursor *pC;
int res;
UnpackedRecord *pIdxKey;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
- } be;
+ } bc;
struct OP_IsUnique_stack_vars {
u16 ii;
VdbeCursor *pCx;
BtCursor *pCrsr;
@@ -51173,176 +51129,163 @@
u16 nField;
Mem *aMem;
UnpackedRecord r; /* B-Tree index search key */
i64 R; /* Rowid stored in register P3 */
- } bf;
- struct OP_NotExists_stack_vars {
- int i;
+ } bd;
+ struct OP_NotExists_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
u64 iKey;
- } bg;
+ } be;
struct OP_NewRowid_stack_vars {
- int i;
- i64 v;
- VdbeCursor *pC;
- int res;
- int rx;
- int cnt;
- i64 x;
- Mem *pMem;
- } bh;
+ i64 v; /* The new rowid */
+ VdbeCursor *pC; /* Cursor of table to get the new rowid */
+ int res; /* Result of an sqlite3BtreeLast() */
+ int cnt; /* Counter to limit the number of searches */
+ Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
+ } bf;
struct OP_Insert_stack_vars {
Mem *pData;
Mem *pKey;
i64 iKey; /* The integer ROWID or key for the record to be inserted */
- int i;
VdbeCursor *pC;
int nZero;
int seekResult;
const char *zDb;
const char *zTbl;
int op;
- } bi;
- struct OP_Delete_stack_vars {
- int i;
+ } bg;
+ struct OP_Delete_stack_vars {
i64 iKey;
VdbeCursor *pC;
- } bj;
- struct OP_RowData_stack_vars {
- int i;
+ } bh;
+ struct OP_RowData_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
i64 n64;
- } bk;
- struct OP_Rowid_stack_vars {
- int i;
+ } bi;
+ struct OP_Rowid_stack_vars {
VdbeCursor *pC;
i64 v;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
- } bl;
+ } bj;
struct OP_NullRow_stack_vars {
- int i;
VdbeCursor *pC;
- } bm;
+ } bk;
struct OP_Last_stack_vars {
- int i;
+ VdbeCursor *pC;
+ BtCursor *pCrsr;
+ int res;
+ } bl;
+ struct OP_Rewind_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
- } bn;
- struct OP_Rewind_stack_vars {
- int i;
- VdbeCursor *pC;
- BtCursor *pCrsr;
- int res;
- } bo;
+ } bm;
struct OP_Next_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
- } bp;
- struct OP_IdxInsert_stack_vars {
- int i;
+ } bn;
+ struct OP_IdxInsert_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int nKey;
const char *zKey;
- } bq;
- struct OP_IdxDelete_stack_vars {
- int i;
+ } bo;
+ struct OP_IdxDelete_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
- } br;
- struct OP_IdxRowid_stack_vars {
- int i;
+ int res;
+ UnpackedRecord r;
+ } bp;
+ struct OP_IdxRowid_stack_vars {
BtCursor *pCrsr;
VdbeCursor *pC;
i64 rowid;
- } bs;
- struct OP_IdxGE_stack_vars {
- int i;
+ } bq;
+ struct OP_IdxGE_stack_vars {
VdbeCursor *pC;
int res;
UnpackedRecord r;
- } bt;
+ } br;
struct OP_Destroy_stack_vars {
int iMoved;
int iCnt;
Vdbe *pVdbe;
int iDb;
- } bu;
+ } bs;
struct OP_Clear_stack_vars {
int nChange;
- } bv;
+ } bt;
struct OP_CreateTable_stack_vars {
int pgno;
int flags;
Db *pDb;
- } bw;
+ } bu;
struct OP_ParseSchema_stack_vars {
int iDb;
const char *zMaster;
char *zSql;
InitData initData;
- } bx;
+ } bv;
struct OP_IntegrityCk_stack_vars {
int nRoot; /* Number of tables to check. (Number of root pages.) */
int *aRoot; /* Array of rootpage numbers for tables to be checked */
int j; /* Loop counter */
int nErr; /* Number of errors reported */
char *z; /* Text of the error report */
Mem *pnErr; /* Register keeping track of errors remaining */
- } by;
+ } bw;
struct OP_RowSetAdd_stack_vars {
Mem *pIdx;
Mem *pVal;
- } bz;
+ } bx;
struct OP_RowSetRead_stack_vars {
Mem *pIdx;
i64 val;
- } ca;
+ } by;
struct OP_RowSetTest_stack_vars {
int iSet;
int exists;
- } cb;
+ } bz;
struct OP_ContextPush_stack_vars {
int i;
Context *pContext;
- } cc;
+ } ca;
struct OP_ContextPop_stack_vars {
Context *pContext;
- } cd;
+ } cb;
struct OP_AggStep_stack_vars {
int n;
int i;
Mem *pMem;
Mem *pRec;
sqlite3_context ctx;
sqlite3_value **apVal;
- } ce;
+ } cc;
struct OP_AggFinal_stack_vars {
Mem *pMem;
- } cf;
+ } cd;
struct OP_IncrVacuum_stack_vars {
Btree *pBt;
- } cg;
+ } ce;
struct OP_TableLock_stack_vars {
int p1;
u8 isWriteLock;
- } ch;
+ } cf;
struct OP_VBegin_stack_vars {
sqlite3_vtab *pVtab;
- } ci;
+ } cg;
struct OP_VOpen_stack_vars {
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
- } cj;
+ } ch;
struct OP_VFilter_stack_vars {
int nArg;
int iQuery;
const sqlite3_module *pModule;
@@ -51353,25 +51296,25 @@
VdbeCursor *pCur;
int res;
int i;
Mem **apArg;
- } ck;
+ } ci;
struct OP_VColumn_stack_vars {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
- } cl;
+ } cj;
struct OP_VNext_stack_vars {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
- } cm;
+ } ck;
struct OP_VRename_stack_vars {
sqlite3_vtab *pVtab;
Mem *pName;
- } cn;
+ } cl;
struct OP_VUpdate_stack_vars {
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
int nArg;
@@ -51378,17 +51321,17 @@
int i;
sqlite_int64 rowid;
Mem **apArg;
Mem *pX;
- } co;
+ } cm;
struct OP_Pagecount_stack_vars {
int p1;
int nPage;
Pager *pPager;
- } cp;
+ } cn;
struct OP_Trace_stack_vars {
char *zTrace;
- } cq;
+ } co;
} u;
/* End automatically generated code
********************************************************************/
@@ -51733,11 +51676,13 @@
pOp->p1 = sqlite3Strlen30(pOp->p4.z);
#ifndef SQLITE_OMIT_UTF16
if( encoding!=SQLITE_UTF8 ){
- sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
+ rc = sqlite3VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE_UTF8, SQLITE_STATIC);
+ if( rc==SQLITE_TOOBIG ) goto too_big;
if( SQLITE_OK!=sqlite3VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
- if( SQLITE_OK!=sqlite3VdbeMemMakeWriteable(pOut) ) goto no_mem;
+ assert( pOut->zMalloc==pOut->z );
+ assert( pOut->flags & MEM_Dyn );
pOut->zMalloc = 0;
pOut->flags |= MEM_Static;
pOut->flags &= ~MEM_Dyn;
if( pOp->p4type==P4_DYNAMIC ){
@@ -51745,13 +51690,8 @@
}
pOp->p4type = P4_DYNAMIC;
pOp->p4.z = pOut->z;
pOp->p1 = pOut->n;
- if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
- UPDATE_MAX_BLOBSIZE(pOut);
- break;
}
#endif
if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
@@ -51941,11 +51881,15 @@
** ensure that statement-transactions are always nested, not overlapping.
** If the open statement-transaction is not closed here, then the user
** may step another VM that opens its own statement transaction. This
** may lead to overlapping statement transactions.
+ **
+ ** The statement transaction is never a top-level transaction. Hence
+ ** the RELEASE call below can never fail.
*/
assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
- if( SQLITE_OK!=(rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE)) ){
+ rc = sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
+ if( NEVER(rc!=SQLITE_OK) ){
break;
}
/* Invalidate all ephemeral cursor row caches */
@@ -51991,11 +51935,10 @@
if( (pIn1->flags | pIn2->flags) & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
break;
}
- ExpandBlob(pIn1);
- Stringify(pIn1, encoding);
- ExpandBlob(pIn2);
+ if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
+ Stringify(pIn1, encoding);
Stringify(pIn2, encoding);
u.ae.nByte = pIn1->n + pIn2->n;
if( u.ae.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
@@ -52109,10 +52052,10 @@
u.af.rB /= u.af.rA;
break;
}
default: {
- u.af.iA = u.af.rA;
- u.af.iB = u.af.rB;
+ u.af.iA = (i64)u.af.rA;
+ u.af.iB = (i64)u.af.rB;
if( u.af.iA==0 ) goto arithmetic_result_is_null;
if( u.af.iA==-1 ) u.af.iA = 1;
u.af.rB = (double)(u.af.iB % u.af.iA);
break;
@@ -52782,28 +52725,16 @@
}
break;
}
-/* Opcode: IsNull P1 P2 P3 * *
-**
-** Jump to P2 if the value in register P1 is NULL. If P3 is greater
-** than zero, then check all values reg(P1), reg(P1+1),
-** reg(P1+2), ..., reg(P1+P3-1).
+/* Opcode: IsNull P1 P2 * * *
+**
+** Jump to P2 if the value in register P1 is NULL.
*/
case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
-#if 0 /* local variables moved into u.am */
- int n;
-#endif /* local variables moved into u.am */
-
- u.am.n = pOp->p3;
- assert( pOp->p3==0 || pOp->p1>0 );
- do{
- if( (pIn1->flags & MEM_Null)!=0 ){
- pc = pOp->p2 - 1;
- break;
- }
- pIn1++;
- }while( --u.am.n > 0 );
+ if( (pIn1->flags & MEM_Null)!=0 ){
+ pc = pOp->p2 - 1;
+ }
break;
}
/* Opcode: NotNull P1 P2 * * *
@@ -52853,9 +52784,9 @@
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
*/
case OP_Column: {
-#if 0 /* local variables moved into u.an */
+#if 0 /* local variables moved into u.am */
u32 payloadSize; /* Number of bytes in the record */
i64 payloadSize64; /* Number of bytes in the record */
int p1; /* P1 value of the opcode */
int p2; /* column number to retrieve */
@@ -52875,121 +52806,123 @@
u32 offset; /* Offset into the data */
u64 offset64; /* 64-bit offset. 64 bits needed to catch overflow */
int szHdr; /* Size of the header size field at start of record */
int avail; /* Number of bytes of available data */
-#endif /* local variables moved into u.an */
-
-
- u.an.p1 = pOp->p1;
- u.an.p2 = pOp->p2;
- u.an.pC = 0;
- memset(&u.an.sMem, 0, sizeof(u.an.sMem));
- assert( u.an.p1<p->nCursor );
+#endif /* local variables moved into u.am */
+
+
+ u.am.p1 = pOp->p1;
+ u.am.p2 = pOp->p2;
+ u.am.pC = 0;
+ memset(&u.am.sMem, 0, sizeof(u.am.sMem));
+ assert( u.am.p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.an.pDest = &p->aMem[pOp->p3];
- MemSetTypeFlag(u.an.pDest, MEM_Null);
-
- /* This block sets the variable u.an.payloadSize to be the total number of
+ u.am.pDest = &p->aMem[pOp->p3];
+ MemSetTypeFlag(u.am.pDest, MEM_Null);
+
+ /* This block sets the variable u.am.payloadSize to be the total number of
** bytes in the record.
**
- ** u.an.zRec is set to be the complete text of the record if it is available.
+ ** u.am.zRec is set to be the complete text of the record if it is available.
** The complete record text is always available for pseudo-tables
** If the record is stored in a cursor, the complete record text
- ** might be available in the u.an.pC->aRow cache. Or it might not be.
- ** If the data is unavailable, u.an.zRec is set to NULL.
+ ** might be available in the u.am.pC->aRow cache. Or it might not be.
+ ** If the data is unavailable, u.am.zRec is set to NULL.
**
** We also compute the number of columns in the record. For cursors,
** the number of columns is stored in the VdbeCursor.nField element.
*/
- u.an.pC = p->apCsr[u.an.p1];
- assert( u.an.pC!=0 );
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- assert( u.an.pC->pVtabCursor==0 );
-#endif
- if( u.an.pC->pCursor!=0 ){
+ u.am.pC = p->apCsr[u.am.p1];
+ assert( u.am.pC!=0 );
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ assert( u.am.pC->pVtabCursor==0 );
+#endif
+ if( u.am.pC->pCursor!=0 ){
/* The record is stored in a B-Tree */
- rc = sqlite3VdbeCursorMoveto(u.an.pC);
+ rc = sqlite3VdbeCursorMoveto(u.am.pC);
if( rc ) goto abort_due_to_error;
- u.an.zRec = 0;
- u.an.pCrsr = u.an.pC->pCursor;
- if( u.an.pC->nullRow ){
- u.an.payloadSize = 0;
- }else if( u.an.pC->cacheStatus==p->cacheCtr ){
- u.an.payloadSize = u.an.pC->payloadSize;
- u.an.zRec = (char*)u.an.pC->aRow;
- }else if( u.an.pC->isIndex ){
- sqlite3BtreeKeySize(u.an.pCrsr, &u.an.payloadSize64);
- if( (u.an.payloadSize64 & SQLITE_MAX_U32)!=(u64)u.an.payloadSize64 ){
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
- }
- u.an.payloadSize = (u32)u.an.payloadSize64;
- }else{
- sqlite3BtreeDataSize(u.an.pCrsr, &u.an.payloadSize);
- }
- u.an.nField = u.an.pC->nField;
- }else{
- assert( u.an.pC->pseudoTable );
+ u.am.zRec = 0;
+ u.am.pCrsr = u.am.pC->pCursor;
+ if( u.am.pC->nullRow ){
+ u.am.payloadSize = 0;
+ }else if( u.am.pC->cacheStatus==p->cacheCtr ){
+ u.am.payloadSize = u.am.pC->payloadSize;
+ u.am.zRec = (char*)u.am.pC->aRow;
+ }else if( u.am.pC->isIndex ){
+ sqlite3BtreeKeySize(u.am.pCrsr, &u.am.payloadSize64);
+ /* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
+ ** payload size, so it is impossible for u.am.payloadSize64 to be
+ ** larger than 32 bits. */
+ assert( (u.am.payloadSize64 & SQLITE_MAX_U32)==(u64)u.am.payloadSize64 );
+ u.am.payloadSize = (u32)u.am.payloadSize64;
+ }else{
+ sqlite3BtreeDataSize(u.am.pCrsr, &u.am.payloadSize);
+ }
+ u.am.nField = u.am.pC->nField;
+ }else if( u.am.pC->pseudoTable ){
/* The record is the sole entry of a pseudo-table */
- u.an.payloadSize = u.an.pC->nData;
- u.an.zRec = u.an.pC->pData;
- u.an.pC->cacheStatus = CACHE_STALE;
- assert( u.an.payloadSize==0 || u.an.zRec!=0 );
- u.an.nField = u.an.pC->nField;
- u.an.pCrsr = 0;
- }
-
- /* If u.an.payloadSize is 0, then just store a NULL */
- if( u.an.payloadSize==0 ){
- assert( u.an.pDest->flags&MEM_Null );
+ u.am.payloadSize = u.am.pC->nData;
+ u.am.zRec = u.am.pC->pData;
+ u.am.pC->cacheStatus = CACHE_STALE;
+ assert( u.am.payloadSize==0 || u.am.zRec!=0 );
+ u.am.nField = u.am.pC->nField;
+ u.am.pCrsr = 0;
+ }else{
+ /* Consider the row to be NULL */
+ u.am.payloadSize = 0;
+ }
+
+ /* If u.am.payloadSize is 0, then just store a NULL */
+ if( u.am.payloadSize==0 ){
+ assert( u.am.pDest->flags&MEM_Null );
goto op_column_out;
}
assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
- if( u.an.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( u.am.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- assert( u.an.p2<u.an.nField );
+ assert( u.am.p2<u.am.nField );
/* Read and parse the table header. Store the results of the parse
** into the record header cache fields of the cursor.
*/
- u.an.aType = u.an.pC->aType;
- if( u.an.pC->cacheStatus==p->cacheCtr ){
- u.an.aOffset = u.an.pC->aOffset;
- }else{
- assert(u.an.aType);
- u.an.avail = 0;
- u.an.pC->aOffset = u.an.aOffset = &u.an.aType[u.an.nField];
- u.an.pC->payloadSize = u.an.payloadSize;
- u.an.pC->cacheStatus = p->cacheCtr;
+ u.am.aType = u.am.pC->aType;
+ if( u.am.pC->cacheStatus==p->cacheCtr ){
+ u.am.aOffset = u.am.pC->aOffset;
+ }else{
+ assert(u.am.aType);
+ u.am.avail = 0;
+ u.am.pC->aOffset = u.am.aOffset = &u.am.aType[u.am.nField];
+ u.am.pC->payloadSize = u.am.payloadSize;
+ u.am.pC->cacheStatus = p->cacheCtr;
/* Figure out how many bytes are in the header */
- if( u.an.zRec ){
- u.an.zData = u.an.zRec;
- }else{
- if( u.an.pC->isIndex ){
- u.an.zData = (char*)sqlite3BtreeKeyFetch(u.an.pCrsr, &u.an.avail);
- }else{
- u.an.zData = (char*)sqlite3BtreeDataFetch(u.an.pCrsr, &u.an.avail);
+ if( u.am.zRec ){
+ u.am.zData = u.am.zRec;
+ }else{
+ if( u.am.pC->isIndex ){
+ u.am.zData = (char*)sqlite3BtreeKeyFetch(u.am.pCrsr, &u.am.avail);
+ }else{
+ u.am.zData = (char*)sqlite3BtreeDataFetch(u.am.pCrsr, &u.am.avail);
}
/* If KeyFetch()/DataFetch() managed to get the entire payload,
- ** save the payload in the u.an.pC->aRow cache. That will save us from
+ ** save the payload in the u.am.pC->aRow cache. That will save us from
** having to make additional calls to fetch the content portion of
** the record.
*/
- assert( u.an.avail>=0 );
- if( u.an.payloadSize <= (u32)u.an.avail ){
- u.an.zRec = u.an.zData;
- u.an.pC->aRow = (u8*)u.an.zData;
- }else{
- u.an.pC->aRow = 0;
+ assert( u.am.avail>=0 );
+ if( u.am.payloadSize <= (u32)u.am.avail ){
+ u.am.zRec = u.am.zData;
+ u.am.pC->aRow = (u8*)u.am.zData;
+ }else{
+ u.am.pC->aRow = 0;
}
}
/* The following assert is true in all cases accept when
** the database file has been corrupted externally.
- ** assert( u.an.zRec!=0 || u.an.avail>=u.an.payloadSize || u.an.avail>=9 ); */
- u.an.szHdr = getVarint32((u8*)u.an.zData, u.an.offset);
+ ** assert( u.am.zRec!=0 || u.am.avail>=u.am.payloadSize || u.am.avail>=9 ); */
+ u.am.szHdr = getVarint32((u8*)u.am.zData, u.am.offset);
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
**
@@ -52998,134 +52931,134 @@
** them, respectively. So the maximum header length results from a
** 3-byte type for each of the maximum of 32768 columns plus three
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
*/
- if( u.an.offset > 98307 ){
+ if( u.am.offset > 98307 ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
- /* Compute in u.an.len the number of bytes of data we need to read in order
- ** to get u.an.nField type values. u.an.offset is an upper bound on this. But
- ** u.an.nField might be significantly less than the true number of columns
- ** in the table, and in that case, 5*u.an.nField+3 might be smaller than u.an.offset.
- ** We want to minimize u.an.len in order to limit the size of the memory
- ** allocation, especially if a corrupt database file has caused u.an.offset
+ /* Compute in u.am.len the number of bytes of data we need to read in order
+ ** to get u.am.nField type values. u.am.offset is an upper bound on this. But
+ ** u.am.nField might be significantly less than the true number of columns
+ ** in the table, and in that case, 5*u.am.nField+3 might be smaller than u.am.offset.
+ ** We want to minimize u.am.len in order to limit the size of the memory
+ ** allocation, especially if a corrupt database file has caused u.am.offset
** to be oversized. Offset is limited to 98307 above. But 98307 might
** still exceed Robson memory allocation limits on some configurations.
- ** On systems that cannot tolerate large memory allocations, u.an.nField*5+3
- ** will likely be much smaller since u.an.nField will likely be less than
+ ** On systems that cannot tolerate large memory allocations, u.am.nField*5+3
+ ** will likely be much smaller since u.am.nField will likely be less than
** 20 or so. This insures that Robson memory allocation limits are
** not exceeded even for corrupt database files.
*/
- u.an.len = u.an.nField*5 + 3;
- if( u.an.len > u.an.offset ) u.an.len = u.an.offset;
+ u.am.len = u.am.nField*5 + 3;
+ if( u.am.len > (int)u.am.offset ) u.am.len = (int)u.am.offset;
/* The KeyFetch() or DataFetch() above are fast and will get the entire
** record header in most cases. But they will fail to get the complete
** record header if the record header does not fit on a single page
** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to
** acquire the complete header text.
*/
- if( !u.an.zRec && u.an.avail<u.an.len ){
- u.an.sMem.flags = 0;
- u.an.sMem.db = 0;
- rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, 0, u.an.len, u.an.pC->isIndex, &u.an.sMem);
+ if( !u.am.zRec && u.am.avail<u.am.len ){
+ u.am.sMem.flags = 0;
+ u.am.sMem.db = 0;
+ rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, 0, u.am.len, u.am.pC->isIndex, &u.am.sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
- u.an.zData = u.an.sMem.z;
- }
- u.an.zEndHdr = (u8 *)&u.an.zData[u.an.len];
- u.an.zIdx = (u8 *)&u.an.zData[u.an.szHdr];
-
- /* Scan the header and use it to fill in the u.an.aType[] and u.an.aOffset[]
- ** arrays. u.an.aType[u.an.i] will contain the type integer for the u.an.i-th
- ** column and u.an.aOffset[u.an.i] will contain the u.an.offset from the beginning
- ** of the record to the start of the data for the u.an.i-th column
- */
- u.an.offset64 = u.an.offset;
- for(u.an.i=0; u.an.i<u.an.nField; u.an.i++){
- if( u.an.zIdx<u.an.zEndHdr ){
- u.an.aOffset[u.an.i] = (u32)u.an.offset64;
- u.an.zIdx += getVarint32(u.an.zIdx, u.an.aType[u.an.i]);
- u.an.offset64 += sqlite3VdbeSerialTypeLen(u.an.aType[u.an.i]);
- }else{
- /* If u.an.i is less that u.an.nField, then there are less fields in this
+ u.am.zData = u.am.sMem.z;
+ }
+ u.am.zEndHdr = (u8 *)&u.am.zData[u.am.len];
+ u.am.zIdx = (u8 *)&u.am.zData[u.am.szHdr];
+
+ /* Scan the header and use it to fill in the u.am.aType[] and u.am.aOffset[]
+ ** arrays. u.am.aType[u.am.i] will contain the type integer for the u.am.i-th
+ ** column and u.am.aOffset[u.am.i] will contain the u.am.offset from the beginning
+ ** of the record to the start of the data for the u.am.i-th column
+ */
+ u.am.offset64 = u.am.offset;
+ for(u.am.i=0; u.am.i<u.am.nField; u.am.i++){
+ if( u.am.zIdx<u.am.zEndHdr ){
+ u.am.aOffset[u.am.i] = (u32)u.am.offset64;
+ u.am.zIdx += getVarint32(u.am.zIdx, u.am.aType[u.am.i]);
+ u.am.offset64 += sqlite3VdbeSerialTypeLen(u.am.aType[u.am.i]);
+ }else{
+ /* If u.am.i is less that u.am.nField, then there are less fields in this
** record than SetNumColumns indicated there are columns in the
- ** table. Set the u.an.offset for any extra columns not present in
+ ** table. Set the u.am.offset for any extra columns not present in
** the record to 0. This tells code below to store a NULL
** instead of deserializing a value from the record.
*/
- u.an.aOffset[u.an.i] = 0;
- }
- }
- sqlite3VdbeMemRelease(&u.an.sMem);
- u.an.sMem.flags = MEM_Null;
+ u.am.aOffset[u.am.i] = 0;
+ }
+ }
+ sqlite3VdbeMemRelease(&u.am.sMem);
+ u.am.sMem.flags = MEM_Null;
/* If we have read more header data than was contained in the header,
** or if the end of the last field appears to be past the end of the
** record, or if the end of the last field appears to be before the end
** of the record (when all fields present), then we must be dealing
** with a corrupt database.
*/
- if( (u.an.zIdx > u.an.zEndHdr)|| (u.an.offset64 > u.an.payloadSize)
- || (u.an.zIdx==u.an.zEndHdr && u.an.offset64!=(u64)u.an.payloadSize) ){
+ if( (u.am.zIdx > u.am.zEndHdr)|| (u.am.offset64 > u.am.payloadSize)
+ || (u.am.zIdx==u.am.zEndHdr && u.am.offset64!=(u64)u.am.payloadSize) ){
rc = SQLITE_CORRUPT_BKPT;
goto op_column_out;
}
}
- /* Get the column information. If u.an.aOffset[u.an.p2] is non-zero, then
- ** deserialize the value from the record. If u.an.aOffset[u.an.p2] is zero,
+ /* Get the column information. If u.am.aOffset[u.am.p2] is non-zero, then
+ ** deserialize the value from the record. If u.am.aOffset[u.am.p2] is zero,
** then there are not enough fields in the record to satisfy the
** request. In this case, set the value NULL or to P4 if P4 is
** a pointer to a Mem object.
*/
- if( u.an.aOffset[u.an.p2] ){
+ if( u.am.aOffset[u.am.p2] ){
assert( rc==SQLITE_OK );
- if( u.an.zRec ){
- sqlite3VdbeMemReleaseExternal(u.an.pDest);
- sqlite3VdbeSerialGet((u8 *)&u.an.zRec[u.an.aOffset[u.an.p2]], u.an.aType[u.an.p2], u.an.pDest);
- }else{
- u.an.len = sqlite3VdbeSerialTypeLen(u.an.aType[u.an.p2]);
- sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest);
- rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len, u.an.pC->isIndex, &u.an.sMem);
+ if( u.am.zRec ){
+ sqlite3VdbeMemReleaseExternal(u.am.pDest);
+ sqlite3VdbeSerialGet((u8 *)&u.am.zRec[u.am.aOffset[u.am.p2]], u.am.aType[u.am.p2], u.am.pDest);
+ }else{
+ u.am.len = sqlite3VdbeSerialTypeLen(u.am.aType[u.am.p2]);
+ sqlite3VdbeMemMove(&u.am.sMem, u.am.pDest);
+ rc = sqlite3VdbeMemFromBtree(u.am.pCrsr, u.am.aOffset[u.am.p2], u.am.len, u.am.pC->isIndex, &u.am.sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
- u.an.zData = u.an.sMem.z;
- sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.aType[u.an.p2], u.an.pDest);
- }
- u.an.pDest->enc = encoding;
+ u.am.zData = u.am.sMem.z;
+ sqlite3VdbeSerialGet((u8*)u.am.zData, u.am.aType[u.am.p2], u.am.pDest);
+ }
+ u.am.pDest->enc = encoding;
}else{
if( pOp->p4type==P4_MEM ){
- sqlite3VdbeMemShallowCopy(u.an.pDest, pOp->p4.pMem, MEM_Static);
- }else{
- assert( u.an.pDest->flags&MEM_Null );
+ sqlite3VdbeMemShallowCopy(u.am.pDest, pOp->p4.pMem, MEM_Static);
+ }else{
+ assert( u.am.pDest->flags&MEM_Null );
}
}
/* If we dynamically allocated space to hold the data (in the
** sqlite3VdbeMemFromBtree() call above) then transfer control of that
- ** dynamically allocated space over to the u.an.pDest structure.
+ ** dynamically allocated space over to the u.am.pDest structure.
** This prevents a memory copy.
*/
- if( u.an.sMem.zMalloc ){
- assert( u.an.sMem.z==u.an.sMem.zMalloc );
- assert( !(u.an.pDest->flags & MEM_Dyn) );
- assert( !(u.an.pDest->flags & (MEM_Blob|MEM_Str)) || u.an.pDest->z==u.an.sMem.z );
- u.an.pDest->flags &= ~(MEM_Ephem|MEM_Static);
- u.an.pDest->flags |= MEM_Term;
- u.an.pDest->z = u.an.sMem.z;
- u.an.pDest->zMalloc = u.an.sMem.zMalloc;
- }
-
- rc = sqlite3VdbeMemMakeWriteable(u.an.pDest);
+ if( u.am.sMem.zMalloc ){
+ assert( u.am.sMem.z==u.am.sMem.zMalloc );
+ assert( !(u.am.pDest->flags & MEM_Dyn) );
+ assert( !(u.am.pDest->flags & (MEM_Blob|MEM_Str)) || u.am.pDest->z==u.am.sMem.z );
+ u.am.pDest->flags &= ~(MEM_Ephem|MEM_Static);
+ u.am.pDest->flags |= MEM_Term;
+ u.am.pDest->z = u.am.sMem.z;
+ u.am.pDest->zMalloc = u.am.sMem.zMalloc;
+ }
+
+ rc = sqlite3VdbeMemMakeWriteable(u.am.pDest);
op_column_out:
- UPDATE_MAX_BLOBSIZE(u.an.pDest);
- REGISTER_TRACE(pOp->p3, u.an.pDest);
+ UPDATE_MAX_BLOBSIZE(u.am.pDest);
+ REGISTER_TRACE(pOp->p3, u.am.pDest);
break;
}
/* Opcode: Affinity P1 P2 * P4 *
@@ -53136,21 +53069,21 @@
** string indicates the column affinity that should be used for the nth
** memory cell in the range.
*/
case OP_Affinity: {
-#if 0 /* local variables moved into u.ao */
+#if 0 /* local variables moved into u.an */
char *zAffinity; /* The affinity to be applied */
Mem *pData0; /* First register to which to apply affinity */
Mem *pLast; /* Last register to which to apply affinity */
Mem *pRec; /* Current register */
-#endif /* local variables moved into u.ao */
-
- u.ao.zAffinity = pOp->p4.z;
- u.ao.pData0 = &p->aMem[pOp->p1];
- u.ao.pLast = &u.ao.pData0[pOp->p2-1];
- for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){
- ExpandBlob(u.ao.pRec);
- applyAffinity(u.ao.pRec, u.ao.zAffinity[u.ao.pRec-u.ao.pData0], encoding);
+#endif /* local variables moved into u.an */
+
+ u.an.zAffinity = pOp->p4.z;
+ u.an.pData0 = &p->aMem[pOp->p1];
+ u.an.pLast = &u.an.pData0[pOp->p2-1];
+ for(u.an.pRec=u.an.pData0; u.an.pRec<=u.an.pLast; u.an.pRec++){
+ ExpandBlob(u.an.pRec);
+ applyAffinity(u.an.pRec, u.an.zAffinity[u.an.pRec-u.an.pData0], encoding);
}
break;
}
@@ -53172,9 +53105,9 @@
**
** If P4 is NULL then all index fields have the affinity NONE.
*/
case OP_MakeRecord: {
-#if 0 /* local variables moved into u.ap */
+#if 0 /* local variables moved into u.ao */
u8 *zNewRecord; /* A buffer to hold the data for the new record */
Mem *pRec; /* The new record */
u64 nData; /* Number of bytes of data space */
int nHdr; /* Number of bytes of header space */
@@ -53188,9 +53121,9 @@
char *zAffinity; /* The affinity string for the record */
int file_format; /* File format to use for encoding */
int i; /* Space used in zNewRecord[] */
int len; /* Length of a field */
-#endif /* local variables moved into u.ap */
+#endif /* local variables moved into u.ao */
/* Assuming the record contains N fields, the record format looks
** like this:
**
@@ -53205,50 +53138,50 @@
** corresponding data element (see sqlite3VdbeSerialType()). The
** hdr-size field is also a varint which is the offset from the beginning
** of the record to data0.
*/
- u.ap.nData = 0; /* Number of bytes of data space */
- u.ap.nHdr = 0; /* Number of bytes of header space */
- u.ap.nByte = 0; /* Data space required for this record */
- u.ap.nZero = 0; /* Number of zero bytes at the end of the record */
- u.ap.nField = pOp->p1;
- u.ap.zAffinity = pOp->p4.z;
- assert( u.ap.nField>0 && pOp->p2>0 && pOp->p2+u.ap.nField<=p->nMem+1 );
- u.ap.pData0 = &p->aMem[u.ap.nField];
- u.ap.nField = pOp->p2;
- u.ap.pLast = &u.ap.pData0[u.ap.nField-1];
- u.ap.file_format = p->minWriteFileFormat;
+ u.ao.nData = 0; /* Number of bytes of data space */
+ u.ao.nHdr = 0; /* Number of bytes of header space */
+ u.ao.nByte = 0; /* Data space required for this record */
+ u.ao.nZero = 0; /* Number of zero bytes at the end of the record */
+ u.ao.nField = pOp->p1;
+ u.ao.zAffinity = pOp->p4.z;
+ assert( u.ao.nField>0 && pOp->p2>0 && pOp->p2+u.ao.nField<=p->nMem+1 );
+ u.ao.pData0 = &p->aMem[u.ao.nField];
+ u.ao.nField = pOp->p2;
+ u.ao.pLast = &u.ao.pData0[u.ao.nField-1];
+ u.ao.file_format = p->minWriteFileFormat;
/* Loop through the elements that will make up the record to figure
** out how much space is required for the new record.
*/
- for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){
- if( u.ap.zAffinity ){
- applyAffinity(u.ap.pRec, u.ap.zAffinity[u.ap.pRec-u.ap.pData0], encoding);
- }
- if( u.ap.pRec->flags&MEM_Zero && u.ap.pRec->n>0 ){
- sqlite3VdbeMemExpandBlob(u.ap.pRec);
- }
- u.ap.serial_type = sqlite3VdbeSerialType(u.ap.pRec, u.ap.file_format);
- u.ap.len = sqlite3VdbeSerialTypeLen(u.ap.serial_type);
- u.ap.nData += u.ap.len;
- u.ap.nHdr += sqlite3VarintLen(u.ap.serial_type);
- if( u.ap.pRec->flags & MEM_Zero ){
+ for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){
+ if( u.ao.zAffinity ){
+ applyAffinity(u.ao.pRec, u.ao.zAffinity[u.ao.pRec-u.ao.pData0], encoding);
+ }
+ if( u.ao.pRec->flags&MEM_Zero && u.ao.pRec->n>0 ){
+ sqlite3VdbeMemExpandBlob(u.ao.pRec);
+ }
+ u.ao.serial_type = sqlite3VdbeSerialType(u.ao.pRec, u.ao.file_format);
+ u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.serial_type);
+ u.ao.nData += u.ao.len;
+ u.ao.nHdr += sqlite3VarintLen(u.ao.serial_type);
+ if( u.ao.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. */
- u.ap.nZero += u.ap.pRec->u.nZero;
- }else if( u.ap.len ){
- u.ap.nZero = 0;
+ u.ao.nZero += u.ao.pRec->u.nZero;
+ }else if( u.ao.len ){
+ u.ao.nZero = 0;
}
}
/* Add the initial header varint and total the size */
- u.ap.nHdr += u.ap.nVarint = sqlite3VarintLen(u.ap.nHdr);
- if( u.ap.nVarint<sqlite3VarintLen(u.ap.nHdr) ){
- u.ap.nHdr++;
- }
- u.ap.nByte = u.ap.nHdr+u.ap.nData-u.ap.nZero;
- if( u.ap.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ u.ao.nHdr += u.ao.nVarint = sqlite3VarintLen(u.ao.nHdr);
+ if( u.ao.nVarint<sqlite3VarintLen(u.ao.nHdr) ){
+ u.ao.nHdr++;
+ }
+ u.ao.nByte = u.ao.nHdr+u.ao.nData-u.ao.nZero;
+ if( u.ao.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
/* Make sure the output register has a buffer large enough to store
@@ -53257,30 +53190,30 @@
** 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, (int)u.ap.nByte, 0) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)u.ao.nByte, 0) ){
goto no_mem;
}
- u.ap.zNewRecord = (u8 *)pOut->z;
+ u.ao.zNewRecord = (u8 *)pOut->z;
/* Write the record */
- u.ap.i = putVarint32(u.ap.zNewRecord, u.ap.nHdr);
- for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){
- u.ap.serial_type = sqlite3VdbeSerialType(u.ap.pRec, u.ap.file_format);
- u.ap.i += putVarint32(&u.ap.zNewRecord[u.ap.i], u.ap.serial_type); /* serial type */
- }
- for(u.ap.pRec=u.ap.pData0; u.ap.pRec<=u.ap.pLast; u.ap.pRec++){ /* serial data */
- u.ap.i += sqlite3VdbeSerialPut(&u.ap.zNewRecord[u.ap.i], (int)(u.ap.nByte-u.ap.i), u.ap.pRec,u.ap.file_format);
- }
- assert( u.ap.i==u.ap.nByte );
+ u.ao.i = putVarint32(u.ao.zNewRecord, u.ao.nHdr);
+ for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){
+ u.ao.serial_type = sqlite3VdbeSerialType(u.ao.pRec, u.ao.file_format);
+ u.ao.i += putVarint32(&u.ao.zNewRecord[u.ao.i], u.ao.serial_type); /* serial type */
+ }
+ for(u.ao.pRec=u.ao.pData0; u.ao.pRec<=u.ao.pLast; u.ao.pRec++){ /* serial data */
+ u.ao.i += sqlite3VdbeSerialPut(&u.ao.zNewRecord[u.ao.i], (int)(u.ao.nByte-u.ao.i), u.ao.pRec,u.ao.file_format);
+ }
+ assert( u.ao.i==u.ao.nByte );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pOut->n = (int)u.ap.nByte;
+ pOut->n = (int)u.ao.nByte;
pOut->flags = MEM_Blob | MEM_Dyn;
pOut->xDel = 0;
- if( u.ap.nZero ){
- pOut->u.nZero = u.ap.nZero;
+ if( u.ao.nZero ){
+ pOut->u.nZero = u.ao.nZero;
pOut->flags |= MEM_Zero;
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
REGISTER_TRACE(pOp->p3, pOut);
@@ -53294,21 +53227,21 @@
** opened by cursor P1 in register P2
*/
#ifndef SQLITE_OMIT_BTREECOUNT
case OP_Count: { /* out2-prerelease */
-#if 0 /* local variables moved into u.aq */
+#if 0 /* local variables moved into u.ap */
i64 nEntry;
BtCursor *pCrsr;
-#endif /* local variables moved into u.aq */
-
- u.aq.pCrsr = p->apCsr[pOp->p1]->pCursor;
- if( u.aq.pCrsr ){
- rc = sqlite3BtreeCount(u.aq.pCrsr, &u.aq.nEntry);
- }else{
- u.aq.nEntry = 0;
+#endif /* local variables moved into u.ap */
+
+ u.ap.pCrsr = p->apCsr[pOp->p1]->pCursor;
+ if( u.ap.pCrsr ){
+ rc = sqlite3BtreeCount(u.ap.pCrsr, &u.ap.nEntry);
+ }else{
+ u.ap.nEntry = 0;
}
pOut->flags = MEM_Int;
- pOut->u.i = u.aq.nEntry;
+ pOut->u.i = u.ap.nEntry;
break;
}
#endif
@@ -53334,25 +53267,23 @@
** database file has an index of 0 and the file used for temporary tables
** has an index of 1.
*/
case OP_Statement: {
-#if 0 /* local variables moved into u.ar */
- int i;
+#if 0 /* local variables moved into u.aq */
Btree *pBt;
-#endif /* local variables moved into u.ar */
+#endif /* local variables moved into u.aq */
if( db->autoCommit==0 || db->activeVdbeCnt>1 ){
- u.ar.i = pOp->p1;
- assert( u.ar.i>=0 && u.ar.i<db->nDb );
- assert( db->aDb[u.ar.i].pBt!=0 );
- u.ar.pBt = db->aDb[u.ar.i].pBt;
- assert( sqlite3BtreeIsInTrans(u.ar.pBt) );
- assert( (p->btreeMask & (1<<u.ar.i))!=0 );
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( db->aDb[pOp->p1].pBt!=0 );
+ u.aq.pBt = db->aDb[pOp->p1].pBt;
+ assert( sqlite3BtreeIsInTrans(u.aq.pBt) );
+ assert( (p->btreeMask & (1<<pOp->p1))!=0 );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
db->nStatement++;
p->iStatement = db->nSavepoint + db->nStatement;
}
- rc = sqlite3BtreeBeginStmt(u.ar.pBt, p->iStatement);
+ rc = sqlite3BtreeBeginStmt(u.aq.pBt, p->iStatement);
}
break;
}
@@ -53362,9 +53293,9 @@
** on the value of P1. To open a new savepoint, P1==0. To release (commit) an
** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
*/
case OP_Savepoint: {
-#if 0 /* local variables moved into u.as */
+#if 0 /* local variables moved into u.ar */
int p1; /* Value of P1 operand */
char *zName; /* Name of savepoint */
int nName;
Savepoint *pNew;
@@ -53371,22 +53302,22 @@
Savepoint *pSavepoint;
Savepoint *pTmp;
int iSavepoint;
int ii;
-#endif /* local variables moved into u.as */
-
- u.as.p1 = pOp->p1;
- u.as.zName = pOp->p4.z;
-
- /* Assert that the u.as.p1 parameter is valid. Also that if there is no open
+#endif /* local variables moved into u.ar */
+
+ u.ar.p1 = pOp->p1;
+ u.ar.zName = pOp->p4.z;
+
+ /* Assert that the u.ar.p1 parameter is valid. Also that if there is no open
** transaction, then there cannot be any savepoints.
*/
assert( db->pSavepoint==0 || db->autoCommit==0 );
- assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK );
+ assert( u.ar.p1==SAVEPOINT_BEGIN||u.ar.p1==SAVEPOINT_RELEASE||u.ar.p1==SAVEPOINT_ROLLBACK );
assert( db->pSavepoint || db->isTransactionSavepoint==0 );
assert( checkSavepointCount(db) );
- if( u.as.p1==SAVEPOINT_BEGIN ){
+ if( u.ar.p1==SAVEPOINT_BEGIN ){
if( db->writeVdbeCnt>0 ){
/* A new savepoint cannot be created if there are active write
** statements (i.e. open read/write incremental blob handles).
*/
@@ -53393,15 +53324,15 @@
sqlite3SetString(&p->zErrMsg, db, "cannot open savepoint - "
"SQL statements in progress");
rc = SQLITE_BUSY;
}else{
- u.as.nName = sqlite3Strlen30(u.as.zName);
+ u.ar.nName = sqlite3Strlen30(u.ar.zName);
/* Create a new savepoint structure. */
- u.as.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.as.nName+1);
- if( u.as.pNew ){
- u.as.pNew->zName = (char *)&u.as.pNew[1];
- memcpy(u.as.pNew->zName, u.as.zName, u.as.nName+1);
+ u.ar.pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+u.ar.nName+1);
+ if( u.ar.pNew ){
+ u.ar.pNew->zName = (char *)&u.ar.pNew[1];
+ memcpy(u.ar.pNew->zName, u.ar.zName, u.ar.nName+1);
/* If there is no open transaction, then mark this as a special
** "transaction savepoint". */
if( db->autoCommit ){
@@ -53411,37 +53342,37 @@
db->nSavepoint++;
}
/* Link the new savepoint into the database handle's list. */
- u.as.pNew->pNext = db->pSavepoint;
- db->pSavepoint = u.as.pNew;
- }
- }
- }else{
- u.as.iSavepoint = 0;
+ u.ar.pNew->pNext = db->pSavepoint;
+ db->pSavepoint = u.ar.pNew;
+ }
+ }
+ }else{
+ u.ar.iSavepoint = 0;
/* Find the named savepoint. If there is no such savepoint, then an
** an error is returned to the user. */
for(
- u.as.pSavepoint = db->pSavepoint;
- u.as.pSavepoint && sqlite3StrICmp(u.as.pSavepoint->zName, u.as.zName);
- u.as.pSavepoint = u.as.pSavepoint->pNext
- ){
- u.as.iSavepoint++;
- }
- if( !u.as.pSavepoint ){
- sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName);
+ u.ar.pSavepoint = db->pSavepoint;
+ u.ar.pSavepoint && sqlite3StrICmp(u.ar.pSavepoint->zName, u.ar.zName);
+ u.ar.pSavepoint = u.ar.pSavepoint->pNext
+ ){
+ u.ar.iSavepoint++;
+ }
+ if( !u.ar.pSavepoint ){
+ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName);
rc = SQLITE_ERROR;
}else if(
- db->writeVdbeCnt>0 || (u.as.p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1)
+ db->writeVdbeCnt>0 || (u.ar.p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1)
){
/* It is not possible to release (commit) a savepoint if there are
** active write statements. It is not possible to rollback a savepoint
** if there are any active statements at all.
*/
sqlite3SetString(&p->zErrMsg, db,
"cannot %s savepoint - SQL statements in progress",
- (u.as.p1==SAVEPOINT_ROLLBACK ? "rollback": "release")
+ (u.ar.p1==SAVEPOINT_ROLLBACK ? "rollback": "release")
);
rc = SQLITE_BUSY;
}else{
@@ -53448,10 +53379,10 @@
/* Determine whether or not this is a transaction savepoint. If so,
** and this is a RELEASE command, then the current transaction
** is committed.
*/
- int isTransaction = u.as.pSavepoint->pNext==0 && db->isTransactionSavepoint;
- if( isTransaction && u.as.p1==SAVEPOINT_RELEASE ){
+ int isTransaction = u.ar.pSavepoint->pNext==0 && db->isTransactionSavepoint;
+ if( isTransaction && u.ar.p1==SAVEPOINT_RELEASE ){
db->autoCommit = 1;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pc = pc;
db->autoCommit = 0;
@@ -53460,35 +53391,35 @@
}
db->isTransactionSavepoint = 0;
rc = p->rc;
}else{
- u.as.iSavepoint = db->nSavepoint - u.as.iSavepoint - 1;
- for(u.as.ii=0; u.as.ii<db->nDb; u.as.ii++){
- rc = sqlite3BtreeSavepoint(db->aDb[u.as.ii].pBt, u.as.p1, u.as.iSavepoint);
+ u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1;
+ for(u.ar.ii=0; u.ar.ii<db->nDb; u.ar.ii++){
+ rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
}
- if( u.as.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
+ if( u.ar.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetInternalSchema(db, 0);
}
}
/* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
** savepoints nested inside of the savepoint being operated on. */
- while( db->pSavepoint!=u.as.pSavepoint ){
- u.as.pTmp = db->pSavepoint;
- db->pSavepoint = u.as.pTmp->pNext;
- sqlite3DbFree(db, u.as.pTmp);
+ while( db->pSavepoint!=u.ar.pSavepoint ){
+ u.ar.pTmp = db->pSavepoint;
+ db->pSavepoint = u.ar.pTmp->pNext;
+ sqlite3DbFree(db, u.ar.pTmp);
db->nSavepoint--;
}
/* If it is a RELEASE, then destroy the savepoint being operated on too */
- if( u.as.p1==SAVEPOINT_RELEASE ){
- assert( u.as.pSavepoint==db->pSavepoint );
- db->pSavepoint = u.as.pSavepoint->pNext;
- sqlite3DbFree(db, u.as.pSavepoint);
+ if( u.ar.p1==SAVEPOINT_RELEASE ){
+ assert( u.ar.pSavepoint==db->pSavepoint );
+ db->pSavepoint = u.ar.pSavepoint->pNext;
+ sqlite3DbFree(db, u.ar.pSavepoint);
if( !isTransaction ){
db->nSavepoint--;
}
}
@@ -53507,46 +53438,46 @@
**
** This instruction causes the VM to halt.
*/
case OP_AutoCommit: {
-#if 0 /* local variables moved into u.at */
+#if 0 /* local variables moved into u.as */
int desiredAutoCommit;
- int rollback;
+ int iRollback;
int turnOnAC;
-#endif /* local variables moved into u.at */
-
- u.at.desiredAutoCommit = pOp->p1;
- u.at.rollback = pOp->p2;
- u.at.turnOnAC = u.at.desiredAutoCommit && !db->autoCommit;
- assert( u.at.desiredAutoCommit==1 || u.at.desiredAutoCommit==0 );
- assert( u.at.desiredAutoCommit==1 || u.at.rollback==0 );
+#endif /* local variables moved into u.as */
+
+ u.as.desiredAutoCommit = pOp->p1;
+ u.as.iRollback = pOp->p2;
+ u.as.turnOnAC = u.as.desiredAutoCommit && !db->autoCommit;
+ assert( u.as.desiredAutoCommit==1 || u.as.desiredAutoCommit==0 );
+ assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 );
assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
- if( u.at.turnOnAC && u.at.rollback && db->activeVdbeCnt>1 ){
+ if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){
/* If this instruction implements a ROLLBACK and other VMs are
** still running, and a transaction is active, return an error indicating
** that the other VMs must complete first.
*/
- sqlite3SetString(&p->zErrMsg, db, "cannot u.at.rollback transaction - "
+ sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
"SQL statements in progress");
rc = SQLITE_BUSY;
- }else if( u.at.turnOnAC && !u.at.rollback && db->writeVdbeCnt>1 ){
+ }else if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){
/* If this instruction implements a COMMIT and other VMs are writing
** return an error indicating that the other VMs must complete first.
*/
sqlite3SetString(&p->zErrMsg, db, "cannot commit transaction - "
"SQL statements in progress");
rc = SQLITE_BUSY;
- }else if( u.at.desiredAutoCommit!=db->autoCommit ){
- if( u.at.rollback ){
- assert( u.at.desiredAutoCommit==1 );
+ }else if( u.as.desiredAutoCommit!=db->autoCommit ){
+ if( u.as.iRollback ){
+ assert( u.as.desiredAutoCommit==1 );
sqlite3RollbackAll(db);
db->autoCommit = 1;
}else{
- db->autoCommit = (u8)u.at.desiredAutoCommit;
+ db->autoCommit = (u8)u.as.desiredAutoCommit;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pc = pc;
- db->autoCommit = (u8)(1-u.at.desiredAutoCommit);
+ db->autoCommit = (u8)(1-u.as.desiredAutoCommit);
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
}
@@ -53559,10 +53490,10 @@
}
goto vdbe_return;
}else{
sqlite3SetString(&p->zErrMsg, db,
- (!u.at.desiredAutoCommit)?"cannot start a transaction within a transaction":(
- (u.at.rollback)?"cannot u.at.rollback - no transaction is active":
+ (!u.as.desiredAutoCommit)?"cannot start a transaction within a transaction":(
+ (u.as.iRollback)?"cannot rollback - no transaction is active":
"cannot commit - no transaction is active"));
rc = SQLITE_ERROR;
}
@@ -53590,20 +53521,18 @@
**
** If P2 is zero, then a read-lock is obtained on the database file.
*/
case OP_Transaction: {
-#if 0 /* local variables moved into u.au */
- int i;
+#if 0 /* local variables moved into u.at */
Btree *pBt;
-#endif /* local variables moved into u.au */
-
- u.au.i = pOp->p1;
- assert( u.au.i>=0 && u.au.i<db->nDb );
- assert( (p->btreeMask & (1<<u.au.i))!=0 );
- u.au.pBt = db->aDb[u.au.i].pBt;
-
- if( u.au.pBt ){
- rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
+#endif /* local variables moved into u.at */
+
+ assert( pOp->p1>=0 && pOp->p1<db->nDb );
+ assert( (p->btreeMask & (1<<pOp->p1))!=0 );
+ u.at.pBt = db->aDb[pOp->p1].pBt;
+
+ if( u.at.pBt ){
+ rc = sqlite3BtreeBeginTrans(u.at.pBt, pOp->p2);
if( rc==SQLITE_BUSY ){
p->pc = pc;
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
@@ -53627,23 +53556,23 @@
** must be started or there must be an open cursor) before
** executing this instruction.
*/
case OP_ReadCookie: { /* out2-prerelease */
-#if 0 /* local variables moved into u.av */
+#if 0 /* local variables moved into u.au */
int iMeta;
int iDb;
int iCookie;
-#endif /* local variables moved into u.av */
-
- u.av.iDb = pOp->p1;
- u.av.iCookie = pOp->p3;
+#endif /* local variables moved into u.au */
+
+ u.au.iDb = pOp->p1;
+ u.au.iCookie = pOp->p3;
assert( pOp->p3<SQLITE_N_BTREE_META );
- assert( u.av.iDb>=0 && u.av.iDb<db->nDb );
- assert( db->aDb[u.av.iDb].pBt!=0 );
- assert( (p->btreeMask & (1<<u.av.iDb))!=0 );
-
- rc = sqlite3BtreeGetMeta(db->aDb[u.av.iDb].pBt, u.av.iCookie, (u32 *)&u.av.iMeta);
- pOut->u.i = u.av.iMeta;
+ assert( u.au.iDb>=0 && u.au.iDb<db->nDb );
+ assert( db->aDb[u.au.iDb].pBt!=0 );
+ assert( (p->btreeMask & (1<<u.au.iDb))!=0 );
+
+ rc = sqlite3BtreeGetMeta(db->aDb[u.au.iDb].pBt, u.au.iCookie, (u32 *)&u.au.iMeta);
+ pOut->u.i = u.au.iMeta;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -53657,26 +53586,26 @@
**
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: { /* in3 */
-#if 0 /* local variables moved into u.aw */
+#if 0 /* local variables moved into u.av */
Db *pDb;
-#endif /* local variables moved into u.aw */
+#endif /* local variables moved into u.av */
assert( pOp->p2<SQLITE_N_BTREE_META );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
- u.aw.pDb = &db->aDb[pOp->p1];
- assert( u.aw.pDb->pBt!=0 );
+ u.av.pDb = &db->aDb[pOp->p1];
+ assert( u.av.pDb->pBt!=0 );
sqlite3VdbeMemIntegerify(pIn3);
/* See note about index shifting on OP_ReadCookie */
- rc = sqlite3BtreeUpdateMeta(u.aw.pDb->pBt, pOp->p2, (int)pIn3->u.i);
+ rc = sqlite3BtreeUpdateMeta(u.av.pDb->pBt, pOp->p2, (int)pIn3->u.i);
if( pOp->p2==BTREE_SCHEMA_VERSION ){
/* When the schema cookie changes, record the new cookie internally */
- u.aw.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
+ u.av.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
db->flags |= SQLITE_InternChanges;
}else if( pOp->p2==BTREE_FILE_FORMAT ){
/* Record changes in the file format */
- u.aw.pDb->pSchema->file_format = (u8)pIn3->u.i;
+ u.av.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 */
@@ -53701,22 +53630,22 @@
** to be executed (to establish a read lock) before this opcode is
** invoked.
*/
case OP_VerifyCookie: {
-#if 0 /* local variables moved into u.ax */
+#if 0 /* local variables moved into u.aw */
int iMeta;
Btree *pBt;
-#endif /* local variables moved into u.ax */
+#endif /* local variables moved into u.aw */
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
- u.ax.pBt = db->aDb[pOp->p1].pBt;
- if( u.ax.pBt ){
- rc = sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta);
+ u.aw.pBt = db->aDb[pOp->p1].pBt;
+ if( u.aw.pBt ){
+ rc = sqlite3BtreeGetMeta(u.aw.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.aw.iMeta);
}else{
rc = SQLITE_OK;
- u.ax.iMeta = 0;
- }
- if( rc==SQLITE_OK && u.ax.iMeta!=pOp->p2 ){
+ u.aw.iMeta = 0;
+ }
+ if( rc==SQLITE_OK && u.aw.iMeta!=pOp->p2 ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
** stored with the in-memory representation of the schema, do
@@ -53730,9 +53659,9 @@
** v-table would have to be ready for the sqlite3_vtab structure itself
** to be invalidated whenever sqlite3_step() is called from within
** a v-table method.
*/
- if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ax.iMeta ){
+ if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.aw.iMeta ){
sqlite3ResetInternalSchema(db, pOp->p1);
}
sqlite3ExpirePreparedStatements(db);
@@ -53791,103 +53720,102 @@
** See also OpenRead.
*/
case OP_OpenRead:
case OP_OpenWrite: {
-#if 0 /* local variables moved into u.ay */
+#if 0 /* local variables moved into u.ax */
int nField;
KeyInfo *pKeyInfo;
- int i;
int p2;
int iDb;
int wrFlag;
Btree *pX;
VdbeCursor *pCur;
Db *pDb;
int flags;
-#endif /* local variables moved into u.ay */
-
- u.ay.nField = 0;
- u.ay.pKeyInfo = 0;
- u.ay.i = pOp->p1;
- u.ay.p2 = pOp->p2;
- u.ay.iDb = pOp->p3;
- assert( u.ay.iDb>=0 && u.ay.iDb<db->nDb );
- assert( (p->btreeMask & (1<<u.ay.iDb))!=0 );
- u.ay.pDb = &db->aDb[u.ay.iDb];
- u.ay.pX = u.ay.pDb->pBt;
- assert( u.ay.pX!=0 );
+#endif /* local variables moved into u.ax */
+
+ u.ax.nField = 0;
+ u.ax.pKeyInfo = 0;
+ u.ax.p2 = pOp->p2;
+ u.ax.iDb = pOp->p3;
+ assert( u.ax.iDb>=0 && u.ax.iDb<db->nDb );
+ assert( (p->btreeMask & (1<<u.ax.iDb))!=0 );
+ u.ax.pDb = &db->aDb[u.ax.iDb];
+ u.ax.pX = u.ax.pDb->pBt;
+ assert( u.ax.pX!=0 );
if( pOp->opcode==OP_OpenWrite ){
- u.ay.wrFlag = 1;
- if( u.ay.pDb->pSchema->file_format < p->minWriteFileFormat ){
- p->minWriteFileFormat = u.ay.pDb->pSchema->file_format;
- }
- }else{
- u.ay.wrFlag = 0;
+ u.ax.wrFlag = 1;
+ if( u.ax.pDb->pSchema->file_format < p->minWriteFileFormat ){
+ p->minWriteFileFormat = u.ax.pDb->pSchema->file_format;
+ }
+ }else{
+ u.ax.wrFlag = 0;
}
if( pOp->p5 ){
- assert( u.ay.p2>0 );
- assert( u.ay.p2<=p->nMem );
- pIn2 = &p->aMem[u.ay.p2];
+ assert( u.ax.p2>0 );
+ assert( u.ax.p2<=p->nMem );
+ pIn2 = &p->aMem[u.ax.p2];
sqlite3VdbeMemIntegerify(pIn2);
- u.ay.p2 = (int)pIn2->u.i;
- if( u.ay.p2<2 ) {
+ u.ax.p2 = (int)pIn2->u.i;
+ /* The u.ax.p2 value always comes from a prior OP_CreateTable opcode and
+ ** that opcode will always set the u.ax.p2 value to 2 or more or else fail.
+ ** If there were a failure, the prepared statement would have halted
+ ** before reaching this instruction. */
+ if( NEVER(u.ax.p2<2) ) {
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
}
- assert( u.ay.i>=0 );
if( pOp->p4type==P4_KEYINFO ){
- u.ay.pKeyInfo = pOp->p4.pKeyInfo;
- u.ay.pKeyInfo->enc = ENC(p->db);
- u.ay.nField = u.ay.pKeyInfo->nField+1;
+ u.ax.pKeyInfo = pOp->p4.pKeyInfo;
+ u.ax.pKeyInfo->enc = ENC(p->db);
+ u.ax.nField = u.ax.pKeyInfo->nField+1;
}else if( pOp->p4type==P4_INT32 ){
- u.ay.nField = pOp->p4.i;
- }
- u.ay.pCur = allocateCursor(p, u.ay.i, u.ay.nField, u.ay.iDb, 1);
- if( u.ay.pCur==0 ) goto no_mem;
- u.ay.pCur->nullRow = 1;
- rc = sqlite3BtreeCursor(u.ay.pX, u.ay.p2, u.ay.wrFlag, u.ay.pKeyInfo, u.ay.pCur->pCursor);
- u.ay.pCur->pKeyInfo = u.ay.pKeyInfo;
+ u.ax.nField = pOp->p4.i;
+ }
+ assert( pOp->p1>=0 );
+ u.ax.pCur = allocateCursor(p, pOp->p1, u.ax.nField, u.ax.iDb, 1);
+ if( u.ax.pCur==0 ) goto no_mem;
+ u.ax.pCur->nullRow = 1;
+ rc = sqlite3BtreeCursor(u.ax.pX, u.ax.p2, u.ax.wrFlag, u.ax.pKeyInfo, u.ax.pCur->pCursor);
+ u.ax.pCur->pKeyInfo = u.ax.pKeyInfo;
switch( rc ){
- case SQLITE_BUSY: {
- p->pc = pc;
- p->rc = rc = SQLITE_BUSY;
- goto vdbe_return;
- }
case SQLITE_OK: {
- u.ay.flags = sqlite3BtreeFlags(u.ay.pCur->pCursor);
- /* Sanity checking. Only the lower four bits of the u.ay.flags byte should
+ u.ax.flags = sqlite3BtreeFlags(u.ax.pCur->pCursor);
+
+ /* Sanity checking. Only the lower four bits of the u.ax.flags byte should
** be used. Bit 3 (mask 0x08) is unpredictable. The lower 3 bits
** (mask 0x07) should be either 5 (intkey+leafdata for tables) or
** 2 (zerodata for indices). If these conditions are not met it can
- ** only mean that we are dealing with a corrupt database file
- */
- if( (u.ay.flags & 0xf0)!=0 || ((u.ay.flags & 0x07)!=5 && (u.ay.flags & 0x07)!=2) ){
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
- }
- u.ay.pCur->isTable = (u.ay.flags & BTREE_INTKEY)!=0 ?1:0;
- u.ay.pCur->isIndex = (u.ay.flags & BTREE_ZERODATA)!=0 ?1:0;
+ ** only mean that we are dealing with a corrupt database file.
+ ** Note: All of the above is checked already in sqlite3BtreeCursor().
+ */
+ assert( (u.ax.flags & 0xf0)==0 );
+ assert( (u.ax.flags & 0x07)==5 || (u.ax.flags & 0x07)==2 );
+
+ u.ax.pCur->isTable = (u.ax.flags & BTREE_INTKEY)!=0 ?1:0;
+ u.ax.pCur->isIndex = (u.ax.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
*/
- if( (u.ay.pCur->isTable && pOp->p4type==P4_KEYINFO)
- || (u.ay.pCur->isIndex && pOp->p4type!=P4_KEYINFO) ){
+ if( (u.ax.pCur->isTable && pOp->p4type==P4_KEYINFO)
+ || (u.ax.pCur->isIndex && pOp->p4type!=P4_KEYINFO) ){
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
break;
}
case SQLITE_EMPTY: {
- u.ay.pCur->isTable = pOp->p4type!=P4_KEYINFO;
- u.ay.pCur->isIndex = !u.ay.pCur->isTable;
- u.ay.pCur->pCursor = 0;
+ u.ax.pCur->isTable = pOp->p4type!=P4_KEYINFO;
+ u.ax.pCur->isIndex = !u.ax.pCur->isTable;
+ u.ax.pCur->pCursor = 0;
rc = SQLITE_OK;
break;
}
default: {
+ assert( rc!=SQLITE_BUSY ); /* Busy conditions detected earlier */
goto abort_due_to_error;
}
}
break;
@@ -53911,28 +53839,26 @@
** this opcode. Then this opcode was call OpenVirtual. But
** that created confusion with the whole virtual-table idea.
*/
case OP_OpenEphemeral: {
-#if 0 /* local variables moved into u.az */
- int i;
+#if 0 /* local variables moved into u.ay */
VdbeCursor *pCx;
-#endif /* local variables moved into u.az */
+#endif /* local variables moved into u.ay */
static const int openFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXCLUSIVE |
SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_TRANSIENT_DB;
- u.az.i = pOp->p1;
- assert( u.az.i>=0 );
- u.az.pCx = allocateCursor(p, u.az.i, pOp->p2, -1, 1);
- if( u.az.pCx==0 ) goto no_mem;
- u.az.pCx->nullRow = 1;
+ assert( pOp->p1>=0 );
+ u.ay.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( u.ay.pCx==0 ) goto no_mem;
+ u.ay.pCx->nullRow = 1;
rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags,
- &u.az.pCx->pBt);
- if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(u.az.pCx->pBt, 1);
+ &u.ay.pCx->pBt);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeBeginTrans(u.ay.pCx->pBt, 1);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
** sqlite3BtreeCreateTable() with the BTREE_ZERODATA flag before
@@ -53941,23 +53867,23 @@
*/
if( pOp->p4.pKeyInfo ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(u.az.pCx->pBt, &pgno, BTREE_ZERODATA);
+ rc = sqlite3BtreeCreateTable(u.ay.pCx->pBt, &pgno, BTREE_ZERODATA);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
- rc = sqlite3BtreeCursor(u.az.pCx->pBt, pgno, 1,
- (KeyInfo*)pOp->p4.z, u.az.pCx->pCursor);
- u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
- u.az.pCx->pKeyInfo->enc = ENC(p->db);
- }
- u.az.pCx->isTable = 0;
- }else{
- rc = sqlite3BtreeCursor(u.az.pCx->pBt, MASTER_ROOT, 1, 0, u.az.pCx->pCursor);
- u.az.pCx->isTable = 1;
- }
- }
- u.az.pCx->isIndex = !u.az.pCx->isTable;
+ rc = sqlite3BtreeCursor(u.ay.pCx->pBt, pgno, 1,
+ (KeyInfo*)pOp->p4.z, u.ay.pCx->pCursor);
+ u.ay.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+ u.ay.pCx->pKeyInfo->enc = ENC(p->db);
+ }
+ u.ay.pCx->isTable = 0;
+ }else{
+ rc = sqlite3BtreeCursor(u.ay.pCx->pBt, MASTER_ROOT, 1, 0, u.ay.pCx->pCursor);
+ u.ay.pCx->isTable = 1;
+ }
+ }
+ u.ay.pCx->isIndex = !u.ay.pCx->isTable;
break;
}
/* Opcode: OpenPseudo P1 P2 P3 * *
@@ -53983,22 +53909,20 @@
** P3 is the number of fields in the records that will be stored by
** the pseudo-table.
*/
case OP_OpenPseudo: {
-#if 0 /* local variables moved into u.ba */
- int i;
+#if 0 /* local variables moved into u.az */
VdbeCursor *pCx;
-#endif /* local variables moved into u.ba */
-
- u.ba.i = pOp->p1;
- assert( u.ba.i>=0 );
- u.ba.pCx = allocateCursor(p, u.ba.i, pOp->p3, -1, 0);
- if( u.ba.pCx==0 ) goto no_mem;
- u.ba.pCx->nullRow = 1;
- u.ba.pCx->pseudoTable = 1;
- u.ba.pCx->ephemPseudoTable = (u8)pOp->p2;
- u.ba.pCx->isTable = 1;
- u.ba.pCx->isIndex = 0;
+#endif /* local variables moved into u.az */
+
+ assert( pOp->p1>=0 );
+ u.az.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+ if( u.az.pCx==0 ) goto no_mem;
+ u.az.pCx->nullRow = 1;
+ u.az.pCx->pseudoTable = 1;
+ u.az.pCx->ephemPseudoTable = (u8)pOp->p2;
+ u.az.pCx->isTable = 1;
+ u.az.pCx->isIndex = 0;
break;
}
/* Opcode: Close P1 * * * *
@@ -54006,15 +53930,11 @@
** Close a cursor previously opened as P1. If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
-#if 0 /* local variables moved into u.bb */
- int i;
-#endif /* local variables moved into u.bb */
- u.bb.i = pOp->p1;
- assert( u.bb.i>=0 && u.bb.i<p->nCursor );
- sqlite3VdbeFreeCursor(p, p->apCsr[u.bb.i]);
- p->apCsr[u.bb.i] = 0;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
+ p->apCsr[pOp->p1] = 0;
break;
}
/* Opcode: SeekGe P1 P2 P3 P4 *
@@ -54072,33 +53992,31 @@
case OP_SeekLt: /* jump, in3 */
case OP_SeekLe: /* jump, in3 */
case OP_SeekGe: /* jump, in3 */
case OP_SeekGt: { /* jump, in3 */
-#if 0 /* local variables moved into u.bc */
- int i;
+#if 0 /* local variables moved into u.ba */
int res;
int oc;
VdbeCursor *pC;
UnpackedRecord r;
int nField;
i64 iKey; /* The rowid we are to seek to */
-#endif /* local variables moved into u.bc */
-
- u.bc.i = pOp->p1;
- assert( u.bc.i>=0 && u.bc.i<p->nCursor );
+#endif /* local variables moved into u.ba */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p2!=0 );
- u.bc.pC = p->apCsr[u.bc.i];
- assert( u.bc.pC!=0 );
- if( u.bc.pC->pCursor!=0 ){
- u.bc.oc = pOp->opcode;
- u.bc.pC->nullRow = 0;
- if( u.bc.pC->isTable ){
+ u.ba.pC = p->apCsr[pOp->p1];
+ assert( u.ba.pC!=0 );
+ if( u.ba.pC->pCursor!=0 ){
+ u.ba.oc = pOp->opcode;
+ u.ba.pC->nullRow = 0;
+ if( u.ba.pC->isTable ){
/* 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);
- u.bc.iKey = sqlite3VdbeIntValue(pIn3);
- u.bc.pC->rowidIsValid = 0;
+ u.ba.iKey = sqlite3VdbeIntValue(pIn3);
+ u.ba.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 ){
@@ -54111,97 +54029,98 @@
/* If we reach this point, then the P3 value must be a floating
** point number. */
assert( (pIn3->flags & MEM_Real)!=0 );
- if( u.bc.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bc.iKey || pIn3->r>0) ){
- /* The P3 value is to large in magnitude to be expressed as an
+ if( u.ba.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.ba.iKey || pIn3->r>0) ){
+ /* The P3 value is too large in magnitude to be expressed as an
** integer. */
- u.bc.res = 1;
+ u.ba.res = 1;
if( pIn3->r<0 ){
- if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekGe ){
- rc = sqlite3BtreeFirst(u.bc.pC->pCursor, &u.bc.res);
+ if( u.ba.oc==OP_SeekGt || u.ba.oc==OP_SeekGe ){
+ rc = sqlite3BtreeFirst(u.ba.pC->pCursor, &u.ba.res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}else{
- if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe ){
- rc = sqlite3BtreeLast(u.bc.pC->pCursor, &u.bc.res);
+ if( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe ){
+ rc = sqlite3BtreeLast(u.ba.pC->pCursor, &u.ba.res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
- if( u.bc.res ){
+ if( u.ba.res ){
pc = pOp->p2 - 1;
}
break;
- }else if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekGe ){
+ }else if( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekGe ){
/* Use the ceiling() function to convert real->int */
- if( pIn3->r > (double)u.bc.iKey ) u.bc.iKey++;
+ if( pIn3->r > (double)u.ba.iKey ) u.ba.iKey++;
}else{
/* Use the floor() function to convert real->int */
- assert( u.bc.oc==OP_SeekLe || u.bc.oc==OP_SeekGt );
- if( pIn3->r < (double)u.bc.iKey ) u.bc.iKey--;
- }
- }
- rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, 0, (u64)u.bc.iKey, 0, &u.bc.res);
+ assert( u.ba.oc==OP_SeekLe || u.ba.oc==OP_SeekGt );
+ if( pIn3->r < (double)u.ba.iKey ) u.ba.iKey--;
+ }
+ }
+ rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, 0, (u64)u.ba.iKey, 0, &u.ba.res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- if( u.bc.res==0 ){
- u.bc.pC->rowidIsValid = 1;
- u.bc.pC->lastRowid = u.bc.iKey;
- }
- }else{
- u.bc.nField = pOp->p4.i;
+ if( u.ba.res==0 ){
+ u.ba.pC->rowidIsValid = 1;
+ u.ba.pC->lastRowid = u.ba.iKey;
+ }
+ }else{
+ u.ba.nField = pOp->p4.i;
assert( pOp->p4type==P4_INT32 );
- assert( u.bc.nField>0 );
- u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
- u.bc.r.nField = (u16)u.bc.nField;
- if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){
- u.bc.r.flags = UNPACKED_INCRKEY;
- }else{
- u.bc.r.flags = 0;
- }
- u.bc.r.aMem = &p->aMem[pOp->p3];
- rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, &u.bc.r, 0, 0, &u.bc.res);
+ assert( u.ba.nField>0 );
+ u.ba.r.pKeyInfo = u.ba.pC->pKeyInfo;
+ u.ba.r.nField = (u16)u.ba.nField;
+ if( u.ba.oc==OP_SeekGt || u.ba.oc==OP_SeekLe ){
+ u.ba.r.flags = UNPACKED_INCRKEY;
+ }else{
+ u.ba.r.flags = 0;
+ }
+ u.ba.r.aMem = &p->aMem[pOp->p3];
+ rc = sqlite3BtreeMovetoUnpacked(u.ba.pC->pCursor, &u.ba.r, 0, 0, &u.ba.res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- u.bc.pC->rowidIsValid = 0;
- }
- u.bc.pC->deferredMoveto = 0;
- u.bc.pC->cacheStatus = CACHE_STALE;
+ u.ba.pC->rowidIsValid = 0;
+ }
+ u.ba.pC->deferredMoveto = 0;
+ u.ba.pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
- if( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt ){
- if( u.bc.res<0 || (u.bc.res==0 && u.bc.oc==OP_SeekGt) ){
- rc = sqlite3BtreeNext(u.bc.pC->pCursor, &u.bc.res);
+ if( u.ba.oc==OP_SeekGe || u.ba.oc==OP_SeekGt ){
+ if( u.ba.res<0 || (u.ba.res==0 && u.ba.oc==OP_SeekGt) ){
+ rc = sqlite3BtreeNext(u.ba.pC->pCursor, &u.ba.res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
- u.bc.pC->rowidIsValid = 0;
- }else{
- u.bc.res = 0;
- }
- }else{
- assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
- if( u.bc.res>0 || (u.bc.res==0 && u.bc.oc==OP_SeekLt) ){
- rc = sqlite3BtreePrevious(u.bc.pC->pCursor, &u.bc.res);
+ u.ba.pC->rowidIsValid = 0;
+ }else{
+ u.ba.res = 0;
+ }
+ }else{
+ assert( u.ba.oc==OP_SeekLt || u.ba.oc==OP_SeekLe );
+ if( u.ba.res>0 || (u.ba.res==0 && u.ba.oc==OP_SeekLt) ){
+ rc = sqlite3BtreePrevious(u.ba.pC->pCursor, &u.ba.res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
- u.bc.pC->rowidIsValid = 0;
- }else{
- /* u.bc.res might be negative because the table is empty. Check to
+ u.ba.pC->rowidIsValid = 0;
+ }else{
+ /* u.ba.res might be negative because the table is empty. Check to
** see if this is the case.
*/
- u.bc.res = sqlite3BtreeEof(u.bc.pC->pCursor);
+ u.ba.res = sqlite3BtreeEof(u.ba.pC->pCursor);
}
}
assert( pOp->p2>0 );
- if( u.bc.res ){
+ if( u.ba.res ){
pc = pOp->p2 - 1;
}
- }else if( !u.bc.pC->pseudoTable ){
+ }else{
/* This happens when attempting to open the sqlite3_master table
** for read access returns SQLITE_EMPTY. In this case always
** take the jump (since there are no records in the table).
*/
+ assert( u.ba.pC->pseudoTable==0 );
pc = pOp->p2 - 1;
}
break;
}
@@ -54215,23 +54134,21 @@
** the cursor is used to read a record. That way, if no reads
** occur, no unnecessary I/O happens.
*/
case OP_Seek: { /* in2 */
-#if 0 /* local variables moved into u.bd */
- int i;
- VdbeCursor *pC;
-#endif /* local variables moved into u.bd */
-
- u.bd.i = pOp->p1;
- assert( u.bd.i>=0 && u.bd.i<p->nCursor );
- u.bd.pC = p->apCsr[u.bd.i];
- assert( u.bd.pC!=0 );
- if( u.bd.pC->pCursor!=0 ){
- assert( u.bd.pC->isTable );
- u.bd.pC->nullRow = 0;
- u.bd.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
- u.bd.pC->rowidIsValid = 0;
- u.bd.pC->deferredMoveto = 1;
+#if 0 /* local variables moved into u.bb */
+ VdbeCursor *pC;
+#endif /* local variables moved into u.bb */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bb.pC = p->apCsr[pOp->p1];
+ assert( u.bb.pC!=0 );
+ if( ALWAYS(u.bb.pC->pCursor!=0) ){
+ assert( u.bb.pC->isTable );
+ u.bb.pC->nullRow = 0;
+ u.bb.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+ u.bb.pC->rowidIsValid = 0;
+ u.bb.pC->deferredMoveto = 1;
}
break;
}
@@ -54267,46 +54184,45 @@
** See also: Found, NotExists, IsUnique
*/
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
-#if 0 /* local variables moved into u.be */
- int i;
+#if 0 /* local variables moved into u.bc */
int alreadyExists;
VdbeCursor *pC;
int res;
UnpackedRecord *pIdxKey;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-#endif /* local variables moved into u.be */
-
- u.be.i = pOp->p1;
- u.be.alreadyExists = 0;
- assert( u.be.i>=0 && u.be.i<p->nCursor );
- assert( p->apCsr[u.be.i]!=0 );
- if( (u.be.pC = p->apCsr[u.be.i])->pCursor!=0 ){
-
- assert( u.be.pC->isTable==0 );
+#endif /* local variables moved into u.bc */
+
+ u.bc.alreadyExists = 0;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bc.pC = p->apCsr[pOp->p1];
+ assert( u.bc.pC!=0 );
+ if( ALWAYS(u.bc.pC->pCursor!=0) ){
+
+ assert( u.bc.pC->isTable==0 );
assert( pIn3->flags & MEM_Blob );
- u.be.pIdxKey = sqlite3VdbeRecordUnpack(u.be.pC->pKeyInfo, pIn3->n, pIn3->z,
- u.be.aTempRec, sizeof(u.be.aTempRec));
- if( u.be.pIdxKey==0 ){
+ u.bc.pIdxKey = sqlite3VdbeRecordUnpack(u.bc.pC->pKeyInfo, pIn3->n, pIn3->z,
+ u.bc.aTempRec, sizeof(u.bc.aTempRec));
+ if( u.bc.pIdxKey==0 ){
goto no_mem;
}
if( pOp->opcode==OP_Found ){
- u.be.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
- }
- rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, u.be.pIdxKey, 0, 0, &u.be.res);
- sqlite3VdbeDeleteUnpackedRecord(u.be.pIdxKey);
+ u.bc.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+ }
+ rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, u.bc.pIdxKey, 0, 0, &u.bc.res);
+ sqlite3VdbeDeleteUnpackedRecord(u.bc.pIdxKey);
if( rc!=SQLITE_OK ){
break;
}
- u.be.alreadyExists = (u.be.res==0);
- u.be.pC->deferredMoveto = 0;
- u.be.pC->cacheStatus = CACHE_STALE;
+ u.bc.alreadyExists = (u.bc.res==0);
+ u.bc.pC->deferredMoveto = 0;
+ u.bc.pC->cacheStatus = CACHE_STALE;
}
if( pOp->opcode==OP_Found ){
- if( u.be.alreadyExists ) pc = pOp->p2 - 1;
- }else{
- if( !u.be.alreadyExists ) pc = pOp->p2 - 1;
+ if( u.bc.alreadyExists ) pc = pOp->p2 - 1;
+ }else{
+ if( !u.bc.alreadyExists ) pc = pOp->p2 - 1;
}
break;
}
@@ -54335,61 +54251,61 @@
**
** See also: NotFound, NotExists, Found
*/
case OP_IsUnique: { /* jump, in3 */
-#if 0 /* local variables moved into u.bf */
+#if 0 /* local variables moved into u.bd */
u16 ii;
VdbeCursor *pCx;
BtCursor *pCrsr;
u16 nField;
Mem *aMem;
UnpackedRecord r; /* B-Tree index search key */
i64 R; /* Rowid stored in register P3 */
-#endif /* local variables moved into u.bf */
-
- u.bf.aMem = &p->aMem[pOp->p4.i];
+#endif /* local variables moved into u.bd */
+
+ u.bd.aMem = &p->aMem[pOp->p4.i];
/* Assert that the values of parameters P1 and P4 are in range. */
assert( pOp->p4type==P4_INT32 );
assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
/* Find the index cursor. */
- u.bf.pCx = p->apCsr[pOp->p1];
- assert( u.bf.pCx->deferredMoveto==0 );
- u.bf.pCx->seekResult = 0;
- u.bf.pCx->cacheStatus = CACHE_STALE;
- u.bf.pCrsr = u.bf.pCx->pCursor;
+ u.bd.pCx = p->apCsr[pOp->p1];
+ assert( u.bd.pCx->deferredMoveto==0 );
+ u.bd.pCx->seekResult = 0;
+ u.bd.pCx->cacheStatus = CACHE_STALE;
+ u.bd.pCrsr = u.bd.pCx->pCursor;
/* If any of the values are NULL, take the jump. */
- u.bf.nField = u.bf.pCx->pKeyInfo->nField;
- for(u.bf.ii=0; u.bf.ii<u.bf.nField; u.bf.ii++){
- if( u.bf.aMem[u.bf.ii].flags & MEM_Null ){
+ u.bd.nField = u.bd.pCx->pKeyInfo->nField;
+ for(u.bd.ii=0; u.bd.ii<u.bd.nField; u.bd.ii++){
+ if( u.bd.aMem[u.bd.ii].flags & MEM_Null ){
pc = pOp->p2 - 1;
- u.bf.pCrsr = 0;
- break;
- }
- }
- assert( (u.bf.aMem[u.bf.nField].flags & MEM_Null)==0 );
-
- if( u.bf.pCrsr!=0 ){
+ u.bd.pCrsr = 0;
+ break;
+ }
+ }
+ assert( (u.bd.aMem[u.bd.nField].flags & MEM_Null)==0 );
+
+ if( u.bd.pCrsr!=0 ){
/* Populate the index search key. */
- u.bf.r.pKeyInfo = u.bf.pCx->pKeyInfo;
- u.bf.r.nField = u.bf.nField + 1;
- u.bf.r.flags = UNPACKED_PREFIX_SEARCH;
- u.bf.r.aMem = u.bf.aMem;
-
- /* Extract the value of u.bf.R from register P3. */
+ u.bd.r.pKeyInfo = u.bd.pCx->pKeyInfo;
+ u.bd.r.nField = u.bd.nField + 1;
+ u.bd.r.flags = UNPACKED_PREFIX_SEARCH;
+ u.bd.r.aMem = u.bd.aMem;
+
+ /* Extract the value of u.bd.R from register P3. */
sqlite3VdbeMemIntegerify(pIn3);
- u.bf.R = pIn3->u.i;
+ u.bd.R = pIn3->u.i;
/* Search the B-Tree index. If no conflicting record is found, jump
** to P2. Otherwise, copy the rowid of the conflicting record to
** register P3 and fall through to the next instruction. */
- rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, &u.bf.r, 0, 0, &u.bf.pCx->seekResult);
- if( (u.bf.r.flags & UNPACKED_PREFIX_SEARCH) || u.bf.r.rowid==u.bf.R ){
+ rc = sqlite3BtreeMovetoUnpacked(u.bd.pCrsr, &u.bd.r, 0, 0, &u.bd.pCx->seekResult);
+ if( (u.bd.r.flags & UNPACKED_PREFIX_SEARCH) || u.bd.r.rowid==u.bd.R ){
pc = pOp->p2 - 1;
}else{
- pIn3->u.i = u.bf.r.rowid;
+ pIn3->u.i = u.bd.r.rowid;
}
}
break;
}
@@ -54408,43 +54324,44 @@
**
** See also: Found, NotFound, IsUnique
*/
case OP_NotExists: { /* jump, in3 */
-#if 0 /* local variables moved into u.bg */
- int i;
+#if 0 /* local variables moved into u.be */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
u64 iKey;
-#endif /* local variables moved into u.bg */
-
- u.bg.i = pOp->p1;
- assert( u.bg.i>=0 && u.bg.i<p->nCursor );
- assert( p->apCsr[u.bg.i]!=0 );
- if( (u.bg.pCrsr = (u.bg.pC = p->apCsr[u.bg.i])->pCursor)!=0 ){
- u.bg.res = 0;
- assert( pIn3->flags & MEM_Int );
- assert( p->apCsr[u.bg.i]->isTable );
- u.bg.iKey = intToKey(pIn3->u.i);
- rc = sqlite3BtreeMovetoUnpacked(u.bg.pCrsr, 0, u.bg.iKey, 0, &u.bg.res);
- u.bg.pC->lastRowid = pIn3->u.i;
- u.bg.pC->rowidIsValid = u.bg.res==0 ?1:0;
- u.bg.pC->nullRow = 0;
- u.bg.pC->cacheStatus = CACHE_STALE;
- u.bg.pC->deferredMoveto = 0;
- if( u.bg.res!=0 ){
+#endif /* local variables moved into u.be */
+
+ assert( pIn3->flags & MEM_Int );
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.be.pC = p->apCsr[pOp->p1];
+ assert( u.be.pC!=0 );
+ assert( u.be.pC->isTable );
+ u.be.pCrsr = u.be.pC->pCursor;
+ if( u.be.pCrsr!=0 ){
+ u.be.res = 0;
+ u.be.iKey = pIn3->u.i;
+ rc = sqlite3BtreeMovetoUnpacked(u.be.pCrsr, 0, u.be.iKey, 0, &u.be.res);
+ u.be.pC->lastRowid = pIn3->u.i;
+ u.be.pC->rowidIsValid = u.be.res==0 ?1:0;
+ u.be.pC->nullRow = 0;
+ u.be.pC->cacheStatus = CACHE_STALE;
+ u.be.pC->deferredMoveto = 0;
+ if( u.be.res!=0 ){
pc = pOp->p2 - 1;
- assert( u.bg.pC->rowidIsValid==0 );
- }
- u.bg.pC->seekResult = u.bg.res;
- }else if( !u.bg.pC->pseudoTable ){
+ assert( u.be.pC->rowidIsValid==0 );
+ }
+ u.be.pC->seekResult = u.be.res;
+ }else{
/* This happens when an attempt to open a read cursor on the
** sqlite_master table returns SQLITE_EMPTY.
*/
- assert( u.bg.pC->isTable );
+ assert( !u.be.pC->pseudoTable );
+ assert( u.be.pC->isTable );
pc = pOp->p2 - 1;
- assert( u.bg.pC->rowidIsValid==0 );
- u.bg.pC->seekResult = 0;
+ assert( u.be.pC->rowidIsValid==0 );
+ u.be.pC->seekResult = 0;
}
break;
}
@@ -54455,12 +54372,11 @@
** The sequence number on the cursor is incremented after this
** instruction.
*/
case OP_Sequence: { /* out2-prerelease */
- int i = pOp->p1;
- assert( i>=0 && i<p->nCursor );
- assert( p->apCsr[i]!=0 );
- pOut->u.i = p->apCsr[i]->seqCount++;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( p->apCsr[pOp->p1]!=0 );
+ pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -54479,26 +54395,22 @@
** record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
case OP_NewRowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bh */
- int i;
- i64 v;
- VdbeCursor *pC;
- int res;
- int rx;
- int cnt;
- i64 x;
- Mem *pMem;
-#endif /* local variables moved into u.bh */
-
- u.bh.i = pOp->p1;
- u.bh.v = 0;
- u.bh.res = 0;
- u.bh.rx = SQLITE_OK;
- assert( u.bh.i>=0 && u.bh.i<p->nCursor );
- assert( p->apCsr[u.bh.i]!=0 );
- if( (u.bh.pC = p->apCsr[u.bh.i])->pCursor==0 ){
+#if 0 /* local variables moved into u.bf */
+ i64 v; /* The new rowid */
+ VdbeCursor *pC; /* Cursor of table to get the new rowid */
+ int res; /* Result of an sqlite3BtreeLast() */
+ int cnt; /* Counter to limit the number of searches */
+ Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
+#endif /* local variables moved into u.bf */
+
+ u.bf.v = 0;
+ u.bf.res = 0;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bf.pC = p->apCsr[pOp->p1];
+ assert( u.bf.pC!=0 );
+ if( NEVER(u.bf.pC->pCursor==0) ){
/* The zero initialization above is all that is needed */
}else{
/* The next rowid or record number (different terms for the same
** thing) is obtained in a two-step algorithm.
@@ -54510,36 +54422,12 @@
**
** The second algorithm is to select a rowid at random and see if
** it already exists in the table. If it does not exist, we have
** succeeded. If the random rowid does exist, we select a new one
- ** and try again, up to 1000 times.
- **
- ** For a table with less than 2 billion entries, the probability
- ** of not finding a unused rowid is about 1.0e-300. This is a
- ** non-zero probability, but it is still vanishingly small and should
- ** never cause a problem. You are much, much more likely to have a
- ** hardware failure than for this algorithm to fail.
- **
- ** The analysis in the previous paragraph assumes that you have a good
- ** source of random numbers. Is a library function like lrand48()
- ** good enough? Maybe. Maybe not. It's hard to know whether there
- ** might be subtle bugs is some implementations of lrand48() that
- ** could cause problems. To avoid uncertainty, SQLite uses its own
- ** random number generator based on the RC4 algorithm.
- **
- ** To promote locality of reference for repetitive inserts, the
- ** first few attempts at choosing a random rowid pick values just a little
- ** larger than the previous rowid. This has been shown experimentally
- ** to double the speed of the COPY operation.
- */
- u.bh.cnt = 0;
- if( (sqlite3BtreeFlags(u.bh.pC->pCursor)&(BTREE_INTKEY|BTREE_ZERODATA)) !=
- BTREE_INTKEY ){
- rc = SQLITE_CORRUPT_BKPT;
- goto abort_due_to_error;
- }
- assert( (sqlite3BtreeFlags(u.bh.pC->pCursor) & BTREE_INTKEY)!=0 );
- assert( (sqlite3BtreeFlags(u.bh.pC->pCursor) & BTREE_ZERODATA)==0 );
+ ** and try again, up to 100 times.
+ */
+ assert( u.bf.pC->isTable );
+ u.bf.cnt = 0;
#ifdef SQLITE_32BIT_ROWID
# define MAX_ROWID 0x7fffffff
#else
@@ -54549,76 +54437,74 @@
*/
# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
#endif
- if( !u.bh.pC->useRandomRowid ){
- u.bh.v = sqlite3BtreeGetCachedRowid(u.bh.pC->pCursor);
- if( u.bh.v==0 ){
- rc = sqlite3BtreeLast(u.bh.pC->pCursor, &u.bh.res);
+ if( !u.bf.pC->useRandomRowid ){
+ u.bf.v = sqlite3BtreeGetCachedRowid(u.bf.pC->pCursor);
+ if( u.bf.v==0 ){
+ rc = sqlite3BtreeLast(u.bf.pC->pCursor, &u.bf.res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- if( u.bh.res ){
- u.bh.v = 1;
- }else{
- sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v);
- u.bh.v = keyToInt(u.bh.v);
- if( u.bh.v==MAX_ROWID ){
- u.bh.pC->useRandomRowid = 1;
+ if( u.bf.res ){
+ u.bf.v = 1;
+ }else{
+ sqlite3BtreeKeySize(u.bf.pC->pCursor, &u.bf.v);
+ if( u.bf.v==MAX_ROWID ){
+ u.bf.pC->useRandomRowid = 1;
}else{
- u.bh.v++;
+ u.bf.v++;
}
}
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( pOp->p3 ){
assert( pOp->p3>0 && pOp->p3<=p->nMem ); /* P3 is a valid memory cell */
- u.bh.pMem = &p->aMem[pOp->p3];
- REGISTER_TRACE(pOp->p3, u.bh.pMem);
- sqlite3VdbeMemIntegerify(u.bh.pMem);
- assert( (u.bh.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
- if( u.bh.pMem->u.i==MAX_ROWID || u.bh.pC->useRandomRowid ){
+ u.bf.pMem = &p->aMem[pOp->p3];
+ REGISTER_TRACE(pOp->p3, u.bf.pMem);
+ sqlite3VdbeMemIntegerify(u.bf.pMem);
+ assert( (u.bf.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
+ if( u.bf.pMem->u.i==MAX_ROWID || u.bf.pC->useRandomRowid ){
rc = SQLITE_FULL;
goto abort_due_to_error;
}
- if( u.bh.v<u.bh.pMem->u.i+1 ){
- u.bh.v = u.bh.pMem->u.i + 1;
- }
- u.bh.pMem->u.i = u.bh.v;
- }
-#endif
-
- sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, u.bh.v<MAX_ROWID ? u.bh.v+1 : 0);
- }
- if( u.bh.pC->useRandomRowid ){
- assert( pOp->p3==0 ); /* SQLITE_FULL must have occurred prior to this */
- u.bh.v = db->priorNewRowid;
- u.bh.cnt = 0;
+ if( u.bf.v<u.bf.pMem->u.i+1 ){
+ u.bf.v = u.bf.pMem->u.i + 1;
+ }
+ u.bf.pMem->u.i = u.bf.v;
+ }
+#endif
+
+ sqlite3BtreeSetCachedRowid(u.bf.pC->pCursor, u.bf.v<MAX_ROWID ? u.bf.v+1 : 0);
+ }
+ if( u.bf.pC->useRandomRowid ){
+ assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
+ ** an AUTOINCREMENT table. */
+ u.bf.v = db->priorNewRowid;
+ u.bf.cnt = 0;
do{
- if( u.bh.cnt==0 && (u.bh.v&0xffffff)==u.bh.v ){
- u.bh.v++;
- }else{
- sqlite3_randomness(sizeof(u.bh.v), &u.bh.v);
- if( u.bh.cnt<5 ) u.bh.v &= 0xffffff;
- }
- if( u.bh.v==0 ) continue;
- u.bh.x = intToKey(u.bh.v);
- u.bh.rx = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.x, 0, &u.bh.res);
- u.bh.cnt++;
- }while( u.bh.cnt<100 && u.bh.rx==SQLITE_OK && u.bh.res==0 );
- db->priorNewRowid = u.bh.v;
- if( u.bh.rx==SQLITE_OK && u.bh.res==0 ){
+ if( u.bf.cnt==0 && (u.bf.v&0xffffff)==u.bf.v ){
+ u.bf.v++;
+ }else{
+ sqlite3_randomness(sizeof(u.bf.v), &u.bf.v);
+ if( u.bf.cnt<5 ) u.bf.v &= 0xffffff;
+ }
+ rc = sqlite3BtreeMovetoUnpacked(u.bf.pC->pCursor, 0, (u64)u.bf.v, 0, &u.bf.res);
+ u.bf.cnt++;
+ }while( u.bf.cnt<100 && rc==SQLITE_OK && u.bf.res==0 );
+ db->priorNewRowid = u.bf.v;
+ if( rc==SQLITE_OK && u.bf.res==0 ){
rc = SQLITE_FULL;
goto abort_due_to_error;
}
}
- u.bh.pC->rowidIsValid = 0;
- u.bh.pC->deferredMoveto = 0;
- u.bh.pC->cacheStatus = CACHE_STALE;
+ u.bf.pC->rowidIsValid = 0;
+ u.bf.pC->deferredMoveto = 0;
+ u.bf.pC->cacheStatus = CACHE_STALE;
}
MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = u.bh.v;
+ pOut->u.i = u.bf.v;
break;
}
/* Opcode: Insert P1 P2 P3 P4 P5
@@ -54647,89 +54533,87 @@
** This instruction only works on tables. The equivalent instruction
** for indices is OP_IdxInsert.
*/
case OP_Insert: {
-#if 0 /* local variables moved into u.bi */
+#if 0 /* local variables moved into u.bg */
Mem *pData;
Mem *pKey;
i64 iKey; /* The integer ROWID or key for the record to be inserted */
- int i;
VdbeCursor *pC;
int nZero;
int seekResult;
const char *zDb;
const char *zTbl;
int op;
-#endif /* local variables moved into u.bi */
-
- u.bi.pData = &p->aMem[pOp->p2];
- u.bi.pKey = &p->aMem[pOp->p3];
- u.bi.i = pOp->p1;
- assert( u.bi.i>=0 && u.bi.i<p->nCursor );
- u.bi.pC = p->apCsr[u.bi.i];
- assert( u.bi.pC!=0 );
- assert( u.bi.pC->pCursor!=0 || u.bi.pC->pseudoTable );
- assert( u.bi.pKey->flags & MEM_Int );
- assert( u.bi.pC->isTable );
- REGISTER_TRACE(pOp->p2, u.bi.pData);
- REGISTER_TRACE(pOp->p3, u.bi.pKey);
-
- u.bi.iKey = intToKey(u.bi.pKey->u.i);
+#endif /* local variables moved into u.bg */
+
+ u.bg.pData = &p->aMem[pOp->p2];
+ u.bg.pKey = &p->aMem[pOp->p3];
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bg.pC = p->apCsr[pOp->p1];
+ assert( u.bg.pC!=0 );
+ assert( u.bg.pC->pCursor!=0 || u.bg.pC->pseudoTable );
+ assert( u.bg.pKey->flags & MEM_Int );
+ assert( u.bg.pC->isTable );
+ REGISTER_TRACE(pOp->p2, u.bg.pData);
+ REGISTER_TRACE(pOp->p3, u.bg.pKey);
+
+ u.bg.iKey = u.bg.pKey->u.i;
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = u.bi.pKey->u.i;
- if( u.bi.pData->flags & MEM_Null ){
- u.bi.pData->z = 0;
- u.bi.pData->n = 0;
- }else{
- assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) );
- }
- if( u.bi.pC->pseudoTable ){
- if( !u.bi.pC->ephemPseudoTable ){
- sqlite3DbFree(db, u.bi.pC->pData);
- }
- u.bi.pC->iKey = u.bi.iKey;
- u.bi.pC->nData = u.bi.pData->n;
- if( u.bi.pData->z==u.bi.pData->zMalloc || u.bi.pC->ephemPseudoTable ){
- u.bi.pC->pData = u.bi.pData->z;
- if( !u.bi.pC->ephemPseudoTable ){
- u.bi.pData->flags &= ~MEM_Dyn;
- u.bi.pData->flags |= MEM_Ephem;
- u.bi.pData->zMalloc = 0;
- }
- }else{
- u.bi.pC->pData = sqlite3Malloc( u.bi.pC->nData+2 );
- if( !u.bi.pC->pData ) goto no_mem;
- memcpy(u.bi.pC->pData, u.bi.pData->z, u.bi.pC->nData);
- u.bi.pC->pData[u.bi.pC->nData] = 0;
- u.bi.pC->pData[u.bi.pC->nData+1] = 0;
- }
- u.bi.pC->nullRow = 0;
- }else{
- u.bi.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bi.pC->seekResult : 0);
- if( u.bi.pData->flags & MEM_Zero ){
- u.bi.nZero = u.bi.pData->u.nZero;
- }else{
- u.bi.nZero = 0;
- }
- sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
- rc = sqlite3BtreeInsert(u.bi.pC->pCursor, 0, u.bi.iKey,
- u.bi.pData->z, u.bi.pData->n, u.bi.nZero,
- pOp->p5 & OPFLAG_APPEND, u.bi.seekResult
- );
- }
-
- u.bi.pC->rowidIsValid = 0;
- u.bi.pC->deferredMoveto = 0;
- u.bi.pC->cacheStatus = CACHE_STALE;
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = u.bg.pKey->u.i;
+ if( u.bg.pData->flags & MEM_Null ){
+ u.bg.pData->z = 0;
+ u.bg.pData->n = 0;
+ }else{
+ assert( u.bg.pData->flags & (MEM_Blob|MEM_Str) );
+ }
+ if( u.bg.pC->pseudoTable ){
+ if( !u.bg.pC->ephemPseudoTable ){
+ sqlite3DbFree(db, u.bg.pC->pData);
+ }
+ u.bg.pC->iKey = u.bg.iKey;
+ u.bg.pC->nData = u.bg.pData->n;
+ if( u.bg.pC->ephemPseudoTable || u.bg.pData->z==u.bg.pData->zMalloc ){
+ u.bg.pC->pData = u.bg.pData->z;
+ if( !u.bg.pC->ephemPseudoTable ){
+ u.bg.pData->flags &= ~MEM_Dyn;
+ u.bg.pData->flags |= MEM_Ephem;
+ u.bg.pData->zMalloc = 0;
+ }
+ }else{
+ u.bg.pC->pData = sqlite3Malloc( u.bg.pC->nData+2 );
+ if( !u.bg.pC->pData ) goto no_mem;
+ memcpy(u.bg.pC->pData, u.bg.pData->z, u.bg.pC->nData);
+ u.bg.pC->pData[u.bg.pC->nData] = 0;
+ u.bg.pC->pData[u.bg.pC->nData+1] = 0;
+ }
+ u.bg.pC->nullRow = 0;
+ }else{
+ u.bg.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bg.pC->seekResult : 0);
+ if( u.bg.pData->flags & MEM_Zero ){
+ u.bg.nZero = u.bg.pData->u.nZero;
+ }else{
+ u.bg.nZero = 0;
+ }
+ sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, 0);
+ rc = sqlite3BtreeInsert(u.bg.pC->pCursor, 0, u.bg.iKey,
+ u.bg.pData->z, u.bg.pData->n, u.bg.nZero,
+ pOp->p5 & OPFLAG_APPEND, u.bg.seekResult
+ );
+ }
+
+ u.bg.pC->rowidIsValid = 0;
+ u.bg.pC->deferredMoveto = 0;
+ u.bg.pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
- u.bi.zDb = db->aDb[u.bi.pC->iDb].zName;
- u.bi.zTbl = pOp->p4.z;
- u.bi.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
- assert( u.bi.pC->isTable );
- db->xUpdateCallback(db->pUpdateArg, u.bi.op, u.bi.zDb, u.bi.zTbl, u.bi.iKey);
- assert( u.bi.pC->iDb>=0 );
+ u.bg.zDb = db->aDb[u.bg.pC->iDb].zName;
+ u.bg.zTbl = pOp->p4.z;
+ u.bg.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
+ assert( u.bg.pC->isTable );
+ db->xUpdateCallback(db->pUpdateArg, u.bg.op, u.bg.zDb, u.bg.zTbl, u.bg.iKey);
+ assert( u.bg.pC->iDb>=0 );
}
break;
}
@@ -54753,42 +54637,49 @@
** If P4 is not NULL then the P1 cursor must have been positioned
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
-#if 0 /* local variables moved into u.bj */
- int i;
+#if 0 /* local variables moved into u.bh */
i64 iKey;
VdbeCursor *pC;
-#endif /* local variables moved into u.bj */
-
- u.bj.i = pOp->p1;
- u.bj.iKey = 0;
- assert( u.bj.i>=0 && u.bj.i<p->nCursor );
- u.bj.pC = p->apCsr[u.bj.i];
- assert( u.bj.pC!=0 );
- assert( u.bj.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
-
- /* If the update-hook will be invoked, set u.bj.iKey to the rowid of the
+#endif /* local variables moved into u.bh */
+
+ u.bh.iKey = 0;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bh.pC = p->apCsr[pOp->p1];
+ assert( u.bh.pC!=0 );
+ assert( u.bh.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
+
+ /* If the update-hook will be invoked, set u.bh.iKey to the rowid of the
** row being deleted.
*/
if( db->xUpdateCallback && pOp->p4.z ){
- assert( u.bj.pC->isTable );
- assert( u.bj.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
- u.bj.iKey = u.bj.pC->lastRowid;
- }
-
- rc = sqlite3VdbeCursorMoveto(u.bj.pC);
- if( rc ) goto abort_due_to_error;
- sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0);
- rc = sqlite3BtreeDelete(u.bj.pC->pCursor);
- u.bj.pC->cacheStatus = CACHE_STALE;
+ assert( u.bh.pC->isTable );
+ assert( u.bh.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
+ u.bh.iKey = u.bh.pC->lastRowid;
+ }
+
+ /* The OP_Delete opcode always follows an OP_NotExists or OP_Last or
+ ** OP_Column on the same table without any intervening operations that
+ ** might move or invalidate the cursor. Hence cursor u.bh.pC is always pointing
+ ** to the row to be deleted and the sqlite3VdbeCursorMoveto() operation
+ ** below is always a no-op and cannot fail. We will run it anyhow, though,
+ ** to guard against future changes to the code generator.
+ **/
+ assert( u.bh.pC->deferredMoveto==0 );
+ rc = sqlite3VdbeCursorMoveto(u.bh.pC);
+ if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
+
+ sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, 0);
+ rc = sqlite3BtreeDelete(u.bh.pC->pCursor);
+ u.bh.pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
- const char *zDb = db->aDb[u.bj.pC->iDb].zName;
+ const char *zDb = db->aDb[u.bh.pC->iDb].zName;
const char *zTbl = pOp->p4.z;
- db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bj.iKey);
- assert( u.bj.pC->iDb>=0 );
+ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bh.iKey);
+ assert( u.bh.pC->iDb>=0 );
}
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
break;
}
@@ -54829,53 +54720,59 @@
** of a real table, not a pseudo-table.
*/
case OP_RowKey:
case OP_RowData: {
-#if 0 /* local variables moved into u.bk */
- int i;
+#if 0 /* local variables moved into u.bi */
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
i64 n64;
-#endif /* local variables moved into u.bk */
-
- u.bk.i = pOp->p1;
+#endif /* local variables moved into u.bi */
+
pOut = &p->aMem[pOp->p2];
/* Note that RowKey and RowData are really exactly the same instruction */
- assert( u.bk.i>=0 && u.bk.i<p->nCursor );
- u.bk.pC = p->apCsr[u.bk.i];
- assert( u.bk.pC->isTable || pOp->opcode==OP_RowKey );
- assert( u.bk.pC->isIndex || pOp->opcode==OP_RowData );
- assert( u.bk.pC!=0 );
- assert( u.bk.pC->nullRow==0 );
- assert( u.bk.pC->pseudoTable==0 );
- assert( u.bk.pC->pCursor!=0 );
- u.bk.pCrsr = u.bk.pC->pCursor;
- rc = sqlite3VdbeCursorMoveto(u.bk.pC);
- if( rc ) goto abort_due_to_error;
- if( u.bk.pC->isIndex ){
- assert( !u.bk.pC->isTable );
- sqlite3BtreeKeySize(u.bk.pCrsr, &u.bk.n64);
- if( u.bk.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bi.pC = p->apCsr[pOp->p1];
+ assert( u.bi.pC->isTable || pOp->opcode==OP_RowKey );
+ assert( u.bi.pC->isIndex || pOp->opcode==OP_RowData );
+ assert( u.bi.pC!=0 );
+ assert( u.bi.pC->nullRow==0 );
+ assert( u.bi.pC->pseudoTable==0 );
+ assert( u.bi.pC->pCursor!=0 );
+ u.bi.pCrsr = u.bi.pC->pCursor;
+
+ /* The OP_RowKey and OP_RowData opcodes always follow OP_NotExists or
+ ** OP_Rewind/Op_Next with no intervening instructions that might invalidate
+ ** the cursor. Hence the following sqlite3VdbeCursorMoveto() call is always
+ ** a no-op and can never fail. But we leave it in place as a safety.
+ */
+ assert( u.bi.pC->deferredMoveto==0 );
+ rc = sqlite3VdbeCursorMoveto(u.bi.pC);
+ if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
+
+ if( u.bi.pC->isIndex ){
+ assert( !u.bi.pC->isTable );
+ sqlite3BtreeKeySize(u.bi.pCrsr, &u.bi.n64);
+ if( u.bi.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- u.bk.n = (u32)u.bk.n64;
- }else{
- sqlite3BtreeDataSize(u.bk.pCrsr, &u.bk.n);
- if( u.bk.n>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ u.bi.n = (u32)u.bi.n64;
+ }else{
+ sqlite3BtreeDataSize(u.bi.pCrsr, &u.bi.n);
+ if( u.bi.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
}
- if( sqlite3VdbeMemGrow(pOut, u.bk.n, 0) ){
+ if( sqlite3VdbeMemGrow(pOut, u.bi.n, 0) ){
goto no_mem;
}
- pOut->n = u.bk.n;
+ pOut->n = u.bi.n;
MemSetTypeFlag(pOut, MEM_Blob);
- if( u.bk.pC->isIndex ){
- rc = sqlite3BtreeKey(u.bk.pCrsr, 0, u.bk.n, pOut->z);
- }else{
- rc = sqlite3BtreeData(u.bk.pCrsr, 0, u.bk.n, pOut->z);
+ if( u.bi.pC->isIndex ){
+ rc = sqlite3BtreeKey(u.bi.pCrsr, 0, u.bi.n, pOut->z);
+ }else{
+ rc = sqlite3BtreeData(u.bi.pCrsr, 0, u.bi.n, pOut->z);
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -54890,51 +54787,48 @@
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
case OP_Rowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bl */
- int i;
+#if 0 /* local variables moved into u.bj */
VdbeCursor *pC;
i64 v;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
-#endif /* local variables moved into u.bl */
-
- u.bl.i = pOp->p1;
- assert( u.bl.i>=0 && u.bl.i<p->nCursor );
- u.bl.pC = p->apCsr[u.bl.i];
- assert( u.bl.pC!=0 );
- if( u.bl.pC->nullRow ){
+#endif /* local variables moved into u.bj */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bj.pC = p->apCsr[pOp->p1];
+ assert( u.bj.pC!=0 );
+ if( u.bj.pC->nullRow ){
/* Do nothing so that reg[P2] remains NULL */
break;
- }else if( u.bl.pC->deferredMoveto ){
- u.bl.v = u.bl.pC->movetoTarget;
- }else if( u.bl.pC->pseudoTable ){
- u.bl.v = keyToInt(u.bl.pC->iKey);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- }else if( u.bl.pC->pVtabCursor ){
- u.bl.pVtab = u.bl.pC->pVtabCursor->pVtab;
- u.bl.pModule = u.bl.pVtab->pModule;
- assert( u.bl.pModule->xRowid );
+ }else if( u.bj.pC->deferredMoveto ){
+ u.bj.v = u.bj.pC->movetoTarget;
+ }else if( u.bj.pC->pseudoTable ){
+ u.bj.v = u.bj.pC->iKey;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ }else if( u.bj.pC->pVtabCursor ){
+ u.bj.pVtab = u.bj.pC->pVtabCursor->pVtab;
+ u.bj.pModule = u.bj.pVtab->pModule;
+ assert( u.bj.pModule->xRowid );
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- rc = u.bl.pModule->xRowid(u.bl.pC->pVtabCursor, &u.bl.v);
+ rc = u.bj.pModule->xRowid(u.bj.pC->pVtabCursor, &u.bj.v);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.bl.pVtab->zErrMsg;
- u.bl.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.bj.pVtab->zErrMsg;
+ u.bj.pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
- rc = sqlite3VdbeCursorMoveto(u.bl.pC);
+ rc = sqlite3VdbeCursorMoveto(u.bj.pC);
if( rc ) goto abort_due_to_error;
- if( u.bl.pC->rowidIsValid ){
- u.bl.v = u.bl.pC->lastRowid;
- }else{
- assert( u.bl.pC->pCursor!=0 );
- sqlite3BtreeKeySize(u.bl.pC->pCursor, &u.bl.v);
- u.bl.v = keyToInt(u.bl.v);
- }
- }
- pOut->u.i = u.bl.v;
+ if( u.bj.pC->rowidIsValid ){
+ u.bj.v = u.bj.pC->lastRowid;
+ }else{
+ assert( u.bj.pC->pCursor!=0 );
+ sqlite3BtreeKeySize(u.bj.pC->pCursor, &u.bj.v);
+ }
+ }
+ pOut->u.i = u.bj.v;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -54944,21 +54838,19 @@
** that occur while the cursor is on the null row will always
** write a NULL.
*/
case OP_NullRow: {
-#if 0 /* local variables moved into u.bm */
- int i;
+#if 0 /* local variables moved into u.bk */
VdbeCursor *pC;
-#endif /* local variables moved into u.bm */
-
- u.bm.i = pOp->p1;
- assert( u.bm.i>=0 && u.bm.i<p->nCursor );
- u.bm.pC = p->apCsr[u.bm.i];
- assert( u.bm.pC!=0 );
- u.bm.pC->nullRow = 1;
- u.bm.pC->rowidIsValid = 0;
- if( u.bm.pC->pCursor ){
- sqlite3BtreeClearCursor(u.bm.pC->pCursor);
+#endif /* local variables moved into u.bk */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bk.pC = p->apCsr[pOp->p1];
+ assert( u.bk.pC!=0 );
+ u.bk.pC->nullRow = 1;
+ u.bk.pC->rowidIsValid = 0;
+ if( u.bk.pC->pCursor ){
+ sqlite3BtreeClearCursor(u.bk.pC->pCursor);
}
break;
}
@@ -54970,27 +54862,28 @@
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: { /* jump */
-#if 0 /* local variables moved into u.bn */
- int i;
+#if 0 /* local variables moved into u.bl */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
-#endif /* local variables moved into u.bn */
-
- u.bn.i = pOp->p1;
- assert( u.bn.i>=0 && u.bn.i<p->nCursor );
- u.bn.pC = p->apCsr[u.bn.i];
- assert( u.bn.pC!=0 );
- u.bn.pCrsr = u.bn.pC->pCursor;
- assert( u.bn.pCrsr!=0 );
- rc = sqlite3BtreeLast(u.bn.pCrsr, &u.bn.res);
- u.bn.pC->nullRow = (u8)u.bn.res;
- u.bn.pC->deferredMoveto = 0;
- u.bn.pC->rowidIsValid = 0;
- u.bn.pC->cacheStatus = CACHE_STALE;
- if( u.bn.res && pOp->p2>0 ){
+#endif /* local variables moved into u.bl */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bl.pC = p->apCsr[pOp->p1];
+ assert( u.bl.pC!=0 );
+ u.bl.pCrsr = u.bl.pC->pCursor;
+ if( u.bl.pCrsr==0 ){
+ u.bl.res = 1;
+ }else{
+ rc = sqlite3BtreeLast(u.bl.pCrsr, &u.bl.res);
+ }
+ u.bl.pC->nullRow = (u8)u.bl.res;
+ u.bl.pC->deferredMoveto = 0;
+ u.bl.pC->rowidIsValid = 0;
+ u.bl.pC->cacheStatus = CACHE_STALE;
+ if( pOp->p2>0 && u.bl.res ){
pc = pOp->p2 - 1;
}
break;
}
@@ -55024,31 +54917,29 @@
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Rewind: { /* jump */
-#if 0 /* local variables moved into u.bo */
- int i;
+#if 0 /* local variables moved into u.bm */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
-#endif /* local variables moved into u.bo */
-
- u.bo.i = pOp->p1;
- assert( u.bo.i>=0 && u.bo.i<p->nCursor );
- u.bo.pC = p->apCsr[u.bo.i];
- assert( u.bo.pC!=0 );
- if( (u.bo.pCrsr = u.bo.pC->pCursor)!=0 ){
- rc = sqlite3BtreeFirst(u.bo.pCrsr, &u.bo.res);
- u.bo.pC->atFirst = u.bo.res==0 ?1:0;
- u.bo.pC->deferredMoveto = 0;
- u.bo.pC->cacheStatus = CACHE_STALE;
- u.bo.pC->rowidIsValid = 0;
- }else{
- u.bo.res = 1;
- }
- u.bo.pC->nullRow = (u8)u.bo.res;
+#endif /* local variables moved into u.bm */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bm.pC = p->apCsr[pOp->p1];
+ assert( u.bm.pC!=0 );
+ if( (u.bm.pCrsr = u.bm.pC->pCursor)!=0 ){
+ rc = sqlite3BtreeFirst(u.bm.pCrsr, &u.bm.res);
+ u.bm.pC->atFirst = u.bm.res==0 ?1:0;
+ u.bm.pC->deferredMoveto = 0;
+ u.bm.pC->cacheStatus = CACHE_STALE;
+ u.bm.pC->rowidIsValid = 0;
+ }else{
+ u.bm.res = 1;
+ }
+ u.bm.pC->nullRow = (u8)u.bm.res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
- if( u.bo.res ){
+ if( u.bm.res ){
pc = pOp->p2 - 1;
}
break;
}
@@ -55074,36 +54965,39 @@
** The P1 cursor must be for a real table, not a pseudo-table.
*/
case OP_Prev: /* jump */
case OP_Next: { /* jump */
-#if 0 /* local variables moved into u.bp */
+#if 0 /* local variables moved into u.bn */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
-#endif /* local variables moved into u.bp */
+#endif /* local variables moved into u.bn */
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
- u.bp.pC = p->apCsr[pOp->p1];
- if( u.bp.pC==0 ){
+ u.bn.pC = p->apCsr[pOp->p1];
+ if( u.bn.pC==0 ){
break; /* See ticket #2273 */
}
- u.bp.pCrsr = u.bp.pC->pCursor;
- assert( u.bp.pCrsr );
- u.bp.res = 1;
- assert( u.bp.pC->deferredMoveto==0 );
- rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(u.bp.pCrsr, &u.bp.res) :
- sqlite3BtreePrevious(u.bp.pCrsr, &u.bp.res);
- u.bp.pC->nullRow = (u8)u.bp.res;
- u.bp.pC->cacheStatus = CACHE_STALE;
- if( u.bp.res==0 ){
+ u.bn.pCrsr = u.bn.pC->pCursor;
+ if( u.bn.pCrsr==0 ){
+ u.bn.pC->nullRow = 1;
+ break;
+ }
+ u.bn.res = 1;
+ assert( u.bn.pC->deferredMoveto==0 );
+ rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(u.bn.pCrsr, &u.bn.res) :
+ sqlite3BtreePrevious(u.bn.pCrsr, &u.bn.res);
+ u.bn.pC->nullRow = (u8)u.bn.res;
+ u.bn.pC->cacheStatus = CACHE_STALE;
+ if( u.bn.res==0 ){
pc = pOp->p2 - 1;
if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
}
- u.bp.pC->rowidIsValid = 0;
+ u.bn.pC->rowidIsValid = 0;
break;
}
/* Opcode: IdxInsert P1 P2 P3 * P5
@@ -55118,31 +55012,31 @@
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
case OP_IdxInsert: { /* in2 */
-#if 0 /* local variables moved into u.bq */
- int i;
+#if 0 /* local variables moved into u.bo */
VdbeCursor *pC;
BtCursor *pCrsr;
int nKey;
const char *zKey;
-#endif /* local variables moved into u.bq */
-
- u.bq.i = pOp->p1;
- assert( u.bq.i>=0 && u.bq.i<p->nCursor );
- assert( p->apCsr[u.bq.i]!=0 );
+#endif /* local variables moved into u.bo */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bo.pC = p->apCsr[pOp->p1];
+ assert( u.bo.pC!=0 );
assert( pIn2->flags & MEM_Blob );
- if( (u.bq.pCrsr = (u.bq.pC = p->apCsr[u.bq.i])->pCursor)!=0 ){
- assert( u.bq.pC->isTable==0 );
+ u.bo.pCrsr = u.bo.pC->pCursor;
+ if( ALWAYS(u.bo.pCrsr!=0) ){
+ assert( u.bo.pC->isTable==0 );
rc = ExpandBlob(pIn2);
if( rc==SQLITE_OK ){
- u.bq.nKey = pIn2->n;
- u.bq.zKey = pIn2->z;
- rc = sqlite3BtreeInsert(u.bq.pCrsr, u.bq.zKey, u.bq.nKey, "", 0, 0, pOp->p3,
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bq.pC->seekResult : 0)
- );
- assert( u.bq.pC->deferredMoveto==0 );
- u.bq.pC->cacheStatus = CACHE_STALE;
+ u.bo.nKey = pIn2->n;
+ u.bo.zKey = pIn2->z;
+ rc = sqlite3BtreeInsert(u.bo.pCrsr, u.bo.zKey, u.bo.nKey, "", 0, 0, pOp->p3,
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bo.pC->seekResult : 0)
+ );
+ assert( u.bo.pC->deferredMoveto==0 );
+ u.bo.pC->cacheStatus = CACHE_STALE;
}
}
break;
}
@@ -55153,32 +55047,32 @@
** an unpacked index key. This opcode removes that entry from the
** index opened by cursor P1.
*/
case OP_IdxDelete: {
-#if 0 /* local variables moved into u.br */
- int i;
+#if 0 /* local variables moved into u.bp */
VdbeCursor *pC;
BtCursor *pCrsr;
-#endif /* local variables moved into u.br */
-
- u.br.i = pOp->p1;
+ int res;
+ UnpackedRecord r;
+#endif /* local variables moved into u.bp */
+
assert( pOp->p3>0 );
assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
- assert( u.br.i>=0 && u.br.i<p->nCursor );
- assert( p->apCsr[u.br.i]!=0 );
- if( (u.br.pCrsr = (u.br.pC = p->apCsr[u.br.i])->pCursor)!=0 ){
- int res;
- UnpackedRecord r;
- r.pKeyInfo = u.br.pC->pKeyInfo;
- r.nField = (u16)pOp->p3;
- r.flags = 0;
- r.aMem = &p->aMem[pOp->p2];
- rc = sqlite3BtreeMovetoUnpacked(u.br.pCrsr, &r, 0, 0, &res);
- if( rc==SQLITE_OK && res==0 ){
- rc = sqlite3BtreeDelete(u.br.pCrsr);
- }
- assert( u.br.pC->deferredMoveto==0 );
- u.br.pC->cacheStatus = CACHE_STALE;
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bp.pC = p->apCsr[pOp->p1];
+ assert( u.bp.pC!=0 );
+ u.bp.pCrsr = u.bp.pC->pCursor;
+ if( ALWAYS(u.bp.pCrsr!=0) ){
+ u.bp.r.pKeyInfo = u.bp.pC->pKeyInfo;
+ u.bp.r.nField = (u16)pOp->p3;
+ u.bp.r.flags = 0;
+ u.bp.r.aMem = &p->aMem[pOp->p2];
+ rc = sqlite3BtreeMovetoUnpacked(u.bp.pCrsr, &u.bp.r, 0, 0, &u.bp.res);
+ if( rc==SQLITE_OK && u.bp.res==0 ){
+ rc = sqlite3BtreeDelete(u.bp.pCrsr);
+ }
+ assert( u.bp.pC->deferredMoveto==0 );
+ u.bp.pC->cacheStatus = CACHE_STALE;
}
break;
}
@@ -55190,30 +55084,30 @@
**
** See also: Rowid, MakeRecord.
*/
case OP_IdxRowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bs */
- int i;
+#if 0 /* local variables moved into u.bq */
BtCursor *pCrsr;
VdbeCursor *pC;
i64 rowid;
-#endif /* local variables moved into u.bs */
-
- u.bs.i = pOp->p1;
- assert( u.bs.i>=0 && u.bs.i<p->nCursor );
- assert( p->apCsr[u.bs.i]!=0 );
- if( (u.bs.pCrsr = (u.bs.pC = p->apCsr[u.bs.i])->pCursor)!=0 ){
- rc = sqlite3VdbeCursorMoveto(u.bs.pC);
- if( rc ) goto abort_due_to_error;
- assert( u.bs.pC->deferredMoveto==0 );
- assert( u.bs.pC->isTable==0 );
- if( !u.bs.pC->nullRow ){
- rc = sqlite3VdbeIdxRowid(u.bs.pCrsr, &u.bs.rowid);
+#endif /* local variables moved into u.bq */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.bq.pC = p->apCsr[pOp->p1];
+ assert( u.bq.pC!=0 );
+ u.bq.pCrsr = u.bq.pC->pCursor;
+ if( ALWAYS(u.bq.pCrsr!=0) ){
+ rc = sqlite3VdbeCursorMoveto(u.bq.pC);
+ if( NEVER(rc) ) goto abort_due_to_error;
+ assert( u.bq.pC->deferredMoveto==0 );
+ assert( u.bq.pC->isTable==0 );
+ if( !u.bq.pC->nullRow ){
+ rc = sqlite3VdbeIdxRowid(db, u.bq.pCrsr, &u.bq.rowid);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = u.bs.rowid;
+ pOut->u.i = u.bq.rowid;
}
}
break;
}
@@ -55245,38 +55139,37 @@
** to the comparison. This makes the opcode work like IdxLE.
*/
case OP_IdxLT: /* jump, in3 */
case OP_IdxGE: { /* jump, in3 */
-#if 0 /* local variables moved into u.bt */
- int i;
+#if 0 /* local variables moved into u.br */
VdbeCursor *pC;
int res;
UnpackedRecord r;
-#endif /* local variables moved into u.bt */
-
- u.bt.i = pOp->p1;
- assert( u.bt.i>=0 && u.bt.i<p->nCursor );
- assert( p->apCsr[u.bt.i]!=0 );
- if( (u.bt.pC = p->apCsr[u.bt.i])->pCursor!=0 ){
- assert( u.bt.pC->deferredMoveto==0 );
+#endif /* local variables moved into u.br */
+
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ u.br.pC = p->apCsr[pOp->p1];
+ assert( u.br.pC!=0 );
+ if( ALWAYS(u.br.pC->pCursor!=0) ){
+ assert( u.br.pC->deferredMoveto==0 );
assert( pOp->p5==0 || pOp->p5==1 );
assert( pOp->p4type==P4_INT32 );
- u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
- u.bt.r.nField = (u16)pOp->p4.i;
+ u.br.r.pKeyInfo = u.br.pC->pKeyInfo;
+ u.br.r.nField = (u16)pOp->p4.i;
if( pOp->p5 ){
- u.bt.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
- }else{
- u.bt.r.flags = UNPACKED_IGNORE_ROWID;
- }
- u.bt.r.aMem = &p->aMem[pOp->p3];
- rc = sqlite3VdbeIdxKeyCompare(u.bt.pC, &u.bt.r, &u.bt.res);
+ u.br.r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
+ }else{
+ u.br.r.flags = UNPACKED_IGNORE_ROWID;
+ }
+ u.br.r.aMem = &p->aMem[pOp->p3];
+ rc = sqlite3VdbeIdxKeyCompare(u.br.pC, &u.br.r, &u.br.res);
if( pOp->opcode==OP_IdxLT ){
- u.bt.res = -u.bt.res;
+ u.br.res = -u.br.res;
}else{
assert( pOp->opcode==OP_IdxGE );
- u.bt.res++;
- }
- if( u.bt.res>0 ){
+ u.br.res++;
+ }
+ if( u.br.res>0 ){
pc = pOp->p2 - 1 ;
}
}
break;
@@ -55302,37 +55195,37 @@
**
** See also: Clear
*/
case OP_Destroy: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bu */
+#if 0 /* local variables moved into u.bs */
int iMoved;
int iCnt;
Vdbe *pVdbe;
int iDb;
-#endif /* local variables moved into u.bu */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- u.bu.iCnt = 0;
- for(u.bu.pVdbe=db->pVdbe; u.bu.pVdbe; u.bu.pVdbe = u.bu.pVdbe->pNext){
- if( u.bu.pVdbe->magic==VDBE_MAGIC_RUN && u.bu.pVdbe->inVtabMethod<2 && u.bu.pVdbe->pc>=0 ){
- u.bu.iCnt++;
- }
- }
-#else
- u.bu.iCnt = db->activeVdbeCnt;
-#endif
- if( u.bu.iCnt>1 ){
+#endif /* local variables moved into u.bs */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ u.bs.iCnt = 0;
+ for(u.bs.pVdbe=db->pVdbe; u.bs.pVdbe; u.bs.pVdbe = u.bs.pVdbe->pNext){
+ if( u.bs.pVdbe->magic==VDBE_MAGIC_RUN && u.bs.pVdbe->inVtabMethod<2 && u.bs.pVdbe->pc>=0 ){
+ u.bs.iCnt++;
+ }
+ }
+#else
+ u.bs.iCnt = db->activeVdbeCnt;
+#endif
+ if( u.bs.iCnt>1 ){
rc = SQLITE_LOCKED;
p->errorAction = OE_Abort;
}else{
- u.bu.iDb = pOp->p3;
- assert( u.bu.iCnt==1 );
- assert( (p->btreeMask & (1<<u.bu.iDb))!=0 );
- rc = sqlite3BtreeDropTable(db->aDb[u.bu.iDb].pBt, pOp->p1, &u.bu.iMoved);
+ u.bs.iDb = pOp->p3;
+ assert( u.bs.iCnt==1 );
+ assert( (p->btreeMask & (1<<u.bs.iDb))!=0 );
+ rc = sqlite3BtreeDropTable(db->aDb[u.bs.iDb].pBt, pOp->p1, &u.bs.iMoved);
MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = u.bu.iMoved;
+ pOut->u.i = u.bs.iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( rc==SQLITE_OK && u.bu.iMoved!=0 ){
- sqlite3RootPageMoved(&db->aDb[u.bu.iDb], u.bu.iMoved, pOp->p1);
+ if( rc==SQLITE_OK && u.bs.iMoved!=0 ){
+ sqlite3RootPageMoved(&db->aDb[u.bs.iDb], u.bs.iMoved, pOp->p1);
}
#endif
}
break;
@@ -55356,21 +55249,21 @@
**
** See also: Destroy
*/
case OP_Clear: {
-#if 0 /* local variables moved into u.bv */
+#if 0 /* local variables moved into u.bt */
int nChange;
-#endif /* local variables moved into u.bv */
-
- u.bv.nChange = 0;
+#endif /* local variables moved into u.bt */
+
+ u.bt.nChange = 0;
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
rc = sqlite3BtreeClearTable(
- db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bv.nChange : 0)
+ db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bt.nChange : 0)
);
if( pOp->p3 ){
- p->nChange += u.bv.nChange;
+ p->nChange += u.bt.nChange;
if( pOp->p3>0 ){
- p->aMem[pOp->p3].u.i += u.bv.nChange;
+ p->aMem[pOp->p3].u.i += u.bt.nChange;
}
}
break;
}
@@ -55398,27 +55291,27 @@
** See documentation on OP_CreateTable for additional information.
*/
case OP_CreateIndex: /* out2-prerelease */
case OP_CreateTable: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bw */
+#if 0 /* local variables moved into u.bu */
int pgno;
int flags;
Db *pDb;
-#endif /* local variables moved into u.bw */
-
- u.bw.pgno = 0;
+#endif /* local variables moved into u.bu */
+
+ u.bu.pgno = 0;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
- u.bw.pDb = &db->aDb[pOp->p1];
- assert( u.bw.pDb->pBt!=0 );
+ u.bu.pDb = &db->aDb[pOp->p1];
+ assert( u.bu.pDb->pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
- /* u.bw.flags = BTREE_INTKEY; */
- u.bw.flags = BTREE_LEAFDATA|BTREE_INTKEY;
- }else{
- u.bw.flags = BTREE_ZERODATA;
- }
- rc = sqlite3BtreeCreateTable(u.bw.pDb->pBt, &u.bw.pgno, u.bw.flags);
- pOut->u.i = u.bw.pgno;
+ /* u.bu.flags = BTREE_INTKEY; */
+ u.bu.flags = BTREE_LEAFDATA|BTREE_INTKEY;
+ }else{
+ u.bu.flags = BTREE_ZERODATA;
+ }
+ rc = sqlite3BtreeCreateTable(u.bu.pDb->pBt, &u.bu.pgno, u.bu.flags);
+ pOut->u.i = u.bu.pgno;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -55434,17 +55327,17 @@
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine. It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
-#if 0 /* local variables moved into u.bx */
+#if 0 /* local variables moved into u.bv */
int iDb;
const char *zMaster;
char *zSql;
InitData initData;
-#endif /* local variables moved into u.bx */
-
- u.bx.iDb = pOp->p1;
- assert( u.bx.iDb>=0 && u.bx.iDb<db->nDb );
+#endif /* local variables moved into u.bv */
+
+ u.bv.iDb = pOp->p1;
+ assert( u.bv.iDb>=0 && u.bv.iDb<db->nDb );
/* If pOp->p2 is 0, then this opcode is being executed to read a
** single row, for example the row corresponding to a new index
** created by this VDBE, from the sqlite_master table. It only
@@ -55452,42 +55345,42 @@
** loaded. Otherwise, the new index definition can be loaded along
** with the rest of the schema when it is required.
**
** Although the mutex on the BtShared object that corresponds to
- ** database u.bx.iDb (the database containing the sqlite_master table
+ ** database u.bv.iDb (the database containing the sqlite_master table
** read by this instruction) is currently held, it is necessary to
** obtain the mutexes on all attached databases before checking if
- ** the schema of u.bx.iDb is loaded. This is because, at the start of
+ ** the schema of u.bv.iDb is loaded. This is because, at the start of
** the sqlite3_exec() call below, SQLite will invoke
** sqlite3BtreeEnterAll(). If all mutexes are not already held, the
- ** u.bx.iDb mutex may be temporarily released to avoid deadlock. If
+ ** u.bv.iDb mutex may be temporarily released to avoid deadlock. If
** this happens, then some other thread may delete the in-memory
- ** schema of database u.bx.iDb before the SQL statement runs. The schema
+ ** schema of database u.bv.iDb before the SQL statement runs. The schema
** will not be reloaded becuase the db->init.busy flag is set. This
** can result in a "no such table: sqlite_master" or "malformed
** database schema" error being returned to the user.
*/
- assert( sqlite3BtreeHoldsMutex(db->aDb[u.bx.iDb].pBt) );
+ assert( sqlite3BtreeHoldsMutex(db->aDb[u.bv.iDb].pBt) );
sqlite3BtreeEnterAll(db);
- if( pOp->p2 || DbHasProperty(db, u.bx.iDb, DB_SchemaLoaded) ){
- u.bx.zMaster = SCHEMA_TABLE(u.bx.iDb);
- u.bx.initData.db = db;
- u.bx.initData.iDb = pOp->p1;
- u.bx.initData.pzErrMsg = &p->zErrMsg;
- u.bx.zSql = sqlite3MPrintf(db,
+ if( pOp->p2 || ALWAYS(DbHasProperty(db, u.bv.iDb, DB_SchemaLoaded)) ){
+ u.bv.zMaster = SCHEMA_TABLE(u.bv.iDb);
+ u.bv.initData.db = db;
+ u.bv.initData.iDb = pOp->p1;
+ u.bv.initData.pzErrMsg = &p->zErrMsg;
+ u.bv.zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s",
- db->aDb[u.bx.iDb].zName, u.bx.zMaster, pOp->p4.z);
- if( u.bx.zSql==0 ){
+ db->aDb[u.bv.iDb].zName, u.bv.zMaster, pOp->p4.z);
+ if( u.bv.zSql==0 ){
rc = SQLITE_NOMEM;
}else{
(void)sqlite3SafetyOff(db);
assert( db->init.busy==0 );
db->init.busy = 1;
- u.bx.initData.rc = SQLITE_OK;
+ u.bv.initData.rc = SQLITE_OK;
assert( !db->mallocFailed );
- rc = sqlite3_exec(db, u.bx.zSql, sqlite3InitCallback, &u.bx.initData, 0);
- if( rc==SQLITE_OK ) rc = u.bx.initData.rc;
- sqlite3DbFree(db, u.bx.zSql);
+ rc = sqlite3_exec(db, u.bv.zSql, sqlite3InitCallback, &u.bv.initData, 0);
+ if( rc==SQLITE_OK ) rc = u.bv.initData.rc;
+ sqlite3DbFree(db, u.bv.zSql);
db->init.busy = 0;
(void)sqlite3SafetyOn(db);
}
}
@@ -55497,9 +55390,9 @@
}
break;
}
-#if !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER)
+#if !defined(SQLITE_OMIT_ANALYZE)
/* Opcode: LoadAnalysis P1 * * * *
**
** Read the sqlite_stat1 table for database P1 and load the content
** of that table into the internal index hash table. This will cause
@@ -55509,9 +55402,9 @@
assert( pOp->p1>=0 && pOp->p1<db->nDb );
rc = sqlite3AnalysisLoad(db, pOp->p1);
break;
}
-#endif /* !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER) */
+#endif /* !defined(SQLITE_OMIT_ANALYZE) */
/* Opcode: DropTable P1 * * P4 *
**
** Remove the internal (in-memory) data structures that describe
@@ -55570,43 +55463,43 @@
**
** This opcode is used to implement the integrity_check pragma.
*/
case OP_IntegrityCk: {
-#if 0 /* local variables moved into u.by */
+#if 0 /* local variables moved into u.bw */
int nRoot; /* Number of tables to check. (Number of root pages.) */
int *aRoot; /* Array of rootpage numbers for tables to be checked */
int j; /* Loop counter */
int nErr; /* Number of errors reported */
char *z; /* Text of the error report */
Mem *pnErr; /* Register keeping track of errors remaining */
-#endif /* local variables moved into u.by */
-
- u.by.nRoot = pOp->p2;
- assert( u.by.nRoot>0 );
- u.by.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.by.nRoot+1) );
- if( u.by.aRoot==0 ) goto no_mem;
+#endif /* local variables moved into u.bw */
+
+ u.bw.nRoot = pOp->p2;
+ assert( u.bw.nRoot>0 );
+ u.bw.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bw.nRoot+1) );
+ if( u.bw.aRoot==0 ) goto no_mem;
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.by.pnErr = &p->aMem[pOp->p3];
- assert( (u.by.pnErr->flags & MEM_Int)!=0 );
- assert( (u.by.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+ u.bw.pnErr = &p->aMem[pOp->p3];
+ assert( (u.bw.pnErr->flags & MEM_Int)!=0 );
+ assert( (u.bw.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
pIn1 = &p->aMem[pOp->p1];
- for(u.by.j=0; u.by.j<u.by.nRoot; u.by.j++){
- u.by.aRoot[u.by.j] = (int)sqlite3VdbeIntValue(&pIn1[u.by.j]);
- }
- u.by.aRoot[u.by.j] = 0;
+ for(u.bw.j=0; u.bw.j<u.bw.nRoot; u.bw.j++){
+ u.bw.aRoot[u.bw.j] = (int)sqlite3VdbeIntValue(&pIn1[u.bw.j]);
+ }
+ u.bw.aRoot[u.bw.j] = 0;
assert( pOp->p5<db->nDb );
assert( (p->btreeMask & (1<<pOp->p5))!=0 );
- u.by.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.by.aRoot, u.by.nRoot,
- (int)u.by.pnErr->u.i, &u.by.nErr);
- sqlite3DbFree(db, u.by.aRoot);
- u.by.pnErr->u.i -= u.by.nErr;
+ u.bw.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bw.aRoot, u.bw.nRoot,
+ (int)u.bw.pnErr->u.i, &u.bw.nErr);
+ sqlite3DbFree(db, u.bw.aRoot);
+ u.bw.pnErr->u.i -= u.bw.nErr;
sqlite3VdbeMemSetNull(pIn1);
- if( u.by.nErr==0 ){
- assert( u.by.z==0 );
- }else if( u.by.z==0 ){
+ if( u.bw.nErr==0 ){
+ assert( u.bw.z==0 );
+ }else if( u.bw.z==0 ){
goto no_mem;
}else{
- sqlite3VdbeMemSetStr(pIn1, u.by.z, -1, SQLITE_UTF8, sqlite3_free);
+ sqlite3VdbeMemSetStr(pIn1, u.bw.z, -1, SQLITE_UTF8, sqlite3_free);
}
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding);
break;
@@ -55620,22 +55513,22 @@
**
** An assertion fails if P2 is not an integer.
*/
case OP_RowSetAdd: { /* in2 */
-#if 0 /* local variables moved into u.bz */
+#if 0 /* local variables moved into u.bx */
Mem *pIdx;
Mem *pVal;
-#endif /* local variables moved into u.bz */
+#endif /* local variables moved into u.bx */
assert( pOp->p1>0 && pOp->p1<=p->nMem );
- u.bz.pIdx = &p->aMem[pOp->p1];
+ u.bx.pIdx = &p->aMem[pOp->p1];
assert( pOp->p2>0 && pOp->p2<=p->nMem );
- u.bz.pVal = &p->aMem[pOp->p2];
- assert( (u.bz.pVal->flags & MEM_Int)!=0 );
- if( (u.bz.pIdx->flags & MEM_RowSet)==0 ){
- sqlite3VdbeMemSetRowSet(u.bz.pIdx);
- if( (u.bz.pIdx->flags & MEM_RowSet)==0 ) goto no_mem;
- }
- sqlite3RowSetInsert(u.bz.pIdx->u.pRowSet, u.bz.pVal->u.i);
+ u.bx.pVal = &p->aMem[pOp->p2];
+ assert( (u.bx.pVal->flags & MEM_Int)!=0 );
+ if( (u.bx.pIdx->flags & MEM_RowSet)==0 ){
+ sqlite3VdbeMemSetRowSet(u.bx.pIdx);
+ if( (u.bx.pIdx->flags & MEM_RowSet)==0 ) goto no_mem;
+ }
+ sqlite3RowSetInsert(u.bx.pIdx->u.pRowSet, u.bx.pVal->u.i);
break;
}
/* Opcode: RowSetRead P1 P2 P3 * *
@@ -55644,26 +55537,26 @@
** register P3. Or, if boolean index P1 is initially empty, leave P3
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: { /* jump, out3 */
-#if 0 /* local variables moved into u.ca */
+#if 0 /* local variables moved into u.by */
Mem *pIdx;
i64 val;
-#endif /* local variables moved into u.ca */
+#endif /* local variables moved into u.by */
assert( pOp->p1>0 && pOp->p1<=p->nMem );
CHECK_FOR_INTERRUPT;
- u.ca.pIdx = &p->aMem[pOp->p1];
+ u.by.pIdx = &p->aMem[pOp->p1];
pOut = &p->aMem[pOp->p3];
- if( (u.ca.pIdx->flags & MEM_RowSet)==0
- || sqlite3RowSetNext(u.ca.pIdx->u.pRowSet, &u.ca.val)==0
+ if( (u.by.pIdx->flags & MEM_RowSet)==0
+ || sqlite3RowSetNext(u.by.pIdx->u.pRowSet, &u.by.val)==0
){
/* The boolean index is empty */
- sqlite3VdbeMemSetNull(u.ca.pIdx);
+ sqlite3VdbeMemSetNull(u.by.pIdx);
pc = pOp->p2 - 1;
}else{
/* A value was pulled from the index */
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- sqlite3VdbeMemSetInt64(pOut, u.ca.val);
+ sqlite3VdbeMemSetInt64(pOut, u.by.val);
}
break;
}
@@ -55690,14 +55583,14 @@
** previously inserted as part of set X (only if it was previously
** inserted as part of some other set).
*/
case OP_RowSetTest: { /* jump, in1, in3 */
-#if 0 /* local variables moved into u.cb */
+#if 0 /* local variables moved into u.bz */
int iSet;
int exists;
-#endif /* local variables moved into u.cb */
-
- u.cb.iSet = pOp->p4.i;
+#endif /* local variables moved into u.bz */
+
+ u.bz.iSet = pOp->p4.i;
assert( pIn3->flags&MEM_Int );
/* If there is anything other than a rowset object in memory cell P1,
** delete it now and initialize P1 with an empty rowset
@@ -55707,19 +55600,19 @@
if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
}
assert( pOp->p4type==P4_INT32 );
- assert( u.cb.iSet==-1 || u.cb.iSet>=0 );
- if( u.cb.iSet ){
- u.cb.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
- (u8)(u.cb.iSet>=0 ? u.cb.iSet & 0xf : 0xff),
+ assert( u.bz.iSet==-1 || u.bz.iSet>=0 );
+ if( u.bz.iSet ){
+ u.bz.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
+ (u8)(u.bz.iSet>=0 ? u.bz.iSet & 0xf : 0xff),
pIn3->u.i);
- if( u.cb.exists ){
+ if( u.bz.exists ){
pc = pOp->p2 - 1;
break;
}
}
- if( u.cb.iSet>=0 ){
+ if( u.bz.iSet>=0 ){
sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
}
break;
}
@@ -55732,25 +55625,25 @@
** opcode. The context stores the last insert row id, the last statement change
** count, and the current statement change count.
*/
case OP_ContextPush: {
-#if 0 /* local variables moved into u.cc */
+#if 0 /* local variables moved into u.ca */
int i;
Context *pContext;
-#endif /* local variables moved into u.cc */
-
- u.cc.i = p->contextStackTop++;
- assert( u.cc.i>=0 );
+#endif /* local variables moved into u.ca */
+
+ u.ca.i = p->contextStackTop++;
+ assert( u.ca.i>=0 );
/* FIX ME: This should be allocated as part of the vdbe at compile-time */
- if( u.cc.i>=p->contextStackDepth ){
- p->contextStackDepth = u.cc.i+1;
+ if( u.ca.i>=p->contextStackDepth ){
+ p->contextStackDepth = u.ca.i+1;
p->contextStack = sqlite3DbReallocOrFree(db, p->contextStack,
- sizeof(Context)*(u.cc.i+1));
+ sizeof(Context)*(u.ca.i+1));
if( p->contextStack==0 ) goto no_mem;
}
- u.cc.pContext = &p->contextStack[u.cc.i];
- u.cc.pContext->lastRowid = db->lastRowid;
- u.cc.pContext->nChange = p->nChange;
+ u.ca.pContext = &p->contextStack[u.ca.i];
+ u.ca.pContext->lastRowid = db->lastRowid;
+ u.ca.pContext->nChange = p->nChange;
break;
}
/* Opcode: ContextPop * * *
@@ -55759,15 +55652,15 @@
** executed. The context stores the last insert row id, the last statement
** change count, and the current statement change count.
*/
case OP_ContextPop: {
-#if 0 /* local variables moved into u.cd */
+#if 0 /* local variables moved into u.cb */
Context *pContext;
-#endif /* local variables moved into u.cd */
- u.cd.pContext = &p->contextStack[--p->contextStackTop];
+#endif /* local variables moved into u.cb */
+ u.cb.pContext = &p->contextStack[--p->contextStackTop];
assert( p->contextStackTop>=0 );
- db->lastRowid = u.cd.pContext->lastRowid;
- p->nChange = u.cd.pContext->nChange;
+ db->lastRowid = u.cb.pContext->lastRowid;
+ p->nChange = u.cb.pContext->nChange;
break;
}
#endif /* #ifndef SQLITE_OMIT_TRIGGER */
@@ -55845,49 +55738,49 @@
** The P5 arguments are taken from register P2 and its
** successors.
*/
case OP_AggStep: {
-#if 0 /* local variables moved into u.ce */
+#if 0 /* local variables moved into u.cc */
int n;
int i;
Mem *pMem;
Mem *pRec;
sqlite3_context ctx;
sqlite3_value **apVal;
-#endif /* local variables moved into u.ce */
-
- u.ce.n = pOp->p5;
- assert( u.ce.n>=0 );
- u.ce.pRec = &p->aMem[pOp->p2];
- u.ce.apVal = p->apArg;
- assert( u.ce.apVal || u.ce.n==0 );
- for(u.ce.i=0; u.ce.i<u.ce.n; u.ce.i++, u.ce.pRec++){
- u.ce.apVal[u.ce.i] = u.ce.pRec;
- storeTypeInfo(u.ce.pRec, encoding);
- }
- u.ce.ctx.pFunc = pOp->p4.pFunc;
+#endif /* local variables moved into u.cc */
+
+ u.cc.n = pOp->p5;
+ assert( u.cc.n>=0 );
+ u.cc.pRec = &p->aMem[pOp->p2];
+ u.cc.apVal = p->apArg;
+ assert( u.cc.apVal || u.cc.n==0 );
+ for(u.cc.i=0; u.cc.i<u.cc.n; u.cc.i++, u.cc.pRec++){
+ u.cc.apVal[u.cc.i] = u.cc.pRec;
+ storeTypeInfo(u.cc.pRec, encoding);
+ }
+ u.cc.ctx.pFunc = pOp->p4.pFunc;
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.ce.ctx.pMem = u.ce.pMem = &p->aMem[pOp->p3];
- u.ce.pMem->n++;
- u.ce.ctx.s.flags = MEM_Null;
- u.ce.ctx.s.z = 0;
- u.ce.ctx.s.zMalloc = 0;
- u.ce.ctx.s.xDel = 0;
- u.ce.ctx.s.db = db;
- u.ce.ctx.isError = 0;
- u.ce.ctx.pColl = 0;
- if( u.ce.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ u.cc.ctx.pMem = u.cc.pMem = &p->aMem[pOp->p3];
+ u.cc.pMem->n++;
+ u.cc.ctx.s.flags = MEM_Null;
+ u.cc.ctx.s.z = 0;
+ u.cc.ctx.s.zMalloc = 0;
+ u.cc.ctx.s.xDel = 0;
+ u.cc.ctx.s.db = db;
+ u.cc.ctx.isError = 0;
+ u.cc.ctx.pColl = 0;
+ if( u.cc.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>p->aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
- u.ce.ctx.pColl = pOp[-1].p4.pColl;
- }
- (u.ce.ctx.pFunc->xStep)(&u.ce.ctx, u.ce.n, u.ce.apVal);
- if( u.ce.ctx.isError ){
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ce.ctx.s));
- rc = u.ce.ctx.isError;
- }
- sqlite3VdbeMemRelease(&u.ce.ctx.s);
+ u.cc.ctx.pColl = pOp[-1].p4.pColl;
+ }
+ (u.cc.ctx.pFunc->xStep)(&u.cc.ctx, u.cc.n, u.cc.apVal);
+ if( u.cc.ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cc.ctx.s));
+ rc = u.cc.ctx.isError;
+ }
+ sqlite3VdbeMemRelease(&u.cc.ctx.s);
break;
}
/* Opcode: AggFinal P1 P2 * P4 *
@@ -55902,21 +55795,21 @@
** P4 argument is only needed for the degenerate case where
** the step function was not previously called.
*/
case OP_AggFinal: {
-#if 0 /* local variables moved into u.cf */
+#if 0 /* local variables moved into u.cd */
Mem *pMem;
-#endif /* local variables moved into u.cf */
+#endif /* local variables moved into u.cd */
assert( pOp->p1>0 && pOp->p1<=p->nMem );
- u.cf.pMem = &p->aMem[pOp->p1];
- assert( (u.cf.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
- rc = sqlite3VdbeMemFinalize(u.cf.pMem, pOp->p4.pFunc);
+ u.cd.pMem = &p->aMem[pOp->p1];
+ assert( (u.cd.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
+ rc = sqlite3VdbeMemFinalize(u.cd.pMem, pOp->p4.pFunc);
if( rc==SQLITE_ERROR ){
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cf.pMem));
- }
- sqlite3VdbeChangeEncoding(u.cf.pMem, encoding);
- UPDATE_MAX_BLOBSIZE(u.cf.pMem);
- if( sqlite3VdbeMemTooBig(u.cf.pMem) ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cd.pMem));
+ }
+ sqlite3VdbeChangeEncoding(u.cd.pMem, encoding);
+ UPDATE_MAX_BLOBSIZE(u.cd.pMem);
+ if( sqlite3VdbeMemTooBig(u.cd.pMem) ){
goto too_big;
}
break;
}
@@ -55944,16 +55837,16 @@
** the P1 database. If the vacuum has finished, jump to instruction
** P2. Otherwise, fall through to the next instruction.
*/
case OP_IncrVacuum: { /* jump */
-#if 0 /* local variables moved into u.cg */
+#if 0 /* local variables moved into u.ce */
Btree *pBt;
-#endif /* local variables moved into u.cg */
+#endif /* local variables moved into u.ce */
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
- u.cg.pBt = db->aDb[pOp->p1].pBt;
- rc = sqlite3BtreeIncrVacuum(u.cg.pBt);
+ u.ce.pBt = db->aDb[pOp->p1].pBt;
+ rc = sqlite3BtreeIncrVacuum(u.ce.pBt);
if( rc==SQLITE_DONE ){
pc = pOp->p2 - 1;
rc = SQLITE_OK;
}
@@ -55994,19 +55887,19 @@
** P4 contains a pointer to the name of the table being locked. This is only
** used to generate an error message if the lock cannot be obtained.
*/
case OP_TableLock: {
-#if 0 /* local variables moved into u.ch */
+#if 0 /* local variables moved into u.cf */
int p1;
u8 isWriteLock;
-#endif /* local variables moved into u.ch */
-
- u.ch.p1 = pOp->p1;
- u.ch.isWriteLock = (u8)pOp->p3;
- assert( u.ch.p1>=0 && u.ch.p1<db->nDb );
- assert( (p->btreeMask & (1<<u.ch.p1))!=0 );
- assert( u.ch.isWriteLock==0 || u.ch.isWriteLock==1 );
- rc = sqlite3BtreeLockTable(db->aDb[u.ch.p1].pBt, pOp->p2, u.ch.isWriteLock);
+#endif /* local variables moved into u.cf */
+
+ u.cf.p1 = pOp->p1;
+ u.cf.isWriteLock = (u8)pOp->p3;
+ assert( u.cf.p1>=0 && u.cf.p1<db->nDb );
+ assert( (p->btreeMask & (1<<u.cf.p1))!=0 );
+ assert( u.cf.isWriteLock==0 || u.cf.isWriteLock==1 );
+ rc = sqlite3BtreeLockTable(db->aDb[u.cf.p1].pBt, pOp->p2, u.cf.isWriteLock);
if( (rc&0xFF)==SQLITE_LOCKED ){
const char *z = pOp->p4.z;
sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
}
@@ -56024,17 +55917,17 @@
** within a callback to a virtual table xSync() method. If it is, the error
** code will be set to SQLITE_LOCKED.
*/
case OP_VBegin: {
-#if 0 /* local variables moved into u.ci */
+#if 0 /* local variables moved into u.cg */
sqlite3_vtab *pVtab;
-#endif /* local variables moved into u.ci */
- u.ci.pVtab = pOp->p4.pVtab;
- rc = sqlite3VtabBegin(db, u.ci.pVtab);
- if( u.ci.pVtab ){
+#endif /* local variables moved into u.cg */
+ u.cg.pVtab = pOp->p4.pVtab;
+ rc = sqlite3VtabBegin(db, u.cg.pVtab);
+ if( u.cg.pVtab ){
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.ci.pVtab->zErrMsg;
- u.ci.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.cg.pVtab->zErrMsg;
+ u.cg.pVtab->zErrMsg = 0;
}
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -56072,38 +55965,38 @@
** P1 is a cursor number. This opcode opens a cursor to the virtual
** table and stores that cursor in P1.
*/
case OP_VOpen: {
-#if 0 /* local variables moved into u.cj */
+#if 0 /* local variables moved into u.ch */
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
-#endif /* local variables moved into u.cj */
-
- u.cj.pCur = 0;
- u.cj.pVtabCursor = 0;
- u.cj.pVtab = pOp->p4.pVtab;
- u.cj.pModule = (sqlite3_module *)u.cj.pVtab->pModule;
- assert(u.cj.pVtab && u.cj.pModule);
+#endif /* local variables moved into u.ch */
+
+ u.ch.pCur = 0;
+ u.ch.pVtabCursor = 0;
+ u.ch.pVtab = pOp->p4.pVtab;
+ u.ch.pModule = (sqlite3_module *)u.ch.pVtab->pModule;
+ assert(u.ch.pVtab && u.ch.pModule);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- rc = u.cj.pModule->xOpen(u.cj.pVtab, &u.cj.pVtabCursor);
+ rc = u.ch.pModule->xOpen(u.ch.pVtab, &u.ch.pVtabCursor);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.cj.pVtab->zErrMsg;
- u.cj.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.ch.pVtab->zErrMsg;
+ u.ch.pVtab->zErrMsg = 0;
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
- u.cj.pVtabCursor->pVtab = u.cj.pVtab;
+ u.ch.pVtabCursor->pVtab = u.ch.pVtab;
/* Initialise vdbe cursor object */
- u.cj.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
- if( u.cj.pCur ){
- u.cj.pCur->pVtabCursor = u.cj.pVtabCursor;
- u.cj.pCur->pModule = u.cj.pVtabCursor->pVtab->pModule;
+ u.ch.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
+ if( u.ch.pCur ){
+ u.ch.pCur->pVtabCursor = u.ch.pVtabCursor;
+ u.ch.pCur->pModule = u.ch.pVtabCursor->pVtab->pModule;
}else{
db->mallocFailed = 1;
- u.cj.pModule->xClose(u.cj.pVtabCursor);
+ u.ch.pModule->xClose(u.ch.pVtabCursor);
}
}
break;
}
@@ -56128,9 +56021,9 @@
**
** A jump is made to P2 if the result set after filtering would be empty.
*/
case OP_VFilter: { /* jump */
-#if 0 /* local variables moved into u.ck */
+#if 0 /* local variables moved into u.ci */
int nArg;
int iQuery;
const sqlite3_module *pModule;
Mem *pQuery;
@@ -56140,52 +56033,52 @@
VdbeCursor *pCur;
int res;
int i;
Mem **apArg;
-#endif /* local variables moved into u.ck */
-
- u.ck.pQuery = &p->aMem[pOp->p3];
- u.ck.pArgc = &u.ck.pQuery[1];
- u.ck.pCur = p->apCsr[pOp->p1];
- REGISTER_TRACE(pOp->p3, u.ck.pQuery);
- assert( u.ck.pCur->pVtabCursor );
- u.ck.pVtabCursor = u.ck.pCur->pVtabCursor;
- u.ck.pVtab = u.ck.pVtabCursor->pVtab;
- u.ck.pModule = u.ck.pVtab->pModule;
+#endif /* local variables moved into u.ci */
+
+ u.ci.pQuery = &p->aMem[pOp->p3];
+ u.ci.pArgc = &u.ci.pQuery[1];
+ u.ci.pCur = p->apCsr[pOp->p1];
+ REGISTER_TRACE(pOp->p3, u.ci.pQuery);
+ assert( u.ci.pCur->pVtabCursor );
+ u.ci.pVtabCursor = u.ci.pCur->pVtabCursor;
+ u.ci.pVtab = u.ci.pVtabCursor->pVtab;
+ u.ci.pModule = u.ci.pVtab->pModule;
/* Grab the index number and argc parameters */
- assert( (u.ck.pQuery->flags&MEM_Int)!=0 && u.ck.pArgc->flags==MEM_Int );
- u.ck.nArg = (int)u.ck.pArgc->u.i;
- u.ck.iQuery = (int)u.ck.pQuery->u.i;
+ assert( (u.ci.pQuery->flags&MEM_Int)!=0 && u.ci.pArgc->flags==MEM_Int );
+ u.ci.nArg = (int)u.ci.pArgc->u.i;
+ u.ci.iQuery = (int)u.ci.pQuery->u.i;
/* Invoke the xFilter method */
{
- u.ck.res = 0;
- u.ck.apArg = p->apArg;
- for(u.ck.i = 0; u.ck.i<u.ck.nArg; u.ck.i++){
- u.ck.apArg[u.ck.i] = &u.ck.pArgc[u.ck.i+1];
- storeTypeInfo(u.ck.apArg[u.ck.i], 0);
+ u.ci.res = 0;
+ u.ci.apArg = p->apArg;
+ for(u.ci.i = 0; u.ci.i<u.ci.nArg; u.ci.i++){
+ u.ci.apArg[u.ci.i] = &u.ci.pArgc[u.ci.i+1];
+ storeTypeInfo(u.ci.apArg[u.ci.i], 0);
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- sqlite3VtabLock(u.ck.pVtab);
+ sqlite3VtabLock(u.ci.pVtab);
p->inVtabMethod = 1;
- rc = u.ck.pModule->xFilter(u.ck.pVtabCursor, u.ck.iQuery, pOp->p4.z, u.ck.nArg, u.ck.apArg);
+ rc = u.ci.pModule->xFilter(u.ci.pVtabCursor, u.ci.iQuery, pOp->p4.z, u.ci.nArg, u.ci.apArg);
p->inVtabMethod = 0;
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.ck.pVtab->zErrMsg;
- u.ck.pVtab->zErrMsg = 0;
- sqlite3VtabUnlock(db, u.ck.pVtab);
- if( rc==SQLITE_OK ){
- u.ck.res = u.ck.pModule->xEof(u.ck.pVtabCursor);
+ p->zErrMsg = u.ci.pVtab->zErrMsg;
+ u.ci.pVtab->zErrMsg = 0;
+ sqlite3VtabUnlock(db, u.ci.pVtab);
+ if( rc==SQLITE_OK ){
+ u.ci.res = u.ci.pModule->xEof(u.ci.pVtabCursor);
}
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
- if( u.ck.res ){
+ if( u.ci.res ){
pc = pOp->p2 - 1;
}
}
- u.ck.pCur->nullRow = 0;
+ u.ci.pCur->nullRow = 0;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -56197,55 +56090,55 @@
** the row of the virtual-table that the
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
-#if 0 /* local variables moved into u.cl */
+#if 0 /* local variables moved into u.cj */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
-#endif /* local variables moved into u.cl */
+#endif /* local variables moved into u.cj */
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.cl.pDest = &p->aMem[pOp->p3];
+ u.cj.pDest = &p->aMem[pOp->p3];
if( pCur->nullRow ){
- sqlite3VdbeMemSetNull(u.cl.pDest);
+ sqlite3VdbeMemSetNull(u.cj.pDest);
break;
}
- u.cl.pVtab = pCur->pVtabCursor->pVtab;
- u.cl.pModule = u.cl.pVtab->pModule;
- assert( u.cl.pModule->xColumn );
- memset(&u.cl.sContext, 0, sizeof(u.cl.sContext));
+ u.cj.pVtab = pCur->pVtabCursor->pVtab;
+ u.cj.pModule = u.cj.pVtab->pModule;
+ assert( u.cj.pModule->xColumn );
+ memset(&u.cj.sContext, 0, sizeof(u.cj.sContext));
/* The output cell may already have a buffer allocated. Move
- ** the current contents to u.cl.sContext.s so in case the user-function
+ ** the current contents to u.cj.sContext.s so in case the user-function
** can use the already allocated buffer instead of allocating a
** new one.
*/
- sqlite3VdbeMemMove(&u.cl.sContext.s, u.cl.pDest);
- MemSetTypeFlag(&u.cl.sContext.s, MEM_Null);
+ sqlite3VdbeMemMove(&u.cj.sContext.s, u.cj.pDest);
+ MemSetTypeFlag(&u.cj.sContext.s, MEM_Null);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- rc = u.cl.pModule->xColumn(pCur->pVtabCursor, &u.cl.sContext, pOp->p2);
+ rc = u.cj.pModule->xColumn(pCur->pVtabCursor, &u.cj.sContext, pOp->p2);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.cl.pVtab->zErrMsg;
- u.cl.pVtab->zErrMsg = 0;
+ p->zErrMsg = u.cj.pVtab->zErrMsg;
+ u.cj.pVtab->zErrMsg = 0;
/* Copy the result of the function to the P3 register. We
** do this regardless of whether or not an error occurred to ensure any
- ** dynamic allocation in u.cl.sContext.s (a Mem struct) is released.
- */
- sqlite3VdbeChangeEncoding(&u.cl.sContext.s, encoding);
- REGISTER_TRACE(pOp->p3, u.cl.pDest);
- sqlite3VdbeMemMove(u.cl.pDest, &u.cl.sContext.s);
- UPDATE_MAX_BLOBSIZE(u.cl.pDest);
+ ** dynamic allocation in u.cj.sContext.s (a Mem struct) is released.
+ */
+ sqlite3VdbeChangeEncoding(&u.cj.sContext.s, encoding);
+ REGISTER_TRACE(pOp->p3, u.cj.pDest);
+ sqlite3VdbeMemMove(u.cj.pDest, &u.cj.sContext.s);
+ UPDATE_MAX_BLOBSIZE(u.cj.pDest);
if( sqlite3SafetyOn(db) ){
goto abort_due_to_misuse;
}
- if( sqlite3VdbeMemTooBig(u.cl.pDest) ){
+ if( sqlite3VdbeMemTooBig(u.cj.pDest) ){
goto too_big;
}
break;
}
@@ -56258,24 +56151,24 @@
** jump to instruction P2. Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: { /* jump */
-#if 0 /* local variables moved into u.cm */
+#if 0 /* local variables moved into u.ck */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
-#endif /* local variables moved into u.cm */
-
- u.cm.res = 0;
- u.cm.pCur = p->apCsr[pOp->p1];
- assert( u.cm.pCur->pVtabCursor );
- if( u.cm.pCur->nullRow ){
+#endif /* local variables moved into u.ck */
+
+ u.ck.res = 0;
+ u.ck.pCur = p->apCsr[pOp->p1];
+ assert( u.ck.pCur->pVtabCursor );
+ if( u.ck.pCur->nullRow ){
break;
}
- u.cm.pVtab = u.cm.pCur->pVtabCursor->pVtab;
- u.cm.pModule = u.cm.pVtab->pModule;
- assert( u.cm.pModule->xNext );
+ u.ck.pVtab = u.ck.pCur->pVtabCursor->pVtab;
+ u.ck.pModule = u.ck.pVtab->pModule;
+ assert( u.ck.pModule->xNext );
/* Invoke the xNext() method of the module. There is no way for the
** underlying implementation to return an error if one occurs during
** xNext(). Instead, if an error occurs, true is returned (indicating that
@@ -56282,22 +56175,22 @@
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- sqlite3VtabLock(u.cm.pVtab);
+ sqlite3VtabLock(u.ck.pVtab);
p->inVtabMethod = 1;
- rc = u.cm.pModule->xNext(u.cm.pCur->pVtabCursor);
+ rc = u.ck.pModule->xNext(u.ck.pCur->pVtabCursor);
p->inVtabMethod = 0;
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.cm.pVtab->zErrMsg;
- u.cm.pVtab->zErrMsg = 0;
- sqlite3VtabUnlock(db, u.cm.pVtab);
- if( rc==SQLITE_OK ){
- u.cm.res = u.cm.pModule->xEof(u.cm.pCur->pVtabCursor);
+ p->zErrMsg = u.ck.pVtab->zErrMsg;
+ u.ck.pVtab->zErrMsg = 0;
+ sqlite3VtabUnlock(db, u.ck.pVtab);
+ if( rc==SQLITE_OK ){
+ u.ck.res = u.ck.pModule->xEof(u.ck.pCur->pVtabCursor);
}
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
- if( !u.cm.res ){
+ if( !u.ck.res ){
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
break;
@@ -56311,27 +56204,25 @@
** This opcode invokes the corresponding xRename method. The value
** in register P1 is passed as the zName argument to the xRename method.
*/
case OP_VRename: {
-#if 0 /* local variables moved into u.cn */
+#if 0 /* local variables moved into u.cl */
sqlite3_vtab *pVtab;
Mem *pName;
-#endif /* local variables moved into u.cn */
-
- u.cn.pVtab = pOp->p4.pVtab;
- u.cn.pName = &p->aMem[pOp->p1];
- assert( u.cn.pVtab->pModule->xRename );
- REGISTER_TRACE(pOp->p1, u.cn.pName);
-
- Stringify(u.cn.pName, encoding);
-
+#endif /* local variables moved into u.cl */
+
+ u.cl.pVtab = pOp->p4.pVtab;
+ u.cl.pName = &p->aMem[pOp->p1];
+ assert( u.cl.pVtab->pModule->xRename );
+ REGISTER_TRACE(pOp->p1, u.cl.pName);
+ assert( u.cl.pName->flags & MEM_Str );
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- sqlite3VtabLock(u.cn.pVtab);
- rc = u.cn.pVtab->pModule->xRename(u.cn.pVtab, u.cn.pName->z);
+ sqlite3VtabLock(u.cl.pVtab);
+ rc = u.cl.pVtab->pModule->xRename(u.cl.pVtab, u.cl.pName->z);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.cn.pVtab->zErrMsg;
- u.cn.pVtab->zErrMsg = 0;
- sqlite3VtabUnlock(db, u.cn.pVtab);
+ p->zErrMsg = u.cl.pVtab->zErrMsg;
+ u.cl.pVtab->zErrMsg = 0;
+ sqlite3VtabUnlock(db, u.cl.pVtab);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
}
@@ -56361,44 +56252,41 @@
** is successful, then the value returned by sqlite3_last_insert_rowid()
** is set to the value of the rowid for the row just inserted.
*/
case OP_VUpdate: {
-#if 0 /* local variables moved into u.co */
+#if 0 /* local variables moved into u.cm */
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
int nArg;
int i;
sqlite_int64 rowid;
Mem **apArg;
Mem *pX;
-#endif /* local variables moved into u.co */
-
- u.co.pVtab = pOp->p4.pVtab;
- u.co.pModule = (sqlite3_module *)u.co.pVtab->pModule;
- u.co.nArg = pOp->p2;
+#endif /* local variables moved into u.cm */
+
+ u.cm.pVtab = pOp->p4.pVtab;
+ u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
+ u.cm.nArg = pOp->p2;
assert( pOp->p4type==P4_VTAB );
- if( u.co.pModule->xUpdate==0 ){
- sqlite3SetString(&p->zErrMsg, db, "read-only table");
- rc = SQLITE_ERROR;
- }else{
- u.co.apArg = p->apArg;
- u.co.pX = &p->aMem[pOp->p3];
- for(u.co.i=0; u.co.i<u.co.nArg; u.co.i++){
- storeTypeInfo(u.co.pX, 0);
- u.co.apArg[u.co.i] = u.co.pX;
- u.co.pX++;
+ if( ALWAYS(u.cm.pModule->xUpdate) ){
+ u.cm.apArg = p->apArg;
+ u.cm.pX = &p->aMem[pOp->p3];
+ for(u.cm.i=0; u.cm.i<u.cm.nArg; u.cm.i++){
+ storeTypeInfo(u.cm.pX, 0);
+ u.cm.apArg[u.cm.i] = u.cm.pX;
+ u.cm.pX++;
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
- sqlite3VtabLock(u.co.pVtab);
- rc = u.co.pModule->xUpdate(u.co.pVtab, u.co.nArg, u.co.apArg, &u.co.rowid);
+ sqlite3VtabLock(u.cm.pVtab);
+ rc = u.cm.pModule->xUpdate(u.cm.pVtab, u.cm.nArg, u.cm.apArg, &u.cm.rowid);
sqlite3DbFree(db, p->zErrMsg);
- p->zErrMsg = u.co.pVtab->zErrMsg;
- u.co.pVtab->zErrMsg = 0;
- sqlite3VtabUnlock(db, u.co.pVtab);
+ p->zErrMsg = u.cm.pVtab->zErrMsg;
+ u.cm.pVtab->zErrMsg = 0;
+ sqlite3VtabUnlock(db, u.cm.pVtab);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
- if( pOp->p1 && rc==SQLITE_OK ){
- assert( u.co.nArg>1 && u.co.apArg[0] && (u.co.apArg[0]->flags&MEM_Null) );
- db->lastRowid = u.co.rowid;
+ if( rc==SQLITE_OK && pOp->p1 ){
+ assert( u.cm.nArg>1 && u.cm.apArg[0] && (u.cm.apArg[0]->flags&MEM_Null) );
+ db->lastRowid = u.cm.rowid;
}
p->nChange++;
}
break;
@@ -56410,20 +56298,23 @@
**
** Write the current number of pages in database P1 to memory cell P2.
*/
case OP_Pagecount: { /* out2-prerelease */
-#if 0 /* local variables moved into u.cp */
+#if 0 /* local variables moved into u.cn */
int p1;
int nPage;
Pager *pPager;
-#endif /* local variables moved into u.cp */
-
- u.cp.p1 = pOp->p1;
- u.cp.pPager = sqlite3BtreePager(db->aDb[u.cp.p1].pBt);
- rc = sqlite3PagerPagecount(u.cp.pPager, &u.cp.nPage);
- if( rc==SQLITE_OK ){
+#endif /* local variables moved into u.cn */
+
+ u.cn.p1 = pOp->p1;
+ u.cn.pPager = sqlite3BtreePager(db->aDb[u.cn.p1].pBt);
+ rc = sqlite3PagerPagecount(u.cn.pPager, &u.cn.nPage);
+ /* OP_Pagecount is always called from within a read transaction. The
+ ** page count has already been successfully read and cached. So the
+ ** sqlite3PagerPagecount() call above cannot fail. */
+ if( ALWAYS(rc==SQLITE_OK) ){
pOut->flags = MEM_Int;
- pOut->u.i = u.cp.nPage;
+ pOut->u.i = u.cn.nPage;
}
break;
}
#endif
@@ -56434,20 +56325,20 @@
** If tracing is enabled (by the sqlite3_trace()) interface, then
** the UTF-8 string contained in P4 is emitted on the trace callback.
*/
case OP_Trace: {
-#if 0 /* local variables moved into u.cq */
+#if 0 /* local variables moved into u.co */
char *zTrace;
-#endif /* local variables moved into u.cq */
-
- u.cq.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
- if( u.cq.zTrace ){
+#endif /* local variables moved into u.co */
+
+ u.co.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
+ if( u.co.zTrace ){
if( db->xTrace ){
- db->xTrace(db->pTraceArg, u.cq.zTrace);
+ db->xTrace(db->pTraceArg, u.co.zTrace);
}
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0 ){
- sqlite3DebugPrintf("SQL-trace: %s\n", u.cq.zTrace);
+ sqlite3DebugPrintf("SQL-trace: %s\n", u.co.zTrace);
}
#endif /* SQLITE_DEBUG */
}
break;
@@ -57462,9 +57353,9 @@
*************************************************************************
** This file contains routines used for walking the parser tree for
** an SQL statement.
**
-** $Id: walker.c,v 1.6 2009/05/28 01:00:55 drh Exp $
+** $Id: walker.c,v 1.7 2009/06/15 23:15:59 drh Exp $
*/
/*
@@ -57509,16 +57400,16 @@
** Call sqlite3WalkExpr() for every expression in list p or until
** an abort request is seen.
*/
SQLITE_PRIVATE int sqlite3WalkExprList(Walker *pWalker, ExprList *p){
- int i, rc = WRC_Continue;
+ int i;
struct ExprList_item *pItem;
if( p ){
for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
if( sqlite3WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
}
}
- return rc & WRC_Continue;
+ return WRC_Continue;
}
/*
** Walk all expressions associated with SELECT statement p. Do
@@ -57549,9 +57440,9 @@
int i;
struct SrcList_item *pItem;
pSrc = p->pSrc;
- if( pSrc ){
+ if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
if( sqlite3WalkSelect(pWalker, pItem->pSelect) ){
return WRC_Abort;
}
@@ -57602,9 +57493,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.28 2009/06/01 16:53:10 shane Exp $
+** $Id: resolve.c,v 1.30 2009/06/15 23:15:59 drh Exp $
*/
/*
** Turn the pExpr expression into an alias for the iCol-th column of the
@@ -57661,17 +57552,16 @@
pDup = sqlite3ExprDup(db, pOrig, 0);
if( pDup==0 ) return;
}else{
char *zToken = pOrig->u.zToken;
+ assert( zToken!=0 );
pOrig->u.zToken = 0;
pDup = sqlite3ExprDup(db, pOrig, 0);
pOrig->u.zToken = zToken;
if( pDup==0 ) return;
- if( zToken ){
- assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
- pDup->flags2 |= EP2_MallocedToken;
- pDup->u.zToken = sqlite3DbStrDup(db, zToken);
- }
+ assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
+ pDup->flags2 |= EP2_MallocedToken;
+ pDup->u.zToken = sqlite3DbStrDup(db, zToken);
}
if( pExpr->flags & EP_ExpCollate ){
pDup->pColl = pExpr->pColl;
pDup->flags |= EP_ExpCollate;
@@ -57705,9 +57595,9 @@
** means that the form of the name is Z and that columns from any table
** can be used.
**
** If the name cannot be resolved unambiguously, leave an error message
-** in pParse and return non-zero. Return zero on success.
+** in pParse and return WRC_Abort. Return WRC_Prune on success.
*/
static int lookupName(
Parse *pParse, /* The parsing context */
const char *zDb, /* Name of the database containing table, or NULL */
@@ -57754,9 +57644,11 @@
char *zTabName = pItem->zAlias;
if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
}else{
char *zTabName = pTab->zName;
- if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){
+ continue;
+ }
if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
continue;
}
}
@@ -57833,16 +57725,14 @@
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
cnt++;
pExpr->iColumn = iCol==pTab->iPKey ? -1 : (i16)iCol;
pExpr->pTab = pTab;
- if( iCol>=0 ){
- testcase( iCol==31 );
- testcase( iCol==32 );
- if( iCol>=32 ){
- *piColMask = 0xffffffff;
- }else{
- *piColMask |= ((u32)1)<<iCol;
- }
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ if( iCol>=32 ){
+ *piColMask = 0xffffffff;
+ }else{
+ *piColMask |= ((u32)1)<<iCol;
}
break;
}
}
@@ -57881,9 +57771,9 @@
assert( pExpr->x.pSelect==0 );
pOrig = pEList->a[j].pExpr;
if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
- return 2;
+ return WRC_Abort;
}
resolveAlias(pParse, pEList, j, pExpr, "");
cnt = 1;
pMatch = 0;
@@ -57913,9 +57803,9 @@
*/
if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
pExpr->op = TK_STRING;
pExpr->pTab = 0;
- return 0;
+ return WRC_Prune;
}
/*
** cnt==0 means there was not match. cnt>1 means there were two or
@@ -57968,11 +57858,11 @@
pTopNC->nRef++;
if( pTopNC==pNC ) break;
pTopNC = pTopNC->pNext;
}
- return 0;
+ return WRC_Prune;
} else {
- return 1;
+ return WRC_Abort;
}
}
/*
@@ -58029,10 +57919,9 @@
/* A lone identifier is the name of a column.
*/
case TK_ID: {
- lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
- return WRC_Prune;
+ return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
}
/* A table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
@@ -58054,10 +57943,9 @@
zDb = pExpr->pLeft->u.zToken;
zTable = pRight->pLeft->u.zToken;
zColumn = pRight->pRight->u.zToken;
}
- lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
- return WRC_Prune;
+ return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
}
/* Resolve function names
*/
@@ -58073,8 +57961,9 @@
const char *zId; /* The function name. */
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
+ testcase( pExpr->op==TK_CONST_FUNC );
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId);
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
@@ -58127,11 +58016,12 @@
return WRC_Prune;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT:
- case TK_EXISTS:
+ case TK_EXISTS: testcase( pExpr->op==TK_EXISTS );
#endif
case TK_IN: {
+ testcase( pExpr->op==TK_IN );
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
int nRef = pNC->nRef;
#ifndef SQLITE_OMIT_CHECK
if( pNC->isCheck ){
@@ -58178,9 +58068,9 @@
int i; /* Loop counter */
UNUSED_PARAMETER(pParse);
- if( pE->op==TK_ID || (pE->op==TK_STRING && pE->u.zToken[0]!='\'') ){
+ if( pE->op==TK_ID ){
char *zCol = pE->u.zToken;
for(i=0; i<pEList->nExpr; i++){
char *zAs = pEList->a[i].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
@@ -58314,9 +58204,9 @@
Expr *pE, *pDup;
if( pItem->done ) continue;
pE = pItem->pExpr;
if( sqlite3ExprIsInteger(pE, &iCol) ){
- if( iCol<0 || iCol>pEList->nExpr ){
+ if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
return 1;
}
}else{
@@ -58327,11 +58217,8 @@
assert(pDup);
iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
}
sqlite3ExprDelete(db, pDup);
- }
- if( iCol<0 ){
- return 1;
}
}
if( iCol>0 ){
CollSeq *pColl = pE->pColl;
@@ -58437,11 +58324,8 @@
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
Expr *pE = pItem->pExpr;
iCol = resolveAsName(pParse, pSelect->pEList, pE);
- if( iCol<0 ){
- return 1; /* OOM error */
- }
if( iCol>0 ){
/* If an AS-name match is found, mark this ORDER BY column as being
** a copy of the iCol-th result-set column. The subsequent call to
** sqlite3ResolveOrderGroupBy() will convert the expression to a
@@ -58769,9 +58653,9 @@
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.445 2009/06/01 16:53:10 shane Exp $
+** $Id: expr.c,v 1.446 2009/06/19 18:32:55 drh Exp $
*/
/*
** Return the 'affinity' of the expression pExpr if any.
@@ -59246,13 +59130,13 @@
}
}
/*
-** Allocate a Expr node which joins up to two subtrees.
-**
-** The
-** Works like sqlite3Expr() except that it takes an extra Parse*
-** argument and notifies the associated connection object if malloc fails.
+** Allocate a Expr node which joins as many as two subtrees.
+**
+** One or both of the subtrees can be NULL. Return a pointer to the new
+** Expr node. Or, if an OOM error occurs, set pParse->db->mallocFailed,
+** free the subtrees and return NULL.
*/
SQLITE_PRIVATE Expr *sqlite3PExpr(
Parse *pParse, /* Parsing context */
int op, /* Expression opcode */
@@ -64141,9 +64025,9 @@
** BEGIN TRANSACTION
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.549 2009/06/03 11:25:07 danielk1977 Exp $
+** $Id: build.c,v 1.552 2009/06/18 17:22:39 drh Exp $
*/
/*
** This routine is called when a new SQL statement is beginning to
@@ -65373,9 +65257,8 @@
if( !initbusy && (!pColl || !pColl->xCmp) ){
pColl = sqlite3GetCollSeq(db, pColl, zName);
if( !pColl ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
- pColl = 0;
}
}
return pColl;
@@ -67757,9 +67640,9 @@
**
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
-** $Id: callback.c,v 1.41 2009/05/20 02:40:46 drh Exp $
+** $Id: callback.c,v 1.42 2009/06/17 00:35:31 drh Exp $
*/
/*
@@ -67867,11 +67750,9 @@
if( pColl ){
const char *zName = pColl->zName;
CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName);
if( !p ){
- if( pParse->nErr==0 ){
- sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
- }
+ sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
pParse->nErr++;
return SQLITE_ERROR;
}
assert( p==pColl );
@@ -68084,9 +67965,8 @@
int h; /* Hash value */
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
- if( nArg<-1 ) nArg = -1;
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
/* First search for a match amongst the application-defined functions.
*/
@@ -68834,9 +68714,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.237 2009/06/03 01:24:54 drh Exp $
+** $Id: func.c,v 1.239 2009/06/19 16:44:41 drh Exp $
*/
/*
** Return the collating function associated with a function.
@@ -70079,17 +69959,12 @@
pAccum = (StrAccum*)sqlite3_aggregate_context(context, sizeof(*pAccum));
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
- int n;
+ int firstTerm = pAccum->useMalloc==0;
pAccum->useMalloc = 1;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
-#ifdef SQLITE_OMIT_DEPRECATED
- n = context->pMem->n;
-#else
- n = sqlite3_aggregate_count(context);
-#endif
- if( n>1 ){
+ if( !firstTerm ){
if( argc==2 ){
zSep = (char*)sqlite3_value_text(argv[1]);
nSep = sqlite3_value_bytes(argv[1]);
}else{
@@ -70133,11 +70008,8 @@
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
}
}
-#ifdef SQLITE_SSE
- (void)sqlite3SseFunctions(db);
-#endif
}
/*
** Set the LIKEOPT flag on the 2-argument function with the given name.
@@ -73214,14 +73086,14 @@
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.212 2009/06/03 11:25:07 danielk1977 Exp $
+** $Id: pragma.c,v 1.213 2009/06/19 14:06:03 drh Exp $
*/
/* Ignore this whole file if pragmas are disabled
*/
-#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)
+#if !defined(SQLITE_OMIT_PRAGMA)
/*
** Interpret the given string as a safety level. Return 0 for OFF,
** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
@@ -74550,19 +74422,8 @@
}else
#endif
-#ifdef SQLITE_SSE
- /*
- ** Check to see if the sqlite_statements table exists. Create it
- ** if it does not.
- */
- if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){
- extern int sqlite3CreateStatementsTable(Parse*);
- sqlite3CreateStatementsTable(pParse);
- }else
-#endif
-
#if SQLITE_HAS_CODEC
if( sqlite3StrICmp(zLeft, "key")==0 && zRight ){
sqlite3_key(db, zRight, sqlite3Strlen30(zRight));
}else
@@ -74625,9 +74486,9 @@
sqlite3DbFree(db, zLeft);
sqlite3DbFree(db, zRight);
}
-#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */
+#endif /* SQLITE_OMIT_PRAGMA */
/************** End of pragma.c **********************************************/
/************** Begin file prepare.c *****************************************/
/*
@@ -74644,9 +74505,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.121 2009/06/04 00:11:56 drh Exp $
+** $Id: prepare.c,v 1.124 2009/06/22 12:05:10 drh Exp $
*/
/*
** Fill the InitData structure with an error message that indicates
@@ -74661,14 +74522,14 @@
if( !db->mallocFailed && (db->flags & SQLITE_RecoveryMode)==0 ){
if( zObj==0 ) zObj = "?";
sqlite3SetString(pData->pzErrMsg, pData->db,
"malformed database schema (%s)", zObj);
- if( zExtra && zExtra[0] ){
+ if( zExtra ){
*pData->pzErrMsg = sqlite3MAppendf(pData->db, *pData->pzErrMsg, "%s - %s",
*pData->pzErrMsg, zExtra);
}
}
- pData->rc = SQLITE_CORRUPT;
+ pData->rc = db->mallocFailed ? SQLITE_NOMEM : SQLITE_CORRUPT;
}
/*
** This is the callback routine for the code that initializes the
@@ -74692,9 +74553,9 @@
assert( sqlite3_mutex_held(db->mutex) );
DbClearProperty(db, iDb, DB_Empty);
if( db->mallocFailed ){
corruptSchema(pData, argv[0], 0);
- return SQLITE_NOMEM;
+ return 1;
}
assert( iDb>=0 && iDb<db->nDb );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
@@ -74717,9 +74578,9 @@
if( SQLITE_OK!=rc ){
pData->rc = rc;
if( rc==SQLITE_NOMEM ){
db->mallocFailed = 1;
- }else if( rc!=SQLITE_INTERRUPT && (rc&0xff)!=SQLITE_LOCKED ){
+ }else if( rc!=SQLITE_INTERRUPT ){
corruptSchema(pData, argv[0], zErr);
}
sqlite3DbFree(db, zErr);
}
@@ -74733,17 +74594,17 @@
** to do here is record the root page number for that index.
*/
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName);
- if( pIndex==0 || pIndex->tnum!=0 ){
+ if( pIndex==0 ){
/* This can occur if there exists an index on a TEMP table which
** has the same name as another index on a permanent index. Since
** the permanent table is hidden by the TEMP table, we can also
** safely ignore the index on the permanent table.
*/
/* Do Nothing */;
- }else{
- pIndex->tnum = atoi(argv[1]);
+ }else if( sqlite3GetInt32(argv[1], &pIndex->tnum)==0 ){
+ corruptSchema(pData, argv[0], "invalid rootpage");
}
}
return 0;
}
@@ -74827,17 +74688,17 @@
rc = initData.rc;
goto error_out;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
- if( pTab ){
+ if( ALWAYS(pTab) ){
pTab->tabFlags |= TF_Readonly;
}
/* Create a cursor to hold the database open
*/
pDb = &db->aDb[iDb];
if( pDb->pBt==0 ){
- if( !OMIT_TEMPDB && iDb==1 ){
+ if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
DbSetProperty(db, 1, DB_SchemaLoaded);
}
return SQLITE_OK;
}
@@ -74855,10 +74716,15 @@
** Meta values are as follows:
** meta[0] Schema cookie. Changes with each schema change.
** meta[1] File format of schema layer.
** meta[2] Size of the page cache.
- ** meta[3] Use freelist if 0. Autovacuum if greater than zero.
+ ** meta[3] Largest rootpage (auto/incr_vacuum mode)
** meta[4] Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE
+ ** meta[5] User version
+ ** meta[6] Incremental vacuum mode
+ ** meta[7] unused
+ ** meta[8] unused
+ ** meta[9] unused
**
** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
** the possible values of meta[4].
*/
@@ -74933,12 +74799,9 @@
/* Read the schema information out of the schema tables
*/
assert( db->init.busy );
- if( rc==SQLITE_EMPTY ){
- /* For an empty database, there is nothing to read */
- rc = SQLITE_OK;
- }else{
+ {
char *zSql;
zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s",
db->aDb[iDb].zName, zMasterName);
@@ -75010,9 +74873,8 @@
int i, rc;
int commit_internal = !(db->flags&SQLITE_InternChanges);
assert( sqlite3_mutex_held(db->mutex) );
- if( db->init.busy ) return SQLITE_OK;
rc = SQLITE_OK;
db->init.busy = 1;
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
@@ -75026,9 +74888,10 @@
** for the TEMP database. This is loaded last, as the TEMP database
** schema may contain references to objects in other databases.
*/
#ifndef SQLITE_OMIT_TEMPDB
- if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
+ if( rc==SQLITE_OK && ALWAYS(db->nDb>1)
+ && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
rc = sqlite3InitOne(db, 1, pzErrMsg);
if( rc ){
sqlite3ResetInternalSchema(db, 1);
}
@@ -75083,14 +74946,15 @@
memset(curTemp, 0, sqlite3BtreeCursorSize());
rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, curTemp);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie);
- if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
+ if( ALWAYS(rc==SQLITE_OK)
+ && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
allOk = 0;
}
sqlite3BtreeCloseCursor(curTemp);
}
- if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
+ if( NEVER(rc==SQLITE_NOMEM) || rc==SQLITE_IOERR_NOMEM ){
db->mallocFailed = 1;
}
}
sqlite3_free(curTemp);
@@ -75207,8 +75071,10 @@
pParse->db = db;
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
+ testcase( nBytes==mxLen );
+ testcase( nBytes==mxLen+1 );
if( nBytes>mxLen ){
sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
(void)sqlite3SafetyOff(db);
rc = sqlite3ApiExit(db, SQLITE_TOOBIG);
@@ -75313,8 +75179,12 @@
}
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail);
+ if( rc==SQLITE_SCHEMA ){
+ sqlite3_finalize(*ppStmt);
+ rc = sqlite3Prepare(db, zSql, nBytes, saveSqlFlag, ppStmt, pzTail);
+ }
sqlite3BtreeLeaveAll(db);
sqlite3_mutex_leave(db->mutex);
return rc;
}
@@ -75486,9 +75356,9 @@
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.523 2009/06/01 16:53:10 shane Exp $
+** $Id: select.c,v 1.524 2009/06/12 03:27:27 drh Exp $
*/
/*
@@ -78270,8 +78140,9 @@
/* Transfer the FROM clause terms from the subquery into the
** outer query.
*/
for(i=0; i<nSubSrc; i++){
+ sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
pSrc->a[i+iFrom] = pSubSrc->a[i];
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].jointype = jointype;
@@ -81765,9 +81636,9 @@
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
-** $Id: vtab.c,v 1.90 2009/06/02 21:31:39 drh Exp $
+** $Id: vtab.c,v 1.91 2009/06/15 16:27:08 shane Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
@@ -81855,8 +81726,11 @@
** Unlock a virtual table. When the last lock is removed,
** disconnect the virtual table.
*/
SQLITE_PRIVATE void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){
+#ifndef SQLITE_DEBUG
+ UNUSED_PARAMETER(db);
+#endif
assert( pVtab->nRef>0 );
pVtab->nRef--;
assert(db);
assert( sqlite3SafetyCheckOk(db) );
@@ -82634,9 +82508,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.401 2009/06/06 15:17:28 drh Exp $
+** $Id: where.c,v 1.408 2009/06/16 14:15:22 shane Exp $
*/
/*
** Trace output macros
@@ -83276,21 +83150,22 @@
if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
return 0;
}
- z = pRight->u.zToken;
- cnt = 0;
+ if( sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ) return 0;
+ z = pRight->u.zToken;
if( ALWAYS(z) ){
+ cnt = 0;
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
}
- }
- if( cnt==0 || c==0 || 255==(u8)z[cnt-1] ){
- return 0;
- }
- *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
- *pnPattern = cnt;
- return 1;
+ if( cnt!=0 && c!=0 && 255!=(u8)z[cnt-1] ){
+ *pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
+ *pnPattern = cnt;
+ return 1;
+ }
+ }
+ return 0;
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
@@ -83508,8 +83383,24 @@
/*
** chngToIN holds a set of tables that *might* satisfy case 1. But
** we have to do some additional checking to see if case 1 really
** is satisfied.
+ **
+ ** chngToIN will hold either 0, 1, or 2 bits. The 0-bit case means
+ ** that there is no possibility of transforming the OR clause into an
+ ** IN operator because one or more terms in the OR clause contain
+ ** something other than == on a column in the single table. The 1-bit
+ ** case means that every term of the OR clause is of the form
+ ** "table.column=expr" for some single table. The one bit that is set
+ ** will correspond to the common table. We still need to check to make
+ ** sure the same column is used on all terms. The 2-bit case is when
+ ** the all terms are of the form "table1.column=table2.column". It
+ ** might be possible to form an IN operator with either table1.column
+ ** or table2.column as the LHS if either is common to every term of
+ ** the OR clause.
+ **
+ ** Note that terms of the form "table.column1=table.column2" (the
+ ** same table on both sizes of the ==) cannot be optimized.
*/
if( chngToIN ){
int okToChngToIN = 0; /* True if the conversion to IN is valid */
int iColumn = -1; /* Column index on lhs of IN operator */
@@ -83526,20 +83417,40 @@
pOrTerm = pOrWc->a;
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
assert( pOrTerm->eOperator==WO_EQ );
pOrTerm->wtFlags &= ~TERM_OR_OK;
- if( pOrTerm->leftCursor==iColumn ) continue;
- if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ) continue;
+ if( pOrTerm->leftCursor==iCursor ){
+ /* This is the 2-bit case and we are on the second iteration and
+ ** current term is from the first iteration. So skip this term. */
+ assert( j==1 );
+ continue;
+ }
+ if( (chngToIN & getMask(pMaskSet, pOrTerm->leftCursor))==0 ){
+ /* This term must be of the form t1.a==t2.b where t2 is in the
+ ** chngToIN set but t1 is not. This term will be either preceeded
+ ** or follwed by an inverted copy (t2.b==t1.a). Skip this term
+ ** and use its inversion. */
+ testcase( pOrTerm->wtFlags & TERM_COPIED );
+ testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
+ assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
+ continue;
+ }
iColumn = pOrTerm->u.leftColumn;
iCursor = pOrTerm->leftCursor;
break;
}
if( i<0 ){
+ /* No candidate table+column was found. This can only occur
+ ** on the second iteration */
assert( j==1 );
assert( (chngToIN&(chngToIN-1))==0 );
- assert( chngToIN==getMask(pMaskSet, iColumn) );
- break;
- }
+ assert( chngToIN==getMask(pMaskSet, iCursor) );
+ break;
+ }
+ testcase( j==1 );
+
+ /* We have found a candidate table and column. Check to see if that
+ ** table and column is common to every term in the OR clause */
okToChngToIN = 1;
for(; i>=0 && okToChngToIN; i--, pOrTerm++){
assert( pOrTerm->eOperator==WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
@@ -83783,13 +83694,20 @@
pStr1 = sqlite3Expr(db, TK_STRING, pRight->u.zToken);
if( pStr1 ) pStr1->u.zToken[nPattern] = 0;
pStr2 = sqlite3ExprDup(db, pStr1, 0);
if( !db->mallocFailed ){
- u8 c, *pC;
+ u8 c, *pC; /* Last character before the first wildcard */
pC = (u8*)&pStr2->u.zToken[nPattern-1];
c = *pC;
if( noCase ){
- if( c=='@' ) isComplete = 0;
+ /* The point is to increment the last character before the first
+ ** wildcard. But if we increment '@', that will push it into the
+ ** alphabetic range where case conversions will mess up the
+ ** inequality. To avoid this, make sure to also run the full
+ ** LIKE on all candidate expressions by clearing the isComplete flag
+ */
+ if( c=='A'-1 ) isComplete = 0;
+
c = sqlite3UpperToLower[c];
}
*pC = c + 1;
}
@@ -84457,9 +84375,9 @@
}else{
pCost->rCost = pIdxInfo->estimatedCost;
}
pCost->plan.u.pVtabIdx = pIdxInfo;
- if( pIdxInfo && pIdxInfo->orderByConsumed ){
+ if( pIdxInfo->orderByConsumed ){
pCost->plan.wsFlags |= WHERE_ORDERBY;
}
pCost->plan.nEq = 0;
pIdxInfo->nOrderBy = nOrderBy;
@@ -84743,9 +84661,9 @@
}else{
cost += cost*estLog(cost);
WHERETRACE(("...... orderby increases cost to %.9g\n", cost));
}
- }else if( pParse->db->flags & SQLITE_ReverseOrder ){
+ }else if( wsFlags!=0 && (pParse->db->flags & SQLITE_ReverseOrder)!=0 ){
/* For application testing, randomly reverse the output order for
** SELECT statements that omit the ORDER BY clause. This will help
** to find cases where
*/
@@ -84806,16 +84724,19 @@
Bitmask notReady, /* Mask of cursors that are not available */
ExprList *pOrderBy, /* The ORDER BY clause */
WhereCost *pCost /* Lowest cost query plan */
){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pSrc->pTab) ){
sqlite3_index_info *p = 0;
bestVirtualIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost, &p);
if( p->needToFreeIdxStr ){
sqlite3_free(p->idxStr);
}
sqlite3DbFree(pParse->db, p);
- }else{
+ }else
+#endif
+ {
bestBtreeIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost);
}
}
@@ -85449,10 +85370,10 @@
WhereTerm *pFinal; /* Final subterm within the OR-clause. */
SrcList oneTab; /* Shortened table list */
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
- int regRowset; /* Register for RowSet object */
- int regRowid; /* Register holding rowid */
+ int regRowset = 0; /* Register for RowSet object */
+ int regRowid = 0; /* Register holding rowid */
int iLoopBody = sqlite3VdbeMakeLabel(v); /* Start of loop body */
int iRetInit; /* Address of regReturn init */
int ii;
@@ -85489,9 +85410,8 @@
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
-
/* Loop through table entries that match term pOrTerm. */
pSubWInfo = sqlite3WhereBegin(pParse, &oneTab, pOrTerm->pExpr, 0,
WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FORCE_TABLE);
if( pSubWInfo ){
@@ -85790,11 +85710,13 @@
*/
assert( pWC->vmask==0 && pMaskSet->n==0 );
for(i=0; i<pTabList->nSrc; i++){
createMask(pMaskSet, pTabList->a[i].iCursor);
- if( pTabList->a[i].pTab && IsVirtual(pTabList->a[i].pTab) ){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( ALWAYS(pTabList->a[i].pTab) && IsVirtual(pTabList->a[i].pTab) ){
pWC->vmask |= ((Bitmask)1 << i);
}
+#endif
}
#ifndef NDEBUG
{
Bitmask toTheLeft = 0;
@@ -86211,8 +86133,19 @@
** in the input grammar file. */
/*
+** Disable all error recovery processing in the parser push-down
+** automaton.
+*/
+#define YYNOERRORRECOVERY 1
+
+/*
+** Make yytestcase() the same as testcase()
+*/
+#define yytestcase(X) testcase(X)
+
+/*
** An instance of this structure holds information about the
** LIMIT clause of a SELECT statement.
*/
struct LimitVal {
@@ -86355,9 +86288,9 @@
** YYNRULE the number of rules in the grammar
** YYERRORSYMBOL is the code number of the error symbol. If not
** defined, then do no error processing.
*/
-#define YYCODETYPE unsigned short int
+#define YYCODETYPE unsigned char
#define YYNOCODE 252
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 65
#define sqlite3ParserTOKENTYPE Token
@@ -86393,8 +86326,20 @@
/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
static const YYMINORTYPE yyzerominor = { 0 };
+
+/* Define the yytestcase() macro to be a no-op if is not already defined
+** otherwise.
+**
+** Applications can choose to define yytestcase() in the %include section
+** to a macro that can assist in verifying code coverage. For production
+** code the yytestcase() macro should be turned off. But it is useful
+** for testing.
+*/
+#ifndef yytestcase
+# define yytestcase(X)
+#endif
/* Next are the tables used to determine what action to take based on the
** current state and lookahead token. These tables are used to implement
@@ -86971,84 +86916,8 @@
26, /* VIRTUAL => ID */
26, /* REINDEX => ID */
26, /* RENAME => ID */
26, /* CTIME_KW => ID */
- 0, /* ANY => nothing */
- 0, /* OR => nothing */
- 0, /* AND => nothing */
- 0, /* IS => nothing */
- 0, /* BETWEEN => nothing */
- 0, /* IN => nothing */
- 0, /* ISNULL => nothing */
- 0, /* NOTNULL => nothing */
- 0, /* NE => nothing */
- 0, /* EQ => nothing */
- 0, /* GT => nothing */
- 0, /* LE => nothing */
- 0, /* LT => nothing */
- 0, /* GE => nothing */
- 0, /* ESCAPE => nothing */
- 0, /* BITAND => nothing */
- 0, /* BITOR => nothing */
- 0, /* LSHIFT => nothing */
- 0, /* RSHIFT => nothing */
- 0, /* PLUS => nothing */
- 0, /* MINUS => nothing */
- 0, /* STAR => nothing */
- 0, /* SLASH => nothing */
- 0, /* REM => nothing */
- 0, /* CONCAT => nothing */
- 0, /* COLLATE => nothing */
- 0, /* UMINUS => nothing */
- 0, /* UPLUS => nothing */
- 0, /* BITNOT => nothing */
- 0, /* STRING => nothing */
- 0, /* JOIN_KW => nothing */
- 0, /* CONSTRAINT => nothing */
- 0, /* DEFAULT => nothing */
- 0, /* NULL => nothing */
- 0, /* PRIMARY => nothing */
- 0, /* UNIQUE => nothing */
- 0, /* CHECK => nothing */
- 0, /* REFERENCES => nothing */
- 0, /* AUTOINCR => nothing */
- 0, /* ON => nothing */
- 0, /* DELETE => nothing */
- 0, /* UPDATE => nothing */
- 0, /* INSERT => nothing */
- 0, /* SET => nothing */
- 0, /* DEFERRABLE => nothing */
- 0, /* FOREIGN => nothing */
- 0, /* DROP => nothing */
- 0, /* UNION => nothing */
- 0, /* ALL => nothing */
- 0, /* EXCEPT => nothing */
- 0, /* INTERSECT => nothing */
- 0, /* SELECT => nothing */
- 0, /* DISTINCT => nothing */
- 0, /* DOT => nothing */
- 0, /* FROM => nothing */
- 0, /* JOIN => nothing */
- 0, /* USING => nothing */
- 0, /* ORDER => nothing */
- 0, /* GROUP => nothing */
- 0, /* HAVING => nothing */
- 0, /* LIMIT => nothing */
- 0, /* WHERE => nothing */
- 0, /* INTO => nothing */
- 0, /* VALUES => nothing */
- 0, /* INTEGER => nothing */
- 0, /* FLOAT => nothing */
- 0, /* BLOB => nothing */
- 0, /* REGISTER => nothing */
- 0, /* VARIABLE => nothing */
- 0, /* CASE => nothing */
- 0, /* WHEN => nothing */
- 0, /* THEN => nothing */
- 0, /* ELSE => nothing */
- 0, /* INDEX => nothing */
- 0, /* ALTER => nothing */
- 0, /* ADD => nothing */
};
#endif /* YYFALLBACK */
/* The following structure represents a single element of the
@@ -88271,50 +88140,8 @@
** { ... } // User supplied code
** #line <lineno> <thisfile>
** break;
*/
- case 0: /* input ::= cmdlist */
- case 1: /* cmdlist ::= cmdlist ecmd */
- case 2: /* cmdlist ::= ecmd */
- case 3: /* ecmd ::= SEMI */
- case 4: /* ecmd ::= explain cmdx SEMI */
- case 10: /* trans_opt ::= */
- case 11: /* trans_opt ::= TRANSACTION */
- case 12: /* trans_opt ::= TRANSACTION nm */
- case 20: /* savepoint_opt ::= SAVEPOINT */
- case 21: /* savepoint_opt ::= */
- case 25: /* cmd ::= create_table create_table_args */
- case 34: /* columnlist ::= columnlist COMMA column */
- case 35: /* columnlist ::= column */
- case 44: /* type ::= */
- case 51: /* signed ::= plus_num */
- case 52: /* signed ::= minus_num */
- case 53: /* carglist ::= carglist carg */
- case 54: /* carglist ::= */
- case 55: /* carg ::= CONSTRAINT nm ccons */
- case 56: /* carg ::= ccons */
- case 62: /* ccons ::= NULL onconf */
- case 89: /* conslist ::= conslist COMMA tcons */
- case 90: /* conslist ::= conslist tcons */
- case 91: /* conslist ::= tcons */
- case 92: /* tcons ::= CONSTRAINT nm */
- case 268: /* plus_opt ::= PLUS */
- case 269: /* plus_opt ::= */
- case 279: /* foreach_clause ::= */
- case 280: /* foreach_clause ::= FOR EACH ROW */
- case 300: /* database_kw_opt ::= DATABASE */
- case 301: /* database_kw_opt ::= */
- case 309: /* kwcolumn_opt ::= */
- case 310: /* kwcolumn_opt ::= COLUMNKW */
- case 314: /* vtabarglist ::= vtabarg */
- case 315: /* vtabarglist ::= vtabarglist COMMA vtabarg */
- case 317: /* vtabarg ::= vtabarg vtabargtoken */
- case 321: /* anylist ::= */
- case 322: /* anylist ::= anylist LP anylist RP */
- case 323: /* anylist ::= anylist ANY */
-{
-}
- break;
case 5: /* explain ::= */
{ sqlite3BeginParse(pParse, 0); }
break;
case 6: /* explain ::= EXPLAIN */
@@ -88332,16 +88159,16 @@
case 13: /* transtype ::= */
{yygotominor.yy194 = TK_DEFERRED;}
break;
case 14: /* transtype ::= DEFERRED */
- case 15: /* transtype ::= IMMEDIATE */
- case 16: /* transtype ::= EXCLUSIVE */
- case 114: /* multiselect_op ::= UNION */
- case 116: /* multiselect_op ::= EXCEPT|INTERSECT */
+ case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
+ case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
+ case 114: /* multiselect_op ::= UNION */ yytestcase(yyruleno==114);
+ case 116: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==116);
{yygotominor.yy194 = yymsp[0].major;}
break;
case 17: /* cmd ::= COMMIT trans_opt */
- case 18: /* cmd ::= END trans_opt */
+ case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
{sqlite3CommitTransaction(pParse);}
break;
case 19: /* cmd ::= ROLLBACK trans_opt */
{sqlite3RollbackTransaction(pParse);}
@@ -88372,28 +88199,28 @@
yygotominor.yy0 = yymsp[0].minor.yy0;
}
break;
case 28: /* ifnotexists ::= */
- case 31: /* temp ::= */
- case 70: /* autoinc ::= */
- case 84: /* init_deferred_pred_opt ::= */
- case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- case 97: /* defer_subclause_opt ::= */
- case 108: /* ifexists ::= */
- case 119: /* distinct ::= ALL */
- case 120: /* distinct ::= */
- case 222: /* between_op ::= BETWEEN */
- case 225: /* in_op ::= IN */
+ case 31: /* temp ::= */ yytestcase(yyruleno==31);
+ case 70: /* autoinc ::= */ yytestcase(yyruleno==70);
+ case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84);
+ case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
+ case 97: /* defer_subclause_opt ::= */ yytestcase(yyruleno==97);
+ case 108: /* ifexists ::= */ yytestcase(yyruleno==108);
+ case 119: /* distinct ::= ALL */ yytestcase(yyruleno==119);
+ case 120: /* distinct ::= */ yytestcase(yyruleno==120);
+ case 222: /* between_op ::= BETWEEN */ yytestcase(yyruleno==222);
+ case 225: /* in_op ::= IN */ yytestcase(yyruleno==225);
{yygotominor.yy194 = 0;}
break;
case 29: /* ifnotexists ::= IF NOT EXISTS */
- case 30: /* temp ::= TEMP */
- case 71: /* autoinc ::= AUTOINCR */
- case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
- case 107: /* ifexists ::= IF EXISTS */
- case 118: /* distinct ::= DISTINCT */
- case 223: /* between_op ::= NOT BETWEEN */
- case 226: /* in_op ::= NOT IN */
+ case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
+ case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71);
+ case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
+ case 107: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==107);
+ case 118: /* distinct ::= DISTINCT */ yytestcase(yyruleno==118);
+ case 223: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==223);
+ case 226: /* in_op ::= NOT IN */ yytestcase(yyruleno==226);
{yygotominor.yy194 = 1;}
break;
case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
{
@@ -88418,28 +88245,28 @@
yygotominor.yy0 = yymsp[0].minor.yy0;
}
break;
case 38: /* id ::= ID */
- case 39: /* id ::= INDEXED */
- case 40: /* ids ::= ID|STRING */
- case 41: /* nm ::= id */
- case 42: /* nm ::= STRING */
- case 43: /* nm ::= JOIN_KW */
- case 46: /* typetoken ::= typename */
- case 49: /* typename ::= ids */
- case 126: /* as ::= AS nm */
- case 127: /* as ::= ids */
- case 137: /* dbnm ::= DOT nm */
- case 146: /* indexed_opt ::= INDEXED BY nm */
- case 251: /* collate ::= COLLATE ids */
- case 260: /* nmnum ::= plus_num */
- case 261: /* nmnum ::= nm */
- case 262: /* nmnum ::= ON */
- case 263: /* nmnum ::= DELETE */
- case 264: /* nmnum ::= DEFAULT */
- case 265: /* plus_num ::= plus_opt number */
- case 266: /* minus_num ::= MINUS number */
- case 267: /* number ::= INTEGER|FLOAT */
+ case 39: /* id ::= INDEXED */ yytestcase(yyruleno==39);
+ case 40: /* ids ::= ID|STRING */ yytestcase(yyruleno==40);
+ case 41: /* nm ::= id */ yytestcase(yyruleno==41);
+ case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
+ case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
+ case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
+ case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
+ case 126: /* as ::= AS nm */ yytestcase(yyruleno==126);
+ case 127: /* as ::= ids */ yytestcase(yyruleno==127);
+ case 137: /* dbnm ::= DOT nm */ yytestcase(yyruleno==137);
+ case 146: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==146);
+ case 251: /* collate ::= COLLATE ids */ yytestcase(yyruleno==251);
+ case 260: /* nmnum ::= plus_num */ yytestcase(yyruleno==260);
+ case 261: /* nmnum ::= nm */ yytestcase(yyruleno==261);
+ case 262: /* nmnum ::= ON */ yytestcase(yyruleno==262);
+ case 263: /* nmnum ::= DELETE */ yytestcase(yyruleno==263);
+ case 264: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==264);
+ case 265: /* plus_num ::= plus_opt number */ yytestcase(yyruleno==265);
+ case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266);
+ case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267);
{yygotominor.yy0 = yymsp[0].minor.yy0;}
break;
case 45: /* type ::= typetoken */
{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy0);}
@@ -88459,9 +88286,9 @@
case 50: /* typename ::= typename ids */
{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 57: /* ccons ::= DEFAULT term */
- case 59: /* ccons ::= DEFAULT PLUS term */
+ case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59);
{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy190);}
break;
case 58: /* ccons ::= DEFAULT LP expr RP */
{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy190);}
@@ -88533,14 +88360,14 @@
case 81: /* refact ::= RESTRICT */
{ yygotominor.yy194 = OE_Restrict; }
break;
case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- case 83: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- case 98: /* defer_subclause_opt ::= defer_subclause */
- case 100: /* onconf ::= ON CONFLICT resolvetype */
- case 102: /* orconf ::= OR resolvetype */
- case 103: /* resolvetype ::= raisetype */
- case 175: /* insert_cmd ::= INSERT orconf */
+ case 83: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83);
+ case 98: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==98);
+ case 100: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==100);
+ case 102: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==102);
+ case 103: /* resolvetype ::= raisetype */ yytestcase(yyruleno==103);
+ case 175: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==175);
{yygotominor.yy194 = yymsp[0].minor.yy194;}
break;
case 87: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
@@ -88563,16 +88390,16 @@
sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy194);
}
break;
case 99: /* onconf ::= */
- case 101: /* orconf ::= */
+ case 101: /* orconf ::= */ yytestcase(yyruleno==101);
{yygotominor.yy194 = OE_Default;}
break;
case 104: /* resolvetype ::= IGNORE */
{yygotominor.yy194 = OE_Ignore;}
break;
case 105: /* resolvetype ::= REPLACE */
- case 176: /* insert_cmd ::= REPLACE */
+ case 176: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==176);
{yygotominor.yy194 = OE_Replace;}
break;
case 106: /* cmd ::= DROP TABLE ifexists fullname */
{
@@ -88618,16 +88445,16 @@
yygotominor.yy243 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy148,yymsp[-5].minor.yy185,yymsp[-4].minor.yy72,yymsp[-3].minor.yy148,yymsp[-2].minor.yy72,yymsp[-1].minor.yy148,yymsp[-7].minor.yy194,yymsp[0].minor.yy354.pLimit,yymsp[0].minor.yy354.pOffset);
}
break;
case 121: /* sclp ::= selcollist COMMA */
- case 247: /* idxlist_opt ::= LP idxlist RP */
+ case 247: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==247);
{yygotominor.yy148 = yymsp[-1].minor.yy148;}
break;
case 122: /* sclp ::= */
- case 150: /* orderby_opt ::= */
- case 158: /* groupby_opt ::= */
- case 240: /* exprlist ::= */
- case 246: /* idxlist_opt ::= */
+ case 150: /* orderby_opt ::= */ yytestcase(yyruleno==150);
+ case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158);
+ case 240: /* exprlist ::= */ yytestcase(yyruleno==240);
+ case 246: /* idxlist_opt ::= */ yytestcase(yyruleno==246);
{yygotominor.yy148 = 0;}
break;
case 123: /* selcollist ::= sclp expr as */
{
@@ -88664,9 +88491,9 @@
break;
case 131: /* stl_prefix ::= seltablist joinop */
{
yygotominor.yy185 = yymsp[-1].minor.yy185;
- if( yygotominor.yy185 && yygotominor.yy185->nSrc>0 ) yygotominor.yy185->a[yygotominor.yy185->nSrc-1].jointype = (u8)yymsp[0].minor.yy194;
+ if( ALWAYS(yygotominor.yy185 && yygotominor.yy185->nSrc>0) ) yygotominor.yy185->a[yygotominor.yy185->nSrc-1].jointype = (u8)yymsp[0].minor.yy194;
}
break;
case 132: /* stl_prefix ::= */
{yygotominor.yy185 = 0;}
@@ -88683,9 +88510,11 @@
}
break;
case 135: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
- if( yymsp[-6].minor.yy185==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy72==0 && yymsp[0].minor.yy254==0 ){
+ if( yymsp[-6].minor.yy185==0 ){
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy72);
+ sqlite3IdListDelete(pParse->db, yymsp[0].minor.yy254);
yygotominor.yy185 = yymsp[-4].minor.yy185;
}else{
Select *pSubquery;
sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy185);
@@ -88694,9 +88523,9 @@
}
}
break;
case 136: /* dbnm ::= */
- case 145: /* indexed_opt ::= */
+ case 145: /* indexed_opt ::= */ yytestcase(yyruleno==145);
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
break;
case 138: /* fullname ::= nm dbnm */
{yygotominor.yy185 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
@@ -88713,36 +88542,36 @@
case 142: /* joinop ::= JOIN_KW nm nm JOIN */
{ yygotominor.yy194 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
break;
case 143: /* on_opt ::= ON expr */
- case 154: /* sortitem ::= expr */
- case 161: /* having_opt ::= HAVING expr */
- case 168: /* where_opt ::= WHERE expr */
- case 235: /* case_else ::= ELSE expr */
- case 237: /* case_operand ::= expr */
+ case 154: /* sortitem ::= expr */ yytestcase(yyruleno==154);
+ case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161);
+ case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168);
+ case 235: /* case_else ::= ELSE expr */ yytestcase(yyruleno==235);
+ case 237: /* case_operand ::= expr */ yytestcase(yyruleno==237);
{yygotominor.yy72 = yymsp[0].minor.yy190.pExpr;}
break;
case 144: /* on_opt ::= */
- case 160: /* having_opt ::= */
- case 167: /* where_opt ::= */
- case 236: /* case_else ::= */
- case 238: /* case_operand ::= */
+ case 160: /* having_opt ::= */ yytestcase(yyruleno==160);
+ case 167: /* where_opt ::= */ yytestcase(yyruleno==167);
+ case 236: /* case_else ::= */ yytestcase(yyruleno==236);
+ case 238: /* case_operand ::= */ yytestcase(yyruleno==238);
{yygotominor.yy72 = 0;}
break;
case 147: /* indexed_opt ::= NOT INDEXED */
{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
break;
case 148: /* using_opt ::= USING LP inscollist RP */
- case 180: /* inscollist_opt ::= LP inscollist RP */
+ case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180);
{yygotominor.yy254 = yymsp[-1].minor.yy254;}
break;
case 149: /* using_opt ::= */
- case 179: /* inscollist_opt ::= */
+ case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179);
{yygotominor.yy254 = 0;}
break;
case 151: /* orderby_opt ::= ORDER BY sortlist */
- case 159: /* groupby_opt ::= GROUP BY nexprlist */
- case 239: /* exprlist ::= nexprlist */
+ case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159);
+ case 239: /* exprlist ::= nexprlist */ yytestcase(yyruleno==239);
{yygotominor.yy148 = yymsp[0].minor.yy148;}
break;
case 152: /* sortlist ::= sortlist COMMA sortitem sortorder */
{
@@ -88752,13 +88581,13 @@
break;
case 153: /* sortlist ::= sortitem sortorder */
{
yygotominor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy72);
- if( yygotominor.yy148 && yygotominor.yy148->a ) yygotominor.yy148->a[0].sortOrder = (u8)yymsp[0].minor.yy194;
+ if( yygotominor.yy148 && ALWAYS(yygotominor.yy148->a) ) yygotominor.yy148->a[0].sortOrder = (u8)yymsp[0].minor.yy194;
}
break;
case 155: /* sortorder ::= ASC */
- case 157: /* sortorder ::= */
+ case 157: /* sortorder ::= */ yytestcase(yyruleno==157);
{yygotominor.yy194 = SQLITE_SO_ASC;}
break;
case 156: /* sortorder ::= DESC */
{yygotominor.yy194 = SQLITE_SO_DESC;}
@@ -88809,13 +88638,13 @@
case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
{sqlite3Insert(pParse, yymsp[-3].minor.yy185, 0, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy194);}
break;
case 177: /* itemlist ::= itemlist COMMA expr */
- case 241: /* nexprlist ::= nexprlist COMMA expr */
+ case 241: /* nexprlist ::= nexprlist COMMA expr */ yytestcase(yyruleno==241);
{yygotominor.yy148 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);}
break;
case 178: /* itemlist ::= expr */
- case 242: /* nexprlist ::= expr */
+ case 242: /* nexprlist ::= expr */ yytestcase(yyruleno==242);
{yygotominor.yy148 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr);}
break;
case 181: /* inscollist ::= inscollist COMMA nm */
{yygotominor.yy254 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);}
@@ -88823,21 +88652,21 @@
case 182: /* inscollist ::= nm */
{yygotominor.yy254 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
break;
case 183: /* expr ::= term */
- case 211: /* escape ::= ESCAPE expr */
+ case 211: /* escape ::= ESCAPE expr */ yytestcase(yyruleno==211);
{yygotominor.yy190 = yymsp[0].minor.yy190;}
break;
case 184: /* expr ::= LP expr RP */
{yygotominor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr; spanSet(&yygotominor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
break;
case 185: /* term ::= NULL */
- case 190: /* term ::= INTEGER|FLOAT|BLOB */
- case 191: /* term ::= STRING */
+ case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190);
+ case 191: /* term ::= STRING */ yytestcase(yyruleno==191);
{spanExpr(&yygotominor.yy190, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
break;
case 186: /* expr ::= id */
- case 187: /* expr ::= JOIN_KW */
+ case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187);
{spanExpr(&yygotominor.yy190, pParse, TK_ID, &yymsp[0].minor.yy0);}
break;
case 188: /* expr ::= nm DOT nm */
{
@@ -88893,9 +88722,9 @@
}
break;
case 196: /* expr ::= ID LP distinct exprlist RP */
{
- if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>SQLITE_MAX_FUNCTION_ARG ){
+ if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
}
yygotominor.yy190.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0);
spanSet(&yygotominor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
@@ -88921,23 +88750,23 @@
spanSet(&yygotominor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
break;
case 199: /* expr ::= expr AND expr */
- case 200: /* expr ::= expr OR expr */
- case 201: /* expr ::= expr LT|GT|GE|LE expr */
- case 202: /* expr ::= expr EQ|NE expr */
- case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- case 204: /* expr ::= expr PLUS|MINUS expr */
- case 205: /* expr ::= expr STAR|SLASH|REM expr */
- case 206: /* expr ::= expr CONCAT expr */
+ case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200);
+ case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201);
+ case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202);
+ case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203);
+ case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204);
+ case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205);
+ case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206);
{spanBinaryExpr(&yygotominor.yy190,pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);}
break;
case 207: /* likeop ::= LIKE_KW */
- case 209: /* likeop ::= MATCH */
+ case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209);
{yygotominor.yy392.eOperator = yymsp[0].minor.yy0; yygotominor.yy392.not = 0;}
break;
case 208: /* likeop ::= NOT LIKE_KW */
- case 210: /* likeop ::= NOT MATCH */
+ case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210);
{yygotominor.yy392.eOperator = yymsp[0].minor.yy0; yygotominor.yy392.not = 1;}
break;
case 212: /* escape ::= */
{memset(&yygotominor.yy190,0,sizeof(yygotominor.yy190));}
@@ -88969,9 +88798,9 @@
case 217: /* expr ::= expr IS NOT NULL */
{spanUnaryPostfix(&yygotominor.yy190,pParse,TK_NOTNULL,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy0);}
break;
case 218: /* expr ::= NOT expr */
- case 219: /* expr ::= BITNOT expr */
+ case 219: /* expr ::= BITNOT expr */ yytestcase(yyruleno==219);
{spanUnaryPrefix(&yygotominor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);}
break;
case 220: /* expr ::= MINUS expr */
{spanUnaryPrefix(&yygotominor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);}
@@ -89099,9 +88928,9 @@
&yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy194);
}
break;
case 244: /* uniqueflag ::= UNIQUE */
- case 293: /* raisetype ::= ABORT */
+ case 293: /* raisetype ::= ABORT */ yytestcase(yyruleno==293);
{yygotominor.yy194 = OE_Abort;}
break;
case 245: /* uniqueflag ::= */
{yygotominor.yy194 = OE_None;}
@@ -89138,9 +88967,9 @@
case 252: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite3DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);}
break;
case 253: /* cmd ::= VACUUM */
- case 254: /* cmd ::= VACUUM nm */
+ case 254: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==254);
{sqlite3Vacuum(pParse);}
break;
case 255: /* cmd ::= PRAGMA nm dbnm */
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
@@ -89171,9 +89000,9 @@
yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
}
break;
case 272: /* trigger_time ::= BEFORE */
- case 275: /* trigger_time ::= */
+ case 275: /* trigger_time ::= */ yytestcase(yyruleno==275);
{ yygotominor.yy194 = TK_BEFORE; }
break;
case 273: /* trigger_time ::= AFTER */
{ yygotominor.yy194 = TK_AFTER; }
@@ -89181,20 +89010,20 @@
case 274: /* trigger_time ::= INSTEAD OF */
{ yygotominor.yy194 = TK_INSTEAD;}
break;
case 276: /* trigger_event ::= DELETE|INSERT */
- case 277: /* trigger_event ::= UPDATE */
+ case 277: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==277);
{yygotominor.yy332.a = yymsp[0].major; yygotominor.yy332.b = 0;}
break;
case 278: /* trigger_event ::= UPDATE OF inscollist */
{yygotominor.yy332.a = TK_UPDATE; yygotominor.yy332.b = yymsp[0].minor.yy254;}
break;
case 281: /* when_clause ::= */
- case 298: /* key_opt ::= */
+ case 298: /* key_opt ::= */ yytestcase(yyruleno==298);
{ yygotominor.yy72 = 0; }
break;
case 282: /* when_clause ::= WHEN expr */
- case 299: /* key_opt ::= KEY expr */
+ case 299: /* key_opt ::= KEY expr */ yytestcase(yyruleno==299);
{ yygotominor.yy72 = yymsp[0].minor.yy190.pExpr; }
break;
case 283: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
@@ -89309,11 +89138,52 @@
case 316: /* vtabarg ::= */
{sqlite3VtabArgInit(pParse);}
break;
case 318: /* vtabargtoken ::= ANY */
- case 319: /* vtabargtoken ::= lp anylist RP */
- case 320: /* lp ::= LP */
+ case 319: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==319);
+ case 320: /* lp ::= LP */ yytestcase(yyruleno==320);
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
+ break;
+ default:
+ /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
+ /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
+ /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
+ /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);
+ /* (4) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==4);
+ /* (10) trans_opt ::= */ yytestcase(yyruleno==10);
+ /* (11) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==11);
+ /* (12) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==12);
+ /* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20);
+ /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
+ /* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25);
+ /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
+ /* (35) columnlist ::= column */ yytestcase(yyruleno==35);
+ /* (44) type ::= */ yytestcase(yyruleno==44);
+ /* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
+ /* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
+ /* (53) carglist ::= carglist carg */ yytestcase(yyruleno==53);
+ /* (54) carglist ::= */ yytestcase(yyruleno==54);
+ /* (55) carg ::= CONSTRAINT nm ccons */ yytestcase(yyruleno==55);
+ /* (56) carg ::= ccons */ yytestcase(yyruleno==56);
+ /* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62);
+ /* (89) conslist ::= conslist COMMA tcons */ yytestcase(yyruleno==89);
+ /* (90) conslist ::= conslist tcons */ yytestcase(yyruleno==90);
+ /* (91) conslist ::= tcons */ yytestcase(yyruleno==91);
+ /* (92) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==92);
+ /* (268) plus_opt ::= PLUS */ yytestcase(yyruleno==268);
+ /* (269) plus_opt ::= */ yytestcase(yyruleno==269);
+ /* (279) foreach_clause ::= */ yytestcase(yyruleno==279);
+ /* (280) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==280);
+ /* (300) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==300);
+ /* (301) database_kw_opt ::= */ yytestcase(yyruleno==301);
+ /* (309) kwcolumn_opt ::= */ yytestcase(yyruleno==309);
+ /* (310) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==310);
+ /* (314) vtabarglist ::= vtabarg */ yytestcase(yyruleno==314);
+ /* (315) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==315);
+ /* (317) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==317);
+ /* (321) anylist ::= */ yytestcase(yyruleno==321);
+ /* (322) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==322);
+ /* (323) anylist ::= anylist ANY */ yytestcase(yyruleno==323);
break;
};
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
@@ -89344,8 +89214,9 @@
/*
** The following code executes when the parse fails
*/
+#ifndef YYNOERRORRECOVERY
static void yy_parse_failed(
yyParser *yypParser /* The parser */
){
sqlite3ParserARG_FETCH;
@@ -89358,8 +89229,9 @@
/* Here code is inserted which will be executed whenever the
** parser fails */
sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
+#endif /* YYNOERRORRECOVERY */
/*
** The following code executes when a syntax error first occurs.
*/
@@ -89528,8 +89400,20 @@
}
}
yypParser->yyerrcnt = 3;
yyerrorhit = 1;
+#elif defined(YYNOERRORRECOVERY)
+ /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
+ ** do any kind of error recovery. Instead, simply invoke the syntax
+ ** error routine and continue going as if nothing had happened.
+ **
+ ** Applications can set this macro (for example inside %include) if
+ ** they intend to abandon the parse upon the first syntax error seen.
+ */
+ yy_syntax_error(yypParser,yymajor,yyminorunion);
+ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
+ yymajor = YYNOCODE;
+
#else /* YYERRORSYMBOL is not defined */
/* This is what we do if the grammar does not define ERROR:
**
** * Report an error message, and throw away the input token.
@@ -89572,9 +89456,9 @@
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.158 2009/05/28 01:00:55 drh Exp $
+** $Id: tokenize.c,v 1.161 2009/06/17 01:17:13 drh Exp $
*/
/*
** The charMap() macro maps alphabetic characters into their
@@ -89625,9 +89509,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.37 2009/02/01 00:00:46 drh Exp $
+** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.38 2009/06/09 14:27:41 drh 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.
@@ -89760,127 +89644,127 @@
(charMap(z[n-1])*3) ^
n) % 127;
for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){
if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){
- testcase( i==0 ); /* TK_REINDEX */
- testcase( i==1 ); /* TK_INDEXED */
- testcase( i==2 ); /* TK_INDEX */
- testcase( i==3 ); /* TK_DESC */
- testcase( i==4 ); /* TK_ESCAPE */
- testcase( i==5 ); /* TK_EACH */
- testcase( i==6 ); /* TK_CHECK */
- testcase( i==7 ); /* TK_KEY */
- testcase( i==8 ); /* TK_BEFORE */
- testcase( i==9 ); /* TK_FOREIGN */
- testcase( i==10 ); /* TK_FOR */
- testcase( i==11 ); /* TK_IGNORE */
- testcase( i==12 ); /* TK_LIKE_KW */
- testcase( i==13 ); /* TK_EXPLAIN */
- testcase( i==14 ); /* TK_INSTEAD */
- testcase( i==15 ); /* TK_ADD */
- testcase( i==16 ); /* TK_DATABASE */
- testcase( i==17 ); /* TK_AS */
- testcase( i==18 ); /* TK_SELECT */
- testcase( i==19 ); /* TK_TABLE */
- testcase( i==20 ); /* TK_JOIN_KW */
- testcase( i==21 ); /* TK_THEN */
- testcase( i==22 ); /* TK_END */
- testcase( i==23 ); /* TK_DEFERRABLE */
- testcase( i==24 ); /* TK_ELSE */
- testcase( i==25 ); /* TK_EXCEPT */
- testcase( i==26 ); /* TK_TRANSACTION */
- testcase( i==27 ); /* TK_ON */
- testcase( i==28 ); /* TK_JOIN_KW */
- testcase( i==29 ); /* TK_ALTER */
- testcase( i==30 ); /* TK_RAISE */
- testcase( i==31 ); /* TK_EXCLUSIVE */
- testcase( i==32 ); /* TK_EXISTS */
- testcase( i==33 ); /* TK_SAVEPOINT */
- testcase( i==34 ); /* TK_INTERSECT */
- testcase( i==35 ); /* TK_TRIGGER */
- testcase( i==36 ); /* TK_REFERENCES */
- testcase( i==37 ); /* TK_CONSTRAINT */
- testcase( i==38 ); /* TK_INTO */
- testcase( i==39 ); /* TK_OFFSET */
- testcase( i==40 ); /* TK_OF */
- testcase( i==41 ); /* TK_SET */
- testcase( i==42 ); /* TK_TEMP */
- testcase( i==43 ); /* TK_TEMP */
- testcase( i==44 ); /* TK_OR */
- testcase( i==45 ); /* TK_UNIQUE */
- testcase( i==46 ); /* TK_QUERY */
- testcase( i==47 ); /* TK_ATTACH */
- testcase( i==48 ); /* TK_HAVING */
- testcase( i==49 ); /* TK_GROUP */
- testcase( i==50 ); /* TK_UPDATE */
- testcase( i==51 ); /* TK_BEGIN */
- testcase( i==52 ); /* TK_JOIN_KW */
- testcase( i==53 ); /* TK_RELEASE */
- testcase( i==54 ); /* TK_BETWEEN */
- testcase( i==55 ); /* TK_NOTNULL */
- testcase( i==56 ); /* TK_NOT */
- testcase( i==57 ); /* TK_NULL */
- testcase( i==58 ); /* TK_LIKE_KW */
- testcase( i==59 ); /* TK_CASCADE */
- testcase( i==60 ); /* TK_ASC */
- testcase( i==61 ); /* TK_DELETE */
- testcase( i==62 ); /* TK_CASE */
- testcase( i==63 ); /* TK_COLLATE */
- testcase( i==64 ); /* TK_CREATE */
- testcase( i==65 ); /* TK_CTIME_KW */
- testcase( i==66 ); /* TK_DETACH */
- testcase( i==67 ); /* TK_IMMEDIATE */
- testcase( i==68 ); /* TK_JOIN */
- testcase( i==69 ); /* TK_INSERT */
- testcase( i==70 ); /* TK_MATCH */
- testcase( i==71 ); /* TK_PLAN */
- testcase( i==72 ); /* TK_ANALYZE */
- testcase( i==73 ); /* TK_PRAGMA */
- testcase( i==74 ); /* TK_ABORT */
- testcase( i==75 ); /* TK_VALUES */
- testcase( i==76 ); /* TK_VIRTUAL */
- testcase( i==77 ); /* TK_LIMIT */
- testcase( i==78 ); /* TK_WHEN */
- testcase( i==79 ); /* TK_WHERE */
- testcase( i==80 ); /* TK_RENAME */
- testcase( i==81 ); /* TK_AFTER */
- testcase( i==82 ); /* TK_REPLACE */
- testcase( i==83 ); /* TK_AND */
- testcase( i==84 ); /* TK_DEFAULT */
- testcase( i==85 ); /* TK_AUTOINCR */
- testcase( i==86 ); /* TK_TO */
- testcase( i==87 ); /* TK_IN */
- testcase( i==88 ); /* TK_CAST */
- testcase( i==89 ); /* TK_COLUMNKW */
- testcase( i==90 ); /* TK_COMMIT */
- testcase( i==91 ); /* TK_CONFLICT */
- testcase( i==92 ); /* TK_JOIN_KW */
- testcase( i==93 ); /* TK_CTIME_KW */
- testcase( i==94 ); /* TK_CTIME_KW */
- testcase( i==95 ); /* TK_PRIMARY */
- testcase( i==96 ); /* TK_DEFERRED */
- testcase( i==97 ); /* TK_DISTINCT */
- testcase( i==98 ); /* TK_IS */
- testcase( i==99 ); /* TK_DROP */
- testcase( i==100 ); /* TK_FAIL */
- testcase( i==101 ); /* TK_FROM */
- testcase( i==102 ); /* TK_JOIN_KW */
- testcase( i==103 ); /* TK_LIKE_KW */
- testcase( i==104 ); /* TK_BY */
- testcase( i==105 ); /* TK_IF */
- testcase( i==106 ); /* TK_ISNULL */
- testcase( i==107 ); /* TK_ORDER */
- testcase( i==108 ); /* TK_RESTRICT */
- testcase( i==109 ); /* TK_JOIN_KW */
- testcase( i==110 ); /* TK_JOIN_KW */
- testcase( i==111 ); /* TK_ROLLBACK */
- testcase( i==112 ); /* TK_ROW */
- testcase( i==113 ); /* TK_UNION */
- testcase( i==114 ); /* TK_USING */
- testcase( i==115 ); /* TK_VACUUM */
- testcase( i==116 ); /* TK_VIEW */
- testcase( i==117 ); /* TK_INITIALLY */
- testcase( i==118 ); /* TK_ALL */
+ testcase( i==0 ); /* REINDEX */
+ testcase( i==1 ); /* INDEXED */
+ testcase( i==2 ); /* INDEX */
+ testcase( i==3 ); /* DESC */
+ testcase( i==4 ); /* ESCAPE */
+ testcase( i==5 ); /* EACH */
+ testcase( i==6 ); /* CHECK */
+ testcase( i==7 ); /* KEY */
+ testcase( i==8 ); /* BEFORE */
+ testcase( i==9 ); /* FOREIGN */
+ testcase( i==10 ); /* FOR */
+ testcase( i==11 ); /* IGNORE */
+ testcase( i==12 ); /* REGEXP */
+ testcase( i==13 ); /* EXPLAIN */
+ testcase( i==14 ); /* INSTEAD */
+ testcase( i==15 ); /* ADD */
+ testcase( i==16 ); /* DATABASE */
+ testcase( i==17 ); /* AS */
+ testcase( i==18 ); /* SELECT */
+ testcase( i==19 ); /* TABLE */
+ testcase( i==20 ); /* LEFT */
+ testcase( i==21 ); /* THEN */
+ testcase( i==22 ); /* END */
+ testcase( i==23 ); /* DEFERRABLE */
+ testcase( i==24 ); /* ELSE */
+ testcase( i==25 ); /* EXCEPT */
+ testcase( i==26 ); /* TRANSACTION */
+ testcase( i==27 ); /* ON */
+ testcase( i==28 ); /* NATURAL */
+ testcase( i==29 ); /* ALTER */
+ testcase( i==30 ); /* RAISE */
+ testcase( i==31 ); /* EXCLUSIVE */
+ testcase( i==32 ); /* EXISTS */
+ testcase( i==33 ); /* SAVEPOINT */
+ testcase( i==34 ); /* INTERSECT */
+ testcase( i==35 ); /* TRIGGER */
+ testcase( i==36 ); /* REFERENCES */
+ testcase( i==37 ); /* CONSTRAINT */
+ testcase( i==38 ); /* INTO */
+ testcase( i==39 ); /* OFFSET */
+ testcase( i==40 ); /* OF */
+ testcase( i==41 ); /* SET */
+ testcase( i==42 ); /* TEMP */
+ testcase( i==43 ); /* TEMPORARY */
+ testcase( i==44 ); /* OR */
+ testcase( i==45 ); /* UNIQUE */
+ testcase( i==46 ); /* QUERY */
+ testcase( i==47 ); /* ATTACH */
+ testcase( i==48 ); /* HAVING */
+ testcase( i==49 ); /* GROUP */
+ testcase( i==50 ); /* UPDATE */
+ testcase( i==51 ); /* BEGIN */
+ testcase( i==52 ); /* INNER */
+ testcase( i==53 ); /* RELEASE */
+ testcase( i==54 ); /* BETWEEN */
+ testcase( i==55 ); /* NOTNULL */
+ testcase( i==56 ); /* NOT */
+ testcase( i==57 ); /* NULL */
+ testcase( i==58 ); /* LIKE */
+ testcase( i==59 ); /* CASCADE */
+ testcase( i==60 ); /* ASC */
+ testcase( i==61 ); /* DELETE */
+ testcase( i==62 ); /* CASE */
+ testcase( i==63 ); /* COLLATE */
+ testcase( i==64 ); /* CREATE */
+ testcase( i==65 ); /* CURRENT_DATE */
+ testcase( i==66 ); /* DETACH */
+ testcase( i==67 ); /* IMMEDIATE */
+ testcase( i==68 ); /* JOIN */
+ testcase( i==69 ); /* INSERT */
+ testcase( i==70 ); /* MATCH */
+ testcase( i==71 ); /* PLAN */
+ testcase( i==72 ); /* ANALYZE */
+ testcase( i==73 ); /* PRAGMA */
+ testcase( i==74 ); /* ABORT */
+ testcase( i==75 ); /* VALUES */
+ testcase( i==76 ); /* VIRTUAL */
+ testcase( i==77 ); /* LIMIT */
+ testcase( i==78 ); /* WHEN */
+ testcase( i==79 ); /* WHERE */
+ testcase( i==80 ); /* RENAME */
+ testcase( i==81 ); /* AFTER */
+ testcase( i==82 ); /* REPLACE */
+ testcase( i==83 ); /* AND */
+ testcase( i==84 ); /* DEFAULT */
+ testcase( i==85 ); /* AUTOINCREMENT */
+ testcase( i==86 ); /* TO */
+ testcase( i==87 ); /* IN */
+ testcase( i==88 ); /* CAST */
+ testcase( i==89 ); /* COLUMN */
+ testcase( i==90 ); /* COMMIT */
+ testcase( i==91 ); /* CONFLICT */
+ testcase( i==92 ); /* CROSS */
+ testcase( i==93 ); /* CURRENT_TIMESTAMP */
+ testcase( i==94 ); /* CURRENT_TIME */
+ testcase( i==95 ); /* PRIMARY */
+ testcase( i==96 ); /* DEFERRED */
+ testcase( i==97 ); /* DISTINCT */
+ testcase( i==98 ); /* IS */
+ testcase( i==99 ); /* DROP */
+ testcase( i==100 ); /* FAIL */
+ testcase( i==101 ); /* FROM */
+ testcase( i==102 ); /* FULL */
+ testcase( i==103 ); /* GLOB */
+ testcase( i==104 ); /* BY */
+ testcase( i==105 ); /* IF */
+ testcase( i==106 ); /* ISNULL */
+ testcase( i==107 ); /* ORDER */
+ testcase( i==108 ); /* RESTRICT */
+ testcase( i==109 ); /* OUTER */
+ testcase( i==110 ); /* RIGHT */
+ testcase( i==111 ); /* ROLLBACK */
+ testcase( i==112 ); /* ROW */
+ testcase( i==113 ); /* UNION */
+ testcase( i==114 ); /* USING */
+ testcase( i==115 ); /* VACUUM */
+ testcase( i==116 ); /* VIEW */
+ testcase( i==117 ); /* INITIALLY */
+ testcase( i==118 ); /* ALL */
return aCode[i];
}
}
return TK_ID;
@@ -89948,8 +89832,13 @@
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *z, int *tokenType){
int i, c;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
+ testcase( z[0]==' ' );
+ testcase( z[0]=='\t' );
+ testcase( z[0]=='\n' );
+ testcase( z[0]=='\f' );
+ testcase( z[0]=='\r' );
for(i=1; sqlite3Isspace(z[i]); i++){}
*tokenType = TK_SPACE;
return i;
}
@@ -90060,8 +89949,11 @@
case '`':
case '\'':
case '"': {
int delim = z[0];
+ testcase( delim=='`' );
+ testcase( delim=='\'' );
+ testcase( delim=='"' );
for(i=1; (c=z[i])!=0; i++){
if( c==delim ){
if( z[i+1]==delim ){
i++;
@@ -90093,8 +89985,12 @@
** number that begins with ".". Fall thru into the next case */
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
+ testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
+ testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' );
+ testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' );
+ testcase( z[0]=='9' );
*tokenType = TK_INTEGER;
for(i=0; sqlite3Isdigit(z[i]); i++){}
#ifndef SQLITE_OMIT_FLOATING_POINT
if( z[i]=='.' ){
@@ -90144,8 +90040,9 @@
#endif
case '@': /* For compatibility with MS SQL Server */
case ':': {
int n = 0;
+ testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' );
*tokenType = TK_VARIABLE;
for(i=1; (c=z[i])!=0; i++){
if( IdChar(c) ){
n++;
@@ -90171,8 +90068,9 @@
return i;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case 'x': case 'X': {
+ testcase( z[0]=='x' ); testcase( z[0]=='X' );
if( z[1]=='\'' ){
*tokenType = TK_BLOB;
for(i=2; (c=z[i])!=0 && c!='\''; i++){
if( !sqlite3Isxdigit(c) ){
@@ -90249,10 +90147,10 @@
}
switch( tokenType ){
case TK_SPACE: {
if( db->u1.isInterrupted ){
- pParse->rc = SQLITE_INTERRUPT;
- sqlite3SetString(pzErrMsg, db, "interrupt");
+ sqlite3ErrorMsg(pParse, "interrupt");
+ pParse->rc = SQLITE_INTERRUPT;
goto abort_parse;
}
break;
}
@@ -90297,14 +90195,11 @@
}
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
sqlite3SetString(&pParse->zErrMsg, db, "%s", sqlite3ErrStr(pParse->rc));
}
+ assert( pzErrMsg!=0 );
if( pParse->zErrMsg ){
- if( *pzErrMsg==0 ){
- *pzErrMsg = pParse->zErrMsg;
- }else{
- sqlite3DbFree(db, pParse->zErrMsg);
- }
+ *pzErrMsg = pParse->zErrMsg;
pParse->zErrMsg = 0;
nErr++;
}
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
@@ -90337,9 +90232,9 @@
Table *p = pParse->pZombieTab;
pParse->pZombieTab = p->pNextZombie;
sqlite3DeleteTable(p);
}
- if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
+ if( nErr>0 && pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
}
return nErr;
}
@@ -90640,9 +90535,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.555 2009/06/01 16:53:10 shane Exp $
+** $Id: main.c,v 1.558 2009/06/19 14:06:03 drh Exp $
*/
#ifdef SQLITE_ENABLE_FTS3
/************** Include fts3.h in the middle of main.c ***********************/
@@ -91062,9 +90957,8 @@
}else{
/* The heap pointer is not NULL, then install one of the
** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
** ENABLE_MEMSYS5 is defined, return an error.
- ** the default case and return an error.
*/
#ifdef SQLITE_ENABLE_MEMSYS3
sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
#endif
@@ -91296,15 +91190,8 @@
if( !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE;
}
sqlite3_mutex_enter(db->mutex);
-
-#ifdef SQLITE_SSE
- {
- extern void sqlite3SseCleanup(sqlite3*);
- sqlite3SseCleanup(db);
- }
-#endif
sqlite3ResetInternalSchema(db, 0);
/* If a transaction is open, the ResetInternalSchema() call above