postgres.git / summary / log / commit / refs

commit    7027dd499dd6a31528f9cb27ba872cec8e9b7bbd
Author:   David Rowley <drowley@postgresql.org>
Date:     Mon Jan 26 10:27:15 2026 +0000

    Remove deduplication logic from find_window_functions
    
    This code thought it was optimizing WindowAgg evaluation by getting rid
    of duplicate WindowFuncs, but it turns out all it does today is lead to
    cost-underestimations and makes it possible that optimize_window_clauses
    could miss some of the WindowFuncs that must receive an updated winref.
    
    The deduplication likely was useful when it was first added, but since
    the projection code was changed in b8d7f053c, the list of WindowFuncs
    gathered by find_window_functions isn't used during execution.  Instead,
    the expression evaluation code will process the node's targetlist to find
    the WindowFuncs.
    
    The reason the deduplication could cause issues for
    optimize_window_clauses() is because if a WindowFunc is moved to another
    WindowClause, the winref is adjusted to reference the new WindowClause.
    If any duplicate WindowFuncs were discarded in find_window_functions()
    then the WindowFuncLists may not include all the WindowFuncs that need
    their winref adjusted.  This could lead to an error message such as:
    
    ERROR:  WindowFunc with winref 2 assigned to WindowAgg with winref 1
    
    The back-branches will receive a different fix so that the WindowAgg costs
    are not affected.
    
    Author: Meng Zhang <mza117jc@gmail.com>
    Reviewed-by: David Rowley <dgrowleyml@gmail.com>
    Discussion: https://postgr.es/m/CAErYLFAuxmW0UVdgrz7iiuNrxGQnFK_OP9hBD5CUzRgjrVrz=Q@mail.gmail.com


src/backend/optimizer/util/clauses.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 39d35827c35..32204776c45 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -261,13 +261,10 @@ find_window_functions_walker(Node *node, WindowFuncLists *lists) if (wfunc->winref > lists->maxWinRef) elog(ERROR, "WindowFunc contains out-of-range winref %u", wfunc->winref); - /* eliminate duplicates, so that we avoid repeated computation */ - if (!list_member(lists->windowFuncs[wfunc->winref], wfunc)) - { - lists->windowFuncs[wfunc->winref] = - lappend(lists->windowFuncs[wfunc->winref], wfunc); - lists->numWindowFuncs++; - } + + lists->windowFuncs[wfunc->winref] = + lappend(lists->windowFuncs[wfunc->winref], wfunc); + lists->numWindowFuncs++; /* * We assume that the parser checked that there are no window [parent: 6ceef9408c26]