Add a linked list of ParseCleanup objects to the end of a Parse object and
use that list as a place to put other sub-objects that need to be deallocated. Have a single such list for infrequently used sub-objects is more efficient than doing an a separate check for each kind of sub-object. FossilOrigin-Name: affa2b7b316941b8a6c4d0d1ff212c81a593faf1d05d129e14d2b70d73a25c59
This commit is contained in:
parent
a6e6cf2c8f
commit
cf3c078f93
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C New\sCLI\scommand:\s\s".stats\svmstep"\senables\sthe\sdisplay\sof\sthe\svirtual-machine\nstep\scount\sonly,\safter\seach\scommand.\s\sUseful\sfor\soptimization\sproblems.
|
||||
D 2021-01-09T19:10:04.989
|
||||
C Add\sa\slinked\slist\sof\sParseCleanup\sobjects\sto\sthe\send\sof\sa\sParse\sobject\sand\nuse\sthat\slist\sas\sa\splace\sto\sput\sother\ssub-objects\sthat\sneed\sto\sbe\sdeallocated.\nHave\sa\ssingle\ssuch\slist\sfor\sinfrequently\sused\ssub-objects\sis\smore\sefficient\nthan\sdoing\san\sa\sseparate\scheck\sfor\seach\skind\sof\ssub-object.
|
||||
D 2021-01-11T20:37:02.868
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -501,7 +501,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
|
||||
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
|
||||
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 81b7ee72cd754b5d0018659d5593355f2d61b3d80f07f200167c4826846e907d
|
||||
F src/insert.c 9ced988440d29531568bfe4f48c7b69035b100f6833ca1080abb710b7c415111
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
|
||||
F src/main.c 97e9f137354bc1f76dc9bb60a0a24f8c45cf73b33e80d3ee4c64155336fb820d
|
||||
@ -535,17 +535,17 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
|
||||
F src/pragma.c 6daaaecc26a4b09481d21722525b079ce756751a43a79cc1d8f122d686806193
|
||||
F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
|
||||
F src/prepare.c a6bac9100b5f171189f6bb7ee12dfeeda7f3a8fd0c89be4a7958f14df13fa746
|
||||
F src/prepare.c 1f8bb4f20d83024194780f28920c6af9cfe52adc772ded8f33b4ee2b66f46f66
|
||||
F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 1948a92ca9eab776632816b97e57c61d933474a78aad4f4ef835c916a83dbb1c
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c 85c7cec9a4a983416d4bd023b2c4fbbeb608ae8dfb069781f80c8ed08b0c7a7c
|
||||
F src/select.c b7281a798ee02cb356d2d8b7381939cb513646a91210478587ed6f7f33c357a8
|
||||
F src/shell.c.in 79bceb990e4bac23a09bb8dd65783ea4867b8bfca9242b5a82b884043e65109a
|
||||
F src/sqlite.h.in 0af968a1fa3c717261e1df0ed105fa7bddb4d82de7e0adb3eab49e6aa81b4de7
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
|
||||
F src/sqliteInt.h 0eb4c251a6df26fb97fcd0c285c5dd442f90f0d0305c14f2a9d0cfc006a0e1da
|
||||
F src/sqliteInt.h e484ffb8ce2182ecd745b2e0af0caa12996e848b0f91748c742d1d135d31770c
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@ -604,9 +604,9 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9
|
||||
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 01dba3023659dc6f6b1e054c14b35a0074bd35de10466b99454d33278191d97f
|
||||
F src/tokenize.c c64c49d7c2ec4490c2fef1f24350167ba16b03b0c6cee58ad1a1d70a4325d4e9
|
||||
F src/treeview.c 4b92992176fb2caefbe06ba5bd06e0e0ebcde3d5564758da672631f17aa51cda
|
||||
F src/trigger.c 515e79206d40d1d4149129318582e79a6e9db590a7b74e226fdb5b2a6c7e1b10
|
||||
F src/trigger.c 29680c54c1aa088fa1b4d50137d75669a40d5ef814394e321fab1e547868e3d3
|
||||
F src/update.c 9f126204a6acb96bbe47391ae48e0fc579105d8e76a6d9c4fab3271367476580
|
||||
F src/upsert.c df8f1727d62b5987c4fd302cd4d7c0c84ae57cd65683c5a34a740dfe24039235
|
||||
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
@ -1895,7 +1895,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 5204c2c4a7b73a64764b0d2d1d7c53709bb64e0d2685a829c7bf31af13bab5e7
|
||||
R 08e016b91a617b99baf0add20ffab4d1
|
||||
P 49dfce469e6a17111b349e53578479daf783064200bf0eec5bf8a91d3553b19f
|
||||
R f1889156a8e996b56aa3e8cdd75a199d
|
||||
U drh
|
||||
Z 8b24dd36b9adf4430f5fd36c021c9d5f
|
||||
Z 2f77ed20cd8529f3498738d09cff4442
|
||||
|
@ -1 +1 @@
|
||||
49dfce469e6a17111b349e53578479daf783064200bf0eec5bf8a91d3553b19f
|
||||
affa2b7b316941b8a6c4d0d1ff212c81a593faf1d05d129e14d2b70d73a25c59
|
@ -371,6 +371,7 @@ static int autoIncBegin(
|
||||
if( pInfo==0 ){
|
||||
pInfo = sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo));
|
||||
if( pInfo==0 ) return 0;
|
||||
sqlite3ParserAddCleanup(pToplevel, sqlite3DbFreeNN, pInfo);
|
||||
pInfo->pNext = pToplevel->pAinc;
|
||||
pToplevel->pAinc = pInfo;
|
||||
pInfo->pTab = pTab;
|
||||
|
@ -570,8 +570,16 @@ void sqlite3ParserReset(Parse *pParse){
|
||||
agginfoFree(db, pThis);
|
||||
pThis = pNext;
|
||||
}
|
||||
while( pParse->pCleanup ){
|
||||
ParseCleanup *pThis = pParse->pCleanup;
|
||||
pParse->pCleanup = pThis->pNext;
|
||||
pThis->xCleanup(db, pThis->pPtr);
|
||||
sqlite3DbFree(db, pThis);
|
||||
}
|
||||
sqlite3DbFree(db, pParse->aLabel);
|
||||
sqlite3ExprListDelete(db, pParse->pConstExpr);
|
||||
if( pParse->pConstExpr ){
|
||||
sqlite3ExprListDelete(db, pParse->pConstExpr);
|
||||
}
|
||||
if( db ){
|
||||
assert( db->lookaside.bDisable >= pParse->disableLookaside );
|
||||
db->lookaside.bDisable -= pParse->disableLookaside;
|
||||
@ -580,6 +588,34 @@ void sqlite3ParserReset(Parse *pParse){
|
||||
pParse->disableLookaside = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a new cleanup operation to a Parser. The cleanup should happen when
|
||||
** the parser object is destroyed.
|
||||
**
|
||||
** Use this mechanism for uncommon cleanups. There is a higher setup
|
||||
** cost, so this should not be used for common cleanups. But for less
|
||||
** common cleanups, we save a single NULL-pointer comparison in
|
||||
** sqlite3ParserReset(), which makes a surprising difference in total
|
||||
** performance.
|
||||
**
|
||||
** If a memory allocation error occurs, then the cleanup happens immediately.
|
||||
*/
|
||||
void sqlite3ParserAddCleanup(
|
||||
Parse *pParse,
|
||||
void (*xCleanup)(sqlite3*,void*),
|
||||
void *pPtr
|
||||
){
|
||||
ParseCleanup *pCleanup = sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
|
||||
if( pCleanup ){
|
||||
pCleanup->pNext = pParse->pCleanup;
|
||||
pParse->pCleanup = pCleanup;
|
||||
pCleanup->pPtr = pPtr;
|
||||
pCleanup->xCleanup = xCleanup;
|
||||
}else{
|
||||
xCleanup(pParse->db, pPtr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
|
||||
*/
|
||||
|
12
src/select.c
12
src/select.c
@ -4140,8 +4140,9 @@ static int flattenSubquery(
|
||||
Table *pTabToDel = pSubitem->pTab;
|
||||
if( pTabToDel->nTabRef==1 ){
|
||||
Parse *pToplevel = sqlite3ParseToplevel(pParse);
|
||||
pTabToDel->pNextZombie = pToplevel->pZombieTab;
|
||||
pToplevel->pZombieTab = pTabToDel;
|
||||
sqlite3ParserAddCleanup(pToplevel,
|
||||
(void(*)(sqlite3*,void*))sqlite3DeleteTable,
|
||||
pTabToDel);
|
||||
}else{
|
||||
pTabToDel->nTabRef--;
|
||||
}
|
||||
@ -4856,12 +4857,15 @@ static struct Cte *searchWith(
|
||||
** statement with which it is associated.
|
||||
*/
|
||||
void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
|
||||
assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
|
||||
if( pWith ){
|
||||
assert( pParse->pWith!=pWith );
|
||||
pWith->pOuter = pParse->pWith;
|
||||
pParse->pWith = pWith;
|
||||
if( bFree ) pParse->pWithToFree = pWith;
|
||||
if( bFree ){
|
||||
sqlite3ParserAddCleanup(pParse,
|
||||
(void(*)(sqlite3*,void*))sqlite3WithDelete,
|
||||
pWith);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1154,6 +1154,7 @@ typedef struct LookasideSlot LookasideSlot;
|
||||
typedef struct Module Module;
|
||||
typedef struct NameContext NameContext;
|
||||
typedef struct Parse Parse;
|
||||
typedef struct ParseCleanup ParseCleanup;
|
||||
typedef struct PreUpdate PreUpdate;
|
||||
typedef struct PrintfArguments PrintfArguments;
|
||||
typedef struct RenameToken RenameToken;
|
||||
@ -2186,7 +2187,6 @@ struct Table {
|
||||
#endif
|
||||
Trigger *pTrigger; /* List of triggers stored in pSchema */
|
||||
Schema *pSchema; /* Schema that contains this table */
|
||||
Table *pNextZombie; /* Next on the Parse.pZombieTab list */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -3348,6 +3348,17 @@ struct TriggerPrg {
|
||||
# define DbMaskNonZero(M) (M)!=0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** An instance of the ParseCleanup object specifies an operation that
|
||||
** should be performed after parsing to deallocation resources obtained
|
||||
** during the parse and which are no longer needed.
|
||||
*/
|
||||
struct ParseCleanup {
|
||||
ParseCleanup *pNext; /* Next cleanup task */
|
||||
void *pPtr; /* Pointer to object to deallocate */
|
||||
void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */
|
||||
};
|
||||
|
||||
/*
|
||||
** An SQL parser context. A copy of this structure is passed through
|
||||
** the parser and down into all the parser action routine in order to
|
||||
@ -3457,10 +3468,9 @@ struct Parse {
|
||||
Token sArg; /* Complete text of a module argument */
|
||||
Table **apVtabLock; /* Pointer to virtual tables needing locking */
|
||||
#endif
|
||||
Table *pZombieTab; /* List of Table objects to delete after code gen */
|
||||
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
|
||||
With *pWith; /* Current WITH clause, or NULL */
|
||||
With *pWithToFree; /* Free this WITH object at the end of the parse */
|
||||
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
|
||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
|
||||
#endif
|
||||
@ -4827,6 +4837,7 @@ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
|
||||
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
|
||||
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
||||
void sqlite3ParserReset(Parse*);
|
||||
void sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
|
||||
#ifdef SQLITE_ENABLE_NORMALIZE
|
||||
char *sqlite3Normalize(Vdbe*, const char*);
|
||||
#endif
|
||||
|
@ -713,19 +713,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
if( !IN_RENAME_OBJECT ){
|
||||
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
|
||||
}
|
||||
|
||||
if( pParse->pWithToFree ) sqlite3WithDelete(db, pParse->pWithToFree);
|
||||
sqlite3DbFree(db, pParse->pVList);
|
||||
while( pParse->pAinc ){
|
||||
AutoincInfo *p = pParse->pAinc;
|
||||
pParse->pAinc = p->pNext;
|
||||
sqlite3DbFreeNN(db, p);
|
||||
}
|
||||
while( pParse->pZombieTab ){
|
||||
Table *p = pParse->pZombieTab;
|
||||
pParse->pZombieTab = p->pNextZombie;
|
||||
sqlite3DeleteTable(db, p);
|
||||
}
|
||||
db->pParse = pParse->pParentParse;
|
||||
pParse->pParentParse = 0;
|
||||
assert( nErr==0 || pParse->rc!=SQLITE_OK );
|
||||
|
@ -1000,7 +1000,6 @@ static TriggerPrg *codeRowTrigger(
|
||||
sqlite3VdbeDelete(v);
|
||||
}
|
||||
|
||||
assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
|
||||
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
|
||||
sqlite3ParserReset(pSubParse);
|
||||
sqlite3StackFree(db, pSubParse);
|
||||
|
Loading…
Reference in New Issue
Block a user