Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d344115

Browse files
committed
Apply my original fix for Taiki Yamaguchi's bug report about DISTINCT MAX().
Add some regression tests for plausible failures in this area.
1 parent e86237f commit d344115

File tree

5 files changed

+96
-3
lines changed

5 files changed

+96
-3
lines changed

src/backend/optimizer/path/equivclass.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.9 2008/01/09 20:42:27 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.10 2008/03/31 16:59:26 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -1638,6 +1638,44 @@ add_child_rel_equivalences(PlannerInfo *root,
16381638
}
16391639

16401640

1641+
/*
1642+
* mutate_eclass_expressions
1643+
* Apply an expression tree mutator to all expressions stored in
1644+
* equivalence classes.
1645+
*
1646+
* This is a bit of a hack ... it's currently needed only by planagg.c,
1647+
* which needs to do a global search-and-replace of MIN/MAX Aggrefs
1648+
* after eclasses are already set up. Without changing the eclasses too,
1649+
* subsequent matching of ORDER BY clauses would fail.
1650+
*
1651+
* Note that we assume the mutation won't affect relation membership or any
1652+
* other properties we keep track of (which is a bit bogus, but by the time
1653+
* planagg.c runs, it no longer matters). Also we must be called in the
1654+
* main planner memory context.
1655+
*/
1656+
void
1657+
mutate_eclass_expressions(PlannerInfo *root,
1658+
Node *(*mutator) (),
1659+
void *context)
1660+
{
1661+
ListCell *lc1;
1662+
1663+
foreach(lc1, root->eq_classes)
1664+
{
1665+
EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
1666+
ListCell *lc2;
1667+
1668+
foreach(lc2, cur_ec->ec_members)
1669+
{
1670+
EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
1671+
1672+
cur_em->em_expr = (Expr *)
1673+
mutator((Node *) cur_em->em_expr, context);
1674+
}
1675+
}
1676+
}
1677+
1678+
16411679
/*
16421680
* find_eclass_clauses_for_index_join
16431681
* Create joinclauses usable for a nestloop-with-inner-indexscan

src/backend/optimizer/plan/planagg.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.36 2008/01/01 19:45:50 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.37 2008/03/31 16:59:26 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -187,6 +187,18 @@ optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path)
187187
hqual = replace_aggs_with_params_mutator(parse->havingQual,
188188
&aggs_list);
189189

190+
/*
191+
* We have to replace Aggrefs with Params in equivalence classes too,
192+
* else ORDER BY or DISTINCT on an optimized aggregate will fail.
193+
*
194+
* Note: at some point it might become necessary to mutate other
195+
* data structures too, such as the query's sortClause or distinctClause.
196+
* Right now, those won't be examined after this point.
197+
*/
198+
mutate_eclass_expressions(root,
199+
replace_aggs_with_params_mutator,
200+
&aggs_list);
201+
190202
/*
191203
* Generate the output plan --- basically just a Result
192204
*/

src/include/optimizer/paths.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.103 2008/01/01 19:45:58 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.104 2008/03/31 16:59:26 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -127,6 +127,9 @@ extern void add_child_rel_equivalences(PlannerInfo *root,
127127
AppendRelInfo *appinfo,
128128
RelOptInfo *parent_rel,
129129
RelOptInfo *child_rel);
130+
extern void mutate_eclass_expressions(PlannerInfo *root,
131+
Node *(*mutator) (),
132+
void *context);
130133
extern List *find_eclass_clauses_for_index_join(PlannerInfo *root,
131134
RelOptInfo *rel,
132135
Relids outer_relids);

src/test/regress/expected/aggregates.out

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,3 +484,36 @@ from int4_tbl;
484484
-2147483647 | 0
485485
(5 rows)
486486

487+
-- check some cases that were handled incorrectly in 8.3.0
488+
select distinct max(unique2) from tenk1;
489+
max
490+
------
491+
9999
492+
(1 row)
493+
494+
select max(unique2) from tenk1 order by 1;
495+
max
496+
------
497+
9999
498+
(1 row)
499+
500+
select max(unique2) from tenk1 order by max(unique2);
501+
max
502+
------
503+
9999
504+
(1 row)
505+
506+
select max(unique2) from tenk1 order by max(unique2)+1;
507+
max
508+
------
509+
9999
510+
(1 row)
511+
512+
select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
513+
max | g
514+
------+---
515+
9999 | 3
516+
9999 | 2
517+
9999 | 1
518+
(3 rows)
519+

src/test/regress/sql/aggregates.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,3 +217,10 @@ select min(tenthous) from tenk1 where thousand = 33;
217217
-- check parameter propagation into an indexscan subquery
218218
select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
219219
from int4_tbl;
220+
221+
-- check some cases that were handled incorrectly in 8.3.0
222+
select distinct max(unique2) from tenk1;
223+
select max(unique2) from tenk1 order by 1;
224+
select max(unique2) from tenk1 order by max(unique2);
225+
select max(unique2) from tenk1 order by max(unique2)+1;
226+
select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;

0 commit comments

Comments
 (0)