diff options
author | drh <drh@noemail.net> | 2010-01-07 15:17:02 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2010-01-07 15:17:02 +0000 |
commit | 1d9da70ad7602c63646ba84312c912ee3ea842a4 (patch) | |
tree | 4db790023d2cea9302a5b40eb062533fe6118cff /src/expr.c | |
parent | 93a696f61bce669693fb0eb9cdb7fef7f4b9a57d (diff) | |
download | sqlite-1d9da70ad7602c63646ba84312c912ee3ea842a4.tar.gz sqlite-1d9da70ad7602c63646ba84312c912ee3ea842a4.zip |
Fix the expression comparison logic to take the COLLATE operator into account.
Ticket [360c6073e197]
FossilOrigin-Name: 44bb1bfe5dedd8054ddd933941ee4112ed8d3b68
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 50 |
1 files changed, 27 insertions, 23 deletions
diff --git a/src/expr.c b/src/expr.c index 6ba373875..34655f97a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3415,57 +3415,61 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ } /* -** Do a deep comparison of two expression trees. Return TRUE (non-zero) -** if they are identical and return FALSE if they differ in any way. +** 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 +** other than the top-level COLLATE operator. ** -** Sometimes this routine will return FALSE even if the two expressions +** 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 FALSE just to be safe. So if this routine -** returns false, then you do not really know for certain if the two -** expressions are the same. But if you get a TRUE return, then you +** identical, we return 2 just to be safe. So if this routine +** returns 2, then you do not really know for certain if the two +** expressions are the same. But if you get a 0 or 1 return, then you ** can be sure the expressions are the same. In the places where -** this routine is used, it does not hurt to get an extra FALSE - that +** this routine is used, it does not hurt to get an extra 2 - that ** just might result in some slightly slower code. But returning -** an incorrect TRUE could lead to a malfunction. +** an incorrect 0 or 1 could lead to a malfunction. */ int sqlite3ExprCompare(Expr *pA, Expr *pB){ int i; if( pA==0||pB==0 ){ - return pB==pA; + return pB==pA ? 0 : 2; } assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ - return 0; + return 2; } - if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; - if( pA->op!=pB->op ) return 0; - if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0; - if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0; + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; + if( pA->op!=pB->op ) return 2; + if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; + if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; if( pA->x.pList && pB->x.pList ){ - if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0; + if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 2; for(i=0; i<pA->x.pList->nExpr; i++){ Expr *pExprA = pA->x.pList->a[i].pExpr; Expr *pExprB = pB->x.pList->a[i].pExpr; - if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0; + if( sqlite3ExprCompare(pExprA, pExprB) ) return 2; } }else if( pA->x.pList || pB->x.pList ){ - return 0; + return 2; } - if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; + if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; if( ExprHasProperty(pA, EP_IntValue) ){ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ - return 0; + return 2; } }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ - if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 0; + if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){ - return 0; + return 2; } } - return 1; + 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; } @@ -3596,7 +3600,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) ){ + if( sqlite3ExprCompare(pItem->pExpr, pExpr)==0 ){ break; } } |