aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2009-12-24 16:00:28 +0000
committerdrh <drh@noemail.net>2009-12-24 16:00:28 +0000
commitb6da74ebd5140fac15bb007ce21e3b79b981f98e (patch)
tree469fc9a139de5d332f6b84302bd0b4ffad43ec4b /src/expr.c
parent07096f68ae9f9de330350cafc6d11b37d8e328f7 (diff)
downloadsqlite-b6da74ebd5140fac15bb007ce21e3b79b981f98e.tar.gz
sqlite-b6da74ebd5140fac15bb007ce21e3b79b981f98e.zip
Immediately purge entries from the column cache when the associated register
undergoes an affinity change. Ticket [eb5548a849]. Enhance the SQLITE_TESTCTRL_OPTIMIZATIONS setting of sqlite3_test_control so that it can disable the column cache for testing purposes, in an effort to prevent future problems of a similar nature to this one. FossilOrigin-Name: ea4e57e1c1b6663ceb12872e31a8503f6c14e3d8
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c74
1 files changed, 25 insertions, 49 deletions
diff --git a/src/expr.c b/src/expr.c
index aee2b7409..7e9eb4170 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -228,30 +228,6 @@ CollSeq *sqlite3BinaryCompareCollSeq(
}
/*
-** Generate the operands for a comparison operation. Before
-** generating the code for each operand, set the EP_AnyAff
-** flag on the expression so that it will be able to used a
-** cached column value that has previously undergone an
-** affinity change.
-*/
-static void codeCompareOperands(
- Parse *pParse, /* Parsing and code generating context */
- Expr *pLeft, /* The left operand */
- int *pRegLeft, /* Register where left operand is stored */
- int *pFreeLeft, /* Free this register when done */
- Expr *pRight, /* The right operand */
- int *pRegRight, /* Register where right operand is stored */
- int *pFreeRight /* Write temp register for right operand there */
-){
- while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft;
- pLeft->flags |= EP_AnyAff;
- *pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft);
- while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft;
- pRight->flags |= EP_AnyAff;
- *pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight);
-}
-
-/*
** Generate code for a comparison operator.
*/
static int codeCompare(
@@ -1982,13 +1958,18 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
assert( iReg>0 ); /* Register numbers are always positive */
assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
+ /* The SQLITE_ColumnCache flag disables the column cache. This is used
+ ** for testing only - to verify that SQLite always gets the same answer
+ ** with and without the column cache.
+ */
+ if( pParse->db->flags & SQLITE_ColumnCache ) return;
+
/* First replace any existing entry */
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
cacheEntryClear(pParse, p);
p->iLevel = pParse->iCacheLevel;
p->iReg = iReg;
- p->affChange = 0;
p->lru = pParse->iCacheCnt++;
return;
}
@@ -2001,7 +1982,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
p->iTable = iTab;
p->iColumn = iCol;
p->iReg = iReg;
- p->affChange = 0;
p->tempReg = 0;
p->lru = pParse->iCacheCnt++;
return;
@@ -2023,7 +2003,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
p->iTable = iTab;
p->iColumn = iCol;
p->iReg = iReg;
- p->affChange = 0;
p->tempReg = 0;
p->lru = pParse->iCacheCnt++;
return;
@@ -2109,16 +2088,14 @@ int sqlite3ExprCodeGetColumn(
Table *pTab, /* Description of the table we are reading from */
int iColumn, /* Index of the table column */
int iTable, /* The cursor pointing to the table */
- int iReg, /* Store results here */
- int allowAffChng /* True if prior affinity changes are OK */
+ int iReg /* Store results here */
){
Vdbe *v = pParse->pVdbe;
int i;
struct yColCache *p;
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
- if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn
- && (!p->affChange || allowAffChng) ){
+ if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
p->lru = pParse->iCacheCnt++;
sqlite3ExprCachePinRegister(pParse, p->iReg);
return p->iReg;
@@ -2162,7 +2139,8 @@ void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
int r = p->iReg;
if( r>=iStart && r<=iEnd ){
- p->affChange = 1;
+ cacheEntryClear(pParse, p);
+ p->iReg = 0;
}
}
}
@@ -2329,10 +2307,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert( pParse->ckBase>0 );
inReg = pExpr->iColumn + pParse->ckBase;
}else{
- testcase( (pExpr->flags & EP_AnyAff)!=0 );
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
- pExpr->iColumn, pExpr->iTable, target,
- pExpr->flags & EP_AnyAff);
+ pExpr->iColumn, pExpr->iTable, target);
}
break;
}
@@ -2449,8 +2425,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
testcase( op==TK_GE );
testcase( op==TK_EQ );
testcase( op==TK_NE );
- codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
- pExpr->pRight, &r2, &regFree2);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2);
testcase( regFree1==0 );
@@ -2461,8 +2437,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
case TK_ISNOT: {
testcase( op==TK_IS );
testcase( op==TK_ISNOT );
- codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
- pExpr->pRight, &r2, &regFree2);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
op = (op==TK_IS) ? TK_EQ : TK_NE;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
@@ -2702,8 +2678,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
struct ExprList_item *pLItem = pExpr->x.pList->a;
Expr *pRight = pLItem->pExpr;
- codeCompareOperands(pParse, pLeft, &r1, &regFree1,
- pRight, &r2, &regFree2);
+ r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
testcase( regFree1==0 );
testcase( regFree2==0 );
r3 = sqlite3GetTempReg(pParse);
@@ -3238,8 +3214,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( op==TK_EQ );
testcase( op==TK_NE );
testcase( jumpIfNull==0 );
- codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
- pExpr->pRight, &r2, &regFree2);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull);
testcase( regFree1==0 );
@@ -3250,8 +3226,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_ISNOT: {
testcase( op==TK_IS );
testcase( op==TK_ISNOT );
- codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
- pExpr->pRight, &r2, &regFree2);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
op = (op==TK_IS) ? TK_EQ : TK_NE;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, SQLITE_NULLEQ);
@@ -3381,8 +3357,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( op==TK_EQ );
testcase( op==TK_NE );
testcase( jumpIfNull==0 );
- codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
- pExpr->pRight, &r2, &regFree2);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull);
testcase( regFree1==0 );
@@ -3393,8 +3369,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_ISNOT: {
testcase( pExpr->op==TK_IS );
testcase( pExpr->op==TK_ISNOT );
- codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
- pExpr->pRight, &r2, &regFree2);
+ r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
+ r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, SQLITE_NULLEQ);