-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
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
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
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
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
-a53bdd311c4154fd5e1131efbb9665362f79db5a35ce9f7b1547f74b8ee2d8ba
\ No newline at end of file
+9a4cc1dbf2a605ccda495ceb8e33cdc95f3436dbc11a1fa8aee4918b125fae90
\ No newline at end of file
#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);
}
}
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;
}
}
/*
-** 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 && iAgg<pAggInfo->nColumn );
- 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 && iAgg<pAggInfo->nFunc );
- 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( iAgg<pAggInfo->nColumn && pAggInfo->aCol[iAgg].pCExpr==pExpr ){
+ pAggInfo->aCol[iAgg].pCExpr = &nullExpr;
+ }
+ if( iAgg<pAggInfo->nFunc && 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;
}
/*
*/
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 */
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;
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 ){
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.
*/
/* Finially, delete what is left of the subquery and return
** success.
*/
- sqlite3AggInfoPersistWalkerInit(&w, pParse);
- sqlite3WalkSelect(&w,pSub1);
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
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;
/* 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);
#ifdef SQLITE_DEBUG
if( pAggInfo ){
for(i=0; i<pAggInfo->nColumn; 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; i<pAggInfo->nFunc; 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"));
} *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 */
};
/*
#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 */
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 */
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);
if( pTab==0 ){
return sqlite3ErrorToParser(db, SQLITE_NOMEM);
}
- sqlite3AggInfoPersistWalkerInit(&w, pParse);
- sqlite3WalkSelect(&w, p);
p->pSrc = 0;
p->pWhere = 0;