1 Allocate a new page if it easy and convenient to do so.
** Otherwise return NULL.
@@ -7677,7 +7759,7 @@ struct sqlite3_rtree_geometry {
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This is the header file for the generic hash-table implemenation
+** This is the header file for the generic hash-table implementation
** used in SQLite.
*/
#ifndef _SQLITE_HASH_H_
@@ -8177,6 +8259,11 @@ struct BusyHandler {
*/
#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
+/*
+** Determine if the argument is a power of two
+*/
+#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
+
/*
** The following value as a destructor means to use sqlite3DbFree().
** The sqlite3DbFree() routine requires two parameters instead of the
@@ -8263,6 +8350,7 @@ typedef struct Parse Parse;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
+typedef struct SelectDest SelectDest;
typedef struct SrcList SrcList;
typedef struct StrAccum StrAccum;
typedef struct Table Table;
@@ -8359,6 +8447,9 @@ SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
+#endif
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
@@ -8402,6 +8493,8 @@ SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree*, int);
SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
+
/*
** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
** should be one of the following values. The integer values are assigned
@@ -8869,7 +8962,7 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\
-/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
+/* 8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x24,\
/* 16 */ 0x00, 0x00, 0x00, 0x24, 0x04, 0x05, 0x04, 0x00,\
/* 24 */ 0x00, 0x01, 0x01, 0x05, 0x05, 0x00, 0x00, 0x00,\
/* 32 */ 0x02, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,\
@@ -8916,7 +9009,7 @@ SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
-SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
+SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
@@ -9106,11 +9199,14 @@ SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
-SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
-SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
-SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
+SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
+SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
+SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager);
+#endif
+
#ifdef SQLITE_ENABLE_ZIPVFS
SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
#endif
@@ -9128,6 +9224,7 @@ SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
SQLITE_PRIVATE void sqlite3PagerClearCache(Pager *);
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
/* Functions used to truncate the database file. */
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
@@ -9825,6 +9922,7 @@ struct sqlite3 {
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
int errCode; /* Most recent error code (SQLITE_*) */
int errMask; /* & result codes with this before returning */
+ u16 dbOptFlags; /* Flags to enable/disable optimizations */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
u8 mallocFailed; /* True if we have seen a malloc failure */
@@ -9929,48 +10027,60 @@ struct sqlite3 {
/*
** Possible values for the sqlite3.flags.
*/
-#define SQLITE_VdbeTrace 0x00000100 /* True to trace VDBE execution */
-#define SQLITE_InternChanges 0x00000200 /* Uncommitted Hash table changes */
-#define SQLITE_FullColNames 0x00000400 /* Show full column names on SELECT */
-#define SQLITE_ShortColNames 0x00000800 /* Show short columns names */
-#define SQLITE_CountRows 0x00001000 /* Count rows changed by INSERT, */
+#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */
+#define SQLITE_InternChanges 0x00000002 /* Uncommitted Hash table changes */
+#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
+#define SQLITE_ShortColNames 0x00000008 /* Show short columns names */
+#define SQLITE_CountRows 0x00000010 /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */
/* the count using a callback. */
-#define SQLITE_NullCallback 0x00002000 /* Invoke the callback once if the */
+#define SQLITE_NullCallback 0x00000020 /* Invoke the callback once if the */
/* result set is empty */
-#define SQLITE_SqlTrace 0x00004000 /* Debug print SQL as it executes */
-#define SQLITE_VdbeListing 0x00008000 /* Debug listings of VDBE programs */
-#define SQLITE_WriteSchema 0x00010000 /* OK to update SQLITE_MASTER */
- /* 0x00020000 Unused */
-#define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */
-#define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */
-#define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */
-#define SQLITE_FullFSync 0x00200000 /* Use full fsync on the backend */
-#define SQLITE_CkptFullFSync 0x00400000 /* Use full fsync for checkpoint */
-#define SQLITE_RecoveryMode 0x00800000 /* Ignore schema errors */
-#define SQLITE_ReverseOrder 0x01000000 /* Reverse unordered SELECTs */
-#define SQLITE_RecTriggers 0x02000000 /* Enable recursive triggers */
-#define SQLITE_ForeignKeys 0x04000000 /* Enforce foreign key constraints */
-#define SQLITE_AutoIndex 0x08000000 /* Enable automatic indexes */
-#define SQLITE_PreferBuiltin 0x10000000 /* Preference to built-in funcs */
-#define SQLITE_LoadExtension 0x20000000 /* Enable load_extension */
-#define SQLITE_EnableTrigger 0x40000000 /* True to enable triggers */
+#define SQLITE_SqlTrace 0x00000040 /* Debug print SQL as it executes */
+#define SQLITE_VdbeListing 0x00000080 /* Debug listings of VDBE programs */
+#define SQLITE_WriteSchema 0x00000100 /* OK to update SQLITE_MASTER */
+#define SQLITE_VdbeAddopTrace 0x00000200 /* Trace sqlite3VdbeAddOp() calls */
+#define SQLITE_IgnoreChecks 0x00000400 /* Do not enforce check constraints */
+#define SQLITE_ReadUncommitted 0x0000800 /* For shared-cache mode */
+#define SQLITE_LegacyFileFmt 0x00001000 /* Create new databases in format 1 */
+#define SQLITE_FullFSync 0x00002000 /* Use full fsync on the backend */
+#define SQLITE_CkptFullFSync 0x00004000 /* Use full fsync for checkpoint */
+#define SQLITE_RecoveryMode 0x00008000 /* Ignore schema errors */
+#define SQLITE_ReverseOrder 0x00010000 /* Reverse unordered SELECTs */
+#define SQLITE_RecTriggers 0x00020000 /* Enable recursive triggers */
+#define SQLITE_ForeignKeys 0x00040000 /* Enforce foreign key constraints */
+#define SQLITE_AutoIndex 0x00080000 /* Enable automatic indexes */
+#define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */
+#define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */
+#define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */
/*
-** Bits of the sqlite3.flags field that are used by the
-** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface.
-** These must be the low-order bits of the flags field.
+** Bits of the sqlite3.dbOptFlags field that are used by the
+** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
+** selectively disable various optimizations.
*/
-#define SQLITE_QueryFlattener 0x01 /* Disable query flattening */
-#define SQLITE_ColumnCache 0x02 /* Disable the column cache */
-#define SQLITE_IndexSort 0x04 /* Disable indexes for sorting */
-#define SQLITE_IndexSearch 0x08 /* Disable indexes for searching */
-#define SQLITE_IndexCover 0x10 /* Disable index covering table */
-#define SQLITE_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */
-#define SQLITE_FactorOutConst 0x40 /* Disable factoring out constants */
-#define SQLITE_IdxRealAsInt 0x80 /* Store REAL as INT in indices */
-#define SQLITE_DistinctOpt 0x80 /* DISTINCT using indexes */
-#define SQLITE_OptMask 0xff /* Mask of all disablable opts */
+#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
+#define SQLITE_ColumnCache 0x0002 /* Column cache */
+#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
+#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
+#define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */
+#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
+#define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */
+#define SQLITE_Transitive 0x0200 /* Transitive constraints */
+#define SQLITE_AllOpts 0xffff /* All optimizations */
+
+/*
+** Macros for testing whether or not optimizations are enabled or disabled.
+*/
+#ifndef SQLITE_OMIT_BUILTIN_TEST
+#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0)
+#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0)
+#else
+#define OptimizationDisabled(db, mask) 0
+#define OptimizationEnabled(db, mask) 1
+#endif
/*
** Possible values for the sqlite.magic field.
@@ -10121,32 +10231,22 @@ struct Column {
char *zDflt; /* Original text of the default value */
char *zType; /* Data type for this column */
char *zColl; /* Collating sequence. If NULL, use the default */
- u8 notNull; /* True if there is a NOT NULL constraint */
- u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */
+ u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
char affinity; /* One of the SQLITE_AFF_... values */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- u8 isHidden; /* True if this column is 'hidden' */
-#endif
+ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
+/* Allowed values for Column.colFlags:
+*/
+#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
+#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
+
/*
** A "Collating Sequence" is defined by an instance of the following
** structure. Conceptually, a collating sequence consists of a name and
** a comparison routine that defines the order of that sequence.
**
-** There may two separate implementations of the collation function, one
-** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that
-** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
-** native byte order. When a collation sequence is invoked, SQLite selects
-** the version that will require the least expensive encoding
-** translations, if any.
-**
-** The CollSeq.pUser member variable is an extra parameter that passed in
-** as the first argument to the UTF-8 comparison function, xCmp.
-** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function,
-** xCmp16.
-**
-** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
+** If CollSeq.xCmp is NULL, it means that the
** collating sequence is undefined. Indices built on an undefined
** collating sequence may not be read or written.
*/
@@ -10284,28 +10384,28 @@ struct VTable {
*/
struct Table {
char *zName; /* Name of the table or view */
- int iPKey; /* If not negative, use aCol[iPKey] as the primary key */
- int nCol; /* Number of columns in this table */
Column *aCol; /* Information about each column */
Index *pIndex; /* List of SQL indexes on this table. */
- int tnum; /* Root BTree node for this table (see note above) */
- tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
- u16 nRef; /* Number of pointers to this Table */
- u8 tabFlags; /* Mask of TF_* values */
- u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */
#ifndef SQLITE_OMIT_CHECK
ExprList *pCheck; /* All CHECK constraints */
#endif
+ tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
+ int tnum; /* Root BTree node for this table (see note above) */
+ i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
+ i16 nCol; /* Number of columns in this table */
+ u16 nRef; /* Number of pointers to this Table */
+ u8 tabFlags; /* Mask of TF_* values */
+ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
#ifndef SQLITE_OMIT_ALTERTABLE
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
- VTable *pVTable; /* List of VTable objects. */
int nModuleArg; /* Number of arguments to the module */
char **azModuleArg; /* Text of all module args. [0] is module name */
+ VTable *pVTable; /* List of VTable objects. */
#endif
Trigger *pTrigger; /* List of triggers stored in pSchema */
Schema *pSchema; /* Schema that contains this table */
@@ -10329,7 +10429,7 @@ struct Table {
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
# define IsVirtual(X) (((X)->tabFlags & TF_Virtual)!=0)
-# define IsHiddenColumn(X) ((X)->isHidden)
+# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
#else
# define IsVirtual(X) 0
# define IsHiddenColumn(X) 0
@@ -10480,20 +10580,20 @@ struct UnpackedRecord {
** element.
*/
struct Index {
- char *zName; /* Name of this index */
- int *aiColumn; /* Which columns are used by this index. 1st is 0 */
- tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
- Table *pTable; /* The SQL table being indexed */
- char *zColAff; /* String defining the affinity of each column */
- Index *pNext; /* The next index associated with the same table */
- Schema *pSchema; /* Schema containing this index */
- u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */
- char **azColl; /* Array of collation sequence names for index */
- int nColumn; /* Number of columns in the table used by this index */
- int tnum; /* Page containing root of this index in database file */
- u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
- u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */
- u8 bUnordered; /* Use this index for == or IN queries only */
+ char *zName; /* Name of this index */
+ int *aiColumn; /* Which columns are used by this index. 1st is 0 */
+ tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
+ Table *pTable; /* The SQL table being indexed */
+ char *zColAff; /* String defining the affinity of each column */
+ Index *pNext; /* The next index associated with the same table */
+ Schema *pSchema; /* Schema containing this index */
+ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */
+ char **azColl; /* Array of collation sequence names for index */
+ int tnum; /* DB Page containing root of this index */
+ u16 nColumn; /* Number of columns in table used by this index */
+ u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
+ unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
+ unsigned bUnordered:1; /* Use this index for == or IN queries only */
#ifdef SQLITE_ENABLE_STAT3
int nSample; /* Number of elements in aSample[] */
tRowcnt avgEq; /* Average nEq value for key values not in aSample */
@@ -10674,13 +10774,15 @@ struct Expr {
ExprList *pList; /* Function arguments or in " IN ( IN ()" */
} x;
- CollSeq *pColl; /* The collation type of the column or 0 */
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
** access them will result in a segfault or malfunction.
*********************************************************************/
+#if SQLITE_MAX_EXPR_DEPTH>0
+ int nHeight; /* Height of the tree headed by this node */
+#endif
int iTable; /* TK_COLUMN: cursor number of table holding column
** TK_REGISTER: register number
** TK_TRIGGER: 1 -> new, 0 -> old */
@@ -10694,9 +10796,6 @@ struct Expr {
** TK_AGG_FUNCTION: nesting depth */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
Table *pTab; /* Table for TK_COLUMN expressions. */
-#if SQLITE_MAX_EXPR_DEPTH>0
- int nHeight; /* Height of the tree headed by this node */
-#endif
};
/*
@@ -10710,7 +10809,7 @@ struct Expr {
#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
#define EP_DblQuoted 0x0040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
-#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
+#define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */
#define EP_FixedDest 0x0200 /* Result needed in a specific register */
#define EP_IntValue 0x0400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */
@@ -10768,18 +10867,27 @@ struct Expr {
** list of "ID = expr" items in an UPDATE. A list of expressions can
** also be used as the argument to a function, in which case the a.zName
** field is not used.
+**
+** By default the Expr.zSpan field holds a human-readable description of
+** the expression that is used in the generation of error messages and
+** column labels. In this case, Expr.zSpan is typically the text of a
+** column expression as it exists in a SELECT statement. However, if
+** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
+** of the result column in the form: DATABASE.TABLE.COLUMN. This later
+** form is used for name resolution with nested FROM clauses.
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
int iECursor; /* VDBE Cursor associated with this ExprList */
struct ExprList_item { /* For each expression in the list */
- Expr *pExpr; /* The list of expressions */
- char *zName; /* Token associated with this expression */
- char *zSpan; /* Original text of the expression */
- u8 sortOrder; /* 1 for DESC or 0 for ASC */
- u8 done; /* A flag to indicate when processing is finished */
- u16 iOrderByCol; /* For ORDER BY, column number in result set */
- u16 iAlias; /* Index into Parse.aAlias[] for zName */
+ Expr *pExpr; /* The list of expressions */
+ char *zName; /* Token associated with this expression */
+ char *zSpan; /* Original text of the expression */
+ u8 sortOrder; /* 1 for DESC or 0 for ASC */
+ unsigned done :1; /* A flag to indicate when processing is finished */
+ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
+ u16 iOrderByCol; /* For ORDER BY, column number in result set */
+ u16 iAlias; /* Index into Parse.aAlias[] for zName */
} *a; /* Alloc a power of two greater or equal to nExpr */
};
@@ -10854,6 +10962,7 @@ struct SrcList {
i16 nSrc; /* Number of tables or subqueries in the FROM clause */
i16 nAlloc; /* Number of entries allocated in a[] below */
struct SrcList_item {
+ Schema *pSchema; /* Schema to which this item is fixed */
char *zDatabase; /* Name of database holding this table */
char *zName; /* Name of the table */
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
@@ -10862,8 +10971,9 @@ struct SrcList {
int addrFillSub; /* Address of subroutine to manifest a subquery */
int regReturn; /* Register holding return address of addrFillSub */
u8 jointype; /* Type of join between this able and the previous */
- u8 notIndexed; /* True if there is a NOT INDEXED clause */
- u8 isCorrelated; /* True if sub-query is correlated */
+ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
+ unsigned isCorrelated :1; /* True if sub-query is correlated */
+ unsigned viaCoroutine :1; /* Implemented as a co-routine */
#ifndef SQLITE_OMIT_EXPLAIN
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
#endif
@@ -10904,7 +11014,8 @@ struct SrcList {
*/
struct WherePlan {
u32 wsFlags; /* WHERE_* flags that describe the strategy */
- u32 nEq; /* Number of == constraints */
+ u16 nEq; /* Number of == constraints */
+ u16 nOBSat; /* Number of ORDER BY terms satisfied */
double nRow; /* Estimated number of rows (for EQP) */
union {
Index *pIdx; /* Index when WHERE_INDEXED is true */
@@ -10944,10 +11055,12 @@ struct WhereLevel {
struct InLoop {
int iCur; /* The VDBE cursor used by this IN operator */
int addrInTop; /* Top of the IN loop */
+ u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */
} *aInLoop; /* Information about each nested IN operator */
} in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
} u;
+ double rOptCost; /* "Optimal" cost for this level */
/* The following field is really not part of the current level. But
** we need a place to cache virtual table index information for each
@@ -10980,24 +11093,28 @@ struct WhereLevel {
** into the second half to give some continuity.
*/
struct WhereInfo {
- Parse *pParse; /* Parsing and code generating context */
- u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
- u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */
- u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
- u8 eDistinct;
- SrcList *pTabList; /* List of tables in the join */
- int iTop; /* The very beginning of the WHERE loop */
- int iContinue; /* Jump here to continue with next record */
- int iBreak; /* Jump here to break out of the loop */
- int nLevel; /* Number of nested loop */
- struct WhereClause *pWC; /* Decomposition of the WHERE clause */
- double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
- double nRowOut; /* Estimated number of output rows */
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
+ Parse *pParse; /* Parsing and code generating context */
+ SrcList *pTabList; /* List of tables in the join */
+ u16 nOBSat; /* Number of ORDER BY terms satisfied by indices */
+ u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
+ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
+ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
+ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
+ int iTop; /* The very beginning of the WHERE loop */
+ int iContinue; /* Jump here to continue with next record */
+ int iBreak; /* Jump here to break out of the loop */
+ int nLevel; /* Number of nested loop */
+ struct WhereClause *pWC; /* Decomposition of the WHERE clause */
+ double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
+ double nRowOut; /* Estimated number of output rows */
+ WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
-#define WHERE_DISTINCT_UNIQUE 1
-#define WHERE_DISTINCT_ORDERED 2
+/* Allowed values for WhereInfo.eDistinct and DistinctCtx.eTnctType */
+#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
+#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
+#define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */
+#define WHERE_DISTINCT_UNORDERED 3 /* Duplicates are scattered */
/*
** A NameContext defines a context in which to resolve table and column
@@ -11056,13 +11173,12 @@ struct NameContext {
** as the OP_OpenEphm instruction is coded because not
** enough information about the compound query is known at that point.
** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
-** for the result set. The KeyInfo for addrOpenTran[2] contains collating
+** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
** sequences for the ORDER BY clause.
*/
struct Select {
ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
- char affinity; /* MakeRecord with this affinity for SRT_Set */
u16 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
@@ -11083,14 +11199,16 @@ struct Select {
** Allowed values for Select.selFlags. The "SF" prefix stands for
** "Select Flag".
*/
-#define SF_Distinct 0x01 /* Output should be DISTINCT */
-#define SF_Resolved 0x02 /* Identifiers have been resolved */
-#define SF_Aggregate 0x04 /* Contains aggregate functions */
-#define SF_UsesEphemeral 0x08 /* Uses the OpenEphemeral opcode */
-#define SF_Expanded 0x10 /* sqlite3SelectExpand() called on this */
-#define SF_HasTypeInfo 0x20 /* FROM subqueries have Table metadata */
-#define SF_UseSorter 0x40 /* Sort using a sorter */
-#define SF_Values 0x80 /* Synthesized from VALUES clause */
+#define SF_Distinct 0x0001 /* Output should be DISTINCT */
+#define SF_Resolved 0x0002 /* Identifiers have been resolved */
+#define SF_Aggregate 0x0004 /* Contains aggregate functions */
+#define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */
+#define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */
+#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
+#define SF_UseSorter 0x0040 /* Sort using a sorter */
+#define SF_Values 0x0080 /* Synthesized from VALUES clause */
+#define SF_Materialize 0x0100 /* Force materialization of views */
+#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
/*
@@ -11113,13 +11231,12 @@ struct Select {
#define SRT_Coroutine 10 /* Generate a single row of result */
/*
-** A structure used to customize the behavior of sqlite3Select(). See
-** comments above sqlite3Select() for details.
+** An instance of this object describes where to put of the results of
+** a SELECT statement.
*/
-typedef struct SelectDest SelectDest;
struct SelectDest {
- u8 eDest; /* How to dispose of the results */
- u8 affSdst; /* Affinity used when eDest==SRT_Set */
+ u8 eDest; /* How to dispose of the results. On of SRT_* above. */
+ char affSdst; /* Affinity used when eDest==SRT_Set */
int iSDParm; /* A parameter used by the eDest disposal method */
int iSdst; /* Base register where results are written */
int nSdst; /* Number of registers allocated */
@@ -11320,6 +11437,7 @@ struct AuthContext {
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */
+#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
/*
* Each trigger present in the database schema is stored as an instance of
@@ -11419,6 +11537,7 @@ struct TriggerStep {
typedef struct DbFixer DbFixer;
struct DbFixer {
Parse *pParse; /* The parsing context. Error messages written here */
+ Schema *pSchema; /* Fix items to this schema */
const char *zDb; /* Make sure all objects are contained in this database */
const char *zType; /* Type of the container - used for error messages */
const Token *pName; /* Name of the container - used for error messages */
@@ -11461,6 +11580,7 @@ struct Sqlite3Config {
int bCoreMutex; /* True to enable core mutexing */
int bFullMutex; /* True to enable full mutexing */
int bOpenUri; /* True to interpret filenames as URIs */
+ int bUseCis; /* Use covering indices for full-scans */
int mxStrlen; /* Maximum string length */
int szLookaside; /* Default lookaside buffer size */
int nLookaside; /* Default lookaside buffer count */
@@ -11490,6 +11610,10 @@ struct Sqlite3Config {
void (*xLog)(void*,int,const char*); /* Function for logging */
void *pLogArg; /* First argument to xLog() */
int bLocaltimeFault; /* True to fail localtime() calls */
+#ifdef SQLITE_ENABLE_SQLLOG
+ void(*xSqllog)(void*,sqlite3*,const char*, int);
+ void *pSqllogArg;
+#endif
};
/*
@@ -11777,6 +11901,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse);
# define sqlite3AutoincrementBegin(X)
# define sqlite3AutoincrementEnd(X)
#endif
+SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
@@ -11796,23 +11921,21 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
- Expr*,ExprList*,int,Expr*,Expr*);
+ Expr*,ExprList*,u16,Expr*,Expr*);
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
+SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
#endif
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
-SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
- Parse*,SrcList*,Expr*,ExprList**,ExprList*,u16,int);
+SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
-SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse*, int, int, int);
SQLITE_PRIVATE void sqlite3ExprCachePush(Parse*);
SQLITE_PRIVATE void sqlite3ExprCachePop(Parse*, int);
@@ -11829,6 +11952,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
@@ -11871,7 +11995,7 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
-SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, char*, int);
+SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, int);
SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
@@ -11952,7 +12076,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
SQLITE_PRIVATE int sqlite3Atoi(const char*);
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
-SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8*, const u8**);
+SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
/*
** Routines to read and write variable-length integers. These used to
@@ -11984,8 +12108,11 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
** x = putVarint32( A, B );
**
*/
-#define getVarint32(A,B) (u8)((*(A)<(u8)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), (u32 *)&(B)))
-#define putVarint32(A,B) (u8)(((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B)))
+#define getVarint32(A,B) \
+ (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
+#define putVarint32(A,B) \
+ (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
+ sqlite3PutVarint32((A),(B)))
#define getVarint sqlite3GetVarint
#define putVarint sqlite3PutVarint
@@ -12005,8 +12132,9 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr*, CollSeq*);
-SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
@@ -12053,13 +12181,14 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int);
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
-SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(sqlite3*, u8, CollSeq *, const char*);
+SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
SQLITE_PRIVATE char sqlite3AffinityType(const char*);
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
@@ -12163,8 +12292,10 @@ SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
SQLITE_PRIVATE const char *sqlite3JournalModename(int);
-SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
-SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
+#ifndef SQLITE_OMIT_WAL
+SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
+SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
+#endif
/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
@@ -12189,8 +12320,10 @@ SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
+SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
#else
#define sqlite3FkDelete(a,b)
+ #define sqlite3FkLocateIndex(a,b,c,d,e)
#endif
@@ -12215,15 +12348,18 @@ SQLITE_PRIVATE void sqlite3EndBenignMalloc(void);
#define IN_INDEX_ROWID 1
#define IN_INDEX_EPH 2
-#define IN_INDEX_INDEX 3
+#define IN_INDEX_INDEX_ASC 3
+#define IN_INDEX_INDEX_DESC 4
SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *);
+SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p);
#else
#define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile)
+ #define sqlite3JournalExists(p) 1
#endif
SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
@@ -12452,6 +12588,10 @@ SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
# define SQLITE_USE_URI 0
#endif
+#ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
+#endif
+
/*
** The following singleton contains the global configuration for
** the SQLite library.
@@ -12461,6 +12601,7 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
1, /* bCoreMutex */
SQLITE_THREADSAFE==1, /* bFullMutex */
SQLITE_USE_URI, /* bOpenUri */
+ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
0x7ffffffe, /* mxStrlen */
128, /* szLookaside */
500, /* nLookaside */
@@ -12489,6 +12630,10 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xLog */
0, /* pLogArg */
0, /* bLocaltimeFault */
+#ifdef SQLITE_ENABLE_SQLLOG
+ 0, /* xSqllog */
+ 0 /* pSqllogArg */
+#endif
};
@@ -12804,9 +12949,6 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_OMIT_MEMORYDB
"OMIT_MEMORYDB",
#endif
-#ifdef SQLITE_OMIT_MERGE_SORT
- "OMIT_MERGE_SORT",
-#endif
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
"OMIT_OR_OPTIMIZATION",
#endif
@@ -12879,6 +13021,9 @@ static const char * const azCompileOpt[] = {
#ifdef SQLITE_PROXY_DEBUG
"PROXY_DEBUG",
#endif
+#ifdef SQLITE_RTREE_INT_ONLY
+ "RTREE_INT_ONLY",
+#endif
#ifdef SQLITE_SECURE_DELETE
"SECURE_DELETE",
#endif
@@ -13026,6 +13171,7 @@ struct VdbeCursor {
Bool isIndex; /* True if an index containing keys only - no data */
Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */
Bool isSorter; /* True if a new-style sorter */
+ Bool multiPseudo; /* Multi-register pseudo-cursor */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
i64 seqCount; /* Sequence counter */
@@ -13085,7 +13231,7 @@ struct VdbeFrame {
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
void *token; /* Copy of SubProgram.token */
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
- u16 nCursor; /* Number of entries in apCsr */
+ int nCursor; /* Number of entries in apCsr */
int pc; /* Program Counter in parent (calling) frame */
int nOp; /* Size of aOp array */
int nMem; /* Number of entries in aMem */
@@ -13150,7 +13296,9 @@ struct Mem {
#define MEM_RowSet 0x0020 /* Value is a RowSet object */
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
#define MEM_Invalid 0x0080 /* Value is undefined */
-#define MEM_TypeMask 0x00ff /* Mask of type bits */
+#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
+#define MEM_TypeMask 0x01ff /* Mask of type bits */
+
/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
@@ -13236,6 +13384,11 @@ struct Explain {
char zBase[100]; /* Initial space */
};
+/* A bitfield type for use inside of structures. Always follow with :N where
+** N is the number of bits.
+*/
+typedef unsigned bft; /* Bit Field Type */
+
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
@@ -13264,7 +13417,7 @@ struct Vdbe {
int nLabel; /* Number of labels used */
int *aLabel; /* Space to hold the labels */
u16 nResColumn; /* Number of columns in one row of the result set */
- u16 nCursor; /* Number of slots in apCsr[] */
+ int nCursor; /* Number of slots in apCsr[] */
u32 magic; /* Magic number for sanity checking */
char *zErrMsg; /* Error message written here */
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
@@ -13277,15 +13430,16 @@ struct Vdbe {
int pc; /* The program counter */
int rc; /* Value to return */
u8 errorAction; /* Recovery action to do in case of an error */
- 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 runOnlyOnce; /* Automatically expire on reset */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
- u8 inVtabMethod; /* See comments above */
- u8 usesStmtJournal; /* True if uses a statement journal */
- u8 readOnly; /* True for read-only statements */
- u8 isPrepareV2; /* True if prepared with prepare_v2() */
+ bft explain:2; /* True if EXPLAIN present on SQL command */
+ bft inVtabMethod:2; /* See comments above */
+ bft changeCntOn:1; /* True to update the change-counter */
+ bft expired:1; /* True if the VM needs to be recompiled */
+ bft runOnlyOnce:1; /* Automatically expire on reset */
+ bft usesStmtJournal:1; /* True if uses a statement journal */
+ bft readOnly:1; /* True for read-only statements */
+ bft isPrepareV2:1; /* True if prepared with prepare_v2() */
+ bft doingRerun:1; /* True if rerunning after an auto-reprepare */
int nChange; /* Number of db changes made since last reset */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
@@ -13383,15 +13537,6 @@ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
-#ifdef SQLITE_OMIT_MERGE_SORT
-# define sqlite3VdbeSorterInit(Y,Z) SQLITE_OK
-# define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK
-# define sqlite3VdbeSorterClose(Y,Z)
-# define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK
-# define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK
-# define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK
-# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
-#else
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
@@ -13399,7 +13544,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
-#endif
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
@@ -13631,7 +13775,8 @@ SQLITE_API int sqlite3_db_status(
db->pnBytesFreed = &nByte;
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
- sqlite3VdbeDeleteObject(db, pVdbe);
+ sqlite3VdbeClearObject(db, pVdbe);
+ sqlite3DbFree(db, pVdbe);
}
db->pnBytesFreed = 0;
@@ -20527,25 +20672,23 @@ static const unsigned char sqlite3Utf8Trans1[] = {
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
}
SQLITE_PRIVATE u32 sqlite3Utf8Read(
- const unsigned char *zIn, /* First byte of UTF-8 character */
- const unsigned char **pzNext /* Write first byte past UTF-8 char here */
+ const unsigned char **pz /* Pointer to string from which to read char */
){
unsigned int c;
/* Same as READ_UTF8() above but without the zTerm parameter.
** For this routine, we assume the UTF8 string is always zero-terminated.
*/
- c = *(zIn++);
+ c = *((*pz)++);
if( c>=0xc0 ){
c = sqlite3Utf8Trans1[c-0xc0];
- while( (*zIn & 0xc0)==0x80 ){
- c = (c<<6) + (0x3f & *(zIn++));
+ while( (*(*pz) & 0xc0)==0x80 ){
+ c = (c<<6) + (0x3f & *((*pz)++));
}
if( c<0x80
|| (c&0xFFFFF800)==0xD800
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
}
- *pzNext = zIn;
return c;
}
@@ -20646,7 +20789,6 @@ SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
if( desiredEnc==SQLITE_UTF16LE ){
/* UTF-8 -> UTF-16 Little-endian */
while( zIn UTF-16 Big-endian */
while( zIn0 && n<=4 );
z[0] = 0;
z = zBuf;
- c = sqlite3Utf8Read(z, (const u8**)&z);
+ c = sqlite3Utf8Read((const u8**)&z);
t = i;
if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
@@ -21186,7 +21327,7 @@ SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
*/
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
#ifndef SQLITE_OMIT_FLOATING_POINT
- int incr = (enc==SQLITE_UTF8?1:2);
+ int incr;
const char *zEnd = z + length;
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of significand */
@@ -21197,10 +21338,22 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
int eValid = 1; /* True exponent is either not used or is well-formed */
double result;
int nDigits = 0;
+ int nonNum = 0;
+ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
- if( enc==SQLITE_UTF16BE ) z++;
+ if( enc==SQLITE_UTF8 ){
+ incr = 1;
+ }else{
+ int i;
+ incr = 2;
+ assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+ for(i=3-enc; i=zEnd && nDigits>0 && eValid;
+ return z>=zEnd && nDigits>0 && eValid && nonNum==0;
#else
return !sqlite3Atoi64(z, pResult, length, enc);
#endif /* SQLITE_OMIT_FLOATING_POINT */
@@ -21382,21 +21535,33 @@ static int compare2pow63(const char *zNum, int incr){
** signed 64-bit integer, its negative -9223372036854665808 can be.
**
** If zNum is too big for a 64-bit integer and is not
-** 9223372036854665808 then return 1.
+** 9223372036854665808 or if zNum contains any non-numeric text,
+** then return 1.
**
** length is the number of bytes in the string (bytes, not characters).
** The string is not necessarily zero-terminated. The encoding is
** given by enc.
*/
SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
- int incr = (enc==SQLITE_UTF8?1:2);
+ int incr;
u64 u = 0;
int neg = 0; /* assume positive */
int i;
int c = 0;
+ int nonNum = 0;
const char *zStart;
const char *zEnd = zNum + length;
- if( enc==SQLITE_UTF16BE ) zNum++;
+ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
+ if( enc==SQLITE_UTF8 ){
+ incr = 1;
+ }else{
+ incr = 2;
+ assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+ for(i=3-enc; i19*incr ){
+ if( (c!=0 && &zNum[i]19*incr || nonNum ){
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranteeing that it is too large) */
return 1;
@@ -22305,7 +22470,7 @@ static void removeElementGivenHash(
}
sqlite3_free( elem );
pH->count--;
- if( pH->count<=0 ){
+ if( pH->count==0 ){
assert( pH->first==0 );
assert( pH->count==0 );
sqlite3HashClear(pH);
@@ -22603,6 +22768,13 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
*/
#if SQLITE_OS_UNIX /* This file is used on unix only */
+/* Use posix_fallocate() if it is available
+*/
+#if !defined(HAVE_POSIX_FALLOCATE) \
+ && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
+# define HAVE_POSIX_FALLOCATE 1
+#endif
+
/*
** There are various methods for file locking used for concurrency
** control:
@@ -22775,6 +22947,10 @@ struct unixFile {
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
+#ifdef __QNXNTO__
+ int sectorSize; /* Device sector size */
+ int deviceCharacteristics; /* Precomputed device characteristics */
+#endif
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
#endif
@@ -23091,7 +23267,7 @@ static int openDirectory(const char*, int*);
** to all overrideable system calls.
*/
static struct unix_syscall {
- const char *zName; /* Name of the sytem call */
+ const char *zName; /* Name of the system call */
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
sqlite3_syscall_ptr pDefault; /* Default value */
} aSyscall[] = {
@@ -23166,11 +23342,7 @@ static struct unix_syscall {
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off_t))\
aSyscall[13].pCurrent)
-#if SQLITE_ENABLE_LOCKING_STYLE
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
-#else
- { "fchmod", (sqlite3_syscall_ptr)0, 0 },
-#endif
#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
@@ -23195,9 +23367,6 @@ static struct unix_syscall {
{ "fchown", (sqlite3_syscall_ptr)posixFchown, 0 },
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
- { "umask", (sqlite3_syscall_ptr)umask, 0 },
-#define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent)
-
}; /* End of the overrideable system calls */
/*
@@ -23302,14 +23471,7 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
*/
static int robust_open(const char *z, int f, mode_t m){
int fd;
- mode_t m2;
- mode_t origM = 0;
- if( m==0 ){
- m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
- }else{
- m2 = m;
- origM = osUmask(0);
- }
+ mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
do{
#if defined(O_CLOEXEC)
fd = osOpen(z,f|O_CLOEXEC,m2);
@@ -23317,12 +23479,20 @@ static int robust_open(const char *z, int f, mode_t m){
fd = osOpen(z,f,m2);
#endif
}while( fd<0 && errno==EINTR );
- if( m ){
- osUmask(origM);
- }
+ if( fd>=0 ){
+ if( m!=0 ){
+ struct stat statbuf;
+ if( osFstat(fd, &statbuf)==0
+ && statbuf.st_size==0
+ && (statbuf.st_mode&0777)!=m
+ ){
+ osFchmod(fd, m);
+ }
+ }
#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
- if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
+ osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
+ }
return fd;
}
@@ -24669,7 +24839,7 @@ static int nolockClose(sqlite3_file *id) {
/******************************************************************************
************************* Begin dot-file Locking ******************************
**
-** The dotfile locking implementation uses the existance of separate lock
+** The dotfile locking implementation uses the existence of separate lock
** files (really a directory) to control access to the database. This works
** on just about every filesystem imaginable. But there are serious downsides:
**
@@ -24684,7 +24854,7 @@ static int nolockClose(sqlite3_file *id) {
**
** Dotfile locking works by creating a subdirectory in the same directory as
** the database and with the same name but with a ".lock" extension added.
-** The existance of a lock directory implies an EXCLUSIVE lock. All other
+** The existence of a lock directory implies an EXCLUSIVE lock. All other
** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
*/
@@ -24851,13 +25021,13 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
** Close a file. Make sure the lock has been released before closing.
*/
static int dotlockClose(sqlite3_file *id) {
- int rc;
+ int rc = SQLITE_OK;
if( id ){
unixFile *pFile = (unixFile*)id;
dotlockUnlock(id, NO_LOCK);
sqlite3_free(pFile->lockingContext);
+ rc = closeUnixFile(id);
}
- rc = closeUnixFile(id);
return rc;
}
/****************** End of the dot-file lock implementation *******************
@@ -25061,10 +25231,12 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
** Close a file.
*/
static int flockClose(sqlite3_file *id) {
+ int rc = SQLITE_OK;
if( id ){
flockUnlock(id, NO_LOCK);
+ rc = closeUnixFile(id);
}
- return closeUnixFile(id);
+ return rc;
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
@@ -25775,6 +25947,8 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
i64 newOffset;
#endif
TIMER_START;
+ assert( cnt==(cnt&0x1ffff) );
+ cnt &= 0x1ffff;
do{
#if defined(USE_PREAD)
got = osPread(id->h, pBuf, cnt, offset);
@@ -25864,6 +26038,8 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
i64 newOffset;
#endif
+ assert( cnt==(cnt&0x1ffff) );
+ cnt &= 0x1ffff;
TIMER_START;
#if defined(USE_PREAD)
do{ got = osPwrite(id->h, pBuf, cnt, offset); }while( got<0 && errno==EINTR );
@@ -26167,7 +26343,7 @@ static int unixSync(sqlite3_file *id, int flags){
}
/* Also fsync the directory containing the file if the DIRSYNC flag
- ** is set. This is a one-time occurrance. Many systems (examples: AIX)
+ ** is set. This is a one-time occurrence. Many systems (examples: AIX)
** are unable to fsync a directory, so ignore errors on the fsync.
*/
if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
@@ -26329,6 +26505,9 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
}
}
+/* Forward declaration */
+static int unixGetTempname(int nBuf, char *zBuf);
+
/*
** Information and control of an open file handle.
*/
@@ -26366,6 +26545,14 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
*(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
return SQLITE_OK;
}
+ case SQLITE_FCNTL_TEMPFILENAME: {
+ char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
+ if( zTFile ){
+ unixGetTempname(pFile->pVfs->mxPathname, zTFile);
+ *(char**)pArg = zTFile;
+ }
+ return SQLITE_OK;
+ }
#ifdef SQLITE_DEBUG
/* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and
@@ -26397,10 +26584,92 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
** a database and its journal file) that the sector size will be the
** same for both.
*/
-static int unixSectorSize(sqlite3_file *pFile){
- (void)pFile;
+#ifndef __QNXNTO__
+static int unixSectorSize(sqlite3_file *NotUsed){
+ UNUSED_PARAMETER(NotUsed);
return SQLITE_DEFAULT_SECTOR_SIZE;
}
+#endif
+
+/*
+** The following version of unixSectorSize() is optimized for QNX.
+*/
+#ifdef __QNXNTO__
+#include
+#include
+static int unixSectorSize(sqlite3_file *id){
+ unixFile *pFile = (unixFile*)id;
+ if( pFile->sectorSize == 0 ){
+ struct statvfs fsInfo;
+
+ /* Set defaults for non-supported filesystems */
+ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+ pFile->deviceCharacteristics = 0;
+ if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
+ return pFile->sectorSize;
+ }
+
+ if( !strcmp(fsInfo.f_basetype, "tmp") ) {
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */
+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
+ ** the write succeeds */
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else if( strstr(fsInfo.f_basetype, "etfs") ){
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ /* etfs cluster size writes are atomic */
+ (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
+ ** the write succeeds */
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */
+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
+ ** the write succeeds */
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ /* full bitset of atomics from max sector size and smaller */
+ ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else if( strstr(fsInfo.f_basetype, "dos") ){
+ pFile->sectorSize = fsInfo.f_bsize;
+ pFile->deviceCharacteristics =
+ /* full bitset of atomics from max sector size and smaller */
+ ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
+ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
+ ** so it is ordered */
+ 0;
+ }else{
+ pFile->deviceCharacteristics =
+ SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */
+ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
+ ** the write succeeds */
+ 0;
+ }
+ }
+ /* Last chance verification. If the sector size isn't a multiple of 512
+ ** then it isn't valid.*/
+ if( pFile->sectorSize % 512 != 0 ){
+ pFile->deviceCharacteristics = 0;
+ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
+ }
+ return pFile->sectorSize;
+}
+#endif /* __QNXNTO__ */
/*
** Return the device characteristics for the file.
@@ -26417,11 +26686,15 @@ static int unixSectorSize(sqlite3_file *pFile){
*/
static int unixDeviceCharacteristics(sqlite3_file *id){
unixFile *p = (unixFile*)id;
+ int rc = 0;
+#ifdef __QNXNTO__
+ if( p->sectorSize==0 ) unixSectorSize(id);
+ rc = p->deviceCharacteristics;
+#endif
if( p->ctrlFlags & UNIXFILE_PSOW ){
- return SQLITE_IOCAP_POWERSAFE_OVERWRITE;
- }else{
- return 0;
+ rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
+ return rc;
}
#ifndef SQLITE_OMIT_WAL
@@ -26837,11 +27110,19 @@ static int unixShmMap(
** the requested memory region.
*/
if( !bExtend ) goto shmpage_out;
+#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
+ if( osFallocate(pShmNode->h, sStat.st_size, nByte)!=0 ){
+ rc = unixLogError(SQLITE_IOERR_SHMSIZE, "fallocate",
+ pShmNode->zFilename);
+ goto shmpage_out;
+ }
+#else
if( robust_ftruncate(pShmNode->h, nByte) ){
rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate",
pShmNode->zFilename);
goto shmpage_out;
}
+#endif
}
}
@@ -26859,7 +27140,7 @@ static int unixShmMap(
if( pShmNode->h>=0 ){
pMem = mmap(0, szRegion,
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
- MAP_SHARED, pShmNode->h, pShmNode->nRegion*szRegion
+ MAP_SHARED, pShmNode->h, szRegion*(i64)pShmNode->nRegion
);
if( pMem==MAP_FAILED ){
rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
@@ -27404,7 +27685,7 @@ static int fillInUnixFile(
"psow", SQLITE_POWERSAFE_OVERWRITE) ){
pNew->ctrlFlags |= UNIXFILE_PSOW;
}
- if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
+ if( strcmp(pVfs->zName,"unix-excl")==0 ){
pNew->ctrlFlags |= UNIXFILE_EXCL;
}
@@ -27436,7 +27717,7 @@ static int fillInUnixFile(
unixEnterMutex();
rc = findInodeInfo(pNew, &pNew->pInode);
if( rc!=SQLITE_OK ){
- /* If an error occured in findInodeInfo(), close the file descriptor
+ /* If an error occurred in findInodeInfo(), close the file descriptor
** immediately, before releasing the mutex. findInodeInfo() may fail
** in two scenarios:
**
@@ -28043,8 +28324,13 @@ static int unixDelete(
int rc = SQLITE_OK;
UNUSED_PARAMETER(NotUsed);
SimulateIOError(return SQLITE_IOERR_DELETE);
- if( osUnlink(zPath)==(-1) && errno!=ENOENT ){
- return unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+ if( osUnlink(zPath)==(-1) ){
+ if( errno==ENOENT ){
+ rc = SQLITE_IOERR_DELETE_NOENT;
+ }else{
+ rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
+ }
+ return rc;
}
#ifndef SQLITE_DISABLE_DIRSYNC
if( (dirSync & 1)!=0 ){
@@ -28069,7 +28355,7 @@ static int unixDelete(
}
/*
-** Test the existance of or access permissions of file zPath. The
+** Test the existence of or access permissions of file zPath. The
** test performed depends on the value of flags:
**
** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
@@ -29632,7 +29918,7 @@ SQLITE_API int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==22 );
+ assert( ArraySize(aSyscall)==21 );
/* Register all VFSes defined in the aVfs[] array */
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
@@ -29889,6 +30175,66 @@ SQLITE_API int sqlite3_open_file_count = 0;
/************** End of os_common.h *******************************************/
/************** Continuing where we left off in os_win.c *********************/
+/*
+** Compiling and using WAL mode requires several APIs that are only
+** available in Windows platforms based on the NT kernel.
+*/
+#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
+# error "WAL mode requires support from the Windows NT kernel, compile\
+ with SQLITE_OMIT_WAL."
+#endif
+
+/*
+** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
+** based on the sub-platform)?
+*/
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
+# define SQLITE_WIN32_HAS_ANSI
+#endif
+
+/*
+** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
+** based on the sub-platform)?
+*/
+#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
+# define SQLITE_WIN32_HAS_WIDE
+#endif
+
+/*
+** Do we need to manually define the Win32 file mapping APIs for use with WAL
+** mode (e.g. these APIs are available in the Windows CE SDK; however, they
+** are not present in the header file)?
+*/
+#if SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL)
+/*
+** Two of the file mapping APIs are different under WinRT. Figure out which
+** set we need.
+*/
+#if SQLITE_OS_WINRT
+WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
+ LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
+
+WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
+#else
+#if defined(SQLITE_WIN32_HAS_ANSI)
+WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
+ DWORD, DWORD, DWORD, LPCSTR);
+#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
+
+#if defined(SQLITE_WIN32_HAS_WIDE)
+WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
+ DWORD, DWORD, DWORD, LPCWSTR);
+#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
+
+WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
+#endif /* SQLITE_OS_WINRT */
+
+/*
+** This file mapping API is common to both Win32 and WinRT.
+*/
+WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
+#endif /* SQLITE_WIN32_FILEMAPPING_API && !defined(SQLITE_OMIT_WAL) */
+
/*
** Macro to find the minimum of two numeric values.
*/
@@ -30094,14 +30440,6 @@ SQLITE_API int sqlite3_os_type = 0;
static int sqlite3_os_type = 0;
#endif
-#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
-# define SQLITE_WIN32_HAS_ANSI
-#endif
-
-#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT
-# define SQLITE_WIN32_HAS_WIDE
-#endif
-
#ifndef SYSCALL
# define SYSCALL sqlite3_syscall_ptr
#endif
@@ -30121,7 +30459,7 @@ static int sqlite3_os_type = 0;
** to all overrideable system calls.
*/
static struct win_syscall {
- const char *zName; /* Name of the sytem call */
+ const char *zName; /* Name of the system call */
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
sqlite3_syscall_ptr pDefault; /* Default value */
} aSyscall[] = {
@@ -30173,6 +30511,16 @@ static struct win_syscall {
#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
+#if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
+ !defined(SQLITE_OMIT_WAL))
+ { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
+#else
+ { "CreateFileMappingA", (SYSCALL)0, 0 },
+#endif
+
+#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
+ DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
+
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
!defined(SQLITE_OMIT_WAL))
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
@@ -30181,7 +30529,7 @@ static struct win_syscall {
#endif
#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
- DWORD,DWORD,DWORD,LPCWSTR))aSyscall[6].pCurrent)
+ DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
@@ -30190,7 +30538,7 @@ static struct win_syscall {
#endif
#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
- LPCWSTR))aSyscall[7].pCurrent)
+ LPCWSTR))aSyscall[8].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "DeleteFileA", (SYSCALL)DeleteFileA, 0 },
@@ -30198,7 +30546,7 @@ static struct win_syscall {
{ "DeleteFileA", (SYSCALL)0, 0 },
#endif
-#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[8].pCurrent)
+#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
#if defined(SQLITE_WIN32_HAS_WIDE)
{ "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
@@ -30206,7 +30554,7 @@ static struct win_syscall {
{ "DeleteFileW", (SYSCALL)0, 0 },
#endif
-#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[9].pCurrent)
+#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
#if SQLITE_OS_WINCE
{ "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
@@ -30215,7 +30563,7 @@ static struct win_syscall {
#endif
#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
- LPFILETIME))aSyscall[10].pCurrent)
+ LPFILETIME))aSyscall[11].pCurrent)
#if SQLITE_OS_WINCE
{ "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 },
@@ -30224,11 +30572,11 @@ static struct win_syscall {
#endif
#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
- LPSYSTEMTIME))aSyscall[11].pCurrent)
+ LPSYSTEMTIME))aSyscall[12].pCurrent)
{ "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
-#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[12].pCurrent)
+#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "FormatMessageA", (SYSCALL)FormatMessageA, 0 },
@@ -30237,7 +30585,7 @@ static struct win_syscall {
#endif
#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
- DWORD,va_list*))aSyscall[13].pCurrent)
+ DWORD,va_list*))aSyscall[14].pCurrent)
#if defined(SQLITE_WIN32_HAS_WIDE)
{ "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
@@ -30246,15 +30594,19 @@ static struct win_syscall {
#endif
#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
- DWORD,va_list*))aSyscall[14].pCurrent)
+ DWORD,va_list*))aSyscall[15].pCurrent)
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
+#else
+ { "FreeLibrary", (SYSCALL)0, 0 },
+#endif
-#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[15].pCurrent)
+#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
{ "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
-#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[16].pCurrent)
+#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
{ "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 },
@@ -30263,7 +30615,7 @@ static struct win_syscall {
#endif
#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
- LPDWORD))aSyscall[17].pCurrent)
+ LPDWORD))aSyscall[18].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
@@ -30272,7 +30624,7 @@ static struct win_syscall {
#endif
#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
- LPDWORD))aSyscall[18].pCurrent)
+ LPDWORD))aSyscall[19].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 },
@@ -30280,7 +30632,7 @@ static struct win_syscall {
{ "GetFileAttributesA", (SYSCALL)0, 0 },
#endif
-#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[19].pCurrent)
+#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
@@ -30288,7 +30640,7 @@ static struct win_syscall {
{ "GetFileAttributesW", (SYSCALL)0, 0 },
#endif
-#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[20].pCurrent)
+#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
#if defined(SQLITE_WIN32_HAS_WIDE)
{ "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
@@ -30297,7 +30649,7 @@ static struct win_syscall {
#endif
#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
- LPVOID))aSyscall[21].pCurrent)
+ LPVOID))aSyscall[22].pCurrent)
#if !SQLITE_OS_WINRT
{ "GetFileSize", (SYSCALL)GetFileSize, 0 },
@@ -30305,7 +30657,7 @@ static struct win_syscall {
{ "GetFileSize", (SYSCALL)0, 0 },
#endif
-#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[22].pCurrent)
+#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
{ "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
@@ -30314,7 +30666,7 @@ static struct win_syscall {
#endif
#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
- LPSTR*))aSyscall[23].pCurrent)
+ LPSTR*))aSyscall[24].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
@@ -30323,12 +30675,13 @@ static struct win_syscall {
#endif
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
- LPWSTR*))aSyscall[24].pCurrent)
+ LPWSTR*))aSyscall[25].pCurrent)
{ "GetLastError", (SYSCALL)GetLastError, 0 },
-#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[25].pCurrent)
+#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
+#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
#if SQLITE_OS_WINCE
/* The GetProcAddressA() routine is only available on Windows CE. */
{ "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
@@ -30337,9 +30690,12 @@ static struct win_syscall {
** an ANSI string regardless of the _UNICODE setting */
{ "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
#endif
+#else
+ { "GetProcAddressA", (SYSCALL)0, 0 },
+#endif
#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
- LPCSTR))aSyscall[26].pCurrent)
+ LPCSTR))aSyscall[27].pCurrent)
#if !SQLITE_OS_WINRT
{ "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
@@ -30347,11 +30703,11 @@ static struct win_syscall {
{ "GetSystemInfo", (SYSCALL)0, 0 },
#endif
-#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[27].pCurrent)
+#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
{ "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
-#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[28].pCurrent)
+#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
#if !SQLITE_OS_WINCE
{ "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
@@ -30360,7 +30716,7 @@ static struct win_syscall {
#endif
#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
- LPFILETIME))aSyscall[29].pCurrent)
+ LPFILETIME))aSyscall[30].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "GetTempPathA", (SYSCALL)GetTempPathA, 0 },
@@ -30368,7 +30724,7 @@ static struct win_syscall {
{ "GetTempPathA", (SYSCALL)0, 0 },
#endif
-#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[30].pCurrent)
+#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
@@ -30376,7 +30732,7 @@ static struct win_syscall {
{ "GetTempPathW", (SYSCALL)0, 0 },
#endif
-#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[31].pCurrent)
+#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
#if !SQLITE_OS_WINRT
{ "GetTickCount", (SYSCALL)GetTickCount, 0 },
@@ -30384,7 +30740,7 @@ static struct win_syscall {
{ "GetTickCount", (SYSCALL)0, 0 },
#endif
-#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[32].pCurrent)
+#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
@@ -30393,12 +30749,12 @@ static struct win_syscall {
#endif
#define osGetVersionExA ((BOOL(WINAPI*)( \
- LPOSVERSIONINFOA))aSyscall[33].pCurrent)
+ LPOSVERSIONINFOA))aSyscall[34].pCurrent)
{ "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
- SIZE_T))aSyscall[34].pCurrent)
+ SIZE_T))aSyscall[35].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapCreate", (SYSCALL)HeapCreate, 0 },
@@ -30407,7 +30763,7 @@ static struct win_syscall {
#endif
#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
- SIZE_T))aSyscall[35].pCurrent)
+ SIZE_T))aSyscall[36].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
@@ -30415,21 +30771,21 @@ static struct win_syscall {
{ "HeapDestroy", (SYSCALL)0, 0 },
#endif
-#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[36].pCurrent)
+#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
{ "HeapFree", (SYSCALL)HeapFree, 0 },
-#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[37].pCurrent)
+#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
{ "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
- SIZE_T))aSyscall[38].pCurrent)
+ SIZE_T))aSyscall[39].pCurrent)
{ "HeapSize", (SYSCALL)HeapSize, 0 },
#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
- LPCVOID))aSyscall[39].pCurrent)
+ LPCVOID))aSyscall[40].pCurrent)
#if !SQLITE_OS_WINRT
{ "HeapValidate", (SYSCALL)HeapValidate, 0 },
@@ -30438,23 +30794,24 @@ static struct win_syscall {
#endif
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
- LPCVOID))aSyscall[40].pCurrent)
+ LPCVOID))aSyscall[41].pCurrent)
-#if defined(SQLITE_WIN32_HAS_ANSI)
+#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
#else
{ "LoadLibraryA", (SYSCALL)0, 0 },
#endif
-#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[41].pCurrent)
+#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
-#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
+#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
+ !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
#else
{ "LoadLibraryW", (SYSCALL)0, 0 },
#endif
-#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[42].pCurrent)
+#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
#if !SQLITE_OS_WINRT
{ "LocalFree", (SYSCALL)LocalFree, 0 },
@@ -30462,7 +30819,7 @@ static struct win_syscall {
{ "LocalFree", (SYSCALL)0, 0 },
#endif
-#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[43].pCurrent)
+#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
{ "LockFile", (SYSCALL)LockFile, 0 },
@@ -30472,7 +30829,7 @@ static struct win_syscall {
#ifndef osLockFile
#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- DWORD))aSyscall[44].pCurrent)
+ DWORD))aSyscall[45].pCurrent)
#endif
#if !SQLITE_OS_WINCE
@@ -30483,7 +30840,7 @@ static struct win_syscall {
#ifndef osLockFileEx
#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
- LPOVERLAPPED))aSyscall[45].pCurrent)
+ LPOVERLAPPED))aSyscall[46].pCurrent)
#endif
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL))
@@ -30493,26 +30850,26 @@ static struct win_syscall {
#endif
#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- SIZE_T))aSyscall[46].pCurrent)
+ SIZE_T))aSyscall[47].pCurrent)
{ "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
- int))aSyscall[47].pCurrent)
+ int))aSyscall[48].pCurrent)
{ "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
- LARGE_INTEGER*))aSyscall[48].pCurrent)
+ LARGE_INTEGER*))aSyscall[49].pCurrent)
{ "ReadFile", (SYSCALL)ReadFile, 0 },
#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
- LPOVERLAPPED))aSyscall[49].pCurrent)
+ LPOVERLAPPED))aSyscall[50].pCurrent)
{ "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
-#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[50].pCurrent)
+#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
#if !SQLITE_OS_WINRT
{ "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
@@ -30521,7 +30878,7 @@ static struct win_syscall {
#endif
#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
- DWORD))aSyscall[51].pCurrent)
+ DWORD))aSyscall[52].pCurrent)
#if !SQLITE_OS_WINRT
{ "Sleep", (SYSCALL)Sleep, 0 },
@@ -30529,12 +30886,12 @@ static struct win_syscall {
{ "Sleep", (SYSCALL)0, 0 },
#endif
-#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[52].pCurrent)
+#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
{ "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
- LPFILETIME))aSyscall[53].pCurrent)
+ LPFILETIME))aSyscall[54].pCurrent)
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
{ "UnlockFile", (SYSCALL)UnlockFile, 0 },
@@ -30544,7 +30901,7 @@ static struct win_syscall {
#ifndef osUnlockFile
#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- DWORD))aSyscall[54].pCurrent)
+ DWORD))aSyscall[55].pCurrent)
#endif
#if !SQLITE_OS_WINCE
@@ -30554,7 +30911,7 @@ static struct win_syscall {
#endif
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
- LPOVERLAPPED))aSyscall[55].pCurrent)
+ LPOVERLAPPED))aSyscall[56].pCurrent)
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL)
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
@@ -30562,17 +30919,17 @@ static struct win_syscall {
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
#endif
-#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[56].pCurrent)
+#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
{ "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
- LPCSTR,LPBOOL))aSyscall[57].pCurrent)
+ LPCSTR,LPBOOL))aSyscall[58].pCurrent)
{ "WriteFile", (SYSCALL)WriteFile, 0 },
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
- LPOVERLAPPED))aSyscall[58].pCurrent)
+ LPOVERLAPPED))aSyscall[59].pCurrent)
#if SQLITE_OS_WINRT
{ "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
@@ -30581,7 +30938,7 @@ static struct win_syscall {
#endif
#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
- DWORD,DWORD))aSyscall[59].pCurrent)
+ DWORD,DWORD))aSyscall[60].pCurrent)
#if !SQLITE_OS_WINRT
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
@@ -30590,7 +30947,7 @@ static struct win_syscall {
#endif
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
- DWORD))aSyscall[60].pCurrent)
+ DWORD))aSyscall[61].pCurrent)
#if SQLITE_OS_WINRT
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
@@ -30599,7 +30956,7 @@ static struct win_syscall {
#endif
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
- BOOL))aSyscall[61].pCurrent)
+ BOOL))aSyscall[62].pCurrent)
#if SQLITE_OS_WINRT
{ "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
@@ -30608,7 +30965,7 @@ static struct win_syscall {
#endif
#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
- PLARGE_INTEGER,DWORD))aSyscall[62].pCurrent)
+ PLARGE_INTEGER,DWORD))aSyscall[63].pCurrent)
#if SQLITE_OS_WINRT
{ "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
@@ -30617,7 +30974,7 @@ static struct win_syscall {
#endif
#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
- FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[63].pCurrent)
+ FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[64].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
{ "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
@@ -30626,7 +30983,7 @@ static struct win_syscall {
#endif
#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
- SIZE_T))aSyscall[64].pCurrent)
+ SIZE_T))aSyscall[65].pCurrent)
#if SQLITE_OS_WINRT
{ "CreateFile2", (SYSCALL)CreateFile2, 0 },
@@ -30635,16 +30992,16 @@ static struct win_syscall {
#endif
#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
- LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[65].pCurrent)
+ LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[66].pCurrent)
-#if SQLITE_OS_WINRT
+#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
{ "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
#else
{ "LoadPackagedLibrary", (SYSCALL)0, 0 },
#endif
#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
- DWORD))aSyscall[66].pCurrent)
+ DWORD))aSyscall[67].pCurrent)
#if SQLITE_OS_WINRT
{ "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
@@ -30652,7 +31009,7 @@ static struct win_syscall {
{ "GetTickCount64", (SYSCALL)0, 0 },
#endif
-#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[67].pCurrent)
+#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[68].pCurrent)
#if SQLITE_OS_WINRT
{ "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
@@ -30661,7 +31018,7 @@ static struct win_syscall {
#endif
#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
- LPSYSTEM_INFO))aSyscall[68].pCurrent)
+ LPSYSTEM_INFO))aSyscall[69].pCurrent)
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
@@ -30669,7 +31026,7 @@ static struct win_syscall {
{ "OutputDebugStringA", (SYSCALL)0, 0 },
#endif
-#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[69].pCurrent)
+#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[70].pCurrent)
#if defined(SQLITE_WIN32_HAS_WIDE)
{ "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
@@ -30677,11 +31034,11 @@ static struct win_syscall {
{ "OutputDebugStringW", (SYSCALL)0, 0 },
#endif
-#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[70].pCurrent)
+#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[71].pCurrent)
{ "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
-#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[71].pCurrent)
+#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[72].pCurrent)
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_WAL)
{ "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
@@ -30690,7 +31047,7 @@ static struct win_syscall {
#endif
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
- LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[72].pCurrent)
+ LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[73].pCurrent)
}; /* End of the overrideable system calls */
@@ -30782,7 +31139,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
** (if available).
*/
-SQLITE_API void sqlite3_win32_write_debug(char *zBuf, int nBuf){
+SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
@@ -30848,6 +31205,8 @@ SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
*/
#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
# define isNT() (1)
+#elif !defined(SQLITE_WIN32_HAS_WIDE)
+# define isNT() (0)
#else
static int isNT(void){
if( sqlite3_os_type==0 ){
@@ -30858,7 +31217,7 @@ SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
}
return sqlite3_os_type==2;
}
-#endif /* SQLITE_OS_WINCE */
+#endif
#ifdef SQLITE_WIN32_MALLOC
/*
@@ -31068,7 +31427,7 @@ static LPWSTR utf8ToUnicode(const char *zFilename){
if( nChar==0 ){
return 0;
}
- zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) );
+ zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) );
if( zWideFilename==0 ){
return 0;
}
@@ -31093,7 +31452,7 @@ static char *unicodeToUtf8(LPCWSTR zWideFilename){
if( nByte == 0 ){
return 0;
}
- zFilename = sqlite3_malloc( nByte );
+ zFilename = sqlite3MallocZero( nByte );
if( zFilename==0 ){
return 0;
}
@@ -31123,7 +31482,7 @@ static LPWSTR mbcsToUnicode(const char *zFilename){
if( nByte==0 ){
return 0;
}
- zMbcsFilename = sqlite3_malloc( nByte*sizeof(zMbcsFilename[0]) );
+ zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) );
if( zMbcsFilename==0 ){
return 0;
}
@@ -31152,7 +31511,7 @@ static char *unicodeToMbcs(LPCWSTR zWideFilename){
if( nByte == 0 ){
return 0;
}
- zFilename = sqlite3_malloc( nByte );
+ zFilename = sqlite3MallocZero( nByte );
if( zFilename==0 ){
return 0;
}
@@ -31413,9 +31772,10 @@ static void logIoerr(int nRetry){
/*************************************************************************
** This section contains code for WinCE only.
*/
+#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
/*
-** Windows CE does not have a localtime() function. So create a
-** substitute.
+** The MSVC CRT on Windows CE may not have a localtime() function. So
+** create a substitute.
*/
/* #include */
struct tm *__cdecl localtime(const time_t *t)
@@ -31439,6 +31799,7 @@ struct tm *__cdecl localtime(const time_t *t)
y.tm_sec = pTm.wSecond;
return &y;
}
+#endif
#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
@@ -31460,15 +31821,17 @@ static void winceMutexAcquire(HANDLE h){
** Create the mutex and shared memory used for locking in the file
** descriptor pFile
*/
-static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
+static int winceCreateLock(const char *zFilename, winFile *pFile){
LPWSTR zTok;
LPWSTR zName;
+ DWORD lastErrno;
+ BOOL bLogged = FALSE;
BOOL bInit = TRUE;
zName = utf8ToUnicode(zFilename);
if( zName==0 ){
/* out of memory */
- return FALSE;
+ return SQLITE_IOERR_NOMEM;
}
/* Initialize the local lockdata */
@@ -31485,9 +31848,10 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
if (!pFile->hMutex){
pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_ERROR, pFile->lastErrno, "winceCreateLock1", zFilename);
+ winLogError(SQLITE_IOERR, pFile->lastErrno,
+ "winceCreateLock1", zFilename);
sqlite3_free(zName);
- return FALSE;
+ return SQLITE_IOERR;
}
/* Acquire the mutex before continuing */
@@ -31504,41 +31868,49 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
/* Set a flag that indicates we're the first to create the memory so it
** must be zero-initialized */
- if (osGetLastError() == ERROR_ALREADY_EXISTS){
+ lastErrno = osGetLastError();
+ if (lastErrno == ERROR_ALREADY_EXISTS){
bInit = FALSE;
}
sqlite3_free(zName);
/* If we succeeded in making the shared memory handle, map it. */
- if (pFile->hShared){
+ if( pFile->hShared ){
pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
/* If mapping failed, close the shared memory handle and erase it */
- if (!pFile->shared){
+ if( !pFile->shared ){
pFile->lastErrno = osGetLastError();
- winLogError(SQLITE_ERROR, pFile->lastErrno,
- "winceCreateLock2", zFilename);
+ winLogError(SQLITE_IOERR, pFile->lastErrno,
+ "winceCreateLock2", zFilename);
+ bLogged = TRUE;
osCloseHandle(pFile->hShared);
pFile->hShared = NULL;
}
}
/* If shared memory could not be created, then close the mutex and fail */
- if (pFile->hShared == NULL){
+ if( pFile->hShared==NULL ){
+ if( !bLogged ){
+ pFile->lastErrno = lastErrno;
+ winLogError(SQLITE_IOERR, pFile->lastErrno,
+ "winceCreateLock3", zFilename);
+ bLogged = TRUE;
+ }
winceMutexRelease(pFile->hMutex);
osCloseHandle(pFile->hMutex);
pFile->hMutex = NULL;
- return FALSE;
+ return SQLITE_IOERR;
}
/* Initialize the shared memory if we're supposed to */
- if (bInit) {
+ if( bInit ){
memset(pFile->shared, 0, sizeof(winceLock));
}
winceMutexRelease(pFile->hMutex);
- return TRUE;
+ return SQLITE_OK;
}
/*
@@ -31617,7 +31989,8 @@ static BOOL winceLockFile(
}
/* Want a pending lock? */
- else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){
+ else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+ && nNumberOfBytesToLockLow == 1){
/* If no pending lock has been acquired, then acquire it */
if (pFile->shared->bPending == 0) {
pFile->shared->bPending = TRUE;
@@ -31627,7 +32000,8 @@ static BOOL winceLockFile(
}
/* Want a reserved lock? */
- else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
+ else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+ && nNumberOfBytesToLockLow == 1){
if (pFile->shared->bReserved == 0) {
pFile->shared->bReserved = TRUE;
pFile->local.bReserved = TRUE;
@@ -31670,7 +32044,8 @@ static BOOL winceUnlockFile(
/* Did we just have a reader lock? */
else if (pFile->local.nReaders){
- assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1);
+ assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
+ || nNumberOfBytesToUnlockLow == 1);
pFile->local.nReaders --;
if (pFile->local.nReaders == 0)
{
@@ -31681,7 +32056,8 @@ static BOOL winceUnlockFile(
}
/* Releasing a pending lock */
- else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
+ else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+ && nNumberOfBytesToUnlockLow == 1){
if (pFile->local.bPending){
pFile->local.bPending = FALSE;
pFile->shared->bPending = FALSE;
@@ -31689,7 +32065,8 @@ static BOOL winceUnlockFile(
}
}
/* Releasing a reserved lock */
- else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
+ else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+ && nNumberOfBytesToUnlockLow == 1){
if (pFile->local.bReserved) {
pFile->local.bReserved = FALSE;
pFile->shared->bReserved = FALSE;
@@ -31799,7 +32176,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
** containing the lower 32-bits of the new file-offset. Or, if it fails,
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
- ** whether an error has actually occured, it is also necessary to call
+ ** whether an error has actually occurred, it is also necessary to call
** GetLastError().
*/
dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
@@ -31855,6 +32232,7 @@ static int winClose(sqlite3_file *id){
assert( pFile->pShm==0 );
#endif
OSTRACE(("CLOSE %d\n", pFile->h));
+ assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
do{
rc = osCloseHandle(pFile->h);
/* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
@@ -31944,7 +32322,7 @@ static int winWrite(
int amt, /* Number of bytes to write */
sqlite3_int64 offset /* Offset into the file to begin writing at */
){
- int rc = 0; /* True if error has occured, else false */
+ int rc = 0; /* True if error has occurred, else false */
winFile *pFile = (winFile*)id; /* File handle */
int nRetry = 0; /* Number of retries */
@@ -31984,7 +32362,8 @@ static int winWrite(
if( retryIoerr(&nRetry, &lastErrno) ) continue;
break;
}
- if( nWrite<=0 ){
+ assert( nWrite==0 || nWrite<=(DWORD)nRem );
+ if( nWrite==0 || nWrite>(DWORD)nRem ){
lastErrno = osGetLastError();
break;
}
@@ -32413,7 +32792,7 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
rc = 1;
OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
}else{
- rc = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
+ rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
if( rc ){
winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
}
@@ -32482,6 +32861,9 @@ static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
}
}
+/* Forward declaration */
+static int getTempname(int nBuf, char *zBuf);
+
/*
** Control and query of the open file handle.
*/
@@ -32542,6 +32924,14 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
}
return SQLITE_OK;
}
+ case SQLITE_FCNTL_TEMPFILENAME: {
+ char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
+ if( zTFile ){
+ getTempname(pFile->pVfs->mxPathname, zTFile);
+ *(char**)pArg = zTFile;
+ }
+ return SQLITE_OK;
+ }
}
return SQLITE_NOTFOUND;
}
@@ -32759,7 +33149,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
(int)osGetCurrentProcessId(), i,
bRc ? "ok" : "failed"));
}
- if( p->hFile.h != INVALID_HANDLE_VALUE ){
+ if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
SimulateIOErrorBenign(1);
winClose((sqlite3_file *)&p->hFile);
SimulateIOErrorBenign(0);
@@ -32799,16 +33189,14 @@ static int winOpenSharedMemory(winFile *pDbFd){
/* Allocate space for the new sqlite3_shm object. Also speculatively
** allocate space for a new winShmNode and filename.
*/
- p = sqlite3_malloc( sizeof(*p) );
+ p = sqlite3MallocZero( sizeof(*p) );
if( p==0 ) return SQLITE_IOERR_NOMEM;
- memset(p, 0, sizeof(*p));
nName = sqlite3Strlen30(pDbFd->zPath);
- pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 17 );
+ pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
if( pNew==0 ){
sqlite3_free(p);
return SQLITE_IOERR_NOMEM;
}
- memset(pNew, 0, sizeof(*pNew) + nName + 17);
pNew->zFilename = (char*)&pNew[1];
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
@@ -32841,7 +33229,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
rc = winOpen(pDbFd->pVfs,
pShmNode->zFilename, /* Name of the file (UTF-8) */
(sqlite3_file*)&pShmNode->hFile, /* File handle here */
- SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
+ SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
0);
if( SQLITE_OK!=rc ){
goto shm_open_err;
@@ -33145,17 +33533,21 @@ static int winShmMap(
pShmNode->aRegion = apNew;
while( pShmNode->nRegion<=iRegion ){
- HANDLE hMap; /* file-mapping handle */
+ HANDLE hMap = NULL; /* file-mapping handle */
void *pMap = 0; /* Mapped memory region */
#if SQLITE_OS_WINRT
hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
NULL, PAGE_READWRITE, nByte, NULL
);
-#else
+#elif defined(SQLITE_WIN32_HAS_WIDE)
hMap = osCreateFileMappingW(pShmNode->hFile.h,
NULL, PAGE_READWRITE, 0, nByte, NULL
);
+#elif defined(SQLITE_WIN32_HAS_ANSI)
+ hMap = osCreateFileMappingA(pShmNode->hFile.h,
+ NULL, PAGE_READWRITE, 0, nByte, NULL
+ );
#endif
OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n",
(int)osGetCurrentProcessId(), pShmNode->nRegion, nByte,
@@ -33452,8 +33844,9 @@ static int winOpen(
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
- assert( id!=0 );
- UNUSED_PARAMETER(pVfs);
+ assert( pFile!=0 );
+ memset(pFile, 0, sizeof(winFile));
+ pFile->h = INVALID_HANDLE_VALUE;
#if SQLITE_OS_WINRT
if( !sqlite3_temp_directory ){
@@ -33462,13 +33855,12 @@ static int winOpen(
}
#endif
- pFile->h = INVALID_HANDLE_VALUE;
-
/* If the second argument to this function is NULL, generate a
** temporary file name to use
*/
if( !zUtf8Name ){
assert(isDelete && !isOpenJournal);
+ memset(zTmpname, 0, MAX_PATH+2);
rc = getTempname(MAX_PATH+2, zTmpname);
if( rc!=SQLITE_OK ){
return rc;
@@ -33591,7 +33983,9 @@ static int winOpen(
sqlite3_free(zConverted);
if( isReadWrite && !isExclusive ){
return winOpen(pVfs, zName, id,
- ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
+ ((flags|SQLITE_OPEN_READONLY) &
+ ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
+ pOutFlags);
}else{
return SQLITE_CANTOPEN_BKPT;
}
@@ -33605,26 +33999,13 @@ static int winOpen(
}
}
- memset(pFile, 0, sizeof(*pFile));
- pFile->pMethod = &winIoMethod;
- pFile->h = h;
- pFile->lastErrno = NO_ERROR;
- pFile->pVfs = pVfs;
-#ifndef SQLITE_OMIT_WAL
- pFile->pShm = 0;
-#endif
- pFile->zPath = zName;
- if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
- pFile->ctrlFlags |= WINFILE_PSOW;
- }
-
#if SQLITE_OS_WINCE
if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
- && !winceCreateLock(zName, pFile)
+ && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
){
osCloseHandle(h);
sqlite3_free(zConverted);
- return SQLITE_CANTOPEN_BKPT;
+ return rc;
}
if( isTemp ){
pFile->zDeleteOnClose = zConverted;
@@ -33634,6 +34015,15 @@ static int winOpen(
sqlite3_free(zConverted);
}
+ pFile->pMethod = &winIoMethod;
+ pFile->pVfs = pVfs;
+ pFile->h = h;
+ if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
+ pFile->ctrlFlags |= WINFILE_PSOW;
+ }
+ pFile->lastErrno = NO_ERROR;
+ pFile->zPath = zName;
+
OpenCounter(+1);
return rc;
}
@@ -33677,14 +34067,26 @@ static int winDelete(
&sAttrData) ){
attr = sAttrData.dwFileAttributes;
}else{
- rc = SQLITE_OK; /* Already gone? */
+ lastErrno = osGetLastError();
+ if( lastErrno==ERROR_FILE_NOT_FOUND
+ || lastErrno==ERROR_PATH_NOT_FOUND ){
+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+ }else{
+ rc = SQLITE_ERROR;
+ }
break;
}
#else
attr = osGetFileAttributesW(zConverted);
#endif
if ( attr==INVALID_FILE_ATTRIBUTES ){
- rc = SQLITE_OK; /* Already gone? */
+ lastErrno = osGetLastError();
+ if( lastErrno==ERROR_FILE_NOT_FOUND
+ || lastErrno==ERROR_PATH_NOT_FOUND ){
+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+ }else{
+ rc = SQLITE_ERROR;
+ }
break;
}
if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
@@ -33706,7 +34108,13 @@ static int winDelete(
do {
attr = osGetFileAttributesA(zConverted);
if ( attr==INVALID_FILE_ATTRIBUTES ){
- rc = SQLITE_OK; /* Already gone? */
+ lastErrno = osGetLastError();
+ if( lastErrno==ERROR_FILE_NOT_FOUND
+ || lastErrno==ERROR_PATH_NOT_FOUND ){
+ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
+ }else{
+ rc = SQLITE_ERROR;
+ }
break;
}
if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
@@ -33724,7 +34132,7 @@ static int winDelete(
} while(1);
}
#endif
- if( rc ){
+ if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
"winDelete", zFilename);
}else{
@@ -33736,7 +34144,7 @@ static int winDelete(
}
/*
-** Check the existance and status of a file.
+** Check the existence and status of a file.
*/
static int winAccess(
sqlite3_vfs *pVfs, /* Not used on win32 */
@@ -33870,16 +34278,12 @@ static int winFullPathname(
*/
char zOut[MAX_PATH+1];
memset(zOut, 0, MAX_PATH+1);
- cygwin_conv_to_win32_path(zRelative, zOut); /* POSIX to Win32 */
+ cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
+ MAX_PATH+1);
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
sqlite3_data_directory, zOut);
}else{
- /*
- ** NOTE: The Cygwin docs state that the maximum length needed
- ** for the buffer passed to cygwin_conv_to_full_win32_path
- ** is MAX_PATH.
- */
- cygwin_conv_to_full_win32_path(zRelative, zFull);
+ cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
}
return SQLITE_OK;
#endif
@@ -33904,7 +34308,7 @@ static int winFullPathname(
#endif
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
- int nByte;
+ DWORD nByte;
void *zConverted;
char *zOut;
@@ -33938,13 +34342,27 @@ static int winFullPathname(
}
if( isNT() ){
LPWSTR zTemp;
- nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0) + 3;
- zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
+ nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
+ if( nByte==0 ){
+ winLogError(SQLITE_ERROR, osGetLastError(),
+ "GetFullPathNameW1", zConverted);
+ sqlite3_free(zConverted);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
+ nByte += 3;
+ zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
if( zTemp==0 ){
sqlite3_free(zConverted);
return SQLITE_IOERR_NOMEM;
}
- osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+ nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
+ if( nByte==0 ){
+ winLogError(SQLITE_ERROR, osGetLastError(),
+ "GetFullPathNameW2", zConverted);
+ sqlite3_free(zConverted);
+ sqlite3_free(zTemp);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
sqlite3_free(zConverted);
zOut = unicodeToUtf8(zTemp);
sqlite3_free(zTemp);
@@ -33952,13 +34370,27 @@ static int winFullPathname(
#ifdef SQLITE_WIN32_HAS_ANSI
else{
char *zTemp;
- nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
- zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
+ nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
+ if( nByte==0 ){
+ winLogError(SQLITE_ERROR, osGetLastError(),
+ "GetFullPathNameA1", zConverted);
+ sqlite3_free(zConverted);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
+ nByte += 3;
+ zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
if( zTemp==0 ){
sqlite3_free(zConverted);
return SQLITE_IOERR_NOMEM;
}
- osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+ nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
+ if( nByte==0 ){
+ winLogError(SQLITE_ERROR, osGetLastError(),
+ "GetFullPathNameA2", zConverted);
+ sqlite3_free(zConverted);
+ sqlite3_free(zTemp);
+ return SQLITE_CANTOPEN_FULLPATH;
+ }
sqlite3_free(zConverted);
zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
sqlite3_free(zTemp);
@@ -34009,9 +34441,9 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
UNUSED_PARAMETER(pVfs);
getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
}
-static void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
+static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
UNUSED_PARAMETER(pVfs);
- return (void(*)(void))osGetProcAddressA((HANDLE)pHandle, zSymbol);
+ return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
}
static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
UNUSED_PARAMETER(pVfs);
@@ -34109,7 +34541,8 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
#endif
/* 2^32 - to avoid use of LL and warnings in gcc */
static const sqlite3_int64 max32BitValue =
- (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296;
+ (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
+ (sqlite3_int64)294967296;
#if SQLITE_OS_WINCE
SYSTEMTIME time;
@@ -34216,7 +34649,7 @@ SQLITE_API int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==73 );
+ assert( ArraySize(aSyscall)==74 );
#ifndef SQLITE_OMIT_WAL
/* get memory map allocation granularity */
@@ -34235,7 +34668,7 @@ SQLITE_API int sqlite3_os_init(void){
SQLITE_API int sqlite3_os_end(void){
#if SQLITE_OS_WINRT
- if( sleepObj != NULL ){
+ if( sleepObj!=NULL ){
osCloseHandle(sleepObj);
sleepObj = NULL;
}
@@ -34320,7 +34753,7 @@ SQLITE_API int sqlite3_os_end(void){
/*
** A bitmap is an instance of the following structure.
**
-** This bitmap records the existance of zero or more bits
+** This bitmap records the existence of zero or more bits
** with values between 1 and iSize, inclusive.
**
** There are three possible representations of the bitmap.
@@ -37222,7 +37655,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
** * A write transaction is active.
** * An EXCLUSIVE or greater lock is held on the database file.
** * All writing and syncing of journal and database data has finished.
-** If no error occured, all that remains is to finalize the journal to
+** If no error occurred, all that remains is to finalize the journal to
** commit the transaction. If an error did occur, the caller will need
** to rollback the transaction.
**
@@ -37470,7 +37903,7 @@ struct PagerSavepoint {
**
** doNotSpill, doNotSyncSpill
**
-** These two boolean variables control the behaviour of cache-spills
+** These two boolean variables control the behavior of cache-spills
** (calls made by the pcache module to the pagerStress() routine to
** write cached data to the file-system in order to free up memory).
**
@@ -38348,7 +38781,7 @@ static int writeJournalHdr(Pager *pPager){
memset(zHeader, 0, sizeof(aJournalMagic)+4);
}
- /* The random check-hash initialiser */
+ /* The random check-hash initializer */
sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
/* The initial database size */
@@ -38787,6 +39220,8 @@ static int pager_error(Pager *pPager, int rc){
return rc;
}
+static int pager_truncate(Pager *pPager, Pgno nPage);
+
/*
** This routine ends a transaction. A transaction is usually ended by
** either a COMMIT or a ROLLBACK operation. This routine may be called
@@ -38840,7 +39275,7 @@ static int pager_error(Pager *pPager, int rc){
** to the first error encountered (the journal finalization one) is
** returned.
*/
-static int pager_end_transaction(Pager *pPager, int hasMaster){
+static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
int rc = SQLITE_OK; /* Error code from journal finalization operation */
int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
@@ -38890,12 +39325,13 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
** file should be closed and deleted. If this connection writes to
** the database file, it will do so using an in-memory journal.
*/
+ int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd));
assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|| pPager->journalMode==PAGER_JOURNALMODE_WAL
);
sqlite3OsClose(pPager->jfd);
- if( !pPager->tempFile ){
+ if( bDelete ){
rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
}
}
@@ -38925,7 +39361,17 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
*/
rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
assert( rc2==SQLITE_OK );
+ }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
+ /* This branch is taken when committing a transaction in rollback-journal
+ ** mode if the database file on disk is larger than the database image.
+ ** At this point the journal has been finalized and the transaction
+ ** successfully committed, but the EXCLUSIVE lock is still held on the
+ ** file. So it is safe to truncate the database file to its minimum
+ ** required size. */
+ assert( pPager->eLock==EXCLUSIVE_LOCK );
+ rc = pager_truncate(pPager, pPager->dbSize);
}
+
if( !pPager->exclusiveMode
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){
@@ -38964,7 +39410,7 @@ static void pagerUnlockAndRollback(Pager *pPager){
sqlite3EndBenignMalloc();
}else if( !pPager->exclusiveMode ){
assert( pPager->eState==PAGER_READER );
- pager_end_transaction(pPager, 0);
+ pager_end_transaction(pPager, 0, 0);
}
}
pager_unlock(pPager);
@@ -39458,6 +39904,21 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
return rc;
}
+/*
+** Return a sanitized version of the sector-size of OS file pFile. The
+** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
+*/
+SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
+ int iRet = sqlite3OsSectorSize(pFile);
+ if( iRet<32 ){
+ iRet = 512;
+ }else if( iRet>MAX_SECTOR_SIZE ){
+ assert( MAX_SECTOR_SIZE>=512 );
+ iRet = MAX_SECTOR_SIZE;
+ }
+ return iRet;
+}
+
/*
** Set the value of the Pager.sectorSize variable for the given
** pager based on the value returned by the xSectorSize method
@@ -39493,14 +39954,7 @@ static void setSectorSize(Pager *pPager){
** call will segfault. */
pPager->sectorSize = 512;
}else{
- pPager->sectorSize = sqlite3OsSectorSize(pPager->fd);
- if( pPager->sectorSize<32 ){
- pPager->sectorSize = 512;
- }
- if( pPager->sectorSize>MAX_SECTOR_SIZE ){
- assert( MAX_SECTOR_SIZE>=512 );
- pPager->sectorSize = MAX_SECTOR_SIZE;
- }
+ pPager->sectorSize = sqlite3SectorSize(pPager->fd);
}
}
@@ -39731,7 +40185,7 @@ end_playback:
rc = sqlite3PagerSync(pPager);
}
if( rc==SQLITE_OK ){
- rc = pager_end_transaction(pPager, zMaster[0]!='\0');
+ rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK && zMaster[0] && res ){
@@ -40100,6 +40554,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
if( rc ) return rc;
if( nPage==0 ){
rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
+ if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
isWal = 0;
}else{
rc = sqlite3OsAccess(
@@ -40417,9 +40872,16 @@ SQLITE_PRIVATE void sqlite3PagerSetBusyhandler(
Pager *pPager, /* Pager object */
int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
-){
+){
pPager->xBusyHandler = xBusyHandler;
pPager->pBusyHandlerArg = pBusyHandlerArg;
+
+ if( isOpen(pPager->fd) ){
+ void **ap = (void **)&pPager->xBusyHandler;
+ assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
+ assert( ap[1]==pBusyHandlerArg );
+ sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
+ }
}
/*
@@ -40651,7 +41113,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
** dirty page were to be discarded from the cache via the pagerStress()
** routine, pagerStress() would not write the current page content to
** the database file. If a savepoint transaction were rolled back after
-** this happened, the correct behaviour would be to restore the current
+** this happened, the correct behavior would be to restore the current
** content of the page. However, since this content is not present in either
** the database file or the portion of the rollback journal and
** sub-journal rolled back the content could not be restored and the
@@ -40675,12 +41137,26 @@ static void assertTruncateConstraint(Pager *pPager){
** function does not actually modify the database file on disk. It
** just sets the internal state of the pager object so that the
** truncation will be done when the current transaction is committed.
+**
+** This function is only called right before committing a transaction.
+** Once this function has been called, the transaction must either be
+** rolled back or committed. It is not safe to call this function and
+** then continue writing to the database.
*/
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
assert( pPager->dbSize>=nPage );
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
pPager->dbSize = nPage;
- assertTruncateConstraint(pPager);
+
+ /* At one point the code here called assertTruncateConstraint() to
+ ** ensure that all pages being truncated away by this operation are,
+ ** if one or more savepoints are open, present in the savepoint
+ ** journal so that they can be restored if the savepoint is rolled
+ ** back. This is no longer necessary as this function is now only
+ ** called right before committing a transaction. So although the
+ ** Pager object may still have open savepoints (Pager.nSavepoint!=0),
+ ** they cannot be rolled back. So the assertTruncateConstraint() call
+ ** is no longer correct. */
}
@@ -41397,7 +41873,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen(
memcpy(pPager->zFilename, zPathname, nPathname);
if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
memcpy(pPager->zJournal, zPathname, nPathname);
- memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+1);
+ memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
#ifndef SQLITE_OMIT_WAL
pPager->zWal = &pPager->zJournal[nPathname+8+1];
@@ -41733,6 +42209,11 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
goto failed;
}
if( bHotJournal ){
+ if( pPager->readOnly ){
+ rc = SQLITE_READONLY_ROLLBACK;
+ goto failed;
+ }
+
/* Get an EXCLUSIVE lock on the database file. At this point it is
** important that a RESERVED lock is not obtained on the way to the
** EXCLUSIVE lock. If it were, another process might open the
@@ -42599,7 +43080,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
# define DIRECT_MODE isDirectMode
#endif
- if( !pPager->changeCountDone && pPager->dbSize>0 ){
+ if( !pPager->changeCountDone && ALWAYS(pPager->dbSize>0) ){
PgHdr *pPgHdr; /* Reference to page 1 */
assert( !pPager->tempFile && isOpen(pPager->fd) );
@@ -42817,38 +43298,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
#endif
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- /* If this transaction has made the database smaller, then all pages
- ** being discarded by the truncation must be written to the journal
- ** file. This can only happen in auto-vacuum mode.
- **
- ** Before reading the pages with page numbers larger than the
- ** current value of Pager.dbSize, set dbSize back to the value
- ** that it took at the start of the transaction. Otherwise, the
- ** calls to sqlite3PagerGet() return zeroed pages instead of
- ** reading data from the database file.
- */
- #ifndef SQLITE_OMIT_AUTOVACUUM
- if( pPager->dbSizedbOrigSize
- && pPager->journalMode!=PAGER_JOURNALMODE_OFF
- ){
- Pgno i; /* Iterator variable */
- const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
- const Pgno dbSize = pPager->dbSize; /* Database image size */
- pPager->dbSize = pPager->dbOrigSize;
- for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
- if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
- PgHdr *pPage; /* Page to journal */
- rc = sqlite3PagerGet(pPager, i, &pPage);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- rc = sqlite3PagerWrite(pPage);
- sqlite3PagerUnref(pPage);
- if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
- }
- }
- pPager->dbSize = dbSize;
- }
- #endif
-
/* Write the master journal name into the journal file. If a master
** journal file name has already been written to the journal file,
** or if zMaster is NULL (no master journal), then this call is a no-op.
@@ -42876,11 +43325,14 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
goto commit_phase_one_exit;
}
sqlite3PcacheCleanAll(pPager->pPCache);
-
- /* If the file on disk is not the same size as the database image,
- ** then use pager_truncate to grow or shrink the file here.
- */
- if( pPager->dbSize!=pPager->dbFileSize ){
+
+ /* If the file on disk is smaller than the database image, use
+ ** pager_truncate to grow the file here. This can happen if the database
+ ** image was extended as part of the current transaction and then the
+ ** last page in the db image moved to the free-list. In this case the
+ ** last page is never written out to disk, leaving the database file
+ ** undersized. Fix this now if it is the case. */
+ if( pPager->dbSize>pPager->dbFileSize ){
Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
assert( pPager->eState==PAGER_WRITER_DBMOD );
rc = pager_truncate(pPager, nNew);
@@ -42953,7 +43405,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
}
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
- rc = pager_end_transaction(pPager, pPager->setMaster);
+ rc = pager_end_transaction(pPager, pPager->setMaster, 1);
return pager_error(pPager, rc);
}
@@ -42998,11 +43450,11 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
if( pagerUseWal(pPager) ){
int rc2;
rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
- rc2 = pager_end_transaction(pPager, pPager->setMaster);
+ rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
if( rc==SQLITE_OK ) rc = rc2;
}else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
int eState = pPager->eState;
- rc = pager_end_transaction(pPager, 0);
+ rc = pager_end_transaction(pPager, 0, 0);
if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
/* This can happen using journal_mode=off. Move the pager to the error
** state to indicate that the contents of the cache may not be trusted.
@@ -43400,7 +43852,8 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
*/
if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
needSyncPgno = pPg->pgno;
- assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
+ assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
+ pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
assert( pPg->flags&PGHDR_DIRTY );
}
@@ -43850,6 +44303,8 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){
return rc;
}
+#endif /* !SQLITE_OMIT_WAL */
+
#ifdef SQLITE_ENABLE_ZIPVFS
/*
** A read-lock must be held on the pager when this function is called. If
@@ -43879,8 +44334,6 @@ SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
}
#endif /* SQLITE_HAS_CODEC */
-#endif /* !SQLITE_OMIT_WAL */
-
#endif /* SQLITE_OMIT_DISKIO */
/************** End of pager.c ***********************************************/
@@ -46404,7 +46857,7 @@ SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *p
assert( walFramePgno(pWal, iFrame)!=1 );
rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame));
}
- walCleanupHash(pWal);
+ if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal);
}
assert( rc==SQLITE_OK );
return rc;
@@ -46714,7 +47167,7 @@ SQLITE_PRIVATE int sqlite3WalFrames(
*/
if( isCommit && (sync_flags & WAL_SYNC_TRANSACTIONS)!=0 ){
if( pWal->padToSectorBoundary ){
- int sectorSize = sqlite3OsSectorSize(pWal->pWalFd);
+ int sectorSize = sqlite3SectorSize(pWal->pWalFd);
w.iSyncPoint = ((iOffset+sectorSize-1)/sectorSize)*sectorSize;
while( iOffsetincrVacuum);
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+#define IfNotOmitAV(expr) (expr)
+#else
+#define IfNotOmitAV(expr) 0
+#endif
+
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** A list of BtShared objects that are eligible for participation
@@ -48483,6 +48956,19 @@ static void btreeClearHasContent(BtShared *pBt){
pBt->pHasContent = 0;
}
+/*
+** Release all of the apPage[] pages for a cursor.
+*/
+static void btreeReleaseAllCursorPages(BtCursor *pCur){
+ int i;
+ for(i=0; i<=pCur->iPage; i++){
+ releasePage(pCur->apPage[i]);
+ pCur->apPage[i] = 0;
+ }
+ pCur->iPage = -1;
+}
+
+
/*
** Save the current cursor position in the variables BtCursor.nKey
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
@@ -48522,12 +49008,7 @@ static int saveCursorPosition(BtCursor *pCur){
assert( !pCur->apPage[0]->intKey || !pCur->pKey );
if( rc==SQLITE_OK ){
- int i;
- for(i=0; i<=pCur->iPage; i++){
- releasePage(pCur->apPage[i]);
- pCur->apPage[i] = 0;
- }
- pCur->iPage = -1;
+ btreeReleaseAllCursorPages(pCur);
pCur->eState = CURSOR_REQUIRESEEK;
}
@@ -48545,11 +49026,15 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
assert( sqlite3_mutex_held(pBt->mutex) );
assert( pExcept==0 || pExcept->pBt==pBt );
for(p=pBt->pCursor; p; p=p->pNext){
- if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) &&
- p->eState==CURSOR_VALID ){
- int rc = saveCursorPosition(p);
- if( SQLITE_OK!=rc ){
- return rc;
+ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
+ if( p->eState==CURSOR_VALID ){
+ int rc = saveCursorPosition(p);
+ if( SQLITE_OK!=rc ){
+ return rc;
+ }
+ }else{
+ testcase( p->iPage>0 );
+ btreeReleaseAllCursorPages(p);
}
}
}
@@ -50127,6 +50612,24 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
return p->pBt->pageSize;
}
+#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+/*
+** This function is similar to sqlite3BtreeGetReserve(), except that it
+** may only be called if it is guaranteed that the b-tree mutex is already
+** held.
+**
+** This is useful in one special case in the backup API code where it is
+** known that the shared b-tree mutex is held, but the mutex on the
+** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
+** were to be called, it might collide with some other operation on the
+** database handle that owns *p, causing undefined behavior.
+*/
+SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
+ assert( sqlite3_mutex_held(p->pBt->mutex) );
+ return p->pBt->pageSize - p->pBt->usableSize;
+}
+#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */
+
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Return the number of bytes of space at the end of every page that
@@ -50440,6 +50943,20 @@ static int newDatabase(BtShared *pBt){
return SQLITE_OK;
}
+/*
+** Initialize the first page of the database file (creating a database
+** consisting of a single page and no schema objects). Return SQLITE_OK
+** if successful, or an SQLite error code otherwise.
+*/
+SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p){
+ int rc;
+ sqlite3BtreeEnter(p);
+ p->pBt->nPage = 0;
+ rc = newDatabase(p->pBt);
+ sqlite3BtreeLeave(p);
+ return rc;
+}
+
/*
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read-
@@ -50490,6 +51007,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
goto trans_begun;
}
+ assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
/* Write transactions are not possible on a read-only database */
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
@@ -50806,24 +51324,23 @@ static int relocatePage(
static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
/*
-** Perform a single step of an incremental-vacuum. If successful,
-** return SQLITE_OK. If there is no work to do (and therefore no
-** point in calling this function again), return SQLITE_DONE.
+** Perform a single step of an incremental-vacuum. If successful, return
+** SQLITE_OK. If there is no work to do (and therefore no point in
+** calling this function again), return SQLITE_DONE. Or, if an error
+** occurs, return some other error code.
**
-** More specificly, this function attempts to re-organize the
-** database so that the last page of the file currently in use
-** is no longer in use.
+** More specificly, this function attempts to re-organize the database so
+** that the last page of the file currently in use is no longer in use.
**
-** If the nFin parameter is non-zero, this function assumes
-** that the caller will keep calling incrVacuumStep() until
-** it returns SQLITE_DONE or an error, and that nFin is the
-** number of pages the database file will contain after this
-** process is complete. If nFin is zero, it is assumed that
-** incrVacuumStep() will be called a finite amount of times
-** which may or may not empty the freelist. A full autovacuum
-** has nFin>0. A "PRAGMA incremental_vacuum" has nFin==0.
+** Parameter nFin is the number of pages that this database would contain
+** were this function called until it returns SQLITE_DONE.
+**
+** If the bCommit parameter is non-zero, this function assumes that the
+** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE
+** or an error. bCommit is passed true for an auto-vacuum-on-commmit
+** operation, or false for an incremental vacuum.
*/
-static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
+static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
Pgno nFreeList; /* Number of pages still on the free-list */
int rc;
@@ -50848,15 +51365,15 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
}
if( eType==PTRMAP_FREEPAGE ){
- if( nFin==0 ){
+ if( bCommit==0 ){
/* Remove the page from the files free-list. This is not required
- ** if nFin is non-zero. In that case, the free-list will be
+ ** if bCommit is non-zero. In that case, the free-list will be
** truncated to zero after this function returns, so it doesn't
** matter if it still contains some garbage entries.
*/
Pgno iFreePg;
MemPage *pFreePg;
- rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1);
+ rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -50866,34 +51383,37 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
} else {
Pgno iFreePg; /* Index of free page to move pLastPg to */
MemPage *pLastPg;
+ u8 eMode = BTALLOC_ANY; /* Mode parameter for allocateBtreePage() */
+ Pgno iNear = 0; /* nearby parameter for allocateBtreePage() */
rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
if( rc!=SQLITE_OK ){
return rc;
}
- /* If nFin is zero, this loop runs exactly once and page pLastPg
+ /* If bCommit is zero, this loop runs exactly once and page pLastPg
** is swapped with the first free page pulled off the free list.
**
- ** On the other hand, if nFin is greater than zero, then keep
+ ** On the other hand, if bCommit is greater than zero, then keep
** looping until a free-page located within the first nFin pages
** of the file is found.
*/
+ if( bCommit==0 ){
+ eMode = BTALLOC_LE;
+ iNear = nFin;
+ }
do {
MemPage *pFreePg;
- rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0);
+ rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
if( rc!=SQLITE_OK ){
releasePage(pLastPg);
return rc;
}
releasePage(pFreePg);
- }while( nFin!=0 && iFreePg>nFin );
+ }while( bCommit && iFreePg>nFin );
assert( iFreePgpDbPage);
- if( rc==SQLITE_OK ){
- rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0);
- }
+ rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
releasePage(pLastPg);
if( rc!=SQLITE_OK ){
return rc;
@@ -50901,29 +51421,39 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
}
}
- if( nFin==0 ){
- iLastPg--;
- while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
- if( PTRMAP_ISPAGE(pBt, iLastPg) ){
- MemPage *pPg;
- rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- rc = sqlite3PagerWrite(pPg->pDbPage);
- releasePage(pPg);
- if( rc!=SQLITE_OK ){
- return rc;
- }
- }
+ if( bCommit==0 ){
+ do {
iLastPg--;
- }
- sqlite3PagerTruncateImage(pBt->pPager, iLastPg);
+ }while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) );
+ pBt->bDoTruncate = 1;
pBt->nPage = iLastPg;
}
return SQLITE_OK;
}
+/*
+** The database opened by the first argument is an auto-vacuum database
+** nOrig pages in size containing nFree free pages. Return the expected
+** size of the database in pages following an auto-vacuum operation.
+*/
+static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
+ int nEntry; /* Number of entries on one ptrmap page */
+ Pgno nPtrmap; /* Number of PtrMap pages to be freed */
+ Pgno nFin; /* Return value */
+
+ nEntry = pBt->usableSize/5;
+ nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
+ nFin = nOrig - nFree - nPtrmap;
+ if( nOrig>PENDING_BYTE_PAGE(pBt) && nFinautoVacuum ){
rc = SQLITE_DONE;
}else{
- invalidateAllOverflowCache(pBt);
- rc = incrVacuumStep(pBt, 0, btreePagecount(pBt));
- if( rc==SQLITE_OK ){
- rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
- put4byte(&pBt->pPage1->aData[28], pBt->nPage);
+ Pgno nOrig = btreePagecount(pBt);
+ Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
+ Pgno nFin = finalDbSize(pBt, nOrig, nFree);
+
+ if( nOrig0 ){
+ invalidateAllOverflowCache(pBt);
+ rc = incrVacuumStep(pBt, nFin, nOrig, 0);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+ put4byte(&pBt->pPage1->aData[28], pBt->nPage);
+ }
+ }else{
+ rc = SQLITE_DONE;
}
}
sqlite3BtreeLeave(p);
@@ -50972,9 +51512,7 @@ static int autoVacuumCommit(BtShared *pBt){
if( !pBt->incrVacuum ){
Pgno nFin; /* Number of pages in database after autovacuuming */
Pgno nFree; /* Number of pages on the freelist initially */
- Pgno nPtrmap; /* Number of PtrMap pages to be freed */
Pgno iFree; /* The next page to be freed */
- int nEntry; /* Number of entries on one ptrmap page */
Pgno nOrig; /* Database size before freeing */
nOrig = btreePagecount(pBt);
@@ -50987,26 +51525,18 @@ static int autoVacuumCommit(BtShared *pBt){
}
nFree = get4byte(&pBt->pPage1->aData[36]);
- nEntry = pBt->usableSize/5;
- nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
- nFin = nOrig - nFree - nPtrmap;
- if( nOrig>PENDING_BYTE_PAGE(pBt) && nFinnOrig ) return SQLITE_CORRUPT_BKPT;
for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
- rc = incrVacuumStep(pBt, nFin, iFree);
+ rc = incrVacuumStep(pBt, nFin, iFree, 1);
}
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
put4byte(&pBt->pPage1->aData[32], 0);
put4byte(&pBt->pPage1->aData[36], 0);
put4byte(&pBt->pPage1->aData[28], nFin);
- sqlite3PagerTruncateImage(pBt->pPager, nFin);
+ pBt->bDoTruncate = 1;
pBt->nPage = nFin;
}
if( rc!=SQLITE_OK ){
@@ -51061,6 +51591,9 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
return rc;
}
}
+ if( pBt->bDoTruncate ){
+ sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
+ }
#endif
rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
sqlite3BtreeLeave(p);
@@ -51076,6 +51609,9 @@ static void btreeEndTransaction(Btree *p){
BtShared *pBt = p->pBt;
assert( sqlite3BtreeHoldsMutex(p) );
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ pBt->bDoTruncate = 0;
+#endif
btreeClearHasContent(pBt);
if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
/* If there are other active statements that belong to this database
@@ -52748,21 +53284,23 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
** an error. *ppPage and *pPgno are undefined in the event of an error.
** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
**
-** If the "nearby" parameter is not 0, then a (feeble) effort is made to
+** If the "nearby" parameter is not 0, then an effort is made to
** locate a page close to the page number "nearby". This can be used in an
** attempt to keep related pages close to each other in the database file,
** which in turn can make database access faster.
**
-** If the "exact" parameter is not 0, and the page-number nearby exists
-** anywhere on the free-list, then it is guarenteed to be returned. This
-** is only used by auto-vacuum databases when allocating a new table.
+** If the eMode parameter is BTALLOC_EXACT and the nearby page exists
+** anywhere on the free-list, then it is guaranteed to be returned. If
+** eMode is BTALLOC_LT then the page returned will be less than or equal
+** to nearby if any such page exists. If eMode is BTALLOC_ANY then there
+** are no restrictions on which page is returned.
*/
static int allocateBtreePage(
- BtShared *pBt,
- MemPage **ppPage,
- Pgno *pPgno,
- Pgno nearby,
- u8 exact
+ BtShared *pBt, /* The btree */
+ MemPage **ppPage, /* Store pointer to the allocated page here */
+ Pgno *pPgno, /* Store the page number here */
+ Pgno nearby, /* Search for a page near this one */
+ u8 eMode /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
){
MemPage *pPage1;
int rc;
@@ -52773,6 +53311,7 @@ static int allocateBtreePage(
Pgno mxPage; /* Total size of the database file */
assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) );
pPage1 = pBt->pPage1;
mxPage = btreePagecount(pBt);
n = get4byte(&pPage1->aData[36]);
@@ -52785,21 +53324,24 @@ static int allocateBtreePage(
Pgno iTrunk;
u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
- /* If the 'exact' parameter was true and a query of the pointer-map
+ /* If eMode==BTALLOC_EXACT and a query of the pointer-map
** shows that the page 'nearby' is somewhere on the free-list, then
** the entire-list will be searched for that page.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( exact && nearby<=mxPage ){
- u8 eType;
- assert( nearby>0 );
- assert( pBt->autoVacuum );
- rc = ptrmapGet(pBt, nearby, &eType, 0);
- if( rc ) return rc;
- if( eType==PTRMAP_FREEPAGE ){
- searchList = 1;
+ if( eMode==BTALLOC_EXACT ){
+ if( nearby<=mxPage ){
+ u8 eType;
+ assert( nearby>0 );
+ assert( pBt->autoVacuum );
+ rc = ptrmapGet(pBt, nearby, &eType, 0);
+ if( rc ) return rc;
+ if( eType==PTRMAP_FREEPAGE ){
+ searchList = 1;
+ }
}
- *pPgno = nearby;
+ }else if( eMode==BTALLOC_LE ){
+ searchList = 1;
}
#endif
@@ -52812,7 +53354,8 @@ static int allocateBtreePage(
/* The code within this loop is run only once if the 'searchList' variable
** is not true. Otherwise, it runs once for each trunk-page on the
- ** free-list until the page 'nearby' is located.
+ ** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT)
+ ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT)
*/
do {
pPrevTrunk = pTrunk;
@@ -52854,11 +53397,13 @@ static int allocateBtreePage(
rc = SQLITE_CORRUPT_BKPT;
goto end_allocate_page;
#ifndef SQLITE_OMIT_AUTOVACUUM
- }else if( searchList && nearby==iTrunk ){
+ }else if( searchList
+ && (nearby==iTrunk || (iTrunkpDbPage);
@@ -52921,14 +53466,24 @@ static int allocateBtreePage(
unsigned char *aData = pTrunk->aData;
if( nearby>0 ){
u32 i;
- int dist;
closest = 0;
- dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
- for(i=1; ibDoTruncate));
+
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
if( rc ) return rc;
pBt->nPage++;
@@ -52985,7 +53560,7 @@ static int allocateBtreePage(
MemPage *pPg = 0;
TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1);
+ rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
if( rc==SQLITE_OK ){
rc = sqlite3PagerWrite(pPg->pDbPage);
releasePage(pPg);
@@ -52999,7 +53574,7 @@ static int allocateBtreePage(
*pPgno = pBt->nPage;
assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
- rc = btreeGetPage(pBt, *pPgno, ppPage, 1);
+ rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
if( rc ) return rc;
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
@@ -53183,7 +53758,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
return SQLITE_OK; /* No overflow pages. Return without doing anything */
}
if( pCell+info.iOverflow+3 > pPage->aData+pPage->maskPage ){
- return SQLITE_CORRUPT; /* Cell extends past end of page */
+ return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
}
ovflPgno = get4byte(&pCell[info.iOverflow]);
assert( pBt->usableSize > 4 );
@@ -53327,7 +53902,7 @@ static int fillInCell(
** If this is the first overflow page, then write a partial entry
** to the pointer-map. If we write nothing to this pointer-map slot,
** then the optimistic overflow chain processing in clearCell()
- ** may misinterpret the uninitialised values and delete the
+ ** may misinterpret the uninitialized values and delete the
** wrong pages from the database.
*/
if( pBt->autoVacuum && rc==SQLITE_OK ){
@@ -53639,7 +54214,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
assert( pPage->nOverflow==1 );
/* This error condition is now caught prior to reaching this function */
- if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT;
+ if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT;
/* Allocate a new page. This page will become the right-sibling of
** pPage. Make the parent page writable, so that the new divider cell
@@ -54800,7 +55375,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
- /* If no error has occured and pPage has an overflow cell, call balance()
+ /* If no error has occurred 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.
@@ -55014,7 +55589,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
** be moved to the allocated page (unless the allocated page happens
** to reside at pgnoRoot).
*/
- rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1);
+ rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
if( rc!=SQLITE_OK ){
return rc;
}
@@ -55921,7 +56496,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
}
i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
- sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000);
+ sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
sCheck.errMsg.useMalloc = 2;
/* Check the integrity of the freelist
@@ -56456,20 +57031,28 @@ static int isFatalError(int rc){
** page iSrcPg from the source database. Copy this data into the
** destination database.
*/
-static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
+static int backupOnePage(
+ sqlite3_backup *p, /* Backup handle */
+ Pgno iSrcPg, /* Source database page to backup */
+ const u8 *zSrcData, /* Source database page data */
+ int bUpdate /* True for an update, false otherwise */
+){
Pager * const pDestPager = sqlite3BtreePager(p->pDest);
const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
#ifdef SQLITE_HAS_CODEC
- int nSrcReserve = sqlite3BtreeGetReserve(p->pSrc);
+ /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
+ ** guaranteed that the shared-mutex is held by this thread, handle
+ ** p->pSrc may not actually be the owner. */
+ int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
int nDestReserve = sqlite3BtreeGetReserve(p->pDest);
#endif
-
int rc = SQLITE_OK;
i64 iOff;
+ assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
assert( p->bDestLocked );
assert( !isFatalError(p->rc) );
assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
@@ -56526,6 +57109,9 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
*/
memcpy(zOut, zIn, nCopy);
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
+ if( iOff==0 && bUpdate==0 ){
+ sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
+ }
}
sqlite3PagerUnref(pDestPg);
}
@@ -56632,7 +57218,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
DbPage *pSrcPg; /* Source page object */
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
if( rc==SQLITE_OK ){
- rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg));
+ rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
sqlite3PagerUnref(pSrcPg);
}
}
@@ -56654,7 +57240,13 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
** same schema version.
*/
if( rc==SQLITE_DONE ){
- rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+ if( nSrcPage==0 ){
+ rc = sqlite3BtreeNewDb(p->pDest);
+ nSrcPage = 1;
+ }
+ if( rc==SQLITE_OK || rc==SQLITE_DONE ){
+ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+ }
if( rc==SQLITE_OK ){
if( p->pDestDb ){
sqlite3ResetAllSchemasOfConnection(p->pDestDb);
@@ -56688,7 +57280,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
}else{
nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
}
- sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
+ assert( nDestTruncate>0 );
if( pgszSrc= iSize || (
+ assert( nDestTruncate==0
+ || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
));
- /* This call ensures that all data required to recreate the original
+ /* This block ensures that all data required to recreate the original
** database has been stored in the journal for pDestPager and the
** journal synced to disk. So at this point we may safely modify
** the database file in any way, knowing that if a power failure
** occurs, the original database will be reconstructed from the
** journal file. */
- rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
+ sqlite3PagerPagecount(pDestPager, &nDstPage);
+ for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
+ if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
+ DbPage *pPg;
+ rc = sqlite3PagerGet(pDestPager, iPg, &pPg);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerWrite(pPg);
+ sqlite3PagerUnref(pPg);
+ }
+ }
+ }
+ if( rc==SQLITE_OK ){
+ rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
+ }
/* Write the extra pages and truncate the database file as required */
iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
@@ -56744,6 +57352,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
rc = sqlite3PagerSync(pDestPager);
}
}else{
+ sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
}
@@ -56872,7 +57481,7 @@ SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, con
int rc;
assert( p->pDestDb );
sqlite3_mutex_enter(p->pDestDb->mutex);
- rc = backupOnePage(p, iPage, aData);
+ rc = backupOnePage(p, iPage, aData, 1);
sqlite3_mutex_leave(p->pDestDb->mutex);
assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
if( rc!=SQLITE_OK ){
@@ -56995,7 +57604,9 @@ copy_finished:
** between formats.
*/
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
+#ifndef SQLITE_OMIT_UTF16
int rc;
+#endif
assert( (pMem->flags&MEM_RowSet)==0 );
assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|| desiredEnc==SQLITE_UTF16BE );
@@ -58140,18 +58751,6 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
** But that file was getting too big so this subroutines were split out.
*/
-
-
-/*
-** When debugging the code generator in a symbolic debugger, one can
-** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed
-** as they are added to the instruction stream.
-*/
-#ifdef SQLITE_DEBUG
-SQLITE_PRIVATE int sqlite3VdbeAddopTrace = 0;
-#endif
-
-
/*
** Create a new virtual database engine.
*/
@@ -58176,7 +58775,7 @@ SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(sqlite3 *db){
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
assert( isPrepareV2==1 || isPrepareV2==0 );
if( p==0 ) return;
-#ifdef SQLITE_OMIT_TRACE
+#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
if( !isPrepareV2 ) return;
#endif
assert( p->zSql==0 );
@@ -58281,7 +58880,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
pOp->p4type = P4_NOTUSED;
#ifdef SQLITE_DEBUG
pOp->zComment = 0;
- if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+ if( p->db->flags & SQLITE_VdbeAddopTrace ){
+ sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+ }
#endif
#ifdef VDBE_PROFILE
pOp->cycles = 0;
@@ -58500,7 +59101,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|| (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1)
#endif
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
- && (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
+ && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
){
hasAbort = 1;
break;
@@ -58508,7 +59109,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
}
sqlite3DbFree(v->db, sIter.apSub);
- /* Return true if hasAbort==mayAbort. Or if a malloc failure occured.
+ /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
** If malloc failed, then the while() loop above may not have iterated
** through all opcodes and hasAbort may be set incorrectly. Return
** true for this case to prevent the assert() in the callers frame
@@ -58635,7 +59236,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
pOut->p5 = 0;
#ifdef SQLITE_DEBUG
pOut->zComment = 0;
- if( sqlite3VdbeAddopTrace ){
+ if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
}
#endif
@@ -58846,6 +59447,7 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
addr = p->nOp - 1;
}
pOp = &p->aOp[addr];
+ assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 );
freeP4(db, pOp->p4type, pOp->p4.p);
pOp->p4.p = 0;
if( n==P4_INT32 ){
@@ -58868,10 +59470,9 @@ SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int
u8 *aSortOrder;
memcpy((char*)pKeyInfo, zP4, nByte - nField);
aSortOrder = pKeyInfo->aSortOrder;
- if( aSortOrder ){
- pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
- memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
- }
+ assert( aSortOrder!=0 );
+ pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
+ memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
pOp->p4type = P4_KEYINFO;
}else{
p->db->mallocFailed = 1;
@@ -58984,26 +59585,23 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
case P4_KEYINFO: {
int i, j;
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
+ assert( pKeyInfo->aSortOrder!=0 );
sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField);
i = sqlite3Strlen30(zTemp);
for(j=0; jnField; j++){
CollSeq *pColl = pKeyInfo->aColl[j];
- if( pColl ){
- int n = sqlite3Strlen30(pColl->zName);
- if( i+n>nTemp-6 ){
- memcpy(&zTemp[i],",...",4);
- break;
- }
- zTemp[i++] = ',';
- if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){
- zTemp[i++] = '-';
- }
- memcpy(&zTemp[i], pColl->zName,n+1);
- i += n;
- }else if( i+4zName : "nil";
+ int n = sqlite3Strlen30(zColl);
+ if( i+n>nTemp-6 ){
+ memcpy(&zTemp[i],",...",4);
+ break;
}
+ zTemp[i++] = ',';
+ if( pKeyInfo->aSortOrder[j] ){
+ zTemp[i++] = '-';
+ }
+ memcpy(&zTemp[i], zColl, n+1);
+ i += n;
}
zTemp[i++] = ')';
zTemp[i] = 0;
@@ -59664,7 +60262,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
zEnd = &zCsr[nByte];
}while( nByte && !db->mallocFailed );
- p->nCursor = (u16)nCursor;
+ p->nCursor = nCursor;
p->nOnceFlag = nOnce;
if( p->aVar ){
p->nVar = (ynVar)nVar;
@@ -59893,7 +60491,9 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
if( sqlite3BtreeIsInTrans(pBt) ){
needXcommit = 1;
if( i!=1 ) nTrans++;
+ sqlite3BtreeEnter(pBt);
rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
+ sqlite3BtreeLeave(pBt);
}
}
if( rc!=SQLITE_OK ){
@@ -59904,7 +60504,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
if( needXcommit && db->xCommitCallback ){
rc = db->xCommitCallback(db->pCommitArg);
if( rc ){
- return SQLITE_CONSTRAINT;
+ return SQLITE_CONSTRAINT_COMMITHOOK;
}
}
@@ -60141,7 +60741,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
/* If p->iStatement is greater than zero, then this Vdbe opened a
** statement transaction that should be closed here. The only exception
- ** is that an IO error may have occured, causing an emergency rollback.
+ ** is that an IO error may have occurred, causing an emergency rollback.
** In this case (db->nStatement==0), and there is nothing to do.
*/
if( db->nStatement && p->iStatement ){
@@ -60196,14 +60796,14 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
**
** If there are outstanding FK violations and this function returns
-** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write
-** an error message to it. Then return SQLITE_ERROR.
+** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
+** and write an error message to it. Then return SQLITE_ERROR.
*/
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
sqlite3 *db = p->db;
if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
- p->rc = SQLITE_CONSTRAINT;
+ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
return SQLITE_ERROR;
@@ -60277,7 +60877,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
**
** Even if the statement is read-only, it is important to perform
** a statement or transaction rollback operation. If the error
- ** occured while writing to the journal, sub-journal or database
+ ** occurred while writing to the journal, sub-journal or database
** file as part of an effort to free up cache space (see function
** pagerStress() in pager.c), the rollback is required to restore
** the pager to a consistent state.
@@ -60318,7 +60918,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
sqlite3VdbeLeave(p);
return SQLITE_ERROR;
}
- rc = SQLITE_CONSTRAINT;
+ rc = SQLITE_CONSTRAINT_FOREIGNKEY;
}else{
/* The auto-commit flag is true, the vdbe program was successful
** or hit an 'OR FAIL' constraint and there are no deferred foreign
@@ -60361,7 +60961,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
if( eStatementOp ){
rc = sqlite3VdbeCloseStatement(p, eStatementOp);
if( rc ){
- if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
+ if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){
p->rc = rc;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
@@ -60447,6 +61047,27 @@ SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p){
return rc;
}
+#ifdef SQLITE_ENABLE_SQLLOG
+/*
+** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run,
+** invoke it.
+*/
+static void vdbeInvokeSqllog(Vdbe *v){
+ if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){
+ char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql);
+ assert( v->db->init.busy==0 );
+ if( zExpanded ){
+ sqlite3GlobalConfig.xSqllog(
+ sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1
+ );
+ sqlite3DbFree(v->db, zExpanded);
+ }
+ }
+}
+#else
+# define vdbeInvokeSqllog(x)
+#endif
+
/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg. Return the result code.
@@ -60474,6 +61095,7 @@ SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe *p){
** instructions yet, leave the main database error information unchanged.
*/
if( p->pc>=0 ){
+ vdbeInvokeSqllog(p);
sqlite3VdbeTransferError(p);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
@@ -60555,12 +61177,14 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
}
/*
-** Free all memory associated with the Vdbe passed as the second argument.
+** Free all memory associated with the Vdbe passed as the second argument,
+** except for object itself, which is preserved.
+**
** The difference between this function and sqlite3VdbeDelete() is that
** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
-** the database connection.
+** the database connection and frees the object itself.
*/
-SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
+SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
int i;
assert( p->db==0 || p->db==db );
@@ -60581,7 +61205,6 @@ SQLITE_PRIVATE void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
sqlite3DbFree(db, p->zExplain);
sqlite3DbFree(db, p->pExplain);
#endif
- sqlite3DbFree(db, p);
}
/*
@@ -60593,6 +61216,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
if( NEVER(p==0) ) return;
db = p->db;
assert( sqlite3_mutex_held(db->mutex) );
+ sqlite3VdbeClearObject(db, p);
if( p->pPrev ){
p->pPrev->pNext = p->pNext;
}else{
@@ -60604,7 +61228,7 @@ SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe *p){
}
p->magic = VDBE_MAGIC_DEAD;
p->db = 0;
- sqlite3VdbeDeleteObject(db, p);
+ sqlite3DbFree(db, p);
}
/*
@@ -60667,7 +61291,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
** the blob of data that it corresponds to. In a table record, all serial
** types are stored at the start of the record, and the blobs of data at
** the end. Hence these functions allow the caller to handle the
-** serial-type and data blob seperately.
+** serial-type and data blob separately.
**
** The following table describes the various storage classes for data:
**
@@ -60706,9 +61330,6 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
# define MAX_6BYTE ((((i64)0x00008000)<<32)-1)
i64 i = pMem->u.i;
u64 u;
- if( file_format>=4 && (i&1)==i ){
- return 8+(u32)i;
- }
if( i<0 ){
if( i<(-MAX_6BYTE) ) return 6;
/* Previous test prevents: u = -(-9223372036854775808) */
@@ -60716,7 +61337,9 @@ SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format){
}else{
u = i;
}
- if( u<=127 ) return 1;
+ if( u<=127 ){
+ return ((i&1)==i && file_format>=4) ? 8+(u32)u : 1;
+ }
if( u<=32767 ) return 2;
if( u<=8388607 ) return 3;
if( u<=2147483647 ) return 4;
@@ -61001,6 +61624,7 @@ SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(
}
p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
+ assert( pKeyInfo->aSortOrder!=0 );
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nField + 1;
return p;
@@ -61094,6 +61718,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
nField = pKeyInfo->nField;
+ assert( pKeyInfo->aSortOrder!=0 );
while( idx1nField ){
u32 serial_type1;
@@ -61113,7 +61738,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
assert( mem1.zMalloc==0 ); /* See comment below */
/* Invert the result if we are using DESC sort order. */
- if( pKeyInfo->aSortOrder && iaSortOrder[i] ){
+ if( iaSortOrder[i] ){
rc = -rc;
}
@@ -61806,7 +62431,7 @@ end_of_step:
assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
/* If this statement was prepared using sqlite3_prepare_v2(), and an
- ** error has occured, then return the error code in p->rc to the
+ ** error has occurred, then return the error code in p->rc to the
** caller. Set the error code in the database handle to the same value.
*/
rc = sqlite3VdbeTransferError(p);
@@ -61839,10 +62464,12 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
}
db = v->db;
sqlite3_mutex_enter(db->mutex);
+ v->doingRerun = 0;
while( (rc = sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY
&& (rc2 = rc = sqlite3Reprepare(v))==SQLITE_OK ){
sqlite3_reset(pStmt);
+ v->doingRerun = 1;
assert( v->expired==0 );
}
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
@@ -62557,7 +63184,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa
if( zName ){
for(i=0; inzVar; i++){
const char *z = p->azVar[i];
- if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
+ if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
return i+1;
}
}
@@ -63094,11 +63721,7 @@ SQLITE_API int sqlite3_found_count = 0;
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
-#ifdef SQLITE_OMIT_MERGE_SORT
-# define isSorter(x) 0
-#else
# define isSorter(x) ((x)->pSorter!=0)
-#endif
/*
** Argument pMem points at a register that will be passed to a
@@ -63364,7 +63987,9 @@ SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
** Print the value of a register for tracing purposes:
*/
static void memTracePrint(FILE *out, Mem *p){
- if( p->flags & MEM_Null ){
+ if( p->flags & MEM_Invalid ){
+ fprintf(out, " undefined");
+ }else if( p->flags & MEM_Null ){
fprintf(out, " NULL");
}else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
fprintf(out, " si:%lld", p->u.i);
@@ -63615,6 +64240,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
} aa;
struct OP_Null_stack_vars {
int cnt;
+ u16 nullFlag;
} ab;
struct OP_Variable_stack_vars {
Mem *pVar; /* Value being transferred */
@@ -63625,39 +64251,43 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int p1; /* Register to copy from */
int p2; /* Register to copy to */
} ad;
+ struct OP_Copy_stack_vars {
+ int n;
+ } ae;
struct OP_ResultRow_stack_vars {
Mem *pMem;
int i;
- } ae;
+ } af;
struct OP_Concat_stack_vars {
i64 nByte;
- } af;
+ } ag;
struct OP_Remainder_stack_vars {
+ char bIntint; /* Started out as two integer operands */
int flags; /* Combined MEM_* flags from both inputs */
i64 iA; /* Integer value of left operand */
i64 iB; /* Integer value of right operand */
double rA; /* Real value of left operand */
double rB; /* Real value of right operand */
- } ag;
+ } ah;
struct OP_Function_stack_vars {
int i;
Mem *pArg;
sqlite3_context ctx;
sqlite3_value **apVal;
int n;
- } ah;
+ } ai;
struct OP_ShiftRight_stack_vars {
i64 iA;
u64 uA;
i64 iB;
u8 op;
- } ai;
+ } aj;
struct OP_Ge_stack_vars {
int res; /* Result of the comparison of pIn1 against pIn3 */
char affinity; /* Affinity to use for comparison */
u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */
- } aj;
+ } ak;
struct OP_Compare_stack_vars {
int n;
int i;
@@ -63667,14 +64297,14 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
- } ak;
+ } al;
struct OP_Or_stack_vars {
int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
- } al;
+ } am;
struct OP_IfNot_stack_vars {
int c;
- } am;
+ } an;
struct OP_Column_stack_vars {
u32 payloadSize; /* Number of bytes in the record */
i64 payloadSize64; /* Number of bytes in the record */
@@ -63699,11 +64329,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
- } an;
+ } ao;
struct OP_Affinity_stack_vars {
const char *zAffinity; /* The affinity to be applied */
char cAff; /* A single character of affinity */
- } ao;
+ } ap;
struct OP_MakeRecord_stack_vars {
u8 *zNewRecord; /* A buffer to hold the data for the new record */
Mem *pRec; /* The new record */
@@ -63720,11 +64350,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int file_format; /* File format to use for encoding */
int i; /* Space used in zNewRecord[] */
int len; /* Length of a field */
- } ap;
+ } aq;
struct OP_Count_stack_vars {
i64 nEntry;
BtCursor *pCrsr;
- } aq;
+ } ar;
struct OP_Savepoint_stack_vars {
int p1; /* Value of P1 operand */
char *zName; /* Name of savepoint */
@@ -63734,28 +64364,28 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
Savepoint *pTmp;
int iSavepoint;
int ii;
- } ar;
+ } as;
struct OP_AutoCommit_stack_vars {
int desiredAutoCommit;
int iRollback;
int turnOnAC;
- } as;
+ } at;
struct OP_Transaction_stack_vars {
Btree *pBt;
- } at;
+ } au;
struct OP_ReadCookie_stack_vars {
int iMeta;
int iDb;
int iCookie;
- } au;
+ } av;
struct OP_SetCookie_stack_vars {
Db *pDb;
- } av;
+ } aw;
struct OP_VerifyCookie_stack_vars {
int iMeta;
int iGen;
Btree *pBt;
- } aw;
+ } ax;
struct OP_OpenWrite_stack_vars {
int nField;
KeyInfo *pKeyInfo;
@@ -63765,16 +64395,16 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
Btree *pX;
VdbeCursor *pCur;
Db *pDb;
- } ax;
+ } ay;
struct OP_OpenEphemeral_stack_vars {
VdbeCursor *pCx;
- } ay;
+ } az;
struct OP_SorterOpen_stack_vars {
VdbeCursor *pCx;
- } az;
+ } ba;
struct OP_OpenPseudo_stack_vars {
VdbeCursor *pCx;
- } ba;
+ } bb;
struct OP_SeekGt_stack_vars {
int res;
int oc;
@@ -63782,10 +64412,10 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
UnpackedRecord r;
int nField;
i64 iKey; /* The rowid we are to seek to */
- } bb;
+ } bc;
struct OP_Seek_stack_vars {
VdbeCursor *pC;
- } bc;
+ } bd;
struct OP_Found_stack_vars {
int alreadyExists;
VdbeCursor *pC;
@@ -63794,7 +64424,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
UnpackedRecord *pIdxKey;
UnpackedRecord r;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
- } bd;
+ } be;
struct OP_IsUnique_stack_vars {
u16 ii;
VdbeCursor *pCx;
@@ -63803,13 +64433,13 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
Mem *aMx;
UnpackedRecord r; /* B-Tree index search key */
i64 R; /* Rowid stored in register P3 */
- } be;
+ } bf;
struct OP_NotExists_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
u64 iKey;
- } bf;
+ } bg;
struct OP_NewRowid_stack_vars {
i64 v; /* The new rowid */
VdbeCursor *pC; /* Cursor of table to get the new rowid */
@@ -63817,7 +64447,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int cnt; /* Counter to limit the number of searches */
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
VdbeFrame *pFrame; /* Root frame of VDBE */
- } bg;
+ } bh;
struct OP_InsertInt_stack_vars {
Mem *pData; /* MEM cell holding data for the record to be inserted */
Mem *pKey; /* MEM cell holding key for the record */
@@ -63828,89 +64458,89 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
const char *zDb; /* database name - used by the update hook */
const char *zTbl; /* Table name - used by the opdate hook */
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
- } bh;
+ } bi;
struct OP_Delete_stack_vars {
i64 iKey;
VdbeCursor *pC;
- } bi;
+ } bj;
struct OP_SorterCompare_stack_vars {
VdbeCursor *pC;
int res;
- } bj;
+ } bk;
struct OP_SorterData_stack_vars {
VdbeCursor *pC;
- } bk;
+ } bl;
struct OP_RowData_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
i64 n64;
- } bl;
+ } bm;
struct OP_Rowid_stack_vars {
VdbeCursor *pC;
i64 v;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
- } bm;
+ } bn;
struct OP_NullRow_stack_vars {
VdbeCursor *pC;
- } bn;
+ } bo;
struct OP_Last_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
- } bo;
+ } bp;
struct OP_Rewind_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
- } bp;
+ } bq;
struct OP_Next_stack_vars {
VdbeCursor *pC;
int res;
- } bq;
+ } br;
struct OP_IdxInsert_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int nKey;
const char *zKey;
- } br;
+ } bs;
struct OP_IdxDelete_stack_vars {
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
UnpackedRecord r;
- } bs;
+ } bt;
struct OP_IdxRowid_stack_vars {
BtCursor *pCrsr;
VdbeCursor *pC;
i64 rowid;
- } bt;
+ } bu;
struct OP_IdxGE_stack_vars {
VdbeCursor *pC;
int res;
UnpackedRecord r;
- } bu;
+ } bv;
struct OP_Destroy_stack_vars {
int iMoved;
int iCnt;
Vdbe *pVdbe;
int iDb;
- } bv;
+ } bw;
struct OP_Clear_stack_vars {
int nChange;
- } bw;
+ } bx;
struct OP_CreateTable_stack_vars {
int pgno;
int flags;
Db *pDb;
- } bx;
+ } by;
struct OP_ParseSchema_stack_vars {
int iDb;
const char *zMaster;
char *zSql;
InitData initData;
- } by;
+ } bz;
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 */
@@ -63918,14 +64548,14 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int nErr; /* Number of errors reported */
char *z; /* Text of the error report */
Mem *pnErr; /* Register keeping track of errors remaining */
- } bz;
+ } ca;
struct OP_RowSetRead_stack_vars {
i64 val;
- } ca;
+ } cb;
struct OP_RowSetTest_stack_vars {
int iSet;
int exists;
- } cb;
+ } cc;
struct OP_Program_stack_vars {
int nMem; /* Number of memory registers for sub-program */
int nByte; /* Bytes of runtime space required for sub-program */
@@ -63935,15 +64565,15 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
VdbeFrame *pFrame; /* New vdbe frame to execute in */
SubProgram *pProgram; /* Sub-program to execute */
void *t; /* Token identifying trigger */
- } cc;
+ } cd;
struct OP_Param_stack_vars {
VdbeFrame *pFrame;
Mem *pIn;
- } cd;
+ } ce;
struct OP_MemMax_stack_vars {
Mem *pIn1;
VdbeFrame *pFrame;
- } ce;
+ } cf;
struct OP_AggStep_stack_vars {
int n;
int i;
@@ -63951,34 +64581,36 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
Mem *pRec;
sqlite3_context ctx;
sqlite3_value **apVal;
- } cf;
+ } cg;
struct OP_AggFinal_stack_vars {
Mem *pMem;
- } cg;
+ } ch;
struct OP_Checkpoint_stack_vars {
int i; /* Loop counter */
int aRes[3]; /* Results */
Mem *pMem; /* Write results here */
- } ch;
+ } ci;
struct OP_JournalMode_stack_vars {
Btree *pBt; /* Btree to change journal mode of */
Pager *pPager; /* Pager associated with pBt */
int eNew; /* New journal mode */
int eOld; /* The old journal mode */
+#ifndef SQLITE_OMIT_WAL
const char *zFilename; /* Name of database file for pPager */
- } ci;
+#endif
+ } cj;
struct OP_IncrVacuum_stack_vars {
Btree *pBt;
- } cj;
+ } ck;
struct OP_VBegin_stack_vars {
VTable *pVTab;
- } ck;
+ } cl;
struct OP_VOpen_stack_vars {
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
- } cl;
+ } cm;
struct OP_VFilter_stack_vars {
int nArg;
int iQuery;
@@ -63991,23 +64623,23 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
int res;
int i;
Mem **apArg;
- } cm;
+ } cn;
struct OP_VColumn_stack_vars {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
- } cn;
+ } co;
struct OP_VNext_stack_vars {
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
- } co;
+ } cp;
struct OP_VRename_stack_vars {
sqlite3_vtab *pVtab;
Mem *pName;
- } cp;
+ } cq;
struct OP_VUpdate_stack_vars {
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
@@ -64016,11 +64648,11 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
sqlite_int64 rowid;
Mem **apArg;
Mem *pX;
- } cq;
+ } cr;
struct OP_Trace_stack_vars {
char *zTrace;
char *z;
- } cr;
+ } cs;
} u;
/* End automatically generated code
********************************************************************/
@@ -64322,7 +64954,7 @@ case OP_Halt: {
if( rc==SQLITE_BUSY ){
p->rc = rc = SQLITE_BUSY;
}else{
- assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT );
+ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
assert( rc==SQLITE_OK || db->nDeferredCons>0 );
rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
}
@@ -64411,25 +65043,30 @@ case OP_String: { /* out2-prerelease */
break;
}
-/* Opcode: Null * P2 P3 * *
+/* Opcode: Null P1 P2 P3 * *
**
** Write a NULL into registers P2. If P3 greater than P2, then also write
-** NULL into register P3 and ever register in between P2 and P3. If P3
+** NULL into register P3 and every register in between P2 and P3. If P3
** is less than P2 (typically P3 is zero) then only register P2 is
-** set to NULL
+** set to NULL.
+**
+** If the P1 value is non-zero, then also set the MEM_Cleared flag so that
+** NULL values will not compare equal even if SQLITE_NULLEQ is set on
+** OP_Ne or OP_Eq.
*/
case OP_Null: { /* out2-prerelease */
#if 0 /* local variables moved into u.ab */
int cnt;
+ u16 nullFlag;
#endif /* local variables moved into u.ab */
u.ab.cnt = pOp->p3-pOp->p2;
assert( pOp->p3<=p->nMem );
- pOut->flags = MEM_Null;
+ pOut->flags = u.ab.nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
while( u.ab.cnt>0 ){
pOut++;
memAboutToChange(p, pOut);
VdbeMemRelease(pOut);
- pOut->flags = MEM_Null;
+ pOut->flags = u.ab.nullFlag;
u.ab.cnt--;
}
break;
@@ -64474,10 +65111,10 @@ case OP_Variable: { /* out2-prerelease */
/* Opcode: Move P1 P2 P3 * *
**
-** Move the values in register P1..P1+P3-1 over into
-** registers P2..P2+P3-1. Registers P1..P1+P1-1 are
+** Move the values in register P1..P1+P3 over into
+** registers P2..P2+P3. Registers P1..P1+P3 are
** left holding a NULL. It is an error for register ranges
-** P1..P1+P3-1 and P2..P2+P3-1 to overlap.
+** P1..P1+P3 and P2..P2+P3 to overlap.
*/
case OP_Move: {
#if 0 /* local variables moved into u.ad */
@@ -64487,7 +65124,7 @@ case OP_Move: {
int p2; /* Register to copy to */
#endif /* local variables moved into u.ad */
- u.ad.n = pOp->p3;
+ u.ad.n = pOp->p3 + 1;
u.ad.p1 = pOp->p1;
u.ad.p2 = pOp->p2;
assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 );
@@ -64516,20 +65153,33 @@ case OP_Move: {
break;
}
-/* Opcode: Copy P1 P2 * * *
+/* Opcode: Copy P1 P2 P3 * *
**
-** Make a copy of register P1 into register P2.
+** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
**
** This instruction makes a deep copy of the value. A duplicate
** is made of any string or blob constant. See also OP_SCopy.
*/
-case OP_Copy: { /* in1, out2 */
+case OP_Copy: {
+#if 0 /* local variables moved into u.ae */
+ int n;
+#endif /* local variables moved into u.ae */
+
+ u.ae.n = pOp->p3;
pIn1 = &aMem[pOp->p1];
pOut = &aMem[pOp->p2];
assert( pOut!=pIn1 );
- sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
- Deephemeralize(pOut);
- REGISTER_TRACE(pOp->p2, pOut);
+ while( 1 ){
+ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
+ Deephemeralize(pOut);
+#ifdef SQLITE_DEBUG
+ pOut->pScopyFrom = 0;
+#endif
+ REGISTER_TRACE(pOp->p2+pOp->p3-u.ae.n, pOut);
+ if( (u.ae.n--)==0 ) break;
+ pOut++;
+ pIn1++;
+ }
break;
}
@@ -64566,10 +65216,10 @@ case OP_SCopy: { /* in1, out2 */
** row.
*/
case OP_ResultRow: {
-#if 0 /* local variables moved into u.ae */
+#if 0 /* local variables moved into u.af */
Mem *pMem;
int i;
-#endif /* local variables moved into u.ae */
+#endif /* local variables moved into u.af */
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 );
assert( pOp->p1+pOp->p2<=p->nMem+1 );
@@ -64611,15 +65261,15 @@ case OP_ResultRow: {
** and have an assigned type. The results are de-ephemeralized as
** a side effect.
*/
- u.ae.pMem = p->pResultSet = &aMem[pOp->p1];
- for(u.ae.i=0; u.ae.ip2; u.ae.i++){
- assert( memIsValid(&u.ae.pMem[u.ae.i]) );
- Deephemeralize(&u.ae.pMem[u.ae.i]);
- assert( (u.ae.pMem[u.ae.i].flags & MEM_Ephem)==0
- || (u.ae.pMem[u.ae.i].flags & (MEM_Str|MEM_Blob))==0 );
- sqlite3VdbeMemNulTerminate(&u.ae.pMem[u.ae.i]);
- sqlite3VdbeMemStoreType(&u.ae.pMem[u.ae.i]);
- REGISTER_TRACE(pOp->p1+u.ae.i, &u.ae.pMem[u.ae.i]);
+ u.af.pMem = p->pResultSet = &aMem[pOp->p1];
+ for(u.af.i=0; u.af.ip2; u.af.i++){
+ assert( memIsValid(&u.af.pMem[u.af.i]) );
+ Deephemeralize(&u.af.pMem[u.af.i]);
+ assert( (u.af.pMem[u.af.i].flags & MEM_Ephem)==0
+ || (u.af.pMem[u.af.i].flags & (MEM_Str|MEM_Blob))==0 );
+ sqlite3VdbeMemNulTerminate(&u.af.pMem[u.af.i]);
+ sqlite3VdbeMemStoreType(&u.af.pMem[u.af.i]);
+ REGISTER_TRACE(pOp->p1+u.af.i, &u.af.pMem[u.af.i]);
}
if( db->mallocFailed ) goto no_mem;
@@ -64643,9 +65293,9 @@ case OP_ResultRow: {
** to avoid a memcpy().
*/
case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
-#if 0 /* local variables moved into u.af */
+#if 0 /* local variables moved into u.ag */
i64 nByte;
-#endif /* local variables moved into u.af */
+#endif /* local variables moved into u.ag */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
@@ -64658,22 +65308,22 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
Stringify(pIn1, encoding);
Stringify(pIn2, encoding);
- u.af.nByte = pIn1->n + pIn2->n;
- if( u.af.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ u.ag.nByte = pIn1->n + pIn2->n;
+ if( u.ag.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
MemSetTypeFlag(pOut, MEM_Str);
- if( sqlite3VdbeMemGrow(pOut, (int)u.af.nByte+2, pOut==pIn2) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)u.ag.nByte+2, pOut==pIn2) ){
goto no_mem;
}
if( pOut!=pIn2 ){
memcpy(pOut->z, pIn2->z, pIn2->n);
}
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
- pOut->z[u.af.nByte] = 0;
- pOut->z[u.af.nByte+1] = 0;
+ pOut->z[u.ag.nByte] = 0;
+ pOut->z[u.ag.nByte+1] = 0;
pOut->flags |= MEM_Term;
- pOut->n = (int)u.af.nByte;
+ pOut->n = (int)u.ag.nByte;
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -64717,76 +65367,79 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */
case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
-#if 0 /* local variables moved into u.ag */
+#if 0 /* local variables moved into u.ah */
+ char bIntint; /* Started out as two integer operands */
int flags; /* Combined MEM_* flags from both inputs */
i64 iA; /* Integer value of left operand */
i64 iB; /* Integer value of right operand */
double rA; /* Real value of left operand */
double rB; /* Real value of right operand */
-#endif /* local variables moved into u.ag */
+#endif /* local variables moved into u.ah */
pIn1 = &aMem[pOp->p1];
applyNumericAffinity(pIn1);
pIn2 = &aMem[pOp->p2];
applyNumericAffinity(pIn2);
pOut = &aMem[pOp->p3];
- u.ag.flags = pIn1->flags | pIn2->flags;
- if( (u.ag.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
+ u.ah.flags = pIn1->flags | pIn2->flags;
+ if( (u.ah.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){
- u.ag.iA = pIn1->u.i;
- u.ag.iB = pIn2->u.i;
+ u.ah.iA = pIn1->u.i;
+ u.ah.iB = pIn2->u.i;
+ u.ah.bIntint = 1;
switch( pOp->opcode ){
- case OP_Add: if( sqlite3AddInt64(&u.ag.iB,u.ag.iA) ) goto fp_math; break;
- case OP_Subtract: if( sqlite3SubInt64(&u.ag.iB,u.ag.iA) ) goto fp_math; break;
- case OP_Multiply: if( sqlite3MulInt64(&u.ag.iB,u.ag.iA) ) goto fp_math; break;
+ case OP_Add: if( sqlite3AddInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
+ case OP_Subtract: if( sqlite3SubInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
+ case OP_Multiply: if( sqlite3MulInt64(&u.ah.iB,u.ah.iA) ) goto fp_math; break;
case OP_Divide: {
- if( u.ag.iA==0 ) goto arithmetic_result_is_null;
- if( u.ag.iA==-1 && u.ag.iB==SMALLEST_INT64 ) goto fp_math;
- u.ag.iB /= u.ag.iA;
+ if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ah.iA==-1 && u.ah.iB==SMALLEST_INT64 ) goto fp_math;
+ u.ah.iB /= u.ah.iA;
break;
}
default: {
- if( u.ag.iA==0 ) goto arithmetic_result_is_null;
- if( u.ag.iA==-1 ) u.ag.iA = 1;
- u.ag.iB %= u.ag.iA;
+ if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ah.iA==-1 ) u.ah.iA = 1;
+ u.ah.iB %= u.ah.iA;
break;
}
}
- pOut->u.i = u.ag.iB;
+ pOut->u.i = u.ah.iB;
MemSetTypeFlag(pOut, MEM_Int);
}else{
+ u.ah.bIntint = 0;
fp_math:
- u.ag.rA = sqlite3VdbeRealValue(pIn1);
- u.ag.rB = sqlite3VdbeRealValue(pIn2);
+ u.ah.rA = sqlite3VdbeRealValue(pIn1);
+ u.ah.rB = sqlite3VdbeRealValue(pIn2);
switch( pOp->opcode ){
- case OP_Add: u.ag.rB += u.ag.rA; break;
- case OP_Subtract: u.ag.rB -= u.ag.rA; break;
- case OP_Multiply: u.ag.rB *= u.ag.rA; break;
+ case OP_Add: u.ah.rB += u.ah.rA; break;
+ case OP_Subtract: u.ah.rB -= u.ah.rA; break;
+ case OP_Multiply: u.ah.rB *= u.ah.rA; break;
case OP_Divide: {
/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
- if( u.ag.rA==(double)0 ) goto arithmetic_result_is_null;
- u.ag.rB /= u.ag.rA;
+ if( u.ah.rA==(double)0 ) goto arithmetic_result_is_null;
+ u.ah.rB /= u.ah.rA;
break;
}
default: {
- u.ag.iA = (i64)u.ag.rA;
- u.ag.iB = (i64)u.ag.rB;
- if( u.ag.iA==0 ) goto arithmetic_result_is_null;
- if( u.ag.iA==-1 ) u.ag.iA = 1;
- u.ag.rB = (double)(u.ag.iB % u.ag.iA);
+ u.ah.iA = (i64)u.ah.rA;
+ u.ah.iB = (i64)u.ah.rB;
+ if( u.ah.iA==0 ) goto arithmetic_result_is_null;
+ if( u.ah.iA==-1 ) u.ah.iA = 1;
+ u.ah.rB = (double)(u.ah.iB % u.ah.iA);
break;
}
}
#ifdef SQLITE_OMIT_FLOATING_POINT
- pOut->u.i = u.ag.rB;
+ pOut->u.i = u.ah.rB;
MemSetTypeFlag(pOut, MEM_Int);
#else
- if( sqlite3IsNaN(u.ag.rB) ){
+ if( sqlite3IsNaN(u.ah.rB) ){
goto arithmetic_result_is_null;
}
- pOut->r = u.ag.rB;
+ pOut->r = u.ah.rB;
MemSetTypeFlag(pOut, MEM_Real);
- if( (u.ag.flags & MEM_Real)==0 ){
+ if( (u.ah.flags & MEM_Real)==0 && !u.ah.bIntint ){
sqlite3VdbeIntegerAffinity(pOut);
}
#endif
@@ -64838,70 +65491,70 @@ case OP_CollSeq: {
** See also: AggStep and AggFinal
*/
case OP_Function: {
-#if 0 /* local variables moved into u.ah */
+#if 0 /* local variables moved into u.ai */
int i;
Mem *pArg;
sqlite3_context ctx;
sqlite3_value **apVal;
int n;
-#endif /* local variables moved into u.ah */
+#endif /* local variables moved into u.ai */
- u.ah.n = pOp->p5;
- u.ah.apVal = p->apArg;
- assert( u.ah.apVal || u.ah.n==0 );
+ u.ai.n = pOp->p5;
+ u.ai.apVal = p->apArg;
+ assert( u.ai.apVal || u.ai.n==0 );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
pOut = &aMem[pOp->p3];
memAboutToChange(p, pOut);
- assert( u.ah.n==0 || (pOp->p2>0 && pOp->p2+u.ah.n<=p->nMem+1) );
- assert( pOp->p3p2 || pOp->p3>=pOp->p2+u.ah.n );
- u.ah.pArg = &aMem[pOp->p2];
- for(u.ah.i=0; u.ah.ip2+u.ah.i, u.ah.pArg);
+ assert( u.ai.n==0 || (pOp->p2>0 && pOp->p2+u.ai.n<=p->nMem+1) );
+ assert( pOp->p3p2 || pOp->p3>=pOp->p2+u.ai.n );
+ u.ai.pArg = &aMem[pOp->p2];
+ for(u.ai.i=0; u.ai.ip2+u.ai.i, u.ai.pArg);
}
assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
if( pOp->p4type==P4_FUNCDEF ){
- u.ah.ctx.pFunc = pOp->p4.pFunc;
- u.ah.ctx.pVdbeFunc = 0;
+ u.ai.ctx.pFunc = pOp->p4.pFunc;
+ u.ai.ctx.pVdbeFunc = 0;
}else{
- u.ah.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
- u.ah.ctx.pFunc = u.ah.ctx.pVdbeFunc->pFunc;
+ u.ai.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
+ u.ai.ctx.pFunc = u.ai.ctx.pVdbeFunc->pFunc;
}
- u.ah.ctx.s.flags = MEM_Null;
- u.ah.ctx.s.db = db;
- u.ah.ctx.s.xDel = 0;
- u.ah.ctx.s.zMalloc = 0;
+ u.ai.ctx.s.flags = MEM_Null;
+ u.ai.ctx.s.db = db;
+ u.ai.ctx.s.xDel = 0;
+ u.ai.ctx.s.zMalloc = 0;
/* The output cell may already have a buffer allocated. Move
- ** the pointer to u.ah.ctx.s so in case the user-function can use
+ ** the pointer to u.ai.ctx.s so in case the user-function can use
** the already allocated buffer instead of allocating a new one.
*/
- sqlite3VdbeMemMove(&u.ah.ctx.s, pOut);
- MemSetTypeFlag(&u.ah.ctx.s, MEM_Null);
+ sqlite3VdbeMemMove(&u.ai.ctx.s, pOut);
+ MemSetTypeFlag(&u.ai.ctx.s, MEM_Null);
- u.ah.ctx.isError = 0;
- if( u.ah.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ u.ai.ctx.isError = 0;
+ if( u.ai.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
- u.ah.ctx.pColl = pOp[-1].p4.pColl;
+ u.ai.ctx.pColl = pOp[-1].p4.pColl;
}
db->lastRowid = lastRowid;
- (*u.ah.ctx.pFunc->xFunc)(&u.ah.ctx, u.ah.n, u.ah.apVal); /* IMP: R-24505-23230 */
+ (*u.ai.ctx.pFunc->xFunc)(&u.ai.ctx, u.ai.n, u.ai.apVal); /* IMP: R-24505-23230 */
lastRowid = db->lastRowid;
/* If any auxiliary data functions have been called by this user function,
** immediately call the destructor for any non-static values.
*/
- if( u.ah.ctx.pVdbeFunc ){
- sqlite3VdbeDeleteAuxData(u.ah.ctx.pVdbeFunc, pOp->p1);
- pOp->p4.pVdbeFunc = u.ah.ctx.pVdbeFunc;
+ if( u.ai.ctx.pVdbeFunc ){
+ sqlite3VdbeDeleteAuxData(u.ai.ctx.pVdbeFunc, pOp->p1);
+ pOp->p4.pVdbeFunc = u.ai.ctx.pVdbeFunc;
pOp->p4type = P4_VDBEFUNC;
}
@@ -64911,19 +65564,19 @@ case OP_Function: {
** to return a value. The following call releases any resources
** associated with such a value.
*/
- sqlite3VdbeMemRelease(&u.ah.ctx.s);
+ sqlite3VdbeMemRelease(&u.ai.ctx.s);
goto no_mem;
}
/* If the function returned an error, throw an exception */
- if( u.ah.ctx.isError ){
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ah.ctx.s));
- rc = u.ah.ctx.isError;
+ if( u.ai.ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.ai.ctx.s));
+ rc = u.ai.ctx.isError;
}
/* Copy the result of the function into register P3 */
- sqlite3VdbeChangeEncoding(&u.ah.ctx.s, encoding);
- sqlite3VdbeMemMove(pOut, &u.ah.ctx.s);
+ sqlite3VdbeChangeEncoding(&u.ai.ctx.s, encoding);
+ sqlite3VdbeMemMove(pOut, &u.ai.ctx.s);
if( sqlite3VdbeMemTooBig(pOut) ){
goto too_big;
}
@@ -64971,12 +65624,12 @@ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */
case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */
case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */
case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
-#if 0 /* local variables moved into u.ai */
+#if 0 /* local variables moved into u.aj */
i64 iA;
u64 uA;
i64 iB;
u8 op;
-#endif /* local variables moved into u.ai */
+#endif /* local variables moved into u.aj */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
@@ -64985,38 +65638,38 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */
sqlite3VdbeMemSetNull(pOut);
break;
}
- u.ai.iA = sqlite3VdbeIntValue(pIn2);
- u.ai.iB = sqlite3VdbeIntValue(pIn1);
- u.ai.op = pOp->opcode;
- if( u.ai.op==OP_BitAnd ){
- u.ai.iA &= u.ai.iB;
- }else if( u.ai.op==OP_BitOr ){
- u.ai.iA |= u.ai.iB;
- }else if( u.ai.iB!=0 ){
- assert( u.ai.op==OP_ShiftRight || u.ai.op==OP_ShiftLeft );
+ u.aj.iA = sqlite3VdbeIntValue(pIn2);
+ u.aj.iB = sqlite3VdbeIntValue(pIn1);
+ u.aj.op = pOp->opcode;
+ if( u.aj.op==OP_BitAnd ){
+ u.aj.iA &= u.aj.iB;
+ }else if( u.aj.op==OP_BitOr ){
+ u.aj.iA |= u.aj.iB;
+ }else if( u.aj.iB!=0 ){
+ assert( u.aj.op==OP_ShiftRight || u.aj.op==OP_ShiftLeft );
/* If shifting by a negative amount, shift in the other direction */
- if( u.ai.iB<0 ){
+ if( u.aj.iB<0 ){
assert( OP_ShiftRight==OP_ShiftLeft+1 );
- u.ai.op = 2*OP_ShiftLeft + 1 - u.ai.op;
- u.ai.iB = u.ai.iB>(-64) ? -u.ai.iB : 64;
+ u.aj.op = 2*OP_ShiftLeft + 1 - u.aj.op;
+ u.aj.iB = u.aj.iB>(-64) ? -u.aj.iB : 64;
}
- if( u.ai.iB>=64 ){
- u.ai.iA = (u.ai.iA>=0 || u.ai.op==OP_ShiftLeft) ? 0 : -1;
+ if( u.aj.iB>=64 ){
+ u.aj.iA = (u.aj.iA>=0 || u.aj.op==OP_ShiftLeft) ? 0 : -1;
}else{
- memcpy(&u.ai.uA, &u.ai.iA, sizeof(u.ai.uA));
- if( u.ai.op==OP_ShiftLeft ){
- u.ai.uA <<= u.ai.iB;
+ memcpy(&u.aj.uA, &u.aj.iA, sizeof(u.aj.uA));
+ if( u.aj.op==OP_ShiftLeft ){
+ u.aj.uA <<= u.aj.iB;
}else{
- u.ai.uA >>= u.ai.iB;
+ u.aj.uA >>= u.aj.iB;
/* Sign-extend on a right shift of a negative number */
- if( u.ai.iA<0 ) u.ai.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.ai.iB);
+ if( u.aj.iA<0 ) u.aj.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.aj.iB);
}
- memcpy(&u.ai.iA, &u.ai.uA, sizeof(u.ai.iA));
+ memcpy(&u.aj.iA, &u.aj.uA, sizeof(u.aj.iA));
}
}
- pOut->u.i = u.ai.iA;
+ pOut->u.i = u.aj.iA;
MemSetTypeFlag(pOut, MEM_Int);
break;
}
@@ -65208,6 +65861,10 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
**
** If the SQLITE_STOREP2 bit of P5 is set, then do not jump. Instead,
** store a boolean result (either 0, or 1, or NULL) in register P2.
+**
+** If the SQLITE_NULLEQ bit is set in P5, then NULL values are considered
+** equal to one another, provided that they do not have their MEM_Cleared
+** bit set.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
**
@@ -65257,18 +65914,18 @@ case OP_Lt: /* same as TK_LT, jump, in1, in3 */
case OP_Le: /* same as TK_LE, jump, in1, in3 */
case OP_Gt: /* same as TK_GT, jump, in1, in3 */
case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
-#if 0 /* local variables moved into u.aj */
+#if 0 /* local variables moved into u.ak */
int res; /* Result of the comparison of pIn1 against pIn3 */
char affinity; /* Affinity to use for comparison */
u16 flags1; /* Copy of initial value of pIn1->flags */
u16 flags3; /* Copy of initial value of pIn3->flags */
-#endif /* local variables moved into u.aj */
+#endif /* local variables moved into u.ak */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
- u.aj.flags1 = pIn1->flags;
- u.aj.flags3 = pIn3->flags;
- if( (u.aj.flags1 | u.aj.flags3)&MEM_Null ){
+ u.ak.flags1 = pIn1->flags;
+ u.ak.flags3 = pIn3->flags;
+ if( (u.ak.flags1 | u.ak.flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
/* If SQLITE_NULLEQ is set (which will only happen if the operator is
@@ -65276,7 +65933,15 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** or not both operands are null.
*/
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
- u.aj.res = (u.aj.flags1 & u.aj.flags3 & MEM_Null)==0;
+ assert( (u.ak.flags1 & MEM_Cleared)==0 );
+ if( (u.ak.flags1&MEM_Null)!=0
+ && (u.ak.flags3&MEM_Null)!=0
+ && (u.ak.flags3&MEM_Cleared)==0
+ ){
+ u.ak.res = 0; /* Results are equal */
+ }else{
+ u.ak.res = 1; /* Results are not equal */
+ }
}else{
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
** then the result is always NULL.
@@ -65293,40 +65958,40 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}
}else{
/* Neither operand is NULL. Do a comparison. */
- u.aj.affinity = pOp->p5 & SQLITE_AFF_MASK;
- if( u.aj.affinity ){
- applyAffinity(pIn1, u.aj.affinity, encoding);
- applyAffinity(pIn3, u.aj.affinity, encoding);
+ u.ak.affinity = pOp->p5 & SQLITE_AFF_MASK;
+ if( u.ak.affinity ){
+ applyAffinity(pIn1, u.ak.affinity, encoding);
+ applyAffinity(pIn3, u.ak.affinity, encoding);
if( db->mallocFailed ) goto no_mem;
}
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
ExpandBlob(pIn1);
ExpandBlob(pIn3);
- u.aj.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
+ u.ak.res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
switch( pOp->opcode ){
- case OP_Eq: u.aj.res = u.aj.res==0; break;
- case OP_Ne: u.aj.res = u.aj.res!=0; break;
- case OP_Lt: u.aj.res = u.aj.res<0; break;
- case OP_Le: u.aj.res = u.aj.res<=0; break;
- case OP_Gt: u.aj.res = u.aj.res>0; break;
- default: u.aj.res = u.aj.res>=0; break;
+ case OP_Eq: u.ak.res = u.ak.res==0; break;
+ case OP_Ne: u.ak.res = u.ak.res!=0; break;
+ case OP_Lt: u.ak.res = u.ak.res<0; break;
+ case OP_Le: u.ak.res = u.ak.res<=0; break;
+ case OP_Gt: u.ak.res = u.ak.res>0; break;
+ default: u.ak.res = u.ak.res>=0; break;
}
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = u.aj.res;
+ pOut->u.i = u.ak.res;
REGISTER_TRACE(pOp->p2, pOut);
- }else if( u.aj.res ){
+ }else if( u.ak.res ){
pc = pOp->p2-1;
}
/* Undo any changes made by applyAffinity() to the input registers. */
- pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.aj.flags1&MEM_TypeMask);
- pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.aj.flags3&MEM_TypeMask);
+ pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.ak.flags1&MEM_TypeMask);
+ pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.ak.flags3&MEM_TypeMask);
break;
}
@@ -65335,9 +66000,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.
**
-** The permutation is only valid until the next OP_Permutation, OP_Compare,
-** OP_Halt, or OP_ResultRow. Typically the OP_Permutation should occur
-** immediately prior to the OP_Compare.
+** The permutation is only valid until the next OP_Compare that has
+** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
+** occur immediately prior to the OP_Compare.
*/
case OP_Permutation: {
assert( pOp->p4type==P4_INTARRAY );
@@ -65346,12 +66011,17 @@ case OP_Permutation: {
break;
}
-/* Opcode: Compare P1 P2 P3 P4 *
+/* Opcode: Compare P1 P2 P3 P4 P5
**
** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of
** the comparison for use by the next OP_Jump instruct.
**
+** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is
+** determined by the most recent OP_Permutation operator. If the
+** OPFLAG_PERMUTE bit is clear, then register are compared in sequential
+** order.
+**
** P4 is a KeyInfo structure that defines collating sequences and sort
** orders for the comparison. The permutation applies to registers
** only. The KeyInfo elements are used sequentially.
@@ -65361,7 +66031,7 @@ case OP_Permutation: {
** and strings are less than blobs.
*/
case OP_Compare: {
-#if 0 /* local variables moved into u.ak */
+#if 0 /* local variables moved into u.al */
int n;
int i;
int p1;
@@ -65370,37 +66040,38 @@ case OP_Compare: {
int idx;
CollSeq *pColl; /* Collating sequence to use on this term */
int bRev; /* True for DESCENDING sort order */
-#endif /* local variables moved into u.ak */
+#endif /* local variables moved into u.al */
- u.ak.n = pOp->p3;
- u.ak.pKeyInfo = pOp->p4.pKeyInfo;
- assert( u.ak.n>0 );
- assert( u.ak.pKeyInfo!=0 );
- u.ak.p1 = pOp->p1;
- u.ak.p2 = pOp->p2;
+ if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0;
+ u.al.n = pOp->p3;
+ u.al.pKeyInfo = pOp->p4.pKeyInfo;
+ assert( u.al.n>0 );
+ assert( u.al.pKeyInfo!=0 );
+ u.al.p1 = pOp->p1;
+ u.al.p2 = pOp->p2;
#if SQLITE_DEBUG
if( aPermute ){
int k, mx = 0;
- for(k=0; kmx ) mx = aPermute[k];
- assert( u.ak.p1>0 && u.ak.p1+mx<=p->nMem+1 );
- assert( u.ak.p2>0 && u.ak.p2+mx<=p->nMem+1 );
+ for(k=0; kmx ) mx = aPermute[k];
+ assert( u.al.p1>0 && u.al.p1+mx<=p->nMem+1 );
+ assert( u.al.p2>0 && u.al.p2+mx<=p->nMem+1 );
}else{
- assert( u.ak.p1>0 && u.ak.p1+u.ak.n<=p->nMem+1 );
- assert( u.ak.p2>0 && u.ak.p2+u.ak.n<=p->nMem+1 );
+ assert( u.al.p1>0 && u.al.p1+u.al.n<=p->nMem+1 );
+ assert( u.al.p2>0 && u.al.p2+u.al.n<=p->nMem+1 );
}
#endif /* SQLITE_DEBUG */
- for(u.ak.i=0; u.ak.inField );
- u.ak.pColl = u.ak.pKeyInfo->aColl[u.ak.i];
- u.ak.bRev = u.ak.pKeyInfo->aSortOrder[u.ak.i];
- iCompare = sqlite3MemCompare(&aMem[u.ak.p1+u.ak.idx], &aMem[u.ak.p2+u.ak.idx], u.ak.pColl);
+ for(u.al.i=0; u.al.inField );
+ u.al.pColl = u.al.pKeyInfo->aColl[u.al.i];
+ u.al.bRev = u.al.pKeyInfo->aSortOrder[u.al.i];
+ iCompare = sqlite3MemCompare(&aMem[u.al.p1+u.al.idx], &aMem[u.al.p2+u.al.idx], u.al.pColl);
if( iCompare ){
- if( u.ak.bRev ) iCompare = -iCompare;
+ if( u.al.bRev ) iCompare = -iCompare;
break;
}
}
@@ -65445,35 +66116,35 @@ case OP_Jump: { /* jump */
*/
case OP_And: /* same as TK_AND, in1, in2, out3 */
case OP_Or: { /* same as TK_OR, in1, in2, out3 */
-#if 0 /* local variables moved into u.al */
+#if 0 /* local variables moved into u.am */
int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
-#endif /* local variables moved into u.al */
+#endif /* local variables moved into u.am */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ){
- u.al.v1 = 2;
+ u.am.v1 = 2;
}else{
- u.al.v1 = sqlite3VdbeIntValue(pIn1)!=0;
+ u.am.v1 = sqlite3VdbeIntValue(pIn1)!=0;
}
pIn2 = &aMem[pOp->p2];
if( pIn2->flags & MEM_Null ){
- u.al.v2 = 2;
+ u.am.v2 = 2;
}else{
- u.al.v2 = sqlite3VdbeIntValue(pIn2)!=0;
+ u.am.v2 = sqlite3VdbeIntValue(pIn2)!=0;
}
if( pOp->opcode==OP_And ){
static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
- u.al.v1 = and_logic[u.al.v1*3+u.al.v2];
+ u.am.v1 = and_logic[u.am.v1*3+u.am.v2];
}else{
static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
- u.al.v1 = or_logic[u.al.v1*3+u.al.v2];
+ u.am.v1 = or_logic[u.am.v1*3+u.am.v2];
}
pOut = &aMem[pOp->p3];
- if( u.al.v1==2 ){
+ if( u.am.v1==2 ){
MemSetTypeFlag(pOut, MEM_Null);
}else{
- pOut->u.i = u.al.v1;
+ pOut->u.i = u.am.v1;
MemSetTypeFlag(pOut, MEM_Int);
}
break;
@@ -65517,8 +66188,6 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
**
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
** set the flag and fall through to the next instruction.
-**
-** See also: JumpOnce
*/
case OP_Once: { /* jump */
assert( pOp->p1nOnceFlag );
@@ -65544,21 +66213,21 @@ case OP_Once: { /* jump */
*/
case OP_If: /* jump, in1 */
case OP_IfNot: { /* jump, in1 */
-#if 0 /* local variables moved into u.am */
+#if 0 /* local variables moved into u.an */
int c;
-#endif /* local variables moved into u.am */
+#endif /* local variables moved into u.an */
pIn1 = &aMem[pOp->p1];
if( pIn1->flags & MEM_Null ){
- u.am.c = pOp->p3;
+ u.an.c = pOp->p3;
}else{
#ifdef SQLITE_OMIT_FLOATING_POINT
- u.am.c = sqlite3VdbeIntValue(pIn1)!=0;
+ u.an.c = sqlite3VdbeIntValue(pIn1)!=0;
#else
- u.am.c = sqlite3VdbeRealValue(pIn1)!=0.0;
+ u.an.c = sqlite3VdbeRealValue(pIn1)!=0.0;
#endif
- if( pOp->opcode==OP_IfNot ) u.am.c = !u.am.c;
+ if( pOp->opcode==OP_IfNot ) u.an.c = !u.an.c;
}
- if( u.am.c ){
+ if( u.an.c ){
pc = pOp->p2-1;
}
break;
@@ -65613,7 +66282,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
** skipped for length() and all content loading can be skipped for typeof().
*/
case OP_Column: {
-#if 0 /* local variables moved into u.an */
+#if 0 /* local variables moved into u.ao */
u32 payloadSize; /* Number of bytes in the record */
i64 payloadSize64; /* Number of bytes in the record */
int p1; /* P1 value of the opcode */
@@ -65637,126 +66306,131 @@ case OP_Column: {
int avail; /* Number of bytes of available data */
u32 t; /* A type code from the record header */
Mem *pReg; /* PseudoTable input register */
-#endif /* local variables moved into u.an */
+#endif /* local variables moved into u.ao */
- 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.p1nCursor );
+ u.ao.p1 = pOp->p1;
+ u.ao.p2 = pOp->p2;
+ u.ao.pC = 0;
+ memset(&u.ao.sMem, 0, sizeof(u.ao.sMem));
+ assert( u.ao.p1nCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.an.pDest = &aMem[pOp->p3];
- memAboutToChange(p, u.an.pDest);
- u.an.zRec = 0;
+ u.ao.pDest = &aMem[pOp->p3];
+ memAboutToChange(p, u.ao.pDest);
+ u.ao.zRec = 0;
- /* This block sets the variable u.an.payloadSize to be the total number of
+ /* This block sets the variable u.ao.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.ao.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.ao.pC->aRow cache. Or it might not be.
+ ** If the data is unavailable, u.ao.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 );
+ u.ao.pC = p->apCsr[u.ao.p1];
+ assert( u.ao.pC!=0 );
#ifndef SQLITE_OMIT_VIRTUALTABLE
- assert( u.an.pC->pVtabCursor==0 );
+ assert( u.ao.pC->pVtabCursor==0 );
#endif
- u.an.pCrsr = u.an.pC->pCursor;
- if( u.an.pCrsr!=0 ){
+ u.ao.pCrsr = u.ao.pC->pCursor;
+ if( u.ao.pCrsr!=0 ){
/* The record is stored in a B-Tree */
- rc = sqlite3VdbeCursorMoveto(u.an.pC);
+ rc = sqlite3VdbeCursorMoveto(u.ao.pC);
if( rc ) goto abort_due_to_error;
- 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 ){
- assert( sqlite3BtreeCursorIsValid(u.an.pCrsr) );
- VVA_ONLY(rc =) sqlite3BtreeKeySize(u.an.pCrsr, &u.an.payloadSize64);
+ if( u.ao.pC->nullRow ){
+ u.ao.payloadSize = 0;
+ }else if( u.ao.pC->cacheStatus==p->cacheCtr ){
+ u.ao.payloadSize = u.ao.pC->payloadSize;
+ u.ao.zRec = (char*)u.ao.pC->aRow;
+ }else if( u.ao.pC->isIndex ){
+ assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(u.ao.pCrsr, &u.ao.payloadSize64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
/* sqlite3BtreeParseCellPtr() uses getVarint32() to extract the
- ** payload size, so it is impossible for u.an.payloadSize64 to be
+ ** payload size, so it is impossible for u.ao.payloadSize64 to be
** larger than 32 bits. */
- assert( (u.an.payloadSize64 & SQLITE_MAX_U32)==(u64)u.an.payloadSize64 );
- u.an.payloadSize = (u32)u.an.payloadSize64;
+ assert( (u.ao.payloadSize64 & SQLITE_MAX_U32)==(u64)u.ao.payloadSize64 );
+ u.ao.payloadSize = (u32)u.ao.payloadSize64;
}else{
- assert( sqlite3BtreeCursorIsValid(u.an.pCrsr) );
- VVA_ONLY(rc =) sqlite3BtreeDataSize(u.an.pCrsr, &u.an.payloadSize);
+ assert( sqlite3BtreeCursorIsValid(u.ao.pCrsr) );
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(u.ao.pCrsr, &u.ao.payloadSize);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
}
- }else if( ALWAYS(u.an.pC->pseudoTableReg>0) ){
- u.an.pReg = &aMem[u.an.pC->pseudoTableReg];
- assert( u.an.pReg->flags & MEM_Blob );
- assert( memIsValid(u.an.pReg) );
- u.an.payloadSize = u.an.pReg->n;
- u.an.zRec = u.an.pReg->z;
- u.an.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
- assert( u.an.payloadSize==0 || u.an.zRec!=0 );
+ }else if( ALWAYS(u.ao.pC->pseudoTableReg>0) ){
+ u.ao.pReg = &aMem[u.ao.pC->pseudoTableReg];
+ if( u.ao.pC->multiPseudo ){
+ sqlite3VdbeMemShallowCopy(u.ao.pDest, u.ao.pReg+u.ao.p2, MEM_Ephem);
+ Deephemeralize(u.ao.pDest);
+ goto op_column_out;
+ }
+ assert( u.ao.pReg->flags & MEM_Blob );
+ assert( memIsValid(u.ao.pReg) );
+ u.ao.payloadSize = u.ao.pReg->n;
+ u.ao.zRec = u.ao.pReg->z;
+ u.ao.pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
+ assert( u.ao.payloadSize==0 || u.ao.zRec!=0 );
}else{
/* Consider the row to be NULL */
- u.an.payloadSize = 0;
+ u.ao.payloadSize = 0;
}
- /* If u.an.payloadSize is 0, then just store a NULL. This can happen because of
+ /* If u.ao.payloadSize is 0, then just store a NULL. This can happen because of
** nullRow or because of a corrupt database. */
- if( u.an.payloadSize==0 ){
- MemSetTypeFlag(u.an.pDest, MEM_Null);
+ if( u.ao.payloadSize==0 ){
+ MemSetTypeFlag(u.ao.pDest, 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.ao.payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- u.an.nField = u.an.pC->nField;
- assert( u.an.p2nField;
+ assert( u.ao.p2aType;
- if( u.an.pC->cacheStatus==p->cacheCtr ){
- u.an.aOffset = u.an.pC->aOffset;
+ u.ao.aType = u.ao.pC->aType;
+ if( u.ao.pC->cacheStatus==p->cacheCtr ){
+ u.ao.aOffset = u.ao.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;
+ assert(u.ao.aType);
+ u.ao.avail = 0;
+ u.ao.pC->aOffset = u.ao.aOffset = &u.ao.aType[u.ao.nField];
+ u.ao.pC->payloadSize = u.ao.payloadSize;
+ u.ao.pC->cacheStatus = p->cacheCtr;
/* Figure out how many bytes are in the header */
- if( u.an.zRec ){
- u.an.zData = u.an.zRec;
+ if( u.ao.zRec ){
+ u.ao.zData = u.ao.zRec;
}else{
- if( u.an.pC->isIndex ){
- u.an.zData = (char*)sqlite3BtreeKeyFetch(u.an.pCrsr, &u.an.avail);
+ if( u.ao.pC->isIndex ){
+ u.ao.zData = (char*)sqlite3BtreeKeyFetch(u.ao.pCrsr, &u.ao.avail);
}else{
- u.an.zData = (char*)sqlite3BtreeDataFetch(u.an.pCrsr, &u.an.avail);
+ u.ao.zData = (char*)sqlite3BtreeDataFetch(u.ao.pCrsr, &u.ao.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.ao.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;
+ assert( u.ao.avail>=0 );
+ if( u.ao.payloadSize <= (u32)u.ao.avail ){
+ u.ao.zRec = u.ao.zData;
+ u.ao.pC->aRow = (u8*)u.ao.zData;
}else{
- u.an.pC->aRow = 0;
+ u.ao.pC->aRow = 0;
}
}
/* The following assert is true in all cases except 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.ao.zRec!=0 || u.ao.avail>=u.ao.payloadSize || u.ao.avail>=9 ); */
+ u.ao.szHdr = getVarint32((u8*)u.ao.zData, u.ao.offset);
/* Make sure a corrupt database has not given us an oversize header.
** Do this now to avoid an oversize memory allocation.
@@ -65767,26 +66441,26 @@ case OP_Column: {
** 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.ao.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.ao.len the number of bytes of data we need to read in order
+ ** to get u.ao.nField type values. u.ao.offset is an upper bound on this. But
+ ** u.ao.nField might be significantly less than the true number of columns
+ ** in the table, and in that case, 5*u.ao.nField+3 might be smaller than u.ao.offset.
+ ** We want to minimize u.ao.len in order to limit the size of the memory
+ ** allocation, especially if a corrupt database file has caused u.ao.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.ao.nField*5+3
+ ** will likely be much smaller since u.ao.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 > (int)u.an.offset ) u.an.len = (int)u.an.offset;
+ u.ao.len = u.ao.nField*5 + 3;
+ if( u.ao.len > (int)u.ao.offset ) u.ao.len = (int)u.ao.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
@@ -65794,51 +66468,51 @@ case OP_Column: {
** in the B-Tree. When that happens, use sqlite3VdbeMemFromBtree() to
** acquire the complete header text.
*/
- if( !u.an.zRec && u.an.availisIndex, &u.an.sMem);
+ if( !u.ao.zRec && u.ao.availisIndex, &u.ao.sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
- u.an.zData = u.an.sMem.z;
+ u.ao.zData = u.ao.sMem.z;
}
- u.an.zEndHdr = (u8 *)&u.an.zData[u.an.len];
- u.an.zIdx = (u8 *)&u.an.zData[u.an.szHdr];
+ u.ao.zEndHdr = (u8 *)&u.ao.zData[u.ao.len];
+ u.ao.zIdx = (u8 *)&u.ao.zData[u.ao.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
+ /* Scan the header and use it to fill in the u.ao.aType[] and u.ao.aOffset[]
+ ** arrays. u.ao.aType[u.ao.i] will contain the type integer for the u.ao.i-th
+ ** column and u.ao.aOffset[u.ao.i] will contain the u.ao.offset from the beginning
+ ** of the record to the start of the data for the u.ao.i-th column
*/
- for(u.an.i=0; u.an.i u.an.zEndHdr) || (u.an.offset > u.an.payloadSize)
- || (u.an.zIdx==u.an.zEndHdr && u.an.offset!=u.an.payloadSize) ){
+ if( (u.ao.zIdx > u.ao.zEndHdr) || (u.ao.offset > u.ao.payloadSize)
+ || (u.ao.zIdx==u.ao.zEndHdr && u.ao.offset!=u.ao.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.ao.aOffset[u.ao.p2] is non-zero, then
+ ** deserialize the value from the record. If u.ao.aOffset[u.ao.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.ao.aOffset[u.ao.p2] ){
assert( rc==SQLITE_OK );
- if( u.an.zRec ){
+ if( u.ao.zRec ){
/* This is the common case where the whole row fits on a single page */
- VdbeMemRelease(u.an.pDest);
- sqlite3VdbeSerialGet((u8 *)&u.an.zRec[u.an.aOffset[u.an.p2]], u.an.aType[u.an.p2], u.an.pDest);
+ VdbeMemRelease(u.ao.pDest);
+ sqlite3VdbeSerialGet((u8 *)&u.ao.zRec[u.ao.aOffset[u.ao.p2]], u.ao.aType[u.ao.p2], u.ao.pDest);
}else{
/* This branch happens only when the row overflows onto multiple pages */
- u.an.t = u.an.aType[u.an.p2];
+ u.ao.t = u.ao.aType[u.ao.p2];
if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
- && ((u.an.t>=12 && (u.an.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
+ && ((u.ao.t>=12 && (u.ao.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0)
){
/* Content is irrelevant for the typeof() function and for
** the length(X) function if X is a blob. So we might as well use
** bogus content rather than reading content from disk. NULL works
- ** for text and blob and whatever is in the u.an.payloadSize64 variable
+ ** for text and blob and whatever is in the u.ao.payloadSize64 variable
** will work for everything else. */
- u.an.zData = u.an.t<12 ? (char*)&u.an.payloadSize64 : 0;
+ u.ao.zData = u.ao.t<12 ? (char*)&u.ao.payloadSize64 : 0;
}else{
- u.an.len = sqlite3VdbeSerialTypeLen(u.an.t);
- 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);
+ u.ao.len = sqlite3VdbeSerialTypeLen(u.ao.t);
+ sqlite3VdbeMemMove(&u.ao.sMem, u.ao.pDest);
+ rc = sqlite3VdbeMemFromBtree(u.ao.pCrsr, u.ao.aOffset[u.ao.p2], u.ao.len, u.ao.pC->isIndex,
+ &u.ao.sMem);
if( rc!=SQLITE_OK ){
goto op_column_out;
}
- u.an.zData = u.an.sMem.z;
+ u.ao.zData = u.ao.sMem.z;
}
- sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.t, u.an.pDest);
+ sqlite3VdbeSerialGet((u8*)u.ao.zData, u.ao.t, u.ao.pDest);
}
- u.an.pDest->enc = encoding;
+ u.ao.pDest->enc = encoding;
}else{
if( pOp->p4type==P4_MEM ){
- sqlite3VdbeMemShallowCopy(u.an.pDest, pOp->p4.pMem, MEM_Static);
+ sqlite3VdbeMemShallowCopy(u.ao.pDest, pOp->p4.pMem, MEM_Static);
}else{
- MemSetTypeFlag(u.an.pDest, MEM_Null);
+ MemSetTypeFlag(u.ao.pDest, 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.ao.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;
+ if( u.ao.sMem.zMalloc ){
+ assert( u.ao.sMem.z==u.ao.sMem.zMalloc );
+ assert( !(u.ao.pDest->flags & MEM_Dyn) );
+ assert( !(u.ao.pDest->flags & (MEM_Blob|MEM_Str)) || u.ao.pDest->z==u.ao.sMem.z );
+ u.ao.pDest->flags &= ~(MEM_Ephem|MEM_Static);
+ u.ao.pDest->flags |= MEM_Term;
+ u.ao.pDest->z = u.ao.sMem.z;
+ u.ao.pDest->zMalloc = u.ao.sMem.zMalloc;
}
- rc = sqlite3VdbeMemMakeWriteable(u.an.pDest);
+ rc = sqlite3VdbeMemMakeWriteable(u.ao.pDest);
op_column_out:
- UPDATE_MAX_BLOBSIZE(u.an.pDest);
- REGISTER_TRACE(pOp->p3, u.an.pDest);
+ UPDATE_MAX_BLOBSIZE(u.ao.pDest);
+ REGISTER_TRACE(pOp->p3, u.ao.pDest);
break;
}
@@ -65930,20 +66604,20 @@ op_column_out:
** memory cell in the range.
*/
case OP_Affinity: {
-#if 0 /* local variables moved into u.ao */
+#if 0 /* local variables moved into u.ap */
const char *zAffinity; /* The affinity to be applied */
char cAff; /* A single character of affinity */
-#endif /* local variables moved into u.ao */
+#endif /* local variables moved into u.ap */
- u.ao.zAffinity = pOp->p4.z;
- assert( u.ao.zAffinity!=0 );
- assert( u.ao.zAffinity[pOp->p2]==0 );
+ u.ap.zAffinity = pOp->p4.z;
+ assert( u.ap.zAffinity!=0 );
+ assert( u.ap.zAffinity[pOp->p2]==0 );
pIn1 = &aMem[pOp->p1];
- while( (u.ao.cAff = *(u.ao.zAffinity++))!=0 ){
+ while( (u.ap.cAff = *(u.ap.zAffinity++))!=0 ){
assert( pIn1 <= &p->aMem[p->nMem] );
assert( memIsValid(pIn1) );
ExpandBlob(pIn1);
- applyAffinity(pIn1, u.ao.cAff, encoding);
+ applyAffinity(pIn1, u.ap.cAff, encoding);
pIn1++;
}
break;
@@ -65965,7 +66639,7 @@ case OP_Affinity: {
** 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.aq */
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 */
@@ -65981,7 +66655,7 @@ case OP_MakeRecord: {
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.aq */
/* Assuming the record contains N fields, the record format looks
** like this:
@@ -65998,16 +66672,16 @@ case OP_MakeRecord: {
** 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.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 = &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.aq.nData = 0; /* Number of bytes of data space */
+ u.aq.nHdr = 0; /* Number of bytes of header space */
+ u.aq.nZero = 0; /* Number of zero bytes at the end of the record */
+ u.aq.nField = pOp->p1;
+ u.aq.zAffinity = pOp->p4.z;
+ assert( u.aq.nField>0 && pOp->p2>0 && pOp->p2+u.aq.nField<=p->nMem+1 );
+ u.aq.pData0 = &aMem[u.aq.nField];
+ u.aq.nField = pOp->p2;
+ u.aq.pLast = &u.aq.pData0[u.aq.nField-1];
+ u.aq.file_format = p->minWriteFileFormat;
/* Identify the output register */
assert( pOp->p3p1 || pOp->p3>=pOp->p1+pOp->p2 );
@@ -66017,34 +66691,34 @@ case OP_MakeRecord: {
/* 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++){
- assert( memIsValid(u.ap.pRec) );
- if( u.ap.zAffinity ){
- applyAffinity(u.ap.pRec, u.ap.zAffinity[u.ap.pRec-u.ap.pData0], encoding);
+ for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
+ assert( memIsValid(u.aq.pRec) );
+ if( u.aq.zAffinity ){
+ applyAffinity(u.aq.pRec, u.aq.zAffinity[u.aq.pRec-u.aq.pData0], encoding);
}
- if( u.ap.pRec->flags&MEM_Zero && u.ap.pRec->n>0 ){
- sqlite3VdbeMemExpandBlob(u.ap.pRec);
+ if( u.aq.pRec->flags&MEM_Zero && u.aq.pRec->n>0 ){
+ sqlite3VdbeMemExpandBlob(u.aq.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 ){
+ u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
+ u.aq.len = sqlite3VdbeSerialTypeLen(u.aq.serial_type);
+ u.aq.nData += u.aq.len;
+ u.aq.nHdr += sqlite3VarintLen(u.aq.serial_type);
+ if( u.aq.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.aq.nZero += u.aq.pRec->u.nZero;
+ }else if( u.aq.len ){
+ u.aq.nZero = 0;
}
}
/* Add the initial header varint and total the size */
- u.ap.nHdr += u.ap.nVarint = sqlite3VarintLen(u.ap.nHdr);
- if( u.ap.nVarintdb->aLimit[SQLITE_LIMIT_LENGTH] ){
+ u.aq.nByte = u.aq.nHdr+u.aq.nData-u.aq.nZero;
+ if( u.aq.nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
@@ -66053,28 +66727,28 @@ case OP_MakeRecord: {
** be one of the input registers (because the following call to
** sqlite3VdbeMemGrow() could clobber the value before it is used).
*/
- if( sqlite3VdbeMemGrow(pOut, (int)u.ap.nByte, 0) ){
+ if( sqlite3VdbeMemGrow(pOut, (int)u.aq.nByte, 0) ){
goto no_mem;
}
- u.ap.zNewRecord = (u8 *)pOut->z;
+ u.aq.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 */
+ u.aq.i = putVarint32(u.aq.zNewRecord, u.aq.nHdr);
+ for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){
+ u.aq.serial_type = sqlite3VdbeSerialType(u.aq.pRec, u.aq.file_format);
+ u.aq.i += putVarint32(&u.aq.zNewRecord[u.aq.i], u.aq.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);
+ for(u.aq.pRec=u.aq.pData0; u.aq.pRec<=u.aq.pLast; u.aq.pRec++){ /* serial data */
+ u.aq.i += sqlite3VdbeSerialPut(&u.aq.zNewRecord[u.aq.i], (int)(u.aq.nByte-u.aq.i), u.aq.pRec,u.aq.file_format);
}
- assert( u.ap.i==u.ap.nByte );
+ assert( u.aq.i==u.aq.nByte );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- pOut->n = (int)u.ap.nByte;
+ pOut->n = (int)u.aq.nByte;
pOut->flags = MEM_Blob | MEM_Dyn;
pOut->xDel = 0;
- if( u.ap.nZero ){
- pOut->u.nZero = u.ap.nZero;
+ if( u.aq.nZero ){
+ pOut->u.nZero = u.aq.nZero;
pOut->flags |= MEM_Zero;
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever converted to text */
@@ -66090,18 +66764,18 @@ case OP_MakeRecord: {
*/
#ifndef SQLITE_OMIT_BTREECOUNT
case OP_Count: { /* out2-prerelease */
-#if 0 /* local variables moved into u.aq */
+#if 0 /* local variables moved into u.ar */
i64 nEntry;
BtCursor *pCrsr;
-#endif /* local variables moved into u.aq */
+#endif /* local variables moved into u.ar */
- u.aq.pCrsr = p->apCsr[pOp->p1]->pCursor;
- if( ALWAYS(u.aq.pCrsr) ){
- rc = sqlite3BtreeCount(u.aq.pCrsr, &u.aq.nEntry);
+ u.ar.pCrsr = p->apCsr[pOp->p1]->pCursor;
+ if( ALWAYS(u.ar.pCrsr) ){
+ rc = sqlite3BtreeCount(u.ar.pCrsr, &u.ar.nEntry);
}else{
- u.aq.nEntry = 0;
+ u.ar.nEntry = 0;
}
- pOut->u.i = u.aq.nEntry;
+ pOut->u.i = u.ar.nEntry;
break;
}
#endif
@@ -66113,7 +66787,7 @@ case OP_Count: { /* out2-prerelease */
** existing savepoint, P1==1, or to rollback an existing savepoint P1==2.
*/
case OP_Savepoint: {
-#if 0 /* local variables moved into u.ar */
+#if 0 /* local variables moved into u.as */
int p1; /* Value of P1 operand */
char *zName; /* Name of savepoint */
int nName;
@@ -66122,20 +66796,20 @@ case OP_Savepoint: {
Savepoint *pTmp;
int iSavepoint;
int ii;
-#endif /* local variables moved into u.ar */
+#endif /* local variables moved into u.as */
- u.ar.p1 = pOp->p1;
- u.ar.zName = pOp->p4.z;
+ u.as.p1 = pOp->p1;
+ u.as.zName = pOp->p4.z;
- /* Assert that the u.ar.p1 parameter is valid. Also that if there is no open
+ /* Assert that the u.as.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.ar.p1==SAVEPOINT_BEGIN||u.ar.p1==SAVEPOINT_RELEASE||u.ar.p1==SAVEPOINT_ROLLBACK );
+ assert( u.as.p1==SAVEPOINT_BEGIN||u.as.p1==SAVEPOINT_RELEASE||u.as.p1==SAVEPOINT_ROLLBACK );
assert( db->pSavepoint || db->isTransactionSavepoint==0 );
assert( checkSavepointCount(db) );
- if( u.ar.p1==SAVEPOINT_BEGIN ){
+ if( u.as.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).
@@ -66144,7 +66818,7 @@ case OP_Savepoint: {
"SQL statements in progress");
rc = SQLITE_BUSY;
}else{
- u.ar.nName = sqlite3Strlen30(u.ar.zName);
+ u.as.nName = sqlite3Strlen30(u.as.zName);
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* This call is Ok even if this savepoint is actually a transaction
@@ -66158,10 +66832,10 @@ case OP_Savepoint: {
#endif
/* Create a new savepoint structure. */
- 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);
+ 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);
/* If there is no open transaction, then mark this as a special
** "transaction savepoint". */
@@ -66173,27 +66847,27 @@ case OP_Savepoint: {
}
/* Link the new savepoint into the database handle's list. */
- u.ar.pNew->pNext = db->pSavepoint;
- db->pSavepoint = u.ar.pNew;
- u.ar.pNew->nDeferredCons = db->nDeferredCons;
+ u.as.pNew->pNext = db->pSavepoint;
+ db->pSavepoint = u.as.pNew;
+ u.as.pNew->nDeferredCons = db->nDeferredCons;
}
}
}else{
- u.ar.iSavepoint = 0;
+ u.as.iSavepoint = 0;
/* Find the named savepoint. If there is no such savepoint, then an
** an error is returned to the user. */
for(
- u.ar.pSavepoint = db->pSavepoint;
- u.ar.pSavepoint && sqlite3StrICmp(u.ar.pSavepoint->zName, u.ar.zName);
- u.ar.pSavepoint = u.ar.pSavepoint->pNext
+ u.as.pSavepoint = db->pSavepoint;
+ u.as.pSavepoint && sqlite3StrICmp(u.as.pSavepoint->zName, u.as.zName);
+ u.as.pSavepoint = u.as.pSavepoint->pNext
){
- u.ar.iSavepoint++;
+ u.as.iSavepoint++;
}
- if( !u.ar.pSavepoint ){
- sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName);
+ if( !u.as.pSavepoint ){
+ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zName);
rc = SQLITE_ERROR;
- }else if( db->writeVdbeCnt>0 && u.ar.p1==SAVEPOINT_RELEASE ){
+ }else if( db->writeVdbeCnt>0 && u.as.p1==SAVEPOINT_RELEASE ){
/* It is not possible to release (commit) a savepoint if there are
** active write statements.
*/
@@ -66207,8 +66881,8 @@ case OP_Savepoint: {
** and this is a RELEASE command, then the current transaction
** is committed.
*/
- int isTransaction = u.ar.pSavepoint->pNext==0 && db->isTransactionSavepoint;
- if( isTransaction && u.ar.p1==SAVEPOINT_RELEASE ){
+ int isTransaction = u.as.pSavepoint->pNext==0 && db->isTransactionSavepoint;
+ if( isTransaction && u.as.p1==SAVEPOINT_RELEASE ){
if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
goto vdbe_return;
}
@@ -66222,19 +66896,19 @@ case OP_Savepoint: {
db->isTransactionSavepoint = 0;
rc = p->rc;
}else{
- u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1;
- if( u.ar.p1==SAVEPOINT_ROLLBACK ){
- for(u.ar.ii=0; u.ar.iinDb; u.ar.ii++){
- sqlite3BtreeTripAllCursors(db->aDb[u.ar.ii].pBt, SQLITE_ABORT);
+ u.as.iSavepoint = db->nSavepoint - u.as.iSavepoint - 1;
+ if( u.as.p1==SAVEPOINT_ROLLBACK ){
+ for(u.as.ii=0; u.as.iinDb; u.as.ii++){
+ sqlite3BtreeTripAllCursors(db->aDb[u.as.ii].pBt, SQLITE_ABORT);
}
}
- for(u.ar.ii=0; u.ar.iinDb; u.ar.ii++){
- rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint);
+ for(u.as.ii=0; u.as.iinDb; u.as.ii++){
+ rc = sqlite3BtreeSavepoint(db->aDb[u.as.ii].pBt, u.as.p1, u.as.iSavepoint);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
}
- if( u.ar.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
+ if( u.as.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
db->flags = (db->flags | SQLITE_InternChanges);
@@ -66243,10 +66917,10 @@ case OP_Savepoint: {
/* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
** savepoints nested inside of the savepoint being operated on. */
- while( db->pSavepoint!=u.ar.pSavepoint ){
- u.ar.pTmp = db->pSavepoint;
- db->pSavepoint = u.ar.pTmp->pNext;
- sqlite3DbFree(db, u.ar.pTmp);
+ while( db->pSavepoint!=u.as.pSavepoint ){
+ u.as.pTmp = db->pSavepoint;
+ db->pSavepoint = u.as.pTmp->pNext;
+ sqlite3DbFree(db, u.as.pTmp);
db->nSavepoint--;
}
@@ -66254,19 +66928,19 @@ case OP_Savepoint: {
** too. If it is a ROLLBACK TO, then set the number of deferred
** constraint violations present in the database to the value stored
** when the savepoint was created. */
- if( u.ar.p1==SAVEPOINT_RELEASE ){
- assert( u.ar.pSavepoint==db->pSavepoint );
- db->pSavepoint = u.ar.pSavepoint->pNext;
- sqlite3DbFree(db, u.ar.pSavepoint);
+ if( u.as.p1==SAVEPOINT_RELEASE ){
+ assert( u.as.pSavepoint==db->pSavepoint );
+ db->pSavepoint = u.as.pSavepoint->pNext;
+ sqlite3DbFree(db, u.as.pSavepoint);
if( !isTransaction ){
db->nSavepoint--;
}
}else{
- db->nDeferredCons = u.ar.pSavepoint->nDeferredCons;
+ db->nDeferredCons = u.as.pSavepoint->nDeferredCons;
}
if( !isTransaction ){
- rc = sqlite3VtabSavepoint(db, u.ar.p1, u.ar.iSavepoint);
+ rc = sqlite3VtabSavepoint(db, u.as.p1, u.as.iSavepoint);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
@@ -66285,21 +66959,21 @@ case OP_Savepoint: {
** This instruction causes the VM to halt.
*/
case OP_AutoCommit: {
-#if 0 /* local variables moved into u.as */
+#if 0 /* local variables moved into u.at */
int desiredAutoCommit;
int iRollback;
int turnOnAC;
-#endif /* local variables moved into u.as */
+#endif /* local variables moved into u.at */
- 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 );
+ u.at.desiredAutoCommit = pOp->p1;
+ u.at.iRollback = 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.iRollback==0 );
assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
#if 0
- if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){
+ if( u.at.turnOnAC && u.at.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.
@@ -66309,25 +66983,25 @@ case OP_AutoCommit: {
rc = SQLITE_BUSY;
}else
#endif
- if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){
+ if( u.at.turnOnAC && !u.at.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.as.desiredAutoCommit!=db->autoCommit ){
- if( u.as.iRollback ){
- assert( u.as.desiredAutoCommit==1 );
+ }else if( u.at.desiredAutoCommit!=db->autoCommit ){
+ if( u.at.iRollback ){
+ assert( u.at.desiredAutoCommit==1 );
sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK);
db->autoCommit = 1;
}else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
goto vdbe_return;
}else{
- db->autoCommit = (u8)u.as.desiredAutoCommit;
+ db->autoCommit = (u8)u.at.desiredAutoCommit;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
p->pc = pc;
- db->autoCommit = (u8)(1-u.as.desiredAutoCommit);
+ db->autoCommit = (u8)(1-u.at.desiredAutoCommit);
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
@@ -66342,8 +67016,8 @@ case OP_AutoCommit: {
goto vdbe_return;
}else{
sqlite3SetString(&p->zErrMsg, db,
- (!u.as.desiredAutoCommit)?"cannot start a transaction within a transaction":(
- (u.as.iRollback)?"cannot rollback - no transaction is active":
+ (!u.at.desiredAutoCommit)?"cannot start a transaction within a transaction":(
+ (u.at.iRollback)?"cannot rollback - no transaction is active":
"cannot commit - no transaction is active"));
rc = SQLITE_ERROR;
@@ -66383,16 +67057,16 @@ case OP_AutoCommit: {
** If P2 is zero, then a read-lock is obtained on the database file.
*/
case OP_Transaction: {
-#if 0 /* local variables moved into u.at */
+#if 0 /* local variables moved into u.au */
Btree *pBt;
-#endif /* local variables moved into u.at */
+#endif /* local variables moved into u.au */
assert( pOp->p1>=0 && pOp->p1nDb );
assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 );
- u.at.pBt = db->aDb[pOp->p1].pBt;
+ u.au.pBt = db->aDb[pOp->p1].pBt;
- if( u.at.pBt ){
- rc = sqlite3BtreeBeginTrans(u.at.pBt, pOp->p2);
+ if( u.au.pBt ){
+ rc = sqlite3BtreeBeginTrans(u.au.pBt, pOp->p2);
if( rc==SQLITE_BUSY ){
p->pc = pc;
p->rc = rc = SQLITE_BUSY;
@@ -66405,7 +67079,7 @@ case OP_Transaction: {
if( pOp->p2 && p->usesStmtJournal
&& (db->autoCommit==0 || db->activeVdbeCnt>1)
){
- assert( sqlite3BtreeIsInTrans(u.at.pBt) );
+ assert( sqlite3BtreeIsInTrans(u.au.pBt) );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
db->nStatement++;
@@ -66414,7 +67088,7 @@ case OP_Transaction: {
rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, p->iStatement-1);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginStmt(u.at.pBt, p->iStatement);
+ rc = sqlite3BtreeBeginStmt(u.au.pBt, p->iStatement);
}
/* Store the current value of the database handles deferred constraint
@@ -66439,21 +67113,21 @@ case OP_Transaction: {
** executing this instruction.
*/
case OP_ReadCookie: { /* out2-prerelease */
-#if 0 /* local variables moved into u.au */
+#if 0 /* local variables moved into u.av */
int iMeta;
int iDb;
int iCookie;
-#endif /* local variables moved into u.au */
+#endif /* local variables moved into u.av */
- u.au.iDb = pOp->p1;
- u.au.iCookie = pOp->p3;
+ u.av.iDb = pOp->p1;
+ u.av.iCookie = pOp->p3;
assert( pOp->p3=0 && u.au.iDbnDb );
- assert( db->aDb[u.au.iDb].pBt!=0 );
- assert( (p->btreeMask & (((yDbMask)1)<=0 && u.av.iDbnDb );
+ assert( db->aDb[u.av.iDb].pBt!=0 );
+ assert( (p->btreeMask & (((yDbMask)1)<aDb[u.au.iDb].pBt, u.au.iCookie, (u32 *)&u.au.iMeta);
- pOut->u.i = u.au.iMeta;
+ sqlite3BtreeGetMeta(db->aDb[u.av.iDb].pBt, u.av.iCookie, (u32 *)&u.av.iMeta);
+ pOut->u.i = u.av.iMeta;
break;
}
@@ -66468,26 +67142,26 @@ case OP_ReadCookie: { /* out2-prerelease */
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: { /* in3 */
-#if 0 /* local variables moved into u.av */
+#if 0 /* local variables moved into u.aw */
Db *pDb;
-#endif /* local variables moved into u.av */
+#endif /* local variables moved into u.aw */
assert( pOp->p2p1>=0 && pOp->p1nDb );
assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 );
- u.av.pDb = &db->aDb[pOp->p1];
- assert( u.av.pDb->pBt!=0 );
+ u.aw.pDb = &db->aDb[pOp->p1];
+ assert( u.aw.pDb->pBt!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
pIn3 = &aMem[pOp->p3];
sqlite3VdbeMemIntegerify(pIn3);
/* See note about index shifting on OP_ReadCookie */
- rc = sqlite3BtreeUpdateMeta(u.av.pDb->pBt, pOp->p2, (int)pIn3->u.i);
+ rc = sqlite3BtreeUpdateMeta(u.aw.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.av.pDb->pSchema->schema_cookie = (int)pIn3->u.i;
+ u.aw.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.av.pDb->pSchema->file_format = (u8)pIn3->u.i;
+ u.aw.pDb->pSchema->file_format = (u8)pIn3->u.i;
}
if( pOp->p1==1 ){
/* Invalidate all prepared statements whenever the TEMP database
@@ -66517,23 +67191,23 @@ case OP_SetCookie: { /* in3 */
** invoked.
*/
case OP_VerifyCookie: {
-#if 0 /* local variables moved into u.aw */
+#if 0 /* local variables moved into u.ax */
int iMeta;
int iGen;
Btree *pBt;
-#endif /* local variables moved into u.aw */
+#endif /* local variables moved into u.ax */
assert( pOp->p1>=0 && pOp->p1nDb );
assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
- u.aw.pBt = db->aDb[pOp->p1].pBt;
- if( u.aw.pBt ){
- sqlite3BtreeGetMeta(u.aw.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.aw.iMeta);
- u.aw.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
+ u.ax.pBt = db->aDb[pOp->p1].pBt;
+ if( u.ax.pBt ){
+ sqlite3BtreeGetMeta(u.ax.pBt, BTREE_SCHEMA_VERSION, (u32 *)&u.ax.iMeta);
+ u.ax.iGen = db->aDb[pOp->p1].pSchema->iGeneration;
}else{
- u.aw.iGen = u.aw.iMeta = 0;
+ u.ax.iGen = u.ax.iMeta = 0;
}
- if( u.aw.iMeta!=pOp->p2 || u.aw.iGen!=pOp->p3 ){
+ if( u.ax.iMeta!=pOp->p2 || u.ax.iGen!=pOp->p3 ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
@@ -66549,7 +67223,7 @@ case OP_VerifyCookie: {
** to be invalidated whenever sqlite3_step() is called from within
** a v-table method.
*/
- if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.aw.iMeta ){
+ if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.ax.iMeta ){
sqlite3ResetOneSchema(db, pOp->p1);
}
@@ -66610,7 +67284,7 @@ case OP_VerifyCookie: {
*/
case OP_OpenRead:
case OP_OpenWrite: {
-#if 0 /* local variables moved into u.ax */
+#if 0 /* local variables moved into u.ay */
int nField;
KeyInfo *pKeyInfo;
int p2;
@@ -66619,7 +67293,7 @@ case OP_OpenWrite: {
Btree *pX;
VdbeCursor *pCur;
Db *pDb;
-#endif /* local variables moved into u.ax */
+#endif /* local variables moved into u.ay */
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
@@ -66629,57 +67303,57 @@ case OP_OpenWrite: {
break;
}
- 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.iDbnDb );
- assert( (p->btreeMask & (((yDbMask)1)<aDb[u.ax.iDb];
- u.ax.pX = u.ax.pDb->pBt;
- assert( u.ax.pX!=0 );
+ u.ay.nField = 0;
+ u.ay.pKeyInfo = 0;
+ u.ay.p2 = pOp->p2;
+ u.ay.iDb = pOp->p3;
+ assert( u.ay.iDb>=0 && u.ay.iDbnDb );
+ assert( (p->btreeMask & (((yDbMask)1)<aDb[u.ay.iDb];
+ u.ay.pX = u.ay.pDb->pBt;
+ assert( u.ay.pX!=0 );
if( pOp->opcode==OP_OpenWrite ){
- u.ax.wrFlag = 1;
- assert( sqlite3SchemaMutexHeld(db, u.ax.iDb, 0) );
- if( u.ax.pDb->pSchema->file_format < p->minWriteFileFormat ){
- p->minWriteFileFormat = u.ax.pDb->pSchema->file_format;
+ u.ay.wrFlag = 1;
+ assert( sqlite3SchemaMutexHeld(db, u.ay.iDb, 0) );
+ if( u.ay.pDb->pSchema->file_format < p->minWriteFileFormat ){
+ p->minWriteFileFormat = u.ay.pDb->pSchema->file_format;
}
}else{
- u.ax.wrFlag = 0;
+ u.ay.wrFlag = 0;
}
if( pOp->p5 & OPFLAG_P2ISREG ){
- assert( u.ax.p2>0 );
- assert( u.ax.p2<=p->nMem );
- pIn2 = &aMem[u.ax.p2];
+ assert( u.ay.p2>0 );
+ assert( u.ay.p2<=p->nMem );
+ pIn2 = &aMem[u.ay.p2];
assert( memIsValid(pIn2) );
assert( (pIn2->flags & MEM_Int)!=0 );
sqlite3VdbeMemIntegerify(pIn2);
- 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.
+ u.ay.p2 = (int)pIn2->u.i;
+ /* The u.ay.p2 value always comes from a prior OP_CreateTable opcode and
+ ** that opcode will always set the u.ay.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) ) {
+ if( NEVER(u.ay.p2<2) ) {
rc = SQLITE_CORRUPT_BKPT;
goto abort_due_to_error;
}
}
if( pOp->p4type==P4_KEYINFO ){
- u.ax.pKeyInfo = pOp->p4.pKeyInfo;
- u.ax.pKeyInfo->enc = ENC(p->db);
- u.ax.nField = u.ax.pKeyInfo->nField+1;
+ u.ay.pKeyInfo = pOp->p4.pKeyInfo;
+ u.ay.pKeyInfo->enc = ENC(p->db);
+ u.ay.nField = u.ay.pKeyInfo->nField+1;
}else if( pOp->p4type==P4_INT32 ){
- u.ax.nField = pOp->p4.i;
+ u.ay.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;
- u.ax.pCur->isOrdered = 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;
+ u.ay.pCur = allocateCursor(p, pOp->p1, u.ay.nField, u.ay.iDb, 1);
+ if( u.ay.pCur==0 ) goto no_mem;
+ u.ay.pCur->nullRow = 1;
+ u.ay.pCur->isOrdered = 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;
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
- sqlite3BtreeCursorHints(u.ax.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
+ sqlite3BtreeCursorHints(u.ay.pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
/* Since it performs no memory allocation or IO, the only value that
** sqlite3BtreeCursor() may return is SQLITE_OK. */
@@ -66689,8 +67363,8 @@ case OP_OpenWrite: {
** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has
** since moved into the btree layer. */
- u.ax.pCur->isTable = pOp->p4type!=P4_KEYINFO;
- u.ax.pCur->isIndex = !u.ax.pCur->isTable;
+ u.ay.pCur->isTable = pOp->p4type!=P4_KEYINFO;
+ u.ay.pCur->isIndex = !u.ay.pCur->isTable;
break;
}
@@ -66726,9 +67400,9 @@ case OP_OpenWrite: {
*/
case OP_OpenAutoindex:
case OP_OpenEphemeral: {
-#if 0 /* local variables moved into u.ay */
+#if 0 /* local variables moved into u.az */
VdbeCursor *pCx;
-#endif /* local variables moved into u.ay */
+#endif /* local variables moved into u.az */
static const int vfsFlags =
SQLITE_OPEN_READWRITE |
SQLITE_OPEN_CREATE |
@@ -66737,13 +67411,13 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_TRANSIENT_DB;
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 = sqlite3BtreeOpen(db->pVfs, 0, db, &u.ay.pCx->pBt,
+ u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( u.az.pCx==0 ) goto no_mem;
+ u.az.pCx->nullRow = 1;
+ rc = sqlite3BtreeOpen(db->pVfs, 0, db, &u.az.pCx->pBt,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeBeginTrans(u.ay.pCx->pBt, 1);
+ rc = sqlite3BtreeBeginTrans(u.az.pCx->pBt, 1);
}
if( rc==SQLITE_OK ){
/* If a transient index is required, create it by calling
@@ -66754,55 +67428,52 @@ case OP_OpenEphemeral: {
if( pOp->p4.pKeyInfo ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
- rc = sqlite3BtreeCreateTable(u.ay.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
+ rc = sqlite3BtreeCreateTable(u.az.pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
- 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);
+ 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.ay.pCx->isTable = 0;
+ u.az.pCx->isTable = 0;
}else{
- rc = sqlite3BtreeCursor(u.ay.pCx->pBt, MASTER_ROOT, 1, 0, u.ay.pCx->pCursor);
- u.ay.pCx->isTable = 1;
+ rc = sqlite3BtreeCursor(u.az.pCx->pBt, MASTER_ROOT, 1, 0, u.az.pCx->pCursor);
+ u.az.pCx->isTable = 1;
}
}
- u.ay.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
- u.ay.pCx->isIndex = !u.ay.pCx->isTable;
+ u.az.pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ u.az.pCx->isIndex = !u.az.pCx->isTable;
break;
}
-/* Opcode: OpenSorter P1 P2 * P4 *
+/* Opcode: SorterOpen P1 P2 * P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
** tables using an external merge-sort algorithm.
*/
case OP_SorterOpen: {
-#if 0 /* local variables moved into u.az */
+#if 0 /* local variables moved into u.ba */
VdbeCursor *pCx;
-#endif /* local variables moved into u.az */
-#ifndef SQLITE_OMIT_MERGE_SORT
- u.az.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
- if( u.az.pCx==0 ) goto no_mem;
- u.az.pCx->pKeyInfo = pOp->p4.pKeyInfo;
- u.az.pCx->pKeyInfo->enc = ENC(p->db);
- u.az.pCx->isSorter = 1;
- rc = sqlite3VdbeSorterInit(db, u.az.pCx);
-#else
- pOp->opcode = OP_OpenEphemeral;
- pc--;
-#endif
+#endif /* local variables moved into u.ba */
+
+ u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
+ if( u.ba.pCx==0 ) goto no_mem;
+ u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
+ u.ba.pCx->pKeyInfo->enc = ENC(p->db);
+ u.ba.pCx->isSorter = 1;
+ rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
break;
}
-/* Opcode: OpenPseudo P1 P2 P3 * *
+/* Opcode: OpenPseudo P1 P2 P3 * P5
**
** Open a new cursor that points to a fake table that contains a single
** row of data. The content of that one row in the content of memory
-** register P2. In other words, cursor P1 becomes an alias for the
-** MEM_Blob content contained in register P2.
+** register P2 when P5==0. In other words, cursor P1 becomes an alias for the
+** MEM_Blob content contained in register P2. When P5==1, then the
+** row is represented by P3 consecutive registers beginning with P2.
**
** A pseudo-table created by this opcode is used to hold a single
** row output from the sorter so that the row can be decomposed into
@@ -66813,17 +67484,18 @@ case OP_SorterOpen: {
** the pseudo-table.
*/
case OP_OpenPseudo: {
-#if 0 /* local variables moved into u.ba */
+#if 0 /* local variables moved into u.bb */
VdbeCursor *pCx;
-#endif /* local variables moved into u.ba */
+#endif /* local variables moved into u.bb */
assert( pOp->p1>=0 );
- u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
- if( u.ba.pCx==0 ) goto no_mem;
- u.ba.pCx->nullRow = 1;
- u.ba.pCx->pseudoTableReg = pOp->p2;
- u.ba.pCx->isTable = 1;
- u.ba.pCx->isIndex = 0;
+ u.bb.pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0);
+ if( u.bb.pCx==0 ) goto no_mem;
+ u.bb.pCx->nullRow = 1;
+ u.bb.pCx->pseudoTableReg = pOp->p2;
+ u.bb.pCx->isTable = 1;
+ u.bb.pCx->isIndex = 0;
+ u.bb.pCx->multiPseudo = pOp->p5;
break;
}
@@ -66895,35 +67567,35 @@ 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.bb */
+#if 0 /* local variables moved into u.bc */
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.bb */
+#endif /* local variables moved into u.bc */
assert( pOp->p1>=0 && pOp->p1nCursor );
assert( pOp->p2!=0 );
- u.bb.pC = p->apCsr[pOp->p1];
- assert( u.bb.pC!=0 );
- assert( u.bb.pC->pseudoTableReg==0 );
+ u.bc.pC = p->apCsr[pOp->p1];
+ assert( u.bc.pC!=0 );
+ assert( u.bc.pC->pseudoTableReg==0 );
assert( OP_SeekLe == OP_SeekLt+1 );
assert( OP_SeekGe == OP_SeekLt+2 );
assert( OP_SeekGt == OP_SeekLt+3 );
- assert( u.bb.pC->isOrdered );
- if( ALWAYS(u.bb.pC->pCursor!=0) ){
- u.bb.oc = pOp->opcode;
- u.bb.pC->nullRow = 0;
- if( u.bb.pC->isTable ){
+ assert( u.bc.pC->isOrdered );
+ if( ALWAYS(u.bc.pC->pCursor!=0) ){
+ u.bc.oc = pOp->opcode;
+ u.bc.pC->nullRow = 0;
+ if( u.bc.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. */
pIn3 = &aMem[pOp->p3];
applyNumericAffinity(pIn3);
- u.bb.iKey = sqlite3VdbeIntValue(pIn3);
- u.bb.pC->rowidIsValid = 0;
+ u.bc.iKey = sqlite3VdbeIntValue(pIn3);
+ u.bc.pC->rowidIsValid = 0;
/* If the P3 value could not be converted into an integer without
** loss of information, then special processing is required... */
@@ -66938,101 +67610,101 @@ case OP_SeekGt: { /* jump, in3 */
** point number. */
assert( (pIn3->flags & MEM_Real)!=0 );
- if( u.bb.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bb.iKey || pIn3->r>0) ){
+ if( u.bc.iKey==SMALLEST_INT64 && (pIn3->r<(double)u.bc.iKey || pIn3->r>0) ){
/* The P3 value is too large in magnitude to be expressed as an
** integer. */
- u.bb.res = 1;
+ u.bc.res = 1;
if( pIn3->r<0 ){
- if( u.bb.oc>=OP_SeekGe ){ assert( u.bb.oc==OP_SeekGe || u.bb.oc==OP_SeekGt );
- rc = sqlite3BtreeFirst(u.bb.pC->pCursor, &u.bb.res);
+ if( u.bc.oc>=OP_SeekGe ){ assert( u.bc.oc==OP_SeekGe || u.bc.oc==OP_SeekGt );
+ rc = sqlite3BtreeFirst(u.bc.pC->pCursor, &u.bc.res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}else{
- if( u.bb.oc<=OP_SeekLe ){ assert( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekLe );
- rc = sqlite3BtreeLast(u.bb.pC->pCursor, &u.bb.res);
+ if( u.bc.oc<=OP_SeekLe ){ assert( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekLe );
+ rc = sqlite3BtreeLast(u.bc.pC->pCursor, &u.bc.res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
}
- if( u.bb.res ){
+ if( u.bc.res ){
pc = pOp->p2 - 1;
}
break;
- }else if( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekGe ){
+ }else if( u.bc.oc==OP_SeekLt || u.bc.oc==OP_SeekGe ){
/* Use the ceiling() function to convert real->int */
- if( pIn3->r > (double)u.bb.iKey ) u.bb.iKey++;
+ if( pIn3->r > (double)u.bc.iKey ) u.bc.iKey++;
}else{
/* Use the floor() function to convert real->int */
- assert( u.bb.oc==OP_SeekLe || u.bb.oc==OP_SeekGt );
- if( pIn3->r < (double)u.bb.iKey ) u.bb.iKey--;
+ assert( u.bc.oc==OP_SeekLe || u.bc.oc==OP_SeekGt );
+ if( pIn3->r < (double)u.bc.iKey ) u.bc.iKey--;
}
}
- rc = sqlite3BtreeMovetoUnpacked(u.bb.pC->pCursor, 0, (u64)u.bb.iKey, 0, &u.bb.res);
+ rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, 0, (u64)u.bc.iKey, 0, &u.bc.res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- if( u.bb.res==0 ){
- u.bb.pC->rowidIsValid = 1;
- u.bb.pC->lastRowid = u.bb.iKey;
+ if( u.bc.res==0 ){
+ u.bc.pC->rowidIsValid = 1;
+ u.bc.pC->lastRowid = u.bc.iKey;
}
}else{
- u.bb.nField = pOp->p4.i;
+ u.bc.nField = pOp->p4.i;
assert( pOp->p4type==P4_INT32 );
- assert( u.bb.nField>0 );
- u.bb.r.pKeyInfo = u.bb.pC->pKeyInfo;
- u.bb.r.nField = (u16)u.bb.nField;
+ assert( u.bc.nField>0 );
+ u.bc.r.pKeyInfo = u.bc.pC->pKeyInfo;
+ u.bc.r.nField = (u16)u.bc.nField;
/* The next line of code computes as follows, only faster:
- ** if( u.bb.oc==OP_SeekGt || u.bb.oc==OP_SeekLe ){
- ** u.bb.r.flags = UNPACKED_INCRKEY;
+ ** if( u.bc.oc==OP_SeekGt || u.bc.oc==OP_SeekLe ){
+ ** u.bc.r.flags = UNPACKED_INCRKEY;
** }else{
- ** u.bb.r.flags = 0;
+ ** u.bc.r.flags = 0;
** }
*/
- u.bb.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.bb.oc - OP_SeekLt)));
- assert( u.bb.oc!=OP_SeekGt || u.bb.r.flags==UNPACKED_INCRKEY );
- assert( u.bb.oc!=OP_SeekLe || u.bb.r.flags==UNPACKED_INCRKEY );
- assert( u.bb.oc!=OP_SeekGe || u.bb.r.flags==0 );
- assert( u.bb.oc!=OP_SeekLt || u.bb.r.flags==0 );
+ u.bc.r.flags = (u16)(UNPACKED_INCRKEY * (1 & (u.bc.oc - OP_SeekLt)));
+ assert( u.bc.oc!=OP_SeekGt || u.bc.r.flags==UNPACKED_INCRKEY );
+ assert( u.bc.oc!=OP_SeekLe || u.bc.r.flags==UNPACKED_INCRKEY );
+ assert( u.bc.oc!=OP_SeekGe || u.bc.r.flags==0 );
+ assert( u.bc.oc!=OP_SeekLt || u.bc.r.flags==0 );
- u.bb.r.aMem = &aMem[pOp->p3];
+ u.bc.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; ipCursor, &u.bb.r, 0, 0, &u.bb.res);
+ ExpandBlob(u.bc.r.aMem);
+ rc = sqlite3BtreeMovetoUnpacked(u.bc.pC->pCursor, &u.bc.r, 0, 0, &u.bc.res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- u.bb.pC->rowidIsValid = 0;
+ u.bc.pC->rowidIsValid = 0;
}
- u.bb.pC->deferredMoveto = 0;
- u.bb.pC->cacheStatus = CACHE_STALE;
+ u.bc.pC->deferredMoveto = 0;
+ u.bc.pC->cacheStatus = CACHE_STALE;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
- if( u.bb.oc>=OP_SeekGe ){ assert( u.bb.oc==OP_SeekGe || u.bb.oc==OP_SeekGt );
- if( u.bb.res<0 || (u.bb.res==0 && u.bb.oc==OP_SeekGt) ){
- rc = sqlite3BtreeNext(u.bb.pC->pCursor, &u.bb.res);
+ if( u.bc.oc>=OP_SeekGe ){ assert( 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( rc!=SQLITE_OK ) goto abort_due_to_error;
- u.bb.pC->rowidIsValid = 0;
+ u.bc.pC->rowidIsValid = 0;
}else{
- u.bb.res = 0;
+ u.bc.res = 0;
}
}else{
- assert( u.bb.oc==OP_SeekLt || u.bb.oc==OP_SeekLe );
- if( u.bb.res>0 || (u.bb.res==0 && u.bb.oc==OP_SeekLt) ){
- rc = sqlite3BtreePrevious(u.bb.pC->pCursor, &u.bb.res);
+ 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);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
- u.bb.pC->rowidIsValid = 0;
+ u.bc.pC->rowidIsValid = 0;
}else{
- /* u.bb.res might be negative because the table is empty. Check to
+ /* u.bc.res might be negative because the table is empty. Check to
** see if this is the case.
*/
- u.bb.res = sqlite3BtreeEof(u.bb.pC->pCursor);
+ u.bc.res = sqlite3BtreeEof(u.bc.pC->pCursor);
}
}
assert( pOp->p2>0 );
- if( u.bb.res ){
+ if( u.bc.res ){
pc = pOp->p2 - 1;
}
}else{
@@ -67055,20 +67727,20 @@ case OP_SeekGt: { /* jump, in3 */
** occur, no unnecessary I/O happens.
*/
case OP_Seek: { /* in2 */
-#if 0 /* local variables moved into u.bc */
+#if 0 /* local variables moved into u.bd */
VdbeCursor *pC;
-#endif /* local variables moved into u.bc */
+#endif /* local variables moved into u.bd */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bc.pC = p->apCsr[pOp->p1];
- assert( u.bc.pC!=0 );
- if( ALWAYS(u.bc.pC->pCursor!=0) ){
- assert( u.bc.pC->isTable );
- u.bc.pC->nullRow = 0;
+ u.bd.pC = p->apCsr[pOp->p1];
+ assert( u.bd.pC!=0 );
+ if( ALWAYS(u.bd.pC->pCursor!=0) ){
+ assert( u.bd.pC->isTable );
+ u.bd.pC->nullRow = 0;
pIn2 = &aMem[pOp->p2];
- u.bc.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
- u.bc.pC->rowidIsValid = 0;
- u.bc.pC->deferredMoveto = 1;
+ u.bd.pC->movetoTarget = sqlite3VdbeIntValue(pIn2);
+ u.bd.pC->rowidIsValid = 0;
+ u.bd.pC->deferredMoveto = 1;
}
break;
}
@@ -67100,7 +67772,7 @@ case OP_Seek: { /* in2 */
*/
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
-#if 0 /* local variables moved into u.bd */
+#if 0 /* local variables moved into u.be */
int alreadyExists;
VdbeCursor *pC;
int res;
@@ -67108,55 +67780,55 @@ case OP_Found: { /* jump, in3 */
UnpackedRecord *pIdxKey;
UnpackedRecord r;
char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7];
-#endif /* local variables moved into u.bd */
+#endif /* local variables moved into u.be */
#ifdef SQLITE_TEST
sqlite3_found_count++;
#endif
- u.bd.alreadyExists = 0;
+ u.be.alreadyExists = 0;
assert( pOp->p1>=0 && pOp->p1nCursor );
assert( pOp->p4type==P4_INT32 );
- u.bd.pC = p->apCsr[pOp->p1];
- assert( u.bd.pC!=0 );
+ u.be.pC = p->apCsr[pOp->p1];
+ assert( u.be.pC!=0 );
pIn3 = &aMem[pOp->p3];
- if( ALWAYS(u.bd.pC->pCursor!=0) ){
+ if( ALWAYS(u.be.pC->pCursor!=0) ){
- assert( u.bd.pC->isTable==0 );
+ assert( u.be.pC->isTable==0 );
if( pOp->p4.i>0 ){
- u.bd.r.pKeyInfo = u.bd.pC->pKeyInfo;
- u.bd.r.nField = (u16)pOp->p4.i;
- u.bd.r.aMem = pIn3;
+ u.be.r.pKeyInfo = u.be.pC->pKeyInfo;
+ u.be.r.nField = (u16)pOp->p4.i;
+ u.be.r.aMem = pIn3;
#ifdef SQLITE_DEBUG
- { int i; for(i=0; ipKeyInfo, u.bd.aTempRec, sizeof(u.bd.aTempRec), &u.bd.pFree
+ u.be.pIdxKey = sqlite3VdbeAllocUnpackedRecord(
+ u.be.pC->pKeyInfo, u.be.aTempRec, sizeof(u.be.aTempRec), &u.be.pFree
);
- if( u.bd.pIdxKey==0 ) goto no_mem;
+ if( u.be.pIdxKey==0 ) goto no_mem;
assert( pIn3->flags & MEM_Blob );
assert( (pIn3->flags & MEM_Zero)==0 ); /* zeroblobs already expanded */
- sqlite3VdbeRecordUnpack(u.bd.pC->pKeyInfo, pIn3->n, pIn3->z, u.bd.pIdxKey);
- u.bd.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
+ sqlite3VdbeRecordUnpack(u.be.pC->pKeyInfo, pIn3->n, pIn3->z, u.be.pIdxKey);
+ u.be.pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
}
- rc = sqlite3BtreeMovetoUnpacked(u.bd.pC->pCursor, u.bd.pIdxKey, 0, 0, &u.bd.res);
+ rc = sqlite3BtreeMovetoUnpacked(u.be.pC->pCursor, u.be.pIdxKey, 0, 0, &u.be.res);
if( pOp->p4.i==0 ){
- sqlite3DbFree(db, u.bd.pFree);
+ sqlite3DbFree(db, u.be.pFree);
}
if( rc!=SQLITE_OK ){
break;
}
- u.bd.alreadyExists = (u.bd.res==0);
- u.bd.pC->deferredMoveto = 0;
- u.bd.pC->cacheStatus = CACHE_STALE;
+ u.be.alreadyExists = (u.be.res==0);
+ u.be.pC->deferredMoveto = 0;
+ u.be.pC->cacheStatus = CACHE_STALE;
}
if( pOp->opcode==OP_Found ){
- if( u.bd.alreadyExists ) pc = pOp->p2 - 1;
+ if( u.be.alreadyExists ) pc = pOp->p2 - 1;
}else{
- if( !u.bd.alreadyExists ) pc = pOp->p2 - 1;
+ if( !u.be.alreadyExists ) pc = pOp->p2 - 1;
}
break;
}
@@ -67188,7 +67860,7 @@ case OP_Found: { /* jump, in3 */
** See also: NotFound, NotExists, Found
*/
case OP_IsUnique: { /* jump, in3 */
-#if 0 /* local variables moved into u.be */
+#if 0 /* local variables moved into u.bf */
u16 ii;
VdbeCursor *pCx;
BtCursor *pCrsr;
@@ -67196,55 +67868,55 @@ case OP_IsUnique: { /* jump, in3 */
Mem *aMx;
UnpackedRecord r; /* B-Tree index search key */
i64 R; /* Rowid stored in register P3 */
-#endif /* local variables moved into u.be */
+#endif /* local variables moved into u.bf */
pIn3 = &aMem[pOp->p3];
- u.be.aMx = &aMem[pOp->p4.i];
+ u.bf.aMx = &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->p1nCursor );
/* Find the index cursor. */
- u.be.pCx = p->apCsr[pOp->p1];
- assert( u.be.pCx->deferredMoveto==0 );
- u.be.pCx->seekResult = 0;
- u.be.pCx->cacheStatus = CACHE_STALE;
- u.be.pCrsr = u.be.pCx->pCursor;
+ 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;
/* If any of the values are NULL, take the jump. */
- u.be.nField = u.be.pCx->pKeyInfo->nField;
- for(u.be.ii=0; u.be.iipKeyInfo->nField;
+ for(u.bf.ii=0; u.bf.iip2 - 1;
- u.be.pCrsr = 0;
+ u.bf.pCrsr = 0;
break;
}
}
- assert( (u.be.aMx[u.be.nField].flags & MEM_Null)==0 );
+ assert( (u.bf.aMx[u.bf.nField].flags & MEM_Null)==0 );
- if( u.be.pCrsr!=0 ){
+ if( u.bf.pCrsr!=0 ){
/* Populate the index search key. */
- u.be.r.pKeyInfo = u.be.pCx->pKeyInfo;
- u.be.r.nField = u.be.nField + 1;
- u.be.r.flags = UNPACKED_PREFIX_SEARCH;
- u.be.r.aMem = u.be.aMx;
+ 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.aMx;
#ifdef SQLITE_DEBUG
- { int i; for(i=0; iu.i;
+ u.bf.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.be.pCrsr, &u.be.r, 0, 0, &u.be.pCx->seekResult);
- if( (u.be.r.flags & UNPACKED_PREFIX_SEARCH) || u.be.r.rowid==u.be.R ){
+ 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 ){
pc = pOp->p2 - 1;
}else{
- pIn3->u.i = u.be.r.rowid;
+ pIn3->u.i = u.bf.r.rowid;
}
}
break;
@@ -67265,42 +67937,42 @@ case OP_IsUnique: { /* jump, in3 */
** See also: Found, NotFound, IsUnique
*/
case OP_NotExists: { /* jump, in3 */
-#if 0 /* local variables moved into u.bf */
+#if 0 /* local variables moved into u.bg */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
u64 iKey;
-#endif /* local variables moved into u.bf */
+#endif /* local variables moved into u.bg */
pIn3 = &aMem[pOp->p3];
assert( pIn3->flags & MEM_Int );
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bf.pC = p->apCsr[pOp->p1];
- assert( u.bf.pC!=0 );
- assert( u.bf.pC->isTable );
- assert( u.bf.pC->pseudoTableReg==0 );
- u.bf.pCrsr = u.bf.pC->pCursor;
- if( ALWAYS(u.bf.pCrsr!=0) ){
- u.bf.res = 0;
- u.bf.iKey = pIn3->u.i;
- rc = sqlite3BtreeMovetoUnpacked(u.bf.pCrsr, 0, u.bf.iKey, 0, &u.bf.res);
- u.bf.pC->lastRowid = pIn3->u.i;
- u.bf.pC->rowidIsValid = u.bf.res==0 ?1:0;
- u.bf.pC->nullRow = 0;
- u.bf.pC->cacheStatus = CACHE_STALE;
- u.bf.pC->deferredMoveto = 0;
- if( u.bf.res!=0 ){
+ u.bg.pC = p->apCsr[pOp->p1];
+ assert( u.bg.pC!=0 );
+ assert( u.bg.pC->isTable );
+ assert( u.bg.pC->pseudoTableReg==0 );
+ u.bg.pCrsr = u.bg.pC->pCursor;
+ if( ALWAYS(u.bg.pCrsr!=0) ){
+ u.bg.res = 0;
+ u.bg.iKey = 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 ){
pc = pOp->p2 - 1;
- assert( u.bf.pC->rowidIsValid==0 );
+ assert( u.bg.pC->rowidIsValid==0 );
}
- u.bf.pC->seekResult = u.bf.res;
+ u.bg.pC->seekResult = u.bg.res;
}else{
/* This happens when an attempt to open a read cursor on the
** sqlite_master table returns SQLITE_EMPTY.
*/
pc = pOp->p2 - 1;
- assert( u.bf.pC->rowidIsValid==0 );
- u.bf.pC->seekResult = 0;
+ assert( u.bg.pC->rowidIsValid==0 );
+ u.bg.pC->seekResult = 0;
}
break;
}
@@ -67335,21 +68007,21 @@ case OP_Sequence: { /* out2-prerelease */
** AUTOINCREMENT feature.
*/
case OP_NewRowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bg */
+#if 0 /* local variables moved into u.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 */
VdbeFrame *pFrame; /* Root frame of VDBE */
-#endif /* local variables moved into u.bg */
+#endif /* local variables moved into u.bh */
- u.bg.v = 0;
- u.bg.res = 0;
+ u.bh.v = 0;
+ u.bh.res = 0;
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bg.pC = p->apCsr[pOp->p1];
- assert( u.bg.pC!=0 );
- if( NEVER(u.bg.pC->pCursor==0) ){
+ u.bh.pC = p->apCsr[pOp->p1];
+ assert( u.bh.pC!=0 );
+ if( NEVER(u.bh.pC->pCursor==0) ){
/* The zero initialization above is all that is needed */
}else{
/* The next rowid or record number (different terms for the same
@@ -67365,7 +68037,7 @@ case OP_NewRowid: { /* out2-prerelease */
** succeeded. If the random rowid does exist, we select a new one
** and try again, up to 100 times.
*/
- assert( u.bg.pC->isTable );
+ assert( u.bh.pC->isTable );
#ifdef SQLITE_32BIT_ROWID
# define MAX_ROWID 0x7fffffff
@@ -67377,23 +68049,23 @@ case OP_NewRowid: { /* out2-prerelease */
# define MAX_ROWID (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )
#endif
- if( !u.bg.pC->useRandomRowid ){
- u.bg.v = sqlite3BtreeGetCachedRowid(u.bg.pC->pCursor);
- if( u.bg.v==0 ){
- rc = sqlite3BtreeLast(u.bg.pC->pCursor, &u.bg.res);
+ 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( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- if( u.bg.res ){
- u.bg.v = 1; /* IMP: R-61914-48074 */
+ if( u.bh.res ){
+ u.bh.v = 1; /* IMP: R-61914-48074 */
}else{
- assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) );
- rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v);
+ assert( sqlite3BtreeCursorIsValid(u.bh.pC->pCursor) );
+ rc = sqlite3BtreeKeySize(u.bh.pC->pCursor, &u.bh.v);
assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */
- if( u.bg.v>=MAX_ROWID ){
- u.bg.pC->useRandomRowid = 1;
+ if( u.bh.v>=MAX_ROWID ){
+ u.bh.pC->useRandomRowid = 1;
}else{
- u.bg.v++; /* IMP: R-29538-34987 */
+ u.bh.v++; /* IMP: R-29538-34987 */
}
}
}
@@ -67403,35 +68075,35 @@ case OP_NewRowid: { /* out2-prerelease */
/* Assert that P3 is a valid memory cell. */
assert( pOp->p3>0 );
if( p->pFrame ){
- for(u.bg.pFrame=p->pFrame; u.bg.pFrame->pParent; u.bg.pFrame=u.bg.pFrame->pParent);
+ for(u.bh.pFrame=p->pFrame; u.bh.pFrame->pParent; u.bh.pFrame=u.bh.pFrame->pParent);
/* Assert that P3 is a valid memory cell. */
- assert( pOp->p3<=u.bg.pFrame->nMem );
- u.bg.pMem = &u.bg.pFrame->aMem[pOp->p3];
+ assert( pOp->p3<=u.bh.pFrame->nMem );
+ u.bh.pMem = &u.bh.pFrame->aMem[pOp->p3];
}else{
/* Assert that P3 is a valid memory cell. */
assert( pOp->p3<=p->nMem );
- u.bg.pMem = &aMem[pOp->p3];
- memAboutToChange(p, u.bg.pMem);
+ u.bh.pMem = &aMem[pOp->p3];
+ memAboutToChange(p, u.bh.pMem);
}
- assert( memIsValid(u.bg.pMem) );
+ assert( memIsValid(u.bh.pMem) );
- REGISTER_TRACE(pOp->p3, u.bg.pMem);
- sqlite3VdbeMemIntegerify(u.bg.pMem);
- assert( (u.bg.pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
- if( u.bg.pMem->u.i==MAX_ROWID || u.bg.pC->useRandomRowid ){
+ 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 ){
rc = SQLITE_FULL; /* IMP: R-12275-61338 */
goto abort_due_to_error;
}
- if( u.bg.vu.i+1 ){
- u.bg.v = u.bg.pMem->u.i + 1;
+ if( u.bh.vu.i+1 ){
+ u.bh.v = u.bh.pMem->u.i + 1;
}
- u.bg.pMem->u.i = u.bg.v;
+ u.bh.pMem->u.i = u.bh.v;
}
#endif
- sqlite3BtreeSetCachedRowid(u.bg.pC->pCursor, u.bg.vpCursor, u.bh.vuseRandomRowid ){
+ if( u.bh.pC->useRandomRowid ){
/* IMPLEMENTATION-OF: R-07677-41881 If the largest ROWID is equal to the
** largest possible integer (9223372036854775807) then the database
** engine starts picking positive candidate ROWIDs at random until
@@ -67439,35 +68111,35 @@ case OP_NewRowid: { /* out2-prerelease */
assert( pOp->p3==0 ); /* We cannot be in random rowid mode if this is
** an AUTOINCREMENT table. */
/* on the first attempt, simply do one more than previous */
- u.bg.v = lastRowid;
- u.bg.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
- u.bg.v++; /* ensure non-zero */
- u.bg.cnt = 0;
- while( ((rc = sqlite3BtreeMovetoUnpacked(u.bg.pC->pCursor, 0, (u64)u.bg.v,
- 0, &u.bg.res))==SQLITE_OK)
- && (u.bg.res==0)
- && (++u.bg.cnt<100)){
+ u.bh.v = lastRowid;
+ u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+ u.bh.v++; /* ensure non-zero */
+ u.bh.cnt = 0;
+ while( ((rc = sqlite3BtreeMovetoUnpacked(u.bh.pC->pCursor, 0, (u64)u.bh.v,
+ 0, &u.bh.res))==SQLITE_OK)
+ && (u.bh.res==0)
+ && (++u.bh.cnt<100)){
/* collision - try another random rowid */
- sqlite3_randomness(sizeof(u.bg.v), &u.bg.v);
- if( u.bg.cnt<5 ){
+ sqlite3_randomness(sizeof(u.bh.v), &u.bh.v);
+ if( u.bh.cnt<5 ){
/* try "small" random rowids for the initial attempts */
- u.bg.v &= 0xffffff;
+ u.bh.v &= 0xffffff;
}else{
- u.bg.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
+ u.bh.v &= (MAX_ROWID>>1); /* ensure doesn't go negative */
}
- u.bg.v++; /* ensure non-zero */
+ u.bh.v++; /* ensure non-zero */
}
- if( rc==SQLITE_OK && u.bg.res==0 ){
+ if( rc==SQLITE_OK && u.bh.res==0 ){
rc = SQLITE_FULL; /* IMP: R-38219-53002 */
goto abort_due_to_error;
}
- assert( u.bg.v>0 ); /* EV: R-40812-03570 */
+ assert( u.bh.v>0 ); /* EV: R-40812-03570 */
}
- u.bg.pC->rowidIsValid = 0;
- u.bg.pC->deferredMoveto = 0;
- u.bg.pC->cacheStatus = CACHE_STALE;
+ u.bh.pC->rowidIsValid = 0;
+ u.bh.pC->deferredMoveto = 0;
+ u.bh.pC->cacheStatus = CACHE_STALE;
}
- pOut->u.i = u.bg.v;
+ pOut->u.i = u.bh.v;
break;
}
@@ -67517,7 +68189,7 @@ case OP_NewRowid: { /* out2-prerelease */
*/
case OP_Insert:
case OP_InsertInt: {
-#if 0 /* local variables moved into u.bh */
+#if 0 /* local variables moved into u.bi */
Mem *pData; /* MEM cell holding data for the record to be inserted */
Mem *pKey; /* MEM cell holding key for the record */
i64 iKey; /* The integer ROWID or key for the record to be inserted */
@@ -67527,60 +68199,60 @@ case OP_InsertInt: {
const char *zDb; /* database name - used by the update hook */
const char *zTbl; /* Table name - used by the opdate hook */
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
-#endif /* local variables moved into u.bh */
+#endif /* local variables moved into u.bi */
- u.bh.pData = &aMem[pOp->p2];
+ u.bi.pData = &aMem[pOp->p2];
assert( pOp->p1>=0 && pOp->p1nCursor );
- assert( memIsValid(u.bh.pData) );
- u.bh.pC = p->apCsr[pOp->p1];
- assert( u.bh.pC!=0 );
- assert( u.bh.pC->pCursor!=0 );
- assert( u.bh.pC->pseudoTableReg==0 );
- assert( u.bh.pC->isTable );
- REGISTER_TRACE(pOp->p2, u.bh.pData);
+ assert( memIsValid(u.bi.pData) );
+ u.bi.pC = p->apCsr[pOp->p1];
+ assert( u.bi.pC!=0 );
+ assert( u.bi.pC->pCursor!=0 );
+ assert( u.bi.pC->pseudoTableReg==0 );
+ assert( u.bi.pC->isTable );
+ REGISTER_TRACE(pOp->p2, u.bi.pData);
if( pOp->opcode==OP_Insert ){
- u.bh.pKey = &aMem[pOp->p3];
- assert( u.bh.pKey->flags & MEM_Int );
- assert( memIsValid(u.bh.pKey) );
- REGISTER_TRACE(pOp->p3, u.bh.pKey);
- u.bh.iKey = u.bh.pKey->u.i;
+ u.bi.pKey = &aMem[pOp->p3];
+ assert( u.bi.pKey->flags & MEM_Int );
+ assert( memIsValid(u.bi.pKey) );
+ REGISTER_TRACE(pOp->p3, u.bi.pKey);
+ u.bi.iKey = u.bi.pKey->u.i;
}else{
assert( pOp->opcode==OP_InsertInt );
- u.bh.iKey = pOp->p3;
+ u.bi.iKey = pOp->p3;
}
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
- if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bh.iKey;
- if( u.bh.pData->flags & MEM_Null ){
- u.bh.pData->z = 0;
- u.bh.pData->n = 0;
+ if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = lastRowid = u.bi.iKey;
+ if( u.bi.pData->flags & MEM_Null ){
+ u.bi.pData->z = 0;
+ u.bi.pData->n = 0;
}else{
- assert( u.bh.pData->flags & (MEM_Blob|MEM_Str) );
+ assert( u.bi.pData->flags & (MEM_Blob|MEM_Str) );
}
- u.bh.seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bh.pC->seekResult : 0);
- if( u.bh.pData->flags & MEM_Zero ){
- u.bh.nZero = u.bh.pData->u.nZero;
+ 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.bh.nZero = 0;
+ u.bi.nZero = 0;
}
- sqlite3BtreeSetCachedRowid(u.bh.pC->pCursor, 0);
- rc = sqlite3BtreeInsert(u.bh.pC->pCursor, 0, u.bh.iKey,
- u.bh.pData->z, u.bh.pData->n, u.bh.nZero,
- pOp->p5 & OPFLAG_APPEND, u.bh.seekResult
+ 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.bh.pC->rowidIsValid = 0;
- u.bh.pC->deferredMoveto = 0;
- u.bh.pC->cacheStatus = CACHE_STALE;
+ u.bi.pC->rowidIsValid = 0;
+ u.bi.pC->deferredMoveto = 0;
+ u.bi.pC->cacheStatus = CACHE_STALE;
/* Invoke the update-hook if required. */
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){
- u.bh.zDb = db->aDb[u.bh.pC->iDb].zName;
- u.bh.zTbl = pOp->p4.z;
- u.bh.op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT);
- assert( u.bh.pC->isTable );
- db->xUpdateCallback(db->pUpdateArg, u.bh.op, u.bh.zDb, u.bh.zTbl, u.bh.iKey);
- assert( u.bh.pC->iDb>=0 );
+ 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 );
}
break;
}
@@ -67606,47 +68278,47 @@ case OP_InsertInt: {
** using OP_NotFound prior to invoking this opcode.
*/
case OP_Delete: {
-#if 0 /* local variables moved into u.bi */
+#if 0 /* local variables moved into u.bj */
i64 iKey;
VdbeCursor *pC;
-#endif /* local variables moved into u.bi */
+#endif /* local variables moved into u.bj */
- u.bi.iKey = 0;
+ u.bj.iKey = 0;
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bi.pC = p->apCsr[pOp->p1];
- assert( u.bi.pC!=0 );
- assert( u.bi.pC->pCursor!=0 ); /* Only valid for real tables, no pseudotables */
+ u.bj.pC = p->apCsr[pOp->p1];
+ 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.bi.iKey to the rowid of the
+ /* If the update-hook will be invoked, set u.bj.iKey to the rowid of the
** row being deleted.
*/
if( db->xUpdateCallback && pOp->p4.z ){
- assert( u.bi.pC->isTable );
- assert( u.bi.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
- u.bi.iKey = u.bi.pC->lastRowid;
+ assert( u.bj.pC->isTable );
+ assert( u.bj.pC->rowidIsValid ); /* lastRowid set by previous OP_NotFound */
+ u.bj.iKey = u.bj.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.bi.pC is always pointing
+ ** might move or invalidate the cursor. Hence cursor u.bj.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.bi.pC->deferredMoveto==0 );
- rc = sqlite3VdbeCursorMoveto(u.bi.pC);
+ assert( u.bj.pC->deferredMoveto==0 );
+ rc = sqlite3VdbeCursorMoveto(u.bj.pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
- sqlite3BtreeSetCachedRowid(u.bi.pC->pCursor, 0);
- rc = sqlite3BtreeDelete(u.bi.pC->pCursor);
- u.bi.pC->cacheStatus = CACHE_STALE;
+ sqlite3BtreeSetCachedRowid(u.bj.pC->pCursor, 0);
+ rc = sqlite3BtreeDelete(u.bj.pC->pCursor);
+ u.bj.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.bi.pC->iDb].zName;
+ const char *zDb = db->aDb[u.bj.pC->iDb].zName;
const char *zTbl = pOp->p4.z;
- db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bi.iKey);
- assert( u.bi.pC->iDb>=0 );
+ db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, zTbl, u.bj.iKey);
+ assert( u.bj.pC->iDb>=0 );
}
if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
break;
@@ -67672,16 +68344,16 @@ case OP_ResetCount: {
** fall through to the next instruction. Otherwise, jump to instruction P2.
*/
case OP_SorterCompare: {
-#if 0 /* local variables moved into u.bj */
+#if 0 /* local variables moved into u.bk */
VdbeCursor *pC;
int res;
-#endif /* local variables moved into u.bj */
+#endif /* local variables moved into u.bk */
- u.bj.pC = p->apCsr[pOp->p1];
- assert( isSorter(u.bj.pC) );
+ u.bk.pC = p->apCsr[pOp->p1];
+ assert( isSorter(u.bk.pC) );
pIn3 = &aMem[pOp->p3];
- rc = sqlite3VdbeSorterCompare(u.bj.pC, pIn3, &u.bj.res);
- if( u.bj.res ){
+ rc = sqlite3VdbeSorterCompare(u.bk.pC, pIn3, &u.bk.res);
+ if( u.bk.res ){
pc = pOp->p2-1;
}
break;
@@ -67692,18 +68364,14 @@ case OP_SorterCompare: {
** Write into register P2 the current sorter data for sorter cursor P1.
*/
case OP_SorterData: {
-#if 0 /* local variables moved into u.bk */
+#if 0 /* local variables moved into u.bl */
VdbeCursor *pC;
-#endif /* local variables moved into u.bk */
-#ifndef SQLITE_OMIT_MERGE_SORT
+#endif /* local variables moved into u.bl */
+
pOut = &aMem[pOp->p2];
- u.bk.pC = p->apCsr[pOp->p1];
- assert( u.bk.pC->isSorter );
- rc = sqlite3VdbeSorterRowkey(u.bk.pC, pOut);
-#else
- pOp->opcode = OP_RowKey;
- pc--;
-#endif
+ u.bl.pC = p->apCsr[pOp->p1];
+ assert( u.bl.pC->isSorter );
+ rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
break;
}
@@ -67729,62 +68397,62 @@ case OP_SorterData: {
*/
case OP_RowKey:
case OP_RowData: {
-#if 0 /* local variables moved into u.bl */
+#if 0 /* local variables moved into u.bm */
VdbeCursor *pC;
BtCursor *pCrsr;
u32 n;
i64 n64;
-#endif /* local variables moved into u.bl */
+#endif /* local variables moved into u.bm */
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
/* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bl.pC = p->apCsr[pOp->p1];
- assert( u.bl.pC->isSorter==0 );
- assert( u.bl.pC->isTable || pOp->opcode!=OP_RowData );
- assert( u.bl.pC->isIndex || pOp->opcode==OP_RowData );
- assert( u.bl.pC!=0 );
- assert( u.bl.pC->nullRow==0 );
- assert( u.bl.pC->pseudoTableReg==0 );
- assert( u.bl.pC->pCursor!=0 );
- u.bl.pCrsr = u.bl.pC->pCursor;
- assert( sqlite3BtreeCursorIsValid(u.bl.pCrsr) );
+ u.bm.pC = p->apCsr[pOp->p1];
+ assert( u.bm.pC->isSorter==0 );
+ assert( u.bm.pC->isTable || pOp->opcode!=OP_RowData );
+ assert( u.bm.pC->isIndex || pOp->opcode==OP_RowData );
+ assert( u.bm.pC!=0 );
+ assert( u.bm.pC->nullRow==0 );
+ assert( u.bm.pC->pseudoTableReg==0 );
+ assert( u.bm.pC->pCursor!=0 );
+ u.bm.pCrsr = u.bm.pC->pCursor;
+ assert( sqlite3BtreeCursorIsValid(u.bm.pCrsr) );
/* 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.bl.pC->deferredMoveto==0 );
- rc = sqlite3VdbeCursorMoveto(u.bl.pC);
+ assert( u.bm.pC->deferredMoveto==0 );
+ rc = sqlite3VdbeCursorMoveto(u.bm.pC);
if( NEVER(rc!=SQLITE_OK) ) goto abort_due_to_error;
- if( u.bl.pC->isIndex ){
- assert( !u.bl.pC->isTable );
- VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bl.pCrsr, &u.bl.n64);
+ if( u.bm.pC->isIndex ){
+ assert( !u.bm.pC->isTable );
+ VVA_ONLY(rc =) sqlite3BtreeKeySize(u.bm.pCrsr, &u.bm.n64);
assert( rc==SQLITE_OK ); /* True because of CursorMoveto() call above */
- if( u.bl.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( u.bm.n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- u.bl.n = (u32)u.bl.n64;
+ u.bm.n = (u32)u.bm.n64;
}else{
- VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bl.pCrsr, &u.bl.n);
+ VVA_ONLY(rc =) sqlite3BtreeDataSize(u.bm.pCrsr, &u.bm.n);
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
- if( u.bl.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( u.bm.n>(u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
}
- if( sqlite3VdbeMemGrow(pOut, u.bl.n, 0) ){
+ if( sqlite3VdbeMemGrow(pOut, u.bm.n, 0) ){
goto no_mem;
}
- pOut->n = u.bl.n;
+ pOut->n = u.bm.n;
MemSetTypeFlag(pOut, MEM_Blob);
- if( u.bl.pC->isIndex ){
- rc = sqlite3BtreeKey(u.bl.pCrsr, 0, u.bl.n, pOut->z);
+ if( u.bm.pC->isIndex ){
+ rc = sqlite3BtreeKey(u.bm.pCrsr, 0, u.bm.n, pOut->z);
}else{
- rc = sqlite3BtreeData(u.bl.pCrsr, 0, u.bl.n, pOut->z);
+ rc = sqlite3BtreeData(u.bm.pCrsr, 0, u.bm.n, pOut->z);
}
pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */
UPDATE_MAX_BLOBSIZE(pOut);
@@ -67801,42 +68469,42 @@ case OP_RowData: {
** one opcode now works for both table types.
*/
case OP_Rowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bm */
+#if 0 /* local variables moved into u.bn */
VdbeCursor *pC;
i64 v;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
-#endif /* local variables moved into u.bm */
+#endif /* local variables moved into u.bn */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bm.pC = p->apCsr[pOp->p1];
- assert( u.bm.pC!=0 );
- assert( u.bm.pC->pseudoTableReg==0 );
- if( u.bm.pC->nullRow ){
+ u.bn.pC = p->apCsr[pOp->p1];
+ assert( u.bn.pC!=0 );
+ assert( u.bn.pC->pseudoTableReg==0 || u.bn.pC->nullRow );
+ if( u.bn.pC->nullRow ){
pOut->flags = MEM_Null;
break;
- }else if( u.bm.pC->deferredMoveto ){
- u.bm.v = u.bm.pC->movetoTarget;
+ }else if( u.bn.pC->deferredMoveto ){
+ u.bn.v = u.bn.pC->movetoTarget;
#ifndef SQLITE_OMIT_VIRTUALTABLE
- }else if( u.bm.pC->pVtabCursor ){
- u.bm.pVtab = u.bm.pC->pVtabCursor->pVtab;
- u.bm.pModule = u.bm.pVtab->pModule;
- assert( u.bm.pModule->xRowid );
- rc = u.bm.pModule->xRowid(u.bm.pC->pVtabCursor, &u.bm.v);
- importVtabErrMsg(p, u.bm.pVtab);
+ }else if( u.bn.pC->pVtabCursor ){
+ u.bn.pVtab = u.bn.pC->pVtabCursor->pVtab;
+ u.bn.pModule = u.bn.pVtab->pModule;
+ assert( u.bn.pModule->xRowid );
+ rc = u.bn.pModule->xRowid(u.bn.pC->pVtabCursor, &u.bn.v);
+ importVtabErrMsg(p, u.bn.pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
- assert( u.bm.pC->pCursor!=0 );
- rc = sqlite3VdbeCursorMoveto(u.bm.pC);
+ assert( u.bn.pC->pCursor!=0 );
+ rc = sqlite3VdbeCursorMoveto(u.bn.pC);
if( rc ) goto abort_due_to_error;
- if( u.bm.pC->rowidIsValid ){
- u.bm.v = u.bm.pC->lastRowid;
+ if( u.bn.pC->rowidIsValid ){
+ u.bn.v = u.bn.pC->lastRowid;
}else{
- rc = sqlite3BtreeKeySize(u.bm.pC->pCursor, &u.bm.v);
+ rc = sqlite3BtreeKeySize(u.bn.pC->pCursor, &u.bn.v);
assert( rc==SQLITE_OK ); /* Always so because of CursorMoveto() above */
}
}
- pOut->u.i = u.bm.v;
+ pOut->u.i = u.bn.v;
break;
}
@@ -67847,18 +68515,18 @@ case OP_Rowid: { /* out2-prerelease */
** write a NULL.
*/
case OP_NullRow: {
-#if 0 /* local variables moved into u.bn */
+#if 0 /* local variables moved into u.bo */
VdbeCursor *pC;
-#endif /* local variables moved into u.bn */
+#endif /* local variables moved into u.bo */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bn.pC = p->apCsr[pOp->p1];
- assert( u.bn.pC!=0 );
- u.bn.pC->nullRow = 1;
- u.bn.pC->rowidIsValid = 0;
- assert( u.bn.pC->pCursor || u.bn.pC->pVtabCursor );
- if( u.bn.pC->pCursor ){
- sqlite3BtreeClearCursor(u.bn.pC->pCursor);
+ u.bo.pC = p->apCsr[pOp->p1];
+ assert( u.bo.pC!=0 );
+ u.bo.pC->nullRow = 1;
+ u.bo.pC->rowidIsValid = 0;
+ assert( u.bo.pC->pCursor || u.bo.pC->pVtabCursor );
+ if( u.bo.pC->pCursor ){
+ sqlite3BtreeClearCursor(u.bo.pC->pCursor);
}
break;
}
@@ -67872,25 +68540,25 @@ case OP_NullRow: {
** to the following instruction.
*/
case OP_Last: { /* jump */
-#if 0 /* local variables moved into u.bo */
+#if 0 /* local variables moved into u.bp */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
-#endif /* local variables moved into u.bo */
+#endif /* local variables moved into u.bp */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bo.pC = p->apCsr[pOp->p1];
- assert( u.bo.pC!=0 );
- u.bo.pCrsr = u.bo.pC->pCursor;
- u.bo.res = 0;
- if( ALWAYS(u.bo.pCrsr!=0) ){
- rc = sqlite3BtreeLast(u.bo.pCrsr, &u.bo.res);
+ u.bp.pC = p->apCsr[pOp->p1];
+ assert( u.bp.pC!=0 );
+ u.bp.pCrsr = u.bp.pC->pCursor;
+ u.bp.res = 0;
+ if( ALWAYS(u.bp.pCrsr!=0) ){
+ rc = sqlite3BtreeLast(u.bp.pCrsr, &u.bp.res);
}
- u.bo.pC->nullRow = (u8)u.bo.res;
- u.bo.pC->deferredMoveto = 0;
- u.bo.pC->rowidIsValid = 0;
- u.bo.pC->cacheStatus = CACHE_STALE;
- if( pOp->p2>0 && u.bo.res ){
+ u.bp.pC->nullRow = (u8)u.bp.res;
+ u.bp.pC->deferredMoveto = 0;
+ u.bp.pC->rowidIsValid = 0;
+ u.bp.pC->cacheStatus = CACHE_STALE;
+ if( pOp->p2>0 && u.bp.res ){
pc = pOp->p2 - 1;
}
break;
@@ -67910,9 +68578,6 @@ case OP_Last: { /* jump */
** correctly optimizing out sorts.
*/
case OP_SorterSort: /* jump */
-#ifdef SQLITE_OMIT_MERGE_SORT
- pOp->opcode = OP_Sort;
-#endif
case OP_Sort: { /* jump */
#ifdef SQLITE_TEST
sqlite3_sort_count++;
@@ -67930,31 +68595,31 @@ case OP_Sort: { /* jump */
** to the following instruction.
*/
case OP_Rewind: { /* jump */
-#if 0 /* local variables moved into u.bp */
+#if 0 /* local variables moved into u.bq */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
-#endif /* local variables moved into u.bp */
+#endif /* local variables moved into u.bq */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bp.pC = p->apCsr[pOp->p1];
- assert( u.bp.pC!=0 );
- assert( u.bp.pC->isSorter==(pOp->opcode==OP_SorterSort) );
- u.bp.res = 1;
- if( isSorter(u.bp.pC) ){
- rc = sqlite3VdbeSorterRewind(db, u.bp.pC, &u.bp.res);
+ u.bq.pC = p->apCsr[pOp->p1];
+ assert( u.bq.pC!=0 );
+ assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterSort) );
+ u.bq.res = 1;
+ if( isSorter(u.bq.pC) ){
+ rc = sqlite3VdbeSorterRewind(db, u.bq.pC, &u.bq.res);
}else{
- u.bp.pCrsr = u.bp.pC->pCursor;
- assert( u.bp.pCrsr );
- rc = sqlite3BtreeFirst(u.bp.pCrsr, &u.bp.res);
- u.bp.pC->atFirst = u.bp.res==0 ?1:0;
- u.bp.pC->deferredMoveto = 0;
- u.bp.pC->cacheStatus = CACHE_STALE;
- u.bp.pC->rowidIsValid = 0;
+ u.bq.pCrsr = u.bq.pC->pCursor;
+ assert( u.bq.pCrsr );
+ rc = sqlite3BtreeFirst(u.bq.pCrsr, &u.bq.res);
+ u.bq.pC->atFirst = u.bq.res==0 ?1:0;
+ u.bq.pC->deferredMoveto = 0;
+ u.bq.pC->cacheStatus = CACHE_STALE;
+ u.bq.pC->rowidIsValid = 0;
}
- u.bp.pC->nullRow = (u8)u.bp.res;
+ u.bq.pC->nullRow = (u8)u.bq.res;
assert( pOp->p2>0 && pOp->p2nOp );
- if( u.bp.res ){
+ if( u.bq.res ){
pc = pOp->p2 - 1;
}
break;
@@ -67993,45 +68658,42 @@ case OP_Rewind: { /* jump */
** number P5-1 in the prepared statement is incremented.
*/
case OP_SorterNext: /* jump */
-#ifdef SQLITE_OMIT_MERGE_SORT
- pOp->opcode = OP_Next;
-#endif
case OP_Prev: /* jump */
case OP_Next: { /* jump */
-#if 0 /* local variables moved into u.bq */
+#if 0 /* local variables moved into u.br */
VdbeCursor *pC;
int res;
-#endif /* local variables moved into u.bq */
+#endif /* local variables moved into u.br */
CHECK_FOR_INTERRUPT;
assert( pOp->p1>=0 && pOp->p1nCursor );
assert( pOp->p5<=ArraySize(p->aCounter) );
- u.bq.pC = p->apCsr[pOp->p1];
- if( u.bq.pC==0 ){
+ u.br.pC = p->apCsr[pOp->p1];
+ if( u.br.pC==0 ){
break; /* See ticket #2273 */
}
- assert( u.bq.pC->isSorter==(pOp->opcode==OP_SorterNext) );
- if( isSorter(u.bq.pC) ){
+ assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterNext) );
+ if( isSorter(u.br.pC) ){
assert( pOp->opcode==OP_SorterNext );
- rc = sqlite3VdbeSorterNext(db, u.bq.pC, &u.bq.res);
+ rc = sqlite3VdbeSorterNext(db, u.br.pC, &u.br.res);
}else{
- u.bq.res = 1;
- assert( u.bq.pC->deferredMoveto==0 );
- assert( u.bq.pC->pCursor );
+ u.br.res = 1;
+ assert( u.br.pC->deferredMoveto==0 );
+ assert( u.br.pC->pCursor );
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
- rc = pOp->p4.xAdvance(u.bq.pC->pCursor, &u.bq.res);
+ rc = pOp->p4.xAdvance(u.br.pC->pCursor, &u.br.res);
}
- u.bq.pC->nullRow = (u8)u.bq.res;
- u.bq.pC->cacheStatus = CACHE_STALE;
- if( u.bq.res==0 ){
+ u.br.pC->nullRow = (u8)u.br.res;
+ u.br.pC->cacheStatus = CACHE_STALE;
+ if( u.br.res==0 ){
pc = pOp->p2 - 1;
if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
}
- u.bq.pC->rowidIsValid = 0;
+ u.br.pC->rowidIsValid = 0;
break;
}
@@ -68048,38 +68710,35 @@ case OP_Next: { /* jump */
** for tables is OP_Insert.
*/
case OP_SorterInsert: /* in2 */
-#ifdef SQLITE_OMIT_MERGE_SORT
- pOp->opcode = OP_IdxInsert;
-#endif
case OP_IdxInsert: { /* in2 */
-#if 0 /* local variables moved into u.br */
+#if 0 /* local variables moved into u.bs */
VdbeCursor *pC;
BtCursor *pCrsr;
int nKey;
const char *zKey;
-#endif /* local variables moved into u.br */
+#endif /* local variables moved into u.bs */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.br.pC = p->apCsr[pOp->p1];
- assert( u.br.pC!=0 );
- assert( u.br.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
+ u.bs.pC = p->apCsr[pOp->p1];
+ assert( u.bs.pC!=0 );
+ assert( u.bs.pC->isSorter==(pOp->opcode==OP_SorterInsert) );
pIn2 = &aMem[pOp->p2];
assert( pIn2->flags & MEM_Blob );
- u.br.pCrsr = u.br.pC->pCursor;
- if( ALWAYS(u.br.pCrsr!=0) ){
- assert( u.br.pC->isTable==0 );
+ u.bs.pCrsr = u.bs.pC->pCursor;
+ if( ALWAYS(u.bs.pCrsr!=0) ){
+ assert( u.bs.pC->isTable==0 );
rc = ExpandBlob(pIn2);
if( rc==SQLITE_OK ){
- if( isSorter(u.br.pC) ){
- rc = sqlite3VdbeSorterWrite(db, u.br.pC, pIn2);
+ if( isSorter(u.bs.pC) ){
+ rc = sqlite3VdbeSorterWrite(db, u.bs.pC, pIn2);
}else{
- u.br.nKey = pIn2->n;
- u.br.zKey = pIn2->z;
- rc = sqlite3BtreeInsert(u.br.pCrsr, u.br.zKey, u.br.nKey, "", 0, 0, pOp->p3,
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.br.pC->seekResult : 0)
+ u.bs.nKey = pIn2->n;
+ u.bs.zKey = pIn2->z;
+ rc = sqlite3BtreeInsert(u.bs.pCrsr, u.bs.zKey, u.bs.nKey, "", 0, 0, pOp->p3,
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? u.bs.pC->seekResult : 0)
);
- assert( u.br.pC->deferredMoveto==0 );
- u.br.pC->cacheStatus = CACHE_STALE;
+ assert( u.bs.pC->deferredMoveto==0 );
+ u.bs.pC->cacheStatus = CACHE_STALE;
}
}
}
@@ -68093,33 +68752,33 @@ case OP_IdxInsert: { /* in2 */
** index opened by cursor P1.
*/
case OP_IdxDelete: {
-#if 0 /* local variables moved into u.bs */
+#if 0 /* local variables moved into u.bt */
VdbeCursor *pC;
BtCursor *pCrsr;
int res;
UnpackedRecord r;
-#endif /* local variables moved into u.bs */
+#endif /* local variables moved into u.bt */
assert( pOp->p3>0 );
assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bs.pC = p->apCsr[pOp->p1];
- assert( u.bs.pC!=0 );
- u.bs.pCrsr = u.bs.pC->pCursor;
- if( ALWAYS(u.bs.pCrsr!=0) ){
- u.bs.r.pKeyInfo = u.bs.pC->pKeyInfo;
- u.bs.r.nField = (u16)pOp->p3;
- u.bs.r.flags = 0;
- u.bs.r.aMem = &aMem[pOp->p2];
+ u.bt.pC = p->apCsr[pOp->p1];
+ assert( u.bt.pC!=0 );
+ u.bt.pCrsr = u.bt.pC->pCursor;
+ if( ALWAYS(u.bt.pCrsr!=0) ){
+ u.bt.r.pKeyInfo = u.bt.pC->pKeyInfo;
+ u.bt.r.nField = (u16)pOp->p3;
+ u.bt.r.flags = 0;
+ u.bt.r.aMem = &aMem[pOp->p2];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; ideferredMoveto==0 );
- u.bs.pC->cacheStatus = CACHE_STALE;
+ assert( u.bt.pC->deferredMoveto==0 );
+ u.bt.pC->cacheStatus = CACHE_STALE;
}
break;
}
@@ -68133,28 +68792,28 @@ case OP_IdxDelete: {
** See also: Rowid, MakeRecord.
*/
case OP_IdxRowid: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bt */
+#if 0 /* local variables moved into u.bu */
BtCursor *pCrsr;
VdbeCursor *pC;
i64 rowid;
-#endif /* local variables moved into u.bt */
+#endif /* local variables moved into u.bu */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bt.pC = p->apCsr[pOp->p1];
- assert( u.bt.pC!=0 );
- u.bt.pCrsr = u.bt.pC->pCursor;
+ u.bu.pC = p->apCsr[pOp->p1];
+ assert( u.bu.pC!=0 );
+ u.bu.pCrsr = u.bu.pC->pCursor;
pOut->flags = MEM_Null;
- if( ALWAYS(u.bt.pCrsr!=0) ){
- rc = sqlite3VdbeCursorMoveto(u.bt.pC);
+ if( ALWAYS(u.bu.pCrsr!=0) ){
+ rc = sqlite3VdbeCursorMoveto(u.bu.pC);
if( NEVER(rc) ) goto abort_due_to_error;
- assert( u.bt.pC->deferredMoveto==0 );
- assert( u.bt.pC->isTable==0 );
- if( !u.bt.pC->nullRow ){
- rc = sqlite3VdbeIdxRowid(db, u.bt.pCrsr, &u.bt.rowid);
+ assert( u.bu.pC->deferredMoveto==0 );
+ assert( u.bu.pC->isTable==0 );
+ if( !u.bu.pC->nullRow ){
+ rc = sqlite3VdbeIdxRowid(db, u.bu.pCrsr, &u.bu.rowid);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- pOut->u.i = u.bt.rowid;
+ pOut->u.i = u.bu.rowid;
pOut->flags = MEM_Int;
}
}
@@ -68189,39 +68848,39 @@ case OP_IdxRowid: { /* out2-prerelease */
*/
case OP_IdxLT: /* jump */
case OP_IdxGE: { /* jump */
-#if 0 /* local variables moved into u.bu */
+#if 0 /* local variables moved into u.bv */
VdbeCursor *pC;
int res;
UnpackedRecord r;
-#endif /* local variables moved into u.bu */
+#endif /* local variables moved into u.bv */
assert( pOp->p1>=0 && pOp->p1nCursor );
- u.bu.pC = p->apCsr[pOp->p1];
- assert( u.bu.pC!=0 );
- assert( u.bu.pC->isOrdered );
- if( ALWAYS(u.bu.pC->pCursor!=0) ){
- assert( u.bu.pC->deferredMoveto==0 );
+ u.bv.pC = p->apCsr[pOp->p1];
+ assert( u.bv.pC!=0 );
+ assert( u.bv.pC->isOrdered );
+ if( ALWAYS(u.bv.pC->pCursor!=0) ){
+ assert( u.bv.pC->deferredMoveto==0 );
assert( pOp->p5==0 || pOp->p5==1 );
assert( pOp->p4type==P4_INT32 );
- u.bu.r.pKeyInfo = u.bu.pC->pKeyInfo;
- u.bu.r.nField = (u16)pOp->p4.i;
+ u.bv.r.pKeyInfo = u.bv.pC->pKeyInfo;
+ u.bv.r.nField = (u16)pOp->p4.i;
if( pOp->p5 ){
- u.bu.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
+ u.bv.r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH;
}else{
- u.bu.r.flags = UNPACKED_PREFIX_MATCH;
+ u.bv.r.flags = UNPACKED_PREFIX_MATCH;
}
- u.bu.r.aMem = &aMem[pOp->p3];
+ u.bv.r.aMem = &aMem[pOp->p3];
#ifdef SQLITE_DEBUG
- { int i; for(i=0; iopcode==OP_IdxLT ){
- u.bu.res = -u.bu.res;
+ u.bv.res = -u.bv.res;
}else{
assert( pOp->opcode==OP_IdxGE );
- u.bu.res++;
+ u.bv.res++;
}
- if( u.bu.res>0 ){
+ if( u.bv.res>0 ){
pc = pOp->p2 - 1 ;
}
}
@@ -68249,39 +68908,40 @@ case OP_IdxGE: { /* jump */
** See also: Clear
*/
case OP_Destroy: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bv */
+#if 0 /* local variables moved into u.bw */
int iMoved;
int iCnt;
Vdbe *pVdbe;
int iDb;
-#endif /* local variables moved into u.bv */
+#endif /* local variables moved into u.bw */
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
- u.bv.iCnt = 0;
- for(u.bv.pVdbe=db->pVdbe; u.bv.pVdbe; u.bv.pVdbe = u.bv.pVdbe->pNext){
- if( u.bv.pVdbe->magic==VDBE_MAGIC_RUN && u.bv.pVdbe->inVtabMethod<2 && u.bv.pVdbe->pc>=0 ){
- u.bv.iCnt++;
+ u.bw.iCnt = 0;
+ for(u.bw.pVdbe=db->pVdbe; u.bw.pVdbe; u.bw.pVdbe = u.bw.pVdbe->pNext){
+ if( u.bw.pVdbe->magic==VDBE_MAGIC_RUN && u.bw.pVdbe->inVtabMethod<2 && u.bw.pVdbe->pc>=0 ){
+ u.bw.iCnt++;
}
}
#else
- u.bv.iCnt = db->activeVdbeCnt;
+ u.bw.iCnt = db->activeVdbeCnt;
#endif
pOut->flags = MEM_Null;
- if( u.bv.iCnt>1 ){
+ if( u.bw.iCnt>1 ){
rc = SQLITE_LOCKED;
p->errorAction = OE_Abort;
}else{
- u.bv.iDb = pOp->p3;
- assert( u.bv.iCnt==1 );
- assert( (p->btreeMask & (((yDbMask)1)<aDb[u.bv.iDb].pBt, pOp->p1, &u.bv.iMoved);
+ u.bw.iDb = pOp->p3;
+ assert( u.bw.iCnt==1 );
+ assert( (p->btreeMask & (((yDbMask)1)<aDb[u.bw.iDb].pBt, pOp->p1, &u.bw.iMoved);
pOut->flags = MEM_Int;
- pOut->u.i = u.bv.iMoved;
+ pOut->u.i = u.bw.iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
- if( rc==SQLITE_OK && u.bv.iMoved!=0 ){
- sqlite3RootPageMoved(db, u.bv.iDb, u.bv.iMoved, pOp->p1);
+ if( rc==SQLITE_OK && u.bw.iMoved!=0 ){
+ sqlite3RootPageMoved(db, u.bw.iDb, u.bw.iMoved, pOp->p1);
/* All OP_Destroy operations occur on the same btree */
- assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bv.iDb+1 );
- resetSchemaOnFault = u.bv.iDb+1;
+ assert( resetSchemaOnFault==0 || resetSchemaOnFault==u.bw.iDb+1 );
+ resetSchemaOnFault = u.bw.iDb+1;
}
#endif
}
@@ -68307,21 +68967,21 @@ case OP_Destroy: { /* out2-prerelease */
** See also: Destroy
*/
case OP_Clear: {
-#if 0 /* local variables moved into u.bw */
+#if 0 /* local variables moved into u.bx */
int nChange;
-#endif /* local variables moved into u.bw */
+#endif /* local variables moved into u.bx */
- u.bw.nChange = 0;
+ u.bx.nChange = 0;
assert( (p->btreeMask & (((yDbMask)1)<p2))!=0 );
rc = sqlite3BtreeClearTable(
- db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bw.nChange : 0)
+ db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &u.bx.nChange : 0)
);
if( pOp->p3 ){
- p->nChange += u.bw.nChange;
+ p->nChange += u.bx.nChange;
if( pOp->p3>0 ){
assert( memIsValid(&aMem[pOp->p3]) );
memAboutToChange(p, &aMem[pOp->p3]);
- aMem[pOp->p3].u.i += u.bw.nChange;
+ aMem[pOp->p3].u.i += u.bx.nChange;
}
}
break;
@@ -68351,25 +69011,25 @@ case OP_Clear: {
*/
case OP_CreateIndex: /* out2-prerelease */
case OP_CreateTable: { /* out2-prerelease */
-#if 0 /* local variables moved into u.bx */
+#if 0 /* local variables moved into u.by */
int pgno;
int flags;
Db *pDb;
-#endif /* local variables moved into u.bx */
+#endif /* local variables moved into u.by */
- u.bx.pgno = 0;
+ u.by.pgno = 0;
assert( pOp->p1>=0 && pOp->p1nDb );
assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 );
- u.bx.pDb = &db->aDb[pOp->p1];
- assert( u.bx.pDb->pBt!=0 );
+ u.by.pDb = &db->aDb[pOp->p1];
+ assert( u.by.pDb->pBt!=0 );
if( pOp->opcode==OP_CreateTable ){
- /* u.bx.flags = BTREE_INTKEY; */
- u.bx.flags = BTREE_INTKEY;
+ /* u.by.flags = BTREE_INTKEY; */
+ u.by.flags = BTREE_INTKEY;
}else{
- u.bx.flags = BTREE_BLOBKEY;
+ u.by.flags = BTREE_BLOBKEY;
}
- rc = sqlite3BtreeCreateTable(u.bx.pDb->pBt, &u.bx.pgno, u.bx.flags);
- pOut->u.i = u.bx.pgno;
+ rc = sqlite3BtreeCreateTable(u.by.pDb->pBt, &u.by.pgno, u.by.flags);
+ pOut->u.i = u.by.pgno;
break;
}
@@ -68382,44 +69042,44 @@ case OP_CreateTable: { /* out2-prerelease */
** then runs the new virtual machine. It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
-#if 0 /* local variables moved into u.by */
+#if 0 /* local variables moved into u.bz */
int iDb;
const char *zMaster;
char *zSql;
InitData initData;
-#endif /* local variables moved into u.by */
+#endif /* local variables moved into u.bz */
/* Any prepared statement that invokes this opcode will hold mutexes
** on every btree. This is a prerequisite for invoking
** sqlite3InitCallback().
*/
#ifdef SQLITE_DEBUG
- for(u.by.iDb=0; u.by.iDbnDb; u.by.iDb++){
- assert( u.by.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.by.iDb].pBt) );
+ for(u.bz.iDb=0; u.bz.iDbnDb; u.bz.iDb++){
+ assert( u.bz.iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[u.bz.iDb].pBt) );
}
#endif
- u.by.iDb = pOp->p1;
- assert( u.by.iDb>=0 && u.by.iDbnDb );
- assert( DbHasProperty(db, u.by.iDb, DB_SchemaLoaded) );
+ u.bz.iDb = pOp->p1;
+ assert( u.bz.iDb>=0 && u.bz.iDbnDb );
+ assert( DbHasProperty(db, u.bz.iDb, DB_SchemaLoaded) );
/* Used to be a conditional */ {
- u.by.zMaster = SCHEMA_TABLE(u.by.iDb);
- u.by.initData.db = db;
- u.by.initData.iDb = pOp->p1;
- u.by.initData.pzErrMsg = &p->zErrMsg;
- u.by.zSql = sqlite3MPrintf(db,
+ u.bz.zMaster = SCHEMA_TABLE(u.bz.iDb);
+ u.bz.initData.db = db;
+ u.bz.initData.iDb = pOp->p1;
+ u.bz.initData.pzErrMsg = &p->zErrMsg;
+ u.bz.zSql = sqlite3MPrintf(db,
"SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
- db->aDb[u.by.iDb].zName, u.by.zMaster, pOp->p4.z);
- if( u.by.zSql==0 ){
+ db->aDb[u.bz.iDb].zName, u.bz.zMaster, pOp->p4.z);
+ if( u.bz.zSql==0 ){
rc = SQLITE_NOMEM;
}else{
assert( db->init.busy==0 );
db->init.busy = 1;
- u.by.initData.rc = SQLITE_OK;
+ u.bz.initData.rc = SQLITE_OK;
assert( !db->mallocFailed );
- rc = sqlite3_exec(db, u.by.zSql, sqlite3InitCallback, &u.by.initData, 0);
- if( rc==SQLITE_OK ) rc = u.by.initData.rc;
- sqlite3DbFree(db, u.by.zSql);
+ rc = sqlite3_exec(db, u.bz.zSql, sqlite3InitCallback, &u.bz.initData, 0);
+ if( rc==SQLITE_OK ) rc = u.bz.initData.rc;
+ sqlite3DbFree(db, u.bz.zSql);
db->init.busy = 0;
}
}
@@ -68503,41 +69163,41 @@ case OP_DropTrigger: {
** This opcode is used to implement the integrity_check pragma.
*/
case OP_IntegrityCk: {
-#if 0 /* local variables moved into u.bz */
+#if 0 /* local variables moved into u.ca */
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.bz */
+#endif /* local variables moved into u.ca */
- u.bz.nRoot = pOp->p2;
- assert( u.bz.nRoot>0 );
- u.bz.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.bz.nRoot+1) );
- if( u.bz.aRoot==0 ) goto no_mem;
+ u.ca.nRoot = pOp->p2;
+ assert( u.ca.nRoot>0 );
+ u.ca.aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(u.ca.nRoot+1) );
+ if( u.ca.aRoot==0 ) goto no_mem;
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.bz.pnErr = &aMem[pOp->p3];
- assert( (u.bz.pnErr->flags & MEM_Int)!=0 );
- assert( (u.bz.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
+ u.ca.pnErr = &aMem[pOp->p3];
+ assert( (u.ca.pnErr->flags & MEM_Int)!=0 );
+ assert( (u.ca.pnErr->flags & (MEM_Str|MEM_Blob))==0 );
pIn1 = &aMem[pOp->p1];
- for(u.bz.j=0; u.bz.jp5nDb );
assert( (p->btreeMask & (((yDbMask)1)<p5))!=0 );
- u.bz.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.bz.aRoot, u.bz.nRoot,
- (int)u.bz.pnErr->u.i, &u.bz.nErr);
- sqlite3DbFree(db, u.bz.aRoot);
- u.bz.pnErr->u.i -= u.bz.nErr;
+ u.ca.z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, u.ca.aRoot, u.ca.nRoot,
+ (int)u.ca.pnErr->u.i, &u.ca.nErr);
+ sqlite3DbFree(db, u.ca.aRoot);
+ u.ca.pnErr->u.i -= u.ca.nErr;
sqlite3VdbeMemSetNull(pIn1);
- if( u.bz.nErr==0 ){
- assert( u.bz.z==0 );
- }else if( u.bz.z==0 ){
+ if( u.ca.nErr==0 ){
+ assert( u.ca.z==0 );
+ }else if( u.ca.z==0 ){
goto no_mem;
}else{
- sqlite3VdbeMemSetStr(pIn1, u.bz.z, -1, SQLITE_UTF8, sqlite3_free);
+ sqlite3VdbeMemSetStr(pIn1, u.ca.z, -1, SQLITE_UTF8, sqlite3_free);
}
UPDATE_MAX_BLOBSIZE(pIn1);
sqlite3VdbeChangeEncoding(pIn1, encoding);
@@ -68571,20 +69231,20 @@ case OP_RowSetAdd: { /* in1, in2 */
** unchanged and jump to instruction P2.
*/
case OP_RowSetRead: { /* jump, in1, out3 */
-#if 0 /* local variables moved into u.ca */
+#if 0 /* local variables moved into u.cb */
i64 val;
-#endif /* local variables moved into u.ca */
+#endif /* local variables moved into u.cb */
CHECK_FOR_INTERRUPT;
pIn1 = &aMem[pOp->p1];
if( (pIn1->flags & MEM_RowSet)==0
- || sqlite3RowSetNext(pIn1->u.pRowSet, &u.ca.val)==0
+ || sqlite3RowSetNext(pIn1->u.pRowSet, &u.cb.val)==0
){
/* The boolean index is empty */
sqlite3VdbeMemSetNull(pIn1);
pc = pOp->p2 - 1;
}else{
/* A value was pulled from the index */
- sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.ca.val);
+ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], u.cb.val);
}
break;
}
@@ -68613,14 +69273,14 @@ case OP_RowSetRead: { /* jump, in1, out3 */
** 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.cc */
int iSet;
int exists;
-#endif /* local variables moved into u.cb */
+#endif /* local variables moved into u.cc */
pIn1 = &aMem[pOp->p1];
pIn3 = &aMem[pOp->p3];
- u.cb.iSet = pOp->p4.i;
+ u.cc.iSet = pOp->p4.i;
assert( pIn3->flags&MEM_Int );
/* If there is anything other than a rowset object in memory cell P1,
@@ -68632,17 +69292,17 @@ case OP_RowSetTest: { /* jump, in1, in3 */
}
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.cc.iSet==-1 || u.cc.iSet>=0 );
+ if( u.cc.iSet ){
+ u.cc.exists = sqlite3RowSetTest(pIn1->u.pRowSet,
+ (u8)(u.cc.iSet>=0 ? u.cc.iSet & 0xf : 0xff),
pIn3->u.i);
- if( u.cb.exists ){
+ if( u.cc.exists ){
pc = pOp->p2 - 1;
break;
}
}
- if( u.cb.iSet>=0 ){
+ if( u.cc.iSet>=0 ){
sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
}
break;
@@ -68665,7 +69325,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
** P4 is a pointer to the VM containing the trigger program.
*/
case OP_Program: { /* jump */
-#if 0 /* local variables moved into u.cc */
+#if 0 /* local variables moved into u.cd */
int nMem; /* Number of memory registers for sub-program */
int nByte; /* Bytes of runtime space required for sub-program */
Mem *pRt; /* Register to allocate runtime space */
@@ -68674,11 +69334,11 @@ case OP_Program: { /* jump */
VdbeFrame *pFrame; /* New vdbe frame to execute in */
SubProgram *pProgram; /* Sub-program to execute */
void *t; /* Token identifying trigger */
-#endif /* local variables moved into u.cc */
+#endif /* local variables moved into u.cd */
- u.cc.pProgram = pOp->p4.pProgram;
- u.cc.pRt = &aMem[pOp->p3];
- assert( u.cc.pProgram->nOp>0 );
+ u.cd.pProgram = pOp->p4.pProgram;
+ u.cd.pRt = &aMem[pOp->p3];
+ assert( u.cd.pProgram->nOp>0 );
/* If the p5 flag is clear, then recursive invocation of triggers is
** disabled for backwards compatibility (p5 is set if this sub-program
@@ -68692,9 +69352,9 @@ case OP_Program: { /* jump */
** single trigger all have the same value for the SubProgram.token
** variable. */
if( pOp->p5 ){
- u.cc.t = u.cc.pProgram->token;
- for(u.cc.pFrame=p->pFrame; u.cc.pFrame && u.cc.pFrame->token!=u.cc.t; u.cc.pFrame=u.cc.pFrame->pParent);
- if( u.cc.pFrame ) break;
+ u.cd.t = u.cd.pProgram->token;
+ for(u.cd.pFrame=p->pFrame; u.cd.pFrame && u.cd.pFrame->token!=u.cd.t; u.cd.pFrame=u.cd.pFrame->pParent);
+ if( u.cd.pFrame ) break;
}
if( p->nFrame>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
@@ -68703,69 +69363,69 @@ case OP_Program: { /* jump */
break;
}
- /* Register u.cc.pRt is used to store the memory required to save the state
+ /* Register u.cd.pRt is used to store the memory required to save the state
** of the current program, and the memory required at runtime to execute
- ** the trigger program. If this trigger has been fired before, then u.cc.pRt
+ ** the trigger program. If this trigger has been fired before, then u.cd.pRt
** is already allocated. Otherwise, it must be initialized. */
- if( (u.cc.pRt->flags&MEM_Frame)==0 ){
+ if( (u.cd.pRt->flags&MEM_Frame)==0 ){
/* SubProgram.nMem is set to the number of memory cells used by the
** program stored in SubProgram.aOp. As well as these, one memory
** cell is required for each cursor used by the program. Set local
- ** variable u.cc.nMem (and later, VdbeFrame.nChildMem) to this value.
+ ** variable u.cd.nMem (and later, VdbeFrame.nChildMem) to this value.
*/
- u.cc.nMem = u.cc.pProgram->nMem + u.cc.pProgram->nCsr;
- u.cc.nByte = ROUND8(sizeof(VdbeFrame))
- + u.cc.nMem * sizeof(Mem)
- + u.cc.pProgram->nCsr * sizeof(VdbeCursor *)
- + u.cc.pProgram->nOnce * sizeof(u8);
- u.cc.pFrame = sqlite3DbMallocZero(db, u.cc.nByte);
- if( !u.cc.pFrame ){
+ u.cd.nMem = u.cd.pProgram->nMem + u.cd.pProgram->nCsr;
+ u.cd.nByte = ROUND8(sizeof(VdbeFrame))
+ + u.cd.nMem * sizeof(Mem)
+ + u.cd.pProgram->nCsr * sizeof(VdbeCursor *)
+ + u.cd.pProgram->nOnce * sizeof(u8);
+ u.cd.pFrame = sqlite3DbMallocZero(db, u.cd.nByte);
+ if( !u.cd.pFrame ){
goto no_mem;
}
- sqlite3VdbeMemRelease(u.cc.pRt);
- u.cc.pRt->flags = MEM_Frame;
- u.cc.pRt->u.pFrame = u.cc.pFrame;
+ sqlite3VdbeMemRelease(u.cd.pRt);
+ u.cd.pRt->flags = MEM_Frame;
+ u.cd.pRt->u.pFrame = u.cd.pFrame;
- u.cc.pFrame->v = p;
- u.cc.pFrame->nChildMem = u.cc.nMem;
- u.cc.pFrame->nChildCsr = u.cc.pProgram->nCsr;
- u.cc.pFrame->pc = pc;
- u.cc.pFrame->aMem = p->aMem;
- u.cc.pFrame->nMem = p->nMem;
- u.cc.pFrame->apCsr = p->apCsr;
- u.cc.pFrame->nCursor = p->nCursor;
- u.cc.pFrame->aOp = p->aOp;
- u.cc.pFrame->nOp = p->nOp;
- u.cc.pFrame->token = u.cc.pProgram->token;
- u.cc.pFrame->aOnceFlag = p->aOnceFlag;
- u.cc.pFrame->nOnceFlag = p->nOnceFlag;
+ u.cd.pFrame->v = p;
+ u.cd.pFrame->nChildMem = u.cd.nMem;
+ u.cd.pFrame->nChildCsr = u.cd.pProgram->nCsr;
+ u.cd.pFrame->pc = pc;
+ u.cd.pFrame->aMem = p->aMem;
+ u.cd.pFrame->nMem = p->nMem;
+ u.cd.pFrame->apCsr = p->apCsr;
+ u.cd.pFrame->nCursor = p->nCursor;
+ u.cd.pFrame->aOp = p->aOp;
+ u.cd.pFrame->nOp = p->nOp;
+ u.cd.pFrame->token = u.cd.pProgram->token;
+ u.cd.pFrame->aOnceFlag = p->aOnceFlag;
+ u.cd.pFrame->nOnceFlag = p->nOnceFlag;
- u.cc.pEnd = &VdbeFrameMem(u.cc.pFrame)[u.cc.pFrame->nChildMem];
- for(u.cc.pMem=VdbeFrameMem(u.cc.pFrame); u.cc.pMem!=u.cc.pEnd; u.cc.pMem++){
- u.cc.pMem->flags = MEM_Invalid;
- u.cc.pMem->db = db;
+ u.cd.pEnd = &VdbeFrameMem(u.cd.pFrame)[u.cd.pFrame->nChildMem];
+ for(u.cd.pMem=VdbeFrameMem(u.cd.pFrame); u.cd.pMem!=u.cd.pEnd; u.cd.pMem++){
+ u.cd.pMem->flags = MEM_Invalid;
+ u.cd.pMem->db = db;
}
}else{
- u.cc.pFrame = u.cc.pRt->u.pFrame;
- assert( u.cc.pProgram->nMem+u.cc.pProgram->nCsr==u.cc.pFrame->nChildMem );
- assert( u.cc.pProgram->nCsr==u.cc.pFrame->nChildCsr );
- assert( pc==u.cc.pFrame->pc );
+ u.cd.pFrame = u.cd.pRt->u.pFrame;
+ assert( u.cd.pProgram->nMem+u.cd.pProgram->nCsr==u.cd.pFrame->nChildMem );
+ assert( u.cd.pProgram->nCsr==u.cd.pFrame->nChildCsr );
+ assert( pc==u.cd.pFrame->pc );
}
p->nFrame++;
- u.cc.pFrame->pParent = p->pFrame;
- u.cc.pFrame->lastRowid = lastRowid;
- u.cc.pFrame->nChange = p->nChange;
+ u.cd.pFrame->pParent = p->pFrame;
+ u.cd.pFrame->lastRowid = lastRowid;
+ u.cd.pFrame->nChange = p->nChange;
p->nChange = 0;
- p->pFrame = u.cc.pFrame;
- p->aMem = aMem = &VdbeFrameMem(u.cc.pFrame)[-1];
- p->nMem = u.cc.pFrame->nChildMem;
- p->nCursor = (u16)u.cc.pFrame->nChildCsr;
+ p->pFrame = u.cd.pFrame;
+ p->aMem = aMem = &VdbeFrameMem(u.cd.pFrame)[-1];
+ p->nMem = u.cd.pFrame->nChildMem;
+ p->nCursor = (u16)u.cd.pFrame->nChildCsr;
p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
- p->aOp = aOp = u.cc.pProgram->aOp;
- p->nOp = u.cc.pProgram->nOp;
+ p->aOp = aOp = u.cd.pProgram->aOp;
+ p->nOp = u.cd.pProgram->nOp;
p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
- p->nOnceFlag = u.cc.pProgram->nOnce;
+ p->nOnceFlag = u.cd.pProgram->nOnce;
pc = -1;
memset(p->aOnceFlag, 0, p->nOnceFlag);
@@ -68785,13 +69445,13 @@ case OP_Program: { /* jump */
** calling OP_Program instruction.
*/
case OP_Param: { /* out2-prerelease */
-#if 0 /* local variables moved into u.cd */
+#if 0 /* local variables moved into u.ce */
VdbeFrame *pFrame;
Mem *pIn;
-#endif /* local variables moved into u.cd */
- u.cd.pFrame = p->pFrame;
- u.cd.pIn = &u.cd.pFrame->aMem[pOp->p1 + u.cd.pFrame->aOp[u.cd.pFrame->pc].p1];
- sqlite3VdbeMemShallowCopy(pOut, u.cd.pIn, MEM_Ephem);
+#endif /* local variables moved into u.ce */
+ u.ce.pFrame = p->pFrame;
+ u.ce.pIn = &u.ce.pFrame->aMem[pOp->p1 + u.ce.pFrame->aOp[u.ce.pFrame->pc].p1];
+ sqlite3VdbeMemShallowCopy(pOut, u.ce.pIn, MEM_Ephem);
break;
}
@@ -68847,22 +69507,22 @@ case OP_FkIfZero: { /* jump */
** an integer.
*/
case OP_MemMax: { /* in2 */
-#if 0 /* local variables moved into u.ce */
+#if 0 /* local variables moved into u.cf */
Mem *pIn1;
VdbeFrame *pFrame;
-#endif /* local variables moved into u.ce */
+#endif /* local variables moved into u.cf */
if( p->pFrame ){
- for(u.ce.pFrame=p->pFrame; u.ce.pFrame->pParent; u.ce.pFrame=u.ce.pFrame->pParent);
- u.ce.pIn1 = &u.ce.pFrame->aMem[pOp->p1];
+ for(u.cf.pFrame=p->pFrame; u.cf.pFrame->pParent; u.cf.pFrame=u.cf.pFrame->pParent);
+ u.cf.pIn1 = &u.cf.pFrame->aMem[pOp->p1];
}else{
- u.ce.pIn1 = &aMem[pOp->p1];
+ u.cf.pIn1 = &aMem[pOp->p1];
}
- assert( memIsValid(u.ce.pIn1) );
- sqlite3VdbeMemIntegerify(u.ce.pIn1);
+ assert( memIsValid(u.cf.pIn1) );
+ sqlite3VdbeMemIntegerify(u.cf.pIn1);
pIn2 = &aMem[pOp->p2];
sqlite3VdbeMemIntegerify(pIn2);
- if( u.ce.pIn1->u.iu.i){
- u.ce.pIn1->u.i = pIn2->u.i;
+ if( u.cf.pIn1->u.iu.i){
+ u.cf.pIn1->u.i = pIn2->u.i;
}
break;
}
@@ -68929,56 +69589,56 @@ case OP_IfZero: { /* jump, in1 */
** successors.
*/
case OP_AggStep: {
-#if 0 /* local variables moved into u.cf */
+#if 0 /* local variables moved into u.cg */
int n;
int i;
Mem *pMem;
Mem *pRec;
sqlite3_context ctx;
sqlite3_value **apVal;
-#endif /* local variables moved into u.cf */
+#endif /* local variables moved into u.cg */
- u.cf.n = pOp->p5;
- assert( u.cf.n>=0 );
- u.cf.pRec = &aMem[pOp->p2];
- u.cf.apVal = p->apArg;
- assert( u.cf.apVal || u.cf.n==0 );
- for(u.cf.i=0; u.cf.ip5;
+ assert( u.cg.n>=0 );
+ u.cg.pRec = &aMem[pOp->p2];
+ u.cg.apVal = p->apArg;
+ assert( u.cg.apVal || u.cg.n==0 );
+ for(u.cg.i=0; u.cg.ip4.pFunc;
+ u.cg.ctx.pFunc = pOp->p4.pFunc;
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.cf.ctx.pMem = u.cf.pMem = &aMem[pOp->p3];
- u.cf.pMem->n++;
- u.cf.ctx.s.flags = MEM_Null;
- u.cf.ctx.s.z = 0;
- u.cf.ctx.s.zMalloc = 0;
- u.cf.ctx.s.xDel = 0;
- u.cf.ctx.s.db = db;
- u.cf.ctx.isError = 0;
- u.cf.ctx.pColl = 0;
- u.cf.ctx.skipFlag = 0;
- if( u.cf.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
+ u.cg.ctx.pMem = u.cg.pMem = &aMem[pOp->p3];
+ u.cg.pMem->n++;
+ u.cg.ctx.s.flags = MEM_Null;
+ u.cg.ctx.s.z = 0;
+ u.cg.ctx.s.zMalloc = 0;
+ u.cg.ctx.s.xDel = 0;
+ u.cg.ctx.s.db = db;
+ u.cg.ctx.isError = 0;
+ u.cg.ctx.pColl = 0;
+ u.cg.ctx.skipFlag = 0;
+ if( u.cg.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
assert( pOp>p->aOp );
assert( pOp[-1].p4type==P4_COLLSEQ );
assert( pOp[-1].opcode==OP_CollSeq );
- u.cf.ctx.pColl = pOp[-1].p4.pColl;
+ u.cg.ctx.pColl = pOp[-1].p4.pColl;
}
- (u.cf.ctx.pFunc->xStep)(&u.cf.ctx, u.cf.n, u.cf.apVal); /* IMP: R-24505-23230 */
- if( u.cf.ctx.isError ){
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cf.ctx.s));
- rc = u.cf.ctx.isError;
+ (u.cg.ctx.pFunc->xStep)(&u.cg.ctx, u.cg.n, u.cg.apVal); /* IMP: R-24505-23230 */
+ if( u.cg.ctx.isError ){
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cg.ctx.s));
+ rc = u.cg.ctx.isError;
}
- if( u.cf.ctx.skipFlag ){
+ if( u.cg.ctx.skipFlag ){
assert( pOp[-1].opcode==OP_CollSeq );
- u.cf.i = pOp[-1].p1;
- if( u.cf.i ) sqlite3VdbeMemSetInt64(&aMem[u.cf.i], 1);
+ u.cg.i = pOp[-1].p1;
+ if( u.cg.i ) sqlite3VdbeMemSetInt64(&aMem[u.cg.i], 1);
}
- sqlite3VdbeMemRelease(&u.cf.ctx.s);
+ sqlite3VdbeMemRelease(&u.cg.ctx.s);
break;
}
@@ -68996,19 +69656,19 @@ case OP_AggStep: {
** the step function was not previously called.
*/
case OP_AggFinal: {
-#if 0 /* local variables moved into u.cg */
+#if 0 /* local variables moved into u.ch */
Mem *pMem;
-#endif /* local variables moved into u.cg */
+#endif /* local variables moved into u.ch */
assert( pOp->p1>0 && pOp->p1<=p->nMem );
- u.cg.pMem = &aMem[pOp->p1];
- assert( (u.cg.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
- rc = sqlite3VdbeMemFinalize(u.cg.pMem, pOp->p4.pFunc);
+ u.ch.pMem = &aMem[pOp->p1];
+ assert( (u.ch.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
+ rc = sqlite3VdbeMemFinalize(u.ch.pMem, pOp->p4.pFunc);
if( rc ){
- sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.cg.pMem));
+ sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(u.ch.pMem));
}
- sqlite3VdbeChangeEncoding(u.cg.pMem, encoding);
- UPDATE_MAX_BLOBSIZE(u.cg.pMem);
- if( sqlite3VdbeMemTooBig(u.cg.pMem) ){
+ sqlite3VdbeChangeEncoding(u.ch.pMem, encoding);
+ UPDATE_MAX_BLOBSIZE(u.ch.pMem);
+ if( sqlite3VdbeMemTooBig(u.ch.pMem) ){
goto too_big;
}
break;
@@ -69027,25 +69687,25 @@ case OP_AggFinal: {
** mem[P3+2] are initialized to -1.
*/
case OP_Checkpoint: {
-#if 0 /* local variables moved into u.ch */
+#if 0 /* local variables moved into u.ci */
int i; /* Loop counter */
int aRes[3]; /* Results */
Mem *pMem; /* Write results here */
-#endif /* local variables moved into u.ch */
+#endif /* local variables moved into u.ci */
- u.ch.aRes[0] = 0;
- u.ch.aRes[1] = u.ch.aRes[2] = -1;
+ u.ci.aRes[0] = 0;
+ u.ci.aRes[1] = u.ci.aRes[2] = -1;
assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
|| pOp->p2==SQLITE_CHECKPOINT_FULL
|| pOp->p2==SQLITE_CHECKPOINT_RESTART
);
- rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ch.aRes[1], &u.ch.aRes[2]);
+ rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &u.ci.aRes[1], &u.ci.aRes[2]);
if( rc==SQLITE_BUSY ){
rc = SQLITE_OK;
- u.ch.aRes[0] = 1;
+ u.ci.aRes[0] = 1;
}
- for(u.ch.i=0, u.ch.pMem = &aMem[pOp->p3]; u.ch.i<3; u.ch.i++, u.ch.pMem++){
- sqlite3VdbeMemSetInt64(u.ch.pMem, (i64)u.ch.aRes[u.ch.i]);
+ for(u.ci.i=0, u.ci.pMem = &aMem[pOp->p3]; u.ci.i<3; u.ci.i++, u.ci.pMem++){
+ sqlite3VdbeMemSetInt64(u.ci.pMem, (i64)u.ci.aRes[u.ci.i]);
}
break;
};
@@ -69064,91 +69724,93 @@ case OP_Checkpoint: {
** Write a string containing the final journal-mode to register P2.
*/
case OP_JournalMode: { /* out2-prerelease */
-#if 0 /* local variables moved into u.ci */
+#if 0 /* local variables moved into u.cj */
Btree *pBt; /* Btree to change journal mode of */
Pager *pPager; /* Pager associated with pBt */
int eNew; /* New journal mode */
int eOld; /* The old journal mode */
+#ifndef SQLITE_OMIT_WAL
const char *zFilename; /* Name of database file for pPager */
-#endif /* local variables moved into u.ci */
+#endif
+#endif /* local variables moved into u.cj */
- u.ci.eNew = pOp->p3;
- assert( u.ci.eNew==PAGER_JOURNALMODE_DELETE
- || u.ci.eNew==PAGER_JOURNALMODE_TRUNCATE
- || u.ci.eNew==PAGER_JOURNALMODE_PERSIST
- || u.ci.eNew==PAGER_JOURNALMODE_OFF
- || u.ci.eNew==PAGER_JOURNALMODE_MEMORY
- || u.ci.eNew==PAGER_JOURNALMODE_WAL
- || u.ci.eNew==PAGER_JOURNALMODE_QUERY
+ u.cj.eNew = pOp->p3;
+ assert( u.cj.eNew==PAGER_JOURNALMODE_DELETE
+ || u.cj.eNew==PAGER_JOURNALMODE_TRUNCATE
+ || u.cj.eNew==PAGER_JOURNALMODE_PERSIST
+ || u.cj.eNew==PAGER_JOURNALMODE_OFF
+ || u.cj.eNew==PAGER_JOURNALMODE_MEMORY
+ || u.cj.eNew==PAGER_JOURNALMODE_WAL
+ || u.cj.eNew==PAGER_JOURNALMODE_QUERY
);
assert( pOp->p1>=0 && pOp->p1nDb );
- u.ci.pBt = db->aDb[pOp->p1].pBt;
- u.ci.pPager = sqlite3BtreePager(u.ci.pBt);
- u.ci.eOld = sqlite3PagerGetJournalMode(u.ci.pPager);
- if( u.ci.eNew==PAGER_JOURNALMODE_QUERY ) u.ci.eNew = u.ci.eOld;
- if( !sqlite3PagerOkToChangeJournalMode(u.ci.pPager) ) u.ci.eNew = u.ci.eOld;
+ u.cj.pBt = db->aDb[pOp->p1].pBt;
+ u.cj.pPager = sqlite3BtreePager(u.cj.pBt);
+ u.cj.eOld = sqlite3PagerGetJournalMode(u.cj.pPager);
+ if( u.cj.eNew==PAGER_JOURNALMODE_QUERY ) u.cj.eNew = u.cj.eOld;
+ if( !sqlite3PagerOkToChangeJournalMode(u.cj.pPager) ) u.cj.eNew = u.cj.eOld;
#ifndef SQLITE_OMIT_WAL
- u.ci.zFilename = sqlite3PagerFilename(u.ci.pPager, 1);
+ u.cj.zFilename = sqlite3PagerFilename(u.cj.pPager, 1);
/* Do not allow a transition to journal_mode=WAL for a database
** in temporary storage or if the VFS does not support shared memory
*/
- if( u.ci.eNew==PAGER_JOURNALMODE_WAL
- && (sqlite3Strlen30(u.ci.zFilename)==0 /* Temp file */
- || !sqlite3PagerWalSupported(u.ci.pPager)) /* No shared-memory support */
+ if( u.cj.eNew==PAGER_JOURNALMODE_WAL
+ && (sqlite3Strlen30(u.cj.zFilename)==0 /* Temp file */
+ || !sqlite3PagerWalSupported(u.cj.pPager)) /* No shared-memory support */
){
- u.ci.eNew = u.ci.eOld;
+ u.cj.eNew = u.cj.eOld;
}
- if( (u.ci.eNew!=u.ci.eOld)
- && (u.ci.eOld==PAGER_JOURNALMODE_WAL || u.ci.eNew==PAGER_JOURNALMODE_WAL)
+ if( (u.cj.eNew!=u.cj.eOld)
+ && (u.cj.eOld==PAGER_JOURNALMODE_WAL || u.cj.eNew==PAGER_JOURNALMODE_WAL)
){
if( !db->autoCommit || db->activeVdbeCnt>1 ){
rc = SQLITE_ERROR;
sqlite3SetString(&p->zErrMsg, db,
"cannot change %s wal mode from within a transaction",
- (u.ci.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
+ (u.cj.eNew==PAGER_JOURNALMODE_WAL ? "into" : "out of")
);
break;
}else{
- if( u.ci.eOld==PAGER_JOURNALMODE_WAL ){
+ if( u.cj.eOld==PAGER_JOURNALMODE_WAL ){
/* If leaving WAL mode, close the log file. If successful, the call
** to PagerCloseWal() checkpoints and deletes the write-ahead-log
** file. An EXCLUSIVE lock may still be held on the database file
** after a successful return.
*/
- rc = sqlite3PagerCloseWal(u.ci.pPager);
+ rc = sqlite3PagerCloseWal(u.cj.pPager);
if( rc==SQLITE_OK ){
- sqlite3PagerSetJournalMode(u.ci.pPager, u.ci.eNew);
+ sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
}
- }else if( u.ci.eOld==PAGER_JOURNALMODE_MEMORY ){
+ }else if( u.cj.eOld==PAGER_JOURNALMODE_MEMORY ){
/* Cannot transition directly from MEMORY to WAL. Use mode OFF
** as an intermediate */
- sqlite3PagerSetJournalMode(u.ci.pPager, PAGER_JOURNALMODE_OFF);
+ sqlite3PagerSetJournalMode(u.cj.pPager, PAGER_JOURNALMODE_OFF);
}
/* Open a transaction on the database file. Regardless of the journal
** mode, this transaction always uses a rollback journal.
*/
- assert( sqlite3BtreeIsInTrans(u.ci.pBt)==0 );
+ assert( sqlite3BtreeIsInTrans(u.cj.pBt)==0 );
if( rc==SQLITE_OK ){
- rc = sqlite3BtreeSetVersion(u.ci.pBt, (u.ci.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
+ rc = sqlite3BtreeSetVersion(u.cj.pBt, (u.cj.eNew==PAGER_JOURNALMODE_WAL ? 2 : 1));
}
}
}
#endif /* ifndef SQLITE_OMIT_WAL */
if( rc ){
- u.ci.eNew = u.ci.eOld;
+ u.cj.eNew = u.cj.eOld;
}
- u.ci.eNew = sqlite3PagerSetJournalMode(u.ci.pPager, u.ci.eNew);
+ u.cj.eNew = sqlite3PagerSetJournalMode(u.cj.pPager, u.cj.eNew);
pOut = &aMem[pOp->p2];
pOut->flags = MEM_Str|MEM_Static|MEM_Term;
- pOut->z = (char *)sqlite3JournalModename(u.ci.eNew);
+ pOut->z = (char *)sqlite3JournalModename(u.cj.eNew);
pOut->n = sqlite3Strlen30(pOut->z);
pOut->enc = SQLITE_UTF8;
sqlite3VdbeChangeEncoding(pOut, encoding);
@@ -69177,14 +69839,14 @@ case OP_Vacuum: {
** P2. Otherwise, fall through to the next instruction.
*/
case OP_IncrVacuum: { /* jump */
-#if 0 /* local variables moved into u.cj */
+#if 0 /* local variables moved into u.ck */
Btree *pBt;
-#endif /* local variables moved into u.cj */
+#endif /* local variables moved into u.ck */
assert( pOp->p1>=0 && pOp->p1nDb );
assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 );
- u.cj.pBt = db->aDb[pOp->p1].pBt;
- rc = sqlite3BtreeIncrVacuum(u.cj.pBt);
+ u.ck.pBt = db->aDb[pOp->p1].pBt;
+ rc = sqlite3BtreeIncrVacuum(u.ck.pBt);
if( rc==SQLITE_DONE ){
pc = pOp->p2 - 1;
rc = SQLITE_OK;
@@ -69254,12 +69916,12 @@ case OP_TableLock: {
** code will be set to SQLITE_LOCKED.
*/
case OP_VBegin: {
-#if 0 /* local variables moved into u.ck */
+#if 0 /* local variables moved into u.cl */
VTable *pVTab;
-#endif /* local variables moved into u.ck */
- u.ck.pVTab = pOp->p4.pVtab;
- rc = sqlite3VtabBegin(db, u.ck.pVTab);
- if( u.ck.pVTab ) importVtabErrMsg(p, u.ck.pVTab->pVtab);
+#endif /* local variables moved into u.cl */
+ u.cl.pVTab = pOp->p4.pVtab;
+ rc = sqlite3VtabBegin(db, u.cl.pVTab);
+ if( u.cl.pVTab ) importVtabErrMsg(p, u.cl.pVTab->pVtab);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -69298,32 +69960,32 @@ case OP_VDestroy: {
** table and stores that cursor in P1.
*/
case OP_VOpen: {
-#if 0 /* local variables moved into u.cl */
+#if 0 /* local variables moved into u.cm */
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
-#endif /* local variables moved into u.cl */
+#endif /* local variables moved into u.cm */
- u.cl.pCur = 0;
- u.cl.pVtabCursor = 0;
- u.cl.pVtab = pOp->p4.pVtab->pVtab;
- u.cl.pModule = (sqlite3_module *)u.cl.pVtab->pModule;
- assert(u.cl.pVtab && u.cl.pModule);
- rc = u.cl.pModule->xOpen(u.cl.pVtab, &u.cl.pVtabCursor);
- importVtabErrMsg(p, u.cl.pVtab);
+ u.cm.pCur = 0;
+ u.cm.pVtabCursor = 0;
+ u.cm.pVtab = pOp->p4.pVtab->pVtab;
+ u.cm.pModule = (sqlite3_module *)u.cm.pVtab->pModule;
+ assert(u.cm.pVtab && u.cm.pModule);
+ rc = u.cm.pModule->xOpen(u.cm.pVtab, &u.cm.pVtabCursor);
+ importVtabErrMsg(p, u.cm.pVtab);
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
- u.cl.pVtabCursor->pVtab = u.cl.pVtab;
+ u.cm.pVtabCursor->pVtab = u.cm.pVtab;
- /* Initialise vdbe cursor object */
- u.cl.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
- if( u.cl.pCur ){
- u.cl.pCur->pVtabCursor = u.cl.pVtabCursor;
- u.cl.pCur->pModule = u.cl.pVtabCursor->pVtab->pModule;
+ /* Initialize vdbe cursor object */
+ u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
+ if( u.cm.pCur ){
+ u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
+ u.cm.pCur->pModule = u.cm.pVtabCursor->pVtab->pModule;
}else{
db->mallocFailed = 1;
- u.cl.pModule->xClose(u.cl.pVtabCursor);
+ u.cm.pModule->xClose(u.cm.pVtabCursor);
}
}
break;
@@ -69350,7 +70012,7 @@ case OP_VOpen: {
** 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.cm */
+#if 0 /* local variables moved into u.cn */
int nArg;
int iQuery;
const sqlite3_module *pModule;
@@ -69362,45 +70024,45 @@ case OP_VFilter: { /* jump */
int res;
int i;
Mem **apArg;
-#endif /* local variables moved into u.cm */
+#endif /* local variables moved into u.cn */
- u.cm.pQuery = &aMem[pOp->p3];
- u.cm.pArgc = &u.cm.pQuery[1];
- u.cm.pCur = p->apCsr[pOp->p1];
- assert( memIsValid(u.cm.pQuery) );
- REGISTER_TRACE(pOp->p3, u.cm.pQuery);
- assert( u.cm.pCur->pVtabCursor );
- u.cm.pVtabCursor = u.cm.pCur->pVtabCursor;
- u.cm.pVtab = u.cm.pVtabCursor->pVtab;
- u.cm.pModule = u.cm.pVtab->pModule;
+ u.cn.pQuery = &aMem[pOp->p3];
+ u.cn.pArgc = &u.cn.pQuery[1];
+ u.cn.pCur = p->apCsr[pOp->p1];
+ assert( memIsValid(u.cn.pQuery) );
+ REGISTER_TRACE(pOp->p3, u.cn.pQuery);
+ assert( u.cn.pCur->pVtabCursor );
+ u.cn.pVtabCursor = u.cn.pCur->pVtabCursor;
+ u.cn.pVtab = u.cn.pVtabCursor->pVtab;
+ u.cn.pModule = u.cn.pVtab->pModule;
/* Grab the index number and argc parameters */
- assert( (u.cm.pQuery->flags&MEM_Int)!=0 && u.cm.pArgc->flags==MEM_Int );
- u.cm.nArg = (int)u.cm.pArgc->u.i;
- u.cm.iQuery = (int)u.cm.pQuery->u.i;
+ assert( (u.cn.pQuery->flags&MEM_Int)!=0 && u.cn.pArgc->flags==MEM_Int );
+ u.cn.nArg = (int)u.cn.pArgc->u.i;
+ u.cn.iQuery = (int)u.cn.pQuery->u.i;
/* Invoke the xFilter method */
{
- u.cm.res = 0;
- u.cm.apArg = p->apArg;
- for(u.cm.i = 0; u.cm.iapArg;
+ for(u.cn.i = 0; u.cn.iinVtabMethod = 1;
- rc = u.cm.pModule->xFilter(u.cm.pVtabCursor, u.cm.iQuery, pOp->p4.z, u.cm.nArg, u.cm.apArg);
+ rc = u.cn.pModule->xFilter(u.cn.pVtabCursor, u.cn.iQuery, pOp->p4.z, u.cn.nArg, u.cn.apArg);
p->inVtabMethod = 0;
- importVtabErrMsg(p, u.cm.pVtab);
+ importVtabErrMsg(p, u.cn.pVtab);
if( rc==SQLITE_OK ){
- u.cm.res = u.cm.pModule->xEof(u.cm.pVtabCursor);
+ u.cn.res = u.cn.pModule->xEof(u.cn.pVtabCursor);
}
- if( u.cm.res ){
+ if( u.cn.res ){
pc = pOp->p2 - 1;
}
}
- u.cm.pCur->nullRow = 0;
+ u.cn.pCur->nullRow = 0;
break;
}
@@ -69414,51 +70076,51 @@ case OP_VFilter: { /* jump */
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
-#if 0 /* local variables moved into u.cn */
+#if 0 /* local variables moved into u.co */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
Mem *pDest;
sqlite3_context sContext;
-#endif /* local variables moved into u.cn */
+#endif /* local variables moved into u.co */
VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem );
- u.cn.pDest = &aMem[pOp->p3];
- memAboutToChange(p, u.cn.pDest);
+ u.co.pDest = &aMem[pOp->p3];
+ memAboutToChange(p, u.co.pDest);
if( pCur->nullRow ){
- sqlite3VdbeMemSetNull(u.cn.pDest);
+ sqlite3VdbeMemSetNull(u.co.pDest);
break;
}
- u.cn.pVtab = pCur->pVtabCursor->pVtab;
- u.cn.pModule = u.cn.pVtab->pModule;
- assert( u.cn.pModule->xColumn );
- memset(&u.cn.sContext, 0, sizeof(u.cn.sContext));
+ u.co.pVtab = pCur->pVtabCursor->pVtab;
+ u.co.pModule = u.co.pVtab->pModule;
+ assert( u.co.pModule->xColumn );
+ memset(&u.co.sContext, 0, sizeof(u.co.sContext));
/* The output cell may already have a buffer allocated. Move
- ** the current contents to u.cn.sContext.s so in case the user-function
+ ** the current contents to u.co.sContext.s so in case the user-function
** can use the already allocated buffer instead of allocating a
** new one.
*/
- sqlite3VdbeMemMove(&u.cn.sContext.s, u.cn.pDest);
- MemSetTypeFlag(&u.cn.sContext.s, MEM_Null);
+ sqlite3VdbeMemMove(&u.co.sContext.s, u.co.pDest);
+ MemSetTypeFlag(&u.co.sContext.s, MEM_Null);
- rc = u.cn.pModule->xColumn(pCur->pVtabCursor, &u.cn.sContext, pOp->p2);
- importVtabErrMsg(p, u.cn.pVtab);
- if( u.cn.sContext.isError ){
- rc = u.cn.sContext.isError;
+ rc = u.co.pModule->xColumn(pCur->pVtabCursor, &u.co.sContext, pOp->p2);
+ importVtabErrMsg(p, u.co.pVtab);
+ if( u.co.sContext.isError ){
+ rc = u.co.sContext.isError;
}
/* 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.cn.sContext.s (a Mem struct) is released.
+ ** dynamic allocation in u.co.sContext.s (a Mem struct) is released.
*/
- sqlite3VdbeChangeEncoding(&u.cn.sContext.s, encoding);
- sqlite3VdbeMemMove(u.cn.pDest, &u.cn.sContext.s);
- REGISTER_TRACE(pOp->p3, u.cn.pDest);
- UPDATE_MAX_BLOBSIZE(u.cn.pDest);
+ sqlite3VdbeChangeEncoding(&u.co.sContext.s, encoding);
+ sqlite3VdbeMemMove(u.co.pDest, &u.co.sContext.s);
+ REGISTER_TRACE(pOp->p3, u.co.pDest);
+ UPDATE_MAX_BLOBSIZE(u.co.pDest);
- if( sqlite3VdbeMemTooBig(u.cn.pDest) ){
+ if( sqlite3VdbeMemTooBig(u.co.pDest) ){
goto too_big;
}
break;
@@ -69473,22 +70135,22 @@ case OP_VColumn: {
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: { /* jump */
-#if 0 /* local variables moved into u.co */
+#if 0 /* local variables moved into u.cp */
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
int res;
VdbeCursor *pCur;
-#endif /* local variables moved into u.co */
+#endif /* local variables moved into u.cp */
- u.co.res = 0;
- u.co.pCur = p->apCsr[pOp->p1];
- assert( u.co.pCur->pVtabCursor );
- if( u.co.pCur->nullRow ){
+ u.cp.res = 0;
+ u.cp.pCur = p->apCsr[pOp->p1];
+ assert( u.cp.pCur->pVtabCursor );
+ if( u.cp.pCur->nullRow ){
break;
}
- u.co.pVtab = u.co.pCur->pVtabCursor->pVtab;
- u.co.pModule = u.co.pVtab->pModule;
- assert( u.co.pModule->xNext );
+ u.cp.pVtab = u.cp.pCur->pVtabCursor->pVtab;
+ u.cp.pModule = u.cp.pVtab->pModule;
+ assert( u.cp.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
@@ -69497,14 +70159,14 @@ case OP_VNext: { /* jump */
** some other method is next invoked on the save virtual table cursor.
*/
p->inVtabMethod = 1;
- rc = u.co.pModule->xNext(u.co.pCur->pVtabCursor);
+ rc = u.cp.pModule->xNext(u.cp.pCur->pVtabCursor);
p->inVtabMethod = 0;
- importVtabErrMsg(p, u.co.pVtab);
+ importVtabErrMsg(p, u.cp.pVtab);
if( rc==SQLITE_OK ){
- u.co.res = u.co.pModule->xEof(u.co.pCur->pVtabCursor);
+ u.cp.res = u.cp.pModule->xEof(u.cp.pCur->pVtabCursor);
}
- if( !u.co.res ){
+ if( !u.cp.res ){
/* If there is data, jump to P2 */
pc = pOp->p2 - 1;
}
@@ -69520,24 +70182,24 @@ case OP_VNext: { /* jump */
** in register P1 is passed as the zName argument to the xRename method.
*/
case OP_VRename: {
-#if 0 /* local variables moved into u.cp */
+#if 0 /* local variables moved into u.cq */
sqlite3_vtab *pVtab;
Mem *pName;
-#endif /* local variables moved into u.cp */
+#endif /* local variables moved into u.cq */
- u.cp.pVtab = pOp->p4.pVtab->pVtab;
- u.cp.pName = &aMem[pOp->p1];
- assert( u.cp.pVtab->pModule->xRename );
- assert( memIsValid(u.cp.pName) );
- REGISTER_TRACE(pOp->p1, u.cp.pName);
- assert( u.cp.pName->flags & MEM_Str );
- testcase( u.cp.pName->enc==SQLITE_UTF8 );
- testcase( u.cp.pName->enc==SQLITE_UTF16BE );
- testcase( u.cp.pName->enc==SQLITE_UTF16LE );
- rc = sqlite3VdbeChangeEncoding(u.cp.pName, SQLITE_UTF8);
+ u.cq.pVtab = pOp->p4.pVtab->pVtab;
+ u.cq.pName = &aMem[pOp->p1];
+ assert( u.cq.pVtab->pModule->xRename );
+ assert( memIsValid(u.cq.pName) );
+ REGISTER_TRACE(pOp->p1, u.cq.pName);
+ assert( u.cq.pName->flags & MEM_Str );
+ testcase( u.cq.pName->enc==SQLITE_UTF8 );
+ testcase( u.cq.pName->enc==SQLITE_UTF16BE );
+ testcase( u.cq.pName->enc==SQLITE_UTF16LE );
+ rc = sqlite3VdbeChangeEncoding(u.cq.pName, SQLITE_UTF8);
if( rc==SQLITE_OK ){
- rc = u.cp.pVtab->pModule->xRename(u.cp.pVtab, u.cp.pName->z);
- importVtabErrMsg(p, u.cp.pVtab);
+ rc = u.cq.pVtab->pModule->xRename(u.cq.pVtab, u.cq.pName->z);
+ importVtabErrMsg(p, u.cq.pVtab);
p->expired = 0;
}
break;
@@ -69569,7 +70231,7 @@ case OP_VRename: {
** is set to the value of the rowid for the row just inserted.
*/
case OP_VUpdate: {
-#if 0 /* local variables moved into u.cq */
+#if 0 /* local variables moved into u.cr */
sqlite3_vtab *pVtab;
sqlite3_module *pModule;
int nArg;
@@ -69577,35 +70239,35 @@ case OP_VUpdate: {
sqlite_int64 rowid;
Mem **apArg;
Mem *pX;
-#endif /* local variables moved into u.cq */
+#endif /* local variables moved into u.cr */
assert( pOp->p2==1 || pOp->p5==OE_Fail || pOp->p5==OE_Rollback
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
);
- u.cq.pVtab = pOp->p4.pVtab->pVtab;
- u.cq.pModule = (sqlite3_module *)u.cq.pVtab->pModule;
- u.cq.nArg = pOp->p2;
+ u.cr.pVtab = pOp->p4.pVtab->pVtab;
+ u.cr.pModule = (sqlite3_module *)u.cr.pVtab->pModule;
+ u.cr.nArg = pOp->p2;
assert( pOp->p4type==P4_VTAB );
- if( ALWAYS(u.cq.pModule->xUpdate) ){
+ if( ALWAYS(u.cr.pModule->xUpdate) ){
u8 vtabOnConflict = db->vtabOnConflict;
- u.cq.apArg = p->apArg;
- u.cq.pX = &aMem[pOp->p3];
- for(u.cq.i=0; u.cq.iapArg;
+ u.cr.pX = &aMem[pOp->p3];
+ for(u.cr.i=0; u.cr.ivtabOnConflict = pOp->p5;
- rc = u.cq.pModule->xUpdate(u.cq.pVtab, u.cq.nArg, u.cq.apArg, &u.cq.rowid);
+ rc = u.cr.pModule->xUpdate(u.cr.pVtab, u.cr.nArg, u.cr.apArg, &u.cr.rowid);
db->vtabOnConflict = vtabOnConflict;
- importVtabErrMsg(p, u.cq.pVtab);
+ importVtabErrMsg(p, u.cr.pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
- assert( u.cq.nArg>1 && u.cq.apArg[0] && (u.cq.apArg[0]->flags&MEM_Null) );
- db->lastRowid = lastRowid = u.cq.rowid;
+ assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
+ db->lastRowid = lastRowid = u.cr.rowid;
}
- if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
+ if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
if( pOp->p5==OE_Ignore ){
rc = SQLITE_OK;
}else{
@@ -69663,21 +70325,24 @@ case OP_MaxPgcnt: { /* out2-prerelease */
** the UTF-8 string contained in P4 is emitted on the trace callback.
*/
case OP_Trace: {
-#if 0 /* local variables moved into u.cr */
+#if 0 /* local variables moved into u.cs */
char *zTrace;
char *z;
-#endif /* local variables moved into u.cr */
+#endif /* local variables moved into u.cs */
- if( db->xTrace && (u.cr.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
- u.cr.z = sqlite3VdbeExpandSql(p, u.cr.zTrace);
- db->xTrace(db->pTraceArg, u.cr.z);
- sqlite3DbFree(db, u.cr.z);
+ if( db->xTrace
+ && !p->doingRerun
+ && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+ ){
+ u.cs.z = sqlite3VdbeExpandSql(p, u.cs.zTrace);
+ db->xTrace(db->pTraceArg, u.cs.z);
+ sqlite3DbFree(db, u.cs.z);
}
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0
- && (u.cr.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
+ && (u.cs.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
){
- sqlite3DebugPrintf("SQL-trace: %s\n", u.cr.zTrace);
+ sqlite3DebugPrintf("SQL-trace: %s\n", u.cs.zTrace);
}
#endif /* SQLITE_DEBUG */
break;
@@ -70295,7 +70960,6 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
*/
-#ifndef SQLITE_OMIT_MERGE_SORT
typedef struct VdbeSorterIter VdbeSorterIter;
typedef struct SorterRecord SorterRecord;
@@ -70472,8 +71136,11 @@ static int vdbeSorterIterRead(
int rc; /* sqlite3OsRead() return code */
/* Determine how many bytes of data to read. */
- nRead = (int)(p->iEof - p->iReadOff);
- if( nRead>p->nBuffer ) nRead = p->nBuffer;
+ if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){
+ nRead = p->nBuffer;
+ }else{
+ nRead = (int)(p->iEof - p->iReadOff);
+ }
assert( nRead>0 );
/* Read data from the file. Return early if an error occurs. */
@@ -71312,8 +71979,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
return SQLITE_OK;
}
-#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
-
/************** End of vdbesort.c ********************************************/
/************** Begin file journal.c *****************************************/
/*
@@ -71376,6 +72041,14 @@ static int createFile(JournalFile *p){
assert(p->iSize<=p->nBuf);
rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
}
+ if( rc!=SQLITE_OK ){
+ /* If an error occurred while writing to the file, close it before
+ ** returning. This way, SQLite uses the in-memory journal data to
+ ** roll back changes made to the internal page-cache before this
+ ** function was called. */
+ sqlite3OsClose(pReal);
+ p->pReal = 0;
+ }
}
}
return rc;
@@ -71545,6 +72218,16 @@ SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *p){
return createFile((JournalFile *)p);
}
+/*
+** The file-handle passed as the only argument is guaranteed to be an open
+** file. It may or may not be of class JournalFile. If the file is a
+** JournalFile, and the underlying file on disk has not yet been opened,
+** return 0. Otherwise, return 1.
+*/
+SQLITE_PRIVATE int sqlite3JournalExists(sqlite3_file *p){
+ return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0);
+}
+
/*
** Return the number of bytes required to store a JournalFile that uses vfs
** pVfs to create the underlying on-disk files.
@@ -72030,6 +72713,15 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** from the result in the result-set. We might fix this someday. Or
** then again, we might not...
**
+** If the reference is followed by a COLLATE operator, then make sure
+** the COLLATE operator is preserved. For example:
+**
+** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase;
+**
+** Should be transformed into:
+**
+** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
+**
** The nSubquery parameter specifies how many levels of subquery the
** alias is removed from the original expression. The usually value is
** zero but it might be more if the alias is contained within a subquery
@@ -72053,8 +72745,9 @@ static void resolveAlias(
assert( pOrig!=0 );
assert( pOrig->flags & EP_Resolved );
db = pParse->db;
+ pDup = sqlite3ExprDup(db, pOrig, 0);
+ if( pDup==0 ) return;
if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
- pDup = sqlite3ExprDup(db, pOrig, 0);
incrAggFunctionDepth(pDup, nSubquery);
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
if( pDup==0 ) return;
@@ -72062,32 +72755,26 @@ static void resolveAlias(
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
}
pDup->iTable = pEList->a[iCol].iAlias;
- }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){
- 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;
- 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;
+ if( pExpr->op==TK_COLLATE ){
+ pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
** allowing it to be repopulated by the memcpy() on the following line.
+ ** The pExpr->u.zToken might point into memory that will be freed by the
+ ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
+ ** make a copy of the token before doing the sqlite3DbFree().
*/
ExprSetProperty(pExpr, EP_Static);
sqlite3ExprDelete(db, pExpr);
memcpy(pExpr, pDup, sizeof(*pExpr));
+ if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
+ assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
+ pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
+ pExpr->flags2 |= EP2_MallocedToken;
+ }
sqlite3DbFree(db, pDup);
}
@@ -72108,6 +72795,35 @@ static int nameInUsingClause(IdList *pUsing, const char *zCol){
return 0;
}
+/*
+** Subqueries stores the original database, table and column names for their
+** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
+** Check to see if the zSpan given to this routine matches the zDb, zTab,
+** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
+** match anything.
+*/
+SQLITE_PRIVATE int sqlite3MatchSpanName(
+ const char *zSpan,
+ const char *zCol,
+ const char *zTab,
+ const char *zDb
+){
+ int n;
+ for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
+ if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
+ return 0;
+ }
+ zSpan += n+1;
+ for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
+ if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){
+ return 0;
+ }
+ zSpan += n+1;
+ if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
+ return 0;
+ }
+ return 1;
+}
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
@@ -72157,13 +72873,27 @@ static int lookupName(
assert( pNC ); /* the name context cannot be NULL. */
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
- assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
+ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
/* Initialize the node to no-match */
pExpr->iTable = -1;
pExpr->pTab = 0;
ExprSetIrreducible(pExpr);
+ /* Translate the schema name in zDb into a pointer to the corresponding
+ ** schema. If not found, pSchema will remain NULL and nothing will match
+ ** resulting in an appropriate error message toward the end of this routine
+ */
+ if( zDb ){
+ for(i=0; inDb; i++){
+ assert( db->aDb[i].zName );
+ if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
+ pSchema = db->aDb[i].pSchema;
+ break;
+ }
+ }
+ }
+
/* Start at the inner-most context and move outward until a match is found */
while( pNC && cnt==0 ){
ExprList *pEList;
@@ -72172,31 +72902,36 @@ static int lookupName(
if( pSrcList ){
for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){
Table *pTab;
- int iDb;
Column *pCol;
pTab = pItem->pTab;
assert( pTab!=0 && pTab->zName!=0 );
- iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( pTab->nCol>0 );
+ if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
+ int hit = 0;
+ pEList = pItem->pSelect->pEList;
+ for(j=0; jnExpr; j++){
+ if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
+ cnt++;
+ cntTab = 2;
+ pMatch = pItem;
+ pExpr->iColumn = j;
+ hit = 1;
+ }
+ }
+ if( hit || zTab==0 ) continue;
+ }
+ if( zDb && pTab->pSchema!=pSchema ){
+ continue;
+ }
if( zTab ){
- if( pItem->zAlias ){
- char *zTabName = pItem->zAlias;
- if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- }else{
- char *zTabName = pTab->zName;
- if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){
- continue;
- }
- if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
- continue;
- }
+ const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
+ assert( zTabName!=0 );
+ if( sqlite3StrICmp(zTabName, zTab)!=0 ){
+ continue;
}
}
if( 0==(cntTab++) ){
- pExpr->iTable = pItem->iCursor;
- pExpr->pTab = pTab;
- pSchema = pTab->pSchema;
pMatch = pItem;
}
for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){
@@ -72210,17 +72945,19 @@ static int lookupName(
if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
}
cnt++;
- pExpr->iTable = pItem->iCursor;
- pExpr->pTab = pTab;
pMatch = pItem;
- pSchema = pTab->pSchema;
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
break;
}
}
}
- }
+ if( pMatch ){
+ pExpr->iTable = pMatch->iCursor;
+ pExpr->pTab = pMatch->pTab;
+ pSchema = pExpr->pTab->pSchema;
+ }
+ } /* if( pSrcList ) */
#ifndef SQLITE_OMIT_TRIGGER
/* If we have not already resolved the name, then maybe
@@ -72555,7 +73292,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
pNC->nErr++;
is_agg = 0;
- }else if( no_such_func ){
+ }else if( no_such_func && pParse->db->init.busy==0 ){
sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
pNC->nErr++;
}else if( wrong_num_args ){
@@ -72774,7 +73511,7 @@ static int resolveCompoundOrderBy(
int iCol = -1;
Expr *pE, *pDup;
if( pItem->done ) continue;
- pE = pItem->pExpr;
+ pE = sqlite3ExprSkipCollate(pItem->pExpr);
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
@@ -72792,14 +73529,20 @@ static int resolveCompoundOrderBy(
}
}
if( iCol>0 ){
- CollSeq *pColl = pE->pColl;
- int flags = pE->flags & EP_ExpCollate;
+ /* Convert the ORDER BY term into an integer column number iCol,
+ ** taking care to preserve the COLLATE clause if it exists */
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
+ if( pNew==0 ) return 1;
+ pNew->flags |= EP_IntValue;
+ pNew->u.iValue = iCol;
+ if( pItem->pExpr==pE ){
+ pItem->pExpr = pNew;
+ }else{
+ assert( pItem->pExpr->op==TK_COLLATE );
+ assert( pItem->pExpr->pLeft==pE );
+ pItem->pExpr->pLeft = pNew;
+ }
sqlite3ExprDelete(db, pE);
- pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0);
- if( pE==0 ) return 1;
- pE->pColl = pColl;
- pE->flags |= EP_IntValue | flags;
- pE->u.iValue = iCol;
pItem->iOrderByCol = (u16)iCol;
pItem->done = 1;
}else{
@@ -72904,11 +73647,11 @@ static int resolveOrderGroupBy(
pItem->iOrderByCol = (u16)iCol;
continue;
}
- if( sqlite3ExprIsInteger(pE, &iCol) ){
+ if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
/* The ORDER BY term is an integer constant. Again, set the column
** number so that sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
- if( iCol<1 ){
+ if( iCol<1 || iCol>0xffff ){
resolveOutOfRangeError(pParse, zType, i+1, nResult);
return 1;
}
@@ -72985,23 +73728,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
return WRC_Abort;
}
- /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
- ** resolve the result-set expression list.
- */
- sNC.ncFlags = NC_AllowAgg;
- sNC.pSrcList = p->pSrc;
- sNC.pNext = pOuterNC;
-
- /* Resolve names in the result set. */
- pEList = p->pEList;
- assert( pEList!=0 );
- for(i=0; inExpr; i++){
- Expr *pX = pEList->a[i].pExpr;
- if( sqlite3ResolveExprNames(&sNC, pX) ){
- return WRC_Abort;
- }
- }
-
/* Recursively resolve names in all subqueries
*/
for(i=0; ipSrc->nSrc; i++){
@@ -73029,6 +73755,23 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
+ /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
+ ** resolve the result-set expression list.
+ */
+ sNC.ncFlags = NC_AllowAgg;
+ sNC.pSrcList = p->pSrc;
+ sNC.pNext = pOuterNC;
+
+ /* Resolve names in the result set. */
+ pEList = p->pEList;
+ assert( pEList!=0 );
+ for(i=0; inExpr; i++){
+ Expr *pX = pEList->a[i].pExpr;
+ if( sqlite3ResolveExprNames(&sNC, pX) ){
+ return WRC_Abort;
+ }
+ }
+
/* If there are no aggregate functions in the result-set, and no GROUP BY
** expression, do not allow aggregates in any of the other expressions.
*/
@@ -73262,7 +74005,9 @@ SQLITE_PRIVATE void sqlite3ResolveSelectNames(
** SELECT * FROM t1 WHERE (select a from t1);
*/
SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
- int op = pExpr->op;
+ int op;
+ pExpr = sqlite3ExprSkipCollate(pExpr);
+ op = pExpr->op;
if( op==TK_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
@@ -73287,66 +74032,94 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
}
/*
-** Set the explicit collating sequence for an expression to the
-** collating sequence supplied in the second argument.
+** Set the collating sequence for expression pExpr to be the collating
+** sequence named by pToken. Return a pointer to a new Expr node that
+** implements the COLLATE operator.
+**
+** If a memory allocation error occurs, that fact is recorded in pParse->db
+** and the pExpr parameter is returned unchanged.
*/
-SQLITE_PRIVATE Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){
- if( pExpr && pColl ){
- pExpr->pColl = pColl;
- pExpr->flags |= EP_ExpCollate;
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){
+ if( pCollName->n>0 ){
+ Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
+ if( pNew ){
+ pNew->pLeft = pExpr;
+ pNew->flags |= EP_Collate;
+ pExpr = pNew;
+ }
+ }
+ return pExpr;
+}
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
+ Token s;
+ assert( zC!=0 );
+ s.z = zC;
+ s.n = sqlite3Strlen30(s.z);
+ return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
+}
+
+/*
+** Skip over any TK_COLLATE and/or TK_AS operators at the root of
+** an expression.
+*/
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
+ while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
+ pExpr = pExpr->pLeft;
}
return pExpr;
}
/*
-** Set the collating sequence for expression pExpr to be the collating
-** sequence named by pToken. Return a pointer to the revised expression.
-** The collating sequence is marked as "explicit" using the EP_ExpCollate
-** flag. An explicit collating sequence will override implicit
-** collating sequences.
-*/
-SQLITE_PRIVATE Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
- char *zColl = 0; /* Dequoted name of collation sequence */
- CollSeq *pColl;
- sqlite3 *db = pParse->db;
- zColl = sqlite3NameFromToken(db, pCollName);
- pColl = sqlite3LocateCollSeq(pParse, zColl);
- sqlite3ExprSetColl(pExpr, pColl);
- sqlite3DbFree(db, zColl);
- return pExpr;
-}
-
-/*
-** Return the default collation sequence for the expression pExpr. If
-** there is no default collation type, return 0.
+** Return the collation sequence for the expression pExpr. If
+** there is no defined collating sequence, return NULL.
+**
+** The collating sequence might be determined by a COLLATE operator
+** or by the presence of a column with a defined collating sequence.
+** COLLATE operators take first precedence. Left operands take
+** precedence over right operands.
*/
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
+ sqlite3 *db = pParse->db;
CollSeq *pColl = 0;
Expr *p = pExpr;
while( p ){
- int op;
- pColl = p->pColl;
- if( pColl ) break;
- op = p->op;
- if( p->pTab!=0 && (
- op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER
- )){
- /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
- ** a TK_COLUMN but was previously evaluated and cached in a register */
- const char *zColl;
- int j = p->iColumn;
- if( j>=0 ){
- sqlite3 *db = pParse->db;
- zColl = p->pTab->aCol[j].zColl;
- pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
- pExpr->pColl = pColl;
+ int op = p->op;
+ if( op==TK_CAST || op==TK_UPLUS ){
+ p = p->pLeft;
+ continue;
+ }
+ assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
+ if( op==TK_COLLATE ){
+ if( db->init.busy ){
+ /* Do not report errors when parsing while the schema */
+ pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
+ }else{
+ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
}
break;
}
- if( op!=TK_CAST && op!=TK_UPLUS ){
+ if( p->pTab!=0
+ && (op==TK_AGG_COLUMN || op==TK_COLUMN
+ || op==TK_REGISTER || op==TK_TRIGGER)
+ ){
+ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
+ int j = p->iColumn;
+ if( j>=0 ){
+ const char *zColl = p->pTab->aCol[j].zColl;
+ pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
+ }
+ break;
+ }
+ if( p->flags & EP_Collate ){
+ if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
+ p = p->pLeft;
+ }else{
+ p = p->pRight;
+ }
+ }else{
break;
}
- p = p->pLeft;
}
if( sqlite3CheckCollSeq(pParse, pColl) ){
pColl = 0;
@@ -73450,12 +74223,10 @@ SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
){
CollSeq *pColl;
assert( pLeft );
- if( pLeft->flags & EP_ExpCollate ){
- assert( pLeft->pColl );
- pColl = pLeft->pColl;
- }else if( pRight && pRight->flags & EP_ExpCollate ){
- assert( pRight->pColl );
- pColl = pRight->pColl;
+ if( pLeft->flags & EP_Collate ){
+ pColl = sqlite3ExprCollSeq(pParse, pLeft);
+ }else if( pRight && (pRight->flags & EP_Collate)!=0 ){
+ pColl = sqlite3ExprCollSeq(pParse, pRight);
}else{
pColl = sqlite3ExprCollSeq(pParse, pLeft);
if( !pColl ){
@@ -73685,17 +74456,11 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(
}else{
if( pRight ){
pRoot->pRight = pRight;
- if( pRight->flags & EP_ExpCollate ){
- pRoot->flags |= EP_ExpCollate;
- pRoot->pColl = pRight->pColl;
- }
+ pRoot->flags |= EP_Collate & pRight->flags;
}
if( pLeft ){
pRoot->pLeft = pLeft;
- if( pLeft->flags & EP_ExpCollate ){
- pRoot->flags |= EP_ExpCollate;
- pRoot->pColl = pLeft->pColl;
- }
+ pRoot->flags |= EP_Collate & pLeft->flags;
}
exprSetHeight(pRoot);
}
@@ -73847,7 +74612,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
*/
ynVar i;
for(i=0; inzVar; i++){
- if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){
+ if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
pExpr->iColumn = x = (ynVar)i+1;
break;
}
@@ -73953,7 +74718,7 @@ static int dupedExprStructSize(Expr *p, int flags){
assert( !ExprHasProperty(p, EP_FromJoin) );
assert( (p->flags2 & EP2_MallocedToken)==0 );
assert( (p->flags2 & EP2_Irreducible)==0 );
- if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
+ if( p->pLeft || p->pRight || p->x.pList ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
}else{
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
@@ -74161,6 +74926,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
struct SrcList_item *pNewItem = &pNew->a[i];
struct SrcList_item *pOldItem = &p->a[i];
Table *pTab;
+ pNewItem->pSchema = pOldItem->pSchema;
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase);
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias);
@@ -74169,6 +74935,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
pNewItem->addrFillSub = pOldItem->addrFillSub;
pNewItem->regReturn = pOldItem->regReturn;
pNewItem->isCorrelated = pOldItem->isCorrelated;
+ pNewItem->viaCoroutine = pOldItem->viaCoroutine;
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
pNewItem->notIndexed = pOldItem->notIndexed;
pNewItem->pIndex = pOldItem->pIndex;
@@ -74651,24 +75418,34 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
/*
** This function is used by the implementation of the IN (...) operator.
-** It's job is to find or create a b-tree structure that may be used
-** either to test for membership of the (...) set or to iterate through
-** its members, skipping duplicates.
+** The pX parameter is the expression on the RHS of the IN operator, which
+** might be either a list of expressions or a subquery.
+**
+** The job of this routine is to find or create a b-tree object that can
+** be used either to test for membership in the RHS set or to iterate through
+** all members of the RHS set, skipping duplicates.
+**
+** A cursor is opened on the b-tree object that the RHS of the IN operator
+** and pX->iTable is set to the index of that cursor.
**
-** The index of the cursor opened on the b-tree (database table, database index
-** or ephermal table) is stored in pX->iTable before this function returns.
** The returned value of this function indicates the b-tree type, as follows:
**
-** IN_INDEX_ROWID - The cursor was opened on a database table.
-** IN_INDEX_INDEX - The cursor was opened on a database index.
-** IN_INDEX_EPH - The cursor was opened on a specially created and
-** populated epheremal table.
+** IN_INDEX_ROWID - The cursor was opened on a database table.
+** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index.
+** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
+** IN_INDEX_EPH - The cursor was opened on a specially created and
+** populated epheremal table.
**
-** An existing b-tree may only be used if the SELECT is of the simple
-** form:
+** An existing b-tree might be used if the RHS expression pX is a simple
+** subquery such as:
**
** SELECT FROM
**
+** If the RHS of the IN operator is a list or a more complex subquery, then
+** an ephemeral table might need to be generated from the RHS and then
+** pX->iTable made to point to the ephermeral table instead of an
+** existing table.
+**
** If the prNotFound parameter is 0, then the b-tree will be used to iterate
** through the set members, skipping any duplicates. In this case an
** epheremal table must be used unless the selected is guaranteed
@@ -74764,8 +75541,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
** comparison is the same as the affinity of the column. If
** it is not, it is not possible to use any index.
*/
- char aff = comparisonAffinity(pX);
- int affinity_ok = (pTab->aCol[iCol].affinity==aff||aff==SQLITE_AFF_NONE);
+ int affinity_ok = sqlite3IndexAffinityOk(pX, pTab->aCol[iCol].affinity);
for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
if( (pIdx->aiColumn[0]==iCol)
@@ -74781,7 +75557,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
pKey,P4_KEYINFO_HANDOFF);
VdbeComment((v, "%s", pIdx->zName));
- eType = IN_INDEX_INDEX;
+ assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
+ eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
sqlite3VdbeJumpHere(v, iAddr);
if( prNotFound && !pTab->aCol[iCol].notNull ){
@@ -74893,6 +75670,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
case TK_IN: {
char affinity; /* Affinity of the LHS of the IN */
KeyInfo keyInfo; /* Keyinfo for the generated table */
+ static u8 sortOrder = 0; /* Fake aSortOrder for keyInfo */
int addr; /* Address of OP_OpenEphemeral instruction */
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
@@ -74920,6 +75698,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
+ keyInfo.aSortOrder = &sortOrder;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* Case 1: expr IN (SELECT ...)
@@ -74960,6 +75739,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
affinity = SQLITE_AFF_NONE;
}
keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+ keyInfo.aSortOrder = &sortOrder;
/* Loop through each expression in . */
r1 = sqlite3GetTempReg(pParse);
@@ -75286,7 +76066,7 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int
** for testing only - to verify that SQLite always gets the same answer
** with and without the column cache.
*/
- if( pParse->db->flags & SQLITE_ColumnCache ) return;
+ if( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
/* First replace any existing entry.
**
@@ -75483,8 +76263,8 @@ SQLITE_PRIVATE void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, in
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
int i;
struct yColCache *p;
- if( NEVER(iFrom==iTo) ) return;
- sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
+ assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg-1);
for(i=0, p=pParse->aColCache; iiReg;
if( x>=iFrom && xpVdbe, OP_Copy, iFrom+i, iTo+i);
- }
-}
-
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
/*
** Return true if any register in the range iFrom..iTo (inclusive)
@@ -75976,6 +76744,7 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
sqlite3ReleaseTempReg(pParse, r4);
break;
}
+ case TK_COLLATE:
case TK_UPLUS: {
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
break;
@@ -76142,7 +76911,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
sqlite3VdbeAddOp4(
v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
}else{
- sqlite3HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
+ pExpr->affinity, pExpr->u.zToken, 0);
}
break;
@@ -76345,6 +77115,12 @@ SQLITE_PRIVATE void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
case TK_ISNULL: zUniOp = "ISNULL"; break;
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
+ case TK_COLLATE: {
+ sqlite3ExplainExpr(pOut, pExpr->pLeft);
+ sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken);
+ break;
+ }
+
case TK_AGG_FUNCTION:
case TK_CONST_FUNC:
case TK_FUNCTION: {
@@ -76482,6 +77258,12 @@ SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
sqlite3ExplainPush(pOut);
sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
sqlite3ExplainPop(pOut);
+ if( pList->a[i].zName ){
+ sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
+ }
+ if( pList->a[i].bSpanIsTab ){
+ sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
+ }
if( inExpr-1 ){
sqlite3ExplainNL(pOut);
}
@@ -76563,6 +77345,9 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
case TK_REGISTER: {
return WRC_Prune;
}
+ case TK_COLLATE: {
+ return WRC_Continue;
+ }
case TK_FUNCTION:
case TK_AGG_FUNCTION:
case TK_CONST_FUNC: {
@@ -76584,9 +77369,11 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
}
if( isAppropriateForFactoring(pExpr) ){
int r1 = ++pParse->nMem;
- int r2;
- r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
- if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1);
+ int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
+ /* If r2!=r1, it means that register r1 is never used. That is harmless
+ ** but suboptimal, so we want to know about the situation to fix it.
+ ** Hence the following assert: */
+ assert( r2==r1 );
pExpr->op2 = pExpr->op;
pExpr->op = TK_REGISTER;
pExpr->iTable = r2;
@@ -76614,7 +77401,7 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
SQLITE_PRIVATE void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
Walker w;
if( pParse->cookieGoto ) return;
- if( (pParse->db->flags & SQLITE_FactorOutConst)!=0 ) return;
+ if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
w.xExprCallback = evalConstExpr;
w.xSelectCallback = 0;
w.pParse = pParse;
@@ -76729,7 +77516,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
int r1, r2;
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
- if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */
+ if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
if( NEVER(pExpr==0) ) return; /* No way this can happen */
op = pExpr->op;
switch( op ){
@@ -76849,7 +77636,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
int r1, r2;
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
- if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */
+ if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
if( pExpr==0 ) return;
/* The value of pExpr->op and op are related as follows:
@@ -77003,7 +77790,15 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
return 2;
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
- if( pA->op!=pB->op ) return 2;
+ if( pA->op!=pB->op ){
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
+ return 1;
+ }
+ if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
+ return 1;
+ }
+ return 2;
+ }
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
@@ -77015,11 +77810,9 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){
}else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
- return 2;
+ return pA->op==TK_COLLATE ? 1 : 2;
}
}
- if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
- if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
return 0;
}
@@ -77260,8 +78053,10 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
ExprSetIrreducible(pExpr);
pExpr->iAgg = (i16)i;
pExpr->pAggInfo = pAggInfo;
+ return WRC_Prune;
+ }else{
+ return WRC_Continue;
}
- return WRC_Prune;
}
}
return WRC_Continue;
@@ -77273,9 +78068,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
}
/*
-** Analyze the given expression looking for aggregate functions and
-** for variables that need to be added to the pParse->aAgg[] array.
-** Make additional entries to the pParse->aAgg[] array as necessary.
+** Analyze the pExpr expression looking for aggregate functions and
+** for variables that need to be added to AggInfo object that pNC->pAggInfo
+** points to. Additional entries are made on the AggInfo object as
+** necessary.
**
** This routine should only be called after the expression has been
** analyzed by sqlite3ResolveExprNames().
@@ -77788,7 +78584,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable(
assert( pSrc->nSrc==1 );
assert( sqlite3BtreeHoldsAllMutexes(pParse->db) );
- pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
if( !pTab ) goto exit_rename_table;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
zDb = db->aDb[iDb].zName;
@@ -78038,7 +78834,7 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
** If there is a NOT NULL constraint, then the default value for the
** column must not be NULL.
*/
- if( pCol->isPrimKey ){
+ if( pCol->colFlags & COLFLAG_PRIMKEY ){
sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
return;
}
@@ -78131,7 +78927,7 @@ SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
assert( pParse->pNewTable==0 );
assert( sqlite3BtreeHoldsAllMutexes(db) );
if( db->mallocFailed ) goto exit_begin_add_column;
- pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+ pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
if( !pTab ) goto exit_begin_add_column;
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -78675,7 +79471,7 @@ static void analyzeOneTable(
/* Do not gather statistics on views or virtual tables */
return;
}
- if( memcmp(pTab->zName, "sqlite_", 7)==0 ){
+ if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
/* Do not gather statistics on system tables */
return;
}
@@ -79085,7 +79881,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
if( pIndex==0 ) break;
pIndex->aiRowEst[i] = v;
if( *z==' ' ) z++;
- if( memcmp(z, "unordered", 10)==0 ){
+ if( strcmp(z, "unordered")==0 ){
pIndex->bUnordered = 1;
break;
}
@@ -79437,7 +80233,7 @@ static void attachFunc(
}
}
- /* Allocate the new entry in the db->aDb[] array and initialise the schema
+ /* Allocate the new entry in the db->aDb[] array and initialize the schema
** hash tables.
*/
if( db->aDb==db->aDbStatic ){
@@ -79454,7 +80250,7 @@ static void attachFunc(
/* Open the database file. If the btree is successfully opened, use
** it to obtain the database schema. At this point the schema may
- ** or may not be initialised.
+ ** or may not be initialized.
*/
flags = db->openFlags;
rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
@@ -79762,6 +80558,7 @@ SQLITE_PRIVATE int sqlite3FixInit(
assert( db->nDb>iDb );
pFix->pParse = pParse;
pFix->zDb = db->aDb[iDb].zName;
+ pFix->pSchema = db->aDb[iDb].pSchema;
pFix->zType = zType;
pFix->pName = pName;
return 1;
@@ -79792,14 +80589,15 @@ SQLITE_PRIVATE int sqlite3FixSrcList(
if( NEVER(pList==0) ) return 0;
zDb = pFix->zDb;
for(i=0, pItem=pList->a; inSrc; i++, pItem++){
- if( pItem->zDatabase==0 ){
- pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb);
- }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
+ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
pFix->zType, pFix->pName, pItem->zDatabase);
return 1;
}
+ sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
+ pItem->zDatabase = 0;
+ pItem->pSchema = pFix->pSchema;
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
@@ -80265,6 +81063,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
sqlite3 *db;
Vdbe *v;
+ assert( pParse->pToplevel==0 );
db = pParse->db;
if( db->mallocFailed ) return;
if( pParse->nested ) return;
@@ -80457,6 +81256,31 @@ SQLITE_PRIVATE Table *sqlite3LocateTable(
return p;
}
+/*
+** Locate the table identified by *p.
+**
+** This is a wrapper around sqlite3LocateTable(). The difference between
+** sqlite3LocateTable() and this function is that this function restricts
+** the search to schema (p->pSchema) if it is not NULL. p->pSchema may be
+** non-NULL if it is part of a view or trigger program definition. See
+** sqlite3FixSrcList() for details.
+*/
+SQLITE_PRIVATE Table *sqlite3LocateTableItem(
+ Parse *pParse,
+ int isView,
+ struct SrcList_item *p
+){
+ const char *zDb;
+ assert( p->pSchema==0 || p->zDatabase==0 );
+ if( p->pSchema ){
+ int iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+ zDb = pParse->db->aDb[iDb].zName;
+ }else{
+ zDb = p->zDatabase;
+ }
+ return sqlite3LocateTable(pParse, isView, p->zName, zDb);
+}
+
/*
** Locate the in-memory structure that describes
** a particular index given the name of that index
@@ -81307,7 +82131,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
pTab->tabFlags |= TF_HasPrimaryKey;
if( pList==0 ){
iCol = pTab->nCol - 1;
- pTab->aCol[iCol].isPrimKey = 1;
+ pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
}else{
for(i=0; inExpr; i++){
for(iCol=0; iColnCol; iCol++){
@@ -81316,7 +82140,7 @@ SQLITE_PRIVATE void sqlite3AddPrimaryKey(
}
}
if( iColnCol ){
- pTab->aCol[iCol].isPrimKey = 1;
+ pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY;
}
}
if( pList->nExpr>1 ) iCol = -1;
@@ -81433,10 +82257,7 @@ SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
if( !initbusy && (!pColl || !pColl->xCmp) ){
- pColl = sqlite3GetCollSeq(db, enc, pColl, zName);
- if( !pColl ){
- sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
- }
+ pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
}
return pColl;
@@ -82135,6 +82956,7 @@ static void destroyTable(Parse *pParse, Table *pTab){
return;
}else{
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ assert( iDb>=0 && iDbdb->nDb );
destroyRootPage(pParse, iLargest, iDb);
iDestroyed = iLargest;
}
@@ -82214,7 +83036,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in
/* Drop all SQLITE_MASTER table and index entries that refer to the
** table. The program name loops through the master table and deletes
** every row that refers to a table of the same name as the one being
- ** dropped. Triggers are handled seperately because a trigger can be
+ ** dropped. Triggers are handled separately because a trigger can be
** created in the temp database that refers to a table in another
** database.
*/
@@ -82252,8 +83074,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
if( noErr ) db->suppressErr++;
- pTab = sqlite3LocateTable(pParse, isView,
- pName->a[0].zName, pName->a[0].zDatabase);
+ pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
if( noErr ) db->suppressErr--;
if( pTab==0 ){
@@ -82507,9 +83328,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
int tnum; /* Root page of index */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
-#ifdef SQLITE_OMIT_MERGE_SORT
- int regIdxKey; /* Registers containing the index key */
-#endif
int regRecord; /* Register holding assemblied index record */
sqlite3 *db = pParse->db; /* The database connection */
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
@@ -82537,13 +83355,9 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
(char *)pKey, P4_KEYINFO_HANDOFF);
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
-#ifndef SQLITE_OMIT_MERGE_SORT
/* Open the sorter cursor if we are to use one. */
iSorter = pParse->nTab++;
sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
-#else
- iSorter = iTab;
-#endif
/* Open the table. Loop through all rows of the table, inserting index
** records into the sorter. */
@@ -82551,7 +83365,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
regRecord = sqlite3GetTempReg(pParse);
-#ifndef SQLITE_OMIT_MERGE_SORT
sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
@@ -82562,8 +83375,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
addr2 = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
- sqlite3HaltConstraint(
- pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
+ OE_Abort, "indexed columns are not unique", P4_STATIC
);
}else{
addr2 = sqlite3VdbeCurrentAddr(v);
@@ -82571,30 +83384,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
-#else
- regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
- addr2 = addr1 + 1;
- if( pIndex->onError!=OE_None ){
- const int regRowid = regIdxKey + pIndex->nColumn;
- const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
- void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
-
- /* The registers accessed by the OP_IsUnique opcode were allocated
- ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
- ** call above. Just before that function was freed they were released
- ** (made available to the compiler for reuse) using
- ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
- ** opcode use the values stored within seems dangerous. However, since
- ** we can be sure that no other temp registers have been allocated
- ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
- */
- sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
- sqlite3HaltConstraint(
- pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
- }
- sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
-#endif
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
sqlite3VdbeJumpHere(v, addr1);
@@ -82693,9 +83482,9 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** sqlite3FixSrcList can never fail. */
assert(0);
}
- pTab = sqlite3LocateTable(pParse, 0, pTblName->a[0].zName,
- pTblName->a[0].zDatabase);
- if( !pTab || db->mallocFailed ) goto exit_create_index;
+ pTab = sqlite3LocateTableItem(pParse, 0, &pTblName->a[0]);
+ assert( db->mallocFailed==0 || pTab==0 );
+ if( pTab==0 ) goto exit_create_index;
assert( db->aDb[iDb].pSchema==pTab->pSchema );
}else{
assert( pName==0 );
@@ -82709,7 +83498,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
assert( pTab!=0 );
assert( pParse->nErr==0 );
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
- && memcmp(&pTab->zName[7],"altertab_",9)!=0 ){
+ && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
}
@@ -82806,10 +83595,8 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
for(i=0; inExpr; i++){
Expr *pExpr = pList->a[i].pExpr;
if( pExpr ){
- CollSeq *pColl = pExpr->pColl;
- /* Either pColl!=0 or there was an OOM failure. But if an OOM
- ** failure we have quit before reaching this point. */
- if( ALWAYS(pColl) ){
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
+ if( pColl ){
nExtra += (1 + sqlite3Strlen30(pColl->zName));
}
}
@@ -82872,6 +83659,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
const char *zColName = pListItem->zName;
Column *pTabCol;
int requestedSortOrder;
+ CollSeq *pColl; /* Collating sequence */
char *zColl; /* Collation sequence name */
for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){
@@ -82884,14 +83672,11 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
goto exit_create_index;
}
pIndex->aiColumn[i] = j;
- /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of
- ** the way the "idxlist" non-terminal is constructed by the parser,
- ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl
- ** must exist or else there must have been an OOM error. But if there
- ** was an OOM error, we would never reach this point. */
- if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){
+ if( pListItem->pExpr
+ && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0
+ ){
int nColl;
- zColl = pListItem->pExpr->pColl->zName;
+ zColl = pColl->zName;
nColl = sqlite3Strlen30(zColl) + 1;
assert( nExtra>=nColl );
memcpy(zExtra, zColl, nColl);
@@ -82958,7 +83743,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
** However the ON CONFLICT clauses are different. If both this
** constraint and the previous equivalent constraint have explicit
** ON CONFLICT clauses this is an error. Otherwise, use the
- ** explicitly specified behaviour for the index.
+ ** explicitly specified behavior for the index.
*/
if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
sqlite3ErrorMsg(pParse,
@@ -83705,6 +84490,15 @@ SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *pParse){
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
+#ifndef SQLITE_OMIT_TRIGGER
+ if( pToplevel!=pParse ){
+ /* This branch is taken if a trigger is currently being coded. In this
+ ** case, set cookieGoto to a non-zero value to show that this function
+ ** has been called. This is used by the sqlite3ExprCodeConstants()
+ ** function. */
+ pParse->cookieGoto = -1;
+ }
+#endif
if( pToplevel->cookieGoto==0 ){
Vdbe *v = sqlite3GetVdbe(pToplevel);
if( v==0 ) return; /* This only happens if there was a prior error */
@@ -83802,12 +84596,19 @@ SQLITE_PRIVATE void sqlite3MayAbort(Parse *pParse){
** error. The onError parameter determines which (if any) of the statement
** and/or current transaction is rolled back.
*/
-SQLITE_PRIVATE void sqlite3HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){
+SQLITE_PRIVATE void sqlite3HaltConstraint(
+ Parse *pParse, /* Parsing context */
+ int errCode, /* extended error code */
+ int onError, /* Constraint type */
+ char *p4, /* Error message */
+ int p4type /* P4_STATIC or P4_TRANSIENT */
+){
Vdbe *v = sqlite3GetVdbe(pParse);
+ assert( (errCode&0xff)==SQLITE_CONSTRAINT );
if( onError==OE_Abort ){
sqlite3MayAbort(pParse);
}
- sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type);
+ sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
}
/*
@@ -84054,17 +84855,18 @@ static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
-** sequence can be found.
+** sequence can be found. If no collation is found, leave an error message.
**
** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
*/
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
- sqlite3* db, /* The database connection */
+ Parse *pParse, /* Parsing context */
u8 enc, /* The desired encoding for the collating sequence */
CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
const char *zName /* Collating sequence name */
){
CollSeq *p;
+ sqlite3 *db = pParse->db;
p = pColl;
if( !p ){
@@ -84081,6 +84883,9 @@ SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
p = 0;
}
assert( !p || p->xCmp );
+ if( p==0 ){
+ sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
+ }
return p;
}
@@ -84099,10 +84904,8 @@ SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
if( pColl ){
const char *zName = pColl->zName;
sqlite3 *db = pParse->db;
- CollSeq *p = sqlite3GetCollSeq(db, ENC(db), pColl, zName);
+ CollSeq *p = sqlite3GetCollSeq(pParse, ENC(db), pColl, zName);
if( !p ){
- sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
- pParse->nErr++;
return SQLITE_ERROR;
}
assert( p==pColl );
@@ -84489,7 +85292,7 @@ SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
struct SrcList_item *pItem = pSrc->a;
Table *pTab;
assert( pItem && pSrc->nSrc==1 );
- pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+ pTab = sqlite3LocateTableItem(pParse, 0, pItem);
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
@@ -84550,29 +85353,28 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
int iCur /* Cursor number for ephemerial table */
){
SelectDest dest;
- Select *pDup;
+ Select *pSel;
+ SrcList *pFrom;
sqlite3 *db = pParse->db;
+ int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
- pDup = sqlite3SelectDup(db, pView->pSelect, 0);
- if( pWhere ){
- SrcList *pFrom;
-
- pWhere = sqlite3ExprDup(db, pWhere, 0);
- pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
- if( pFrom ){
- assert( pFrom->nSrc==1 );
- pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName);
- pFrom->a[0].pSelect = pDup;
- assert( pFrom->a[0].pOn==0 );
- assert( pFrom->a[0].pUsing==0 );
- }else{
- sqlite3SelectDelete(db, pDup);
- }
- pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+ pWhere = sqlite3ExprDup(db, pWhere, 0);
+ pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
+
+ if( pFrom ){
+ assert( pFrom->nSrc==1 );
+ pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
+ pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
+ assert( pFrom->a[0].pOn==0 );
+ assert( pFrom->a[0].pUsing==0 );
}
+
+ pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+ if( pSel ) pSel->selFlags |= SF_Materialize;
+
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
- sqlite3Select(pParse, pDup, &dest);
- sqlite3SelectDelete(db, pDup);
+ sqlite3Select(pParse, pSel, &dest);
+ sqlite3SelectDelete(db, pSel);
}
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
@@ -85095,7 +85897,9 @@ SQLITE_PRIVATE int sqlite3GenerateIndexKey(
}
if( doMakeRec ){
const char *zAff;
- if( pTab->pSelect || (pParse->db->flags & SQLITE_IdxRealAsInt)!=0 ){
+ if( pTab->pSelect
+ || OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
+ ){
zAff = 0;
}else{
zAff = sqlite3IndexAffinityStr(v, pIdx);
@@ -85277,6 +86081,56 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
}
+/*
+** Implementation of the instr() function.
+**
+** instr(haystack,needle) finds the first occurrence of needle
+** in haystack and returns the number of previous characters plus 1,
+** or 0 if needle does not occur within haystack.
+**
+** If both haystack and needle are BLOBs, then the result is one more than
+** the number of bytes in haystack prior to the first occurrence of needle,
+** or 0 if needle never occurs in haystack.
+*/
+static void instrFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *zHaystack;
+ const unsigned char *zNeedle;
+ int nHaystack;
+ int nNeedle;
+ int typeHaystack, typeNeedle;
+ int N = 1;
+ int isText;
+
+ UNUSED_PARAMETER(argc);
+ typeHaystack = sqlite3_value_type(argv[0]);
+ typeNeedle = sqlite3_value_type(argv[1]);
+ if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
+ nHaystack = sqlite3_value_bytes(argv[0]);
+ nNeedle = sqlite3_value_bytes(argv[1]);
+ if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
+ zHaystack = sqlite3_value_blob(argv[0]);
+ zNeedle = sqlite3_value_blob(argv[1]);
+ isText = 0;
+ }else{
+ zHaystack = sqlite3_value_text(argv[0]);
+ zNeedle = sqlite3_value_text(argv[1]);
+ isText = 1;
+ }
+ while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
+ N++;
+ do{
+ nHaystack--;
+ zHaystack++;
+ }while( isText && (zHaystack[0]&0xc0)==0x80 );
+ }
+ if( nNeedle>nHaystack ) N = 0;
+ sqlite3_result_int(context, N);
+}
+
/*
** Implementation of the substr() function.
**
@@ -85476,33 +86330,14 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
}
-
-#if 0 /* This function is never used. */
/*
-** The COALESCE() and IFNULL() functions used to be implemented as shown
-** here. But now they are implemented as VDBE code so that unused arguments
-** do not have to be computed. This legacy implementation is retained as
-** comment.
+** The COALESCE() and IFNULL() functions are implemented as VDBE code so
+** that unused argument values do not have to be computed. However, we
+** still need some kind of function implementation for this routines in
+** the function table. That function implementation will never be called
+** so it doesn't matter what the implementation is. We might as well use
+** the "version()" function as a substitute.
*/
-/*
-** Implementation of the IFNULL(), NVL(), and COALESCE() functions.
-** All three do the same thing. They return the first non-NULL
-** argument.
-*/
-static void ifnullFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- int i;
- for(i=0; inoCase;
int prevEscape = 0; /* True if the previous character was 'escape' */
- while( (c = sqlite3Utf8Read(zPattern,&zPattern))!=0 ){
- if( !prevEscape && c==matchAll ){
- while( (c=sqlite3Utf8Read(zPattern,&zPattern)) == matchAll
+ while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
+ if( c==matchAll && !prevEscape ){
+ while( (c=sqlite3Utf8Read(&zPattern)) == matchAll
|| c == matchOne ){
- if( c==matchOne && sqlite3Utf8Read(zString, &zString)==0 ){
+ if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
return 0;
}
}
if( c==0 ){
return 1;
}else if( c==esc ){
- c = sqlite3Utf8Read(zPattern, &zPattern);
+ c = sqlite3Utf8Read(&zPattern);
if( c==0 ){
return 0;
}
@@ -85701,25 +86536,25 @@ static int patternCompare(
}
return *zString!=0;
}
- while( (c2 = sqlite3Utf8Read(zString,&zString))!=0 ){
+ while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
if( noCase ){
GlogUpperToLower(c2);
GlogUpperToLower(c);
while( c2 != 0 && c2 != c ){
- c2 = sqlite3Utf8Read(zString, &zString);
+ c2 = sqlite3Utf8Read(&zString);
GlogUpperToLower(c2);
}
}else{
while( c2 != 0 && c2 != c ){
- c2 = sqlite3Utf8Read(zString, &zString);
+ c2 = sqlite3Utf8Read(&zString);
}
}
if( c2==0 ) return 0;
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
}
return 0;
- }else if( !prevEscape && c==matchOne ){
- if( sqlite3Utf8Read(zString, &zString)==0 ){
+ }else if( c==matchOne && !prevEscape ){
+ if( sqlite3Utf8Read(&zString)==0 ){
return 0;
}
}else if( c==matchSet ){
@@ -85727,20 +86562,20 @@ static int patternCompare(
assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
seen = 0;
invert = 0;
- c = sqlite3Utf8Read(zString, &zString);
+ c = sqlite3Utf8Read(&zString);
if( c==0 ) return 0;
- c2 = sqlite3Utf8Read(zPattern, &zPattern);
+ c2 = sqlite3Utf8Read(&zPattern);
if( c2=='^' ){
invert = 1;
- c2 = sqlite3Utf8Read(zPattern, &zPattern);
+ c2 = sqlite3Utf8Read(&zPattern);
}
if( c2==']' ){
if( c==']' ) seen = 1;
- c2 = sqlite3Utf8Read(zPattern, &zPattern);
+ c2 = sqlite3Utf8Read(&zPattern);
}
while( c2 && c2!=']' ){
if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
- c2 = sqlite3Utf8Read(zPattern, &zPattern);
+ c2 = sqlite3Utf8Read(&zPattern);
if( c>=prior_c && c<=c2 ) seen = 1;
prior_c = 0;
}else{
@@ -85749,7 +86584,7 @@ static int patternCompare(
}
prior_c = c2;
}
- c2 = sqlite3Utf8Read(zPattern, &zPattern);
+ c2 = sqlite3Utf8Read(&zPattern);
}
if( c2==0 || (seen ^ invert)==0 ){
return 0;
@@ -85757,7 +86592,7 @@ static int patternCompare(
}else if( esc==c && !prevEscape ){
prevEscape = 1;
}else{
- c2 = sqlite3Utf8Read(zString, &zString);
+ c2 = sqlite3Utf8Read(&zString);
if( noCase ){
GlogUpperToLower(c);
GlogUpperToLower(c2);
@@ -85829,7 +86664,7 @@ static void likeFunc(
"ESCAPE expression must be a single character", -1);
return;
}
- escape = sqlite3Utf8Read(zEsc, &zEsc);
+ escape = sqlite3Utf8Read(&zEsc);
}
if( zA && zB ){
struct compareInfo *pInfo = sqlite3_user_data(context);
@@ -86040,6 +86875,62 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
}
}
+/*
+** The unicode() function. Return the integer unicode code-point value
+** for the first character of the input string.
+*/
+static void unicodeFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ const unsigned char *z = sqlite3_value_text(argv[0]);
+ (void)argc;
+ if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z));
+}
+
+/*
+** The char() function takes zero or more arguments, each of which is
+** an integer. It constructs a string where each character of the string
+** is the unicode character for the corresponding integer argument.
+*/
+static void charFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ unsigned char *z, *zOut;
+ int i;
+ zOut = z = sqlite3_malloc( argc*4 );
+ if( z==0 ){
+ sqlite3_result_error_nomem(context);
+ return;
+ }
+ for(i=0; i0x10ffff ) x = 0xfffd;
+ c = (unsigned)(x & 0x1fffff);
+ if( c<0x00080 ){
+ *zOut++ = (u8)(c&0xFF);
+ }else if( c<0x00800 ){
+ *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);
+ *zOut++ = 0x80 + (u8)(c & 0x3F);
+ }else if( c<0x10000 ){
+ *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
+ *zOut++ = 0x80 + (u8)(c & 0x3F);
+ }else{
+ *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);
+ *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);
+ *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
+ *zOut++ = 0x80 + (u8)(c & 0x3F);
+ } \
+ }
+ sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free);
+}
+
/*
** The hex() function. Interpret the argument as a blob. Return
** a hexadecimal rendering as text.
@@ -86664,8 +87555,11 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
+ FUNCTION(instr, 2, 0, 0, instrFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
FUNCTION(substr, 3, 0, 0, substrFunc ),
+ FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
+ FUNCTION(char, -1, 0, 0, charFunc ),
FUNCTION(abs, 1, 0, 0, absFunc ),
#ifndef SQLITE_OMIT_FLOATING_POINT
FUNCTION(round, 1, 0, 0, roundFunc ),
@@ -86757,8 +87651,9 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** --------------------------
**
** Foreign keys in SQLite come in two flavours: deferred and immediate.
-** If an immediate foreign key constraint is violated, SQLITE_CONSTRAINT
-** is returned and the current statement transaction rolled back. If a
+** If an immediate foreign key constraint is violated,
+** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
+** statement transaction rolled back. If a
** deferred foreign key constraint is violated, no action is taken
** immediately. However if the application attempts to commit the
** transaction before fixing the constraint violation, the attempt fails.
@@ -86822,7 +87717,8 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** Immediate constraints are usually handled similarly. The only difference
** is that the counter used is stored as part of each individual statement
** object (struct Vdbe). If, after the statement has run, its immediate
-** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT
+** constraint counter is greater than zero,
+** it returns SQLITE_CONSTRAINT_FOREIGNKEY
** and the statement transaction is rolled back. An exception is an INSERT
** statement that inserts a single row only (no triggers). In this case,
** instead of using a counter, an exception is thrown immediately if the
@@ -86878,7 +87774,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** A foreign key constraint requires that the key columns in the parent
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
** Given that pParent is the parent table for foreign key constraint pFKey,
-** search the schema a unique index on the parent key columns.
+** search the schema for a unique index on the parent key columns.
**
** If successful, zero is returned. If the parent key is an INTEGER PRIMARY
** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx
@@ -86914,7 +87810,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
** into pParse. If an OOM error occurs, non-zero is returned and the
** pParse->db->mallocFailed flag is set.
*/
-static int locateFkeyIndex(
+SQLITE_PRIVATE int sqlite3FkLocateIndex(
Parse *pParse, /* Parse context to store any error in */
Table *pParent, /* Parent table of FK constraint pFKey */
FKey *pFKey, /* Foreign key to find index for */
@@ -87011,7 +87907,9 @@ static int locateFkeyIndex(
if( !pIdx ){
if( !pParse->disableTriggers ){
- sqlite3ErrorMsg(pParse, "foreign key mismatch");
+ sqlite3ErrorMsg(pParse,
+ "foreign key mismatch - \"%w\" referencing \"%w\"",
+ pFKey->pFrom->zName, pFKey->zTo);
}
sqlite3DbFree(pParse->db, aiCol);
return 1;
@@ -87160,8 +88058,8 @@ static void fkLookupParent(
** incrementing a counter. This is necessary as the VM code is being
** generated for will not open a statement transaction. */
assert( nIncr==1 );
- sqlite3HaltConstraint(
- pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+ OE_Abort, "foreign key constraint failed", P4_STATIC
);
}else{
if( nIncr>0 && pFKey->isDeferred==0 ){
@@ -87247,12 +88145,15 @@ static void fkScanChildren(
** expression to the parent key column defaults. */
if( pIdx ){
Column *pCol;
+ const char *zColl;
iCol = pIdx->aiColumn[i];
pCol = &pTab->aCol[iCol];
if( pTab->iPKey==iCol ) iCol = -1;
pLeft->iTable = regData+iCol+1;
pLeft->affinity = pCol->affinity;
- pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl);
+ zColl = pCol->zColl;
+ if( zColl==0 ) zColl = db->pDfltColl->zName;
+ pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl);
}else{
pLeft->iTable = regData;
pLeft->affinity = SQLITE_AFF_INTEGER;
@@ -87398,8 +88299,8 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
** any modifications to the schema are made. This is because statement
** transactions are not able to rollback schema changes. */
sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
- sqlite3HaltConstraint(
- pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+ OE_Abort, "foreign key constraint failed", P4_STATIC
);
if( iSkip ){
@@ -87469,7 +88370,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
}else{
pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
}
- if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
+ if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
if( !isIgnoreErrors || db->mallocFailed ) return;
if( pTo==0 ){
@@ -87549,7 +88450,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
continue;
}
- if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
if( !isIgnoreErrors || db->mallocFailed ) return;
continue;
}
@@ -87604,7 +88505,7 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
}
for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
Index *pIdx = 0;
- locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
+ sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
if( pIdx ){
for(i=0; inColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
}
@@ -87661,7 +88562,8 @@ SQLITE_PRIVATE int sqlite3FkRequired(
int iKey;
for(iKey=0; iKeynCol; iKey++){
Column *pCol = &pTab->aCol[iKey];
- if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey) : pCol->isPrimKey) ){
+ if( (zKey ? !sqlite3StrICmp(pCol->zName, zKey)
+ : (pCol->colFlags & COLFLAG_PRIMKEY)!=0) ){
if( aChange[iKey]>=0 ) return 1;
if( iKey==pTab->iPKey && chngRowid ) return 1;
}
@@ -87729,7 +88631,7 @@ static Trigger *fkActionTrigger(
int i; /* Iterator variable */
Expr *pWhen = 0; /* WHEN clause for the trigger */
- if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
assert( aiCol || pFKey->nCol==1 );
for(i=0; inCol; i++){
@@ -87982,7 +88884,7 @@ SQLITE_PRIVATE void sqlite3OpenTable(
int opcode /* OP_OpenRead or OP_OpenWrite */
){
Vdbe *v;
- if( IsVirtual(pTab) ) return;
+ assert( !IsVirtual(pTab) );
v = sqlite3GetVdbe(p);
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName);
@@ -88277,6 +89179,97 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse){
#endif /* SQLITE_OMIT_AUTOINCREMENT */
+/*
+** Generate code for a co-routine that will evaluate a subquery one
+** row at a time.
+**
+** The pSelect parameter is the subquery that the co-routine will evaluation.
+** Information about the location of co-routine and the registers it will use
+** is returned by filling in the pDest object.
+**
+** Registers are allocated as follows:
+**
+** pDest->iSDParm The register holding the next entry-point of the
+** co-routine. Run the co-routine to its next breakpoint
+** by calling "OP_Yield $X" where $X is pDest->iSDParm.
+**
+** pDest->iSDParm+1 The register holding the "completed" flag for the
+** co-routine. This register is 0 if the previous Yield
+** generated a new result row, or 1 if the subquery
+** has completed. If the Yield is called again
+** after this register becomes 1, then the VDBE will
+** halt with an SQLITE_INTERNAL error.
+**
+** pDest->iSdst First result register.
+**
+** pDest->nSdst Number of result registers.
+**
+** This routine handles all of the register allocation and fills in the
+** pDest structure appropriately.
+**
+** Here is a schematic of the generated code assuming that X is the
+** co-routine entry-point register reg[pDest->iSDParm], that EOF is the
+** completed flag reg[pDest->iSDParm+1], and R and S are the range of
+** registers that hold the result set, reg[pDest->iSdst] through
+** reg[pDest->iSdst+pDest->nSdst-1]:
+**
+** X <- A
+** EOF <- 0
+** goto B
+** A: setup for the SELECT
+** loop rows in the SELECT
+** load results into registers R..S
+** yield X
+** end loop
+** cleanup after the SELECT
+** EOF <- 1
+** yield X
+** halt-error
+** B:
+**
+** To use this subroutine, the caller generates code as follows:
+**
+** [ Co-routine generated by this subroutine, shown above ]
+** S: yield X
+** if EOF goto E
+** if skip this row, goto C
+** if terminate loop, goto E
+** deal with this row
+** C: goto S
+** E:
+*/
+SQLITE_PRIVATE int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){
+ int regYield; /* Register holding co-routine entry-point */
+ int regEof; /* Register holding co-routine completion flag */
+ int addrTop; /* Top of the co-routine */
+ int j1; /* Jump instruction */
+ int rc; /* Result code */
+ Vdbe *v; /* VDBE under construction */
+
+ regYield = ++pParse->nMem;
+ regEof = ++pParse->nMem;
+ v = sqlite3GetVdbe(pParse);
+ addrTop = sqlite3VdbeCurrentAddr(v);
+ sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */
+ VdbeComment((v, "Co-routine entry point"));
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */
+ VdbeComment((v, "Co-routine completion flag"));
+ sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield);
+ j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
+ rc = sqlite3Select(pParse, pSelect, pDest);
+ assert( pParse->nErr==0 || rc );
+ if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM;
+ if( rc ) return rc;
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */
+ sqlite3VdbeAddOp1(v, OP_Yield, regYield); /* yield X */
+ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
+ VdbeComment((v, "End of coroutine"));
+ sqlite3VdbeJumpHere(v, j1); /* label B: */
+ return rc;
+}
+
+
+
/* Forward declaration */
static int xferOptimization(
Parse *pParse, /* Parser context */
@@ -88525,51 +89518,12 @@ SQLITE_PRIVATE void sqlite3Insert(
** co-routine is the common header to the 3rd and 4th templates.
*/
if( pSelect ){
- /* Data is coming from a SELECT. Generate code to implement that SELECT
- ** as a co-routine. The code is common to both the 3rd and 4th
- ** templates:
- **
- ** EOF <- 0
- ** X <- A
- ** goto B
- ** A: setup for the SELECT
- ** loop over the tables in the SELECT
- ** load value into register R..R+n
- ** yield X
- ** end loop
- ** cleanup after the SELECT
- ** EOF <- 1
- ** yield X
- ** halt-error
- **
- ** On each invocation of the co-routine, it puts a single row of the
- ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1.
- ** (These output registers are allocated by sqlite3Select().) When
- ** the SELECT completes, it sets the EOF flag stored in regEof.
- */
- int rc, j1;
-
- regEof = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */
- VdbeComment((v, "SELECT eof flag"));
- sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem);
- addrSelect = sqlite3VdbeCurrentAddr(v)+2;
- sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iSDParm);
- j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
- VdbeComment((v, "Jump over SELECT coroutine"));
-
- /* Resolve the expressions in the SELECT statement and execute it. */
- rc = sqlite3Select(pParse, pSelect, &dest);
- assert( pParse->nErr==0 || rc );
- if( rc || NEVER(pParse->nErr) || db->mallocFailed ){
- goto insert_cleanup;
- }
- sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */
- sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm); /* yield X */
- sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
- VdbeComment((v, "End of SELECT coroutine"));
- sqlite3VdbeJumpHere(v, j1); /* label B: */
+ /* Data is coming from a SELECT. Generate a co-routine to run that
+ ** SELECT. */
+ int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
+ if( rc ) goto insert_cleanup;
+ regEof = dest.iSDParm + 1;
regFromSelect = dest.iSdst;
assert( pSelect->pEList );
nColumn = pSelect->pEList->nExpr;
@@ -89150,7 +90104,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
case OE_Fail: {
char *zMsg;
sqlite3VdbeAddOp3(v, OP_HaltIfNull,
- SQLITE_CONSTRAINT, onError, regData+i);
+ SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
pTab->zName, pTab->aCol[i].zName);
sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
@@ -89190,7 +90144,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
}else{
zConsName = 0;
}
- sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
+ onError, zConsName, P4_DYNAMIC);
}
sqlite3VdbeResolveLabel(v, allOk);
}
@@ -89221,8 +90176,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
- sqlite3HaltConstraint(
- pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
+ onError, "PRIMARY KEY must be unique", P4_STATIC);
break;
}
case OE_Replace: {
@@ -89349,7 +90304,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
sqlite3StrAccumAppend(&errMsg,
pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
zErr = sqlite3StrAccumFinish(&errMsg);
- sqlite3HaltConstraint(pParse, onError, zErr, 0);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
+ onError, zErr, 0);
sqlite3DbFree(errMsg.db, zErr);
break;
}
@@ -89648,7 +90604,7 @@ static int xferOptimization(
** we have to check the semantics.
*/
pItem = pSelect->pSrc->a;
- pSrc = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
+ pSrc = sqlite3LocateTableItem(pParse, 0, pItem);
if( pSrc==0 ){
return 0; /* FROM clause does not contain a real table */
}
@@ -89757,8 +90713,8 @@ static int xferOptimization(
if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
- sqlite3HaltConstraint(
- pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
+ onError, "PRIMARY KEY must be unique", P4_STATIC);
sqlite3VdbeJumpHere(v, addr2);
autoIncStep(pParse, regAutoinc, regRowid);
}else if( pDest->pIndex==0 ){
@@ -90215,6 +91171,20 @@ struct sqlite3_api_routines {
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
int (*vtab_config)(sqlite3*,int op,...);
int (*vtab_on_conflict)(sqlite3*);
+ /* Version 3.7.16 and later */
+ int (*close_v2)(sqlite3*);
+ const char *(*db_filename)(sqlite3*,const char*);
+ int (*db_readonly)(sqlite3*,const char*);
+ int (*db_release_memory)(sqlite3*);
+ const char *(*errstr)(int);
+ int (*stmt_busy)(sqlite3_stmt*);
+ int (*stmt_readonly)(sqlite3_stmt*);
+ int (*stricmp)(const char*,const char*);
+ int (*uri_boolean)(const char*,const char*,int);
+ sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
+ const char *(*uri_parameter)(const char*,const char*);
+ char *(*vsnprintf)(int,char*,const char*,va_list);
+ int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
};
/*
@@ -90418,6 +91388,20 @@ struct sqlite3_api_routines {
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
#define sqlite3_vtab_config sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
+/* Version 3.7.16 and later */
+#define sqlite3_close_v2 sqlite3_api->close_v2
+#define sqlite3_db_filename sqlite3_api->db_filename
+#define sqlite3_db_readonly sqlite3_api->db_readonly
+#define sqlite3_db_release_memory sqlite3_api->db_release_memory
+#define sqlite3_errstr sqlite3_api->errstr
+#define sqlite3_stmt_busy sqlite3_api->stmt_busy
+#define sqlite3_stmt_readonly sqlite3_api->stmt_readonly
+#define sqlite3_stricmp sqlite3_api->stricmp
+#define sqlite3_uri_boolean sqlite3_api->uri_boolean
+#define sqlite3_uri_int64 sqlite3_api->uri_int64
+#define sqlite3_uri_parameter sqlite3_api->uri_parameter
+#define sqlite3_uri_vsnprintf sqlite3_api->vsnprintf
+#define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2
#endif /* SQLITE_CORE */
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
@@ -90787,6 +91771,19 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_blob_reopen,
sqlite3_vtab_config,
sqlite3_vtab_on_conflict,
+ sqlite3_close_v2,
+ sqlite3_db_filename,
+ sqlite3_db_readonly,
+ sqlite3_db_release_memory,
+ sqlite3_errstr,
+ sqlite3_stmt_busy,
+ sqlite3_stmt_readonly,
+ sqlite3_stricmp,
+ sqlite3_uri_boolean,
+ sqlite3_uri_int64,
+ sqlite3_uri_parameter,
+ sqlite3_vsnprintf,
+ sqlite3_wal_checkpoint_v2
};
/*
@@ -91253,6 +92250,9 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
{ "sql_trace", SQLITE_SqlTrace },
{ "vdbe_listing", SQLITE_VdbeListing },
{ "vdbe_trace", SQLITE_VdbeTrace },
+ { "vdbe_addoptrace", SQLITE_VdbeAddopTrace},
+ { "vdbe_debug", SQLITE_SqlTrace | SQLITE_VdbeListing
+ | SQLITE_VdbeTrace },
#endif
#ifndef SQLITE_OMIT_CHECK
{ "ignore_check_constraints", SQLITE_IgnoreChecks },
@@ -91426,6 +92426,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
aFcntl[1] = zLeft;
aFcntl[2] = zRight;
aFcntl[3] = 0;
+ db->busyHandler.nBusy = 0;
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
if( rc==SQLITE_OK ){
if( aFcntl[0] ){
@@ -92016,11 +93017,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
- int i;
+ int i, k;
int nHidden = 0;
Column *pCol;
+ Index *pPk;
+ for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
sqlite3VdbeSetNumCols(v, 6);
pParse->nMem = 6;
+ sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
@@ -92043,7 +93047,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
}
- sqlite3VdbeAddOp2(v, OP_Integer, pCol->isPrimKey, 6);
+ if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
+ k = 0;
+ }else if( pPk==0 ){
+ k = 1;
+ }else{
+ for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
+ }
+ sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
}
}
@@ -92059,6 +93070,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
pTab = pIdx->pTable;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
+ sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
@@ -92085,6 +93097,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i = 0;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
+ sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
@@ -92148,6 +93161,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
int i = 0;
sqlite3VdbeSetNumCols(v, 8);
pParse->nMem = 8;
+ sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC);
@@ -92181,6 +93195,122 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else
#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+#ifndef SQLITE_OMIT_TRIGGER
+ if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
+ FKey *pFK; /* A foreign key constraint */
+ Table *pTab; /* Child table contain "REFERENCES" keyword */
+ Table *pParent; /* Parent table that child points to */
+ Index *pIdx; /* Index in the parent table */
+ int i; /* Loop counter: Foreign key number for pTab */
+ int j; /* Loop counter: Field of the foreign key */
+ HashElem *k; /* Loop counter: Next table in schema */
+ int x; /* result variable */
+ int regResult; /* 3 registers to hold a result row */
+ int regKey; /* Register to hold key for checking the FK */
+ int regRow; /* Registers to hold a row from pTab */
+ int addrTop; /* Top of a loop checking foreign keys */
+ int addrOk; /* Jump here if the key is OK */
+ int *aiCols; /* child to parent column mapping */
+
+ if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+ regResult = pParse->nMem+1;
+ pParse->nMem += 4;
+ regKey = ++pParse->nMem;
+ regRow = ++pParse->nMem;
+ v = sqlite3GetVdbe(pParse);
+ sqlite3VdbeSetNumCols(v, 4);
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
+ sqlite3CodeVerifySchema(pParse, iDb);
+ k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
+ while( k ){
+ if( zRight ){
+ pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
+ k = 0;
+ }else{
+ pTab = (Table*)sqliteHashData(k);
+ k = sqliteHashNext(k);
+ }
+ if( pTab==0 || pTab->pFKey==0 ) continue;
+ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+ if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
+ sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
+ P4_TRANSIENT);
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+ pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
+ if( pParent==0 ) break;
+ pIdx = 0;
+ sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
+ if( x==0 ){
+ if( pIdx==0 ){
+ sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
+ }else{
+ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+ sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
+ sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+ }
+ }else{
+ k = 0;
+ break;
+ }
+ }
+ if( pFK ) break;
+ if( pParse->nTabnTab = i;
+ addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
+ for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+ pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
+ assert( pParent!=0 );
+ pIdx = 0;
+ aiCols = 0;
+ x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
+ assert( x==0 );
+ addrOk = sqlite3VdbeMakeLabel(v);
+ if( pIdx==0 ){
+ int iKey = pFK->aCol[0].iFrom;
+ assert( iKey>=0 && iKeynCol );
+ if( iKey!=pTab->iPKey ){
+ sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
+ sqlite3ColumnDefault(v, pTab, iKey, regRow);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
+ sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
+ sqlite3VdbeCurrentAddr(v)+3);
+ }else{
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
+ }
+ sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
+ sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+ }else{
+ for(j=0; jnCol; j++){
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
+ aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
+ sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
+ }
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
+ sqlite3VdbeChangeP4(v, -1,
+ sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
+ sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+ }
+ sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
+ pFK->zTo, P4_TRANSIENT);
+ sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
+ sqlite3VdbeResolveLabel(v, addrOk);
+ sqlite3DbFree(db, aiCols);
+ }
+ sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
+ sqlite3VdbeJumpHere(v, addrTop);
+ }
+ }else
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
+
#ifndef NDEBUG
if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
if( zRight ){
@@ -92302,7 +93432,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName),
P4_DYNAMIC);
- sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
+ sqlite3VdbeAddOp2(v, OP_Move, 2, 4);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
sqlite3VdbeJumpHere(v, addr);
@@ -92605,6 +93735,22 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3_db_release_memory(db);
}else
+ /*
+ ** PRAGMA busy_timeout
+ ** PRAGMA busy_timeout = N
+ **
+ ** Call sqlite3_busy_timeout(db, N). Return the current timeout value
+ ** if one is set. If no busy handler or a different busy handler is set
+ ** then 0 is returned. Setting the busy_timeout to 0 or negative
+ ** disables the timeout.
+ */
+ if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){
+ if( zRight ){
+ sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
+ }
+ returnSingleInt(pParse, "timeout", db->busyTimeout);
+ }else
+
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
@@ -92620,13 +93766,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", SQLITE_STATIC);
for(i=0; inDb; i++){
Btree *pBt;
- Pager *pPager;
const char *zState = "unknown";
int j;
if( db->aDb[i].zName==0 ) continue;
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC);
pBt = db->aDb[i].pBt;
- if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
+ if( pBt==0 || sqlite3BtreePager(pBt)==0 ){
zState = "closed";
}else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
@@ -92663,7 +93808,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else
#endif
#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
- if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
+ if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
#ifdef SQLITE_HAS_CODEC
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
sqlite3_activate_see(&zRight[4]);
@@ -92835,7 +93980,9 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
int rc;
int i;
+#ifndef SQLITE_OMIT_DEPRECATED
int size;
+#endif
Table *pTab;
Db *pDb;
char const *azArg[4];
@@ -92878,7 +94025,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
/* zMasterSchema and zInitScript are set to point at the master schema
** and initialisation script appropriate for the database being
- ** initialised. zMasterName is the name of the master table.
+ ** initialized. zMasterName is the name of the master table.
*/
if( !OMIT_TEMPDB && iDb==1 ){
zMasterSchema = temp_master_schema;
@@ -92958,11 +94105,15 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
*/
if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */
if( iDb==0 ){
+#ifndef SQLITE_OMIT_UTF16
u8 encoding;
/* If opening the main database, set ENC(db). */
encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
if( encoding==0 ) encoding = SQLITE_UTF8;
ENC(db) = encoding;
+#else
+ ENC(db) = SQLITE_UTF8;
+#endif
}else{
/* If opening an attached database, the encoding much match ENC(db) */
if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
@@ -93099,7 +94250,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
}
}
- /* Once all the other databases have been initialised, load the schema
+ /* Once all the other databases have been initialized, load the schema
** for the TEMP database. This is loaded last, as the TEMP database
** schema may contain references to objects in other databases.
*/
@@ -93122,7 +94273,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
}
/*
-** This routine is a no-op if the database schema is already initialised.
+** This routine is a no-op if the database schema is already initialized.
** Otherwise, the schema is loaded. An error code is returned.
*/
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){
@@ -93620,7 +94771,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
ExprList *pGroupBy, /* the GROUP BY clause */
Expr *pHaving, /* the HAVING clause */
ExprList *pOrderBy, /* the ORDER BY clause */
- int isDistinct, /* true if the DISTINCT keyword is present */
+ u16 selFlags, /* Flag parameters, such as SF_Distinct */
Expr *pLimit, /* LIMIT value. NULL means not used */
Expr *pOffset /* OFFSET value. NULL means no offset */
){
@@ -93644,7 +94795,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy;
- pNew->selFlags = isDistinct ? SF_Distinct : 0;
+ pNew->selFlags = selFlags;
pNew->op = TK_SELECT;
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
@@ -94090,6 +95241,19 @@ static int checkForMultiColumnSelectError(
}
#endif
+/*
+** An instance of the following object is used to record information about
+** how to process the DISTINCT keyword, to simplify passing that information
+** into the selectInnerLoop() routine.
+*/
+typedef struct DistinctCtx DistinctCtx;
+struct DistinctCtx {
+ u8 isTnct; /* True if the DISTINCT keyword is present */
+ u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
+ int tabTnct; /* Ephemeral table used for DISTINCT processing */
+ int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
+};
+
/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
@@ -94106,7 +95270,7 @@ static void selectInnerLoop(
int srcTab, /* Pull data from this table */
int nColumn, /* Number of columns in the source table */
ExprList *pOrderBy, /* If not NULL, sort results using this key */
- int distinct, /* If >=0, make sure results are distinct */
+ DistinctCtx *pDistinct, /* If not NULL, info on how to process DISTINCT */
SelectDest *pDest, /* How to dispose of the results */
int iContinue, /* Jump here to continue with next row */
int iBreak /* Jump here to break out of the inner loop */
@@ -94122,7 +95286,7 @@ static void selectInnerLoop(
assert( v );
if( NEVER(v==0) ) return;
assert( pEList!=0 );
- hasDistinct = distinct>=0;
+ hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
if( pOrderBy==0 && !hasDistinct ){
codeOffset(v, p, iContinue);
}
@@ -94162,7 +95326,55 @@ static void selectInnerLoop(
if( hasDistinct ){
assert( pEList!=0 );
assert( pEList->nExpr==nColumn );
- codeDistinct(pParse, distinct, iContinue, nColumn, regResult);
+ switch( pDistinct->eTnctType ){
+ case WHERE_DISTINCT_ORDERED: {
+ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
+ int iJump; /* Jump destination */
+ int regPrev; /* Previous row content */
+
+ /* Allocate space for the previous row */
+ regPrev = pParse->nMem+1;
+ pParse->nMem += nColumn;
+
+ /* Change the OP_OpenEphemeral coded earlier to an OP_Null
+ ** sets the MEM_Cleared bit on the first register of the
+ ** previous value. This will cause the OP_Ne below to always
+ ** fail on the first iteration of the loop even if the first
+ ** row is all NULLs.
+ */
+ sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
+ pOp = sqlite3VdbeGetOp(v, pDistinct->addrTnct);
+ pOp->opcode = OP_Null;
+ pOp->p1 = 1;
+ pOp->p2 = regPrev;
+
+ iJump = sqlite3VdbeCurrentAddr(v) + nColumn;
+ for(i=0; ia[i].pExpr);
+ if( iaddrTnct);
+ break;
+ }
+
+ default: {
+ assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
+ codeDistinct(pParse, pDistinct->tabTnct, iContinue, nColumn, regResult);
+ break;
+ }
+ }
if( pOrderBy==0 ){
codeOffset(v, p, iContinue);
}
@@ -94220,7 +95432,8 @@ static void selectInnerLoop(
*/
case SRT_Set: {
assert( nColumn==1 );
- p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
+ pDest->affSdst =
+ sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
if( pOrderBy ){
/* At first glance you would think we could optimize out the
** ORDER BY in this case since the order of entries in the set
@@ -94229,7 +95442,7 @@ static void selectInnerLoop(
pushOntoSorter(pParse, pOrderBy, p, regResult);
}else{
int r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
sqlite3ReleaseTempReg(pParse, r1);
@@ -94496,7 +95709,8 @@ static void generateSortTail(
#ifndef SQLITE_OMIT_SUBQUERY
case SRT_Set: {
assert( nColumn==1 );
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid,
+ &pDest->affSdst, 1);
sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
break;
@@ -94811,7 +96025,7 @@ static void generateColumnNames(
static int selectColumnsFromExprList(
Parse *pParse, /* Parsing context */
ExprList *pEList, /* Expr list from which to derive column names */
- int *pnCol, /* Write the number of columns here */
+ i16 *pnCol, /* Write the number of columns here */
Column **paCol /* Write the new column list here */
){
sqlite3 *db = pParse->db; /* Database connection */
@@ -94837,9 +96051,7 @@ static int selectColumnsFromExprList(
for(i=0, pCol=aCol; ia[i].pExpr;
- assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
- || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
+ p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS " phrase, use as the name */
zName = sqlite3DbStrDup(db, zName);
@@ -94877,6 +96089,9 @@ static int selectColumnsFromExprList(
for(j=cnt=0; j1 && sqlite3Isdigit(zName[k]); k--){}
+ if( zName[k]==':' ) nName = k;
zName[nName] = 0;
zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
sqlite3DbFree(db, zName);
@@ -95208,6 +96423,8 @@ static int multiSelect(
int addr = 0;
int nLimit;
assert( !pPrior->pLimit );
+ pPrior->iLimit = p->iLimit;
+ pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
pPrior->pOffset = p->pOffset;
explainSetInteger(iSub1, pParse->iNextSelectId);
@@ -95333,7 +96550,7 @@ static int multiSelect(
sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak);
iStart = sqlite3VdbeCurrentAddr(v);
selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
- 0, -1, &dest, iCont, iBreak);
+ 0, 0, &dest, iCont, iBreak);
sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart);
sqlite3VdbeResolveLabel(v, iBreak);
@@ -95411,7 +96628,7 @@ static int multiSelect(
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
sqlite3ReleaseTempReg(pParse, r1);
selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
- 0, -1, &dest, iCont, iBreak);
+ 0, 0, &dest, iCont, iBreak);
sqlite3VdbeResolveLabel(v, iCont);
sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart);
sqlite3VdbeResolveLabel(v, iBreak);
@@ -95457,6 +96674,7 @@ static int multiSelect(
*apColl = db->pDfltColl;
}
}
+ pKeyInfo->aSortOrder = (u8*)apColl;
for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
for(i=0; i<2; i++){
@@ -95530,7 +96748,7 @@ static int generateOutputSubroutine(
(char*)pKeyInfo, p4type);
sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
sqlite3VdbeJumpHere(v, j1);
- sqlite3ExprCodeCopy(pParse, pIn->iSdst, regPrev+1, pIn->nSdst);
+ sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
}
if( pParse->db->mallocFailed ) return 0;
@@ -95565,10 +96783,10 @@ static int generateOutputSubroutine(
case SRT_Set: {
int r1;
assert( pIn->nSdst==1 );
- p->affinity =
+ pDest->affSdst =
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &p->affinity, 1);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1);
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
sqlite3ReleaseTempReg(pParse, r1);
@@ -95834,12 +97052,13 @@ static int multiSelectOrderBy(
for(i=0; ia[i].pExpr;
- if( pTerm->flags & EP_ExpCollate ){
- pColl = pTerm->pColl;
+ if( pTerm->flags & EP_Collate ){
+ pColl = sqlite3ExprCollSeq(pParse, pTerm);
}else{
pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
- pTerm->flags |= EP_ExpCollate;
- pTerm->pColl = pColl;
+ if( pColl==0 ) pColl = db->pDfltColl;
+ pOrderBy->a[i].pExpr =
+ sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
}
pKeyMerge->aColl[i] = pColl;
pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
@@ -95863,7 +97082,8 @@ static int multiSelectOrderBy(
}else{
int nExpr = p->pEList->nExpr;
assert( nOrderBy>=nExpr || db->mallocFailed );
- regPrev = sqlite3GetTempRange(pParse, nExpr+1);
+ regPrev = pParse->nMem+1;
+ pParse->nMem += nExpr+1;
sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
pKeyDup = sqlite3DbMallocZero(db,
sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
@@ -96042,14 +97262,9 @@ static int multiSelectOrderBy(
sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy,
(char*)pKeyMerge, P4_KEYINFO_HANDOFF);
+ sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
- /* Release temporary registers
- */
- if( regPrev ){
- sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1);
- }
-
/* Jump to the this point in order to terminate the query.
*/
sqlite3VdbeResolveLabel(v, labelEnd);
@@ -96109,9 +97324,6 @@ static Expr *substExpr(
assert( pEList!=0 && pExpr->iColumnnExpr );
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
- if( pNew && pExpr->pColl ){
- pNew->pColl = pExpr->pColl;
- }
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
}
@@ -96310,7 +97522,7 @@ static int flattenSubquery(
*/
assert( p!=0 );
assert( p->pPrior==0 ); /* Unable to flatten compound queries */
- if( db->flags & SQLITE_QueryFlattener ) return 0;
+ if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
pSrc = p->pSrc;
assert( pSrc && iFrom>=0 && iFromnSrc );
pSubitem = &pSrc->a[iFrom];
@@ -96464,12 +97676,15 @@ static int flattenSubquery(
Select *pNew;
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
+ Expr *pOffset = p->pOffset;
Select *pPrior = p->pPrior;
p->pOrderBy = 0;
p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
+ p->pOffset = 0;
pNew = sqlite3SelectDup(db, p, 0);
+ p->pOffset = pOffset;
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->pSrc = pSrc;
@@ -96599,10 +97814,9 @@ static int flattenSubquery(
pList = pParent->pEList;
for(i=0; inExpr; i++){
if( pList->a[i].zName==0 ){
- const char *zSpan = pList->a[i].zSpan;
- if( ALWAYS(zSpan) ){
- pList->a[i].zName = sqlite3DbStrDup(db, zSpan);
- }
+ char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan);
+ sqlite3Dequote(zName);
+ pList->a[i].zName = zName;
}
}
substExprList(db, pParent->pEList, iParent, pSub->pEList);
@@ -96663,34 +97877,43 @@ static int flattenSubquery(
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
-** Analyze the SELECT statement passed as an argument to see if it
-** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if
-** it is, or 0 otherwise. At present, a query is considered to be
-** a min()/max() query if:
+** Based on the contents of the AggInfo structure indicated by the first
+** argument, this function checks if the following are true:
**
-** 1. There is a single object in the FROM clause.
+** * the query contains just a single aggregate function,
+** * the aggregate function is either min() or max(), and
+** * the argument to the aggregate function is a column value.
**
-** 2. There is a single expression in the result set, and it is
-** either min(x) or max(x), where x is a column reference.
+** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
+** is returned as appropriate. Also, *ppMinMax is set to point to the
+** list of arguments passed to the aggregate before returning.
+**
+** Or, if the conditions above are not met, *ppMinMax is set to 0 and
+** WHERE_ORDERBY_NORMAL is returned.
*/
-static u8 minMaxQuery(Select *p){
- Expr *pExpr;
- ExprList *pEList = p->pEList;
+static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
+ int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
- if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
- pExpr = pEList->a[0].pExpr;
- if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
- if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0;
- pEList = pExpr->x.pList;
- if( pEList==0 || pEList->nExpr!=1 ) return 0;
- if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
- if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){
- return WHERE_ORDERBY_MIN;
- }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
- return WHERE_ORDERBY_MAX;
+ *ppMinMax = 0;
+ if( pAggInfo->nFunc==1 ){
+ Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
+ ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */
+
+ assert( pExpr->op==TK_AGG_FUNCTION );
+ if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
+ const char *zFunc = pExpr->u.zToken;
+ if( sqlite3StrICmp(zFunc, "min")==0 ){
+ eRet = WHERE_ORDERBY_MIN;
+ *ppMinMax = pEList;
+ }else if( sqlite3StrICmp(zFunc, "max")==0 ){
+ eRet = WHERE_ORDERBY_MAX;
+ *ppMinMax = pEList;
+ }
+ }
}
- return WHERE_ORDERBY_NORMAL;
+
+ assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
+ return eRet;
}
/*
@@ -96785,14 +98008,16 @@ static int selectExpander(Walker *pWalker, Select *p){
ExprList *pEList;
struct SrcList_item *pFrom;
sqlite3 *db = pParse->db;
+ Expr *pE, *pRight, *pExpr;
+ u16 selFlags = p->selFlags;
+ p->selFlags |= SF_Expanded;
if( db->mallocFailed ){
return WRC_Abort;
}
- if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
+ if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){
return WRC_Prune;
}
- p->selFlags |= SF_Expanded;
pTabList = p->pSrc;
pEList = p->pEList;
@@ -96833,9 +98058,14 @@ static int selectExpander(Walker *pWalker, Select *p){
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
- pFrom->pTab = pTab =
- sqlite3LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
+ pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
+ if( pTab->nRef==0xffff ){
+ sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
+ pTab->zName);
+ pFrom->pTab = 0;
+ return WRC_Abort;
+ }
pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
if( pTab->pSelect || IsVirtual(pTab) ){
@@ -96871,7 +98101,7 @@ static int selectExpander(Walker *pWalker, Select *p){
** that need expanding.
*/
for(k=0; knExpr; k++){
- Expr *pE = pEList->a[k].pExpr;
+ pE = pEList->a[k].pExpr;
if( pE->op==TK_ALL ) break;
assert( pE->op!=TK_DOT || pE->pRight!=0 );
assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
@@ -96889,10 +98119,18 @@ static int selectExpander(Walker *pWalker, Select *p){
int longNames = (flags & SQLITE_FullColNames)!=0
&& (flags & SQLITE_ShortColNames)==0;
+ /* When processing FROM-clause subqueries, it is always the case
+ ** that full_column_names=OFF and short_column_names=ON. The
+ ** sqlite3ResultSetOfSelect() routine makes it so. */
+ assert( (p->selFlags & SF_NestedFrom)==0
+ || ((flags & SQLITE_FullColNames)==0 &&
+ (flags & SQLITE_ShortColNames)!=0) );
+
for(k=0; knExpr; k++){
- Expr *pE = a[k].pExpr;
- assert( pE->op!=TK_DOT || pE->pRight!=0 );
- if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
+ pE = a[k].pExpr;
+ pRight = pE->pRight;
+ assert( pE->op!=TK_DOT || pRight!=0 );
+ if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
/* This particular expression does not need to be expanded.
*/
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
@@ -96907,32 +98145,43 @@ static int selectExpander(Walker *pWalker, Select *p){
/* This expression is a "*" or a "TABLE.*" and needs to be
** expanded. */
int tableSeen = 0; /* Set to 1 when TABLE matches */
- char *zTName; /* text of name of TABLE */
+ char *zTName = 0; /* text of name of TABLE */
if( pE->op==TK_DOT ){
assert( pE->pLeft!=0 );
assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
zTName = pE->pLeft->u.zToken;
- }else{
- zTName = 0;
}
for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){
Table *pTab = pFrom->pTab;
+ Select *pSub = pFrom->pSelect;
char *zTabName = pFrom->zAlias;
+ const char *zSchemaName = 0;
+ int iDb;
if( zTabName==0 ){
zTabName = pTab->zName;
}
if( db->mallocFailed ) break;
- if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
- continue;
+ if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
+ pSub = 0;
+ if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+ continue;
+ }
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
}
- tableSeen = 1;
for(j=0; jnCol; j++){
- Expr *pExpr, *pRight;
char *zName = pTab->aCol[j].zName;
char *zColname; /* The computed column name */
char *zToFree; /* Malloced string that needs to be freed */
Token sColname; /* Computed column name as a token */
+ assert( zName );
+ if( zTName && pSub
+ && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
+ ){
+ continue;
+ }
+
/* If a column is marked as 'hidden' (currently only possible
** for virtual tables), do not include it in the expanded
** result-set list.
@@ -96941,6 +98190,7 @@ static int selectExpander(Walker *pWalker, Select *p){
assert(IsVirtual(pTab));
continue;
}
+ tableSeen = 1;
if( i>0 && zTName==0 ){
if( (pFrom->jointype & JT_NATURAL)!=0
@@ -96963,6 +98213,10 @@ static int selectExpander(Walker *pWalker, Select *p){
Expr *pLeft;
pLeft = sqlite3Expr(db, TK_ID, zTabName);
pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ if( zSchemaName ){
+ pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
+ }
if( longNames ){
zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
zToFree = zColname;
@@ -96974,6 +98228,18 @@ static int selectExpander(Walker *pWalker, Select *p){
sColname.z = zColname;
sColname.n = sqlite3Strlen30(zColname);
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
+ if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
+ struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+ if( pSub ){
+ pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
+ testcase( pX->zSpan==0 );
+ }else{
+ pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
+ zSchemaName, zTabName, zColname);
+ testcase( pX->zSpan==0 );
+ }
+ pX->bSpanIsTab = 1;
+ }
sqlite3DbFree(db, zToFree);
}
}
@@ -97112,6 +98378,7 @@ SQLITE_PRIVATE void sqlite3SelectPrep(
sqlite3 *db;
if( NEVER(p==0) ) return;
db = pParse->db;
+ if( db->mallocFailed ) return;
if( p->selFlags & SF_HasTypeInfo ) return;
sqlite3SelectExpand(pParse, p);
if( pParse->nErr || db->mallocFailed ) return;
@@ -97350,11 +98617,9 @@ SQLITE_PRIVATE int sqlite3Select(
ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */
ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */
Expr *pHaving; /* The HAVING clause. May be NULL */
- int isDistinct; /* True if the DISTINCT keyword is present */
- int distinct; /* Table to use for the distinct set */
int rc = 1; /* Value to return from this function */
int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
- int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
+ DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
sqlite3 *db; /* The database connection */
@@ -97414,8 +98679,17 @@ SQLITE_PRIVATE int sqlite3Select(
int isAggSub;
if( pSub==0 ) continue;
+
+ /* Sometimes the code for a subquery will be generated more than
+ ** once, if the subquery is part of the WHERE clause in a LEFT JOIN,
+ ** for example. In that case, do not regenerate the code to manifest
+ ** a view or the co-routine to implement a view. The first instance
+ ** is sufficient, though the subroutine to manifest the view does need
+ ** to be invoked again. */
if( pItem->addrFillSub ){
- sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+ if( pItem->viaCoroutine==0 ){
+ sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub);
+ }
continue;
}
@@ -97436,6 +98710,44 @@ SQLITE_PRIVATE int sqlite3Select(
p->selFlags |= SF_Aggregate;
}
i = -1;
+ }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0
+ && OptimizationEnabled(db, SQLITE_SubqCoroutine)
+ ){
+ /* Implement a co-routine that will return a single row of the result
+ ** set on each invocation.
+ */
+ int addrTop;
+ int addrEof;
+ pItem->regReturn = ++pParse->nMem;
+ addrEof = ++pParse->nMem;
+ /* Before coding the OP_Goto to jump to the start of the main routine,
+ ** ensure that the jump to the verify-schema routine has already
+ ** been coded. Otherwise, the verify-schema would likely be coded as
+ ** part of the co-routine. If the main routine then accessed the
+ ** database before invoking the co-routine for the first time (for
+ ** example to initialize a LIMIT register from a sub-select), it would
+ ** be doing so without having verified the schema version and obtained
+ ** the required db locks. See ticket d6b36be38. */
+ sqlite3CodeVerifySchema(pParse, -1);
+ sqlite3VdbeAddOp0(v, OP_Goto);
+ addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
+ sqlite3VdbeChangeP5(v, 1);
+ VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
+ pItem->addrFillSub = addrTop;
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof);
+ sqlite3VdbeChangeP5(v, 1);
+ sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
+ explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
+ sqlite3Select(pParse, pSub, &dest);
+ pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
+ pItem->viaCoroutine = 1;
+ sqlite3VdbeChangeP2(v, addrTop, dest.iSdst);
+ sqlite3VdbeChangeP3(v, addrTop, dest.nSdst);
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof);
+ sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn);
+ VdbeComment((v, "end %s", pItem->pTab->zName));
+ sqlite3VdbeJumpHere(v, addrTop-1);
+ sqlite3ClearTempRegCache(pParse);
}else{
/* Generate a subroutine that will fill an ephemeral table with
** the content of this subquery. pItem->addrFillSub will point
@@ -97480,7 +98792,7 @@ SQLITE_PRIVATE int sqlite3Select(
pWhere = p->pWhere;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
- isDistinct = (p->selFlags & SF_Distinct)!=0;
+ sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* If there is are a sequence of queries, do the earlier ones first.
@@ -97515,7 +98827,7 @@ SQLITE_PRIVATE int sqlite3Select(
** to disable this optimization for testing purposes.
*/
if( sqlite3ExprListCompare(p->pGroupBy, pOrderBy)==0
- && (db->flags & SQLITE_GroupByOrder)==0 ){
+ && OptimizationEnabled(db, SQLITE_GroupByOrder) ){
pOrderBy = 0;
}
@@ -97541,6 +98853,10 @@ SQLITE_PRIVATE int sqlite3Select(
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
pOrderBy = 0;
+ /* Notice that even thought SF_Distinct has been cleared from p->selFlags,
+ ** the sDistinct.isTnct is still set. Hence, isTnct represents the
+ ** original setting of the SF_Distinct flag, not the current setting */
+ assert( sDistinct.isTnct );
}
/* If there is an ORDER BY clause, then this sorting
@@ -97581,24 +98897,27 @@ SQLITE_PRIVATE int sqlite3Select(
/* Open a virtual index to use for the distinct set.
*/
if( p->selFlags & SF_Distinct ){
- KeyInfo *pKeyInfo;
- distinct = pParse->nTab++;
- pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
- addrDistinctIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
- (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
+ sDistinct.tabTnct = pParse->nTab++;
+ sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ sDistinct.tabTnct, 0, 0,
+ (char*)keyInfoFromExprList(pParse, p->pEList),
+ P4_KEYINFO_HANDOFF);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
+ sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
}else{
- distinct = addrDistinctIndex = -1;
+ sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
}
- /* Aggregate and non-aggregate queries are handled differently */
if( !isAgg && pGroupBy==0 ){
- ExprList *pDist = (isDistinct ? p->pEList : 0);
+ /* No aggregate functions and no GROUP BY clause */
+ ExprList *pDist = (sDistinct.isTnct ? p->pEList : 0);
/* Begin the database scan. */
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0,0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0,0);
if( pWInfo==0 ) goto select_end;
if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
+ if( pWInfo->eDistinct ) sDistinct.eTnctType = pWInfo->eDistinct;
+ if( pOrderBy && pWInfo->nOBSat==pOrderBy->nExpr ) pOrderBy = 0;
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -97609,59 +98928,16 @@ SQLITE_PRIVATE int sqlite3Select(
p->addrOpenEphm[2] = -1;
}
- if( pWInfo->eDistinct ){
- VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
-
- assert( addrDistinctIndex>=0 );
- pOp = sqlite3VdbeGetOp(v, addrDistinctIndex);
-
- assert( isDistinct );
- assert( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
- || pWInfo->eDistinct==WHERE_DISTINCT_UNIQUE
- );
- distinct = -1;
- if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED ){
- int iJump;
- int iExpr;
- int iFlag = ++pParse->nMem;
- int iBase = pParse->nMem+1;
- int iBase2 = iBase + pEList->nExpr;
- pParse->nMem += (pEList->nExpr*2);
-
- /* Change the OP_OpenEphemeral coded earlier to an OP_Integer. The
- ** OP_Integer initializes the "first row" flag. */
- pOp->opcode = OP_Integer;
- pOp->p1 = 1;
- pOp->p2 = iFlag;
-
- sqlite3ExprCodeExprList(pParse, pEList, iBase, 1);
- iJump = sqlite3VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
- sqlite3VdbeAddOp2(v, OP_If, iFlag, iJump-1);
- for(iExpr=0; iExprnExpr; iExpr++){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
- sqlite3VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
- sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
- sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
- }
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iContinue);
-
- sqlite3VdbeAddOp2(v, OP_Integer, 0, iFlag);
- assert( sqlite3VdbeCurrentAddr(v)==iJump );
- sqlite3VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr);
- }else{
- pOp->opcode = OP_Noop;
- }
- }
-
/* Use the standard inner loop. */
- selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest,
+ selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, &sDistinct, pDest,
pWInfo->iContinue, pWInfo->iBreak);
/* End the database scan loop.
*/
sqlite3WhereEnd(pWInfo);
}else{
- /* This is the processing for aggregate queries */
+ /* This case when there exist aggregate functions or a GROUP BY clause
+ ** or both */
NameContext sNC; /* Name context for processing aggregate information */
int iAMem; /* First Mem address for storing current GROUP BY */
int iBMem; /* First Mem address for previous GROUP BY */
@@ -97769,14 +99045,13 @@ SQLITE_PRIVATE int sqlite3Select(
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0, 0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0);
if( pWInfo==0 ) goto select_end;
- if( pGroupBy==0 ){
+ if( pWInfo->nOBSat==pGroupBy->nExpr ){
/* The optimizer is able to deliver rows in group by order so
** we do not have to sort. The OP_OpenEphemeral table will be
** cancelled later because we still need to use the pKeyInfo
*/
- pGroupBy = p->pGroupBy;
groupBySort = 0;
}else{
/* Rows are coming out in undetermined order. We have to push
@@ -97790,7 +99065,8 @@ SQLITE_PRIVATE int sqlite3Select(
int nGroupBy;
explainTempTable(pParse,
- isDistinct && !(p->selFlags&SF_Distinct)?"DISTINCT":"GROUP BY");
+ (sDistinct.isTnct && (p->selFlags&SF_Distinct)==0) ?
+ "DISTINCT" : "GROUP BY");
groupBySort = 1;
nGroupBy = pGroupBy->nExpr;
@@ -97922,7 +99198,7 @@ SQLITE_PRIVATE int sqlite3Select(
finalizeAggFunctions(pParse, &sAggInfo);
sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL);
selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
- distinct, pDest,
+ &sDistinct, pDest,
addrOutputRow+1, addrSetAbort);
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
VdbeComment((v, "end groupby result generator"));
@@ -98010,7 +99286,7 @@ SQLITE_PRIVATE int sqlite3Select(
** value of x, the only row required).
**
** A special flag must be passed to sqlite3WhereBegin() to slightly
- ** modify behaviour as follows:
+ ** modify behavior as follows:
**
** + If the query is a "SELECT min(x)", then the loop coded by
** where.c should not iterate over any values with a NULL value
@@ -98022,10 +99298,17 @@ SQLITE_PRIVATE int sqlite3Select(
** Refer to code and comments in where.c for details.
*/
ExprList *pMinMax = 0;
- u8 flag = minMaxQuery(p);
+ u8 flag = WHERE_ORDERBY_NORMAL;
+
+ assert( p->pGroupBy==0 );
+ assert( flag==0 );
+ if( p->pHaving==0 ){
+ flag = minMaxQuery(&sAggInfo, &pMinMax);
+ }
+ assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
+
if( flag ){
- assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
- pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
+ pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
pDel = pMinMax;
if( pMinMax && !db->mallocFailed ){
pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
@@ -98038,13 +99321,14 @@ SQLITE_PRIVATE int sqlite3Select(
** of output.
*/
resetAccumulator(pParse, &sAggInfo);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax,0,flag,0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDel);
goto select_end;
}
updateAccumulator(pParse, &sAggInfo);
- if( !pMinMax && flag ){
+ assert( pMinMax==0 || pMinMax->nExpr==1 );
+ if( pWInfo->nOBSat>0 ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
VdbeComment((v, "%s() by index",
(flag==WHERE_ORDERBY_MIN?"min":"max")));
@@ -98055,7 +99339,7 @@ SQLITE_PRIVATE int sqlite3Select(
pOrderBy = 0;
sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL);
- selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1,
+ selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, 0,
pDest, addrEnd, addrEnd);
sqlite3ExprListDelete(db, pDel);
}
@@ -98063,7 +99347,7 @@ SQLITE_PRIVATE int sqlite3Select(
} /* endif aggregate query */
- if( distinct>=0 ){
+ if( sDistinct.eTnctType==WHERE_DISTINCT_UNORDERED ){
explainTempTable(pParse, "DISTINCT");
}
@@ -98180,7 +99464,10 @@ SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
sqlite3ExplainPrintf(pVdbe, "(null-select)");
return;
}
- while( p->pPrior ) p = p->pPrior;
+ while( p->pPrior ){
+ p->pPrior->pNext = p;
+ p = p->pPrior;
+ }
sqlite3ExplainPush(pVdbe);
while( p ){
explainOneSelect(pVdbe, p);
@@ -99128,6 +100415,15 @@ static int codeTriggerProgram(
*/
pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
+ /* Clear the cookieGoto flag. When coding triggers, the cookieGoto
+ ** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
+ ** that it is not safe to refactor constants (this happens after the
+ ** start of the first loop in the SQL statement is coded - at that
+ ** point code may be conditionally executed, so it is no longer safe to
+ ** initialize constant register values). */
+ assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
+ pParse->cookieGoto = 0;
+
switch( pStep->op ){
case TK_UPDATE: {
sqlite3Update(pParse,
@@ -99983,7 +101279,7 @@ SQLITE_PRIVATE void sqlite3Update(
/* The row-trigger may have deleted the row being updated. In this
** case, jump to the next row. No updates or AFTER triggers are
- ** required. This behaviour - what happens when the row being updated
+ ** required. This behavior - what happens when the row being updated
** is deleted or renamed by a BEFORE trigger - is left undefined in the
** documentation.
*/
@@ -100284,6 +101580,7 @@ SQLITE_PRIVATE void sqlite3Vacuum(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp2(v, OP_Vacuum, 0, 0);
+ sqlite3VdbeUsesBtree(v, 0);
}
return;
}
@@ -100812,7 +102109,7 @@ SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table *p){
if( p->azModuleArg ){
int i;
for(i=0; inModuleArg; i++){
- sqlite3DbFree(db, p->azModuleArg[i]);
+ if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
}
sqlite3DbFree(db, p->azModuleArg);
}
@@ -100872,7 +102169,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse(
pTable->tabFlags |= TF_Virtual;
pTable->nModuleArg = 0;
addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName));
- addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName));
+ addModuleArgument(db, pTable, 0);
addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName));
pParse->sNameToken.n = (int)(&pModuleName->z[pModuleName->n] - pName1->z);
@@ -101029,6 +102326,7 @@ static int vtabCallConstructor(
int nArg = pTab->nModuleArg;
char *zErr = 0;
char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
+ int iDb;
if( !zModuleName ){
return SQLITE_NOMEM;
@@ -101042,6 +102340,9 @@ static int vtabCallConstructor(
pVTable->db = db;
pVTable->pMod = pMod;
+ iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+ pTab->azModuleArg[1] = db->aDb[iDb].zName;
+
/* Invoke the virtual table constructor */
assert( &db->pVtabCtx );
assert( xConstruct );
@@ -101076,7 +102377,7 @@ static int vtabCallConstructor(
/* If everything went according to plan, link the new VTable structure
** into the linked list headed by pTab->pVTable. Then loop through the
** columns of the table to see if any of them contain the token "hidden".
- ** If so, set the Column.isHidden flag and remove the token from
+ ** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
** the type string. */
pVTable->pNext = pTab->pVTable;
pTab->pVTable = pVTable;
@@ -101107,7 +102408,7 @@ static int vtabCallConstructor(
assert(zType[i-1]==' ');
zType[i-1] = '\0';
}
- pTab->aCol[iCol].isHidden = 1;
+ pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
}
}
}
@@ -101668,9 +102969,10 @@ SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-SQLITE_PRIVATE int sqlite3WhereTrace = 0;
+/***/ int sqlite3WhereTrace = 0;
#endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
# define WHERETRACE(X) if(sqlite3WhereTrace) sqlite3DebugPrintf X
#else
# define WHERETRACE(X)
@@ -101742,8 +103044,8 @@ struct WhereTerm {
int leftCursor; /* Cursor number of X in "X " */
union {
int leftColumn; /* Column number of X in "X " */
- WhereOrInfo *pOrInfo; /* Extra information if eOperator==WO_OR */
- WhereAndInfo *pAndInfo; /* Extra information if eOperator==WO_AND */
+ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
+ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
} u;
u16 eOperator; /* A WO_xx value describing */
u8 wtFlags; /* TERM_xxx bit flags. See below */
@@ -101784,7 +103086,6 @@ struct WhereTerm {
struct WhereClause {
Parse *pParse; /* The parser context */
WhereMaskSet *pMaskSet; /* Mapping of table cursor numbers to bitmasks */
- Bitmask vmask; /* Bitmask identifying virtual table cursors */
WhereClause *pOuter; /* Outer conjunction */
u8 op; /* Split operator. TK_AND or TK_OR */
u16 wctrlFlags; /* Might include WHERE_AND_ONLY */
@@ -101871,6 +103172,7 @@ struct WhereCost {
#define WO_ISNULL 0x080
#define WO_OR 0x100 /* Two or more OR-connected terms */
#define WO_AND 0x200 /* Two or more AND-connected terms */
+#define WO_EQUIV 0x400 /* Of the form A==B, both columns */
#define WO_NOOP 0x800 /* This term does not restrict search space */
#define WO_ALL 0xfff /* Mask of all possible WO_* values */
@@ -101897,18 +103199,55 @@ struct WhereCost {
#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
-#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
+#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */
#define WHERE_TOP_LIMIT 0x00100000 /* xEXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and xrCostrCost ) return 1;
+ if( pProbe->rCost>pBaseline->rCost ) return 0;
+ if( pProbe->plan.nOBSat>pBaseline->plan.nOBSat ) return 1;
+ if( pProbe->plan.nRowplan.nRow ) return 1;
+ return 0;
+}
/*
** Initialize a preallocated WhereClause structure.
@@ -101925,7 +103264,6 @@ static void whereClauseInit(
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
- pWC->vmask = 0;
pWC->wctrlFlags = wctrlFlags;
}
@@ -102012,7 +103350,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
}
pTerm = &pWC->a[idx = pWC->nTerm++];
- pTerm->pExpr = p;
+ pTerm->pExpr = sqlite3ExprSkipCollate(p);
pTerm->wtFlags = wtFlags;
pTerm->pWC = pWC;
pTerm->iParent = -1;
@@ -102172,23 +103510,32 @@ static int allowedOp(int op){
** Commute a comparison operator. Expressions of the form "X op Y"
** are converted into "Y op X".
**
-** If a collation sequence is associated with either the left or right
+** If left/right precedence rules come into play when determining the
+** collating
** side of the comparison, it remains associated with the same side after
** the commutation. So "Y collate NOCASE op X" becomes
-** "X collate NOCASE op Y". This is because any collation sequence on
+** "X op Y". This is because any collation sequence on
** the left hand side of a comparison overrides any collation sequence
-** attached to the right. For the same reason the EP_ExpCollate flag
+** attached to the right. For the same reason the EP_Collate flag
** is not commuted.
*/
static void exprCommute(Parse *pParse, Expr *pExpr){
- u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
- u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
+ u16 expRight = (pExpr->pRight->flags & EP_Collate);
+ u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
- pExpr->pRight->pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
- pExpr->pLeft->pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- SWAP(CollSeq*,pExpr->pRight->pColl,pExpr->pLeft->pColl);
- pExpr->pRight->flags = (pExpr->pRight->flags & ~EP_ExpCollate) | expLeft;
- pExpr->pLeft->flags = (pExpr->pLeft->flags & ~EP_ExpCollate) | expRight;
+ if( expRight==expLeft ){
+ /* Either X and Y both have COLLATE operator or neither do */
+ if( expRight ){
+ /* Both X and Y have COLLATE operators. Make sure X is always
+ ** used by clearing the EP_Collate flag from Y. */
+ pExpr->pRight->flags &= ~EP_Collate;
+ }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
+ /* Neither X nor Y have COLLATE operators, but X has a non-default
+ ** collating sequence. So add the EP_Collate marker on X to cause
+ ** it to be searched first. */
+ pExpr->pLeft->flags |= EP_Collate;
+ }
+ }
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
if( pExpr->op>=TK_GT ){
assert( TK_LT==TK_GT+2 );
@@ -102229,6 +103576,23 @@ static u16 operatorMask(int op){
** where X is a reference to the iColumn of table iCur and is one of
** the WO_xx operator codes specified by the op parameter.
** Return a pointer to the term. Return 0 if not found.
+**
+** The term returned might by Y= if there is another constraint in
+** the WHERE clause that specifies that X=Y. Any such constraints will be
+** identified by the WO_EQUIV bit in the pTerm->eOperator field. The
+** aEquiv[] array holds X and all its equivalents, with each SQL variable
+** taking up two slots in aEquiv[]. The first slot is for the cursor number
+** and the second is for the column number. There are 22 slots in aEquiv[]
+** so that means we can look for X plus up to 10 other equivalent values.
+** Hence a search for X will return if X=A1 and A1=A2 and A2=A3
+** and ... and A9=A10 and A10=.
+**
+** If there are multiple terms in the WHERE clause of the form "X "
+** then try for the one with no dependencies on - in other words where
+** is a constant expression of some kind. Only return entries of
+** the form "X Y" where Y is a column in another table if no terms of
+** the form "X " exist. If no terms with a constant RHS
+** exist, try to return a term that does not use WO_EQUIV.
*/
static WhereTerm *findTerm(
WhereClause *pWC, /* The WHERE clause to be searched */
@@ -102238,45 +103602,85 @@ static WhereTerm *findTerm(
u32 op, /* Mask of WO_xx values describing operator */
Index *pIdx /* Must be compatible with this index, if not NULL */
){
- WhereTerm *pTerm;
- int k;
+ WhereTerm *pTerm; /* Term being examined as possible result */
+ WhereTerm *pResult = 0; /* The answer to return */
+ WhereClause *pWCOrig = pWC; /* Original pWC value */
+ int j, k; /* Loop counters */
+ Expr *pX; /* Pointer to an expression */
+ Parse *pParse; /* Parsing context */
+ int iOrigCol = iColumn; /* Original value of iColumn */
+ int nEquiv = 2; /* Number of entires in aEquiv[] */
+ int iEquiv = 2; /* Number of entries of aEquiv[] processed so far */
+ int aEquiv[22]; /* iCur,iColumn and up to 10 other equivalents */
+
assert( iCur>=0 );
- op &= WO_ALL;
- for(; pWC; pWC=pWC->pOuter){
- for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
- if( pTerm->leftCursor==iCur
- && (pTerm->prereqRight & notReady)==0
- && pTerm->u.leftColumn==iColumn
- && (pTerm->eOperator & op)!=0
- ){
- if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
- Expr *pX = pTerm->pExpr;
- CollSeq *pColl;
- char idxaff;
- int j;
- Parse *pParse = pWC->pParse;
-
- idxaff = pIdx->pTable->aCol[iColumn].affinity;
- if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
-
- /* Figure out the collation sequence required from an index for
- ** it to be useful for optimising expression pX. Store this
- ** value in variable pColl.
- */
- assert(pX->pLeft);
- pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
- assert(pColl || pParse->nErr);
-
- for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
- if( NEVER(j>=pIdx->nColumn) ) return 0;
+ aEquiv[0] = iCur;
+ aEquiv[1] = iColumn;
+ for(;;){
+ for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
+ for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
+ if( pTerm->leftCursor==iCur
+ && pTerm->u.leftColumn==iColumn
+ ){
+ if( (pTerm->prereqRight & notReady)==0
+ && (pTerm->eOperator & op & WO_ALL)!=0
+ ){
+ if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
+ CollSeq *pColl;
+ char idxaff;
+
+ pX = pTerm->pExpr;
+ pParse = pWC->pParse;
+ idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
+ if( !sqlite3IndexAffinityOk(pX, idxaff) ){
+ continue;
+ }
+
+ /* Figure out the collation sequence required from an index for
+ ** it to be useful for optimising expression pX. Store this
+ ** value in variable pColl.
+ */
+ assert(pX->pLeft);
+ pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
+ if( pColl==0 ) pColl = pParse->db->pDfltColl;
+
+ for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
+ if( NEVER(j>=pIdx->nColumn) ) return 0;
+ }
+ if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
+ continue;
+ }
+ }
+ if( pTerm->prereqRight==0 ){
+ pResult = pTerm;
+ goto findTerm_success;
+ }else if( pResult==0 ){
+ pResult = pTerm;
+ }
+ }
+ if( (pTerm->eOperator & WO_EQUIV)!=0
+ && nEquivpExpr->pRight);
+ assert( pX->op==TK_COLUMN );
+ for(j=0; jiTable && aEquiv[j+1]==pX->iColumn ) break;
+ }
+ if( j==nEquiv ){
+ aEquiv[j] = pX->iTable;
+ aEquiv[j+1] = pX->iColumn;
+ nEquiv += 2;
+ }
}
- if( pColl && sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
}
- return pTerm;
}
}
+ if( iEquiv>=nEquiv ) break;
+ iCur = aEquiv[iEquiv++];
+ iColumn = aEquiv[iEquiv++];
}
- return 0;
+findTerm_success:
+ return pResult;
}
/* Forward reference */
@@ -102462,7 +103866,7 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
**
** CASE 1:
**
-** If all subterms are of the form T.C=expr for some single column of C
+** If all subterms are of the form T.C=expr for some single column of C and
** a single table T (as shown in example B above) then create a new virtual
** term that is an equivalent IN expression. In other words, if the term
** being analyzed is:
@@ -102550,11 +103954,10 @@ static void exprAnalyzeOrTerm(
** Compute the set of tables that might satisfy cases 1 or 2.
*/
indexable = ~(Bitmask)0;
- chngToIN = ~(pWC->vmask);
+ chngToIN = ~(Bitmask)0;
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
WhereAndInfo *pAndInfo;
- assert( pOrTerm->eOperator==0 );
assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
chngToIN = 0;
pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
@@ -102593,7 +103996,7 @@ static void exprAnalyzeOrTerm(
b |= getMask(pMaskSet, pOther->leftCursor);
}
indexable &= b;
- if( pOrTerm->eOperator!=WO_EQ ){
+ if( (pOrTerm->eOperator & WO_EQ)==0 ){
chngToIN = 0;
}else{
chngToIN &= b;
@@ -102644,7 +104047,7 @@ static void exprAnalyzeOrTerm(
for(j=0; j<2 && !okToChngToIN; j++){
pOrTerm = pOrWc->a;
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
- assert( pOrTerm->eOperator==WO_EQ );
+ assert( pOrTerm->eOperator & WO_EQ );
pOrTerm->wtFlags &= ~TERM_OR_OK;
if( pOrTerm->leftCursor==iCursor ){
/* This is the 2-bit case and we are on the second iteration and
@@ -102670,7 +104073,7 @@ static void exprAnalyzeOrTerm(
/* No candidate table+column was found. This can only occur
** on the second iteration */
assert( j==1 );
- assert( (chngToIN&(chngToIN-1))==0 );
+ assert( IsPowerOfTwo(chngToIN) );
assert( chngToIN==getMask(pMaskSet, iCursor) );
break;
}
@@ -102680,7 +104083,7 @@ static void exprAnalyzeOrTerm(
** 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 );
+ assert( pOrTerm->eOperator & WO_EQ );
if( pOrTerm->leftCursor!=iCursor ){
pOrTerm->wtFlags &= ~TERM_OR_OK;
}else if( pOrTerm->u.leftColumn!=iColumn ){
@@ -102716,7 +104119,7 @@ static void exprAnalyzeOrTerm(
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
- assert( pOrTerm->eOperator==WO_EQ );
+ assert( pOrTerm->eOperator & WO_EQ );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
@@ -102746,7 +104149,6 @@ static void exprAnalyzeOrTerm(
}
#endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
-
/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in. The job of this routine is to analyze the
@@ -102789,6 +104191,7 @@ static void exprAnalyze(
pTerm = &pWC->a[idxTerm];
pMaskSet = pWC->pMaskSet;
pExpr = pTerm->pExpr;
+ assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
if( op==TK_IN ){
@@ -102814,17 +104217,19 @@ static void exprAnalyze(
pTerm->leftCursor = -1;
pTerm->iParent = -1;
pTerm->eOperator = 0;
- if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
- Expr *pLeft = pExpr->pLeft;
- Expr *pRight = pExpr->pRight;
+ if( allowedOp(op) ){
+ Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
+ Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
+ u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
if( pLeft->op==TK_COLUMN ){
pTerm->leftCursor = pLeft->iTable;
pTerm->u.leftColumn = pLeft->iColumn;
- pTerm->eOperator = operatorMask(op);
+ pTerm->eOperator = operatorMask(op) & opMask;
}
if( pRight && pRight->op==TK_COLUMN ){
WhereTerm *pNew;
Expr *pDup;
+ u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */
if( pTerm->leftCursor>=0 ){
int idxNew;
pDup = sqlite3ExprDup(db, pExpr, 0);
@@ -102839,18 +104244,25 @@ static void exprAnalyze(
pTerm = &pWC->a[idxTerm];
pTerm->nChild = 1;
pTerm->wtFlags |= TERM_COPIED;
+ if( pExpr->op==TK_EQ
+ && !ExprHasProperty(pExpr, EP_FromJoin)
+ && OptimizationEnabled(db, SQLITE_Transitive)
+ ){
+ pTerm->eOperator |= WO_EQUIV;
+ eExtraOp = WO_EQUIV;
+ }
}else{
pDup = pExpr;
pNew = pTerm;
}
exprCommute(pParse, pDup);
- pLeft = pDup->pLeft;
+ pLeft = sqlite3ExprSkipCollate(pDup->pLeft);
pNew->leftCursor = pLeft->iTable;
pNew->u.leftColumn = pLeft->iColumn;
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
- pNew->eOperator = operatorMask(pDup->op);
+ pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
}
}
@@ -102923,7 +104335,7 @@ static void exprAnalyze(
Expr *pNewExpr2;
int idxNew1;
int idxNew2;
- CollSeq *pColl; /* Collating sequence to use */
+ Token sCollSeqName; /* Name of collating sequence */
pLeft = pExpr->x.pList->a[1].pExpr;
pStr2 = sqlite3ExprDup(db, pStr1, 0);
@@ -102945,16 +104357,19 @@ static void exprAnalyze(
}
*pC = c + 1;
}
- pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
+ sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
+ sCollSeqName.n = 6;
+ pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
- sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
- pStr1, 0);
+ sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
+ pStr1, 0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew1==0 );
exprAnalyze(pSrc, pWC, idxNew1);
+ pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
- sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
- pStr2, 0);
+ sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
+ pStr2, 0);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew2==0 );
exprAnalyze(pSrc, pWC, idxNew2);
@@ -103051,25 +104466,6 @@ static void exprAnalyze(
pTerm->prereqRight |= extraRight;
}
-/*
-** Return TRUE if any of the expressions in pList->a[iFirst...] contain
-** a reference to any table other than the iBase table.
-*/
-static int referencesOtherTables(
- ExprList *pList, /* Search expressions in ths list */
- WhereMaskSet *pMaskSet, /* Mapping from tables to bitmaps */
- int iFirst, /* Be searching with the iFirst-th expression */
- int iBase /* Ignore references to this table */
-){
- Bitmask allowed = ~getMask(pMaskSet, iBase);
- while( iFirstnExpr ){
- if( (exprTableUsage(pMaskSet, pList->a[iFirst++].pExpr)&allowed)!=0 ){
- return 1;
- }
- }
- return 0;
-}
-
/*
** This function searches the expression list passed as the second argument
** for an expression of type TK_COLUMN that refers to the same column and
@@ -103091,12 +104487,12 @@ static int findIndexCol(
const char *zColl = pIdx->azColl[iCol];
for(i=0; inExpr; i++){
- Expr *p = pList->a[i].pExpr;
+ Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
if( p->op==TK_COLUMN
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, p);
+ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
return i;
}
@@ -103129,7 +104525,8 @@ static int isDistinctIndex(
Bitmask mask = 0; /* Mask of unaccounted for pDistinct exprs */
int i; /* Iterator variable */
- if( pIdx->zName==0 || pDistinct==0 || pDistinct->nExpr>=BMS ) return 0;
+ assert( pDistinct!=0 );
+ if( pIdx->zName==0 || pDistinct->nExpr>=BMS ) return 0;
testcase( pDistinct->nExpr==BMS-1 );
/* Loop through all the expressions in the distinct list. If any of them
@@ -103142,7 +104539,7 @@ static int isDistinctIndex(
*/
for(i=0; inExpr; i++){
WhereTerm *pTerm;
- Expr *p = pDistinct->a[i].pExpr;
+ Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
if( p->op!=TK_COLUMN ) return 0;
pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0);
if( pTerm ){
@@ -103194,7 +104591,7 @@ static int isDistinctRedundant(
** current SELECT is a correlated sub-query.
*/
for(i=0; inExpr; i++){
- Expr *p = pDistinct->a[i].pExpr;
+ Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
}
@@ -103231,165 +104628,6 @@ static int isDistinctRedundant(
return 0;
}
-/*
-** This routine decides if pIdx can be used to satisfy the ORDER BY
-** clause. If it can, it returns 1. If pIdx cannot satisfy the
-** ORDER BY clause, this routine returns 0.
-**
-** pOrderBy is an ORDER BY clause from a SELECT statement. pTab is the
-** left-most table in the FROM clause of that same SELECT statement and
-** the table has a cursor number of "base". pIdx is an index on pTab.
-**
-** nEqCol is the number of columns of pIdx that are used as equality
-** constraints. Any of these columns may be missing from the ORDER BY
-** clause and the match can still be a success.
-**
-** All terms of the ORDER BY that match against the index must be either
-** ASC or DESC. (Terms of the ORDER BY clause past the end of a UNIQUE
-** index do not need to satisfy this constraint.) The *pbRev value is
-** set to 1 if the ORDER BY clause is all DESC and it is set to 0 if
-** the ORDER BY clause is all ASC.
-*/
-static int isSortingIndex(
- Parse *pParse, /* Parsing context */
- WhereMaskSet *pMaskSet, /* Mapping from table cursor numbers to bitmaps */
- Index *pIdx, /* The index we are testing */
- int base, /* Cursor number for the table to be sorted */
- ExprList *pOrderBy, /* The ORDER BY clause */
- int nEqCol, /* Number of index columns with == constraints */
- int wsFlags, /* Index usages flags */
- int *pbRev /* Set to 1 if ORDER BY is DESC */
-){
- int i, j; /* Loop counters */
- int sortOrder = 0; /* XOR of index and ORDER BY sort direction */
- int nTerm; /* Number of ORDER BY terms */
- struct ExprList_item *pTerm; /* A term of the ORDER BY clause */
- sqlite3 *db = pParse->db;
-
- if( !pOrderBy ) return 0;
- if( wsFlags & WHERE_COLUMN_IN ) return 0;
- if( pIdx->bUnordered ) return 0;
-
- nTerm = pOrderBy->nExpr;
- assert( nTerm>0 );
-
- /* Argument pIdx must either point to a 'real' named index structure,
- ** or an index structure allocated on the stack by bestBtreeIndex() to
- ** represent the rowid index that is part of every table. */
- assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
-
- /* Match terms of the ORDER BY clause against columns of
- ** the index.
- **
- ** Note that indices have pIdx->nColumn regular columns plus
- ** one additional column containing the rowid. The rowid column
- ** of the index is also allowed to match against the ORDER BY
- ** clause.
- */
- for(i=j=0, pTerm=pOrderBy->a; jnColumn; i++){
- Expr *pExpr; /* The expression of the ORDER BY pTerm */
- CollSeq *pColl; /* The collating sequence of pExpr */
- int termSortOrder; /* Sort order for this term */
- int iColumn; /* The i-th column of the index. -1 for rowid */
- int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */
- const char *zColl; /* Name of the collating sequence for i-th index term */
-
- pExpr = pTerm->pExpr;
- if( pExpr->op!=TK_COLUMN || pExpr->iTable!=base ){
- /* Can not use an index sort on anything that is not a column in the
- ** left-most table of the FROM clause */
- break;
- }
- pColl = sqlite3ExprCollSeq(pParse, pExpr);
- if( !pColl ){
- pColl = db->pDfltColl;
- }
- if( pIdx->zName && inColumn ){
- iColumn = pIdx->aiColumn[i];
- if( iColumn==pIdx->pTable->iPKey ){
- iColumn = -1;
- }
- iSortOrder = pIdx->aSortOrder[i];
- zColl = pIdx->azColl[i];
- }else{
- iColumn = -1;
- iSortOrder = 0;
- zColl = pColl->zName;
- }
- if( pExpr->iColumn!=iColumn || sqlite3StrICmp(pColl->zName, zColl) ){
- /* Term j of the ORDER BY clause does not match column i of the index */
- if( inColumn ){
- /* Index column i is the rowid. All other terms match. */
- break;
- }else{
- /* If an index column fails to match and is not constrained by ==
- ** then the index cannot satisfy the ORDER BY constraint.
- */
- return 0;
- }
- }
- assert( pIdx->aSortOrder!=0 || iColumn==-1 );
- assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 );
- assert( iSortOrder==0 || iSortOrder==1 );
- termSortOrder = iSortOrder ^ pTerm->sortOrder;
- if( i>nEqCol ){
- if( termSortOrder!=sortOrder ){
- /* Indices can only be used if all ORDER BY terms past the
- ** equality constraints are all either DESC or ASC. */
- return 0;
- }
- }else{
- sortOrder = termSortOrder;
- }
- j++;
- pTerm++;
- if( iColumn<0 && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){
- /* If the indexed column is the primary key and everything matches
- ** so far and none of the ORDER BY terms to the right reference other
- ** tables in the join, then we are assured that the index can be used
- ** to sort because the primary key is unique and so none of the other
- ** columns will make any difference
- */
- j = nTerm;
- }
- }
-
- *pbRev = sortOrder!=0;
- if( j>=nTerm ){
- /* All terms of the ORDER BY clause are covered by this index so
- ** this index can be used for sorting. */
- return 1;
- }
- if( pIdx->onError!=OE_None && i==pIdx->nColumn
- && (wsFlags & WHERE_COLUMN_NULL)==0
- && !referencesOtherTables(pOrderBy, pMaskSet, j, base)
- ){
- Column *aCol = pIdx->pTable->aCol;
-
- /* All terms of this index match some prefix of the ORDER BY clause,
- ** the index is UNIQUE, and no terms on the tail of the ORDER BY
- ** refer to other tables in a join. So, assuming that the index entries
- ** visited contain no NULL values, then this index delivers rows in
- ** the required order.
- **
- ** It is not possible for any of the first nEqCol index fields to be
- ** NULL (since the corresponding "=" operator in the WHERE clause would
- ** not be true). So if all remaining index columns have NOT NULL
- ** constaints attached to them, we can be confident that the visited
- ** index entries are free of NULLs. */
- for(i=nEqCol; inColumn; i++){
- if( aCol[pIdx->aiColumn[i]].notNull==0 ) break;
- }
- return (i==pIdx->nColumn);
- }
- return 0;
-}
-
/*
** Prepare a crude estimate of the logarithm of the input value.
** The results need not be exact. This is only used for estimating
@@ -103454,9 +104692,7 @@ static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
/*
** Required because bestIndex() is called by bestOrClauseIndex()
*/
-static void bestIndex(
- Parse*, WhereClause*, struct SrcList_item*,
- Bitmask, Bitmask, ExprList*, WhereCost*);
+static void bestIndex(WhereBestIdx*);
/*
** This routine attempts to find an scanning strategy that can be used
@@ -103465,20 +104701,14 @@ static void bestIndex(
** The table associated with FROM clause term pSrc may be either a
** regular B-Tree table or a virtual table.
*/
-static void bestOrClauseIndex(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to search */
- Bitmask notReady, /* Mask of cursors not available for indexing */
- Bitmask notValid, /* Cursors not available for any purpose */
- ExprList *pOrderBy, /* The ORDER BY clause */
- WhereCost *pCost /* Lowest cost query plan */
-){
+static void bestOrClauseIndex(WhereBestIdx *p){
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
- const int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
+ WhereClause *pWC = p->pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
+ const int iCur = pSrc->iCursor; /* The cursor of the table */
const Bitmask maskSrc = getMask(pWC->pMaskSet, iCur); /* Bitmask for pSrc */
WhereTerm * const pWCEnd = &pWC->a[pWC->nTerm]; /* End of pWC->a[] */
- WhereTerm *pTerm; /* A single term of the WHERE clause */
+ WhereTerm *pTerm; /* A single term of the WHERE clause */
/* The OR-clause optimization is disallowed if the INDEXED BY or
** NOT INDEXED clauses are used or if the WHERE_AND_ONLY bit is set. */
@@ -103491,8 +104721,8 @@ static void bestOrClauseIndex(
/* Search the WHERE clause terms for a usable WO_OR term. */
for(pTerm=pWC->a; pTermeOperator==WO_OR
- && ((pTerm->prereqAll & ~maskSrc) & notReady)==0
+ if( (pTerm->eOperator & WO_OR)!=0
+ && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
&& (pTerm->u.pOrInfo->indexable & maskSrc)!=0
){
WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
@@ -103502,15 +104732,19 @@ static void bestOrClauseIndex(
double rTotal = 0;
double nRow = 0;
Bitmask used = 0;
+ WhereBestIdx sBOI;
+ sBOI = *p;
+ sBOI.pOrderBy = 0;
+ sBOI.pDistinct = 0;
+ sBOI.ppIdxInfo = 0;
for(pOrTerm=pOrWC->a; pOrTerma), (pTerm - pWC->a)
));
- if( pOrTerm->eOperator==WO_AND ){
- WhereClause *pAndWC = &pOrTerm->u.pAndInfo->wc;
- bestIndex(pParse, pAndWC, pSrc, notReady, notValid, 0, &sTermCost);
+ if( (pOrTerm->eOperator& WO_AND)!=0 ){
+ sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
+ bestIndex(&sBOI);
}else if( pOrTerm->leftCursor==iCur ){
WhereClause tempWC;
tempWC.pParse = pWC->pParse;
@@ -103520,19 +104754,20 @@ static void bestOrClauseIndex(
tempWC.a = pOrTerm;
tempWC.wctrlFlags = 0;
tempWC.nTerm = 1;
- bestIndex(pParse, &tempWC, pSrc, notReady, notValid, 0, &sTermCost);
+ sBOI.pWC = &tempWC;
+ bestIndex(&sBOI);
}else{
continue;
}
- rTotal += sTermCost.rCost;
- nRow += sTermCost.plan.nRow;
- used |= sTermCost.used;
- if( rTotal>=pCost->rCost ) break;
+ rTotal += sBOI.cost.rCost;
+ nRow += sBOI.cost.plan.nRow;
+ used |= sBOI.cost.used;
+ if( rTotal>=p->cost.rCost ) break;
}
/* If there is an ORDER BY clause, increase the scan cost to account
** for the cost of the sort. */
- if( pOrderBy!=0 ){
+ if( p->pOrderBy!=0 ){
WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
rTotal, rTotal+nRow*estLog(nRow)));
rTotal += nRow*estLog(nRow);
@@ -103542,12 +104777,13 @@ static void bestOrClauseIndex(
** less than the current cost stored in pCost, replace the contents
** of pCost. */
WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
- if( rTotalrCost ){
- pCost->rCost = rTotal;
- pCost->used = used;
- pCost->plan.nRow = nRow;
- pCost->plan.wsFlags = flags;
- pCost->plan.u.pTerm = pTerm;
+ if( rTotalcost.rCost ){
+ p->cost.rCost = rTotal;
+ p->cost.used = used;
+ p->cost.plan.nRow = nRow;
+ p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
+ p->cost.plan.wsFlags = flags;
+ p->cost.plan.u.pTerm = pTerm;
}
}
}
@@ -103567,7 +104803,7 @@ static int termCanDriveIndex(
){
char aff;
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
- if( pTerm->eOperator!=WO_EQ ) return 0;
+ if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
@@ -103584,15 +104820,12 @@ static int termCanDriveIndex(
** is taken into account, then alter the query plan to use the
** transient index.
*/
-static void bestAutomaticIndex(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to search */
- Bitmask notReady, /* Mask of cursors that are not available */
- WhereCost *pCost /* Lowest cost query plan */
-){
- double nTableRow; /* Rows in the input table */
- double logN; /* log(nTableRow) */
+static void bestAutomaticIndex(WhereBestIdx *p){
+ Parse *pParse = p->pParse; /* The parsing context */
+ WhereClause *pWC = p->pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
+ double nTableRow; /* Rows in the input table */
+ double logN; /* log(nTableRow) */
double costTempIdx; /* per-query cost of the transient index */
WhereTerm *pTerm; /* A single term of the WHERE clause */
WhereTerm *pWCEnd; /* End of pWC->a[] */
@@ -103606,10 +104839,16 @@ static void bestAutomaticIndex(
/* Automatic indices are disabled at run-time */
return;
}
- if( (pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 ){
+ if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0
+ && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0
+ ){
/* We already have some kind of index in use for this query. */
return;
}
+ if( pSrc->viaCoroutine ){
+ /* Cannot index a co-routine */
+ return;
+ }
if( pSrc->notIndexed ){
/* The NOT INDEXED clause appears in the SQL. */
return;
@@ -103624,7 +104863,7 @@ static void bestAutomaticIndex(
nTableRow = pTable->nRowEst;
logN = estLog(nTableRow);
costTempIdx = 2*logN*(nTableRow/pParse->nQueryLoop + 1);
- if( costTempIdx>=pCost->rCost ){
+ if( costTempIdx>=p->cost.rCost ){
/* The cost of creating the transient table would be greater than
** doing the full table scan */
return;
@@ -103633,19 +104872,19 @@ static void bestAutomaticIndex(
/* Search for any equality comparison term */
pWCEnd = &pWC->a[pWC->nTerm];
for(pTerm=pWC->a; pTermnotReady) ){
WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
- pCost->rCost, costTempIdx));
- pCost->rCost = costTempIdx;
- pCost->plan.nRow = logN + 1;
- pCost->plan.wsFlags = WHERE_TEMP_INDEX;
- pCost->used = pTerm->prereqRight;
+ p->cost.rCost, costTempIdx));
+ p->cost.rCost = costTempIdx;
+ p->cost.plan.nRow = logN + 1;
+ p->cost.plan.wsFlags = WHERE_TEMP_INDEX;
+ p->cost.used = pTerm->prereqRight;
break;
}
}
}
#else
-# define bestAutomaticIndex(A,B,C,D,E) /* no-op */
+# define bestAutomaticIndex(A) /* no-op */
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
@@ -103806,12 +105045,11 @@ static void constructAutomaticIndex(
** responsibility of the caller to eventually release the structure
** by passing the pointer returned by this function to sqlite3_free().
*/
-static sqlite3_index_info *allocateIndexInfo(
- Parse *pParse,
- WhereClause *pWC,
- struct SrcList_item *pSrc,
- ExprList *pOrderBy
-){
+static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
+ Parse *pParse = p->pParse;
+ WhereClause *pWC = p->pWC;
+ struct SrcList_item *pSrc = p->pSrc;
+ ExprList *pOrderBy = p->pOrderBy;
int i, j;
int nTerm;
struct sqlite3_index_constraint *pIdxCons;
@@ -103827,10 +105065,10 @@ static sqlite3_index_info *allocateIndexInfo(
** to this virtual table */
for(i=nTerm=0, pTerm=pWC->a; inTerm; i++, pTerm++){
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
- testcase( pTerm->eOperator==WO_IN );
- testcase( pTerm->eOperator==WO_ISNULL );
- if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+ testcase( pTerm->eOperator & WO_IN );
+ testcase( pTerm->eOperator & WO_ISNULL );
+ if( pTerm->eOperator & (WO_ISNULL) ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
nTerm++;
}
@@ -103841,12 +105079,13 @@ static sqlite3_index_info *allocateIndexInfo(
*/
nOrderBy = 0;
if( pOrderBy ){
- for(i=0; inExpr; i++){
+ int n = pOrderBy->nExpr;
+ for(i=0; ia[i].pExpr;
if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
}
- if( i==pOrderBy->nExpr ){
- nOrderBy = pOrderBy->nExpr;
+ if( i==n){
+ nOrderBy = n;
}
}
@@ -103877,15 +105116,18 @@ static sqlite3_index_info *allocateIndexInfo(
pUsage;
for(i=j=0, pTerm=pWC->a; inTerm; i++, pTerm++){
+ u8 op;
if( pTerm->leftCursor != pSrc->iCursor ) continue;
- assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
- testcase( pTerm->eOperator==WO_IN );
- testcase( pTerm->eOperator==WO_ISNULL );
- if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+ assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+ testcase( pTerm->eOperator & WO_IN );
+ testcase( pTerm->eOperator & WO_ISNULL );
+ if( pTerm->eOperator & (WO_ISNULL) ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
pIdxCons[j].iColumn = pTerm->u.leftColumn;
pIdxCons[j].iTermOffset = i;
- pIdxCons[j].op = (u8)pTerm->eOperator;
+ op = (u8)pTerm->eOperator & WO_ALL;
+ if( op==WO_IN ) op = WO_EQ;
+ pIdxCons[j].op = op;
/* The direct assignment in the previous line is possible only because
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
** following asserts verify this fact. */
@@ -103895,7 +105137,7 @@ static sqlite3_index_info *allocateIndexInfo(
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
- assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
+ assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
j++;
}
for(i=0; ipParse; /* The parsing context */
+ WhereClause *pWC = p->pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
Table *pTab = pSrc->pTab;
sqlite3_index_info *pIdxInfo;
struct sqlite3_index_constraint *pIdxCons;
struct sqlite3_index_constraint_usage *pUsage;
WhereTerm *pTerm;
- int i, j;
+ int i, j, k;
int nOrderBy;
+ int sortOrder; /* Sort order for IN clauses */
+ int bAllowIN; /* Allow IN optimizations */
double rCost;
/* Make sure wsFlags is initialized to some sane value. Otherwise, if the
** malloc in allocateIndexInfo() fails and this function returns leaving
** wsFlags in an uninitialized state, the caller may behave unpredictably.
*/
- memset(pCost, 0, sizeof(*pCost));
- pCost->plan.wsFlags = WHERE_VIRTUALTABLE;
+ memset(&p->cost, 0, sizeof(p->cost));
+ p->cost.plan.wsFlags = WHERE_VIRTUALTABLE;
/* If the sqlite3_index_info structure has not been previously
** allocated and initialized, then allocate and initialize it now.
*/
- pIdxInfo = *ppIdxInfo;
+ pIdxInfo = *p->ppIdxInfo;
if( pIdxInfo==0 ){
- *ppIdxInfo = pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pOrderBy);
+ *p->ppIdxInfo = pIdxInfo = allocateIndexInfo(p);
}
if( pIdxInfo==0 ){
return;
@@ -104021,65 +105259,102 @@ static void bestVirtualIndex(
assert( pTab->azModuleArg && pTab->azModuleArg[0] );
assert( sqlite3GetVTable(pParse->db, pTab) );
- /* Set the aConstraint[].usable fields and initialize all
- ** output variables to zero.
- **
- ** aConstraint[].usable is true for constraints where the right-hand
- ** side contains only references to tables to the left of the current
- ** table. In other words, if the constraint is of the form:
- **
- ** column = expr
- **
- ** and we are evaluating a join, then the constraint on column is
- ** only valid if all tables referenced in expr occur to the left
- ** of the table containing column.
- **
- ** The aConstraints[] array contains entries for all constraints
- ** on the current table. That way we only have to compute it once
- ** even though we might try to pick the best index multiple times.
- ** For each attempt at picking an index, the order of tables in the
- ** join might be different so we have to recompute the usable flag
- ** each time.
+ /* Try once or twice. On the first attempt, allow IN optimizations.
+ ** If an IN optimization is accepted by the virtual table xBestIndex
+ ** method, but the pInfo->aConstrainUsage.omit flag is not set, then
+ ** the query will not work because it might allow duplicate rows in
+ ** output. In that case, run the xBestIndex method a second time
+ ** without the IN constraints. Usually this loop only runs once.
+ ** The loop will exit using a "break" statement.
*/
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- pUsage = pIdxInfo->aConstraintUsage;
- for(i=0; inConstraint; i++, pIdxCons++){
- j = pIdxCons->iTermOffset;
- pTerm = &pWC->a[j];
- pIdxCons->usable = (pTerm->prereqRight¬Ready) ? 0 : 1;
- }
- memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
- if( pIdxInfo->needToFreeIdxStr ){
- sqlite3_free(pIdxInfo->idxStr);
- }
- pIdxInfo->idxStr = 0;
- pIdxInfo->idxNum = 0;
- pIdxInfo->needToFreeIdxStr = 0;
- pIdxInfo->orderByConsumed = 0;
- /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
- pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
- nOrderBy = pIdxInfo->nOrderBy;
- if( !pOrderBy ){
- pIdxInfo->nOrderBy = 0;
- }
+ for(bAllowIN=1; 1; bAllowIN--){
+ assert( bAllowIN==0 || bAllowIN==1 );
- if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
- return;
- }
-
- pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
- for(i=0; inConstraint; i++){
- if( pUsage[i].argvIndex>0 ){
- pCost->used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
+ /* Set the aConstraint[].usable fields and initialize all
+ ** output variables to zero.
+ **
+ ** aConstraint[].usable is true for constraints where the right-hand
+ ** side contains only references to tables to the left of the current
+ ** table. In other words, if the constraint is of the form:
+ **
+ ** column = expr
+ **
+ ** and we are evaluating a join, then the constraint on column is
+ ** only valid if all tables referenced in expr occur to the left
+ ** of the table containing column.
+ **
+ ** The aConstraints[] array contains entries for all constraints
+ ** on the current table. That way we only have to compute it once
+ ** even though we might try to pick the best index multiple times.
+ ** For each attempt at picking an index, the order of tables in the
+ ** join might be different so we have to recompute the usable flag
+ ** each time.
+ */
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ pUsage = pIdxInfo->aConstraintUsage;
+ for(i=0; inConstraint; i++, pIdxCons++){
+ j = pIdxCons->iTermOffset;
+ pTerm = &pWC->a[j];
+ if( (pTerm->prereqRight&p->notReady)==0
+ && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
+ ){
+ pIdxCons->usable = 1;
+ }else{
+ pIdxCons->usable = 0;
+ }
}
+ memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+ if( pIdxInfo->needToFreeIdxStr ){
+ sqlite3_free(pIdxInfo->idxStr);
+ }
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->idxNum = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ pIdxInfo->orderByConsumed = 0;
+ /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
+ pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
+ nOrderBy = pIdxInfo->nOrderBy;
+ if( !p->pOrderBy ){
+ pIdxInfo->nOrderBy = 0;
+ }
+
+ if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
+ return;
+ }
+
+ sortOrder = SQLITE_SO_ASC;
+ pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+ for(i=0; inConstraint; i++, pIdxCons++){
+ if( pUsage[i].argvIndex>0 ){
+ j = pIdxCons->iTermOffset;
+ pTerm = &pWC->a[j];
+ p->cost.used |= pTerm->prereqRight;
+ if( (pTerm->eOperator & WO_IN)!=0 ){
+ if( pUsage[i].omit==0 ){
+ /* Do not attempt to use an IN constraint if the virtual table
+ ** says that the equivalent EQ constraint cannot be safely omitted.
+ ** If we do attempt to use such a constraint, some rows might be
+ ** repeated in the output. */
+ break;
+ }
+ for(k=0; knOrderBy; k++){
+ if( pIdxInfo->aOrderBy[k].iColumn==pIdxCons->iColumn ){
+ sortOrder = pIdxInfo->aOrderBy[k].desc;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if( i>=pIdxInfo->nConstraint ) break;
}
-
+
/* If there is an ORDER BY clause, and the selected virtual table index
** does not satisfy it, increase the cost of the scan accordingly. This
** matches the processing for non-virtual tables in bestBtreeIndex().
*/
rCost = pIdxInfo->estimatedCost;
- if( pOrderBy && pIdxInfo->orderByConsumed==0 ){
+ if( p->pOrderBy && pIdxInfo->orderByConsumed==0 ){
rCost += estLog(rCost)*rCost;
}
@@ -104091,21 +105366,25 @@ static void bestVirtualIndex(
** is defined.
*/
if( (SQLITE_BIG_DBL/((double)2))rCost = (SQLITE_BIG_DBL/((double)2));
+ p->cost.rCost = (SQLITE_BIG_DBL/((double)2));
}else{
- pCost->rCost = rCost;
+ p->cost.rCost = rCost;
}
- pCost->plan.u.pVtabIdx = pIdxInfo;
+ p->cost.plan.u.pVtabIdx = pIdxInfo;
if( pIdxInfo->orderByConsumed ){
- pCost->plan.wsFlags |= WHERE_ORDERBY;
+ assert( sortOrder==0 || sortOrder==1 );
+ p->cost.plan.wsFlags |= WHERE_ORDERED + sortOrder*WHERE_REVERSE;
+ p->cost.plan.nOBSat = nOrderBy;
+ }else{
+ p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
}
- pCost->plan.nEq = 0;
+ p->cost.plan.nEq = 0;
pIdxInfo->nOrderBy = nOrderBy;
/* Try to find a more efficient access pattern by using multiple indexes
** to optimize an OR expression within the WHERE clause.
*/
- bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
+ bestOrClauseIndex(p);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -104193,10 +105472,8 @@ static int whereKeyStats(
pColl = db->pDfltColl;
assert( pColl->enc==SQLITE_UTF8 );
}else{
- pColl = sqlite3GetCollSeq(db, SQLITE_UTF8, 0, *pIdx->azColl);
+ pColl = sqlite3GetCollSeq(pParse, SQLITE_UTF8, 0, *pIdx->azColl);
if( pColl==0 ){
- sqlite3ErrorMsg(pParse, "no such collation sequence: %s",
- *pIdx->azColl);
return SQLITE_ERROR;
}
z = (const u8 *)sqlite3ValueText(pVal, pColl->enc);
@@ -104367,24 +105644,24 @@ static int whereRangeScanEst(
if( pLower ){
Expr *pExpr = pLower->pExpr->pRight;
rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
- assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE );
+ assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
if( rc==SQLITE_OK
&& whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
){
iLower = a[0];
- if( pLower->eOperator==WO_GT ) iLower += a[1];
+ if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
}
sqlite3ValueFree(pRangeVal);
}
if( rc==SQLITE_OK && pUpper ){
Expr *pExpr = pUpper->pExpr->pRight;
rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
- assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE );
+ assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
if( rc==SQLITE_OK
&& whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
){
iUpper = a[0];
- if( pUpper->eOperator==WO_LE ) iUpper += a[1];
+ if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
}
sqlite3ValueFree(pRangeVal);
}
@@ -104504,11 +105781,295 @@ static int whereInScanEst(
}
#endif /* defined(SQLITE_ENABLE_STAT3) */
+/*
+** Check to see if column iCol of the table with cursor iTab will appear
+** in sorted order according to the current query plan.
+**
+** Return values:
+**
+** 0 iCol is not ordered
+** 1 iCol has only a single value
+** 2 iCol is in ASC order
+** 3 iCol is in DESC order
+*/
+static int isOrderedColumn(
+ WhereBestIdx *p,
+ int iTab,
+ int iCol
+){
+ int i, j;
+ WhereLevel *pLevel = &p->aLevel[p->i-1];
+ Index *pIdx;
+ u8 sortOrder;
+ for(i=p->i-1; i>=0; i--, pLevel--){
+ if( pLevel->iTabCur!=iTab ) continue;
+ if( (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+ return 1;
+ }
+ assert( (pLevel->plan.wsFlags & WHERE_ORDERED)!=0 );
+ if( (pIdx = pLevel->plan.u.pIdx)!=0 ){
+ if( iCol<0 ){
+ sortOrder = 0;
+ testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+ }else{
+ int n = pIdx->nColumn;
+ for(j=0; jaiColumn[j] ) break;
+ }
+ if( j>=n ) return 0;
+ sortOrder = pIdx->aSortOrder[j];
+ testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+ }
+ }else{
+ if( iCol!=(-1) ) return 0;
+ sortOrder = 0;
+ testcase( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 );
+ }
+ if( (pLevel->plan.wsFlags & WHERE_REVERSE)!=0 ){
+ assert( sortOrder==0 || sortOrder==1 );
+ testcase( sortOrder==1 );
+ sortOrder = 1 - sortOrder;
+ }
+ return sortOrder+2;
+ }
+ return 0;
+}
+
+/*
+** This routine decides if pIdx can be used to satisfy the ORDER BY
+** clause, either in whole or in part. The return value is the
+** cumulative number of terms in the ORDER BY clause that are satisfied
+** by the index pIdx and other indices in outer loops.
+**
+** The table being queried has a cursor number of "base". pIdx is the
+** index that is postulated for use to access the table.
+**
+** The *pbRev value is set to 0 order 1 depending on whether or not
+** pIdx should be run in the forward order or in reverse order.
+*/
+static int isSortingIndex(
+ WhereBestIdx *p, /* Best index search context */
+ Index *pIdx, /* The index we are testing */
+ int base, /* Cursor number for the table to be sorted */
+ int *pbRev, /* Set to 1 for reverse-order scan of pIdx */
+ int *pbObUnique /* ORDER BY column values will different in every row */
+){
+ int i; /* Number of pIdx terms used */
+ int j; /* Number of ORDER BY terms satisfied */
+ int sortOrder = 2; /* 0: forward. 1: backward. 2: unknown */
+ int nTerm; /* Number of ORDER BY terms */
+ struct ExprList_item *pOBItem;/* A term of the ORDER BY clause */
+ Table *pTab = pIdx->pTable; /* Table that owns index pIdx */
+ ExprList *pOrderBy; /* The ORDER BY clause */
+ Parse *pParse = p->pParse; /* Parser context */
+ sqlite3 *db = pParse->db; /* Database connection */
+ int nPriorSat; /* ORDER BY terms satisfied by outer loops */
+ int seenRowid = 0; /* True if an ORDER BY rowid term is seen */
+ int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */
+ int outerObUnique; /* Outer loops generate different values in
+ ** every row for the ORDER BY columns */
+
+ if( p->i==0 ){
+ nPriorSat = 0;
+ outerObUnique = 1;
+ }else{
+ u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
+ nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
+ if( (wsFlags & WHERE_ORDERED)==0 ){
+ /* This loop cannot be ordered unless the next outer loop is
+ ** also ordered */
+ return nPriorSat;
+ }
+ if( OptimizationDisabled(db, SQLITE_OrderByIdxJoin) ){
+ /* Only look at the outer-most loop if the OrderByIdxJoin
+ ** optimization is disabled */
+ return nPriorSat;
+ }
+ testcase( wsFlags & WHERE_OB_UNIQUE );
+ testcase( wsFlags & WHERE_ALL_UNIQUE );
+ outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
+ }
+ pOrderBy = p->pOrderBy;
+ assert( pOrderBy!=0 );
+ if( pIdx->bUnordered ){
+ /* Hash indices (indicated by the "unordered" tag on sqlite_stat1) cannot
+ ** be used for sorting */
+ return nPriorSat;
+ }
+ nTerm = pOrderBy->nExpr;
+ uniqueNotNull = pIdx->onError!=OE_None;
+ assert( nTerm>0 );
+
+ /* Argument pIdx must either point to a 'real' named index structure,
+ ** or an index structure allocated on the stack by bestBtreeIndex() to
+ ** represent the rowid index that is part of every table. */
+ assert( pIdx->zName || (pIdx->nColumn==1 && pIdx->aiColumn[0]==-1) );
+
+ /* Match terms of the ORDER BY clause against columns of
+ ** the index.
+ **
+ ** Note that indices have pIdx->nColumn regular columns plus
+ ** one additional column containing the rowid. The rowid column
+ ** of the index is also allowed to match against the ORDER BY
+ ** clause.
+ */
+ j = nPriorSat;
+ for(i=0,pOBItem=&pOrderBy->a[j]; jnColumn; i++){
+ Expr *pOBExpr; /* The expression of the ORDER BY pOBItem */
+ CollSeq *pColl; /* The collating sequence of pOBExpr */
+ int termSortOrder; /* Sort order for this term */
+ int iColumn; /* The i-th column of the index. -1 for rowid */
+ int iSortOrder; /* 1 for DESC, 0 for ASC on the i-th index term */
+ int isEq; /* Subject to an == or IS NULL constraint */
+ int isMatch; /* ORDER BY term matches the index term */
+ const char *zColl; /* Name of collating sequence for i-th index term */
+ WhereTerm *pConstraint; /* A constraint in the WHERE clause */
+
+ /* If the next term of the ORDER BY clause refers to anything other than
+ ** a column in the "base" table, then this index will not be of any
+ ** further use in handling the ORDER BY. */
+ pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr);
+ if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){
+ break;
+ }
+
+ /* Find column number and collating sequence for the next entry
+ ** in the index */
+ if( pIdx->zName && inColumn ){
+ iColumn = pIdx->aiColumn[i];
+ if( iColumn==pIdx->pTable->iPKey ){
+ iColumn = -1;
+ }
+ iSortOrder = pIdx->aSortOrder[i];
+ zColl = pIdx->azColl[i];
+ assert( zColl!=0 );
+ }else{
+ iColumn = -1;
+ iSortOrder = 0;
+ zColl = 0;
+ }
+
+ /* Check to see if the column number and collating sequence of the
+ ** index match the column number and collating sequence of the ORDER BY
+ ** clause entry. Set isMatch to 1 if they both match. */
+ if( pOBExpr->iColumn==iColumn ){
+ if( zColl ){
+ pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr);
+ if( !pColl ) pColl = db->pDfltColl;
+ isMatch = sqlite3StrICmp(pColl->zName, zColl)==0;
+ }else{
+ isMatch = 1;
+ }
+ }else{
+ isMatch = 0;
+ }
+
+ /* termSortOrder is 0 or 1 for whether or not the access loop should
+ ** run forward or backwards (respectively) in order to satisfy this
+ ** term of the ORDER BY clause. */
+ assert( pOBItem->sortOrder==0 || pOBItem->sortOrder==1 );
+ assert( iSortOrder==0 || iSortOrder==1 );
+ termSortOrder = iSortOrder ^ pOBItem->sortOrder;
+
+ /* If X is the column in the index and ORDER BY clause, check to see
+ ** if there are any X= or X IS NULL constraints in the WHERE clause. */
+ pConstraint = findTerm(p->pWC, base, iColumn, p->notReady,
+ WO_EQ|WO_ISNULL|WO_IN, pIdx);
+ if( pConstraint==0 ){
+ isEq = 0;
+ }else if( (pConstraint->eOperator & WO_IN)!=0 ){
+ isEq = 0;
+ }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
+ uniqueNotNull = 0;
+ isEq = 1; /* "X IS NULL" means X has only a single value */
+ }else if( pConstraint->prereqRight==0 ){
+ isEq = 1; /* Constraint "X=constant" means X has only a single value */
+ }else{
+ Expr *pRight = pConstraint->pExpr->pRight;
+ if( pRight->op==TK_COLUMN ){
+ WHERETRACE((" .. isOrderedColumn(tab=%d,col=%d)",
+ pRight->iTable, pRight->iColumn));
+ isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
+ WHERETRACE((" -> isEq=%d\n", isEq));
+
+ /* If the constraint is of the form X=Y where Y is an ordered value
+ ** in an outer loop, then make sure the sort order of Y matches the
+ ** sort order required for X. */
+ if( isMatch && isEq>=2 && isEq!=pOBItem->sortOrder+2 ){
+ testcase( isEq==2 );
+ testcase( isEq==3 );
+ break;
+ }
+ }else{
+ isEq = 0; /* "X=expr" places no ordering constraints on X */
+ }
+ }
+ if( !isMatch ){
+ if( isEq==0 ){
+ break;
+ }else{
+ continue;
+ }
+ }else if( isEq!=1 ){
+ if( sortOrder==2 ){
+ sortOrder = termSortOrder;
+ }else if( termSortOrder!=sortOrder ){
+ break;
+ }
+ }
+ j++;
+ pOBItem++;
+ if( iColumn<0 ){
+ seenRowid = 1;
+ break;
+ }else if( pTab->aCol[iColumn].notNull==0 && isEq!=1 ){
+ testcase( isEq==0 );
+ testcase( isEq==2 );
+ testcase( isEq==3 );
+ uniqueNotNull = 0;
+ }
+ }
+ if( seenRowid ){
+ uniqueNotNull = 1;
+ }else if( uniqueNotNull==0 || inColumn ){
+ uniqueNotNull = 0;
+ }
+
+ /* If we have not found at least one ORDER BY term that matches the
+ ** index, then show no progress. */
+ if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
+
+ /* Either the outer queries must generate rows where there are no two
+ ** rows with the same values in all ORDER BY columns, or else this
+ ** loop must generate just a single row of output. Example: Suppose
+ ** the outer loops generate A=1 and A=1, and this loop generates B=3
+ ** and B=4. Then without the following test, ORDER BY A,B would
+ ** generate the wrong order output: 1,3 1,4 1,3 1,4
+ */
+ if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
+ *pbObUnique = uniqueNotNull;
+
+ /* Return the necessary scan order back to the caller */
+ *pbRev = sortOrder & 1;
+
+ /* If there was an "ORDER BY rowid" term that matched, or it is only
+ ** possible for a single row from this table to match, then skip over
+ ** any additional ORDER BY terms dealing with this table.
+ */
+ if( uniqueNotNull ){
+ /* Advance j over additional ORDER BY terms associated with base */
+ WhereMaskSet *pMS = p->pWC->pMaskSet;
+ Bitmask m = ~getMask(pMS, base);
+ while( ja[j].pExpr)&m)==0 ){
+ j++;
+ }
+ }
+ return j;
+}
/*
** Find the best query plan for accessing a particular table. Write the
-** best query plan and its cost into the WhereCost object supplied as the
-** last parameter.
+** best query plan and its cost into the p->cost.
**
** The lowest cost plan wins. The cost is an estimate of the amount of
** CPU and disk I/O needed to process the requested result.
@@ -104528,21 +106089,15 @@ static int whereInScanEst(
** SQLITE_BIG_DBL. If a plan is found that uses the named index,
** then the cost is calculated in the usual way.
**
-** If a NOT INDEXED clause (pSrc->notIndexed!=0) was attached to the table
+** If a NOT INDEXED clause was attached to the table
** in the SELECT statement, then no indexes are considered. However, the
** selected plan may still take advantage of the built-in rowid primary key
** index.
*/
-static void bestBtreeIndex(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to search */
- Bitmask notReady, /* Mask of cursors not available for indexing */
- Bitmask notValid, /* Cursors not available for any purpose */
- ExprList *pOrderBy, /* The ORDER BY clause */
- ExprList *pDistinct, /* The select-list if query is DISTINCT */
- WhereCost *pCost /* Lowest cost query plan */
-){
+static void bestBtreeIndex(WhereBestIdx *p){
+ Parse *pParse = p->pParse; /* The parsing context */
+ WhereClause *pWC = p->pWC; /* The WHERE clause */
+ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */
int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */
Index *pProbe; /* An index we are evaluating */
Index *pIdx; /* Copy of pProbe, or zero for IPK index */
@@ -104551,11 +106106,16 @@ static void bestBtreeIndex(
Index sPk; /* A fake index object for the primary key */
tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
- int wsFlagMask; /* Allowed flags in pCost->plan.wsFlag */
+ int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */
+ int nPriorSat; /* ORDER BY terms satisfied by outer loops */
+ int nOrderBy; /* Number of ORDER BY terms */
+ char bSortInit; /* Initializer for bSort in inner loop */
+ char bDistInit; /* Initializer for bDist in inner loop */
+
/* Initialize the cost to a worst-case value */
- memset(pCost, 0, sizeof(*pCost));
- pCost->rCost = SQLITE_BIG_DBL;
+ memset(&p->cost, 0, sizeof(p->cost));
+ p->cost.rCost = SQLITE_BIG_DBL;
/* If the pSrc table is the right table of a LEFT JOIN then we may not
** use an index to satisfy IS NULL constraints on that table. This is
@@ -104601,22 +106161,29 @@ static void bestBtreeIndex(
pIdx = 0;
}
+ nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0;
+ if( p->i ){
+ nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
+ bSortInit = nPriorSat0;
+ bDistInit = p->pDistinct!=0;
+ }
+
/* Loop over all indices looking for the best one to use
*/
for(; pProbe; pIdx=pProbe=pProbe->pNext){
const tRowcnt * const aiRowEst = pProbe->aiRowEst;
- double cost; /* Cost of using pProbe */
- double nRow; /* Estimated number of rows in result set */
+ WhereCost pc; /* Cost of using pProbe */
double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */
- int rev; /* True to scan in reverse order */
- int wsFlags = 0;
- Bitmask used = 0;
/* The following variables are populated based on the properties of
** index being evaluated. They are then used to determine the expected
** cost and number of rows returned.
**
- ** nEq:
+ ** pc.plan.nEq:
** Number of equality terms that can be implemented using the index.
** In other words, the number of initial fields in the index that
** are used in == or IN or NOT NULL constraints of the WHERE clause.
@@ -104659,6 +106226,10 @@ static void bestBtreeIndex(
** external sort (i.e. scanning the index being evaluated will not
** correctly order records).
**
+ ** bDist:
+ ** Boolean. True if there is a DISTINCT clause that will require an
+ ** external btree.
+ **
** bLookup:
** Boolean. True if a table lookup is required for each index entry
** visited. In other words, true if this is not a covering index.
@@ -104674,29 +106245,35 @@ static void bestBtreeIndex(
** SELECT a, b FROM tbl WHERE a = 1;
** SELECT a, b, c FROM tbl WHERE a = 1;
*/
- int nEq; /* Number of == or IN terms matching index */
int bInEst = 0; /* True if "x IN (SELECT...)" seen */
int nInMul = 1; /* Number of distinct equalities to lookup */
double rangeDiv = (double)1; /* Estimated reduction in search space */
int nBound = 0; /* Number of range constraints seen */
- int bSort = !!pOrderBy; /* True if external sort required */
- int bDist = !!pDistinct; /* True if index cannot help with DISTINCT */
- int bLookup = 0; /* True if not a covering index */
+ char bSort = bSortInit; /* True if external sort required */
+ char bDist = bDistInit; /* True if index cannot help with DISTINCT */
+ char bLookup = 0; /* True if not a covering index */
WhereTerm *pTerm; /* A single term of the WHERE clause */
#ifdef SQLITE_ENABLE_STAT3
WhereTerm *pFirstTerm = 0; /* First term matching the index */
#endif
- /* Determine the values of nEq and nInMul */
- for(nEq=0; nEqnColumn; nEq++){
- int j = pProbe->aiColumn[nEq];
- pTerm = findTerm(pWC, iCur, j, notReady, eqTermMask, pIdx);
+ WHERETRACE((
+ " %s(%s):\n",
+ pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
+ ));
+ memset(&pc, 0, sizeof(pc));
+ pc.plan.nOBSat = nPriorSat;
+
+ /* Determine the values of pc.plan.nEq and nInMul */
+ for(pc.plan.nEq=0; pc.plan.nEqnColumn; pc.plan.nEq++){
+ int j = pProbe->aiColumn[pc.plan.nEq];
+ pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx);
if( pTerm==0 ) break;
- wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
+ pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ);
testcase( pTerm->pWC!=pWC );
if( pTerm->eOperator & WO_IN ){
Expr *pExpr = pTerm->pExpr;
- wsFlags |= WHERE_COLUMN_IN;
+ pc.plan.wsFlags |= WHERE_COLUMN_IN;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* "x IN (SELECT ...)": Assume the SELECT returns 25 rows */
nInMul *= 25;
@@ -104706,12 +106283,12 @@ static void bestBtreeIndex(
nInMul *= pExpr->x.pList->nExpr;
}
}else if( pTerm->eOperator & WO_ISNULL ){
- wsFlags |= WHERE_COLUMN_NULL;
+ pc.plan.wsFlags |= WHERE_COLUMN_NULL;
}
#ifdef SQLITE_ENABLE_STAT3
- if( nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
+ if( pc.plan.nEq==0 && pProbe->aSample ) pFirstTerm = pTerm;
#endif
- used |= pTerm->prereqRight;
+ pc.used |= pTerm->prereqRight;
}
/* If the index being considered is UNIQUE, and there is an equality
@@ -104720,65 +106297,82 @@ static void bestBtreeIndex(
** indicate this to the caller.
**
** Otherwise, if the search may find more than one row, test to see if
- ** there is a range constraint on indexed column (nEq+1) that can be
- ** optimized using the index.
+ ** there is a range constraint on indexed column (pc.plan.nEq+1) that
+ ** can be optimized using the index.
*/
- if( nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
- testcase( wsFlags & WHERE_COLUMN_IN );
- testcase( wsFlags & WHERE_COLUMN_NULL );
- if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
- wsFlags |= WHERE_UNIQUE;
+ if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
+ testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
+ testcase( pc.plan.wsFlags & WHERE_COLUMN_NULL );
+ if( (pc.plan.wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){
+ pc.plan.wsFlags |= WHERE_UNIQUE;
+ if( p->i==0 || (p->aLevel[p->i-1].plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
+ pc.plan.wsFlags |= WHERE_ALL_UNIQUE;
+ }
}
}else if( pProbe->bUnordered==0 ){
- int j = (nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[nEq]);
- if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
- WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx);
- WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx);
- whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &rangeDiv);
+ int j;
+ j = (pc.plan.nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[pc.plan.nEq]);
+ if( findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){
+ WhereTerm *pTop, *pBtm;
+ pTop = findTerm(pWC, iCur, j, p->notReady, WO_LT|WO_LE, pIdx);
+ pBtm = findTerm(pWC, iCur, j, p->notReady, WO_GT|WO_GE, pIdx);
+ whereRangeScanEst(pParse, pProbe, pc.plan.nEq, pBtm, pTop, &rangeDiv);
if( pTop ){
nBound = 1;
- wsFlags |= WHERE_TOP_LIMIT;
- used |= pTop->prereqRight;
+ pc.plan.wsFlags |= WHERE_TOP_LIMIT;
+ pc.used |= pTop->prereqRight;
testcase( pTop->pWC!=pWC );
}
if( pBtm ){
nBound++;
- wsFlags |= WHERE_BTM_LIMIT;
- used |= pBtm->prereqRight;
+ pc.plan.wsFlags |= WHERE_BTM_LIMIT;
+ pc.used |= pBtm->prereqRight;
testcase( pBtm->pWC!=pWC );
}
- wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
+ pc.plan.wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE);
}
}
/* If there is an ORDER BY clause and the index being considered will
** naturally scan rows in the required order, set the appropriate flags
- ** in wsFlags. Otherwise, if there is an ORDER BY clause but the index
- ** will scan rows in a different order, set the bSort variable. */
- if( isSortingIndex(
- pParse, pWC->pMaskSet, pProbe, iCur, pOrderBy, nEq, wsFlags, &rev)
- ){
- bSort = 0;
- wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_ORDERBY;
- wsFlags |= (rev ? WHERE_REVERSE : 0);
+ ** in pc.plan.wsFlags. Otherwise, if there is an ORDER BY clause but
+ ** the index will scan rows in a different order, set the bSort
+ ** variable. */
+ if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
+ int bRev = 2;
+ int bObUnique = 0;
+ WHERETRACE((" --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
+ pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
+ WHERETRACE((" --> after isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
+ bRev, bObUnique, pc.plan.nOBSat));
+ if( nPriorSatpDistinct, pc.plan.nEq)
+ && (pc.plan.wsFlags & WHERE_COLUMN_IN)==0
){
bDist = 0;
- wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
+ pc.plan.wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT;
}
/* If currently calculating the cost of using an index (not the IPK
** index), determine if all required column data may be obtained without
** using the main table (i.e. if the index is a covering
** index for this query). If it is, set the WHERE_IDX_ONLY flag in
- ** wsFlags. Otherwise, set the bLookup variable to true. */
- if( pIdx && wsFlags ){
+ ** pc.plan.wsFlags. Otherwise, set the bLookup variable to true. */
+ if( pIdx ){
Bitmask m = pSrc->colUsed;
int j;
for(j=0; jnColumn; j++){
@@ -104788,7 +106382,7 @@ static void bestBtreeIndex(
}
}
if( m==0 ){
- wsFlags |= WHERE_IDX_ONLY;
+ pc.plan.wsFlags |= WHERE_IDX_ONLY;
}else{
bLookup = 1;
}
@@ -104798,10 +106392,10 @@ static void bestBtreeIndex(
** Estimate the number of rows of output. For an "x IN (SELECT...)"
** constraint, do not let the estimate exceed half the rows in the table.
*/
- nRow = (double)(aiRowEst[nEq] * nInMul);
- if( bInEst && nRow*2>aiRowEst[0] ){
- nRow = aiRowEst[0]/2;
- nInMul = (int)(nRow / aiRowEst[nEq]);
+ pc.plan.nRow = (double)(aiRowEst[pc.plan.nEq] * nInMul);
+ if( bInEst && pc.plan.nRow*2>aiRowEst[0] ){
+ pc.plan.nRow = aiRowEst[0]/2;
+ nInMul = (int)(pc.plan.nRow / aiRowEst[pc.plan.nEq]);
}
#ifdef SQLITE_ENABLE_STAT3
@@ -104811,15 +106405,19 @@ static void bestBtreeIndex(
** to get a better estimate on the number of rows based on
** VALUE and how common that value is according to the histogram.
*/
- if( nRow>(double)1 && nEq==1 && pFirstTerm!=0 && aiRowEst[1]>1 ){
+ if( pc.plan.nRow>(double)1 && pc.plan.nEq==1
+ && pFirstTerm!=0 && aiRowEst[1]>1 ){
assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
- testcase( pFirstTerm->eOperator==WO_EQ );
- testcase( pFirstTerm->eOperator==WO_ISNULL );
- whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight, &nRow);
+ testcase( pFirstTerm->eOperator & WO_EQ );
+ testcase( pFirstTerm->eOperator & WO_EQUIV );
+ testcase( pFirstTerm->eOperator & WO_ISNULL );
+ whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
+ &pc.plan.nRow);
}else if( bInEst==0 ){
- assert( pFirstTerm->eOperator==WO_IN );
- whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList, &nRow);
+ assert( pFirstTerm->eOperator & WO_IN );
+ whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
+ &pc.plan.nRow);
}
}
#endif /* SQLITE_ENABLE_STAT3 */
@@ -104827,8 +106425,8 @@ static void bestBtreeIndex(
/* Adjust the number of output rows and downward to reflect rows
** that are excluded by range constraints.
*/
- nRow = nRow/rangeDiv;
- if( nRow<1 ) nRow = 1;
+ pc.plan.nRow = pc.plan.nRow/rangeDiv;
+ if( pc.plan.nRow<1 ) pc.plan.nRow = 1;
/* Experiments run on real SQLite databases show that the time needed
** to do a binary search to locate a row in a table or index is roughly
@@ -104843,7 +106441,19 @@ static void bestBtreeIndex(
** So this computation assumes table records are about twice as big
** as index records
*/
- if( (wsFlags & WHERE_NOT_FULLSCAN)==0 ){
+ if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
+ ==WHERE_IDX_ONLY
+ && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
+ && sqlite3GlobalConfig.bUseCis
+ && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
+ ){
+ /* This index is not useful for indexing, but it is a covering index.
+ ** A full-scan of the index might be a little faster than a full-scan
+ ** of the table, so give this case a cost slightly less than a table
+ ** scan. */
+ pc.rCost = aiRowEst[0]*3 + pProbe->nColumn;
+ pc.plan.wsFlags |= WHERE_COVER_SCAN|WHERE_COLUMN_RANGE;
+ }else if( (pc.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
/* The cost of a full table scan is a number of move operations equal
** to the number of rows in the table.
**
@@ -104853,10 +106463,15 @@ static void bestBtreeIndex(
** decision and one which we expect to revisit in the future. But
** it seems to be working well enough at the moment.
*/
- cost = aiRowEst[0]*4;
+ pc.rCost = aiRowEst[0]*4;
+ pc.plan.wsFlags &= ~WHERE_IDX_ONLY;
+ if( pIdx ){
+ pc.plan.wsFlags &= ~WHERE_ORDERED;
+ pc.plan.nOBSat = nPriorSat;
+ }
}else{
log10N = estLog(aiRowEst[0]);
- cost = nRow;
+ pc.rCost = pc.plan.nRow;
if( pIdx ){
if( bLookup ){
/* For an index lookup followed by a table lookup:
@@ -104864,20 +106479,20 @@ static void bestBtreeIndex(
** + nRow steps through the index
** + nRow table searches to lookup the table entry using the rowid
*/
- cost += (nInMul + nRow)*log10N;
+ pc.rCost += (nInMul + pc.plan.nRow)*log10N;
}else{
/* For a covering index:
** nInMul index searches to find the initial entry
** + nRow steps through the index
*/
- cost += nInMul*log10N;
+ pc.rCost += nInMul*log10N;
}
}else{
/* For a rowid primary key lookup:
** nInMult table searches to find the initial entry for each range
** + nRow steps through the table
*/
- cost += nInMul*log10N;
+ pc.rCost += nInMul*log10N;
}
}
@@ -104888,10 +106503,12 @@ static void bestBtreeIndex(
** difference and select C of 3.0.
*/
if( bSort ){
- cost += nRow*estLog(nRow)*3;
+ double m = estLog(pc.plan.nRow*(nOrderBy - pc.plan.nOBSat)/nOrderBy);
+ m *= (double)(pc.plan.nOBSat ? 2 : 3);
+ pc.rCost += pc.plan.nRow*m;
}
if( bDist ){
- cost += nRow*estLog(nRow)*3;
+ pc.rCost += pc.plan.nRow*estLog(pc.plan.nRow)*3;
}
/**** Cost of using this index has now been computed ****/
@@ -104912,25 +106529,25 @@ static void bestBtreeIndex(
** might be selected even when there exists an optimal index that has
** no such dependency.
*/
- if( nRow>2 && cost<=pCost->rCost ){
+ if( pc.plan.nRow>2 && pc.rCost<=p->cost.rCost ){
int k; /* Loop counter */
- int nSkipEq = nEq; /* Number of == constraints to skip */
+ int nSkipEq = pc.plan.nEq; /* Number of == constraints to skip */
int nSkipRange = nBound; /* Number of < constraints to skip */
Bitmask thisTab; /* Bitmap for pSrc */
thisTab = getMask(pWC->pMaskSet, iCur);
- for(pTerm=pWC->a, k=pWC->nTerm; nRow>2 && k; k--, pTerm++){
+ for(pTerm=pWC->a, k=pWC->nTerm; pc.plan.nRow>2 && k; k--, pTerm++){
if( pTerm->wtFlags & TERM_VIRTUAL ) continue;
- if( (pTerm->prereqAll & notValid)!=thisTab ) continue;
+ if( (pTerm->prereqAll & p->notValid)!=thisTab ) continue;
if( pTerm->eOperator & (WO_EQ|WO_IN|WO_ISNULL) ){
if( nSkipEq ){
- /* Ignore the first nEq equality matches since the index
+ /* Ignore the first pc.plan.nEq equality matches since the index
** has already accounted for these */
nSkipEq--;
}else{
/* Assume each additional equality match reduces the result
** set size by a factor of 10 */
- nRow /= 10;
+ pc.plan.nRow /= 10;
}
}else if( pTerm->eOperator & (WO_LT|WO_LE|WO_GT|WO_GE) ){
if( nSkipRange ){
@@ -104944,37 +106561,33 @@ static void bestBtreeIndex(
** more selective intentionally because of the subjective
** observation that indexed range constraints really are more
** selective in practice, on average. */
- nRow /= 3;
+ pc.plan.nRow /= 3;
}
- }else if( pTerm->eOperator!=WO_NOOP ){
+ }else if( (pTerm->eOperator & WO_NOOP)==0 ){
/* Any other expression lowers the output row count by half */
- nRow /= 2;
+ pc.plan.nRow /= 2;
}
}
- if( nRow<2 ) nRow = 2;
+ if( pc.plan.nRow<2 ) pc.plan.nRow = 2;
}
WHERETRACE((
- "%s(%s): nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%x\n"
- " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f used=0x%llx\n",
- pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk"),
- nEq, nInMul, (int)rangeDiv, bSort, bLookup, wsFlags,
- notReady, log10N, nRow, cost, used
+ " nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
+ " notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
+ " used=0x%llx nOBSat=%d\n",
+ pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
+ p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
+ pc.plan.nOBSat
));
/* If this index is the best we have seen so far, then record this
- ** index and its cost in the pCost structure.
+ ** index and its cost in the p->cost structure.
*/
- if( (!pIdx || wsFlags)
- && (costrCost || (cost<=pCost->rCost && nRowplan.nRow))
- ){
- pCost->rCost = cost;
- pCost->used = used;
- pCost->plan.nRow = nRow;
- pCost->plan.wsFlags = (wsFlags&wsFlagMask);
- pCost->plan.nEq = nEq;
- pCost->plan.u.pIdx = pIdx;
+ if( (!pIdx || pc.plan.wsFlags) && compareCost(&pc, &p->cost) ){
+ p->cost = pc;
+ p->cost.plan.wsFlags &= wsFlagMask;
+ p->cost.plan.u.pIdx = pIdx;
}
/* If there was an INDEXED BY clause, then only that one index is
@@ -104989,27 +106602,26 @@ static void bestBtreeIndex(
/* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
** is set, then reverse the order that the index will be scanned
** in. This is used for application testing, to help find cases
- ** where application behaviour depends on the (undefined) order that
+ ** where application behavior depends on the (undefined) order that
** SQLite outputs rows in in the absence of an ORDER BY clause. */
- if( !pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
- pCost->plan.wsFlags |= WHERE_REVERSE;
+ if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
+ p->cost.plan.wsFlags |= WHERE_REVERSE;
}
- assert( pOrderBy || (pCost->plan.wsFlags&WHERE_ORDERBY)==0 );
- assert( pCost->plan.u.pIdx==0 || (pCost->plan.wsFlags&WHERE_ROWID_EQ)==0 );
+ assert( p->pOrderBy || (p->cost.plan.wsFlags&WHERE_ORDERED)==0 );
+ assert( p->cost.plan.u.pIdx==0 || (p->cost.plan.wsFlags&WHERE_ROWID_EQ)==0 );
assert( pSrc->pIndex==0
- || pCost->plan.u.pIdx==0
- || pCost->plan.u.pIdx==pSrc->pIndex
+ || p->cost.plan.u.pIdx==0
+ || p->cost.plan.u.pIdx==pSrc->pIndex
);
- WHERETRACE(("best index is: %s\n",
- ((pCost->plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ? "none" :
- pCost->plan.u.pIdx ? pCost->plan.u.pIdx->zName : "ipk")
- ));
+ WHERETRACE((" best index is %s cost=%.1f\n",
+ p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
+ p->cost.rCost));
- bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
- bestAutomaticIndex(pParse, pWC, pSrc, notReady, pCost);
- pCost->plan.wsFlags |= eqTermMask;
+ bestOrClauseIndex(p);
+ bestAutomaticIndex(p);
+ p->cost.plan.wsFlags |= eqTermMask;
}
/*
@@ -105017,28 +106629,28 @@ static void bestBtreeIndex(
** best query plan and its cost into the WhereCost object supplied
** as the last parameter. This function may calculate the cost of
** both real and virtual table scans.
+**
+** This function does not take ORDER BY or DISTINCT into account. Nor
+** does it remember the virtual table query plan. All it does is compute
+** the cost while determining if an OR optimization is applicable. The
+** details will be reconsidered later if the optimization is found to be
+** applicable.
*/
-static void bestIndex(
- Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to search */
- Bitmask notReady, /* Mask of cursors not available for indexing */
- Bitmask notValid, /* Cursors not available for any purpose */
- ExprList *pOrderBy, /* The ORDER BY clause */
- WhereCost *pCost /* Lowest cost query plan */
-){
+static void bestIndex(WhereBestIdx *p){
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pSrc->pTab) ){
- sqlite3_index_info *p = 0;
- bestVirtualIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost,&p);
- if( p->needToFreeIdxStr ){
- sqlite3_free(p->idxStr);
+ if( IsVirtual(p->pSrc->pTab) ){
+ sqlite3_index_info *pIdxInfo = 0;
+ p->ppIdxInfo = &pIdxInfo;
+ bestVirtualIndex(p);
+ assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
+ if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
+ sqlite3_free(pIdxInfo->idxStr);
}
- sqlite3DbFree(pParse->db, p);
+ sqlite3DbFree(p->pParse->db, pIdxInfo);
}else
#endif
{
- bestBtreeIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, 0, pCost);
+ bestBtreeIndex(p);
}
}
@@ -105137,7 +106749,8 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
static int codeEqualityTerm(
Parse *pParse, /* The parsing context */
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
- WhereLevel *pLevel, /* When level of the FROM clause we are working on */
+ WhereLevel *pLevel, /* The level of the FROM clause we are working on */
+ int iEq, /* Index of the equality term within this level */
int iTarget /* Attempt to leave results in this register */
){
Expr *pX = pTerm->pExpr;
@@ -105155,12 +106768,26 @@ static int codeEqualityTerm(
int eType;
int iTab;
struct InLoop *pIn;
+ u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
+ if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0
+ && pLevel->plan.u.pIdx->aSortOrder[iEq]
+ ){
+ testcase( iEq==0 );
+ testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 );
+ testcase( iEq>0 && iEq+1plan.u.pIdx->nColumn );
+ testcase( bRev );
+ bRev = !bRev;
+ }
assert( pX->op==TK_IN );
iReg = iTarget;
eType = sqlite3FindInIndex(pParse, pX, 0);
+ if( eType==IN_INDEX_INDEX_DESC ){
+ testcase( bRev );
+ bRev = !bRev;
+ }
iTab = pX->iTable;
- sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
+ sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
@@ -105178,6 +106805,7 @@ static int codeEqualityTerm(
}else{
pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
}
+ pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
}else{
pLevel->u.in.nIn = 0;
@@ -105272,7 +106900,7 @@ static int codeAllEqualityTerms(
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
- r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
+ r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
sqlite3ReleaseTempReg(pParse, regBase);
@@ -105516,12 +107144,23 @@ static Bitmask codeOneLoopStart(
VdbeComment((v, "init LEFT JOIN no-match flag"));
}
+ /* Special case of a FROM clause subquery implemented as a co-routine */
+ if( pTabItem->viaCoroutine ){
+ int regYield = pTabItem->regReturn;
+ sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield);
+ pLevel->p2 = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
+ VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName));
+ sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk);
+ pLevel->op = OP_Goto;
+ }else
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){
/* Case 0: The table is a virtual-table. Use the VFilter and VNext
** to access the data.
*/
int iReg; /* P3 Value for OP_VFilter */
+ int addrNotFound;
sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
int nConstraint = pVtabIdx->nConstraint;
struct sqlite3_index_constraint_usage *aUsage =
@@ -105531,11 +107170,18 @@ static Bitmask codeOneLoopStart(
sqlite3ExprCachePush(pParse);
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
+ addrNotFound = pLevel->addrBrk;
for(j=1; j<=nConstraint; j++){
for(k=0; ka[iTerm].pExpr->pRight, iReg+j+1);
+ int iTarget = iReg+j+1;
+ pTerm = &pWC->a[aConstraint[k].iTermOffset];
+ if( pTerm->eOperator & WO_IN ){
+ codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget);
+ addrNotFound = pLevel->addrNxt;
+ }else{
+ sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
+ }
break;
}
}
@@ -105543,7 +107189,7 @@ static Bitmask codeOneLoopStart(
}
sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
- sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
+ sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
pVtabIdx->needToFreeIdxStr = 0;
for(j=0; jpExpr!=0 );
- assert( pTerm->leftCursor==iCur );
assert( omitTable==0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
- iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
+ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg);
addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
+ sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
VdbeComment((v, "pk"));
pLevel->op = OP_Noop;
@@ -105734,7 +107380,7 @@ static Bitmask codeOneLoopStart(
** this requires some special handling.
*/
if( (wctrlFlags&WHERE_ORDERBY_MIN)!=0
- && (pLevel->plan.wsFlags&WHERE_ORDERBY)
+ && (pLevel->plan.wsFlags&WHERE_ORDERED)
&& (pIdx->nColumn>nEq)
){
/* assert( pOrderBy->nExpr==1 ); */
@@ -105897,6 +107543,11 @@ static Bitmask codeOneLoopStart(
pLevel->op = OP_Next;
}
pLevel->p1 = iIdxCur;
+ if( pLevel->plan.wsFlags & WHERE_COVER_SCAN ){
+ pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
+ }else{
+ assert( pLevel->p5==0 );
+ }
}else
#ifndef SQLITE_OMIT_OR_OPTIMIZATION
@@ -105956,7 +107607,7 @@ static Bitmask codeOneLoopStart(
pTerm = pLevel->plan.u.pTerm;
assert( pTerm!=0 );
- assert( pTerm->eOperator==WO_OR );
+ assert( pTerm->eOperator & WO_OR );
assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
pOrWc = &pTerm->u.pOrInfo->wc;
pLevel->op = OP_Return;
@@ -106029,7 +107680,7 @@ static Bitmask codeOneLoopStart(
for(ii=0; iinTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
- if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
+ if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr;
if( pAndExpr ){
@@ -106291,42 +107942,46 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
**
** ORDER BY CLAUSE PROCESSING
**
-** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
+** pOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
** if there is one. If there is no ORDER BY clause or if this routine
-** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.
+** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
**
** If an index can be used so that the natural output order of the table
** scan is correct for the ORDER BY clause, then that index is used and
-** *ppOrderBy is set to NULL. This is an optimization that prevents an
-** unnecessary sort of the result set if an index appropriate for the
-** ORDER BY clause already exists.
+** the returned WhereInfo.nOBSat field is set to pOrderBy->nExpr. This
+** is an optimization that prevents an unnecessary sort of the result set
+** if an index appropriate for the ORDER BY clause already exists.
**
** If the where clause loops cannot be arranged to provide the correct
-** output order, then the *ppOrderBy is unchanged.
+** output order, then WhereInfo.nOBSat is 0.
*/
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* A list of all tables to be scanned */
Expr *pWhere, /* The WHERE clause */
- ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
+ ExprList *pOrderBy, /* An ORDER BY clause, or NULL */
ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */
){
- int i; /* Loop counter */
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
int nTabList; /* Number of elements in pTabList */
WhereInfo *pWInfo; /* Will become the return value of this function */
Vdbe *v = pParse->pVdbe; /* The virtual database engine */
Bitmask notReady; /* Cursors that are not yet positioned */
+ WhereBestIdx sWBI; /* Best index search context */
WhereMaskSet *pMaskSet; /* The expression mask set */
- WhereClause *pWC; /* Decomposition of the WHERE clause */
- struct SrcList_item *pTabItem; /* A single entry from pTabList */
- WhereLevel *pLevel; /* A single level in the pWInfo list */
- int iFrom; /* First unused FROM clause element */
+ WhereLevel *pLevel; /* A single level in pWInfo->a[] */
+ int iFrom; /* First unused FROM clause element */
int andFlags; /* AND-ed combination of all pWC->a[].wtFlags */
+ int ii; /* Loop counter */
sqlite3 *db; /* Database connection */
+
+ /* Variable initialization */
+ memset(&sWBI, 0, sizeof(sWBI));
+ sWBI.pParse = pParse;
+
/* The number of tables in the FROM clause is limited by the number of
** bits in a Bitmask
*/
@@ -106366,22 +108021,23 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
pWInfo->pParse = pParse;
pWInfo->pTabList = pTabList;
pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
- pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
+ pWInfo->pWC = sWBI.pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
- pMaskSet = (WhereMaskSet*)&pWC[1];
+ pMaskSet = (WhereMaskSet*)&sWBI.pWC[1];
+ sWBI.aLevel = pWInfo->a;
/* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
- if( db->flags & SQLITE_DistinctOpt ) pDistinct = 0;
+ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator.
*/
initMaskSet(pMaskSet);
- whereClauseInit(pWC, pParse, pMaskSet, wctrlFlags);
+ whereClauseInit(sWBI.pWC, pParse, pMaskSet, wctrlFlags);
sqlite3ExprCodeConstants(pParse, pWhere);
- whereSplit(pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
+ whereSplit(sWBI.pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
@@ -106402,30 +108058,19 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** bitmask for all tables to the left of the join. Knowing the bitmask
** for all tables to the left of a left join is important. Ticket #3015.
**
- ** Configure the WhereClause.vmask variable so that bits that correspond
- ** to virtual table cursors are set. This is used to selectively disable
- ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful
- ** with virtual tables.
- **
** Note that bitmasks are created for all pTabList->nSrc tables in
** pTabList, not just the first nTabList tables. nTabList is normally
** equal to pTabList->nSrc but might be shortened to 1 if the
** WHERE_ONETABLE_ONLY flag is set.
*/
- assert( pWC->vmask==0 && pMaskSet->n==0 );
- for(i=0; inSrc; i++){
- createMask(pMaskSet, pTabList->a[i].iCursor);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( ALWAYS(pTabList->a[i].pTab) && IsVirtual(pTabList->a[i].pTab) ){
- pWC->vmask |= ((Bitmask)1 << i);
- }
-#endif
+ for(ii=0; iinSrc; ii++){
+ createMask(pMaskSet, pTabList->a[ii].iCursor);
}
#ifndef NDEBUG
{
Bitmask toTheLeft = 0;
- for(i=0; inSrc; i++){
- Bitmask m = getMask(pMaskSet, pTabList->a[i].iCursor);
+ for(ii=0; iinSrc; ii++){
+ Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor);
assert( (m-1)==toTheLeft );
toTheLeft |= m;
}
@@ -106437,7 +108082,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** want to analyze these virtual terms, so start analyzing at the end
** and work forward so that the added virtual terms are never processed.
*/
- exprAnalyzeAll(pTabList, pWC);
+ exprAnalyzeAll(pTabList, sWBI.pWC);
if( db->mallocFailed ){
goto whereBeginError;
}
@@ -106446,7 +108091,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** If it is, then set pDistinct to NULL and WhereInfo.eDistinct to
** WHERE_DISTINCT_UNIQUE to tell the caller to ignore the DISTINCT.
*/
- if( pDistinct && isDistinctRedundant(pParse, pTabList, pWC, pDistinct) ){
+ if( pDistinct && isDistinctRedundant(pParse, pTabList, sWBI.pWC, pDistinct) ){
pDistinct = 0;
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}
@@ -106466,22 +108111,26 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** This loop also figures out the nesting order of tables in the FROM
** clause.
*/
- notReady = ~(Bitmask)0;
+ sWBI.notValid = ~(Bitmask)0;
+ sWBI.pOrderBy = pOrderBy;
+ sWBI.n = nTabList;
+ sWBI.pDistinct = pDistinct;
andFlags = ~0;
WHERETRACE(("*** Optimizer Start ***\n"));
- for(i=iFrom=0, pLevel=pWInfo->a; ia; sWBI.i=0 && bestJ<0; isOptimal--){
- Bitmask mask; /* Mask of tables not yet ready */
- for(j=iFrom, pTabItem=&pTabList->a[j]; jjointype & (JT_LEFT|JT_CROSS))!=0;
- if( j!=iFrom && doNotReorder ) break;
- m = getMask(pMaskSet, pTabItem->iCursor);
- if( (m & notReady)==0 ){
+
+ /* The optimal scan check only occurs if there are two or more tables
+ ** available to be reordered */
+ if( iFrom==nTabList-1 ){
+ ckOptimal = 0; /* Common case of just one table in the FROM clause */
+ }else{
+ ckOptimal = -1;
+ for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; jiCursor);
+ if( (m & sWBI.notValid)==0 ){
if( j==iFrom ) iFrom++;
continue;
}
- mask = (isOptimal ? m : notReady);
- pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
- pDist = (i==0 ? pDistinct : 0);
- if( pTabItem->pIndex==0 ) nUnconstrained++;
+ if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
+ if( ++ckOptimal ) break;
+ if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
+ }
+ }
+ assert( ckOptimal==0 || ckOptimal==1 );
+
+ for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
+ for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; jiFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
+ /* This break and one like it in the ckOptimal computation loop
+ ** above prevent table reordering across LEFT and CROSS JOINs.
+ ** The LEFT JOIN case is necessary for correctness. The prohibition
+ ** against reordering across a CROSS JOIN is an SQLite feature that
+ ** allows the developer to control table reordering */
+ break;
+ }
+ m = getMask(pMaskSet, sWBI.pSrc->iCursor);
+ if( (m & sWBI.notValid)==0 ){
+ assert( j>iFrom );
+ continue;
+ }
+ sWBI.notReady = (isOptimal ? m : sWBI.notValid);
+ if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
- WHERETRACE(("=== trying table %d with isOptimal=%d ===\n",
- j, isOptimal));
- assert( pTabItem->pTab );
+ WHERETRACE((" === trying table %d (%s) with isOptimal=%d ===\n",
+ j, sWBI.pSrc->pTab->zName, isOptimal));
+ assert( sWBI.pSrc->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTabItem->pTab) ){
- sqlite3_index_info **pp = &pWInfo->a[j].pIdxInfo;
- bestVirtualIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
- &sCost, pp);
+ if( IsVirtual(sWBI.pSrc->pTab) ){
+ sWBI.ppIdxInfo = &pWInfo->a[j].pIdxInfo;
+ bestVirtualIndex(&sWBI);
}else
#endif
{
- bestBtreeIndex(pParse, pWC, pTabItem, mask, notReady, pOrderBy,
- pDist, &sCost);
+ bestBtreeIndex(&sWBI);
}
- assert( isOptimal || (sCost.used¬Ready)==0 );
+ assert( isOptimal || (sWBI.cost.used&sWBI.notValid)==0 );
/* If an INDEXED BY clause is present, then the plan must use that
** index if it uses any index at all */
- assert( pTabItem->pIndex==0
- || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
- || sCost.plan.u.pIdx==pTabItem->pIndex );
+ assert( sWBI.pSrc->pIndex==0
+ || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
+ || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex );
- if( isOptimal && (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
+ if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
notIndexed |= m;
}
+ if( isOptimal ){
+ pWInfo->a[j].rOptCost = sWBI.cost.rCost;
+ }else if( ckOptimal ){
+ /* If two or more tables have nearly the same outer loop cost, but
+ ** very different inner loop (optimal) cost, we want to choose
+ ** for the outer loop that table which benefits the least from
+ ** being in the inner loop. The following code scales the
+ ** outer loop cost estimate to accomplish that. */
+ WHERETRACE((" scaling cost from %.1f to %.1f\n",
+ sWBI.cost.rCost,
+ sWBI.cost.rCost/pWInfo->a[j].rOptCost));
+ sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
+ }
/* Conditions under which this table becomes the best so far:
**
** (1) The table must not depend on other tables that have not
- ** yet run.
+ ** yet run. (In other words, it must not depend on tables
+ ** in inner loops.)
**
- ** (2) A full-table-scan plan cannot supercede indexed plan unless
- ** the full-table-scan is an "optimal" plan as defined above.
+ ** (2) (This rule was removed on 2012-11-09. The scaling of the
+ ** cost using the optimal scan cost made this rule obsolete.)
**
** (3) All tables have an INDEXED BY clause or this table lacks an
** INDEXED BY clause or this table uses the specific
@@ -106591,43 +108268,47 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** The NEVER() comes about because rule (2) above prevents
** An indexable full-table-scan from reaching rule (3).
**
- ** (4) The plan cost must be lower than prior plans or else the
- ** cost must be the same and the number of rows must be lower.
+ ** (4) The plan cost must be lower than prior plans, where "cost"
+ ** is defined by the compareCost() function above.
*/
- if( (sCost.used¬Ready)==0 /* (1) */
- && (bestJ<0 || (notIndexed&m)!=0 /* (2) */
- || (bestPlan.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
- || (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
- && (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */
- || NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
- && (bestJ<0 || sCost.rCostpIndex==0 /* (3) */
+ || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
+ && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */
){
- WHERETRACE(("=== table %d is best so far"
- " with cost=%g and nRow=%g\n",
- j, sCost.rCost, sCost.plan.nRow));
- bestPlan = sCost;
+ WHERETRACE((" === table %d (%s) is best so far\n"
+ " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
+ j, sWBI.pSrc->pTab->zName,
+ sWBI.cost.rCost, sWBI.cost.plan.nRow,
+ sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
+ bestPlan = sWBI.cost;
bestJ = j;
}
- if( doNotReorder ) break;
+
+ /* In a join like "w JOIN x LEFT JOIN y JOIN z" make sure that
+ ** table y (and not table z) is always the next inner loop inside
+ ** of table x. */
+ if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
}
}
assert( bestJ>=0 );
- assert( notReady & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
- WHERETRACE(("*** Optimizer selects table %d for loop %d"
- " with cost=%g and nRow=%g\n",
- bestJ, pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow));
- /* The ALWAYS() that follows was added to hush up clang scan-build */
- if( (bestPlan.plan.wsFlags & WHERE_ORDERBY)!=0 && ALWAYS(ppOrderBy) ){
- *ppOrderBy = 0;
- }
+ assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
+ assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
+ testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
+ testcase( bestJ>iFrom && bestJa[bestJ+1].jointype & JT_LEFT)!=0 );
+ WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
+ " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
+ bestJ, pTabList->a[bestJ].pTab->zName,
+ pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
+ bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
assert( pWInfo->eDistinct==0 );
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
}
andFlags &= bestPlan.plan.wsFlags;
pLevel->plan = bestPlan.plan;
+ pLevel->iTabCur = pTabList->a[bestJ].iCursor;
testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
@@ -106641,7 +108322,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}else{
pLevel->iIdxCur = -1;
}
- notReady &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
+ sWBI.notValid &= ~getMask(pMaskSet, pTabList->a[bestJ].iCursor);
pLevel->iFrom = (u8)bestJ;
if( bestPlan.plan.nRow>=(double)1 ){
pParse->nQueryLoop *= bestPlan.plan.nRow;
@@ -106669,12 +108350,19 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( pParse->nErr || db->mallocFailed ){
goto whereBeginError;
}
+ if( nTabList ){
+ pLevel--;
+ pWInfo->nOBSat = pLevel->plan.nOBSat;
+ }else{
+ pWInfo->nOBSat = 0;
+ }
/* If the total query only selects a single row, then the ORDER BY
** clause is irrelevant.
*/
- if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){
- *ppOrderBy = 0;
+ if( (andFlags & WHERE_UNIQUE)!=0 && pOrderBy ){
+ assert( nTabList==0 || (pLevel->plan.wsFlags & WHERE_ALL_UNIQUE)!=0 );
+ pWInfo->nOBSat = pOrderBy->nExpr;
}
/* If the caller is an UPDATE or DELETE statement that is requesting
@@ -106694,13 +108382,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
notReady = ~(Bitmask)0;
pWInfo->nRowOut = (double)1;
- for(i=0, pLevel=pWInfo->a; ia; iia[pLevel->iFrom];
pTab = pTabItem->pTab;
- pLevel->iTabCur = pTabItem->iCursor;
pWInfo->nRowOut *= pLevel->plan.nRow;
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
@@ -106711,6 +108399,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
int iCur = pTabItem->iCursor;
sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
+ }else if( IsVirtual(pTab) ){
+ /* noop */
}else
#endif
if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0
@@ -106732,7 +108422,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
if( (pLevel->plan.wsFlags & WHERE_TEMP_INDEX)!=0 ){
- constructAutomaticIndex(pParse, pWC, pTabItem, notReady, pLevel);
+ constructAutomaticIndex(pParse, sWBI.pWC, pTabItem, notReady, pLevel);
}else
#endif
if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
@@ -106746,7 +108436,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
VdbeComment((v, "%s", pIx->zName));
}
sqlite3CodeVerifySchema(pParse, iDb);
- notReady &= ~getMask(pWC->pMaskSet, pTabItem->iCursor);
+ notReady &= ~getMask(sWBI.pWC->pMaskSet, pTabItem->iCursor);
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
if( db->mallocFailed ) goto whereBeginError;
@@ -106756,10 +108446,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** program.
*/
notReady = ~(Bitmask)0;
- for(i=0; ia[i];
- explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags);
- notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady);
+ for(ii=0; iia[ii];
+ explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
+ notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
pWInfo->iContinue = pLevel->addrCont;
}
@@ -106770,16 +108460,20 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
** the index is listed as "{}". If the primary key is used the
** index name is '*'.
*/
- for(i=0; ia[i];
+ int w;
+ struct SrcList_item *pTabItem;
+
+ pLevel = &pWInfo->a[ii];
+ w = pLevel->plan.wsFlags;
pTabItem = &pTabList->a[pLevel->iFrom];
z = pTabItem->zAlias;
if( z==0 ) z = pTabItem->pTab->zName;
n = sqlite3Strlen30(z);
if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
- if( pLevel->plan.wsFlags & WHERE_IDX_ONLY ){
+ if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
nQPlan += 2;
}else{
@@ -106788,12 +108482,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
sqlite3_query_plan[nQPlan++] = ' ';
}
- testcase( pLevel->plan.wsFlags & WHERE_ROWID_EQ );
- testcase( pLevel->plan.wsFlags & WHERE_ROWID_RANGE );
- if( pLevel->plan.wsFlags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
+ testcase( w & WHERE_ROWID_EQ );
+ testcase( w & WHERE_ROWID_RANGE );
+ if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
nQPlan += 2;
- }else if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 ){
+ }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
@@ -106854,7 +108548,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
- sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->addrInTop);
+ sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
sqlite3DbFree(db, pLevel->u.in.aInLoop);
@@ -107162,6 +108856,7 @@ typedef union {
IdList* yy180;
struct {int value; int mask;} yy207;
u8 yy258;
+ u16 yy305;
struct LikeOp yy318;
TriggerStep* yy327;
ExprSpan yy342;
@@ -109112,8 +110807,6 @@ static void yy_reduce(
case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
- case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
- case 121: /* distinct ::= */ yytestcase(yyruleno==121);
case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
{yygotominor.yy392 = 0;}
@@ -109123,7 +110816,6 @@ static void yy_reduce(
case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
- case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
{yygotominor.yy392 = 1;}
@@ -109363,9 +111055,16 @@ static void yy_reduce(
break;
case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
+ yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
}
break;
+ case 119: /* distinct ::= DISTINCT */
+{yygotominor.yy305 = SF_Distinct;}
+ break;
+ case 120: /* distinct ::= ALL */
+ case 121: /* distinct ::= */ yytestcase(yyruleno==121);
+{yygotominor.yy305 = 0;}
+ break;
case 122: /* sclp ::= selcollist COMMA */
case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
{yygotominor.yy442 = yymsp[-1].minor.yy442;}
@@ -109434,10 +111133,20 @@ static void yy_reduce(
{
if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
yygotominor.yy347 = yymsp[-4].minor.yy347;
+ }else if( yymsp[-4].minor.yy347->nSrc==1 ){
+ yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+ if( yygotominor.yy347 ){
+ struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
+ struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
+ pNew->zName = pOld->zName;
+ pNew->zDatabase = pOld->zDatabase;
+ pOld->zName = pOld->zDatabase = 0;
+ }
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
}else{
Select *pSubquery;
sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
}
}
@@ -109652,7 +111361,7 @@ static void yy_reduce(
break;
case 194: /* expr ::= expr COLLATE ids */
{
- yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
+ yygotominor.yy342.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0);
yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart;
yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
@@ -109670,7 +111379,7 @@ static void yy_reduce(
}
yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
- if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
+ if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
yygotominor.yy342.pExpr->flags |= EP_Distinct;
}
}
@@ -109911,11 +111620,7 @@ static void yy_reduce(
break;
case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */
{
- Expr *p = 0;
- if( yymsp[-1].minor.yy0.n>0 ){
- p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
- sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
- }
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p);
sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1);
sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
@@ -109924,11 +111629,7 @@ static void yy_reduce(
break;
case 248: /* idxlist ::= nm collate sortorder */
{
- Expr *p = 0;
- if( yymsp[-1].minor.yy0.n>0 ){
- p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
- sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
- }
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p);
sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1);
sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index");
@@ -110177,6 +111878,7 @@ static void yy_reduce(
/* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326);
break;
};
+ assert( yyruleno>=0 && yyrulenoyyidx -= yysize;
@@ -111742,6 +113444,13 @@ SQLITE_API int sqlite3_initialize(void){
*/
if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
+#ifdef SQLITE_ENABLE_SQLLOG
+ {
+ extern void sqlite3_init_sqllog(void);
+ sqlite3_init_sqllog();
+ }
+#endif
+
/* Make sure the mutex subsystem is initialized. If unable to
** initialize the mutex subsystem, return early with the error.
** If the system is so sick that we are unable to allocate a mutex,
@@ -112085,6 +113794,20 @@ SQLITE_API int sqlite3_config(int op, ...){
break;
}
+ case SQLITE_CONFIG_COVERING_INDEX_SCAN: {
+ sqlite3GlobalConfig.bUseCis = va_arg(ap, int);
+ break;
+ }
+
+#ifdef SQLITE_ENABLE_SQLLOG
+ case SQLITE_CONFIG_SQLLOG: {
+ typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int);
+ sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t);
+ sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *);
+ break;
+ }
+#endif
+
default: {
rc = SQLITE_ERROR;
break;
@@ -112424,6 +114147,13 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
return SQLITE_BUSY;
}
+#ifdef SQLITE_ENABLE_SQLLOG
+ if( sqlite3GlobalConfig.xSqllog ){
+ /* Closing the handle. Fourth parameter is passed the value 2. */
+ sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2);
+ }
+#endif
+
/* Convert the connection into a zombie and then close it.
*/
db->magic = SQLITE_MAGIC_ZOMBIE;
@@ -112467,7 +114197,7 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
/* If we reach this point, it means that the database connection has
** closed all sqlite3_stmt and sqlite3_backup objects and has been
- ** pased to sqlite3_close (meaning that it is a zombie). Therefore,
+ ** passed to sqlite3_close (meaning that it is a zombie). Therefore,
** go ahead and free all resources.
*/
@@ -112584,7 +114314,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
sqlite3VtabRollback(db);
sqlite3EndBenignMalloc();
- if( db->flags&SQLITE_InternChanges ){
+ if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
}
@@ -112726,6 +114456,7 @@ SQLITE_API int sqlite3_busy_handler(
db->busyHandler.xFunc = xBusy;
db->busyHandler.pArg = pArg;
db->busyHandler.nBusy = 0;
+ db->busyTimeout = 0;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -112763,8 +114494,8 @@ SQLITE_API void sqlite3_progress_handler(
*/
SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
if( ms>0 ){
- db->busyTimeout = ms;
sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
+ db->busyTimeout = ms;
}else{
sqlite3_busy_handler(db, 0, 0);
}
@@ -113377,6 +115108,15 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
return db->errCode;
}
+/*
+** Return a string that describes the kind of error specified in the
+** argument. For now, this simply calls the internal sqlite3ErrStr()
+** function.
+*/
+SQLITE_API const char *sqlite3_errstr(int rc){
+ return sqlite3ErrStr(rc);
+}
+
/*
** Create a new collating function for database "db". The name is zName
** and the encoding is enc.
@@ -114046,6 +115786,13 @@ opendb_out:
db->magic = SQLITE_MAGIC_SICK;
}
*ppDb = db;
+#ifdef SQLITE_ENABLE_SQLLOG
+ if( sqlite3GlobalConfig.xSqllog ){
+ /* Opening a db handle. Fourth parameter is passed 0. */
+ void *pArg = sqlite3GlobalConfig.pSqllogArg;
+ sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
+ }
+#endif
return sqlite3ApiExit(0, rc);
}
@@ -114351,7 +116098,7 @@ SQLITE_API int sqlite3_table_column_metadata(
zDataType = pCol->zType;
zCollSeq = pCol->zColl;
notnull = pCol->notNull!=0;
- primarykey = pCol->isPrimKey!=0;
+ primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
}else{
zDataType = "INTEGER";
@@ -114614,8 +116361,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_OPTIMIZATIONS: {
sqlite3 *db = va_arg(ap, sqlite3*);
- int x = va_arg(ap,int);
- db->flags = (x & SQLITE_OptMask) | (db->flags & ~SQLITE_OptMask);
+ db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
break;
}
@@ -115503,7 +117249,7 @@ struct sqlite3_tokenizer_module {
** This method should return either SQLITE_OK (0), or an SQLite error
** code. If SQLITE_OK is returned, then *ppTokenizer should be set
** to point at the newly created tokenizer structure. The generic
- ** sqlite3_tokenizer.pModule variable should not be initialised by
+ ** sqlite3_tokenizer.pModule variable should not be initialized by
** this callback. The caller will do so.
*/
int (*xCreate)(
@@ -115608,7 +117354,7 @@ int fts3_term_cnt(int iTerm, int iCol);
** May you share freely, never taking more than you give.
**
*************************************************************************
-** This is the header file for the generic hash-table implemenation
+** This is the header file for the generic hash-table implementation
** used in SQLite. We've modified it slightly to serve as a standalone
** hash table implementation for the full-text indexing module.
**
@@ -117515,7 +119261,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
}else{
rc = sqlite3_reset(pCsr->pStmt);
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
- /* If no row was found and no error has occured, then the %_content
+ /* If no row was found and no error has occurred, then the %_content
** table is missing a row that is present in the full-text index.
** The data structures are corrupt. */
rc = FTS_CORRUPT_VTAB;
@@ -118755,7 +120501,7 @@ static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
}
/*
-** This function retreives the doclist for the specified term (or term
+** This function retrieves the doclist for the specified term (or term
** prefix) from the database.
*/
static int fts3TermSelect(
@@ -119506,7 +121252,7 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const
#endif
/*
-** Initialise the fts3 extension. If this extension is built as part
+** Initialize the fts3 extension. If this extension is built as part
** of the sqlite library, then this function is called directly by
** SQLite. If fts3 is built as a dynamically loadable extension, this
** function is called by the sqlite3_extension_init() entry point.
@@ -119540,7 +121286,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
sqlite3Fts3SimpleTokenizerModule(&pSimple);
sqlite3Fts3PorterTokenizerModule(&pPorter);
- /* Allocate and initialise the hash-table used to store tokenizers. */
+ /* Allocate and initialize the hash-table used to store tokenizers. */
pHash = sqlite3_malloc(sizeof(Fts3Hash));
if( !pHash ){
rc = SQLITE_NOMEM;
@@ -120687,35 +122433,39 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
- aTmp = sqlite3_malloc(nTmp*2);
- if( !aTmp ){
- *pRc = SQLITE_NOMEM;
+ if( nTmp==0 ){
res = 0;
}else{
- char *aPoslist = p->pPhrase->doclist.pList;
- int nToken = p->pPhrase->nToken;
+ aTmp = sqlite3_malloc(nTmp*2);
+ if( !aTmp ){
+ *pRc = SQLITE_NOMEM;
+ res = 0;
+ }else{
+ char *aPoslist = p->pPhrase->doclist.pList;
+ int nToken = p->pPhrase->nToken;
- for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
- Fts3Phrase *pPhrase = p->pRight->pPhrase;
- int nNear = p->nNear;
- res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
- }
-
- aPoslist = pExpr->pRight->pPhrase->doclist.pList;
- nToken = pExpr->pRight->pPhrase->nToken;
- for(p=pExpr->pLeft; p && res; p=p->pLeft){
- int nNear;
- Fts3Phrase *pPhrase;
- assert( p->pParent && p->pParent->pLeft==p );
- nNear = p->pParent->nNear;
- pPhrase = (
- p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
- );
- res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+ for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
+ Fts3Phrase *pPhrase = p->pRight->pPhrase;
+ int nNear = p->nNear;
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+ }
+
+ aPoslist = pExpr->pRight->pPhrase->doclist.pList;
+ nToken = pExpr->pRight->pPhrase->nToken;
+ for(p=pExpr->pLeft; p && res; p=p->pLeft){
+ int nNear;
+ Fts3Phrase *pPhrase;
+ assert( p->pParent && p->pParent->pLeft==p );
+ nNear = p->pParent->nNear;
+ pPhrase = (
+ p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
+ );
+ res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
+ }
}
+
+ sqlite3_free(aTmp);
}
-
- sqlite3_free(aTmp);
}
return res;
@@ -121135,7 +122885,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
** of the current row.
**
** More specifically, the returned buffer contains 1 varint for each
-** occurence of the phrase in the column, stored using the normal (delta+2)
+** occurrence of the phrase in the column, stored using the normal (delta+2)
** compression and is terminated by either an 0x01 or 0x00 byte. For example,
** if the requested column contains "a b X c d X X" and the position-list
** for 'X' is requested, the buffer returned may contain:
@@ -121874,7 +123624,7 @@ struct ParseContext {
** This function is equivalent to the standard isspace() function.
**
** The standard isspace() can be awkward to use safely, because although it
-** is defined to accept an argument of type int, its behaviour when passed
+** is defined to accept an argument of type int, its behavior when passed
** an integer that falls outside of the range of the unsigned char type
** is undefined (and sometimes, "undefined" means segfault). This wrapper
** is defined to accept an argument of type char, and always returns 0 for
@@ -121953,7 +123703,7 @@ static int getNextToken(
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
if( rc==SQLITE_OK ){
const char *zToken;
- int nToken, iStart, iEnd, iPosition;
+ int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
int nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
@@ -122068,7 +123818,7 @@ static int getNextString(
int ii;
for(ii=0; rc==SQLITE_OK; ii++){
const char *zByte;
- int nByte, iBegin, iEnd, iPos;
+ int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0;
rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
if( rc==SQLITE_OK ){
Fts3PhraseToken *pToken;
@@ -124065,10 +125815,10 @@ static void testFunc(
const char *azArg[64];
const char *zToken;
- int nToken;
- int iStart;
- int iEnd;
- int iPos;
+ int nToken = 0;
+ int iStart = 0;
+ int iEnd = 0;
+ int iPos = 0;
int i;
Tcl_Obj *pRet;
@@ -124242,7 +125992,7 @@ static void intTestFunc(
/*
** Set up SQL objects in database db used to access the contents of
** the hash table pointed to by argument pHash. The hash table must
-** been initialised to use string keys, and to take a private copy
+** been initialized to use string keys, and to take a private copy
** of the key when a value is inserted. i.e. by a call similar to:
**
** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
@@ -125315,16 +127065,16 @@ static int fts3PendingTermsAdd(
int iLangid, /* Language id to use */
const char *zText, /* Text of document to be inserted */
int iCol, /* Column into which text is being inserted */
- u32 *pnWord /* OUT: Number of tokens inserted */
+ u32 *pnWord /* IN/OUT: Incr. by number tokens inserted */
){
int rc;
- int iStart;
- int iEnd;
- int iPos;
+ int iStart = 0;
+ int iEnd = 0;
+ int iPos = 0;
int nWord = 0;
char const *zToken;
- int nToken;
+ int nToken = 0;
sqlite3_tokenizer *pTokenizer = p->pTokenizer;
sqlite3_tokenizer_module const *pModule = pTokenizer->pModule;
@@ -125379,7 +127129,7 @@ static int fts3PendingTermsAdd(
}
pModule->xClose(pCsr);
- *pnWord = nWord;
+ *pnWord += nWord;
return (rc==SQLITE_DONE ? SQLITE_OK : rc);
}
@@ -125583,11 +127333,13 @@ static void fts3DeleteTerms(
int *pRC, /* Result code */
Fts3Table *p, /* The FTS table to delete from */
sqlite3_value *pRowid, /* The docid to be deleted */
- u32 *aSz /* Sizes of deleted document written here */
+ u32 *aSz, /* Sizes of deleted document written here */
+ int *pbFound /* OUT: Set to true if row really does exist */
){
int rc;
sqlite3_stmt *pSelect;
+ assert( *pbFound==0 );
if( *pRC ) return;
rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid);
if( rc==SQLITE_OK ){
@@ -125605,6 +127357,7 @@ static void fts3DeleteTerms(
*pRC = rc;
return;
}
+ *pbFound = 1;
}
rc = sqlite3_reset(pSelect);
}else{
@@ -126018,6 +127771,7 @@ static int fts3SegReaderNextDocid(
*pnOffsetList = (int)(p - pReader->pOffsetList - 1);
}
+ /* List may have been edited in place by fts3EvalNearTrim() */
while( papSegment, nMerge, j, xCmp);
+ if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
+ rc = fts3MsrBufferData(pMsr, pList, nList+1);
+ if( rc!=SQLITE_OK ) return rc;
+ assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
+ pList = pMsr->aBuffer;
+ }
+
if( pMsr->iColFilter>=0 ){
- fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
+ fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList);
}
if( nList>0 ){
- if( fts3SegReaderIsPending(apSegment[0]) ){
- rc = fts3MsrBufferData(pMsr, pList, nList+1);
- if( rc!=SQLITE_OK ) return rc;
- *paPoslist = pMsr->aBuffer;
- assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
- }else{
- *paPoslist = pList;
- }
+ *paPoslist = pList;
*piDocid = iDocid;
*pnPoslist = nList;
break;
@@ -127392,7 +129153,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
}
if( isColFilter ){
- fts3ColumnFilter(pFilter->iCol, &pList, &nList);
+ fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList);
}
if( !isIgnoreEmpty || nList>0 ){
@@ -127829,7 +129590,7 @@ static int fts3DoRebuild(Fts3Table *p){
int iCol;
int iLangid = langidFromSelect(p, pStmt);
rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0));
- aSz[p->nColumn] = 0;
+ memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1));
for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){
const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1);
rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]);
@@ -129473,9 +131234,9 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
- int nToken; /* Number of bytes in token */
- int iDum1, iDum2; /* Dummy variables */
- int iPos; /* Position of token in zText */
+ int nToken = 0; /* Number of bytes in token */
+ int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+ int iPos = 0; /* Position of token in zText */
rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
if( rc==SQLITE_OK ){
@@ -129642,9 +131403,9 @@ SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){
rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC);
while( rc==SQLITE_OK ){
char const *zToken; /* Buffer containing token */
- int nToken; /* Number of bytes in token */
- int iDum1, iDum2; /* Dummy variables */
- int iPos; /* Position of token in zText */
+ int nToken = 0; /* Number of bytes in token */
+ int iDum1 = 0, iDum2 = 0; /* Dummy variables */
+ int iPos = 0; /* Position of token in zText */
rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos);
for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){
@@ -129733,28 +131494,32 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken(
static int fts3DeleteByRowid(
Fts3Table *p,
sqlite3_value *pRowid,
- int *pnDoc,
+ int *pnChng, /* IN/OUT: Decrement if row is deleted */
u32 *aSzDel
){
- int isEmpty = 0;
- int rc = fts3IsEmpty(p, pRowid, &isEmpty);
- if( rc==SQLITE_OK ){
- if( isEmpty ){
- /* Deleting this row means the whole table is empty. In this case
- ** delete the contents of all three tables and throw away any
- ** data in the pendingTerms hash table. */
- rc = fts3DeleteAll(p, 1);
- *pnDoc = *pnDoc - 1;
- }else{
- fts3DeleteTerms(&rc, p, pRowid, aSzDel);
- if( p->zContentTbl==0 ){
- fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
- if( sqlite3_changes(p->db) ) *pnDoc = *pnDoc - 1;
+ int rc = SQLITE_OK; /* Return code */
+ int bFound = 0; /* True if *pRowid really is in the table */
+
+ fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound);
+ if( bFound && rc==SQLITE_OK ){
+ int isEmpty = 0; /* Deleting *pRowid leaves the table empty */
+ rc = fts3IsEmpty(p, pRowid, &isEmpty);
+ if( rc==SQLITE_OK ){
+ if( isEmpty ){
+ /* Deleting this row means the whole table is empty. In this case
+ ** delete the contents of all three tables and throw away any
+ ** data in the pendingTerms hash table. */
+ rc = fts3DeleteAll(p, 1);
+ *pnChng = 0;
+ memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2);
}else{
- *pnDoc = *pnDoc - 1;
- }
- if( p->bHasDocsize ){
- fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
+ *pnChng = *pnChng - 1;
+ if( p->zContentTbl==0 ){
+ fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid);
+ }
+ if( p->bHasDocsize ){
+ fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid);
+ }
}
}
}
@@ -129785,7 +131550,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
int rc = SQLITE_OK; /* Return Code */
int isRemove = 0; /* True for an UPDATE or DELETE */
u32 *aSzIns = 0; /* Sizes of inserted documents */
- u32 *aSzDel; /* Sizes of deleted documents */
+ u32 *aSzDel = 0; /* Sizes of deleted documents */
int nChng = 0; /* Net change in number of documents */
int bInsertDone = 0;
@@ -129813,13 +131578,13 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
}
/* Allocate space to hold the change in document sizes */
- aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 );
- if( aSzIns==0 ){
+ aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 );
+ if( aSzDel==0 ){
rc = SQLITE_NOMEM;
goto update_out;
}
- aSzDel = &aSzIns[p->nColumn+1];
- memset(aSzIns, 0, sizeof(aSzIns[0])*(p->nColumn+1)*2);
+ aSzIns = &aSzDel[p->nColumn+1];
+ memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2);
/* If this is an INSERT operation, or an UPDATE that modifies the rowid
** value, then this operation requires constraint handling.
@@ -129904,7 +131669,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(
}
update_out:
- sqlite3_free(aSzIns);
+ sqlite3_free(aSzDel);
sqlite3Fts3SegmentsClose(p);
return rc;
}
@@ -130325,9 +132090,9 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
** is the snippet with the highest score, where scores are calculated
** by adding:
**
-** (a) +1 point for each occurence of a matchable phrase in the snippet.
+** (a) +1 point for each occurrence of a matchable phrase in the snippet.
**
-** (b) +1000 points for the first occurence of each matchable phrase in
+** (b) +1000 points for the first occurrence of each matchable phrase in
** the snippet for which the corresponding mCovered bit is not set.
**
** The selected snippet parameters are stored in structure *pFragment before
@@ -130512,7 +132277,7 @@ static int fts3SnippetShift(
return rc;
}
while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){
- const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3;
+ const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0;
rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent);
}
pMod->xClose(pC);
@@ -130556,8 +132321,6 @@ static int fts3SnippetText(
int iCol = pFragment->iCol+1; /* Query column to extract text from */
sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */
- const char *ZDUMMY; /* Dummy argument used with tokenizer */
- int DUMMY1; /* Dummy argument used with tokenizer */
zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol);
if( zDoc==0 ){
@@ -130576,10 +132339,23 @@ static int fts3SnippetText(
}
while( rc==SQLITE_OK ){
- int iBegin; /* Offset in zDoc of start of token */
- int iFin; /* Offset in zDoc of end of token */
- int isHighlight; /* True for highlighted terms */
+ const char *ZDUMMY; /* Dummy argument used with tokenizer */
+ int DUMMY1 = -1; /* Dummy argument used with tokenizer */
+ int iBegin = 0; /* Offset in zDoc of start of token */
+ int iFin = 0; /* Offset in zDoc of end of token */
+ int isHighlight = 0; /* True for highlighted terms */
+ /* Variable DUMMY1 is initialized to a negative value above. Elsewhere
+ ** in the FTS code the variable that the third argument to xNext points to
+ ** is initialized to zero before the first (*but not necessarily
+ ** subsequent*) call to xNext(). This is done for a particular application
+ ** that needs to know whether or not the tokenizer is being used for
+ ** snippet generation or for some other purpose.
+ **
+ ** Extreme care is required when writing code to depend on this
+ ** initialization. It is not a documented part of the tokenizer interface.
+ ** If a tokenizer is used directly by any code outside of FTS, this
+ ** convention might not be respected. */
rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_DONE ){
@@ -131269,8 +133045,6 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
){
Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab;
sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule;
- const char *ZDUMMY; /* Dummy argument used with xNext() */
- int NDUMMY; /* Dummy argument used with xNext() */
int rc; /* Return Code */
int nToken; /* Number of tokens in query */
int iCol; /* Column currently being processed */
@@ -131303,9 +133077,11 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets(
*/
for(iCol=0; iColnColumn; iCol++){
sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */
- int iStart;
- int iEnd;
- int iCurrent;
+ const char *ZDUMMY; /* Dummy argument used with xNext() */
+ int NDUMMY = 0; /* Dummy argument used with xNext() */
+ int iStart = 0;
+ int iEnd = 0;
+ int iCurrent = 0;
const char *zDoc;
int nDoc;
@@ -131571,7 +133347,7 @@ static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
**
** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
-** It is not possible to change the behaviour of the tokenizer with respect
+** It is not possible to change the behavior of the tokenizer with respect
** to these codepoints.
*/
static int unicodeAddExceptions(
@@ -134869,12 +136645,12 @@ static int newRowid(Rtree *pRtree, i64 *piRowid){
*/
static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
int rc; /* Return code */
- RtreeNode *pLeaf; /* Leaf node containing record iDelete */
+ RtreeNode *pLeaf = 0; /* Leaf node containing record iDelete */
int iCell; /* Index of iDelete cell in pLeaf */
RtreeNode *pRoot; /* Root node of rtree structure */
- /* Obtain a reference to the root node to initialise Rtree.iDepth */
+ /* Obtain a reference to the root node to initialize Rtree.iDepth */
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
/* Obtain a reference to the leaf node that contains the entry
@@ -135072,7 +136848,7 @@ static int rtreeUpdate(
*/
if( rc==SQLITE_OK && nData>1 ){
/* Insert the new record into the r-tree */
- RtreeNode *pLeaf;
+ RtreeNode *pLeaf = 0;
/* Figure out the rowid of the new row. */
if( bHaveRowid==0 ){
@@ -135258,7 +137034,8 @@ static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
static int getNodeSize(
sqlite3 *db, /* Database handle */
Rtree *pRtree, /* Rtree handle */
- int isCreate /* True for xCreate, false for xConnect */
+ int isCreate, /* True for xCreate, false for xConnect */
+ char **pzErr /* OUT: Error message, if any */
){
int rc;
char *zSql;
@@ -135271,6 +137048,8 @@ static int getNodeSize(
if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)iNodeSize ){
pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
}
+ }else{
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
}else{
zSql = sqlite3_mprintf(
@@ -135278,6 +137057,9 @@ static int getNodeSize(
pRtree->zDb, pRtree->zName
);
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
+ if( rc!=SQLITE_OK ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
}
sqlite3_free(zSql);
@@ -135341,7 +137123,7 @@ static int rtreeInit(
memcpy(pRtree->zName, argv[2], nName);
/* Figure out the node size to use. */
- rc = getNodeSize(db, pRtree, isCreate);
+ rc = getNodeSize(db, pRtree, isCreate, pzErr);
/* Create/Connect to the underlying relational database schema. If
** that is successful, call sqlite3_declare_vtab() to configure
@@ -136188,7 +137970,7 @@ static int icuOpen(
nChar = nInput+1;
pCsr = (IcuCursor *)sqlite3_malloc(
sizeof(IcuCursor) + /* IcuCursor */
- nChar * sizeof(UChar) + /* IcuCursor.aChar[] */
+ ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */
(nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */
);
if( !pCsr ){
@@ -136196,7 +137978,7 @@ static int icuOpen(
}
memset(pCsr, 0, sizeof(IcuCursor));
pCsr->aChar = (UChar *)&pCsr[1];
- pCsr->aOffset = (int *)&pCsr->aChar[nChar];
+ pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3];
pCsr->aOffset[iOut] = iInput;
U8_NEXT(zInput, iInput, nInput, c);
diff --git a/code/game/sqlite3.h b/code/game/sqlite3.h
index 5a1f9d4..69b4586 100644
--- a/code/game/sqlite3.h
+++ b/code/game/sqlite3.h
@@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.7.14.1"
-#define SQLITE_VERSION_NUMBER 3007014
-#define SQLITE_SOURCE_ID "2012-10-04 19:37:12 091570e46d04e84b67228e0bdbcd6e1fb60c6bdb"
+#define SQLITE_VERSION "3.7.16.2"
+#define SQLITE_VERSION_NUMBER 3007016
+#define SQLITE_SOURCE_ID "2013-04-12 11:52:43 cbea02d93865ce0e06789db95fd9168ebac970c7"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -288,7 +288,7 @@ typedef sqlite_uint64 sqlite3_uint64;
** [sqlite3_blob_close | close] all [BLOB handles], and
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
** with the [sqlite3] object prior to attempting to close the object. ^If
-** sqlite3_close() is called on a [database connection] that still has
+** sqlite3_close_v2() is called on a [database connection] that still has
** outstanding [prepared statements], [BLOB handles], and/or
** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
** of resources is deferred until all [prepared statements], [BLOB handles],
@@ -474,14 +474,26 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
+#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
+#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
+#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
+#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
+#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8))
+#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8))
+#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8))
+#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8))
+#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
+#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
/*
** CAPI3REF: Flags For File Open Operations
@@ -855,6 +867,26 @@ struct sqlite3_io_methods {
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
** file control occurs at the beginning of pragma statement analysis and so
** it is able to override built-in [PRAGMA] statements.
+**
+** [[SQLITE_FCNTL_BUSYHANDLER]]
+** ^This file-control may be invoked by SQLite on the database file handle
+** shortly after it is opened in order to provide a custom VFS with access
+** to the connections busy-handler callback. The argument is of type (void **)
+** - an array of two (void *) values. The first (void *) actually points
+** to a function of type (int (*)(void *)). In order to invoke the connections
+** busy-handler, this function should be invoked with the second (void *) in
+** the array as the only argument. If it returns non-zero, then the operation
+** should be retried. If it returns zero, the custom VFS should abandon the
+** current operation.
+**
+** [[SQLITE_FCNTL_TEMPFILENAME]]
+** ^Application can invoke this file-control to have SQLite generate a
+** temporary filename using the same algorithm that is followed to generate
+** temporary filenames for TEMP tables and other internal uses. The
+** argument should be a char** which will be filled with the filename
+** written into memory obtained from [sqlite3_malloc()]. The caller should
+** invoke [sqlite3_free()] on the result to avoid a memory leak.
+**
**
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -871,6 +903,8 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_VFSNAME 12
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
#define SQLITE_FCNTL_PRAGMA 14
+#define SQLITE_FCNTL_BUSYHANDLER 15
+#define SQLITE_FCNTL_TEMPFILENAME 16
/*
** CAPI3REF: Mutex Handle
@@ -1567,11 +1601,39 @@ struct sqlite3_mem_methods {
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
**
+** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]]