Completely remove the column cache logic, which has been a persistent source

of bugs for many years.  We recent enhancements to the performance of the
OP_Column opcode, the removing the column cache actually makes speed-check.sh
run faster.  It also saves about 1,800 bytes of code space.

FossilOrigin-Name: 3f5f60cd7529330209027fdae8129cca420cec1050eae50a7750d0b715b56972
This commit is contained in:
drh 2018-08-03 23:04:16 +00:00
parent a4b5fb55f3
commit 02ceed058a
13 changed files with 26 additions and 336 deletions

View File

@ -1,5 +1,5 @@
C Fix\sthe\shandling\sof\ssub-queries\swith\sLIMIT\sclauses\sby\sthe\soptimization\nactivated\sby\scompile-time\ssymbol\sSQLITE_COUNTOFVIEW_OPTIMIZATION.
D 2018-08-03T20:19:52.614
C Completely\sremove\sthe\scolumn\scache\slogic,\swhich\shas\sbeen\sa\spersistent\ssource\nof\sbugs\sfor\smany\syears.\s\sWe\srecent\senhancements\sto\sthe\sperformance\sof\sthe\nOP_Column\sopcode,\sthe\sremoving\sthe\scolumn\scache\sactually\smakes\sspeed-check.sh\nrun\sfaster.\s\sIt\salso\ssaves\sabout\s1,800\sbytes\sof\scode\sspace.
D 2018-08-03T23:04:16.901
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
@ -449,8 +449,8 @@ F src/ctime.c b157b01081f92442f8b0218ddb93ddce8ebddad36dbddeecfdd771561dd4f387
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/dbpage.c 4aa7f26198934dbd002e69418220eae3dbc71b010bbac32bd78faf86b52ce6c3
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f
F src/expr.c 3a85e8e23611cee71bc2b021cb25c65e30d12ca2bcb8e2ad4608789d268770e1
F src/delete.c 3838d8830dd0219f35afcd78a269934d5a43ef95d4c7fd30e819a2d238648d9b
F src/expr.c 4cb4ca6357b28fee2202d2b2bc5be83a439c65da03195ba5dc4dcece675ffce0
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c f59253c0be4b1e9dfcb073b6d6d6ab83090ae50c08b5c113b76013c4b157cd6a
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
@ -459,7 +459,7 @@ F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 8613af9c5ba1503bc68f4e9432c6c024e0fdafdc791575c50f380f73ec91189f
F src/insert.c 894594952bcda1dc6e1549871e4022517563545ffc7a3f4e9e5f3faa788893fd
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
F src/main.c dc023f468eda20aed1fb7c300673cbb40617607b5771840e4229ec239dade250
@ -491,19 +491,19 @@ F src/parse.y 704c94624d41d7d46a5467574130e55aa8029a563f4df538f0121475eae46e34
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
F src/pragma.c 71c585f1d26e14b931fa4573f587933d6dfddecd9d9001b0f126f74f7306bf87
F src/pragma.c 873b767f233932e97cbffd094aa61928be90aca03f946a94bb29ce5695e4885b
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
F src/prepare.c e966ecc97c3671ff0e96227c8c877b83f2d33ea371ee190bbf1698b36b5605c0
F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 797088662ed61102485e3070ba3b3f7828bd5ef6a588223ba6865d77d52f6cea
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c 18636c49eeb9016bb429ac6892220aea51bc618d021cf16770146e1858cf6f1e
F src/select.c 9d3d5f5035e616d31d45382bae695596bd20d38cbc2b042ae528aa6575f0ce24
F src/shell.c.in 5e4c139799f059a5231f0259111f51f6dffcb28154c535f6b4c2192619a40844
F src/sqlite.h.in c6451bb876adced3aba5b1682c6317d215c5eceaba21a6ce979e71a0b8d0bf95
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
F src/sqliteInt.h de37aae03c6a4e4f1e1eff15c04292153dbba015ad8e0dc0dffe82ea0fe76d5e
F src/sqliteInt.h 31b29c0dcc28ea79099abc1854a9a34838a9f1c755ceacbe0e2311303abc4942
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@ -564,7 +564,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 01e96d1b639c3eb0b9ef90616e766d453935c554f1f7aa86b6db937b79554b97
F src/treeview.c e7a7f90552bb418533cdd0309b5eb71d4effa50165b880fc8c2001e613577e5f
F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995
F src/update.c 7b7c768dc415a8d2eb9fd2cea8b524cb29cf354f319700e22f94f262d3f507cb
F src/update.c 42fe8a034f36eff36a9857709f9cf543ea6dd0b72bbcd2c74a1d338e50e1de2d
F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
@ -573,7 +573,7 @@ F src/vdbe.c 8fbefa50884f4803139bdc2d4795b973a1a892f023726fa72246fea2fe8e9925
F src/vdbe.h d93abdc8bc9295e0a256e582c19f548c545dc498319d108bbc9dd29de31c48a2
F src/vdbeInt.h 2a45270d7f44870ca5452f48cdf3c56387019ae03331c008d670a7d0a3e1ba3f
F src/vdbeapi.c af4a3de00d1851bcbc55b85dfbe52849aa2b1e17b4a5a1f3d9c257df7af361ff
F src/vdbeaux.c 1265a36260c36eb55afb40d744ffc1a3f11252d5712274c6218efb087204a7e5
F src/vdbeaux.c 3872c2956c0a0ca54e3c084194dc0f4d9c6f2701cab6fdf88485109f53fb4b0d
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c a699a1d7ccc3f94cdff69ddf35d5f7540dbf52ca44cf040eda3c87520e67858c
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
@ -583,9 +583,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c d44a0811afd2155b1157c38b33141d4ac028fda6232485bed664015bb05819ca
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
F src/walker.c ba7225773931760cf60bf22f34d0cce2588df7ce5ce0f215a52eb88234b55ac4
F src/where.c 52ab6d07a6ac6e2cb2a7da41217f0b7c13ce17a30d6a1d3459e86ac94b160e15
F src/where.c 155809967fbab889374dedf970ea6561b8fb519fcb165d6ba00776552ecc5cde
F src/whereInt.h b90ef9b9707ef750eab2a7a080c48fb4900315033274689def32d0cf5a81ebe4
F src/wherecode.c eb558ea9a482e179d27858113ca7012e508b904ff90b892367cc9ca4c0b9b246
F src/wherecode.c 9085b9d40a57eb9e34d1dc5e6625e44a3d56e7dbe56431f4505fbb69c1911023
F src/whereexpr.c dc34f0df69418dedb4619f7ad61b7d31f447971223540b957a1b836a62c0ce7b
F src/window.c 4b503da928dace3e845b891381a4d98eeb8c5744313ae3643df8d8d21fdcca65
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@ -676,7 +676,7 @@ F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45
F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983
F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b
F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f
F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99
F test/btree02.test a0f33669ba76632247c14718af32db939fa6de5cd13890798ad3f2a362cf7fe4
F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 510dc6daaad18bcbbc085bcc6217d6dc418def5e73f72ce1475eea0cb7834727
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
@ -1754,7 +1754,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P fa94b49e02eb6b8fc4acc220ecc2fabef546c65845696758b25965c26b251ea9
R 776956319daae57e1b0c061e1c2d74c6
U dan
Z 9283c73cf2ac7987df796a062f7aa1c4
P 21235d9a41567897418aa12f7bd6dd8d6ee363147527e1d8fbca14fc83e0f2c9
R 8d50a200abb983ec87063d77f452edcc
T *branch * omit-column-cache
T *sym-omit-column-cache *
T -sym-trunk *
U drh
Z a8a93a4aa98877787838b1809356b192

View File

@ -1 +1 @@
21235d9a41567897418aa12f7bd6dd8d6ee363147527e1d8fbca14fc83e0f2c9
3f5f60cd7529330209027fdae8129cca420cec1050eae50a7750d0b715b56972

View File

@ -898,7 +898,6 @@ int sqlite3GenerateIndexKey(
if( pIdx->pPartIdxWhere ){
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
pParse->iSelfTab = iDataCur + 1;
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
pParse->iSelfTab = 0;
@ -945,6 +944,5 @@ int sqlite3GenerateIndexKey(
void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
if( iLabel ){
sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel);
sqlite3ExprCachePop(pParse);
}
}

View File

@ -581,7 +581,6 @@ static void codeVectorCompare(
Expr *pL, *pR;
int r1, r2;
assert( i>=0 && i<nLeft );
if( i>0 ) sqlite3ExprCachePush(pParse);
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
@ -593,7 +592,6 @@ static void codeVectorCompare(
testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
sqlite3ReleaseTempReg(pParse, regFree1);
sqlite3ReleaseTempReg(pParse, regFree2);
if( i>0 ) sqlite3ExprCachePop(pParse);
if( i==nLeft-1 ){
break;
}
@ -2627,7 +2625,6 @@ int sqlite3CodeSubselect(
int rReg = 0; /* Register storing resulting */
Vdbe *v = sqlite3GetVdbe(pParse);
if( NEVER(v==0) ) return 0;
sqlite3ExprCachePush(pParse);
/* The evaluation of the IN/EXISTS/SELECT must be repeated every time it
** is encountered if any of the following is true:
@ -2763,7 +2760,6 @@ int sqlite3CodeSubselect(
sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3ExprCacheAffinityChange(pParse, r3, 1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
}
}
@ -2844,7 +2840,6 @@ int sqlite3CodeSubselect(
if( jmpIfDynamic>=0 ){
sqlite3VdbeJumpHere(v, jmpIfDynamic);
}
sqlite3ExprCachePop(pParse);
return rReg;
}
@ -2963,7 +2958,6 @@ static void sqlite3ExprCodeIN(
** aiMap[] array contains a mapping from the original LHS field order to
** the field order that matches the RHS index.
*/
sqlite3ExprCachePush(pParse);
rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
if( i==nVector ){
@ -3122,7 +3116,6 @@ static void sqlite3ExprCodeIN(
sqlite3ExprCodeIN_finished:
if( rLhs!=rLhsOrig ) sqlite3ReleaseTempReg(pParse, rLhs);
sqlite3ExprCachePop(pParse);
VdbeComment((v, "end IN expr"));
sqlite3ExprCodeIN_oom_error:
sqlite3DbFree(pParse->db, aiMap);
@ -3190,152 +3183,6 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
}
}
/*
** 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.
*/
void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
int i;
int minLru;
int idxLru;
struct yColCache *p;
/* Unless an error has occurred, register numbers are always positive. */
assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed );
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( OptimizationDisabled(pParse->db, SQLITE_ColumnCache) ) return;
/* 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
#ifdef SQLITE_DEBUG_COLUMNCACHE
/* Add a SetTabCol opcode for run-time verification that the column
** cache is working correctly.
*/
sqlite3VdbeAddOp3(pParse->pVdbe, OP_SetTabCol, iTab, iCol, iReg);
#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.
*/
void sqlite3ExprCachePush(Parse *pParse){
pParse->iCacheLevel++;
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("PUSH to %d\n", pParse->iCacheLevel);
}
#endif
}
/*
** 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
** appropriate for the iIdxCol-th column of index pIdx.
@ -3410,25 +3257,10 @@ int sqlite3ExprCodeGetColumn(
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->iTable==iTable && p->iColumn==iColumn ){
p->lru = pParse->iCacheCnt++;
sqlite3ExprCachePinRegister(pParse, p->iReg);
#ifdef SQLITE_DEBUG_COLUMNCACHE
sqlite3VdbeAddOp3(v, OP_VerifyTabCol, iTable, iColumn, p->iReg);
#endif
return p->iReg;
}
}
assert( v!=0 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
if( p5 ){
sqlite3VdbeChangeP5(v, p5);
}else{
sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg);
}
return iReg;
}
@ -3443,36 +3275,6 @@ void sqlite3ExprCodeGetColumnToReg(
if( r1!=iReg ) sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, r1, iReg);
}
/*
** Clear all column cache entries.
*/
void sqlite3ExprCacheClear(Parse *pParse){
int i;
#ifdef 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){
sqlite3ExprCacheRemove(pParse, iStart, iCount);
}
/*
** Generate code to move content from registers iFrom...iFrom+nReg-1
** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
@ -3480,29 +3282,8 @@ void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
sqlite3ExprCacheRemove(pParse, iFrom, nReg);
}
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
/*
** Return true if any register in the range iFrom..iTo (inclusive)
** is used as part of the column cache.
**
** 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 */
/*
** Convert a scalar expression node to a TK_REGISTER referencing
** register iReg. The caller must ensure that iReg already contains
@ -3683,8 +3464,6 @@ expr_code_doover:
}
sqlite3VdbeAddOp2(v, OP_Cast, target,
sqlite3AffinityType(pExpr->u.zToken, 0));
testcase( usedAsColumnCache(pParse, inReg, inReg) );
sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
return inReg;
}
#endif /* SQLITE_OMIT_CAST */
@ -3870,10 +3649,7 @@ expr_code_doover:
for(i=1; i<nFarg; i++){
sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
VdbeCoverage(v);
sqlite3ExprCacheRemove(pParse, target, 1);
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
sqlite3ExprCachePop(pParse);
}
sqlite3VdbeResolveLabel(v, endCoalesce);
break;
@ -3939,10 +3715,8 @@ expr_code_doover:
}
}
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
sqlite3ExprCodeExprList(pParse, pFarg, r1, 0,
SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */
}else{
r1 = 0;
}
@ -4115,9 +3889,7 @@ expr_code_doover:
case TK_IF_NULL_ROW: {
int addrINR;
addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
sqlite3ExprCachePush(pParse);
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
sqlite3ExprCachePop(pParse);
sqlite3VdbeJumpHere(v, addrINR);
sqlite3VdbeChangeP3(v, addrINR, inReg);
break;
@ -4178,7 +3950,6 @@ expr_code_doover:
regFree1 = 0;
}
for(i=0; i<nExpr-1; i=i+2){
sqlite3ExprCachePush(pParse);
if( pX ){
assert( pTest!=0 );
opCompare.pRight = aListelem[i].pExpr;
@ -4191,13 +3962,10 @@ expr_code_doover:
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeGoto(v, endLabel);
sqlite3ExprCachePop(pParse);
sqlite3VdbeResolveLabel(v, nextCase);
}
if( (nExpr&1)!=0 ){
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
sqlite3ExprCachePop(pParse);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
@ -4560,18 +4328,14 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse);
break;
}
case TK_OR: {
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse);
break;
}
case TK_NOT: {
@ -4730,19 +4494,15 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_AND: {
testcase( jumpIfNull==0 );
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse);
break;
}
case TK_OR: {
int d2 = sqlite3VdbeMakeLabel(v);
testcase( jumpIfNull==0 );
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse);
break;
}
case TK_NOT: {
@ -5517,14 +5277,6 @@ int sqlite3GetTempReg(Parse *pParse){
*/
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;
}
}
@ -5538,7 +5290,6 @@ int sqlite3GetTempRange(Parse *pParse, int nReg){
i = pParse->iRangeReg;
n = pParse->nRangeReg;
if( nReg<=n ){
assert( !usedAsColumnCache(pParse, i, i+n-1) );
pParse->iRangeReg += nReg;
pParse->nRangeReg -= nReg;
}else{
@ -5552,7 +5303,6 @@ void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
sqlite3ReleaseTempReg(pParse, iReg);
return;
}
sqlite3ExprCacheRemove(pParse, iReg, nReg);
if( nReg>pParse->nRangeReg ){
pParse->nRangeReg = nReg;
pParse->iRangeReg = iReg;

View File

@ -1533,7 +1533,6 @@ void sqlite3GenerateConstraintChecks(
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
VdbeCoverage(v);
sqlite3ExprCachePush(pParse);
switch( onError ){
default: {
@ -1610,7 +1609,6 @@ void sqlite3GenerateConstraintChecks(
break;
}
}
sqlite3ExprCachePop(pParse);
sqlite3VdbeResolveLabel(v, addrRowidOk);
if( sAddr.ipkTop ){
sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto);
@ -1744,7 +1742,6 @@ void sqlite3GenerateConstraintChecks(
}
/* Check to see if the new index entry will be unique */
sqlite3ExprCachePush(pParse);
sqlite3VdbeVerifyAbortable(v, onError);
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
@ -1850,7 +1847,6 @@ void sqlite3GenerateConstraintChecks(
}else{
sqlite3VdbeResolveLabel(v, addrUniqueOk);
}
sqlite3ExprCachePop(pParse);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
}
@ -1954,7 +1950,6 @@ void sqlite3CompleteInsertion(
sqlite3SetMakeRecordP5(v, pTab);
if( !bAffinityDone ){
sqlite3TableAffinity(v, pTab, 0);
sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
}
if( pParse->nested ){
pik_flags = 0;

View File

@ -1550,7 +1550,6 @@ void sqlite3Pragma(
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
/* reg[7] counts the number of entries in the table.
@ -1593,7 +1592,6 @@ void sqlite3Pragma(
char *zErr;
int k;
pParse->iSelfTab = iDataCur + 1;
sqlite3ExprCachePush(pParse);
for(k=pCheck->nExpr-1; k>0; k--){
sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
}
@ -1606,7 +1604,6 @@ void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
integrityCheckResultRow(v);
sqlite3VdbeResolveLabel(v, addrCkOk);
sqlite3ExprCachePop(pParse);
}
sqlite3ExprListDelete(db, pCheck);
}

View File

@ -1149,7 +1149,6 @@ static void selectInnerLoop(
assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
}
@ -1193,7 +1192,6 @@ static void selectInnerLoop(
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}else{
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nResultCol);
sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
}
break;
}
@ -1550,7 +1548,6 @@ static void generateSortTail(
assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) );
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid,
pDest->zAffSdst, nColumn);
sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
break;
}
@ -1565,7 +1562,6 @@ static void generateSortTail(
testcase( eDest==SRT_Coroutine );
if( eDest==SRT_Output ){
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
}else{
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}
@ -2166,7 +2162,6 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
** The current implementation interprets "LIMIT 0" to mean
** no rows.
*/
sqlite3ExprCacheClear(pParse);
if( pLimit ){
assert( pLimit->op==TK_LIMIT );
assert( pLimit->pLeft!=0 );
@ -2952,7 +2947,6 @@ static int generateOutputSubroutine(
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
r1, pDest->zAffSdst, pIn->nSdst);
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
sqlite3ReleaseTempReg(pParse, r1);
@ -2995,7 +2989,6 @@ static int generateOutputSubroutine(
default: {
assert( pDest->eDest==SRT_Output );
sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst);
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
break;
}
}
@ -5336,11 +5329,9 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, pF->iMem);
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
sqlite3ExprCacheClear(pParse);
}
}
@ -5360,12 +5351,10 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
if( regHit ){
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
}
sqlite3ExprCacheClear(pParse);
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
}
pAggInfo->directMode = 0;
sqlite3ExprCacheClear(pParse);
if( addrHitTest ){
sqlite3VdbeJumpHere(v, addrHitTest);
}
@ -6318,7 +6307,6 @@ int sqlite3Select(
}
}
regBase = sqlite3GetTempRange(pParse, nCol);
sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0);
j = nGroupBy;
for(i=0; i<sAggInfo.nColumn; i++){
@ -6342,8 +6330,6 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
sAggInfo.useSortingIdx = 1;
sqlite3ExprCacheClear(pParse);
}
/* If the index or temporary table used by the GROUP BY sort
@ -6366,7 +6352,6 @@ int sqlite3Select(
** from the previous row currently stored in a0, a1, a2...
*/
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3ExprCacheClear(pParse);
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
sortOut, sortPTab);

View File

@ -3091,17 +3091,9 @@ struct Parse {
** Fields above must be initialized to zero. The fields that follow,
** down to the beginning of the recursive section, do not need to be
** initialized as they will be set before being used. The boundary is
** determined by offsetof(Parse,aColCache).
** determined by offsetof(Parse,aTempReg).
**************************************************************************/
struct yColCache {
int iTable; /* Table cursor number */
i16 iColumn; /* Table column number */
u8 tempReg; /* iReg is a temp register that needs to be freed */
int iLevel; /* Nesting level */
int iReg; /* Reg with value of this column. 0 means none. */
int lru; /* Least recently used entry has the smallest value */
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
int aTempReg[8]; /* Holding area for temporary registers */
Token sNameToken; /* Token with unqualified schema object name */
@ -3143,7 +3135,7 @@ struct Parse {
/*
** Sizes and pointers of various parts of the Parse object.
*/
#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/
#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
@ -3930,12 +3922,6 @@ int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnToReg(Parse*, Table*, int, int, int);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int, int);
void sqlite3ExprCacheStore(Parse*, int, int, int);
void sqlite3ExprCachePush(Parse*);
void sqlite3ExprCachePop(Parse*);
void sqlite3ExprCacheRemove(Parse*, int, int);
void sqlite3ExprCacheClear(Parse*);
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
void sqlite3ExprCode(Parse*, Expr*, int);
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);

View File

@ -611,12 +611,6 @@ void sqlite3Update(
testcase( i==31 );
testcase( i==32 );
sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
if( tmask & TRIGGER_BEFORE ){
/* This value will be recomputed in After-BEFORE-trigger-reload-loop
** below, so make sure that it is not cached and reused.
** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */
sqlite3ExprCacheRemove(pParse, regNew+i, 1);
}
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
}

View File

@ -193,14 +193,6 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#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();
}

View File

@ -802,7 +802,6 @@ static void constructAutomaticIndex(
VdbeComment((v, "for %s", pTable->zName));
/* Fill the automatic index with content */
sqlite3ExprCachePush(pParse);
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
if( pTabItem->fg.viaCoroutine ){
int regYield = pTabItem->regReturn;
@ -839,7 +838,6 @@ static void constructAutomaticIndex(
sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3ExprCachePop(pParse);
/* Jump here when skipping the initialization */
sqlite3VdbeJumpHere(v, addrInit);
@ -5077,7 +5075,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
/* Generate loop termination code.
*/
VdbeModuleComment((v, "End WHERE-core"));
sqlite3ExprCacheClear(pParse);
for(i=pWInfo->nLevel-1; i>=0; i--){
int addr;
pLevel = &pWInfo->a[i];

View File

@ -347,7 +347,6 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
/* Code the OP_Affinity opcode if there is anything left to do. */
if( n>0 ){
sqlite3VdbeAddOp4(v, OP_Affinity, base, n, 0, zAff, n);
sqlite3ExprCacheAffinityChange(pParse, base, n);
}
}
@ -1256,7 +1255,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
int nConstraint = pLoop->nLTerm;
int iIn; /* Counter for IN constraints */
sqlite3ExprCachePush(pParse);
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
addrNotFound = pLevel->addrBrk;
for(j=0; j<nConstraint; j++){
@ -1329,7 +1327,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
**
** sqlite3ReleaseTempRange(pParse, iReg, nConstraint+2);
*/
sqlite3ExprCachePop(pParse);
}else
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@ -1422,7 +1419,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
VdbeCoverageIf(v, pX->op==TK_LE);
VdbeCoverageIf(v, pX->op==TK_LT);
VdbeCoverageIf(v, pX->op==TK_GE);
sqlite3ExprCacheAffinityChange(pParse, r1, 1);
sqlite3ReleaseTempReg(pParse, rTemp);
}else{
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrHalt);
@ -1457,7 +1453,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
if( testOp!=OP_Noop ){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
VdbeCoverageIf(v, testOp==OP_Le);
VdbeCoverageIf(v, testOp==OP_Lt);
@ -1683,7 +1678,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
nConstraint = nEq;
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
@ -1708,7 +1702,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
}else if( bStopAtNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
endEq = 0;
nConstraint++;
}
@ -1742,7 +1735,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
)){
iRowidReg = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
VdbeCoverage(v);
}else{
@ -2226,7 +2218,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
pLevel->addrFirst = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
sqlite3ExprCacheClear(pParse);
for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );

View File

@ -33,6 +33,8 @@ do_test btree02-110 {
db eval BEGIN
set i 0
db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} {
if {$a==""} {set a 0}
if {$b==""} {set b 0}
db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)}
# puts "a,b,cnt = ($a,$b,$cnt)"
incr i
@ -47,6 +49,6 @@ do_test btree02-110 {
db eval {COMMIT; BEGIN}
}
db one {COMMIT; SELECT count(*) FROM t1;}
} {20}
} {27}
finish_test