mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Improved optimization of the AND and OR operators.
FossilOrigin-Name: 0fbd154eb419b57b9c064c1f47346835d6324388b966b73f8a0122de065f08b1
This commit is contained in:
81
src/expr.c
81
src/expr.c
@@ -1808,6 +1808,33 @@ int sqlite3ExprTruthValue(const Expr *pExpr){
|
||||
return pExpr->u.zToken[4]==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** If pExpr is an AND or OR expression, try to simplify it by eliminating
|
||||
** terms that are always true or false. Return the simplified expression.
|
||||
** Or return the original expression if no simplification is possible.
|
||||
**
|
||||
** Examples:
|
||||
**
|
||||
** (x<10) AND true => (x<10)
|
||||
** (x<10) AND false => false
|
||||
** (x<10) AND (y=22 OR false) => (x<10) AND (y=22)
|
||||
** (x<10) AND (y=22 OR true) => (x<10)
|
||||
** (y=22) OR true => true
|
||||
*/
|
||||
Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
|
||||
assert( pExpr!=0 );
|
||||
if( pExpr->op==TK_AND || pExpr->op==TK_OR ){
|
||||
Expr *pRight = sqlite3ExprSimplifiedAndOr(pExpr->pRight);
|
||||
Expr *pLeft = sqlite3ExprSimplifiedAndOr(pExpr->pLeft);
|
||||
if( ExprAlwaysTrue(pLeft) || ExprAlwaysFalse(pRight) ){
|
||||
pExpr = pExpr->op==TK_AND ? pRight : pLeft;
|
||||
}else if( ExprAlwaysTrue(pRight) || ExprAlwaysFalse(pLeft) ){
|
||||
pExpr = pExpr->op==TK_AND ? pLeft : pRight;
|
||||
}
|
||||
}
|
||||
return pExpr;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** These routines are Walker callbacks used to check expressions to
|
||||
@@ -4399,18 +4426,23 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
if( NEVER(pExpr==0) ) return; /* No way this can happen */
|
||||
op = pExpr->op;
|
||||
switch( op ){
|
||||
case TK_AND: {
|
||||
int d2 = sqlite3VdbeMakeLabel(pParse);
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
sqlite3VdbeResolveLabel(v, d2);
|
||||
break;
|
||||
}
|
||||
case TK_AND:
|
||||
case TK_OR: {
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
|
||||
if( pAlt!=pExpr ){
|
||||
sqlite3ExprIfTrue(pParse, pAlt, dest, jumpIfNull);
|
||||
}else if( op==TK_AND ){
|
||||
int d2 = sqlite3VdbeMakeLabel(pParse);
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,
|
||||
jumpIfNull^SQLITE_JUMPIFNULL);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
sqlite3VdbeResolveLabel(v, d2);
|
||||
}else{
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_NOT: {
|
||||
@@ -4566,18 +4598,23 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
assert( pExpr->op!=TK_GE || op==OP_Lt );
|
||||
|
||||
switch( pExpr->op ){
|
||||
case TK_AND: {
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
break;
|
||||
}
|
||||
case TK_AND:
|
||||
case TK_OR: {
|
||||
int d2 = sqlite3VdbeMakeLabel(pParse);
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
sqlite3VdbeResolveLabel(v, d2);
|
||||
Expr *pAlt = sqlite3ExprSimplifiedAndOr(pExpr);
|
||||
if( pAlt!=pExpr ){
|
||||
sqlite3ExprIfFalse(pParse, pAlt, dest, jumpIfNull);
|
||||
}else if( pExpr->op==TK_AND ){
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
}else{
|
||||
int d2 = sqlite3VdbeMakeLabel(pParse);
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2,
|
||||
jumpIfNull^SQLITE_JUMPIFNULL);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
sqlite3VdbeResolveLabel(v, d2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TK_NOT: {
|
||||
|
||||
Reference in New Issue
Block a user