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:
parent
a4b5fb55f3
commit
02ceed058a
37
manifest
37
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
21235d9a41567897418aa12f7bd6dd8d6ee363147527e1d8fbca14fc83e0f2c9
|
||||
3f5f60cd7529330209027fdae8129cca420cec1050eae50a7750d0b715b56972
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
250
src/expr.c
250
src/expr.c
@ -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, ®Free1);
|
||||
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2);
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
15
src/select.c
15
src/select.c
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user