Index: third_party/sqlite/src/src/expr.c |
diff --git a/third_party/sqlite/src/src/expr.c b/third_party/sqlite/src/src/expr.c |
index 2d96c8d8e6cf452aa181214b2f177b2f9c7fb928..d8d36afa5489970c616c1003583b003b55caf203 100644 |
--- a/third_party/sqlite/src/src/expr.c |
+++ b/third_party/sqlite/src/src/expr.c |
@@ -91,7 +91,7 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ |
} |
/* |
-** Skip over any TK_COLLATE or TK_AS operators and any unlikely() |
+** Skip over any TK_COLLATE operators and any unlikely() |
** or likelihood() function at the root of an expression. |
*/ |
Expr *sqlite3ExprSkipCollate(Expr *pExpr){ |
@@ -102,7 +102,7 @@ Expr *sqlite3ExprSkipCollate(Expr *pExpr){ |
assert( pExpr->op==TK_FUNCTION ); |
pExpr = pExpr->x.pList->a[0].pExpr; |
}else{ |
- assert( pExpr->op==TK_COLLATE || pExpr->op==TK_AS ); |
+ assert( pExpr->op==TK_COLLATE ); |
pExpr = pExpr->pLeft; |
} |
} |
@@ -133,9 +133,9 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ |
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); |
break; |
} |
- if( p->pTab!=0 |
- && (op==TK_AGG_COLUMN || op==TK_COLUMN |
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN |
|| op==TK_REGISTER || op==TK_TRIGGER) |
+ && p->pTab!=0 |
){ |
/* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally |
** a TK_COLUMN but was previously evaluated and cached in a register */ |
@@ -147,10 +147,25 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ |
break; |
} |
if( p->flags & EP_Collate ){ |
- if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ |
+ if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ |
p = p->pLeft; |
}else{ |
- p = p->pRight; |
+ Expr *pNext = p->pRight; |
+ /* The Expr.x union is never used at the same time as Expr.pRight */ |
+ assert( p->x.pList==0 || p->pRight==0 ); |
+ /* p->flags holds EP_Collate and p->pLeft->flags does not. And |
+ ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at |
+ ** least one EP_Collate. Thus the following two ALWAYS. */ |
+ if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){ |
+ int i; |
+ for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){ |
+ if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ |
+ pNext = p->x.pList->a[i].pExpr; |
+ break; |
+ } |
+ } |
+ } |
+ p = pNext; |
} |
}else{ |
break; |
@@ -176,13 +191,13 @@ char sqlite3CompareAffinity(Expr *pExpr, char aff2){ |
if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ |
return SQLITE_AFF_NUMERIC; |
}else{ |
- return SQLITE_AFF_NONE; |
+ return SQLITE_AFF_BLOB; |
} |
}else if( !aff1 && !aff2 ){ |
/* Neither side of the comparison is a column. Compare the |
** results directly. |
*/ |
- return SQLITE_AFF_NONE; |
+ return SQLITE_AFF_BLOB; |
}else{ |
/* One side is a column, the other is not. Use the columns affinity. */ |
assert( aff1==0 || aff2==0 ); |
@@ -206,7 +221,7 @@ static char comparisonAffinity(Expr *pExpr){ |
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); |
}else if( !aff ){ |
- aff = SQLITE_AFF_NONE; |
+ aff = SQLITE_AFF_BLOB; |
} |
return aff; |
} |
@@ -220,7 +235,7 @@ static char comparisonAffinity(Expr *pExpr){ |
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ |
char aff = comparisonAffinity(pExpr); |
switch( aff ){ |
- case SQLITE_AFF_NONE: |
+ case SQLITE_AFF_BLOB: |
return 1; |
case SQLITE_AFF_TEXT: |
return idx_affinity==SQLITE_AFF_TEXT; |
@@ -356,6 +371,9 @@ static void heightOfSelect(Select *p, int *pnHeight){ |
** Expr.pSelect member has a height of 1. Any other expression |
** has a height equal to the maximum height of any other |
** referenced Expr plus one. |
+** |
+** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags, |
+** if appropriate. |
*/ |
static void exprSetHeight(Expr *p){ |
int nHeight = 0; |
@@ -363,8 +381,9 @@ static void exprSetHeight(Expr *p){ |
heightOfExpr(p->pRight, &nHeight); |
if( ExprHasProperty(p, EP_xIsSelect) ){ |
heightOfSelect(p->x.pSelect, &nHeight); |
- }else{ |
+ }else if( p->x.pList ){ |
heightOfExprList(p->x.pList, &nHeight); |
+ p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); |
} |
p->nHeight = nHeight + 1; |
} |
@@ -373,8 +392,12 @@ static void exprSetHeight(Expr *p){ |
** Set the Expr.nHeight variable using the exprSetHeight() function. If |
** the height is greater than the maximum allowed expression depth, |
** leave an error in pParse. |
+** |
+** Also propagate all EP_Propagate flags from the Expr.x.pList into |
+** Expr.flags. |
*/ |
-void sqlite3ExprSetHeight(Parse *pParse, Expr *p){ |
+void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ |
+ if( pParse->nErr ) return; |
exprSetHeight(p); |
sqlite3ExprCheckHeight(pParse, p->nHeight); |
} |
@@ -388,8 +411,17 @@ int sqlite3SelectExprHeight(Select *p){ |
heightOfSelect(p, &nHeight); |
return nHeight; |
} |
-#else |
- #define exprSetHeight(y) |
+#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */ |
+/* |
+** Propagate all EP_Propagate flags from the Expr.x.pList into |
+** Expr.flags. |
+*/ |
+void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){ |
+ if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){ |
+ p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList); |
+ } |
+} |
+#define exprSetHeight(y) |
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */ |
/* |
@@ -401,7 +433,7 @@ int sqlite3SelectExprHeight(Select *p){ |
** is responsible for making sure the node eventually gets freed. |
** |
** If dequote is true, then the token (if it exists) is dequoted. |
-** If dequote is false, no dequoting is performance. The deQuote |
+** If dequote is false, no dequoting is performed. The deQuote |
** parameter is ignored if pToken is NULL or if the token does not |
** appear to be quoted. If the quotes were of the form "..." (double-quotes) |
** then the EP_DblQuoted flag is set on the expression node. |
@@ -491,11 +523,11 @@ void sqlite3ExprAttachSubtrees( |
}else{ |
if( pRight ){ |
pRoot->pRight = pRight; |
- pRoot->flags |= EP_Collate & pRight->flags; |
+ pRoot->flags |= EP_Propagate & pRight->flags; |
} |
if( pLeft ){ |
pRoot->pLeft = pLeft; |
- pRoot->flags |= EP_Collate & pLeft->flags; |
+ pRoot->flags |= EP_Propagate & pLeft->flags; |
} |
exprSetHeight(pRoot); |
} |
@@ -516,11 +548,11 @@ Expr *sqlite3PExpr( |
const Token *pToken /* Argument token */ |
){ |
Expr *p; |
- if( op==TK_AND && pLeft && pRight ){ |
+ if( op==TK_AND && pParse->nErr==0 ){ |
/* Take advantage of short-circuit false optimization for AND */ |
p = sqlite3ExprAnd(pParse->db, pLeft, pRight); |
}else{ |
- p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); |
+ p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1); |
sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); |
} |
if( p ) { |
@@ -595,7 +627,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){ |
} |
pNew->x.pList = pList; |
assert( !ExprHasProperty(pNew, EP_xIsSelect) ); |
- sqlite3ExprSetHeight(pParse, pNew); |
+ sqlite3ExprSetHeightAndFlags(pParse, pNew); |
return pNew; |
} |
@@ -821,6 +853,7 @@ static int dupedExprSize(Expr *p, int flags){ |
*/ |
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ |
Expr *pNew = 0; /* Value to return */ |
+ assert( flags==0 || flags==EXPRDUP_REDUCE ); |
if( p ){ |
const int isReduced = (flags&EXPRDUP_REDUCE); |
u8 *zAlloc; |
@@ -855,9 +888,9 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ |
assert( ExprHasProperty(p, EP_Reduced)==0 ); |
memcpy(zAlloc, p, nNewSize); |
}else{ |
- int nSize = exprStructSize(p); |
+ u32 nSize = (u32)exprStructSize(p); |
memcpy(zAlloc, p, nSize); |
- if( EXPR_FULLSIZE>nSize ){ |
+ if( nSize<EXPR_FULLSIZE ){ |
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize); |
} |
} |
@@ -949,6 +982,7 @@ static With *withDup(sqlite3 *db, With *p){ |
** part of the in-memory representation of the database schema. |
*/ |
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){ |
+ assert( flags==0 || flags==EXPRDUP_REDUCE ); |
return exprDup(db, p, flags, 0); |
} |
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ |
@@ -1004,16 +1038,18 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){ |
pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); |
pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); |
pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); |
- pNewItem->jointype = pOldItem->jointype; |
+ pNewItem->fg = pOldItem->fg; |
pNewItem->iCursor = pOldItem->iCursor; |
pNewItem->addrFillSub = pOldItem->addrFillSub; |
pNewItem->regReturn = pOldItem->regReturn; |
- pNewItem->isCorrelated = pOldItem->isCorrelated; |
- pNewItem->viaCoroutine = pOldItem->viaCoroutine; |
- pNewItem->isRecursive = pOldItem->isRecursive; |
- pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); |
- pNewItem->notIndexed = pOldItem->notIndexed; |
- pNewItem->pIndex = pOldItem->pIndex; |
+ if( pNewItem->fg.isIndexedBy ){ |
+ pNewItem->u1.zIndexedBy = sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy); |
+ } |
+ pNewItem->pIBIndex = pOldItem->pIBIndex; |
+ if( pNewItem->fg.isTabFunc ){ |
+ pNewItem->u1.pFuncArg = |
+ sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags); |
+ } |
pTab = pNewItem->pTab = pOldItem->pTab; |
if( pTab ){ |
pTab->nRef++; |
@@ -1129,6 +1165,20 @@ no_mem: |
} |
/* |
+** Set the sort order for the last element on the given ExprList. |
+*/ |
+void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){ |
+ if( p==0 ) return; |
+ assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 ); |
+ assert( p->nExpr>0 ); |
+ if( iSortOrder<0 ){ |
+ assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC ); |
+ return; |
+ } |
+ p->a[p->nExpr-1].sortOrder = (u8)iSortOrder; |
+} |
+ |
+/* |
** Set the ExprList.a[].zName element of the most recently added item |
** on the expression list. |
** |
@@ -1213,20 +1263,40 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ |
} |
/* |
-** These routines are Walker callbacks. Walker.u.pi is a pointer |
-** to an integer. These routines are checking an expression to see |
-** if it is a constant. Set *Walker.u.i to 0 if the expression is |
-** not constant. |
+** Return the bitwise-OR of all Expr.flags fields in the given |
+** ExprList. |
+*/ |
+u32 sqlite3ExprListFlags(const ExprList *pList){ |
+ int i; |
+ u32 m = 0; |
+ if( pList ){ |
+ for(i=0; i<pList->nExpr; i++){ |
+ Expr *pExpr = pList->a[i].pExpr; |
+ if( ALWAYS(pExpr) ) m |= pExpr->flags; |
+ } |
+ } |
+ return m; |
+} |
+ |
+/* |
+** These routines are Walker callbacks used to check expressions to |
+** see if they are "constant" for some definition of constant. The |
+** Walker.eCode value determines the type of "constant" we are looking |
+** for. |
** |
** These callback routines are used to implement the following: |
** |
-** sqlite3ExprIsConstant() pWalker->u.i==1 |
-** sqlite3ExprIsConstantNotJoin() pWalker->u.i==2 |
-** sqlite3ExprIsConstantOrFunction() pWalker->u.i==3 or 4 |
+** sqlite3ExprIsConstant() pWalker->eCode==1 |
+** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2 |
+** sqlite3ExprIsTableConstant() pWalker->eCode==3 |
+** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5 |
+** |
+** In all cases, the callbacks set Walker.eCode=0 and abort if the expression |
+** is found to not be a constant. |
** |
** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions |
-** in a CREATE TABLE statement. The Walker.u.i value is 4 when parsing |
-** an existing schema and 3 when processing a new statement. A bound |
+** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing |
+** an existing schema and 4 when processing a new statement. A bound |
** parameter raises an error for new statements, but is silently converted |
** to NULL for existing schemas. This allows sqlite_master tables that |
** contain a bound parameter because they were generated by older versions |
@@ -1235,23 +1305,25 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ |
*/ |
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ |
- /* If pWalker->u.i is 2 then any term of the expression that comes from |
- ** the ON or USING clauses of a join disqualifies the expression |
+ /* If pWalker->eCode is 2 then any term of the expression that comes from |
+ ** the ON or USING clauses of a left join disqualifies the expression |
** from being considered constant. */ |
- if( pWalker->u.i==2 && ExprHasProperty(pExpr, EP_FromJoin) ){ |
- pWalker->u.i = 0; |
+ if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){ |
+ pWalker->eCode = 0; |
return WRC_Abort; |
} |
switch( pExpr->op ){ |
/* Consider functions to be constant if all their arguments are constant |
- ** and either pWalker->u.i==3 or 4 or the function as the SQLITE_FUNC_CONST |
- ** flag. */ |
+ ** and either pWalker->eCode==4 or 5 or the function has the |
+ ** SQLITE_FUNC_CONST flag. */ |
case TK_FUNCTION: |
- if( pWalker->u.i>=3 || ExprHasProperty(pExpr,EP_Constant) ){ |
+ if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){ |
return WRC_Continue; |
+ }else{ |
+ pWalker->eCode = 0; |
+ return WRC_Abort; |
} |
- /* Fall through */ |
case TK_ID: |
case TK_COLUMN: |
case TK_AGG_FUNCTION: |
@@ -1260,18 +1332,22 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ |
testcase( pExpr->op==TK_COLUMN ); |
testcase( pExpr->op==TK_AGG_FUNCTION ); |
testcase( pExpr->op==TK_AGG_COLUMN ); |
- pWalker->u.i = 0; |
- return WRC_Abort; |
+ if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){ |
+ return WRC_Continue; |
+ }else{ |
+ pWalker->eCode = 0; |
+ return WRC_Abort; |
+ } |
case TK_VARIABLE: |
- if( pWalker->u.i==4 ){ |
+ if( pWalker->eCode==5 ){ |
/* Silently convert bound parameters that appear inside of CREATE |
** statements into a NULL when parsing the CREATE statement text out |
** of the sqlite_master table */ |
pExpr->op = TK_NULL; |
- }else if( pWalker->u.i==3 ){ |
+ }else if( pWalker->eCode==4 ){ |
/* A bound parameter in a CREATE statement that originates from |
** sqlite3_prepare() causes an error */ |
- pWalker->u.i = 0; |
+ pWalker->eCode = 0; |
return WRC_Abort; |
} |
/* Fall through */ |
@@ -1283,21 +1359,22 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){ |
} |
static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){ |
UNUSED_PARAMETER(NotUsed); |
- pWalker->u.i = 0; |
+ pWalker->eCode = 0; |
return WRC_Abort; |
} |
-static int exprIsConst(Expr *p, int initFlag){ |
+static int exprIsConst(Expr *p, int initFlag, int iCur){ |
Walker w; |
memset(&w, 0, sizeof(w)); |
- w.u.i = initFlag; |
+ w.eCode = initFlag; |
w.xExprCallback = exprNodeIsConstant; |
w.xSelectCallback = selectNodeIsConstant; |
+ w.u.iCur = iCur; |
sqlite3WalkExpr(&w, p); |
- return w.u.i; |
+ return w.eCode; |
} |
/* |
-** Walk an expression tree. Return 1 if the expression is constant |
+** Walk an expression tree. Return non-zero if the expression is constant |
** and 0 if it involves variables or function calls. |
** |
** For the purposes of this function, a double-quoted string (ex: "abc") |
@@ -1305,21 +1382,31 @@ static int exprIsConst(Expr *p, int initFlag){ |
** a constant. |
*/ |
int sqlite3ExprIsConstant(Expr *p){ |
- return exprIsConst(p, 1); |
+ return exprIsConst(p, 1, 0); |
} |
/* |
-** Walk an expression tree. Return 1 if the expression is constant |
+** Walk an expression tree. Return non-zero if the expression is constant |
** that does no originate from the ON or USING clauses of a join. |
** Return 0 if it involves variables or function calls or terms from |
** an ON or USING clause. |
*/ |
int sqlite3ExprIsConstantNotJoin(Expr *p){ |
- return exprIsConst(p, 2); |
+ return exprIsConst(p, 2, 0); |
} |
/* |
-** Walk an expression tree. Return 1 if the expression is constant |
+** Walk an expression tree. Return non-zero if the expression is constant |
+** for any single row of the table with cursor iCur. In other words, the |
+** expression must not refer to any non-deterministic function nor any |
+** table other than iCur. |
+*/ |
+int sqlite3ExprIsTableConstant(Expr *p, int iCur){ |
+ return exprIsConst(p, 3, iCur); |
+} |
+ |
+/* |
+** Walk an expression tree. Return non-zero if the expression is constant |
** or a function call with constant arguments. Return and 0 if there |
** are any variables. |
** |
@@ -1329,8 +1416,24 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){ |
*/ |
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ |
assert( isInit==0 || isInit==1 ); |
- return exprIsConst(p, 3+isInit); |
+ return exprIsConst(p, 4+isInit, 0); |
+} |
+ |
+#ifdef SQLITE_ENABLE_CURSOR_HINTS |
+/* |
+** Walk an expression tree. Return 1 if the expression contains a |
+** subquery of some kind. Return 0 if there are no subqueries. |
+*/ |
+int sqlite3ExprContainsSubquery(Expr *p){ |
+ Walker w; |
+ memset(&w, 0, sizeof(w)); |
+ w.eCode = 1; |
+ w.xExprCallback = sqlite3ExprWalkNoop; |
+ w.xSelectCallback = selectNodeIsConstant; |
+ sqlite3WalkExpr(&w, p); |
+ return w.eCode==0; |
} |
+#endif |
/* |
** If the expression p codes a constant integer that is small enough |
@@ -1415,7 +1518,7 @@ int sqlite3ExprCanBeNull(const Expr *p){ |
*/ |
int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){ |
u8 op; |
- if( aff==SQLITE_AFF_NONE ) return 1; |
+ if( aff==SQLITE_AFF_BLOB ) return 1; |
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } |
op = p->op; |
if( op==TK_REGISTER ) op = p->op2; |
@@ -1512,13 +1615,13 @@ int sqlite3CodeOnce(Parse *pParse){ |
** to be set to NULL if iCur contains one or more NULL values. |
*/ |
static void sqlite3SetHasNullFlag(Vdbe *v, int iCur, int regHasNull){ |
- int j1; |
+ int addr1; |
sqlite3VdbeAddOp2(v, OP_Integer, 0, regHasNull); |
- j1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); |
+ addr1 = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v); |
sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, regHasNull); |
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); |
VdbeComment((v, "first_entry_in(%d)", iCur)); |
- sqlite3VdbeJumpHere(v, j1); |
+ sqlite3VdbeJumpHere(v, addr1); |
} |
@@ -1625,7 +1728,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int *prRhsHasNull){ |
** ephemeral table. |
*/ |
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); |
- if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){ |
+ if( pParse->nErr==0 && isCandidateForInOpt(p) ){ |
sqlite3 *db = pParse->db; /* Database connection */ |
Table *pTab; /* Table <table>. */ |
Expr *pExpr; /* Expression <column> */ |
@@ -1790,9 +1893,10 @@ int sqlite3CodeSubselect( |
#ifndef SQLITE_OMIT_EXPLAIN |
if( pParse->explain==2 ){ |
- char *zMsg = sqlite3MPrintf( |
- pParse->db, "EXECUTE %s%s SUBQUERY %d", jmpIfDynamic>=0?"":"CORRELATED ", |
- pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId |
+ char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %s%s SUBQUERY %d", |
+ jmpIfDynamic>=0?"":"CORRELATED ", |
+ pExpr->op==TK_IN?"LIST":"SCALAR", |
+ pParse->iNextSelectId |
); |
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC); |
} |
@@ -1866,7 +1970,7 @@ int sqlite3CodeSubselect( |
int r1, r2, r3; |
if( !affinity ){ |
- affinity = SQLITE_AFF_NONE; |
+ affinity = SQLITE_AFF_BLOB; |
} |
if( pKeyInfo ){ |
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) ); |
@@ -1950,6 +2054,7 @@ int sqlite3CodeSubselect( |
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, |
&sqlite3IntTokens[1]); |
pSel->iLimit = 0; |
+ pSel->selFlags &= ~SF_MultiValue; |
if( sqlite3Select(pParse, pSel, &dest) ){ |
return 0; |
} |
@@ -2061,7 +2166,7 @@ static void sqlite3ExprCodeIN( |
} |
if( regCkNull ){ |
sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); |
+ sqlite3VdbeGoto(v, destIfFalse); |
} |
sqlite3VdbeResolveLabel(v, labelOk); |
sqlite3ReleaseTempReg(pParse, regCkNull); |
@@ -2079,7 +2184,7 @@ static void sqlite3ExprCodeIN( |
int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); |
sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); |
VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); |
+ sqlite3VdbeGoto(v, destIfNull); |
sqlite3VdbeJumpHere(v, addr1); |
} |
} |
@@ -2117,7 +2222,7 @@ static void sqlite3ExprCodeIN( |
** the presence of a NULL on the RHS makes a difference in the |
** outcome. |
*/ |
- int j1; |
+ int addr1; |
/* First check to see if the LHS is contained in the RHS. If so, |
** then the answer is TRUE the presence of NULLs in the RHS does |
@@ -2125,12 +2230,12 @@ static void sqlite3ExprCodeIN( |
** answer is NULL if the RHS contains NULLs and the answer is |
** FALSE if the RHS is NULL-free. |
*/ |
- j1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); |
+ addr1 = sqlite3VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1); |
VdbeCoverage(v); |
sqlite3VdbeAddOp2(v, OP_IsNull, rRhsHasNull, destIfNull); |
VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); |
- sqlite3VdbeJumpHere(v, j1); |
+ sqlite3VdbeGoto(v, destIfFalse); |
+ sqlite3VdbeJumpHere(v, addr1); |
} |
} |
} |
@@ -2140,17 +2245,6 @@ static void sqlite3ExprCodeIN( |
} |
#endif /* SQLITE_OMIT_SUBQUERY */ |
-/* |
-** Duplicate an 8-byte value |
-*/ |
-static char *dup8bytes(Vdbe *v, const char *in){ |
- char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8); |
- if( out ){ |
- memcpy(out, in, 8); |
- } |
- return out; |
-} |
- |
#ifndef SQLITE_OMIT_FLOATING_POINT |
/* |
** Generate an instruction that will put the floating point |
@@ -2163,12 +2257,10 @@ static char *dup8bytes(Vdbe *v, const char *in){ |
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ |
if( ALWAYS(z!=0) ){ |
double value; |
- char *zV; |
sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8); |
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */ |
if( negateFlag ) value = -value; |
- zV = dup8bytes(v, (char*)&value); |
- sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL); |
+ sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL); |
} |
} |
#endif |
@@ -2194,10 +2286,8 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){ |
assert( z!=0 ); |
c = sqlite3DecOrHexToI64(z, &value); |
if( c==0 || (c==2 && negFlag) ){ |
- char *zV; |
if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; } |
- zV = dup8bytes(v, (char*)&value); |
- sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64); |
+ sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64); |
}else{ |
#ifdef SQLITE_OMIT_FLOATING_POINT |
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z); |
@@ -2238,7 +2328,8 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){ |
int idxLru; |
struct yColCache *p; |
- assert( iReg>0 ); /* Register numbers are always positive */ |
+ /* Unless an error has occurred, register numbers are always positive. */ |
+ assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed ); |
assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */ |
/* The SQLITE_ColumnCache flag disables the column cache. This is used |
@@ -2362,6 +2453,28 @@ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ |
} |
} |
+/* Generate code that will load into register regOut a value that is |
+** appropriate for the iIdxCol-th column of index pIdx. |
+*/ |
+void sqlite3ExprCodeLoadIndexColumn( |
+ Parse *pParse, /* The parsing context */ |
+ Index *pIdx, /* The index whose column is to be loaded */ |
+ int iTabCur, /* Cursor pointing to a table row */ |
+ int iIdxCol, /* The column of the index to be loaded */ |
+ int regOut /* Store the index column value in this register */ |
+){ |
+ i16 iTabCol = pIdx->aiColumn[iIdxCol]; |
+ if( iTabCol==XN_EXPR ){ |
+ assert( pIdx->aColExpr ); |
+ assert( pIdx->aColExpr->nExpr>iIdxCol ); |
+ pParse->iSelfTab = iTabCur; |
+ sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr, regOut); |
+ }else{ |
+ sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable, iTabCur, |
+ iTabCol, regOut); |
+ } |
+} |
+ |
/* |
** Generate code to extract the value of the iCol-th column of a table. |
*/ |
@@ -2389,9 +2502,12 @@ void sqlite3ExprCodeGetColumnOfTable( |
/* |
** Generate code that will extract the iColumn-th column from |
-** table pTab and store the column value in a register. An effort |
-** is made to store the column value in register iReg, but this is |
-** not guaranteed. The location of the column value is returned. |
+** table pTab and store the column value in a register. |
+** |
+** An effort is made to store the column value in register iReg. This |
+** is not garanteeed for GetColumn() - the result can be stored in |
+** any register. But the result is guaranteed to land in register iReg |
+** for GetColumnToReg(). |
** |
** There must be an open cursor to pTab in iTable when this routine |
** is called. If iColumn<0 then code is generated that extracts the rowid. |
@@ -2402,7 +2518,7 @@ int sqlite3ExprCodeGetColumn( |
int iColumn, /* Index of the table column */ |
int iTable, /* The cursor pointing to the table */ |
int iReg, /* Store results here */ |
- u8 p5 /* P5 value for OP_Column */ |
+ u8 p5 /* P5 value for OP_Column + FLAGS */ |
){ |
Vdbe *v = pParse->pVdbe; |
int i; |
@@ -2424,6 +2540,17 @@ int sqlite3ExprCodeGetColumn( |
} |
return iReg; |
} |
+void sqlite3ExprCodeGetColumnToReg( |
+ Parse *pParse, /* Parsing and code generating context */ |
+ Table *pTab, /* Description of the table we are reading from */ |
+ int iColumn, /* Index of the table column */ |
+ int iTable, /* The cursor pointing to the table */ |
+ int iReg /* Store results here */ |
+){ |
+ int r1 = sqlite3ExprCodeGetColumn(pParse, pTab, iColumn, iTable, iReg, 0); |
+ if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg); |
+} |
+ |
/* |
** Clear all column cache entries. |
@@ -2547,8 +2674,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ |
inReg = pExpr->iColumn + pParse->ckBase; |
break; |
}else{ |
- /* Deleting from a partial index */ |
- iTab = pParse->iPartIdxTab; |
+ /* Coding an expression that is part of an index where column names |
+ ** in the index refer to the table to which the index belongs */ |
+ iTab = pParse->iSelfTab; |
} |
} |
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, |
@@ -2569,7 +2697,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ |
#endif |
case TK_STRING: { |
assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
- sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); |
+ sqlite3VdbeLoadString(v, target, pExpr->u.zToken); |
break; |
} |
case TK_NULL: { |
@@ -2608,10 +2736,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ |
inReg = pExpr->iTable; |
break; |
} |
- case TK_AS: { |
- inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); |
- break; |
- } |
#ifndef SQLITE_OMIT_CAST |
case TK_CAST: { |
/* Expressions of the form: CAST(pLeft AS token) */ |
@@ -2801,7 +2925,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ |
*/ |
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){ |
assert( nFarg>=1 ); |
- sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target); |
+ inReg = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target); |
break; |
} |
@@ -2842,7 +2966,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ |
} |
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ |
- sqlite3ExprCodeExprList(pParse, pFarg, r1, |
+ sqlite3ExprCodeExprList(pParse, pFarg, r1, 0, |
SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR); |
sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */ |
}else{ |
@@ -2871,7 +2995,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ |
if( !pColl ) pColl = db->pDfltColl; |
sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); |
} |
- sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target, |
+ sqlite3VdbeAddOp4(v, OP_Function0, constMask, r1, target, |
(char*)pDef, P4_FUNCDEF); |
sqlite3VdbeChangeP5(v, (u8)nFarg); |
if( nFarg && constMask==0 ){ |
@@ -2986,7 +3110,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ |
#ifndef SQLITE_OMIT_FLOATING_POINT |
/* If the column has REAL affinity, it may currently be stored as an |
- ** integer. Use OP_RealAffinity to make sure it is really real. */ |
+ ** integer. Use OP_RealAffinity to make sure it is really real. |
+ ** |
+ ** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to |
+ ** floating point when extracting it from the record. */ |
if( pExpr->iColumn>=0 |
&& pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL |
){ |
@@ -3063,7 +3190,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ |
sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL); |
testcase( aListelem[i+1].pExpr->op==TK_COLUMN ); |
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel); |
+ sqlite3VdbeGoto(v, endLabel); |
sqlite3ExprCachePop(pParse); |
sqlite3VdbeResolveLabel(v, nextCase); |
} |
@@ -3194,7 +3321,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ |
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target); |
}else{ |
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); |
- assert( pParse->pVdbe || pParse->db->mallocFailed ); |
+ assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); |
if( inReg!=target && pParse->pVdbe ){ |
sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target); |
} |
@@ -3202,6 +3329,18 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ |
} |
/* |
+** Make a transient copy of expression pExpr and then code it using |
+** sqlite3ExprCode(). This routine works just like sqlite3ExprCode() |
+** except that the input expression is guaranteed to be unchanged. |
+*/ |
+void sqlite3ExprCodeCopy(Parse *pParse, Expr *pExpr, int target){ |
+ sqlite3 *db = pParse->db; |
+ pExpr = sqlite3ExprDup(db, pExpr, 0); |
+ if( !db->mallocFailed ) sqlite3ExprCode(pParse, pExpr, target); |
+ sqlite3ExprDelete(db, pExpr); |
+} |
+ |
+/* |
** Generate code that will evaluate expression pExpr and store the |
** results in register target. The results are guaranteed to appear |
** in register target. If the expression is constant, then this routine |
@@ -3239,268 +3378,6 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){ |
exprToRegister(pExpr, iMem); |
} |
-#ifdef SQLITE_DEBUG |
-/* |
-** Generate a human-readable explanation of an expression tree. |
-*/ |
-void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ |
- const char *zBinOp = 0; /* Binary operator */ |
- const char *zUniOp = 0; /* Unary operator */ |
- pView = sqlite3TreeViewPush(pView, moreToFollow); |
- if( pExpr==0 ){ |
- sqlite3TreeViewLine(pView, "nil"); |
- sqlite3TreeViewPop(pView); |
- return; |
- } |
- switch( pExpr->op ){ |
- case TK_AGG_COLUMN: { |
- sqlite3TreeViewLine(pView, "AGG{%d:%d}", |
- pExpr->iTable, pExpr->iColumn); |
- break; |
- } |
- case TK_COLUMN: { |
- if( pExpr->iTable<0 ){ |
- /* This only happens when coding check constraints */ |
- sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn); |
- }else{ |
- sqlite3TreeViewLine(pView, "{%d:%d}", |
- pExpr->iTable, pExpr->iColumn); |
- } |
- break; |
- } |
- case TK_INTEGER: { |
- if( pExpr->flags & EP_IntValue ){ |
- sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue); |
- }else{ |
- sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken); |
- } |
- break; |
- } |
-#ifndef SQLITE_OMIT_FLOATING_POINT |
- case TK_FLOAT: { |
- sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); |
- break; |
- } |
-#endif |
- case TK_STRING: { |
- sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken); |
- break; |
- } |
- case TK_NULL: { |
- sqlite3TreeViewLine(pView,"NULL"); |
- break; |
- } |
-#ifndef SQLITE_OMIT_BLOB_LITERAL |
- case TK_BLOB: { |
- sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken); |
- break; |
- } |
-#endif |
- case TK_VARIABLE: { |
- sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)", |
- pExpr->u.zToken, pExpr->iColumn); |
- break; |
- } |
- case TK_REGISTER: { |
- sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable); |
- break; |
- } |
- case TK_AS: { |
- sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken); |
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); |
- break; |
- } |
- case TK_ID: { |
- sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken); |
- break; |
- } |
-#ifndef SQLITE_OMIT_CAST |
- case TK_CAST: { |
- /* Expressions of the form: CAST(pLeft AS token) */ |
- sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken); |
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); |
- break; |
- } |
-#endif /* SQLITE_OMIT_CAST */ |
- case TK_LT: zBinOp = "LT"; break; |
- case TK_LE: zBinOp = "LE"; break; |
- case TK_GT: zBinOp = "GT"; break; |
- case TK_GE: zBinOp = "GE"; break; |
- case TK_NE: zBinOp = "NE"; break; |
- case TK_EQ: zBinOp = "EQ"; break; |
- case TK_IS: zBinOp = "IS"; break; |
- case TK_ISNOT: zBinOp = "ISNOT"; break; |
- case TK_AND: zBinOp = "AND"; break; |
- case TK_OR: zBinOp = "OR"; break; |
- case TK_PLUS: zBinOp = "ADD"; break; |
- case TK_STAR: zBinOp = "MUL"; break; |
- case TK_MINUS: zBinOp = "SUB"; break; |
- case TK_REM: zBinOp = "REM"; break; |
- case TK_BITAND: zBinOp = "BITAND"; break; |
- case TK_BITOR: zBinOp = "BITOR"; break; |
- case TK_SLASH: zBinOp = "DIV"; break; |
- case TK_LSHIFT: zBinOp = "LSHIFT"; break; |
- case TK_RSHIFT: zBinOp = "RSHIFT"; break; |
- case TK_CONCAT: zBinOp = "CONCAT"; break; |
- case TK_DOT: zBinOp = "DOT"; break; |
- |
- case TK_UMINUS: zUniOp = "UMINUS"; break; |
- case TK_UPLUS: zUniOp = "UPLUS"; break; |
- case TK_BITNOT: zUniOp = "BITNOT"; break; |
- case TK_NOT: zUniOp = "NOT"; break; |
- case TK_ISNULL: zUniOp = "ISNULL"; break; |
- case TK_NOTNULL: zUniOp = "NOTNULL"; break; |
- |
- case TK_COLLATE: { |
- sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); |
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); |
- break; |
- } |
- |
- case TK_AGG_FUNCTION: |
- case TK_FUNCTION: { |
- ExprList *pFarg; /* List of function arguments */ |
- if( ExprHasProperty(pExpr, EP_TokenOnly) ){ |
- pFarg = 0; |
- }else{ |
- pFarg = pExpr->x.pList; |
- } |
- if( pExpr->op==TK_AGG_FUNCTION ){ |
- sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q", |
- pExpr->op2, pExpr->u.zToken); |
- }else{ |
- sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken); |
- } |
- if( pFarg ){ |
- sqlite3TreeViewExprList(pView, pFarg, 0, 0); |
- } |
- break; |
- } |
-#ifndef SQLITE_OMIT_SUBQUERY |
- case TK_EXISTS: { |
- sqlite3TreeViewLine(pView, "EXISTS-expr"); |
- sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); |
- break; |
- } |
- case TK_SELECT: { |
- sqlite3TreeViewLine(pView, "SELECT-expr"); |
- sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); |
- break; |
- } |
- case TK_IN: { |
- sqlite3TreeViewLine(pView, "IN"); |
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); |
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
- sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0); |
- }else{ |
- sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); |
- } |
- break; |
- } |
-#endif /* SQLITE_OMIT_SUBQUERY */ |
- |
- /* |
- ** x BETWEEN y AND z |
- ** |
- ** This is equivalent to |
- ** |
- ** x>=y AND x<=z |
- ** |
- ** X is stored in pExpr->pLeft. |
- ** Y is stored in pExpr->pList->a[0].pExpr. |
- ** Z is stored in pExpr->pList->a[1].pExpr. |
- */ |
- case TK_BETWEEN: { |
- Expr *pX = pExpr->pLeft; |
- Expr *pY = pExpr->x.pList->a[0].pExpr; |
- Expr *pZ = pExpr->x.pList->a[1].pExpr; |
- sqlite3TreeViewLine(pView, "BETWEEN"); |
- sqlite3TreeViewExpr(pView, pX, 1); |
- sqlite3TreeViewExpr(pView, pY, 1); |
- sqlite3TreeViewExpr(pView, pZ, 0); |
- break; |
- } |
- case TK_TRIGGER: { |
- /* If the opcode is TK_TRIGGER, then the expression is a reference |
- ** to a column in the new.* or old.* pseudo-tables available to |
- ** trigger programs. In this case Expr.iTable is set to 1 for the |
- ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn |
- ** is set to the column of the pseudo-table to read, or to -1 to |
- ** read the rowid field. |
- */ |
- sqlite3TreeViewLine(pView, "%s(%d)", |
- pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn); |
- break; |
- } |
- case TK_CASE: { |
- sqlite3TreeViewLine(pView, "CASE"); |
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); |
- sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0); |
- break; |
- } |
-#ifndef SQLITE_OMIT_TRIGGER |
- case TK_RAISE: { |
- const char *zType = "unk"; |
- switch( pExpr->affinity ){ |
- case OE_Rollback: zType = "rollback"; break; |
- case OE_Abort: zType = "abort"; break; |
- case OE_Fail: zType = "fail"; break; |
- case OE_Ignore: zType = "ignore"; break; |
- } |
- sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken); |
- break; |
- } |
-#endif |
- default: { |
- sqlite3TreeViewLine(pView, "op=%d", pExpr->op); |
- break; |
- } |
- } |
- if( zBinOp ){ |
- sqlite3TreeViewLine(pView, "%s", zBinOp); |
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 1); |
- sqlite3TreeViewExpr(pView, pExpr->pRight, 0); |
- }else if( zUniOp ){ |
- sqlite3TreeViewLine(pView, "%s", zUniOp); |
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); |
- } |
- sqlite3TreeViewPop(pView); |
-} |
-#endif /* SQLITE_DEBUG */ |
- |
-#ifdef SQLITE_DEBUG |
-/* |
-** Generate a human-readable explanation of an expression list. |
-*/ |
-void sqlite3TreeViewExprList( |
- TreeView *pView, |
- const ExprList *pList, |
- u8 moreToFollow, |
- const char *zLabel |
-){ |
- int i; |
- pView = sqlite3TreeViewPush(pView, moreToFollow); |
- if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST"; |
- if( pList==0 ){ |
- sqlite3TreeViewLine(pView, "%s (empty)", zLabel); |
- }else{ |
- sqlite3TreeViewLine(pView, "%s", zLabel); |
- for(i=0; i<pList->nExpr; i++){ |
- sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1); |
-#if 0 |
- 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); |
- } |
-#endif |
- } |
- } |
- sqlite3TreeViewPop(pView); |
-} |
-#endif /* SQLITE_DEBUG */ |
- |
/* |
** Generate code that pushes the value of every element of the given |
** expression list into a sequence of registers beginning at target. |
@@ -3512,16 +3389,22 @@ void sqlite3TreeViewExprList( |
** |
** The SQLITE_ECEL_FACTOR argument allows constant arguments to be |
** factored out into initialization code. |
+** |
+** The SQLITE_ECEL_REF flag means that expressions in the list with |
+** ExprList.a[].u.x.iOrderByCol>0 have already been evaluated and stored |
+** in registers at srcReg, and so the value can be copied from there. |
*/ |
int sqlite3ExprCodeExprList( |
Parse *pParse, /* Parsing context */ |
ExprList *pList, /* The expression list to be coded */ |
int target, /* Where to write results */ |
+ int srcReg, /* Source registers if SQLITE_ECEL_REF */ |
u8 flags /* SQLITE_ECEL_* flags */ |
){ |
struct ExprList_item *pItem; |
- int i, n; |
+ int i, j, n; |
u8 copyOp = (flags & SQLITE_ECEL_DUP) ? OP_Copy : OP_SCopy; |
+ Vdbe *v = pParse->pVdbe; |
assert( pList!=0 ); |
assert( target>0 ); |
assert( pParse->pVdbe!=0 ); /* Never gets this far otherwise */ |
@@ -3529,13 +3412,14 @@ int sqlite3ExprCodeExprList( |
if( !ConstFactorOk(pParse) ) flags &= ~SQLITE_ECEL_FACTOR; |
for(pItem=pList->a, i=0; i<n; i++, pItem++){ |
Expr *pExpr = pItem->pExpr; |
- if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ |
+ if( (flags & SQLITE_ECEL_REF)!=0 && (j = pList->a[i].u.x.iOrderByCol)>0 ){ |
+ sqlite3VdbeAddOp2(v, copyOp, j+srcReg-1, target+i); |
+ }else if( (flags & SQLITE_ECEL_FACTOR)!=0 && sqlite3ExprIsConstant(pExpr) ){ |
sqlite3ExprCodeAtInit(pParse, pExpr, target+i, 0); |
}else{ |
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i); |
if( inReg!=target+i ){ |
VdbeOp *pOp; |
- Vdbe *v = pParse->pVdbe; |
if( copyOp==OP_Copy |
&& (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy |
&& pOp->p1+pOp->p3+1==inReg |
@@ -3712,14 +3596,14 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ |
int destIfFalse = sqlite3VdbeMakeLabel(v); |
int destIfNull = jumpIfNull ? dest : destIfFalse; |
sqlite3ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); |
+ sqlite3VdbeGoto(v, dest); |
sqlite3VdbeResolveLabel(v, destIfFalse); |
break; |
} |
#endif |
default: { |
if( exprAlwaysTrue(pExpr) ){ |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); |
+ sqlite3VdbeGoto(v, dest); |
}else if( exprAlwaysFalse(pExpr) ){ |
/* No-op */ |
}else{ |
@@ -3875,7 +3759,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ |
#endif |
default: { |
if( exprAlwaysFalse(pExpr) ){ |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, dest); |
+ sqlite3VdbeGoto(v, dest); |
}else if( exprAlwaysTrue(pExpr) ){ |
/* no-op */ |
}else{ |
@@ -3893,6 +3777,21 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ |
} |
/* |
+** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before |
+** code generation, and that copy is deleted after code generation. This |
+** ensures that the original pExpr is unchanged. |
+*/ |
+void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){ |
+ sqlite3 *db = pParse->db; |
+ Expr *pCopy = sqlite3ExprDup(db, pExpr, 0); |
+ if( db->mallocFailed==0 ){ |
+ sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull); |
+ } |
+ sqlite3ExprDelete(db, pCopy); |
+} |
+ |
+ |
+/* |
** Do a deep comparison of two expression trees. Return 0 if the two |
** expressions are completely identical. Return 1 if they differ only |
** by a COLLATE operator at the top level. Return 2 if there are differences |
@@ -3935,8 +3834,10 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ |
} |
return 2; |
} |
- if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken ){ |
- if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
+ if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){ |
+ if( pA->op==TK_FUNCTION ){ |
+ if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2; |
+ }else if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ |
return pA->op==TK_COLLATE ? 1 : 2; |
} |
} |
@@ -3946,7 +3847,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ |
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2; |
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; |
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; |
- if( ALWAYS((combinedFlags & EP_Reduced)==0) ){ |
+ if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ |
if( pA->iColumn!=pB->iColumn ) return 2; |
if( pA->iTable!=pB->iTable |
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2; |
@@ -4048,10 +3949,11 @@ static int exprSrcCount(Walker *pWalker, Expr *pExpr){ |
int i; |
struct SrcCount *p = pWalker->u.pSrcCount; |
SrcList *pSrc = p->pSrc; |
- for(i=0; i<pSrc->nSrc; i++){ |
+ int nSrc = pSrc ? pSrc->nSrc : 0; |
+ for(i=0; i<nSrc; i++){ |
if( pExpr->iTable==pSrc->a[i].iCursor ) break; |
} |
- if( i<pSrc->nSrc ){ |
+ if( i<nSrc ){ |
p->nThis++; |
}else{ |
p->nOther++; |