postgres.git / summary / log / commit / refs

commit    d8a295389baee766df882f8f934e205b5978b529
Author:   David Rowley <drowley@postgresql.org>
Date:     Mon Oct 09 03:37:05 2023 +0000
First released in: 17.0, 16.1

    Strip off ORDER BY/DISTINCT aggregate pathkeys in create_agg_path
    
    1349d2790 added code to adjust the PlannerInfo.group_pathkeys so that
    ORDER BY / DISTINCT aggregate functions could obtain pre-sorted inputs
    to allow faster execution.  That commit forgot to adjust the pathkeys in
    create_agg_path().  Some code in there assumed that it was always fine
    to make the AggPath's pathkeys the same as its subpath's.  That seems to
    have been ok up until 1349d2790, but since that commit adds pathkeys for
    columns which are within the aggregate function, those columns won't be
    available above the aggregate node.  This can result in "could not find
    pathkey item to sort" during create_plan().
    
    The fix here is to strip off the additional pathkeys added by
    adjust_group_pathkeys_for_groupagg().  It seems that the pathkeys here
    will only ever be group_pathkeys, so all we need to do is check if the
    length of the pathkey list is longer than the num_groupby_pathkeys and
    get rid of the additional ones only if we see extras.
    
    Reported-by: Justin Pryzby
    Reviewed-by: Richard Guo
    Discussion: https://postgr.es/m/ZQhYYRhUxpW3PSf9%40telsasoft.com
    Backpatch-through: 16, where 1349d2790 was introduced


src/backend/optimizer/util/pathnode.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 211ba65389d..b65323532be 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -3133,10 +3133,26 @@ create_agg_path(PlannerInfo *root, pathnode->path.parallel_safe = rel->consider_parallel && subpath->parallel_safe; pathnode->path.parallel_workers = subpath->parallel_workers; + if (aggstrategy == AGG_SORTED) - pathnode->path.pathkeys = subpath->pathkeys; /* preserves order */ + { + /* + * Attempt to preserve the order of the subpath. Additional pathkeys + * may have been added in adjust_group_pathkeys_for_groupagg() to + * support ORDER BY / DISTINCT aggregates. Pathkeys added there + * belong to columns within the aggregate function, so we must strip + * these additional pathkeys off as those columns are unavailable + * above the aggregate node. + */ + if (list_length(subpath->pathkeys) > root->num_groupby_pathkeys) + pathnode->path.pathkeys = list_copy_head(subpath->pathkeys, + root->num_groupby_pathkeys); + else + pathnode->path.pathkeys = subpath->pathkeys; /* preserves order */ + } else pathnode->path.pathkeys = NIL; /* output is unordered */ + pathnode->subpath = subpath; pathnode->aggstrategy = aggstrategy; [parent: 77db13263766]