*       EquivalenceClass for it.
  *
  * sortref is the SortGroupRef of the originating SortGroupClause, if any,
- * or zero if not.
+ * or zero if not.  (It should never be zero if the expression is volatile!)
  *
  * This can be used safely both before and after EquivalenceClass merging;
  * since it never causes merging it does not invalidate any existing ECs
                EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
                ListCell   *lc2;
 
-               /* Never match to a volatile EC */
-               if (cur_ec->ec_has_volatile)
+               /*
+                * Never match to a volatile EC, except when we are looking at another
+                * reference to the same volatile SortGroupClause.
+                */
+               if (cur_ec->ec_has_volatile &&
+                       (sortref == 0 || sortref != cur_ec->ec_sortref))
                        continue;
 
                if (!equal(opfamilies, cur_ec->ec_opfamilies))
        newec->ec_broken = false;
        newec->ec_sortref = sortref;
        newec->ec_merged = NULL;
+
+       if (newec->ec_has_volatile && sortref == 0)             /* should not happen */
+               elog(ERROR, "volatile EquivalenceClass has no sortref");
+
        newem = add_eq_member(newec, expr, pull_varnos((Node *) expr),
                                                  false, expr_datatype);
 
 
                                                        exprType((Node *) tle->expr),
                                                        exprTypmod((Node *) tle->expr),
                                                        0);
+
+                               /*
+                                * Note: it might look funny to be setting sortref = 0 for
+                                * a reference to a volatile sub_eclass.  However, the
+                                * expression is *not* volatile in the outer query: it's
+                                * just a Var referencing whatever the subquery emitted.
+                                * (IOW, the outer query isn't going to re-execute the
+                                * volatile expression itself.)  So this is okay.
+                                */
                                outer_ec =
                                        get_eclass_for_sort_expr(root,
                                                                                         outer_expr,
 
 SELECT DISTINCT ON (string4, ten) string4, ten, two
    FROM tmp
    ORDER BY string4 using <, ten using >, two using <;
+
+-- bug #5049: early 8.4.x chokes on volatile DISTINCT ON clauses
+select distinct on (1) floor(random()) as r, f1 from int4_tbl order by 1,2;