fix_multiple_sortgroupref_labels.patch
text/x-patch
Filename: fix_multiple_sortgroupref_labels.patch
Type: text/x-patch
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| contrib/postgres_fdw/expected/postgres_fdw.out | 17 | 0 |
| contrib/postgres_fdw/postgres_fdw.c | 15 | 24 |
| contrib/postgres_fdw/sql/postgres_fdw.sql | 5 | 0 |
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 4339bbf..69296fd 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -2648,6 +2648,23 @@ select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2
100 | 9 | 5 | 7.0
(10 rows)
+-- GROUP BY clause referring to same column multiple times
+explain (verbose, costs off)
+select c2, c2 from ft1 where c2 = 6 group by 1, 2;
+ QUERY PLAN
+-------------------------------------------------------------------------------
+ Foreign Scan
+ Output: c2, c2
+ Relations: Aggregate on (public.ft1)
+ Remote SQL: SELECT c2, c2 FROM "S 1"."T 1" WHERE ((c2 = 6)) GROUP BY c2, c2
+(4 rows)
+
+select c2, c2 from ft1 where c2 = 6 group by 1, 2;
+ c2 | c2
+----+----
+ 6 | 6
+(1 row)
+
-- Testing HAVING clause shippability
explain (verbose, costs off)
select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index fb65e2e..0ad32a5 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -4591,7 +4591,7 @@ static bool
foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
{
Query *query = root->parse;
- PathTarget *grouping_target;
+ PathTarget *grouping_target = root->upper_targets[UPPERREL_GROUP_AGG];
PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) grouped_rel->fdw_private;
PgFdwRelationInfo *ofpinfo;
List *aggvars;
@@ -4615,16 +4615,6 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
return false;
/*
- * The targetlist expected from this node and the targetlist pushed down
- * to the foreign server may be different. The latter requires
- * sortgrouprefs to be set to push down GROUP BY clause, but should not
- * have those arising from ORDER BY clause. These sortgrouprefs may be
- * different from those in the plan's targetlist. Use a copy of path
- * target to record the new sortgrouprefs.
- */
- grouping_target = copy_pathtarget(root->upper_targets[UPPERREL_GROUP_AGG]);
-
- /*
* Evaluate grouping targets and check whether they are safe to push down
* to the foreign side. All GROUP BY expressions will be part of the
* grouping target and thus there is no need to evaluate it separately.
@@ -4641,6 +4631,8 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
/* Check whether this expression is part of GROUP BY clause */
if (sgref && get_sortgroupref_clause_noerr(sgref, query->groupClause))
{
+ TargetEntry *tle;
+
/*
* If any of the GROUP BY expression is not shippable we can not
* push down aggregation to the foreign server.
@@ -4648,8 +4640,18 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
if (!is_foreign_expr(root, grouped_rel, expr))
return false;
- /* Pushable, add to tlist */
- tlist = add_to_flat_tlist(tlist, list_make1(expr));
+ /*
+ * Pushable, add to tlist. We need to create a tle for this
+ * expression and need to transfer the sortgroupref too. We cannot
+ * use add_to_flat_tlist() here as it avoids the duplicate entries
+ * in the targetlist but here we want those duplicate entries as
+ * there can be multiple GROUP BY expressions pointing to the same
+ * column at different positions.
+ */
+ tle = makeTargetEntry((Expr *) expr, list_length(tlist) + 1, NULL,
+ false);
+ tle->ressortgroupref = sgref;
+ tlist = lappend(tlist, tle);
}
else
{
@@ -4661,14 +4663,6 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
}
else
{
- /*
- * If we have sortgroupref set, then it means that we have an
- * ORDER BY entry pointing to this expression. Since we are
- * not pushing ORDER BY with GROUP BY, clear it.
- */
- if (sgref)
- grouping_target->sortgrouprefs[i] = 0;
-
/* Not matched exactly, pull the var with aggregates then */
aggvars = pull_var_clause((Node *) expr,
PVC_INCLUDE_AGGREGATES);
@@ -4771,9 +4765,6 @@ foreign_grouping_ok(PlannerInfo *root, RelOptInfo *grouped_rel)
}
}
- /* Transfer any sortgroupref data to the replacement tlist */
- apply_pathtarget_labeling_to_tlist(tlist, grouping_target);
-
/* Store generated targetlist */
fpinfo->grouped_tlist = tlist;
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index ddfec79..84db0f9 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -636,6 +636,11 @@ explain (verbose, costs off)
select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
+-- GROUP BY clause referring to same column multiple times
+explain (verbose, costs off)
+select c2, c2 from ft1 where c2 = 6 group by 1, 2;
+select c2, c2 from ft1 where c2 = 6 group by 1, 2;
+
-- Testing HAVING clause shippability
explain (verbose, costs off)
select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;