mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Consider the values bound to SQL variables when determining whether or not a
partial index may be used. FossilOrigin-Name: 7b59c353b805c64689b4ae9df347705acbb5f116346ad77af8ce087da7893747
This commit is contained in:
81
src/expr.c
81
src/expr.c
@@ -1829,7 +1829,7 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
|
||||
** it constant. */
|
||||
for(i=0; i<pGroupBy->nExpr; i++){
|
||||
Expr *p = pGroupBy->a[i].pExpr;
|
||||
if( sqlite3ExprCompare(pExpr, p, -1)<2 ){
|
||||
if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
|
||||
CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p);
|
||||
if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){
|
||||
return WRC_Prune;
|
||||
@@ -4105,7 +4105,7 @@ int sqlite3ExprCodeAtInit(
|
||||
struct ExprList_item *pItem;
|
||||
int i;
|
||||
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
|
||||
if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){
|
||||
if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){
|
||||
return pItem->u.iConstExprReg;
|
||||
}
|
||||
}
|
||||
@@ -4660,6 +4660,48 @@ void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){
|
||||
sqlite3ExprDelete(db, pCopy);
|
||||
}
|
||||
|
||||
/*
|
||||
** Expression pVar is guaranteed to be an SQL variable. pExpr may be any
|
||||
** type of expression.
|
||||
**
|
||||
** If pExpr is a simple SQL value - an integer, real, string, blob
|
||||
** or NULL value - then the VDBE currently being prepared is configured
|
||||
** to re-prepare each time a new value is bound to variable pVar.
|
||||
**
|
||||
** Additionally, if pExpr is a simple SQL value and the value is the
|
||||
** same as that currently bound to variable pVar, non-zero is returned.
|
||||
** Otherwise, if the values are not the same or if pExpr is not a simple
|
||||
** SQL value, zero is returned.
|
||||
*/
|
||||
static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
|
||||
int res = 0;
|
||||
int iVar = pVar->iColumn;
|
||||
Expr *p = pExpr;
|
||||
|
||||
while( p->op==TK_UMINUS ) p = p->pLeft;
|
||||
if( p->op==TK_NULL || p->op==TK_INTEGER
|
||||
|| p->op==TK_FLOAT || p->op==TK_STRING
|
||||
|| p->op==TK_BLOB
|
||||
){
|
||||
sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
|
||||
sqlite3_value *pL;
|
||||
pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
|
||||
if( pL ){
|
||||
sqlite3_value *pR = 0;
|
||||
sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB,&pR);
|
||||
assert( pR || pParse->db->mallocFailed );
|
||||
if( pR && 0==sqlite3MemCompare(pL, pR, 0) ){
|
||||
res = 1;
|
||||
}
|
||||
sqlite3ValueFree(pR);
|
||||
sqlite3ValueFree(pL);
|
||||
}else if( p->op==TK_NULL ){
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** Do a deep comparison of two expression trees. Return 0 if the two
|
||||
@@ -4682,12 +4724,21 @@ void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){
|
||||
** 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 0 or 1 could lead to a malfunction.
|
||||
**
|
||||
** Argument pParse should normally be NULL. If it is not NULL and
|
||||
** expression pA contains SQL variable references, then the values
|
||||
** currently bound to those variable references may be compared to
|
||||
** simple SQL values in pB. See comments above function exprCompareVariable()
|
||||
** for details.
|
||||
*/
|
||||
int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
|
||||
int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
|
||||
u32 combinedFlags;
|
||||
if( pA==0 || pB==0 ){
|
||||
return pB==pA ? 0 : 2;
|
||||
}
|
||||
if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
|
||||
return 0;
|
||||
}
|
||||
combinedFlags = pA->flags | pB->flags;
|
||||
if( combinedFlags & EP_IntValue ){
|
||||
if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
|
||||
@@ -4696,10 +4747,10 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
|
||||
return 2;
|
||||
}
|
||||
if( pA->op!=pB->op ){
|
||||
if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
|
||||
if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){
|
||||
return 1;
|
||||
}
|
||||
if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){
|
||||
if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
@@ -4714,8 +4765,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
|
||||
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
|
||||
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
|
||||
if( combinedFlags & EP_xIsSelect ) return 2;
|
||||
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
|
||||
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
|
||||
if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
|
||||
if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
|
||||
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
||||
if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){
|
||||
if( pA->iColumn!=pB->iColumn ) return 2;
|
||||
@@ -4750,7 +4801,7 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
|
||||
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, iTab) ) return 1;
|
||||
if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -4760,7 +4811,7 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
|
||||
** are ignored.
|
||||
*/
|
||||
int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
|
||||
return sqlite3ExprCompare(
|
||||
return sqlite3ExprCompare(0,
|
||||
sqlite3ExprSkipCollate(pA),
|
||||
sqlite3ExprSkipCollate(pB),
|
||||
iTab);
|
||||
@@ -4786,20 +4837,20 @@ int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
|
||||
** 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 ){
|
||||
int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
|
||||
if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
|
||||
return 1;
|
||||
}
|
||||
if( pE2->op==TK_OR
|
||||
&& (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab)
|
||||
|| sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) )
|
||||
&& (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab)
|
||||
|| sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) )
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){
|
||||
Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft);
|
||||
testcase( pX!=pE1->pLeft );
|
||||
if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1;
|
||||
if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -5040,7 +5091,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, -1)==0 ){
|
||||
if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user