aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2023-10-09 16:37:33 +1300
committerDavid Rowley <drowley@postgresql.org>2023-10-09 16:37:33 +1300
commit9154ededfc99e7637cd61b4ca10f28796125ece2 (patch)
treeb67d29e5d91ba0509ced270331ba3ffe5af9445c
parent3ed98ed88a06f368c700d2ce03ff46d6d415dde3 (diff)
downloadpostgresql-9154ededfc99e7637cd61b4ca10f28796125ece2.tar.gz
postgresql-9154ededfc99e7637cd61b4ca10f28796125ece2.zip
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
-rw-r--r--src/backend/optimizer/util/pathnode.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 5f5596841c8..e518a07e2c6 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -3127,10 +3127,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;