summaryrefslogtreecommitdiffstats
path: root/lib/libsqlite3/src/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libsqlite3/src/expr.c')
-rw-r--r--lib/libsqlite3/src/expr.c135
1 files changed, 97 insertions, 38 deletions
diff --git a/lib/libsqlite3/src/expr.c b/lib/libsqlite3/src/expr.c
index 660397e078a..dd4f5de15fc 100644
--- a/lib/libsqlite3/src/expr.c
+++ b/lib/libsqlite3/src/expr.c
@@ -114,8 +114,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
p = p->pLeft;
continue;
}
- assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
- if( op==TK_COLLATE ){
+ if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
@@ -920,6 +919,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->sortOrder = pOldItem->sortOrder;
pItem->done = 0;
+ pItem->bSpanIsTab = pOldItem->bSpanIsTab;
pItem->iOrderByCol = pOldItem->iOrderByCol;
pItem->iAlias = pOldItem->iAlias;
}
@@ -1278,6 +1278,7 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
case TK_UMINUS: {
int v;
if( sqlite3ExprIsInteger(p->pLeft, &v) ){
+ assert( v!=-2147483648 );
*pValue = -v;
rc = 1;
}
@@ -1596,15 +1597,15 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
/* Could not found an existing table or index to use as the RHS b-tree.
** We will have to generate an ephemeral table to do the job.
*/
- double savedNQueryLoop = pParse->nQueryLoop;
+ u32 savedNQueryLoop = pParse->nQueryLoop;
int rMayHaveNull = 0;
eType = IN_INDEX_EPH;
if( prNotFound ){
*prNotFound = rMayHaveNull = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
}else{
- testcase( pParse->nQueryLoop>(double)1 );
- pParse->nQueryLoop = (double)1;
+ testcase( pParse->nQueryLoop>0 );
+ pParse->nQueryLoop = 0;
if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
eType = IN_INDEX_ROWID;
}
@@ -1646,7 +1647,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
**
** If rMayHaveNull is zero, that means that the subquery is being used
** for membership testing only. There is no need to initialize any
-** registers to indicate the presense or absence of NULLs on the RHS.
+** registers to indicate the presence or absence of NULLs on the RHS.
**
** For a SELECT or EXISTS operator, return the register that holds the
** result. For IN operators or if an error occurs, the return value is 0.
@@ -1691,10 +1692,9 @@ int sqlite3CodeSubselect(
switch( pExpr->op ){
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 */
+ KeyInfo *pKeyInfo = 0; /* Key information */
if( rMayHaveNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
@@ -1718,9 +1718,7 @@ int sqlite3CodeSubselect(
pExpr->iTable = pParse->nTab++;
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
- memset(&keyInfo, 0, sizeof(keyInfo));
- keyInfo.nField = 1;
- keyInfo.aSortOrder = &sortOrder;
+ pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* Case 1: expr IN (SELECT ...)
@@ -1736,14 +1734,17 @@ int sqlite3CodeSubselect(
dest.affSdst = (u8)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pExpr->x.pSelect->iLimit = 0;
+ testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
+ sqlite3DbFree(pParse->db, pKeyInfo);
return 0;
}
pEList = pExpr->x.pSelect->pEList;
- if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){
- keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
- pEList->a[0].pExpr);
- }
+ assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
+ assert( pEList!=0 );
+ assert( pEList->nExpr>0 );
+ pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
+ pEList->a[0].pExpr);
}else if( ALWAYS(pExpr->x.pList!=0) ){
/* Case 2: expr IN (exprlist)
**
@@ -1760,8 +1761,9 @@ int sqlite3CodeSubselect(
if( !affinity ){
affinity = SQLITE_AFF_NONE;
}
- keyInfo.aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- keyInfo.aSortOrder = &sortOrder;
+ if( pKeyInfo ){
+ pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+ }
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
@@ -1800,8 +1802,8 @@ int sqlite3CodeSubselect(
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
- if( !isRowid ){
- sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
+ if( pKeyInfo ){
+ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO_HANDOFF);
}
break;
}
@@ -2361,15 +2363,20 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
/* Otherwise, fall thru into the TK_COLUMN case */
}
case TK_COLUMN: {
- if( pExpr->iTable<0 ){
- /* This only happens when coding check constraints */
- assert( pParse->ckBase>0 );
- inReg = pExpr->iColumn + pParse->ckBase;
- }else{
- inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
- pExpr->iColumn, pExpr->iTable, target,
- pExpr->op2);
+ int iTab = pExpr->iTable;
+ if( iTab<0 ){
+ if( pParse->ckBase>0 ){
+ /* Generating CHECK constraints or inserting into partial index */
+ inReg = pExpr->iColumn + pParse->ckBase;
+ break;
+ }else{
+ /* Deleting from a partial index */
+ iTab = pParse->iPartIdxTab;
+ }
}
+ inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
+ pExpr->iColumn, iTab, target,
+ pExpr->op2);
break;
}
case TK_INTEGER: {
@@ -3497,6 +3504,7 @@ static void exprCodeBetween(
compRight.pLeft = &exprX;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
+ exprX.op2 = exprX.op;
exprX.op = TK_REGISTER;
if( jumpIfTrue ){
sqlite3ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
@@ -3792,6 +3800,12 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
** by a COLLATE operator at the top level. Return 2 if there are differences
** other than the top-level COLLATE operator.
**
+** If any subelement of pB has Expr.iTable==(-1) then it is allowed
+** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
+**
+** The pA side might be using TK_REGISTER. If that is the case and pB is
+** not using TK_REGISTER but is otherwise equivalent, then still return 0.
+**
** Sometimes this routine will return 2 even if the two expressions
** really are equivalent. If we cannot prove that the expressions are
** identical, we return 2 just to be safe. So if this routine
@@ -3802,7 +3816,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
*/
-int sqlite3ExprCompare(Expr *pA, Expr *pB){
+int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
if( pA==0||pB==0 ){
return pB==pA ? 0 : 2;
}
@@ -3812,19 +3826,22 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
return 2;
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
- if( pA->op!=pB->op ){
- if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){
+ if( pA->op!=pB->op && (pA->op!=TK_REGISTER || pA->op2!=pB->op) ){
+ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
return 1;
}
- if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){
+ if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<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;
- if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
+ 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( pA->iColumn!=pB->iColumn ) return 2;
+ if( pA->iTable!=pB->iTable
+ && pA->op!=TK_REGISTER
+ && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
if( ExprHasProperty(pA, EP_IntValue) ){
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
return 2;
@@ -3842,6 +3859,9 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
** Compare two ExprList objects. Return 0 if they are identical and
** non-zero if they differ in any way.
**
+** If any subelement of pB has Expr.iTable==(-1) then it is allowed
+** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
+**
** This routine might return non-zero for equivalent ExprLists. The
** only consequence will be disabled optimizations. But this routine
** must never return 0 if the two ExprList objects are different, or
@@ -3850,7 +3870,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
** Two NULL pointers are considered to be the same. But a NULL pointer
** always differs from a non-NULL pointer.
*/
-int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
+int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
int i;
if( pA==0 && pB==0 ) return 0;
if( pA==0 || pB==0 ) return 1;
@@ -3859,7 +3879,46 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
- if( sqlite3ExprCompare(pExprA, pExprB) ) return 1;
+ if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Return true if we can prove the pE2 will always be true if pE1 is
+** true. Return false if we cannot complete the proof or if pE2 might
+** be false. Examples:
+**
+** pE1: x==5 pE2: x==5 Result: true
+** pE1: x>0 pE2: x==5 Result: false
+** pE1: x=21 pE2: x=21 OR y=43 Result: true
+** pE1: x!=123 pE2: x IS NOT NULL Result: true
+** pE1: x!=?1 pE2: x IS NOT NULL Result: true
+** pE1: x IS NULL pE2: x IS NOT NULL Result: false
+** pE1: x IS ?2 pE2: x IS NOT NULL Reuslt: false
+**
+** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
+** Expr.iTable<0 then assume a table number given by iTab.
+**
+** When in doubt, return false. Returning true might give a performance
+** improvement. Returning false might cause a performance reduction, but
+** it will always give the correct answer and is hence always safe.
+*/
+int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
+ if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){
+ return 1;
+ }
+ if( pE2->op==TK_OR
+ && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
+ || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
+ ){
+ return 1;
+ }
+ if( pE2->op==TK_NOTNULL
+ && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
+ && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
+ ){
+ return 1;
}
return 0;
}
@@ -4044,7 +4103,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
- if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){
+ if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){
break;
}
}