* 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;