aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2008-04-01 01:42:41 +0000
committerdrh <drh@noemail.net>2008-04-01 01:42:41 +0000
commit652fbf55c59da6de986e8d2c5e995c995965e291 (patch)
tree517f0e95128a89ebc5d4ac83f4becafa858348ee /src/expr.c
parente1349cb0f0d2178fa584d2e16dde7b35eeefcbd0 (diff)
downloadsqlite-652fbf55c59da6de986e8d2c5e995c995965e291.tar.gz
sqlite-652fbf55c59da6de986e8d2c5e995c995965e291.zip
Initial test cases and bug fixes in the CSE logic. (CVS 4946)
FossilOrigin-Name: e5aff09ac693946dc7ebb2f245b6434995b12155
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c53
1 files changed, 38 insertions, 15 deletions
diff --git a/src/expr.c b/src/expr.c
index 095c74aca..5ebc58a9f 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.359 2008/03/31 23:48:04 drh Exp $
+** $Id: expr.c,v 1.360 2008/04/01 01:42:41 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -2017,6 +2017,41 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo){
}
/*
+** Return true if any register in the range iFrom..iTo (inclusive)
+** is used as part of the column cache.
+*/
+static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
+ int i;
+ for(i=0; i<pParse->nColCache; i++){
+ int r = pParse->aColCache[i].iReg;
+ if( r>=iFrom && r<=iTo ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Theres is a value in register iCurrent. We ultimately want
+** the value to be in register iTarget. It might be that
+** iCurrent and iTarget are the same register.
+**
+** We are going to modify the value, so we need to make sure it
+** is not a cached register. If iCurrent is a cached register,
+** then try to move the value over to iTarget. If iTarget is a
+** cached register, then clear the corresponding cache line.
+**
+** Return the register that the value ends up in.
+*/
+int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){
+ assert( pParse->pVdbe!=0 );
+ if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){
+ return iCurrent;
+ }
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget);
+ sqlite3ExprExpireColumnCacheLines(pParse, iTarget, iTarget);
+ return iTarget;
+}
+
+/*
** Generate code into the current Vdbe to evaluate the given
** expression. Attempt to store the results in register "target".
** Return the register where results are stored.
@@ -2201,6 +2236,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert( TK_BITNOT==OP_BitNot );
assert( TK_NOT==OP_Not );
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ inReg = sqlite3ExprWritableRegister(pParse, inReg, target);
sqlite3VdbeAddOp1(v, op, inReg);
break;
}
@@ -2417,7 +2453,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
aListelem = pEList->a;
nExpr = pEList->nExpr;
endLabel = sqlite3VdbeMakeLabel(v);
- sqlite3ExprColumnCacheDisable(pParse, 1);
if( (pX = pExpr->pLeft)!=0 ){
cacheX = *pX;
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, &regFree1);
@@ -2427,6 +2462,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
opCompare.pLeft = &cacheX;
pTest = &opCompare;
}
+ sqlite3ExprColumnCacheDisable(pParse, 1);
for(i=0; i<nExpr; i=i+2){
if( pX ){
opCompare.pRight = aListelem[i].pExpr;
@@ -3087,19 +3123,6 @@ void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
}
/*
-** Return true if any register in the range iFrom..iTo (inclusive)
-** is used as part of the column cache.
-*/
-static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
- int i;
- for(i=0; i<pParse->nColCache; i++){
- int r = pParse->aColCache[i].iReg;
- if( r>=iFrom && r<=iTo ) return 1;
- }
- return 0;
-}
-
-/*
** Allocate or deallocate temporary use registers during code generation.
*/
int sqlite3GetTempReg(Parse *pParse){