From 401c2ddf9ce72cccbe39e908737d68a6704c7926 Mon Sep 17 00:00:00 2001 From: Yuya Watari Date: Mon, 30 Jan 2023 09:46:56 +0900 Subject: [PATCH v13 5/7] Fix incorrect filtering condition in iteration The original code incorrectly missed EquivalenceMembers with empty em_relids when 'with_norel_members' is true in eclass_member_iterator_strict_next(). Such an EM passes the second if condition, but fails the last condition because it cannot be superset of non-empty relids. --- src/backend/optimizer/path/equivclass.c | 68 +++++++++++-------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index 561f50cafa..83ea0313e1 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -3733,26 +3733,22 @@ eclass_member_iterator_next(EquivalenceMemberIterator *iter) { EquivalenceMember *em = lfirst_node(EquivalenceMember, lc); - if (!iter->with_children && em->em_is_child) - continue; - - if (!iter->with_norel_members && bms_is_empty(em->em_relids)) - continue; - - if (!bms_overlap(em->em_relids, iter->with_relids)) - continue; - - iter->current_index = foreach_current_index(lc); + if ((iter->with_norel_members && bms_is_empty(em->em_relids)) + || (bms_overlap(em->em_relids, iter->with_relids) + && (iter->with_children || !em->em_is_child))) + { + iter->current_index = foreach_current_index(lc); - /* - * Some users of this iterator will be adding new - * EquivalenceMember during the loop. We must ensure we don't - * return those, so here we return NULL when the loop index goes - * beyond the original length of the ec_members list. - */ - if (iter->current_index >= iter->orig_length) - return NULL; - return em; + /* + * Some users of this iterator will be adding new + * EquivalenceMember during the loop. We must ensure we don't + * return those, so here we return NULL when the loop index goes + * beyond the original length of the ec_members list. + */ + if (iter->current_index >= iter->orig_length) + return NULL; + return em; + } } return NULL; } @@ -3784,26 +3780,22 @@ eclass_member_iterator_strict_next(EquivalenceMemberIterator *iter) { EquivalenceMember *em = lfirst_node(EquivalenceMember, lc); - if (!iter->with_children && em->em_is_child) - continue; - - if (!iter->with_norel_members && bms_is_empty(em->em_relids)) - continue; - - if (!bms_is_subset(iter->with_relids, em->em_relids)) - continue; - - iter->current_index = foreach_current_index(lc); + if ((iter->with_norel_members && bms_is_empty(em->em_relids)) + || (bms_is_subset(iter->with_relids, em->em_relids) + && (iter->with_children || !em->em_is_child))) + { + iter->current_index = foreach_current_index(lc); - /* - * Some users of this iterator will be adding new - * EquivalenceMember during the loop. We must ensure we don't - * return those, so here we return NULL when the loop index goes - * beyond the original length of the ec_members list. - */ - if (iter->current_index >= iter->orig_length) - return NULL; - return em; + /* + * Some users of this iterator will be adding new + * EquivalenceMember during the loop. We must ensure we don't + * return those, so here we return NULL when the loop index goes + * beyond the original length of the ec_members list. + */ + if (iter->current_index >= iter->orig_length) + return NULL; + return em; + } } return NULL; } -- 2.35.3.windows.1