1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-06 15:49:35 +03:00

Fix the CSE mechanism so that it takes into account column affinity

changes that might be imposed by comparison operators. (CVS 4949)

FossilOrigin-Name: 91cc646e2b0c1d62a1989405cc9384a2c22d98d0
This commit is contained in:
drh
2008-04-01 05:07:14 +00:00
parent 2f7794c111
commit da250ea599
9 changed files with 106 additions and 73 deletions

View File

@@ -1,5 +1,5 @@
C More\stest\scases\sand\sbug\sfixes\swith\sCSE.\s(CVS\s4948) C Fix\sthe\sCSE\smechanism\sso\sthat\sit\stakes\sinto\saccount\scolumn\saffinity\nchanges\sthat\smight\sbe\simposed\sby\scomparison\soperators.\s(CVS\s4949)
D 2008-04-01T03:27:39 D 2008-04-01T05:07:15
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in b861627d91df5ee422c54237aa38296954dc0151 F Makefile.in b861627d91df5ee422c54237aa38296954dc0151
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -93,14 +93,14 @@ F src/build.c fb042279457b4908d6f8e6b11855696218ecaa73
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d
F src/delete.c 9573b07fbdaef0e68d63eb218e5874c7a162c727 F src/delete.c 74d5c9c824848a14d7dee37264ec302b168c4ddb
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
F src/expr.c 86aeb607d44c086fc66b2fdfd2a11a067b0e7f6e F src/expr.c 11e9a05c4eb60789cd6f1b056d1b7039ec3512c8
F src/fault.c 83057e86815d473e526f7df0b0108dfdd022ff23 F src/fault.c 83057e86815d473e526f7df0b0108dfdd022ff23
F src/func.c c9e8c7ff4c45027edee89bde7adbf86a3a3b2afe F src/func.c c9e8c7ff4c45027edee89bde7adbf86a3a3b2afe
F src/hash.c 53655c312280211444bfe23af6490a460aec2980 F src/hash.c 53655c312280211444bfe23af6490a460aec2980
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
F src/insert.c 803299d223bdb11ce32ab17c485cd93a9630d673 F src/insert.c 6974a1d02f2dcd616d00eef4996d4872495fad0f
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
F src/legacy.c 8267890e6a0a71f13b680794520999c642299081 F src/legacy.c 8267890e6a0a71f13b680794520999c642299081
F src/loadext.c f26b22f7c84153c9d5dbd7c240848823c6e6b6dc F src/loadext.c f26b22f7c84153c9d5dbd7c240848823c6e6b6dc
@@ -135,12 +135,12 @@ F src/pragma.c e659c9e443d11854cff2fd250012365ae0ca81ba
F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c
F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
F src/select.c 0d1b44c9ef1b97c9f43fe663cd94713186896e77 F src/select.c 53bfb7c4da43b2d20f27b5bf0ceab94d53835080
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
F src/sqlite.h.in b1ac824d9fc163a5d2226ebf5990b09a02a11117 F src/sqlite.h.in b1ac824d9fc163a5d2226ebf5990b09a02a11117
F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3 F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
F src/sqliteInt.h f7ee48df1dd85dfa5342a2be7c48eb1da2858ca8 F src/sqliteInt.h 1b7ad8791bf441901914734fb1f9735b58adfb37
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8 F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda
@@ -170,7 +170,7 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
F src/tokenize.c 13113f94bd1c15dea9e922f08b10f3eee6863474 F src/tokenize.c 13113f94bd1c15dea9e922f08b10f3eee6863474
F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3 F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
F src/update.c e23e83cf481b25d5fc7beb92efbb71d297712fd3 F src/update.c 6d5f7728ec254c4a36a06a744f45b232b2eef857
F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2 F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30 F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
@@ -183,7 +183,7 @@ F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736 F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
F src/vdbemem.c b96fea7b98cc662ad7b587f28560b0c5649ac39f F src/vdbemem.c b96fea7b98cc662ad7b587f28560b0c5649ac39f
F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2 F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2
F src/where.c 811fd1e5c67902499866d942dfa5f44550501adf F src/where.c 86b042dcd57f8428a75ddb59e6289eded6f6af09
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/all.test d56a3ca8acdf761204aff0a2e7aa5eb8e11b31e6 F test/all.test d56a3ca8acdf761204aff0a2e7aa5eb8e11b31e6
@@ -621,7 +621,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P 7d1e79716246b0dd4a64d7c9575b2300e0f6123e P 7e8156129d6d240fe046bbc4ea269ebe1657e2a1
R d317ffb6476a001df9ffa7c9574eac3a R de548c9eaa6939bb8e637e0b7174d31d
U drh U drh
Z 0847abdee1058424d9b79886f0c468bd Z f0f4a4427173bdf817f07a4e85556845

View File

@@ -1 +1 @@
7e8156129d6d240fe046bbc4ea269ebe1657e2a1 91cc646e2b0c1d62a1989405cc9384a2c22d98d0

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements. ** in order to generate code for DELETE FROM statements.
** **
** $Id: delete.c,v 1.165 2008/03/31 23:48:04 drh Exp $ ** $Id: delete.c,v 1.166 2008/04/01 05:07:15 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -534,7 +534,7 @@ int sqlite3GenerateIndexKey(
if( doMakeRec ){ if( doMakeRec ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
sqlite3IndexAffinityStr(v, pIdx); sqlite3IndexAffinityStr(v, pIdx);
sqlite3ExprExpireColumnCacheLines(pParse, regBase, regBase+nCol); sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
} }
sqlite3ReleaseTempRange(pParse, regBase, nCol+1); sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
return regBase; return regBase;

View File

@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and ** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite. ** for generating VDBE code that evaluates expressions in SQLite.
** **
** $Id: expr.c,v 1.361 2008/04/01 03:27:39 drh Exp $ ** $Id: expr.c,v 1.362 2008/04/01 05:07:15 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -201,6 +201,30 @@ CollSeq *sqlite3BinaryCompareCollSeq(
return pColl; return pColl;
} }
/*
** 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. ** Generate code for a comparison operator.
*/ */
@@ -223,8 +247,8 @@ static int codeCompare(
(void*)p4, P4_COLLSEQ); (void*)p4, P4_COLLSEQ);
sqlite3VdbeChangeP5(pParse->pVdbe, p5); sqlite3VdbeChangeP5(pParse->pVdbe, p5);
if( p5 & SQLITE_AFF_MASK ){ if( p5 & SQLITE_AFF_MASK ){
sqlite3ExprExpireColumnCacheLines(pParse, in1, in1); sqlite3ExprCacheAffinityChange(pParse, in1, 1);
sqlite3ExprExpireColumnCacheLines(pParse, in2, in2); sqlite3ExprCacheAffinityChange(pParse, in2, 1);
} }
return addr; return addr;
} }
@@ -1787,7 +1811,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
sqlite3ExprCode(pParse, pE2, r1); sqlite3ExprCode(pParse, pE2, r1);
pParse->disableColCache--; pParse->disableColCache--;
sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
sqlite3ExprExpireColumnCacheLines(pParse, r1, r1); sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2); sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
} }
sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r1);
@@ -1907,26 +1931,33 @@ static void codeInteger(Vdbe *v, const char *z, int n, int negFlag, int iMem){
** **
** There must be an open cursor to pTab in iTable when this routine ** There must be an open cursor to pTab in iTable when this routine
** is called. If iColumn<0 then code is generated that extracts the rowid. ** is called. If iColumn<0 then code is generated that extracts the rowid.
**
** This routine might attempt to reuse the value of the column that
** has already been loaded into a register. The value will always
** be used if it has not undergone any affinity changes. But if
** an affinity change has occurred, then the cached value will only be
** used if allowAffChng is true.
*/ */
int sqlite3ExprCodeGetColumn( int sqlite3ExprCodeGetColumn(
Parse *pParse, /* Parsing and code generating context */ Parse *pParse, /* Parsing and code generating context */
Table *pTab, /* Description of the table we are reading from */ Table *pTab, /* Description of the table we are reading from */
int iColumn, /* Index of the table column */ int iColumn, /* Index of the table column */
int iTable, /* The cursor pointing to the table */ int iTable, /* The cursor pointing to the table */
int iReg /* Store results here */ int iReg, /* Store results here */
int allowAffChng /* True if prior affinity changes are OK */
){ ){
Vdbe *v = pParse->pVdbe; Vdbe *v = pParse->pVdbe;
int i; int i;
struct yColCache *p;
for(i=0; i<pParse->nColCache; i++){ for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
if( pParse->aColCache[i].iTable==iTable if( p->iTable==iTable && p->iColumn==iColumn
&& pParse->aColCache[i].iColumn==iColumn ){ && (!p->affChange || allowAffChng) ){
#if 0 #if 0
sqlite3VdbeAddOp0(v, OP_Noop); sqlite3VdbeAddOp0(v, OP_Noop);
VdbeComment((v, "OPT: tab%d.col%d -> r%d", VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg));
iTable, iColumn, pParse->aColCache[i].iReg));
#endif #endif
return pParse->aColCache[i].iReg; return p->iReg;
} }
} }
assert( v!=0 ); assert( v!=0 );
@@ -1947,9 +1978,10 @@ int sqlite3ExprCodeGetColumn(
} }
if( pParse->disableColCache==0 ){ if( pParse->disableColCache==0 ){
i = pParse->iColCache; i = pParse->iColCache;
pParse->aColCache[i].iTable = iTable; p = &pParse->aColCache[i];
pParse->aColCache[i].iColumn = iColumn; p->iTable = iTable;
pParse->aColCache[i].iReg = iReg; p->iColumn = iColumn;
p->iReg = iReg;
i++; i++;
if( i>=ArraySize(pParse->aColCache) ) i = 0; if( i>=ArraySize(pParse->aColCache) ) i = 0;
if( i>pParse->nColCache ) pParse->nColCache = i; if( i>pParse->nColCache ) pParse->nColCache = i;
@@ -1980,30 +2012,25 @@ void sqlite3ExprClearColumnCache(Parse *pParse, int iTable){
for(i=0; i<pParse->nColCache; i++){ for(i=0; i<pParse->nColCache; i++){
if( pParse->aColCache[i].iTable==iTable ){ if( pParse->aColCache[i].iTable==iTable ){
pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
pParse->iColCache = pParse->nColCache;
} }
} }
pParse->iColCache = pParse->nColCache;
} }
} }
/* /*
** Expire all column cache entry associated with register between ** Record the fact that an affinity change has occurred on iCount
** iFrom and iTo, inclusive. If there are no column cache entries ** registers starting with iStart.
** on those registers then this routine is a no-op.
**
** Call this routine when register contents are overwritten to
** make sure the new register value is not used in place of the
** value that was overwritten.
*/ */
void sqlite3ExprExpireColumnCacheLines(Parse *pParse, int iFrom, int iTo){ void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
int iEnd = iStart + iCount - 1;
int i; int i;
for(i=0; i<pParse->nColCache; i++){ for(i=0; i<pParse->nColCache; i++){
int r = pParse->aColCache[i].iReg; int r = pParse->aColCache[i].iReg;
if( r>=iFrom && r<=iTo ){ if( r>=iStart && r<=iEnd ){
pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache]; pParse->aColCache[i].affChange = 1;
} }
} }
pParse->iColCache = pParse->nColCache;
} }
/* /*
@@ -2047,6 +2074,7 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
** Return the register that the value ends up in. ** Return the register that the value ends up in.
*/ */
int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){ int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){
int i;
assert( pParse->pVdbe!=0 ); assert( pParse->pVdbe!=0 );
if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){ if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){
return iCurrent; return iCurrent;
@@ -2054,7 +2082,12 @@ int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){
if( iCurrent!=iTarget ){ if( iCurrent!=iTarget ){
sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget); sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget);
} }
sqlite3ExprExpireColumnCacheLines(pParse, iTarget, iTarget); for(i=0; i<pParse->nColCache; i++){
if( pParse->aColCache[i].iReg==iTarget ){
pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
pParse->iColCache = pParse->nColCache;
}
}
return iTarget; return iTarget;
} }
@@ -2108,7 +2141,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
inReg = pExpr->iColumn + pParse->ckBase; inReg = pExpr->iColumn + pParse->ckBase;
}else{ }else{
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
pExpr->iColumn, pExpr->iTable, target); pExpr->iColumn, pExpr->iTable, target,
pExpr->flags & EP_AnyAff);
} }
break; break;
} }
@@ -2185,8 +2219,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert( TK_GE==OP_Ge ); assert( TK_GE==OP_Ge );
assert( TK_EQ==OP_Eq ); assert( TK_EQ==OP_Eq );
assert( TK_NE==OP_Ne ); assert( TK_NE==OP_Ne );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2); pExpr->pRight, &r2, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, inReg, SQLITE_STOREP2); r1, r2, inReg, SQLITE_STOREP2);
break; break;
@@ -2330,7 +2364,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
if( nExpr ){ if( nExpr ){
sqlite3ReleaseTempRange(pParse, r1, nExpr); sqlite3ReleaseTempRange(pParse, r1, nExpr);
} }
sqlite3ExprExpireColumnCacheLines(pParse, r1, r1+nExpr-1); sqlite3ExprCacheAffinityChange(pParse, r1, nExpr);
break; break;
} }
#ifndef SQLITE_OMIT_SUBQUERY #ifndef SQLITE_OMIT_SUBQUERY
@@ -2374,7 +2408,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}else{ }else{
r2 = regFree2 = sqlite3GetTempReg(pParse); r2 = regFree2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
sqlite3ExprExpireColumnCacheLines(pParse, r1, r1); sqlite3ExprCacheAffinityChange(pParse, r1, 1);
j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2); j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
} }
sqlite3VdbeAddOp2(v, OP_AddImm, target, -1); sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
@@ -2399,8 +2433,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
struct ExprList_item *pLItem = pExpr->pList->a; struct ExprList_item *pLItem = pExpr->pList->a;
Expr *pRight = pLItem->pExpr; Expr *pRight = pLItem->pExpr;
r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1); codeCompareOperands(pParse, pLeft, &r1, &regFree1,
r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2); pRight, &r2, &regFree2);
r3 = sqlite3GetTempReg(pParse); r3 = sqlite3GetTempReg(pParse);
r4 = sqlite3GetTempReg(pParse); r4 = sqlite3GetTempReg(pParse);
codeCompare(pParse, pLeft, pRight, OP_Ge, codeCompare(pParse, pLeft, pRight, OP_Ge,
@@ -2702,8 +2736,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
assert( TK_GE==OP_Ge ); assert( TK_GE==OP_Ge );
assert( TK_EQ==OP_Eq ); assert( TK_EQ==OP_Eq );
assert( TK_NE==OP_Ne ); assert( TK_NE==OP_Ne );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2); pExpr->pRight, &r2, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull); r1, r2, dest, jumpIfNull);
break; break;
@@ -2833,8 +2867,8 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_GE: case TK_GE:
case TK_NE: case TK_NE:
case TK_EQ: { case TK_EQ: {
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2); pExpr->pRight, &r2, &regFree2);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
r1, r2, dest, jumpIfNull); r1, r2, dest, jumpIfNull);
break; break;

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite. ** to handle INSERT statements in SQLite.
** **
** $Id: insert.c,v 1.234 2008/03/31 23:48:05 drh Exp $ ** $Id: insert.c,v 1.235 2008/04/01 05:07:15 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -1171,7 +1171,7 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i); sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]); sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
sqlite3IndexAffinityStr(v, pIdx); sqlite3IndexAffinityStr(v, pIdx);
sqlite3ExprExpireColumnCacheLines(pParse, regIdx, regIdx+pIdx->nColumn); sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1); sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);
/* Find out what action to take in case there is an indexing conflict */ /* Find out what action to take in case there is an indexing conflict */
@@ -1286,7 +1286,7 @@ void sqlite3CompleteInsertion(
regRec = sqlite3GetTempReg(pParse); regRec = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec); sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
sqlite3TableAffinityStr(v, pTab); sqlite3TableAffinityStr(v, pTab);
sqlite3ExprExpireColumnCacheLines(pParse, regData, regData+pTab->nCol-1); sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER
if( newIdx>=0 ){ if( newIdx>=0 ){
sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid);

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite. ** to handle SELECT statements in SQLite.
** **
** $Id: select.c,v 1.424 2008/03/31 23:48:05 drh Exp $ ** $Id: select.c,v 1.425 2008/04/01 05:07:15 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -669,7 +669,7 @@ static void selectInnerLoop(
}else{ }else{
int r1 = sqlite3GetTempReg(pParse); int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
sqlite3ExprExpireColumnCacheLines(pParse, regResult, regResult); sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r1);
} }
@@ -716,7 +716,7 @@ static void selectInnerLoop(
sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
sqlite3ExprExpireColumnCacheLines(pParse,regResult,regResult+nColumn-1); sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);
} }
break; break;
} }
@@ -835,7 +835,7 @@ static void generateSortTail(
assert( nColumn==1 ); assert( nColumn==1 );
j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow); j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
sqlite3ExprExpireColumnCacheLines(pParse, regRow, regRow); sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
sqlite3VdbeJumpHere(v, j1); sqlite3VdbeJumpHere(v, j1);
break; break;
@@ -858,8 +858,7 @@ static void generateSortTail(
} }
if( eDest==SRT_Callback ){ if( eDest==SRT_Callback ){
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
sqlite3ExprExpireColumnCacheLines(pParse, pDest->iMem, sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
pDest->iMem+nColumn-1);
}else{ }else{
sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm); sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
} }
@@ -2930,7 +2929,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
(void*)pF->pFunc, P4_FUNCDEF); (void*)pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, nArg); sqlite3VdbeChangeP5(v, nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg); sqlite3ReleaseTempRange(pParse, regAgg, nArg);
sqlite3ExprExpireColumnCacheLines(pParse, regAgg, regAgg+nArg-1); sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
if( addrNext ){ if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext); sqlite3VdbeResolveLabel(v, addrNext);
} }
@@ -3441,7 +3440,7 @@ int sqlite3Select(
if( pCol->iSorterColumn>=j ){ if( pCol->iSorterColumn>=j ){
int r1 = j + regBase; int r1 = j + regBase;
int r2 = sqlite3ExprCodeGetColumn(pParse, int r2 = sqlite3ExprCodeGetColumn(pParse,
pCol->pTab, pCol->iColumn, pCol->iTable, r1); pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
if( r1!=r2 ){ if( r1!=r2 ){
sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
} }

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.685 2008/04/01 03:27:39 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.686 2008/04/01 05:07:15 drh Exp $
*/ */
#ifndef _SQLITEINT_H_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
@@ -1139,7 +1139,7 @@ struct Expr {
#define EP_Dequoted 0x0040 /* True if the string has been dequoted */ #define EP_Dequoted 0x0040 /* True if the string has been dequoted */
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
#define EP_Constant 0x0200 /* A constant expression */ #define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */
/* /*
** These macros can be used to test, set, or clear bits in the ** These macros can be used to test, set, or clear bits in the
@@ -1469,7 +1469,7 @@ struct Parse {
struct yColCache { struct yColCache {
int iTable; /* Table cursor number */ int iTable; /* Table cursor number */
int iColumn; /* Table column number */ int iColumn; /* Table column number */
char aff; /* Affinity. Or 0 if none specified */ char affChange; /* True if this register has had an affinity change */
int iReg; /* Register holding value of this column */ int iReg; /* Register holding value of this column */
} aColCache[10]; /* One for each valid column cache entry */ } aColCache[10]; /* One for each valid column cache entry */
u32 writeMask; /* Start a write transaction on these databases */ u32 writeMask; /* Start a write transaction on these databases */
@@ -1838,11 +1838,11 @@ void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8);
void sqlite3WhereEnd(WhereInfo*); void sqlite3WhereEnd(WhereInfo*);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int); void sqlite3ExprCodeMove(Parse*, int, int);
void sqlite3ExprClearColumnCache(Parse*, int); void sqlite3ExprClearColumnCache(Parse*, int);
void sqlite3ExprColumnCacheDisable(Parse*, int); void sqlite3ExprColumnCacheDisable(Parse*, int);
void sqlite3ExprExpireColumnCacheLines(Parse*, int, int); void sqlite3ExprCacheAffinityChange(Parse*, int, int);
int sqlite3ExprWritableRegister(Parse*,int,int); int sqlite3ExprWritableRegister(Parse*,int,int);
int sqlite3ExprCode(Parse*, Expr*, int); int sqlite3ExprCode(Parse*, Expr*, int);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTemp(Parse*, Expr*, int*);

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle UPDATE statements. ** to handle UPDATE statements.
** **
** $Id: update.c,v 1.174 2008/03/31 23:48:05 drh Exp $ ** $Id: update.c,v 1.175 2008/04/01 05:07:15 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -446,7 +446,7 @@ void sqlite3Update(
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow); sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow);
if( !isView ){ if( !isView ){
sqlite3TableAffinityStr(v, pTab); sqlite3TableAffinityStr(v, pTab);
sqlite3ExprExpireColumnCacheLines(pParse, regCols, regCols+pTab->nCol-1); sqlite3ExprCacheAffinityChange(pParse, regCols, pTab->nCol);
} }
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol); sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol);
if( pParse->nErr ) goto update_cleanup; if( pParse->nErr ) goto update_cleanup;

View File

@@ -16,7 +16,7 @@
** so is applicable. Because this module is responsible for selecting ** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer". ** indices, you might also think of this module as the "query optimizer".
** **
** $Id: where.c,v 1.296 2008/03/31 23:48:05 drh Exp $ ** $Id: where.c,v 1.297 2008/04/01 05:07:15 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -1741,7 +1741,7 @@ static void buildIndexProbe(
assert( v!=0 ); assert( v!=0 );
sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest); sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest);
sqlite3IndexAffinityStr(v, pIdx); sqlite3IndexAffinityStr(v, pIdx);
sqlite3ExprExpireColumnCacheLines(pParse, regSrc, regSrc+nColumn-1); sqlite3ExprCacheAffinityChange(pParse, regSrc, nColumn);
} }