diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2022-03-21 17:44:29 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2022-03-21 17:44:29 -0400 |
commit | dfefe38fbea4c6f003319a9921f3fd6ded5e70aa (patch) | |
tree | 8ccabe082e5dffdb14972930df033d5b4469b456 /src/backend/optimizer/plan/subselect.c | |
parent | 2241e5ceda2febd90b06e6cbc02a8b51e9e070e4 (diff) | |
download | postgresql-dfefe38fbea4c6f003319a9921f3fd6ded5e70aa.tar.gz postgresql-dfefe38fbea4c6f003319a9921f3fd6ded5e70aa.zip |
Fix assorted missing logic for GroupingFunc nodes.
The planner needs to treat GroupingFunc like Aggref for many purposes,
in particular with respect to processing of the argument expressions,
which are not to be evaluated at runtime. A few places hadn't gotten
that memo, notably including subselect.c's processing of outer-level
aggregates. This resulted in assertion failures or wrong plans for
cases in which a GROUPING() construct references an outer aggregation
level.
Also fix missing special cases for GroupingFunc in cost_qual_eval
(resulting in wrong cost estimates for GROUPING(), although it's
not clear that that would affect plan shapes in practice) and in
ruleutils.c (resulting in excess parentheses in pretty-print mode).
Per bug #17088 from Yaoguang Chen. Back-patch to all supported
branches.
Richard Guo, Tom Lane
Discussion: https://postgr.es/m/17088-e33882b387de7f5c@postgresql.org
Diffstat (limited to 'src/backend/optimizer/plan/subselect.c')
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 760865a8636..11e29dd1536 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -357,15 +357,17 @@ build_subplan(PlannerInfo *root, Plan *plan, PlannerInfo *subroot, Node *arg = pitem->item; /* - * The Var, PlaceHolderVar, or Aggref has already been adjusted to - * have the correct varlevelsup, phlevelsup, or agglevelsup. + * The Var, PlaceHolderVar, Aggref or GroupingFunc has already been + * adjusted to have the correct varlevelsup, phlevelsup, or + * agglevelsup. * - * If it's a PlaceHolderVar or Aggref, its arguments might contain - * SubLinks, which have not yet been processed (see the comments for - * SS_replace_correlation_vars). Do that now. + * If it's a PlaceHolderVar, Aggref or GroupingFunc, its arguments + * might contain SubLinks, which have not yet been processed (see the + * comments for SS_replace_correlation_vars). Do that now. */ if (IsA(arg, PlaceHolderVar) || - IsA(arg, Aggref)) + IsA(arg, Aggref) || + IsA(arg, GroupingFunc)) arg = SS_process_sublinks(root, arg, false); splan->parParam = lappend_int(splan->parParam, pitem->paramId); @@ -1929,10 +1931,11 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context) } /* - * Don't recurse into the arguments of an outer PHV or aggregate here. Any - * SubLinks in the arguments have to be dealt with at the outer query - * level; they'll be handled when build_subplan collects the PHV or Aggref - * into the arguments to be passed down to the current subplan. + * Don't recurse into the arguments of an outer PHV, Aggref or + * GroupingFunc here. Any SubLinks in the arguments have to be dealt with + * at the outer query level; they'll be handled when build_subplan + * collects the PHV, Aggref or GroupingFunc into the arguments to be + * passed down to the current subplan. */ if (IsA(node, PlaceHolderVar)) { @@ -1944,6 +1947,11 @@ process_sublinks_mutator(Node *node, process_sublinks_context *context) if (((Aggref *) node)->agglevelsup > 0) return node; } + else if (IsA(node, GroupingFunc)) + { + if (((GroupingFunc *) node)->agglevelsup > 0) + return node; + } /* * We should never see a SubPlan expression in the input (since this is @@ -2056,7 +2064,7 @@ SS_identify_outer_params(PlannerInfo *root) outer_params = NULL; for (proot = root->parent_root; proot != NULL; proot = proot->parent_root) { - /* Include ordinary Var/PHV/Aggref params */ + /* Include ordinary Var/PHV/Aggref/GroupingFunc params */ foreach(l, proot->plan_params) { PlannerParamItem *pitem = (PlannerParamItem *) lfirst(l); |