aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2014-01-02 17:57:16 +0000
committerdrh <drh@noemail.net>2014-01-02 17:57:16 +0000
commit991a19851112ffb03946a003350e9e148d631348 (patch)
tree9de6cdc58abb2c34703bde146b3c46bc43c708ee /src/expr.c
parentb00d8621392397de9104e5d191ad1d6f018dcd7a (diff)
downloadsqlite-991a19851112ffb03946a003350e9e148d631348.tar.gz
sqlite-991a19851112ffb03946a003350e9e148d631348.zip
Be more aggressive in optimizing constant conditional expressions.
FossilOrigin-Name: b7e39851a75b87ebca747b26a39989560fd6362b
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/src/expr.c b/src/expr.c
index 8ee73acb7..0db51fe43 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -523,16 +523,25 @@ Expr *sqlite3PExpr(
}
/*
-** Return 1 if an expression must be FALSE in all cases and 0 if the
-** expression might be true. This is an optimization. If is OK to
-** return 0 here even if the expression really is always false (a
-** false negative). But it is a bug to return 1 if the expression
-** might be true in some rare circumstances (a false positive.)
+** If the expression is always either TRUE or FALSE (respectively),
+** then return 1. If one cannot determine the truth value of the
+** expression at compile-time return 0.
+**
+** This is an optimization. If is OK to return 0 here even if
+** the expression really is always false or false (a false negative).
+** But it is a bug to return 1 if the expression might have different
+** boolean values in different circumstances (a false positive.)
**
** Note that if the expression is part of conditional for a
** LEFT JOIN, then we cannot determine at compile-time whether or not
** is it true or false, so always return 0.
*/
+static int exprAlwaysTrue(Expr *p){
+ int v = 0;
+ if( ExprHasProperty(p, EP_FromJoin) ) return 0;
+ if( !sqlite3ExprIsInteger(p, &v) ) return 0;
+ return v!=0;
+}
static int exprAlwaysFalse(Expr *p){
int v = 0;
if( ExprHasProperty(p, EP_FromJoin) ) return 0;
@@ -3614,10 +3623,16 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
}
#endif
default: {
- r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
- sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
- testcase( regFree1==0 );
- testcase( jumpIfNull==0 );
+ if( exprAlwaysTrue(pExpr) ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
+ }else if( exprAlwaysFalse(pExpr) ){
+ /* No-op */
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
+ sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
+ testcase( regFree1==0 );
+ testcase( jumpIfNull==0 );
+ }
break;
}
}
@@ -3759,10 +3774,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
}
#endif
default: {
- r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
- sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
- testcase( regFree1==0 );
- testcase( jumpIfNull==0 );
+ if( exprAlwaysFalse(pExpr) ){
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
+ }else if( exprAlwaysTrue(pExpr) ){
+ /* no-op */
+ }else{
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr, &regFree1);
+ sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
+ testcase( regFree1==0 );
+ testcase( jumpIfNull==0 );
+ }
break;
}
}