From: drh Date: Tue, 9 Jun 2020 14:56:01 +0000 (+0000) Subject: Crazy experimental change to refcount the AggInfo objects. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Frefcount-agginfo;p=thirdparty%2Fsqlite.git Crazy experimental change to refcount the AggInfo objects. FossilOrigin-Name: 9a4cc1dbf2a605ccda495ceb8e33cdc95f3436dbc11a1fa8aee4918b125fae90 --- diff --git a/manifest b/manifest index 330b564652..5bc941daac 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Give\sthe\sexpression\spointer\sfields\sof\sAggInfo\sdistinctive\snames\sin\sorder\sto\nsimplify\stracking\sof\sall\stheir\suses. -D 2020-06-09T13:38:12.505 +C Crazy\sexperimental\schange\sto\srefcount\sthe\sAggInfo\sobjects. +D 2020-06-09T14:56:01.543 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -485,7 +485,7 @@ F src/date.c b29b349d277e3d579dcc295b24c0a2caed83fd8f090a9f7cbe6070c0fd662384 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 793deaf88a0904f88285d93d6713c636d55ede0ffd9f08d10f4ea825531d367f F src/delete.c 88047c8e59878c920fce14582bc1dde4d81157d1ca5ffdf36c2907e6d41996c4 -F src/expr.c 5afb8dd59d5617e0eb25f91143ed042b6cd99c006352bdbd441cb9638d2602d8 +F src/expr.c 87f1d6b0b25dd3ffb980c6a4119ca745220a2dc6b32a3625cdaeb8788b6975f0 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 4b575423b0a5d4898b1a7868ce985cf1a8ad91c741c9abbb108ff02536d20f41 F src/func.c 2333eb4277f55a5efdc12ef754e7d7ec9105d257b2fd00301d23ce1e8fa67dc0 @@ -528,17 +528,17 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a F src/pragma.c 1b0db48177e52b256c003b8dc6ac708b1079a82cded944a23820574586a4731f F src/pragma.h 8168e588536bffd95319451f34e9a754dc37d205ebe433031a7813c5b286beae -F src/prepare.c bb996921a85590418f951f27566216646fad2d6856ba131b21594862055b1bd7 +F src/prepare.c aeb3ba661e2666dab15c4b5c55f6eb816f01d20e35fa860bb807e4a3b36e1e27 F src/printf.c 94b5419ad0a17269f76a9e968ca19cf9fa37617abed2e246fc48844e511b6bc6 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c c2008519a0654f1e7490e9281ed0397d0f14bb840d81f0b96946248afcbdb25d F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c a1f5efdbbfae1f73746242b43daedc974a4ae702d62c305219da650ec10fb08f +F src/select.c 0944abec9afc89dfb89f366a021070af9d676e089edb4e529fdd0225fa23a50d F src/shell.c.in c6e26593f2738eefded08a39204bf6b48db135cdfaa458c26ffe57055b4fe365 F src/sqlite.h.in 74342b41e9d68ff9e56b192009046f8dd0aa2bd76ce1a588f330de614ba61de7 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197 -F src/sqliteInt.h 8fddd3ff00bb5983c45fbe891c9c4134b5d4799d8816a1e97cba38dc66aca4c2 +F src/sqliteInt.h 6c523dc65a4886d2fe943ae0e9a78b1e2c31e1e3689f247ea194737f49aadc13 F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032 F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -624,7 +624,7 @@ F src/where.c 7bcc07ff56d03d73308245135d96de46d2faeaee628bd4badf0bae60ae6a31fe F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c F src/wherecode.c 7b939de85d65cc4b4bfa197513136b9e0ae03167e3b82842ca5a0ba1055ba65d F src/whereexpr.c 264d58971eaf8256eb5b0917bcd7fc7a1f1109fdda183a8382308a1b18a2dce7 -F src/window.c 7d19c08b62b70d5dc2ef4c098cc5ba611fac246a111fa36ebb39505415124b90 +F src/window.c ce5e05bb8fab2fafe5b10da8960a71257a6ce876e0e5e90a18712d5831e76745 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1867,7 +1867,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 b5711b4eead10ef4b0b61f2e2c54768d215a4105f6d47d2ea78991b6e53a6831 -R 45115571336eb976de1e3114a0d3911d +P a53bdd311c4154fd5e1131efbb9665362f79db5a35ce9f7b1547f74b8ee2d8ba +R 3ee13eb60634ef4149de2b3557feb11d +T *branch * refcount-agginfo +T *sym-refcount-agginfo * +T -sym-trunk * U drh -Z b9fb75855deff6080f9952a1c1c95794 +Z 3bf31ff6e0ee54933573322b2a2bdccc diff --git a/manifest.uuid b/manifest.uuid index 2406f422d1..134277863d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a53bdd311c4154fd5e1131efbb9665362f79db5a35ce9f7b1547f74b8ee2d8ba \ No newline at end of file +9a4cc1dbf2a605ccda495ceb8e33cdc95f3436dbc11a1fa8aee4918b125fae90 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 555b2a8d82..eca92ef211 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1135,8 +1135,17 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){ #endif } } - if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken); - if( !ExprHasProperty(p, EP_Static) ){ + if( ExprHasProperty(p, EP_MemToken|EP_AggInfo|EP_Static) ){ + if( ExprHasProperty(p, EP_MemToken) ){ + sqlite3DbFree(db, p->u.zToken); + } + if( ExprHasProperty(p, EP_AggInfo) ){ + sqlite3AggInfoUnref(db, p->pAggInfo, p); + } + if( !ExprHasProperty(p, EP_Static) ){ + sqlite3DbFreeNN(db, p); + } + }else{ sqlite3DbFreeNN(db, p); } } @@ -1371,6 +1380,11 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){ pNew->pRight = sqlite3ExprDup(db, p->pRight, 0); } } + if( ExprHasProperty(p, EP_AggInfo) ){ + p->pAggInfo->nAggRef++; +//printf("AggInfo (%d/%p) up to %d on dup\n", p->pAggInfo->selId, p->pAggInfo, p->pAggInfo->nAggRef); fflush(stdout); + + } } return pNew; } @@ -5715,61 +5729,34 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ } /* -** This is a Walker expression node callback. -** -** For Expr nodes that contain pAggInfo pointers, make sure the AggInfo -** object that is referenced does not refer directly to the Expr. If -** it does, make a copy. This is done because the pExpr argument is -** subject to change. +** Decrement the reference count on pAggInfo. Delete it when the +** reference count reaches zero. ** -** The copy is stored on pParse->pConstExpr with a register number of 0. -** This will cause the expression to be deleted automatically when the -** Parse object is destroyed, but the zero register number means that it -** will not generate any code in the preamble. +** If pExpr is not NULL, that means that the reference count is being +** decremented because pExpr is being deleted. Break the reference +** in pAggInfo to pExpr because pExpr is going away. */ -static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ - if( ALWAYS(!ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced)) - && pExpr->pAggInfo!=0 - ){ - AggInfo *pAggInfo = pExpr->pAggInfo; - int iAgg = pExpr->iAgg; - Parse *pParse = pWalker->pParse; - sqlite3 *db = pParse->db; - assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION ); - if( pExpr->op==TK_AGG_COLUMN ){ - assert( iAgg>=0 && iAggnColumn ); - if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){ - pExpr = sqlite3ExprDup(db, pExpr, 0); - if( pExpr ){ - pAggInfo->aCol[iAgg].pCExpr = pExpr; - pParse->pConstExpr = - sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr); - } - } - }else{ - assert( iAgg>=0 && iAggnFunc ); - if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){ - pExpr = sqlite3ExprDup(db, pExpr, 0); - if( pExpr ){ - pAggInfo->aFunc[iAgg].pFExpr = pExpr; - pParse->pConstExpr = - sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr); - } - } - } +void sqlite3AggInfoUnref(sqlite3 *db, AggInfo *pAggInfo, Expr *pExpr){ + int iAgg; + static Expr nullExpr = { TK_NULL }; + if( pAggInfo==0 ) return; +//printf("AggInfo (%d/%p) nRef down to %d\n", pAggInfo->selId, pAggInfo, pAggInfo->nAggRef-1); fflush(stdout); + if( pAggInfo->nAggRef==1 ){ + sqlite3DbFree(db, pAggInfo->aCol); + sqlite3DbFree(db, pAggInfo->aFunc); + sqlite3DbFree(db, pAggInfo); + return; + } + pAggInfo->nAggRef--; + if( pExpr==0 ) return; + iAgg = pExpr->iAgg; + assert( iAgg>=0 ); + if( iAggnColumn && pAggInfo->aCol[iAgg].pCExpr==pExpr ){ + pAggInfo->aCol[iAgg].pCExpr = &nullExpr; + } + if( iAggnFunc && pAggInfo->aFunc[iAgg].pFExpr==pExpr ){ + pAggInfo->aFunc[iAgg].pFExpr = &nullExpr; } - return WRC_Continue; -} - -/* -** Initialize a Walker object so that will persist AggInfo entries referenced -** by the tree that is walked. -*/ -void sqlite3AggInfoPersistWalkerInit(Walker *pWalker, Parse *pParse){ - memset(pWalker, 0, sizeof(*pWalker)); - pWalker->pParse = pParse; - pWalker->xExprCallback = agginfoPersistExprCb; - pWalker->xSelectCallback = sqlite3SelectWalkNoop; } /* @@ -5879,8 +5866,12 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ */ ExprSetVVAProperty(pExpr, EP_NoReduce); pExpr->pAggInfo = pAggInfo; + pAggInfo->nAggRef++; +//printf("AggInfo (%d/%p) nRef up to %d on col %d\n", pAggInfo->selId, pAggInfo, pAggInfo->nAggRef, k); fflush(stdout); + pExpr->op = TK_AGG_COLUMN; pExpr->iAgg = (i16)k; + ExprSetProperty(pExpr, EP_AggInfo); break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ @@ -5927,6 +5918,10 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ ExprSetVVAProperty(pExpr, EP_NoReduce); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; + pAggInfo->nAggRef++; +//printf("AggInfo (%d/%p) nRef up to %d on func %d\n", pAggInfo->selId, pAggInfo, pAggInfo->nAggRef, i); fflush(stdout); + + ExprSetProperty(pExpr, EP_AggInfo); return WRC_Prune; }else{ return WRC_Continue; diff --git a/src/prepare.c b/src/prepare.c index c63c0a8353..2599546760 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -530,26 +530,11 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){ return i; } -/* -** Deallocate a single AggInfo object -*/ -static void agginfoFree(sqlite3 *db, AggInfo *p){ - sqlite3DbFree(db, p->aCol); - sqlite3DbFree(db, p->aFunc); - sqlite3DbFree(db, p); -} - /* ** Free all memory allocations in the pParse object */ void sqlite3ParserReset(Parse *pParse){ sqlite3 *db = pParse->db; - AggInfo *pThis = pParse->pAggList; - while( pThis ){ - AggInfo *pNext = pThis->pNext; - agginfoFree(db, pThis); - pThis = pNext; - } sqlite3DbFree(db, pParse->aLabel); sqlite3ExprListDelete(db, pParse->pConstExpr); if( db ){ diff --git a/src/select.c b/src/select.c index cd242bb1fd..3de41893f1 100644 --- a/src/select.c +++ b/src/select.c @@ -3791,7 +3791,6 @@ static int flattenSubquery( Expr *pWhere; /* The WHERE clause */ struct SrcList_item *pSubitem; /* The subquery */ sqlite3 *db = pParse->db; - Walker w; /* Walker to persist agginfo data */ /* Check to see if flattening is permitted. Return 0 if not. */ @@ -4166,8 +4165,6 @@ static int flattenSubquery( /* Finially, delete what is left of the subquery and return ** success. */ - sqlite3AggInfoPersistWalkerInit(&w, pParse); - sqlite3WalkSelect(&w,pSub1); sqlite3SelectDelete(db, pSub1); #if SELECTTRACE_ENABLED @@ -6360,8 +6357,7 @@ int sqlite3Select( if( pAggInfo==0 ){ goto select_end; } - pAggInfo->pNext = pParse->pAggList; - pParse->pAggList = pAggInfo; + pAggInfo->nAggRef = 1; pAggInfo->selId = p->selId; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; @@ -6598,7 +6594,7 @@ int sqlite3Select( /* End of the loop */ if( groupBySort ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop); + sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop); VdbeCoverage(v); }else{ sqlite3WhereEnd(pWInfo); @@ -6806,21 +6802,20 @@ select_end: #ifdef SQLITE_DEBUG if( pAggInfo ){ for(i=0; inColumn; i++){ - Expr *pExpr = pAggInfo->aCol[i].pCExpr; - assert( pExpr!=0 || db->mallocFailed ); - if( pExpr==0 ) continue; - assert( pExpr->pAggInfo==pAggInfo ); - assert( pExpr->iAgg==i ); + Expr *pE = pAggInfo->aCol[i].pCExpr; + assert( pE!=0 || db->mallocFailed ); + if( pE==0 ) continue; + assert( pE->pAggInfo==0 || (pE->pAggInfo==pAggInfo && pE->iAgg==i) ); } for(i=0; inFunc; i++){ - Expr *pExpr = pAggInfo->aFunc[i].pFExpr; - assert( pExpr!=0 || db->mallocFailed ); - if( pExpr==0 ) continue; - assert( pExpr->pAggInfo==pAggInfo ); - assert( pExpr->iAgg==i ); + Expr *pE = pAggInfo->aFunc[i].pFExpr; + assert( pE!=0 || db->mallocFailed ); + if( pE==0 ) continue; + assert( pE->pAggInfo==0 || (pE->pAggInfo==pAggInfo && pE->iAgg==i) ); } } #endif + sqlite3AggInfoUnref(db, pAggInfo, 0); #if SELECTTRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end processing\n")); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7231856423..16cd1a85ab 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2524,7 +2524,7 @@ struct AggInfo { } *aFunc; int nFunc; /* Number of entries in aFunc[] */ u32 selId; /* Select to which this AggInfo belongs */ - AggInfo *pNext; /* Next in list of them all */ + u32 nAggRef; /* Ref counter. Delete when it reaches zero */ }; /* @@ -2695,7 +2695,7 @@ struct Expr { #define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ #define EP_Win 0x008000 /* Contains window functions */ #define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ - /* 0x020000 // available for reuse */ +#define EP_AggInfo 0x020000 /* Use the pAggInfo field */ #define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ #define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ @@ -3328,7 +3328,6 @@ struct Parse { Parse *pToplevel; /* Parse structure for main program (or NULL) */ Table *pTriggerTab; /* Table triggers are being coded for */ Parse *pParentParse; /* Parent parser if this parser is nested */ - AggInfo *pAggList; /* List of all AggInfo objects */ int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */ u32 nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */ u32 oldmask; /* Mask of old.* columns referenced */ @@ -4295,7 +4294,7 @@ int sqlite3ExprCompareSkip(Expr*, Expr*, int); int sqlite3ExprListCompare(ExprList*, ExprList*, int); int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); int sqlite3ExprImpliesNonNullRow(Expr*,int); -void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*); +void sqlite3AggInfoUnref(sqlite3*, AggInfo*, Expr*); void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); diff --git a/src/window.c b/src/window.c index 8046e46274..cb1e2d324d 100644 --- a/src/window.c +++ b/src/window.c @@ -964,8 +964,6 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ if( pTab==0 ){ return sqlite3ErrorToParser(db, SQLITE_NOMEM); } - sqlite3AggInfoPersistWalkerInit(&w, pParse); - sqlite3WalkSelect(&w, p); p->pSrc = 0; p->pWhere = 0;