aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2016-08-22 00:48:58 +0000
committerdrh <drh@noemail.net>2016-08-22 00:48:58 +0000
commitdb45bd5e826505fb6f8a02dd28c805a85c349f59 (patch)
tree7ec1d4c69836ff4fbc88dfb65ab328ba7dfcc810 /src/expr.c
parent84b19a3da16ebfd784fea1a42ea90c3473444ddb (diff)
downloadsqlite-db45bd5e826505fb6f8a02dd28c805a85c349f59.tar.gz
sqlite-db45bd5e826505fb6f8a02dd28c805a85c349f59.zip
Reinstate the mechanism in BETWEEN that avoids evaluating the first expression
more than once, but fix the affinity extractor so that it works with this mechanism. The de-duplication of the first expression still does not work for vector expressions, though. FossilOrigin-Name: 2f39987f21bd6dae8d2be610a1fd5f06f8878e9e
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c38
1 files changed, 23 insertions, 15 deletions
diff --git a/src/expr.c b/src/expr.c
index ea8ca32fd..88ff3e40f 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -39,17 +39,14 @@ char sqlite3ExprAffinity(Expr *pExpr){
assert( pExpr->flags&EP_xIsSelect );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
+ if( op==TK_REGISTER ) op = pExpr->op2;
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
return sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
- && pExpr->pTab!=0
- ){
- /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
- ** a TK_COLUMN but was previously evaluated and cached in a register */
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->pTab!=0 ){
int j = pExpr->iColumn;
if( j<0 ) return SQLITE_AFF_INTEGER;
assert( pExpr->pTab && j<pExpr->pTab->nCol );
@@ -4080,37 +4077,48 @@ static void exprCodeBetween(
void (*xJump)(Parse*,Expr*,int,int), /* Action to take */
int jumpIfNull /* Take the jump if the BETWEEN is NULL */
){
- Expr exprAnd; /* The AND operator in x>=y AND x<=z */
+ Expr exprAnd; /* The AND operator in x>=y AND x<=z */
Expr compLeft; /* The x>=y term */
Expr compRight; /* The x<=z term */
+ Expr exprX; /* The x subexpression */
+ int regFree1 = 0; /* Temporary use register */
- assert( xJump==0 || xJump==sqlite3ExprIfTrue || xJump==sqlite3ExprIfFalse );
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
memset(&compLeft, 0, sizeof(Expr));
memset(&compRight, 0, sizeof(Expr));
memset(&exprAnd, 0, sizeof(Expr));
+
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ exprX = *pExpr->pLeft;
exprAnd.op = TK_AND;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
compLeft.op = TK_GE;
- compLeft.pLeft = pExpr->pLeft;
+ compLeft.pLeft = &exprX;
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
compRight.op = TK_LE;
- compRight.pLeft = pExpr->pLeft;
+ compRight.pLeft = &exprX;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
+ if( sqlite3ExprIsVector(&exprX)==0 ){
+ exprToRegister(&exprX, sqlite3ExprCodeTemp(pParse, &exprX, &regFree1));
+ }
if( xJump ){
xJump(pParse, &exprAnd, dest, jumpIfNull);
}else{
- /*exprX.flags |= EP_FromJoin;*/
+ exprX.flags |= EP_FromJoin;
sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
}
+ sqlite3ReleaseTempReg(pParse, regFree1);
/* Ensure adequate test coverage */
- testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 );
- testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 );
- testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 );
- testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 );
+ testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 );
+ testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1!=0 );
+ testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1==0 );
+ testcase( xJump==sqlite3ExprIfTrue && jumpIfNull!=0 && regFree1!=0 );
+ testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1==0 );
+ testcase( xJump==sqlite3ExprIfFalse && jumpIfNull==0 && regFree1!=0 );
+ testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1==0 );
+ testcase( xJump==sqlite3ExprIfFalse && jumpIfNull!=0 && regFree1!=0 );
testcase( xJump==0 );
}