bug-7703.patch
text/x-patch
Filename: bug-7703.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/equivclass.c | 0 | 0 |
| src/backend/optimizer/plan/planagg.c | 0 | 0 |
| src/include/optimizer/paths.h | 0 | 0 |
| src/test/regress/expected/aggregates.out | 0 | 0 |
| src/test/regress/sql/aggregates.sql | 0 | 0 |
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index 58553df3140f03278b8f6e8effdfe7e01615367a..632295197a9b08e35d3f8bb44377c26143a043c2 100644
*** a/src/backend/optimizer/path/equivclass.c
--- b/src/backend/optimizer/path/equivclass.c
*************** add_child_rel_equivalences(PlannerInfo *
*** 1973,1984 ****
/*
* mutate_eclass_expressions
* Apply an expression tree mutator to all expressions stored in
! * equivalence classes.
*
* This is a bit of a hack ... it's currently needed only by planagg.c,
* which needs to do a global search-and-replace of MIN/MAX Aggrefs
* after eclasses are already set up. Without changing the eclasses too,
! * subsequent matching of ORDER BY clauses would fail.
*
* Note that we assume the mutation won't affect relation membership or any
* other properties we keep track of (which is a bit bogus, but by the time
--- 1973,1984 ----
/*
* mutate_eclass_expressions
* Apply an expression tree mutator to all expressions stored in
! * equivalence classes (but ignore child exprs unless include_child_exprs).
*
* This is a bit of a hack ... it's currently needed only by planagg.c,
* which needs to do a global search-and-replace of MIN/MAX Aggrefs
* after eclasses are already set up. Without changing the eclasses too,
! * subsequent matching of ORDER BY and DISTINCT clauses would fail.
*
* Note that we assume the mutation won't affect relation membership or any
* other properties we keep track of (which is a bit bogus, but by the time
*************** add_child_rel_equivalences(PlannerInfo *
*** 1988,1994 ****
void
mutate_eclass_expressions(PlannerInfo *root,
Node *(*mutator) (),
! void *context)
{
ListCell *lc1;
--- 1988,1995 ----
void
mutate_eclass_expressions(PlannerInfo *root,
Node *(*mutator) (),
! void *context,
! bool include_child_exprs)
{
ListCell *lc1;
*************** mutate_eclass_expressions(PlannerInfo *r
*** 2001,2006 ****
--- 2002,2010 ----
{
EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
+ if (cur_em->em_is_child && !include_child_exprs)
+ continue; /* ignore children unless requested */
+
cur_em->em_expr = (Expr *)
mutator((Node *) cur_em->em_expr, context);
}
diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c
index 55a5ed7b4c6320886e1e0d36d7a6aa857efc25e2..658a4abc31570f6046721602c6eed0fcaf10a6e5 100644
*** a/src/backend/optimizer/plan/planagg.c
--- b/src/backend/optimizer/plan/planagg.c
*************** optimize_minmax_aggregates(PlannerInfo *
*** 257,263 ****
/*
* We have to replace Aggrefs with Params in equivalence classes too, else
! * ORDER BY or DISTINCT on an optimized aggregate will fail.
*
* Note: at some point it might become necessary to mutate other data
* structures too, such as the query's sortClause or distinctClause. Right
--- 257,266 ----
/*
* We have to replace Aggrefs with Params in equivalence classes too, else
! * ORDER BY or DISTINCT on an optimized aggregate will fail. We don't
! * need to process child eclass members though, since they aren't of
! * interest anymore --- and replace_aggs_with_params_mutator isn't able
! * to handle Aggrefs containing translated child Vars, anyway.
*
* Note: at some point it might become necessary to mutate other data
* structures too, such as the query's sortClause or distinctClause. Right
*************** optimize_minmax_aggregates(PlannerInfo *
*** 265,271 ****
*/
mutate_eclass_expressions(root,
replace_aggs_with_params_mutator,
! (void *) root);
/*
* Generate the output plan --- basically just a Result
--- 268,275 ----
*/
mutate_eclass_expressions(root,
replace_aggs_with_params_mutator,
! (void *) root,
! false);
/*
* Generate the output plan --- basically just a Result
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 165856de0bcdf730ef49479fc6d83165bad479ab..c7d59d28da38b7a1e69b5db75806e5edc849dd31 100644
*** a/src/include/optimizer/paths.h
--- b/src/include/optimizer/paths.h
*************** extern void add_child_rel_equivalences(P
*** 124,130 ****
RelOptInfo *child_rel);
extern void mutate_eclass_expressions(PlannerInfo *root,
Node *(*mutator) (),
! void *context);
extern List *generate_implied_equalities_for_indexcol(PlannerInfo *root,
IndexOptInfo *index,
int indexcol,
--- 124,131 ----
RelOptInfo *child_rel);
extern void mutate_eclass_expressions(PlannerInfo *root,
Node *(*mutator) (),
! void *context,
! bool include_child_exprs);
extern List *generate_implied_equalities_for_indexcol(PlannerInfo *root,
IndexOptInfo *index,
int indexcol,
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 7286f1aa446ffc0f3b0d0527daf2a5bbba34713e..4c5b98a6126b9eee2b671006c250dd2c057bf49e 100644
*** a/src/test/regress/expected/aggregates.out
--- b/src/test/regress/expected/aggregates.out
*************** select min(f1), max(f1) from minmaxtest;
*** 740,745 ****
--- 740,784 ----
11 | 18
(1 row)
+ -- DISTINCT doesn't do anything useful here, but it shouldn't fail
+ explain (costs off)
+ select distinct min(f1), max(f1) from minmaxtest;
+ QUERY PLAN
+ ----------------------------------------------------------------------------------------------
+ HashAggregate
+ InitPlan 1 (returns $0)
+ -> Limit
+ -> Merge Append
+ Sort Key: minmaxtest.f1
+ -> Index Only Scan using minmaxtesti on minmaxtest
+ Index Cond: (f1 IS NOT NULL)
+ -> Index Only Scan using minmaxtest1i on minmaxtest1
+ Index Cond: (f1 IS NOT NULL)
+ -> Index Only Scan Backward using minmaxtest2i on minmaxtest2
+ Index Cond: (f1 IS NOT NULL)
+ -> Index Only Scan using minmaxtest3i on minmaxtest3
+ Index Cond: (f1 IS NOT NULL)
+ InitPlan 2 (returns $1)
+ -> Limit
+ -> Merge Append
+ Sort Key: minmaxtest_1.f1
+ -> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_1
+ Index Cond: (f1 IS NOT NULL)
+ -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest1_1
+ Index Cond: (f1 IS NOT NULL)
+ -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest2_1
+ Index Cond: (f1 IS NOT NULL)
+ -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest3_1
+ Index Cond: (f1 IS NOT NULL)
+ -> Result
+ (26 rows)
+
+ select distinct min(f1), max(f1) from minmaxtest;
+ min | max
+ -----+-----
+ 11 | 18
+ (1 row)
+
drop table minmaxtest cascade;
NOTICE: drop cascades to 3 other objects
DETAIL: drop cascades to table minmaxtest1
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index 53a2183b3dde54407d37701e48317704213c2377..38d4757df3f611f2ac82b17dd236f24257832d49 100644
*** a/src/test/regress/sql/aggregates.sql
--- b/src/test/regress/sql/aggregates.sql
*************** explain (costs off)
*** 278,283 ****
--- 278,288 ----
select min(f1), max(f1) from minmaxtest;
select min(f1), max(f1) from minmaxtest;
+ -- DISTINCT doesn't do anything useful here, but it shouldn't fail
+ explain (costs off)
+ select distinct min(f1), max(f1) from minmaxtest;
+ select distinct min(f1), max(f1) from minmaxtest;
+
drop table minmaxtest cascade;
-- check for correct detection of nested-aggregate errors