diff options
Diffstat (limited to 'src/backend/optimizer/plan')
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 4 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 49 | ||||
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 23 |
3 files changed, 73 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index e2c68fe6f99..f3b9821498e 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -1328,6 +1328,10 @@ mark_rels_nulled_by_join(PlannerInfo *root, Index ojrelid, { RelOptInfo *rel = root->simple_rel_array[relid]; + /* ignore the RTE_GROUP RTE */ + if (relid == root->group_rtindex) + continue; + if (rel == NULL) /* must be an outer join */ { Assert(bms_is_member(relid, root->outer_join_rels)); diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index bd4b652f7a3..df35d1ff9c4 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -58,6 +58,7 @@ #include "parser/parse_relation.h" #include "parser/parsetree.h" #include "partitioning/partdesc.h" +#include "rewrite/rewriteManip.h" #include "utils/lsyscache.h" #include "utils/rel.h" #include "utils/selfuncs.h" @@ -3506,9 +3507,23 @@ standard_qp_callback(PlannerInfo *root, void *extra) if (grouping_is_sortable(groupClause)) { - root->group_pathkeys = make_pathkeys_for_sortclauses(root, - groupClause, - tlist); + bool sortable; + + /* + * The groupClause is logically below the grouping step. So if + * there is an RTE entry for the grouping step, we need to remove + * its RT index from the sort expressions before we make PathKeys + * for them. + */ + root->group_pathkeys = + make_pathkeys_for_sortclauses_extended(root, + &groupClause, + tlist, + false, + parse->hasGroupRTE, + &sortable, + false); + Assert(sortable); root->num_groupby_pathkeys = list_length(root->group_pathkeys); } else @@ -3538,6 +3553,7 @@ standard_qp_callback(PlannerInfo *root, void *extra) &root->processed_groupClause, tlist, true, + false, &sortable, true); if (!sortable) @@ -3589,6 +3605,7 @@ standard_qp_callback(PlannerInfo *root, void *extra) &root->processed_distinctClause, tlist, true, + false, &sortable, false); if (!sortable) @@ -3616,6 +3633,7 @@ standard_qp_callback(PlannerInfo *root, void *extra) &groupClauses, tlist, false, + false, &sortable, false); if (!sortable) @@ -5526,7 +5544,19 @@ make_group_input_target(PlannerInfo *root, PathTarget *final_target) { /* * It's a grouping column, so add it to the input target as-is. + * + * Note that the target is logically below the grouping step. So + * with grouping sets we need to remove the RT index of the + * grouping step if there is any from the target expression. */ + if (parse->hasGroupRTE && parse->groupingSets != NIL) + { + Assert(root->group_rtindex > 0); + expr = (Expr *) + remove_nulling_relids((Node *) expr, + bms_make_singleton(root->group_rtindex), + NULL); + } add_column_to_pathtarget(input_target, expr, sgref); } else @@ -5554,11 +5584,23 @@ make_group_input_target(PlannerInfo *root, PathTarget *final_target) * includes Vars used in resjunk items, so we are covering the needs of * ORDER BY and window specifications. Vars used within Aggrefs and * WindowFuncs will be pulled out here, too. + * + * Note that the target is logically below the grouping step. So with + * grouping sets we need to remove the RT index of the grouping step if + * there is any from the non-group Vars. */ non_group_vars = pull_var_clause((Node *) non_group_cols, PVC_RECURSE_AGGREGATES | PVC_RECURSE_WINDOWFUNCS | PVC_INCLUDE_PLACEHOLDERS); + if (parse->hasGroupRTE && parse->groupingSets != NIL) + { + Assert(root->group_rtindex > 0); + non_group_vars = (List *) + remove_nulling_relids((Node *) non_group_vars, + bms_make_singleton(root->group_rtindex), + NULL); + } add_new_columns_to_pathtarget(input_target, non_group_vars); /* clean up cruft */ @@ -6207,6 +6249,7 @@ make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc, &wc->partitionClause, tlist, true, + false, &sortable, false); diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 8caf094f7d6..91c7c4fe2fe 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -26,6 +26,7 @@ #include "optimizer/subselect.h" #include "optimizer/tlist.h" #include "parser/parse_relation.h" +#include "rewrite/rewriteManip.h" #include "tcop/utility.h" #include "utils/syscache.h" @@ -2426,6 +2427,28 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset) subplan_itlist = build_tlist_index(subplan->targetlist); + /* + * If it's a grouping node with grouping sets, any Vars and PHVs appearing + * in the targetlist and quals should have nullingrels that include the + * effects of the grouping step, ie they will have nullingrels equal to + * the input Vars/PHVs' nullingrels plus the RT index of the grouping + * step. In order to perform exact nullingrels matches, we remove the RT + * index of the grouping step first. + */ + if (IsA(plan, Agg) && + root->group_rtindex > 0 && + ((Agg *) plan)->groupingSets) + { + plan->targetlist = (List *) + remove_nulling_relids((Node *) plan->targetlist, + bms_make_singleton(root->group_rtindex), + NULL); + plan->qual = (List *) + remove_nulling_relids((Node *) plan->qual, + bms_make_singleton(root->group_rtindex), + NULL); + } + output_targetlist = NIL; foreach(l, plan->targetlist) { |