diff options
author | drh <drh@noemail.net> | 2008-04-01 01:42:41 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2008-04-01 01:42:41 +0000 |
commit | 652fbf55c59da6de986e8d2c5e995c995965e291 (patch) | |
tree | 517f0e95128a89ebc5d4ac83f4becafa858348ee /src/expr.c | |
parent | e1349cb0f0d2178fa584d2e16dde7b35eeefcbd0 (diff) | |
download | sqlite-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.c | 53 |
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, ®Free1); @@ -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){ |