diff --git b/src/backend/optimizer/path/equivclass.c a/src/backend/optimizer/path/equivclass.c index b8c64d80987..30f1ca37e2e 100644 --- b/src/backend/optimizer/path/equivclass.c +++ a/src/backend/optimizer/path/equivclass.c @@ -617,6 +617,7 @@ make_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, ec->ec_has_const = true; /* it can't affect ec_relids */ } + em->iterator_generation = 0; return em; } @@ -930,6 +931,7 @@ find_ec_member_matching_expr(EquivalenceClass *ec, expr = ((RelabelType *) expr)->arg; setup_eclass_member_iterator(&it, ec, relids); + it.warn_if_returned_before = false; while ((em = eclass_member_iterator_next(&it)) != NULL) { Expr *emexpr; @@ -3149,10 +3151,14 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, * ec - The EquivalenceClass from which to iterate members. * child_relids - The relids to return child members for. */ +uint64 iterator_generation = 0; + void setup_eclass_member_iterator(EquivalenceMemberIterator *it, EquivalenceClass *ec, Relids child_relids) { + it->iterator_generation = ++iterator_generation; + it->warn_if_returned_before = true; it->ec = ec; /* no need to set this if the class has no child members */ it->child_relids = ec->ec_childmembers != NULL ? child_relids : NULL; @@ -3179,6 +3185,9 @@ nextcell: EquivalenceMember *em; em = lfirst_node(EquivalenceMember, it->current_cell); + if (it->warn_if_returned_before && em->iterator_generation == it->iterator_generation) + elog(NOTICE, "returned before %llu", it->iterator_generation); + em->iterator_generation = it->iterator_generation; it->current_cell = lnext(it->current_list, it->current_cell); return em; } diff --git b/src/include/nodes/pathnodes.h a/src/include/nodes/pathnodes.h index a44f5bb1f60..60f156da136 100644 --- b/src/include/nodes/pathnodes.h +++ a/src/include/nodes/pathnodes.h @@ -1514,6 +1514,7 @@ typedef struct EquivalenceMember JoinDomain *em_jdomain; /* join domain containing the source clause */ /* if em_is_child is true, this links to corresponding EM for top parent */ struct EquivalenceMember *em_parent pg_node_attr(read_write_ignore); + uint64 iterator_generation; } EquivalenceMember; /* @@ -1570,6 +1571,8 @@ typedef struct EquivalenceMember */ typedef struct { + uint64 iterator_generation; + bool warn_if_returned_before; EquivalenceClass *ec; /* The EquivalenceClass to iterate over */ int current_relid; /* Current relid position within 'relids'. -1 * when still looping over ec_members and -2