From c7525241e4d3c1adac3328420a61ada5aa799107 Mon Sep 17 00:00:00 2001 From: Yuya Watari Date: Mon, 11 Dec 2023 12:19:55 +0900 Subject: [PATCH v23 3/6] Solve conflict with self join removal Written by Alena Rybakina [1] with modifications by me. [1] https://www.postgresql.org/message-id/72d292a1-06ff-432a-a803-af5053786444%40yandex.ru --- src/backend/optimizer/plan/analyzejoins.c | 49 ++++++++++++++++------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index 38328d945a..49f3c17057 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -1589,10 +1589,12 @@ replace_relid(Relids relids, int oldId, int newId) * delete them. */ static void -update_eclasses(EquivalenceClass *ec, int from, int to) +update_eclasses(PlannerInfo *root, EquivalenceClass *ec, int from, int to) { List *new_members = NIL; - List *new_sources = NIL; + Bitmapset *new_source_indexes = NULL; + int i; + int j; ListCell *lc; ListCell *lc1; @@ -1634,18 +1636,28 @@ update_eclasses(EquivalenceClass *ec, int from, int to) list_free(ec->ec_members); ec->ec_members = new_members; - list_free(ec->ec_derives); - ec->ec_derives = NULL; + i = -1; + while ((i = bms_next_member(ec->ec_derive_indexes, i)) >= 0) + { + /* + * Can't delete the element because we would need to rebuild all + * the eq_derives indexes. But set a nuke to detect potential problems. + */ + list_nth_cell(root->eq_derives, i)->ptr_value = NULL; + } + bms_free(ec->ec_derive_indexes); + ec->ec_derive_indexes = NULL; /* Update EC source expressions */ - foreach(lc, ec->ec_sources) + i = -1; + while ((i = bms_next_member(ec->ec_source_indexes, i)) >= 0) { - RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc); + RestrictInfo *rinfo = list_nth_node(RestrictInfo, root->eq_sources, i); bool is_redundant = false; if (!bms_is_member(from, rinfo->required_relids)) { - new_sources = lappend(new_sources, rinfo); + new_source_indexes = bms_add_member(new_source_indexes, i); continue; } @@ -1656,9 +1668,10 @@ update_eclasses(EquivalenceClass *ec, int from, int to) * redundancy with existing ones. We don't have to check for * redundancy with derived clauses, because we've just deleted them. */ - foreach(lc1, new_sources) + j = -1; + while ((j = bms_next_member(new_source_indexes, j)) >= 0) { - RestrictInfo *other = lfirst_node(RestrictInfo, lc1); + RestrictInfo *other = list_nth_node(RestrictInfo, root->eq_sources, j); if (!equal(rinfo->clause_relids, other->clause_relids)) continue; @@ -1670,12 +1683,20 @@ update_eclasses(EquivalenceClass *ec, int from, int to) } } - if (!is_redundant) - new_sources = lappend(new_sources, rinfo); + if (is_redundant) + { + /* + * Can't delete the element because we would need to rebuild all + * the eq_sources indexes. But set a nuke to detect potential problems. + */ + list_nth_cell(root->eq_sources, i)->ptr_value = NULL; + } + else + new_source_indexes = bms_add_member(new_source_indexes, i); } - list_free(ec->ec_sources); - ec->ec_sources = new_sources; + bms_free(ec->ec_source_indexes); + ec->ec_source_indexes = new_source_indexes; ec->ec_relids = replace_relid(ec->ec_relids, from, to); } @@ -1855,7 +1876,7 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark, { EquivalenceClass *ec = (EquivalenceClass *) list_nth(root->eq_classes, i); - update_eclasses(ec, toRemove->relid, toKeep->relid); + update_eclasses(root, ec, toRemove->relid, toKeep->relid); toKeep->eclass_indexes = bms_add_member(toKeep->eclass_indexes, i); } -- 2.42.0.windows.2