Index: src/backend/optimizer/path/equivclass.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/optimizer/path/equivclass.c,v retrieving revision 1.9 diff -c -r1.9 equivclass.c *** src/backend/optimizer/path/equivclass.c 9 Jan 2008 20:42:27 -0000 1.9 --- src/backend/optimizer/path/equivclass.c 27 Mar 2008 18:25:23 -0000 *************** *** 1639,1644 **** --- 1639,1682 ---- /* + * 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 * scanning the given inner rel with the specified set of outer rels. Index: src/backend/optimizer/plan/planagg.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/optimizer/plan/planagg.c,v retrieving revision 1.36 diff -c -r1.36 planagg.c *** src/backend/optimizer/plan/planagg.c 1 Jan 2008 19:45:50 -0000 1.36 --- src/backend/optimizer/plan/planagg.c 27 Mar 2008 18:25:23 -0000 *************** *** 188,193 **** --- 188,201 ---- &aggs_list); /* + * We have to replace Aggrefs with Params in equivalence classes too, + * else ORDER BY or DISTINCT on an optimized aggregate will fail. + */ + mutate_eclass_expressions(root, + replace_aggs_with_params_mutator, + &aggs_list); + + /* * Generate the output plan --- basically just a Result */ plan = (Plan *) make_result(root, tlist, hqual, NULL); Index: src/include/optimizer/paths.h =================================================================== RCS file: /cvsroot/pgsql/src/include/optimizer/paths.h,v retrieving revision 1.103 diff -c -r1.103 paths.h *** src/include/optimizer/paths.h 1 Jan 2008 19:45:58 -0000 1.103 --- src/include/optimizer/paths.h 27 Mar 2008 18:25:23 -0000 *************** *** 127,132 **** --- 127,135 ---- 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);