/*
  * mutate_eclass_expressions
  *   Apply an expression tree mutator to all expressions stored in
- *   equivalence classes.
+ *   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 clauses would fail.
+ * 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
 void
 mutate_eclass_expressions(PlannerInfo *root,
                          Node *(*mutator) (),
-                         void *context)
+                         void *context,
+                         bool include_child_exprs)
 {
    ListCell   *lc1;
 
        {
            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);
        }
 
 
    /*
     * We have to replace Aggrefs with Params in equivalence classes too, else
-    * ORDER BY or DISTINCT on an optimized aggregate will fail.
+    * 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
     */
    mutate_eclass_expressions(root,
                              replace_aggs_with_params_mutator,
-                             (void *) root);
+                             (void *) root,
+                             false);
 
    /*
     * Generate the output plan --- basically just a Result
 
                           RelOptInfo *child_rel);
 extern void mutate_eclass_expressions(PlannerInfo *root,
                          Node *(*mutator) (),
-                         void *context);
+                         void *context,
+                         bool include_child_exprs);
 extern List *generate_implied_equalities_for_indexcol(PlannerInfo *root,
                                         IndexOptInfo *index,
                                         int indexcol);
 
   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: public.minmaxtest.f1
+                 ->  Index Only Scan using minmaxtesti on minmaxtest
+                       Index Cond: (f1 IS NOT NULL)
+                 ->  Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest
+                       Index Cond: (f1 IS NOT NULL)
+                 ->  Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest
+                       Index Cond: (f1 IS NOT NULL)
+                 ->  Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest
+                       Index Cond: (f1 IS NOT NULL)
+   InitPlan 2 (returns $1)
+     ->  Limit
+           ->  Merge Append
+                 Sort Key: public.minmaxtest.f1
+                 ->  Index Only Scan Backward using minmaxtesti on minmaxtest
+                       Index Cond: (f1 IS NOT NULL)
+                 ->  Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest
+                       Index Cond: (f1 IS NOT NULL)
+                 ->  Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest
+                       Index Cond: (f1 IS NOT NULL)
+                 ->  Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest
+                       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
 
   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;
 
 --