From 896366282dae3789fb277c2dad8660784a0895a3 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 7 Jun 2020 17:33:18 +0000 Subject: [PATCH] Alternative fix to ticket [c8d3b9f0a750a529]: Prior to deleting or modifying an Expr not that is referenced by an AggInfo, modify the AggInfo to get its own copy of the original Expr. FossilOrigin-Name: 7682d8a768fbccfe0cc956e9f6481637146e1ab9763b248ff11052761ce32e32 --- manifest | 27 +++++---- manifest.uuid | 2 +- src/build.c | 13 ++++- src/expr.c | 62 ++++++++++++++++++++- src/select.c | 37 ++++++++++++- src/sqliteInt.h | 17 ++++-- src/window.c | 5 +- test/fuzzdata8.db | Bin 1492992 -> 1495040 bytes test/window1.test | 136 ++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 276 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index ca4608031d..5c9f7982ab 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sdebugging\streeview\soutput,\schange\sthe\sname\sof\s"SELECT-expr"\sexpression\nnodes\sto\sbe\s"subquery-expr",\sso\sas\sto\snot\sconfuse\sthem\swith\sactual\sSELECT\nnodes. -D 2020-06-05T04:01:50.831 +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 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -477,7 +477,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c f14e415fcfd0b52b4e4ebd193ba5fadac5e8252c30f023389af682813af44025 F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 5c8b8749805787313ecf49eb5be3ced1e94bbf8ef54bb01470ce6bd0d5185c67 -F src/build.c 1c3dec6d36ddc697dbc1df04100687cdbbed65aacfda067d1e9632e4102e9999 +F src/build.c 02cff9bb5b3eaf437cbad3f0e1b6c9612e4d4f355c9a766b8ebf121d95cee6d2 F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6 @@ -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 4750c6b63419eefb24c8a6158b9287dea2a9714b4e6e297e25805505c9f73b6c +F src/expr.c 23434d32b9bf92638a61ea6a95845e163f388d6cfd4931b7774f8ad7561b7cfd F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 4b575423b0a5d4898b1a7868ce985cf1a8ad91c741c9abbb108ff02536d20f41 F src/func.c 2333eb4277f55a5efdc12ef754e7d7ec9105d257b2fd00301d23ce1e8fa67dc0 @@ -533,12 +533,12 @@ F src/printf.c 94b5419ad0a17269f76a9e968ca19cf9fa37617abed2e246fc48844e511b6bc6 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 F src/resolve.c c2008519a0654f1e7490e9281ed0397d0f14bb840d81f0b96946248afcbdb25d F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 39a00a8bc89596dfb37c16afcbb1d33de5085b9963564b58aafe1566d08c0881 +F src/select.c 6eb5d0c524ed986107bbcb5b5c5d177c705155bc5284b3006bbec9af66361f47 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 f5e422635c089adf60260e1947ecfaf68dd333bda20c2afdd60323357d8540a0 +F src/sqliteInt.h dda913aa727b7c01cae68259cafe6d26b5d8704c114d128585c1610d324d4d41 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 66c5fd1e48af7581cf90b97700268294f4da4037f120f367715f912e1148d3f9 +F src/window.c 7d19c08b62b70d5dc2ef4c098cc5ba611fac246a111fa36ebb39505415124b90 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -1029,7 +1029,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4 F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2 -F test/fuzzdata8.db 209623791b0ad72ab39110c867af2080a79004e493c4da14ad661e790b5d1ed8 +F test/fuzzdata8.db 6acee588a3311994b57b226c9eac9e9e69f135cb8b000bd48fdb924e32041312 F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 @@ -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 502a3e72fce895aaaa633bbe709f6de3c24eed3ecb8098ab9fb8b47584b4452c +F test/window1.test 30ec5cc344f5ad07bd50742a5dda580d3c6954d60879a440fecaee2ded27700a F test/window2.tcl 492c125fa550cda1dd3555768a2303b3effbeceee215293adf8871efc25f1476 F test/window2.test e466a88bd626d66edc3d352d7d7e1d5531e0079b549ba44efb029d1fbff9fd3c F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03 @@ -1866,7 +1866,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 2827c0a186596299e43eb3e7378eea462d2b060b2c3388ce5cb2bc8e0b43999e -R ee30fc3f51275fe44c86656d5c06c7d7 +P c1c8937a30feff6aa4385b0c264fd8e70d54422a0629c2ce38082d85d3334a57 +R 3e4eafa96401be2af64b22062bf801bb +T *branch * persist-agginfo +T *sym-persist-agginfo * +T -sym-trunk * U drh -Z bb7b42e3c07b2ab8975730fed03b093c +Z 6c6c52ade97d07f6efb7096e79fdc901 diff --git a/manifest.uuid b/manifest.uuid index 5c9bd2c32c..b331efaa0b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c1c8937a30feff6aa4385b0c264fd8e70d54422a0629c2ce38082d85d3334a57 \ No newline at end of file +7682d8a768fbccfe0cc956e9f6481637146e1ab9763b248ff11052761ce32e32 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 877db05084..03081b9654 100644 --- a/src/build.c +++ b/src/build.c @@ -207,12 +207,21 @@ void sqlite3FinishCoding(Parse *pParse){ */ sqlite3AutoincrementBegin(pParse); - /* Code constant expressions that where factored out of inner loops */ + /* Code constant expressions that where factored out of inner loops. + ** + ** The pConstExpr list might also contain expressions that we simply + ** want to keep around until the Parse object is deleted. Such + ** expressions have iConstExprReg==0. Do not generate code for + ** those expressions, of course. + */ if( pParse->pConstExpr ){ ExprList *pEL = pParse->pConstExpr; pParse->okConstFactor = 0; for(i=0; inExpr; i++){ - sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg); + int iReg = pEL->a[i].u.iConstExprReg; + if( iReg>0 ){ + sqlite3ExprCode(pParse, pEL->a[i].pExpr, iReg); + } } } diff --git a/src/expr.c b/src/expr.c index 496177a5c7..631d715685 100644 --- a/src/expr.c +++ b/src/expr.c @@ -5709,6 +5709,66 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ return cnt.nThis>0 || cnt.nOther==0; } +/* +** 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. +** +** 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. +*/ +static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){ + if( !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( 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 ){ + assert( iAgg>=0 && iAggnColumn ); + if( pAggInfo->aCol[iAgg].pExpr==pExpr ){ + pExpr = sqlite3ExprDup(db, pExpr, 0); + if( pExpr ){ + pAggInfo->aCol[iAgg].pExpr = pExpr; + pParse->pConstExpr = + sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr); + } + } + }else{ + assert( iAgg>=0 && iAggnFunc ); + if( pAggInfo->aFunc[iAgg].pExpr==pExpr ){ + pExpr = sqlite3ExprDup(db, pExpr, 0); + if( pExpr ){ + pAggInfo->aFunc[iAgg].pExpr = pExpr; + pParse->pConstExpr = + sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr); + } + } + } + } + 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; +} + /* ** Add a new element to the pAggInfo->aCol[] array. Return the index of ** the new element. Return a negative number if malloc fails. @@ -5739,7 +5799,7 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ &i ); return i; -} +} /* ** This is the xExprCallback for a tree walker. It is used to diff --git a/src/select.c b/src/select.c index 7ff2b5d347..0e7a6ecd0f 100644 --- a/src/select.c +++ b/src/select.c @@ -3791,6 +3791,7 @@ 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. */ @@ -4165,6 +4166,8 @@ 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 @@ -5765,6 +5768,9 @@ int sqlite3Select( } 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 ){ @@ -5917,6 +5923,7 @@ int sqlite3Select( } #endif if( p->pNext==0 ) ExplainQueryPlanPop(pParse); + assert( sAggInfo.nFunc==0 && sAggInfo.nColumn==0 ); return rc; } #endif @@ -6789,8 +6796,34 @@ int sqlite3Select( */ select_end: sqlite3ExprListDelete(db, pMinMaxOrderBy); - sqlite3DbFree(db, sAggInfo.aCol); - sqlite3DbFree(db, sAggInfo.aFunc); + if( sAggInfo.aCol ){ +#ifdef SQLITE_DEBUG + for(i=0; idb->mallocFailed ); + if( pExpr==0 ) continue; + assert( pExpr->pAggInfo==&sAggInfo ); + assert( pExpr->iAgg==i ); + } +#endif + sqlite3DbFree(db, sAggInfo.aCol); + } + if( sAggInfo.aFunc ){ +#ifdef SQLITE_DEBUG + for(i=0; idb->mallocFailed ); + if( pExpr==0 ) continue; + assert( pExpr->pAggInfo==&sAggInfo ); + assert( pExpr->iAgg==i ); + } +#endif + sqlite3DbFree(db, sAggInfo.aFunc); + } +#ifdef SQLITE_DEBUG + sAggInfo.iAggMagic = 0; +#endif + #if SELECTTRACE_ENABLED SELECTTRACE(0x1,pParse,p,("end processing\n")); if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index e37ed673af..52ff846966 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2506,11 +2506,11 @@ struct AggInfo { ExprList *pGroupBy; /* The group by clause */ struct AggInfo_col { /* For each column used in source tables */ Table *pTab; /* Source table */ - int iTable; /* Cursor number of the source table */ - int iColumn; /* Column number within the source table */ - int iSorterColumn; /* Column number in the sorting index */ - int iMem; /* Memory location that acts as accumulator */ Expr *pExpr; /* The original expression */ + int iTable; /* Cursor number of the source table */ + int iMem; /* Memory location that acts as accumulator */ + i16 iColumn; /* Column number within the source table */ + i16 iSorterColumn; /* Column number in the sorting index */ } *aCol; int nColumn; /* Number of used entries in aCol[] */ int nAccumulator; /* Number of columns that show through to the output. @@ -2523,8 +2523,16 @@ struct AggInfo { int iDistinct; /* Ephemeral table used to enforce DISTINCT */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ +#ifdef SQLITE_DEBUG + int iAggMagic; /* Magic number when valid */ +#endif }; +/* +** Value for AggInfo.iAggMagic when the structure is valid +*/ +#define AggInfoMagic 0x2059e99e + /* ** The datatype ynVar is a signed integer, either 16-bit or 32-bit. ** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater @@ -4287,6 +4295,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 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 77ec8a02e0..8046e46274 100644 --- a/src/window.c +++ b/src/window.c @@ -956,12 +956,16 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ Window *pMWin = p->pWin; /* Master window object */ Window *pWin; /* Window object iterator */ Table *pTab; + Walker w; + u32 selFlags = p->selFlags; pTab = sqlite3DbMallocZero(db, sizeof(Table)); if( pTab==0 ){ return sqlite3ErrorToParser(db, SQLITE_NOMEM); } + sqlite3AggInfoPersistWalkerInit(&w, pParse); + sqlite3WalkSelect(&w, p); p->pSrc = 0; p->pWhere = 0; @@ -1042,7 +1046,6 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0); if( p->pSrc ){ Table *pTab2; - Walker w; p->pSrc->a[0].pSelect = pSub; sqlite3SrcListAssignCursors(pParse, p->pSrc); pSub->selFlags |= SF_Expanded; diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db index 350ffa26312c32b3452ebf103c8b7bb90ec69ce0..b1837460297bbe7aea0ea95aa6946c523c946fa4 100644 GIT binary patch delta 24027 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 diff --git a/test/window1.test b/test/window1.test index 677297fc89..97c3cdd79a 100644 --- a/test/window1.test +++ b/test/window1.test @@ -1743,5 +1743,141 @@ do_execsql_test 53.0 { WHERE a.c); } {4 4 4 4} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 54.1 { + CREATE TABLE t1(a VARCHAR(20), b FLOAT); + INSERT INTO t1 VALUES('1',10.0); +} + +do_catchsql_test 54.2 { + SELECT * FROM ( + SELECT sum(b) OVER() AS c FROM t1 + UNION + SELECT b AS c FROM t1 + ) WHERE c>10; +} {1 {misuse of window function sum()}} + +do_execsql_test 54.3 { + INSERT INTO t1 VALUES('2',5.0); + INSERT INTO t1 VALUES('3',15.0); +} + +do_catchsql_test 54.4 { + SELECT * FROM ( + SELECT sum(b) OVER() AS c FROM t1 + UNION + SELECT b AS c FROM t1 + ) WHERE c>10; +} {1 {misuse of window function sum()}} + +# 2020-06-05 ticket c8d3b9f0a750a529 +reset_db +do_execsql_test 55.1 { + CREATE TABLE a(b); + SELECT + (SELECT b FROM a + GROUP BY b + HAVING (SELECT COUNT()OVER() + lead(b)OVER(ORDER BY SUM(DISTINCT b) + b)) + ) + FROM a + UNION + SELECT 99 + ORDER BY 1; +} {99} + +#------------------------------------------------------------------------ +reset_db +do_execsql_test 56.1 { + CREATE TABLE t1(a, b INTEGER); + CREATE TABLE t2(c, d); +} +do_catchsql_test 56.2 { + SELECT avg(b) FROM t1 + UNION ALL + SELECT min(c) OVER () FROM t2 + ORDER BY nosuchcolumn; +} {1 {1st ORDER BY term does not match any column in the result set}} + +reset_db +do_execsql_test 57.1 { + CREATE TABLE t4(a, b, c, d, e); +} + +do_catchsql_test 57.2 { + SELECT b FROM t4 + UNION + SELECT a FROM t4 + ORDER BY ( + SELECT sum(x) OVER() FROM ( + SELECT c AS x FROM t4 + UNION + SELECT d FROM t4 + ORDER BY (SELECT e FROM t4) + ) + ); +} {1 {1st ORDER BY term does not match any column in the result set}} + +# 2020-06-06 various dbsqlfuzz finds and +# ticket 0899cf62f597d7e7 +# +reset_db +do_execsql_test 57.1 { + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(NULL,NULL,NULL); + SELECT + sum(a), + min(b) OVER (), + count(c) OVER (ORDER BY b) + FROM t1; +} {{} {} 0} +do_execsql_test 57.2 { + CREATE TABLE v0 ( v1 INTEGER PRIMARY KEY ) ; + INSERT INTO v0 VALUES ( 10 ) ; + SELECT DISTINCT v1, lead(v1) OVER() FROM v0 GROUP BY v1 ORDER BY 2; +} {10 {}} +do_catchsql_test 57.3 { + DROP TABLE t1; + CREATE TABLE t1(a); + INSERT INTO t1(a) VALUES(22); + CREATE TABLE t3(y); + INSERT INTO t3(y) VALUES(5),(11),(-9); + SELECT ( + SELECT max(y) OVER( ORDER BY (SELECT x FROM (SELECT sum(y) AS x FROM t1))) + ) + FROM t3; +} {1 {misuse of aggregate: sum()}} + +# 2020-06-06 ticket 1f6f353b684fc708 +reset_db +do_execsql_test 58.1 { + CREATE TABLE a(a, b, c); + INSERT INTO a VALUES(1, 2, 3); + INSERT INTO a VALUES(4, 5, 6); + SELECT sum(345+b) OVER (ORDER BY b), + sum(avg(678)) OVER (ORDER BY c) FROM a; +} {347 678.0} + +# 2020-06-06 ticket e5504e987e419fb0 +do_catchsql_test 59.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x INTEGER PRIMARY KEY); + INSERT INTO t1 VALUES (123); + SELECT + ntile( (SELECT sum(x)) ) OVER(ORDER BY x), + min(x) OVER(ORDER BY x) + FROM t1; +} {1 {misuse of aggregate: sum()}} + +# 2020-06-07 ticket f7d890858f361402 +do_execsql_test 60.1 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1 (x INTEGER PRIMARY KEY); + INSERT INTO t1 VALUES (99); + SELECT EXISTS(SELECT count(*) OVER() FROM t1 ORDER BY sum(x) OVER()); +} {1} + +reset_db + finish_test