From f030b376820102ff6cda49565c8b8173b2d44606 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 22 Feb 2019 19:24:16 +0000 Subject: [PATCH] Internally, remove all references to a Window object that belongs to an expression in an ORDER BY clause if that expression is converted to an alias of a result-set expression. Fix for [4feb3159c6]. FossilOrigin-Name: 579b66eaa0816561c6e47ea116b46f229188f0fc84c1173bfe0d21df2dff9a9a --- src/resolve.c | 49 ++++++++++++++++++++++++++++++++++------------- test/window1.test | 20 +++++++++++++++++++ 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/resolve.c b/src/resolve.c index 9410bc020..fd2cf539a 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -1243,6 +1243,38 @@ int sqlite3ResolveOrderGroupBy( return 0; } +#ifndef SQLITE_OMIT_WINDOWFUNC +/* +** Walker callback for resolveRemoveWindows(). +*/ +static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){ + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + Window **pp; + for(pp=&pWalker->u.pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ + if( *pp==pExpr->y.pWin ){ + *pp = (*pp)->pNextWin; + break; + } + } + } + return WRC_Continue; +} + +/* +** Remove any Window objects owned by the expression pExpr from the +** Select.pWin list of Select object pSelect. +*/ +static void resolveRemoveWindows(Select *pSelect, Expr *pExpr){ + Walker sWalker; + memset(&sWalker, 0, sizeof(Walker)); + sWalker.xExprCallback = resolveRemoveWindowsCb; + sWalker.u.pSelect = pSelect; + sqlite3WalkExpr(&sWalker, pExpr); +} +#else +# define resolveRemoveWindows(x,y) +#endif + /* ** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. ** The Name context of the SELECT statement is pNC. zType is either @@ -1309,19 +1341,10 @@ static int resolveOrderGroupBy( } for(j=0; jpEList->nExpr; j++){ if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ -#ifndef SQLITE_OMIT_WINDOWFUNC - if( ExprHasProperty(pE, EP_WinFunc) ){ - /* Since this window function is being changed into a reference - ** to the same window function the result set, remove the instance - ** of this window function from the Select.pWin list. */ - Window **pp; - for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ - if( *pp==pE->y.pWin ){ - *pp = (*pp)->pNextWin; - } - } - } -#endif + /* Since this expresion is being changed into a reference + ** to an identical expression in the result set, remove all Window + ** objects belonging to the expression from the Select.pWin list. */ + resolveRemoveWindows(pSelect, pE); pItem->u.x.iOrderByCol = j+1; } } diff --git a/test/window1.test b/test/window1.test index 2c504205e..b3073985b 100644 --- a/test/window1.test +++ b/test/window1.test @@ -594,6 +594,26 @@ } { } +#------------------------------------------------------------------------- +do_execsql_test 17.0 { + CREATE TABLE t8(a); + INSERT INTO t8 VALUES(1), (2), (3); +} + +do_execsql_test 17.1 { + SELECT +sum(0) OVER () ORDER BY +sum(0) OVER (); +} {0} + +do_execsql_test 17.2 { + select +sum(a) OVER () FROM t8 ORDER BY +sum(a) OVER () DESC; +} {6 6 6} + +do_execsql_test 17.3 { + SELECT 10+sum(a) OVER (ORDER BY a) + FROM t8 + ORDER BY 10+sum(a) OVER (ORDER BY a) DESC; +} {16 13 11} + # 2020-05-23 # ticket 7a5279a25c57adf1 # -- 2.39.2