Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix the Parse.aColCache column cache so that all of the valid entries are in the first Parse.nColCache slots. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
6028502059ccbd3699637b7a70a6d8ce |
User & Date: | drh 2016-09-30 20:22:27.729 |
Context
2016-09-30
| ||
21:20 | Fix an always-true conditional left over from the previous commit. (check-in: ab12fce331 user: drh tags: trunk) | |
20:22 | Fix the Parse.aColCache column cache so that all of the valid entries are in the first Parse.nColCache slots. (check-in: 6028502059 user: drh tags: trunk) | |
19:14 | Another simplification to the Parse object. (check-in: c1419727f5 user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
2960 2961 2962 2963 2964 2965 2966 | codeReal(v, z, negFlag, iMem); } #endif } } } | < < < < < < < < < < < | < < | | | < < | > > | 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 | codeReal(v, z, negFlag, iMem); } #endif } } } /* ** Erase column-cache entry number i */ static void cacheEntryClear(Parse *pParse, int i){ if( pParse->aColCache[i].tempReg ){ if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){ pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg; } } pParse->nColCache--; if( i<pParse->nColCache ){ pParse->aColCache[i] = pParse->aColCache[pParse->nColCache]; } } /* ** Record in the column cache that a particular column from a ** particular table is stored in a particular register. */ |
︙ | ︙ | |||
3015 3016 3017 3018 3019 3020 3021 | /* First replace any existing entry. ** ** Actually, the way the column cache is currently used, we are guaranteed ** that the object will never already be in cache. Verify this guarantee. */ #ifndef NDEBUG | | | | < < < < < < < < | < < < < < < | | | | | | | | | > | > > > | | | | | | < < < | | | < | | < > > > | 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 | /* First replace any existing entry. ** ** Actually, the way the column cache is currently used, we are guaranteed ** that the object will never already be in cache. Verify this guarantee. */ #ifndef NDEBUG for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ assert( p->iTable!=iTab || p->iColumn!=iCol ); } #endif /* 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++]; } /* 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++; } /* ** Indicate that registers between iReg..iReg+nReg-1 are being overwritten. ** Purge the range of registers from the column cache. */ void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){ 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++; } } } /* ** Remember the current column cache context. Any new entries added ** added to the column cache after this call are removed when the ** corresponding pop occurs. |
︙ | ︙ | |||
3092 3093 3094 3095 3096 3097 3098 | /* ** Remove from the column cache any entries that were added since the ** the previous sqlite3ExprCachePush operation. In other words, restore ** the cache to the state it was in prior the most recent Push. */ void sqlite3ExprCachePop(Parse *pParse){ | | < | | | > > | | 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 | /* ** Remove from the column cache any entries that were added since the ** the previous sqlite3ExprCachePush operation. In other words, restore ** the cache to the state it was in prior the most recent Push. */ void sqlite3ExprCachePop(Parse *pParse){ int i = 0; assert( pParse->iCacheLevel>=1 ); pParse->iCacheLevel--; #ifdef SQLITE_DEBUG if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ printf("POP to %d\n", pParse->iCacheLevel); } #endif while( i<pParse->nColCache ){ if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){ cacheEntryClear(pParse, i); }else{ i++; } } } /* ** When a cached column is reused, make sure that its register is ** no longer available as a temp register. ticket #3879: that same ** register might be in the cache in multiple places, so be sure to ** get them all. */ static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){ int i; struct yColCache *p; for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){ if( p->iReg==iReg ){ p->tempReg = 0; } } } /* Generate code that will load into register regOut a value that is |
︙ | ︙ | |||
3195 3196 3197 3198 3199 3200 3201 | int iReg, /* Store results here */ u8 p5 /* P5 value for OP_Column + FLAGS */ ){ Vdbe *v = pParse->pVdbe; int i; struct yColCache *p; | | | 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 | int iReg, /* Store results here */ u8 p5 /* P5 value for OP_Column + FLAGS */ ){ Vdbe *v = pParse->pVdbe; int i; struct yColCache *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); return p->iReg; } } assert( v!=0 ); |
︙ | ︙ | |||
3228 3229 3230 3231 3232 3233 3234 | /* ** Clear all column cache entries. */ void sqlite3ExprCacheClear(Parse *pParse){ int i; | < > | > | | > | 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 | /* ** Clear all column cache entries. */ void sqlite3ExprCacheClear(Parse *pParse){ int i; #if SQLITE_DEBUG if( pParse->db->flags & SQLITE_VdbeAddopTrace ){ printf("CLEAR\n"); } #endif 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; } /* ** Record the fact that an affinity change has occurred on iCount ** registers starting with iStart. */ void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){ |
︙ | ︙ | |||
3271 3272 3273 3274 3275 3276 3277 | ** ** This routine is used within assert() and testcase() macros only ** and does not appear in a normal build. */ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; struct yColCache *p; | | | 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 | ** ** This routine is used within assert() and testcase() macros only ** and does not appear in a normal build. */ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; struct yColCache *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*/ } return 0; } #endif /* SQLITE_DEBUG || SQLITE_COVERAGE_TEST */ |
︙ | ︙ | |||
4967 4968 4969 4970 4971 4972 4973 | ** the deallocation is deferred until the column cache line that uses ** the register becomes stale. */ void sqlite3ReleaseTempReg(Parse *pParse, int iReg){ if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){ int i; struct yColCache *p; | | | 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 | ** the deallocation is deferred until the column cache line that uses ** the register becomes stale. */ 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<pParse->nColCache; i++, p++){ if( p->iReg==iReg ){ p->tempReg = 1; return; } } pParse->aTempReg[pParse->nTempReg++] = iReg; } |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
180 181 182 183 184 185 186 | #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS pOp->zComment = 0; #endif #ifdef SQLITE_DEBUG if( p->db->flags & SQLITE_VdbeAddopTrace ){ int jj, kk; Parse *pParse = p->pParse; | | < | 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS pOp->zComment = 0; #endif #ifdef SQLITE_DEBUG if( p->db->flags & SQLITE_VdbeAddopTrace ){ int jj, kk; Parse *pParse = p->pParse; for(jj=kk=0; jj<pParse->nColCache; jj++){ struct yColCache *x = pParse->aColCache + jj; printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn); kk++; } if( kk ) printf("\n"); sqlite3VdbePrintOp(0, i, &p->aOp[i]); test_addop_breakpoint(); } |
︙ | ︙ |