mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Fix the Parse.aColCache column cache so that all of the valid entries are
in the first Parse.nColCache slots. FossilOrigin-Name: 6028502059ccbd3699637b7a70a6d8ce1b7c3dad
This commit is contained in:
126
src/expr.c
126
src/expr.c
@@ -2964,32 +2964,19 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** Verify the consistency of the column cache
|
||||
** Erase column-cache entry number i
|
||||
*/
|
||||
static int cacheIsValid(Parse *pParse){
|
||||
int i, n;
|
||||
for(i=n=0; i<SQLITE_N_COLCACHE; i++){
|
||||
if( pParse->aColCache[i].iReg>0 ) n++;
|
||||
}
|
||||
return n==pParse->nColCache;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Clear a cache entry.
|
||||
*/
|
||||
static void cacheEntryClear(Parse *pParse, struct yColCache *p){
|
||||
if( p->tempReg ){
|
||||
static void cacheEntryClear(Parse *pParse, int i){
|
||||
if( pParse->aColCache[i].tempReg ){
|
||||
if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
|
||||
pParse->aTempReg[pParse->nTempReg++] = p->iReg;
|
||||
pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
|
||||
}
|
||||
p->tempReg = 0;
|
||||
}
|
||||
p->iReg = 0;
|
||||
pParse->nColCache--;
|
||||
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
|
||||
if( i<pParse->nColCache ){
|
||||
pParse->aColCache[i] = pParse->aColCache[pParse->nColCache];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3019,46 +3006,33 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
** that the object will never already be in cache. Verify this guarantee.
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
assert( p->iTable!=iTab || p->iColumn!=iCol );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find an empty slot and replace it */
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg==0 ){
|
||||
p->iLevel = pParse->iCacheLevel;
|
||||
p->iTable = iTab;
|
||||
p->iColumn = iCol;
|
||||
p->iReg = iReg;
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
pParse->nColCache++;
|
||||
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
|
||||
return;
|
||||
/* If the cache is already full, delete the least recently used entry */
|
||||
if( pParse->nColCache>=SQLITE_N_COLCACHE ){
|
||||
minLru = 0x7fffffff;
|
||||
idxLru = -1;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->lru<minLru ){
|
||||
idxLru = i;
|
||||
minLru = p->lru;
|
||||
}
|
||||
}
|
||||
p = &pParse->aColCache[idxLru];
|
||||
}else{
|
||||
p = &pParse->aColCache[pParse->nColCache++];
|
||||
}
|
||||
|
||||
/* Replace the last recently used */
|
||||
minLru = 0x7fffffff;
|
||||
idxLru = -1;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->lru<minLru ){
|
||||
idxLru = i;
|
||||
minLru = p->lru;
|
||||
}
|
||||
}
|
||||
if( ALWAYS(idxLru>=0) ){
|
||||
p = &pParse->aColCache[idxLru];
|
||||
p->iLevel = pParse->iCacheLevel;
|
||||
p->iTable = iTab;
|
||||
p->iColumn = iCol;
|
||||
p->iReg = iReg;
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
assert( cacheIsValid(pParse) );
|
||||
return;
|
||||
}
|
||||
/* Add the new entry to the end of the cache */
|
||||
p->iLevel = pParse->iCacheLevel;
|
||||
p->iTable = iTab;
|
||||
p->iColumn = iCol;
|
||||
p->iReg = iReg;
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3066,13 +3040,14 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
** Purge the range of registers from the column cache.
|
||||
*/
|
||||
void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
|
||||
struct yColCache *p;
|
||||
if( iReg<=0 || pParse->nColCache==0 ) return;
|
||||
p = &pParse->aColCache[SQLITE_N_COLCACHE-1];
|
||||
while(1){
|
||||
if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p);
|
||||
if( p==pParse->aColCache ) break;
|
||||
p--;
|
||||
int i = 0;
|
||||
while( i<pParse->nColCache ){
|
||||
struct yColCache *p = &pParse->aColCache[i];
|
||||
if( p->iReg >= iReg && p->iReg < iReg+nReg ){
|
||||
cacheEntryClear(pParse, i);
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3096,8 +3071,7 @@ void sqlite3ExprCachePush(Parse *pParse){
|
||||
** the cache to the state it was in prior the most recent Push.
|
||||
*/
|
||||
void sqlite3ExprCachePop(Parse *pParse){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
int i = 0;
|
||||
assert( pParse->iCacheLevel>=1 );
|
||||
pParse->iCacheLevel--;
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -3105,9 +3079,11 @@ void sqlite3ExprCachePop(Parse *pParse){
|
||||
printf("POP to %d\n", pParse->iCacheLevel);
|
||||
}
|
||||
#endif
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg && p->iLevel>pParse->iCacheLevel ){
|
||||
cacheEntryClear(pParse, p);
|
||||
while( i<pParse->nColCache ){
|
||||
if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){
|
||||
cacheEntryClear(pParse, i);
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3121,7 +3097,7 @@ void sqlite3ExprCachePop(Parse *pParse){
|
||||
static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
if( p->iReg==iReg ){
|
||||
p->tempReg = 0;
|
||||
}
|
||||
@@ -3199,7 +3175,7 @@ int sqlite3ExprCodeGetColumn(
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
sqlite3ExprCachePinRegister(pParse, p->iReg);
|
||||
@@ -3232,18 +3208,20 @@ void sqlite3ExprCodeGetColumnToReg(
|
||||
*/
|
||||
void sqlite3ExprCacheClear(Parse *pParse){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
|
||||
#if SQLITE_DEBUG
|
||||
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
printf("CLEAR\n");
|
||||
}
|
||||
#endif
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg ){
|
||||
cacheEntryClear(pParse, p);
|
||||
for(i=0; i<pParse->nColCache; i++){
|
||||
if( pParse->aColCache[i].tempReg
|
||||
&& pParse->nTempReg<ArraySize(pParse->aTempReg)
|
||||
){
|
||||
pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
|
||||
}
|
||||
}
|
||||
pParse->nColCache = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3275,7 +3253,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
|
||||
static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
int r = p->iReg;
|
||||
if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
|
||||
}
|
||||
@@ -4971,7 +4949,7 @@ void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
|
||||
if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
if( p->iReg==iReg ){
|
||||
p->tempReg = 1;
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user