diff --git a/manifest b/manifest index 5c9f7982ab..ad5a11efd3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Alternative\sfix\sto\sticket\s[c8d3b9f0a750a529]:\s\sPrior\sto\sdeleting\sor\smodifying\nan\sExpr\snot\sthat\sis\sreferenced\sby\san\sAggInfo,\smodify\sthe\sAggInfo\sto\sget\sits\nown\scopy\sof\sthe\soriginal\sExpr. -D 2020-06-07T17:33:18.737 +C AggInfo\sobjects\smight\sbe\sreferenced\seven\safter\sthe\ssqlite3Select()\sfunction\nthat\screated\sthem\shas\sexited.\s\sSo\sAggInfo\scannot\sbe\sa\sstack\svariable.\s\sAnd\sit\nmust\snot\sbe\sfreed\suntil\sthe\sParse\sobject\sis\sdestroyed. +D 2020-06-07T20:18:07.068 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 23434d32b9bf92638a61ea6a95845e163f388d6cfd4931b7774f8ad7561b7cfd +F src/expr.c 3ee54650bbf8cf1003bee34bbeca354c9c7bddab3ef66ba618f806a1c7c51b4b 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 aeb3ba661e2666dab15c4b5c55f6eb816f01d20e35fa860bb807e4a3b36e1e27 +F src/prepare.c bb996921a85590418f951f27566216646fad2d6856ba131b21594862055b1bd7 F src/printf.c 94b5419ad0a17269f76a9e968ca19cf9fa37617abed2e246fc48844e511b6bc6 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c c2008519a0654f1e7490e9281ed0397d0f14bb840d81f0b96946248afcbdb25d F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 6eb5d0c524ed986107bbcb5b5c5d177c705155bc5284b3006bbec9af66361f47 +F src/select.c fb79ed71f8b8bbe9fefaba9b844f80700dea4f175ccac34c64a7b5cd75abc362 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 dda913aa727b7c01cae68259cafe6d26b5d8704c114d128585c1610d324d4d41 +F src/sqliteInt.h 04621e8c61c2bf4578d07e99cc5b5909b16d5e34600ed8297a8fd4d1a95afc4e F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032 F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -1727,7 +1727,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2 F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 4baffc3acb2e5188a5e3a895b2b543ed09e62f7c72d713c1feebf76222fe9976 F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc -F test/window1.test 30ec5cc344f5ad07bd50742a5dda580d3c6954d60879a440fecaee2ded27700a +F test/window1.test 49f81c25c065fd65b64cd2aaa96f20199fd5d8f847dd1c8151cfccae2aeae83f F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476 F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03 @@ -1866,10 +1866,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 c1c8937a30feff6aa4385b0c264fd8e70d54422a0629c2ce38082d85d3334a57 -R 3e4eafa96401be2af64b22062bf801bb -T *branch * persist-agginfo -T *sym-persist-agginfo * -T -sym-trunk * +P 7682d8a768fbccfe0cc956e9f6481637146e1ab9763b248ff11052761ce32e32 +R aa0e843c27b9cda2c788e9652bc81696 U drh -Z 6c6c52ade97d07f6efb7096e79fdc901 +Z e618df7dc043f3b81d6494dff0ad5e1b diff --git a/manifest.uuid b/manifest.uuid index b331efaa0b..01928527e0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7682d8a768fbccfe0cc956e9f6481637146e1ab9763b248ff11052761ce32e32 \ No newline at end of file +3c840b4df306e2db1da08673e9ede973b4cb6d2b3f9eeeab5835e39452ee3056 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 631d715685..b1beb2e3eb 100644 --- a/src/expr.c +++ b/src/expr.c @@ -5730,7 +5730,6 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ int iAgg = pExpr->iAgg; Parse *pParse = pWalker->pParse; sqlite3 *db = pParse->db; - assert( pAggInfo->iAggMagic==AggInfoMagic ); assert( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_FUNCTION || pExpr->op==TK_AGG_FUNCTION ); if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){ diff --git a/src/prepare.c b/src/prepare.c index 2599546760..c63c0a8353 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -530,11 +530,26 @@ 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 0e7a6ecd0f..9e8af0cb17 100644 --- a/src/select.c +++ b/src/select.c @@ -5752,10 +5752,10 @@ int sqlite3Select( Expr *pWhere; /* The WHERE clause. May be NULL */ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ Expr *pHaving; /* The HAVING clause. May be NULL */ + AggInfo *pAggInfo = 0; /* Aggregate information */ int rc = 1; /* Value to return from this function */ DistinctCtx sDistinct; /* Info on how to code the DISTINCT keyword */ SortCtx sSort; /* Info on how to code the ORDER BY clause */ - AggInfo sAggInfo; /* Information used by aggregate queries */ int iEnd; /* Address of the end of the query */ sqlite3 *db; /* The database connection */ ExprList *pMinMaxOrderBy = 0; /* Added ORDER BY for min/max queries */ @@ -5767,10 +5767,6 @@ int sqlite3Select( return 1; } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; - memset(&sAggInfo, 0, sizeof(sAggInfo)); -#ifdef SQLITE_DEBUG - sAggInfo.iAggMagic = AggInfoMagic; -#endif #if SELECTTRACE_ENABLED SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain)); if( sqlite3SelectTrace & 0x100 ){ @@ -5923,7 +5919,6 @@ int sqlite3Select( } #endif if( p->pNext==0 ) ExplainQueryPlanPop(pParse); - assert( sAggInfo.nFunc==0 && sAggInfo.nColumn==0 ); return rc; } #endif @@ -6361,14 +6356,20 @@ int sqlite3Select( ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the ** SELECT statement. */ + pAggInfo = sqlite3DbMallocZero(db, sizeof(*pAggInfo) ); + if( pAggInfo==0 ){ + goto select_end; + } + pAggInfo->pNext = pParse->pAggList; + pParse->pAggList = pAggInfo; memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; - sNC.uNC.pAggInfo = &sAggInfo; + sNC.uNC.pAggInfo = pAggInfo; VVA_ONLY( sNC.ncFlags = NC_UAggInfo; ) - sAggInfo.mnReg = pParse->nMem+1; - sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; - sAggInfo.pGroupBy = pGroupBy; + pAggInfo->mnReg = pParse->nMem+1; + pAggInfo->nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0; + pAggInfo->pGroupBy = pGroupBy; sqlite3ExprAnalyzeAggList(&sNC, pEList); sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy); if( pHaving ){ @@ -6381,14 +6382,14 @@ int sqlite3Select( } sqlite3ExprAnalyzeAggregates(&sNC, pHaving); } - sAggInfo.nAccumulator = sAggInfo.nColumn; - if( p->pGroupBy==0 && p->pHaving==0 && sAggInfo.nFunc==1 ){ - minMaxFlag = minMaxQuery(db, sAggInfo.aFunc[0].pExpr, &pMinMaxOrderBy); + pAggInfo->nAccumulator = pAggInfo->nColumn; + if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){ + minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pExpr, &pMinMaxOrderBy); }else{ minMaxFlag = WHERE_ORDERBY_NORMAL; } - for(i=0; inFunc; i++){ + Expr *pExpr = pAggInfo->aFunc[i].pExpr; assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); sNC.ncFlags |= NC_InAggFunc; sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList); @@ -6400,22 +6401,22 @@ int sqlite3Select( #endif sNC.ncFlags &= ~NC_InAggFunc; } - sAggInfo.mxReg = pParse->nMem; + pAggInfo->mxReg = pParse->nMem; if( db->mallocFailed ) goto select_end; #if SELECTTRACE_ENABLED if( sqlite3SelectTrace & 0x400 ){ int ii; - SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", &sAggInfo)); + SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo)); sqlite3TreeViewSelect(0, p, 0); - for(ii=0; iinColumn; ii++){ sqlite3DebugPrintf("agg-column[%d] iMem=%d\n", - ii, sAggInfo.aCol[ii].iMem); - sqlite3TreeViewExpr(0, sAggInfo.aCol[ii].pExpr, 0); + ii, pAggInfo->aCol[ii].iMem); + sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pExpr, 0); } - for(ii=0; iinFunc; ii++){ sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n", - ii, sAggInfo.aFunc[ii].iMem); - sqlite3TreeViewExpr(0, sAggInfo.aFunc[ii].pExpr, 0); + ii, pAggInfo->aFunc[ii].iMem); + sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pExpr, 0); } } #endif @@ -6440,10 +6441,11 @@ int sqlite3Select( ** that we do not need it after all, the OP_SorterOpen instruction ** will be converted into a Noop. */ - sAggInfo.sortingIdx = pParse->nTab++; - pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pGroupBy,0,sAggInfo.nColumn); + pAggInfo->sortingIdx = pParse->nTab++; + pKeyInfo = sqlite3KeyInfoFromExprList(pParse, pGroupBy, + 0, pAggInfo->nColumn); addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, - sAggInfo.sortingIdx, sAggInfo.nSortingColumn, + pAggInfo->sortingIdx, pAggInfo->nSortingColumn, 0, (char*)pKeyInfo, P4_KEYINFO); /* Initialize memory locations used by GROUP BY aggregate processing @@ -6498,8 +6500,8 @@ int sqlite3Select( nGroupBy = pGroupBy->nExpr; nCol = nGroupBy; j = nGroupBy; - for(i=0; i=j ){ + for(i=0; inColumn; i++){ + if( pAggInfo->aCol[i].iSorterColumn>=j ){ nCol++; j++; } @@ -6507,8 +6509,8 @@ int sqlite3Select( regBase = sqlite3GetTempRange(pParse, nCol); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); j = nGroupBy; - for(i=0; inColumn; i++){ + struct AggInfo_col *pCol = &pAggInfo->aCol[i]; if( pCol->iSorterColumn>=j ){ int r1 = j + regBase; sqlite3ExprCodeGetColumnOfTable(v, @@ -6518,16 +6520,16 @@ int sqlite3Select( } regRecord = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); - sqlite3VdbeAddOp2(v, OP_SorterInsert, sAggInfo.sortingIdx, regRecord); + sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nCol); sqlite3WhereEnd(pWInfo); - sAggInfo.sortingIdxPTab = sortPTab = pParse->nTab++; + pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++; sortOut = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); - sqlite3VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd); + sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); - sAggInfo.useSortingIdx = 1; + pAggInfo->useSortingIdx = 1; } /* If the index or temporary table used by the GROUP BY sort @@ -6551,14 +6553,14 @@ int sqlite3Select( */ addrTopOfLoop = sqlite3VdbeCurrentAddr(v); if( groupBySort ){ - sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, + sqlite3VdbeAddOp3(v, OP_SorterData, pAggInfo->sortingIdx, sortOut, sortPTab); } for(j=0; jnExpr; j++){ if( groupBySort ){ sqlite3VdbeAddOp3(v, OP_Column, sortPTab, j, iBMem+j); }else{ - sAggInfo.directMode = 1; + pAggInfo->directMode = 1; sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j); } } @@ -6588,14 +6590,14 @@ int sqlite3Select( ** the current row */ sqlite3VdbeJumpHere(v, addr1); - updateAccumulator(pParse, iUseFlag, &sAggInfo); + updateAccumulator(pParse, iUseFlag, pAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); VdbeComment((v, "indicate data in accumulator")); /* End of the loop */ if( groupBySort ){ - sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); + sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop); VdbeCoverage(v); }else{ sqlite3WhereEnd(pWInfo); @@ -6628,7 +6630,7 @@ int sqlite3Select( VdbeCoverage(v); VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); - finalizeAggFunctions(pParse, &sAggInfo); + finalizeAggFunctions(pParse, pAggInfo); sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, -1, &sSort, &sDistinct, pDest, @@ -6639,7 +6641,7 @@ int sqlite3Select( /* Generate a subroutine that will reset the group-by accumulator */ sqlite3VdbeResolveLabel(v, addrReset); - resetAccumulator(pParse, &sAggInfo); + resetAccumulator(pParse, pAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); VdbeComment((v, "indicate accumulator empty")); sqlite3VdbeAddOp1(v, OP_Return, regReset); @@ -6647,7 +6649,7 @@ int sqlite3Select( } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */ else { Table *pTab; - if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){ + if( (pTab = isSimpleCount(p, pAggInfo))!=0 ){ /* If isSimpleCount() returns a pointer to a Table structure, then ** the SQL statement is of the form: ** @@ -6702,7 +6704,7 @@ int sqlite3Select( if( pKeyInfo ){ sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO); } - sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem); + sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem); sqlite3VdbeAddOp1(v, OP_Close, iCsr); explainSimpleCount(pParse, pTab, pBest); }else{ @@ -6717,12 +6719,16 @@ int sqlite3Select( ** first row visited by the aggregate, so that they are updated at ** least once even if the FILTER clause means the min() or max() ** function visits zero rows. */ - if( sAggInfo.nAccumulator ){ - for(i=0; ifuncFlags&SQLITE_FUNC_NEEDCOLL ) break; + if( pAggInfo->nAccumulator ){ + for(i=0; inFunc; i++){ + if( ExprHasProperty(pAggInfo->aFunc[i].pExpr, EP_WinFunc) ){ + continue; + } + if( pAggInfo->aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ){ + break; + } } - if( i==sAggInfo.nFunc ){ + if( i==pAggInfo->nFunc ){ regAcc = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc); } @@ -6733,7 +6739,7 @@ int sqlite3Select( ** of output. */ assert( p->pGroupBy==0 ); - resetAccumulator(pParse, &sAggInfo); + resetAccumulator(pParse, pAggInfo); /* If this query is a candidate for the min/max optimization, then ** minMaxFlag will have been previously set to either @@ -6749,7 +6755,7 @@ int sqlite3Select( if( pWInfo==0 ){ goto select_end; } - updateAccumulator(pParse, regAcc, &sAggInfo); + updateAccumulator(pParse, regAcc, pAggInfo); if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); if( sqlite3WhereIsOrdered(pWInfo)>0 ){ sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo)); @@ -6757,7 +6763,7 @@ int sqlite3Select( (minMaxFlag==WHERE_ORDERBY_MIN?"min":"max"))); } sqlite3WhereEnd(pWInfo); - finalizeAggFunctions(pParse, &sAggInfo); + finalizeAggFunctions(pParse, pAggInfo); } sSort.pOrderBy = 0; @@ -6796,32 +6802,23 @@ int sqlite3Select( */ select_end: sqlite3ExprListDelete(db, pMinMaxOrderBy); - if( sAggInfo.aCol ){ #ifdef SQLITE_DEBUG - for(i=0; idb->mallocFailed ); + if( pAggInfo ){ + for(i=0; inColumn; i++){ + Expr *pExpr = pAggInfo->aCol[i].pExpr; + assert( pExpr!=0 || db->mallocFailed ); if( pExpr==0 ) continue; - assert( pExpr->pAggInfo==&sAggInfo ); + assert( pExpr->pAggInfo==pAggInfo ); assert( pExpr->iAgg==i ); } -#endif - sqlite3DbFree(db, sAggInfo.aCol); - } - if( sAggInfo.aFunc ){ -#ifdef SQLITE_DEBUG - for(i=0; idb->mallocFailed ); + for(i=0; inFunc; i++){ + Expr *pExpr = pAggInfo->aFunc[i].pExpr; + assert( pExpr!=0 || db->mallocFailed ); if( pExpr==0 ) continue; - assert( pExpr->pAggInfo==&sAggInfo ); + assert( pExpr->pAggInfo==pAggInfo ); assert( pExpr->iAgg==i ); } -#endif - sqlite3DbFree(db, sAggInfo.aFunc); } -#ifdef SQLITE_DEBUG - sAggInfo.iAggMagic = 0; #endif #if SELECTTRACE_ENABLED diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 52ff846966..0b71ef42bb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2526,6 +2526,7 @@ struct AggInfo { #ifdef SQLITE_DEBUG int iAggMagic; /* Magic number when valid */ #endif + AggInfo *pNext; /* Next in list of them all */ }; /* @@ -3329,6 +3330,7 @@ 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 */ diff --git a/test/window1.test b/test/window1.test index 97c3cdd79a..3336a613ab 100644 --- a/test/window1.test +++ b/test/window1.test @@ -1877,7 +1877,16 @@ do_execsql_test 60.1 { SELECT EXISTS(SELECT count(*) OVER() FROM t1 ORDER BY sum(x) OVER()); } {1} +# 2020-06-07 test case generated by dbsqlfuzz showing how an AggInfo +# object might be referenced after the sqlite3Select() call that created +# it returns. This proves the need to persist all AggInfo objects until +# the Parse object is destroyed. +# reset_db - +do_execsql_test 61.1 { +CREATE TABLE t1(a); +INSERT INTO t1 VALUES(5),(NULL),('seventeen'); +SELECT (SELECT max(x)OVER(ORDER BY x) % min(x)OVER(ORDER BY CASE x WHEN 889 THEN x WHEN x THEN x END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST((SELECT (SELECT max(x)OVER(ORDER BY x) / min(x)OVER(ORDER BY CASE x WHEN 889 THEN 299 WHEN -true THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a IN(SELECT (SELECT max(x) & sum ( a )OVER(ORDER BY CASE x WHEN -8 THEN 299 WHEN 863 THEN 863 END)) FROM (SELECT (SELECT sum(CAST(a AS )) FROM t1) AS x FROM t1)) AS t1 )) FROM t1) AS x FROM t1)) AS x )) FROM t1) AS x FROM t1)) AS real)) FROM t1) AS x FROM t1); +} {{} {} {}} finish_test