Apply my original fix for Taiki Yamaguchi's bug report about DISTINCT MAX().

Add some regression tests for plausible failures in this area.
This commit is contained in:
Tom Lane 2008-03-31 16:59:26 +00:00
parent e86237ff31
commit d344115519
5 changed files with 96 additions and 3 deletions

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.9 2008/01/09 20:42:27 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.10 2008/03/31 16:59:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1638,6 +1638,44 @@ add_child_rel_equivalences(PlannerInfo *root,
}
/*
* 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
* planagg.c runs, it no longer matters). Also we must be called in the
* main planner memory context.
*/
void
mutate_eclass_expressions(PlannerInfo *root,
Node *(*mutator) (),
void *context)
{
ListCell *lc1;
foreach(lc1, root->eq_classes)
{
EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
ListCell *lc2;
foreach(lc2, cur_ec->ec_members)
{
EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2);
cur_em->em_expr = (Expr *)
mutator((Node *) cur_em->em_expr, context);
}
}
}
/*
* find_eclass_clauses_for_index_join
* Create joinclauses usable for a nestloop-with-inner-indexscan

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.36 2008/01/01 19:45:50 momjian Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.37 2008/03/31 16:59:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -187,6 +187,18 @@ optimize_minmax_aggregates(PlannerInfo *root, List *tlist, Path *best_path)
hqual = replace_aggs_with_params_mutator(parse->havingQual,
&aggs_list);
/*
* 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 now, those won't be examined after this point.
*/
mutate_eclass_expressions(root,
replace_aggs_with_params_mutator,
&aggs_list);
/*
* Generate the output plan --- basically just a Result
*/

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.103 2008/01/01 19:45:58 momjian Exp $
* $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.104 2008/03/31 16:59:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -127,6 +127,9 @@ extern void add_child_rel_equivalences(PlannerInfo *root,
AppendRelInfo *appinfo,
RelOptInfo *parent_rel,
RelOptInfo *child_rel);
extern void mutate_eclass_expressions(PlannerInfo *root,
Node *(*mutator) (),
void *context);
extern List *find_eclass_clauses_for_index_join(PlannerInfo *root,
RelOptInfo *rel,
Relids outer_relids);

View File

@ -484,3 +484,36 @@ from int4_tbl;
-2147483647 | 0
(5 rows)
-- check some cases that were handled incorrectly in 8.3.0
select distinct max(unique2) from tenk1;
max
------
9999
(1 row)
select max(unique2) from tenk1 order by 1;
max
------
9999
(1 row)
select max(unique2) from tenk1 order by max(unique2);
max
------
9999
(1 row)
select max(unique2) from tenk1 order by max(unique2)+1;
max
------
9999
(1 row)
select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
max | g
------+---
9999 | 3
9999 | 2
9999 | 1
(3 rows)

View File

@ -217,3 +217,10 @@ select min(tenthous) from tenk1 where thousand = 33;
-- check parameter propagation into an indexscan subquery
select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
from int4_tbl;
-- check some cases that were handled incorrectly in 8.3.0
select distinct max(unique2) from tenk1;
select max(unique2) from tenk1 order by 1;
select max(unique2) from tenk1 order by max(unique2);
select max(unique2) from tenk1 order by max(unique2)+1;
select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;