From e5be91deda817cec4752b87555e50b6944a96a00 Mon Sep 17 00:00:00 2001 From: Yuya Watari Date: Mon, 8 Aug 2022 15:50:51 +0900 Subject: [PATCH 2/3] Fix bugs --- contrib/postgres_fdw/postgres_fdw.c | 8 +-- src/backend/optimizer/path/equivclass.c | 69 +++++++++++++++++-------- src/backend/optimizer/path/pathkeys.c | 6 +-- 3 files changed, 54 insertions(+), 29 deletions(-) diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 5687d0182f..6bbf10d679 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -7455,7 +7455,7 @@ find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec, { Expr *expr = (Expr *) lfirst(lc1); Index sgref = get_pathtarget_sortgroupref(target, i); - int i; + int j; /* Ignore non-sort expressions */ if (sgref == 0 || @@ -7471,10 +7471,10 @@ find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec, expr = ((RelabelType *) expr)->arg; /* Locate an EquivalenceClass member matching this expr, if any */ - i = -1; - while ((i = bms_next_member(ec->ec_member_indexes, i)) >= 0) + j = -1; + while ((j = bms_next_member(ec->ec_member_indexes, j)) >= 0) { - EquivalenceMember *em = (EquivalenceMember *) list_nth(root->eq_members, i); + EquivalenceMember *em = (EquivalenceMember *) list_nth(root->eq_members, j); Expr *em_expr; /* Don't match constants */ diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index f0dc77a2a2..90c96de7d8 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -365,7 +365,33 @@ process_equivalence(PlannerInfo *root, * PathKeys. We leave it behind with a link so that the merged EC can * be found. */ - ec1->ec_member_indexes = bms_add_members(ec1->ec_member_indexes, ec2->ec_member_indexes); + /* + * TODO: "bms_add_members(ec1->ec_member_indexes, ec2->ec_member_indexes)" + * did not work to combine two EquivalenceClasses. This is probably because + * the order of the EquivalenceMembers is different from the previous + * implementation, which added the ec2's EquivalenceMembers to the end of + * the list. + */ + i = -1; + while ((i = bms_next_member(ec2->ec_member_indexes, i)) >= 0) + { + EquivalenceMember *em = (EquivalenceMember *) list_nth(root->eq_members, i); + int em_index = list_length(root->eq_members); + int j; + + ec1->ec_member_indexes = bms_add_member(ec1->ec_member_indexes, em_index); + root->eq_members = lappend(root->eq_members, em); + + j = -1; + while ((j = bms_next_member(em->em_relids, j)) > 0) + { + RelOptInfo *rel = root->simple_rel_array[j]; + if (bms_equal(rel->relids, em->em_relids)) + { + rel->eclass_member_indexes = bms_add_member(rel->eclass_member_indexes, em_index); + } + } + } ec1->ec_sources = list_concat(ec1->ec_sources, ec2->ec_sources); ec1->ec_derives = list_concat(ec1->ec_derives, ec2->ec_derives); ec1->ec_relids = bms_join(ec1->ec_relids, ec2->ec_relids); @@ -585,8 +611,10 @@ add_eq_member(PlannerInfo *root, EquivalenceClass *ec, Expr *expr, while ((i = bms_next_member(relids, i)) > 0) { RelOptInfo *rel = root->simple_rel_array[i]; - - rel->eclass_member_indexes = bms_add_member(rel->eclass_member_indexes, em_index); + if (bms_equal(rel->relids, relids)) + { + rel->eclass_member_indexes = bms_add_member(rel->eclass_member_indexes, em_index); + } } return em; @@ -2366,19 +2394,14 @@ reconsider_full_join_clause(PlannerInfo *root, RestrictInfo *rinfo) cur_ec->ec_member_indexes = bms_del_member(cur_ec->ec_member_indexes, coal_idx); /* Remove the member from each of the relations */ - /* XXX check this is right. Is there a neater way? */ - i = -1; - while ((i = bms_next_member(left_relids, i)) > 0) - { - RelOptInfo *rel = root->simple_rel_array[i]; - rel->eclass_member_indexes = bms_del_member(rel->eclass_member_indexes, i); - } - i = -1; - while ((i = bms_next_member(right_relids, i)) > 0) + while ((i = bms_next_member(coal_em->em_relids, i)) > 0) { RelOptInfo *rel = root->simple_rel_array[i]; - rel->eclass_member_indexes = bms_del_member(rel->eclass_member_indexes, i); + if (bms_equal(rel->relids, coal_em->em_relids)) + { + rel->eclass_member_indexes = bms_del_member(rel->eclass_member_indexes, coal_idx); + } } return true; @@ -2490,16 +2513,17 @@ match_eclasses_to_foreign_key_col(PlannerInfo *root, i); EquivalenceMember *item1_em = NULL; EquivalenceMember *item2_em = NULL; + int j; /* Never match to a volatile EC */ if (ec->ec_has_volatile) continue; /* Note: it seems okay to match to "broken" eclasses here */ - i = -1; - while ((i = bms_next_member(ec->ec_member_indexes, i)) >= 0) + j = -1; + while ((j = bms_next_member(ec->ec_member_indexes, j)) >= 0) { - EquivalenceMember *em = (EquivalenceMember *) list_nth(root->eq_members, i); + EquivalenceMember *em = (EquivalenceMember *) list_nth(root->eq_members, j); Var *var; if (em->em_is_child) @@ -2914,6 +2938,7 @@ generate_implied_equalities_for_column(PlannerInfo *root, { EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i); EquivalenceMember *cur_em; + int j; /* Sanity check eclass_indexes only contain ECs for rel */ Assert(is_child_rel || bms_is_subset(rel->relids, cur_ec->ec_relids)); @@ -2937,10 +2962,10 @@ generate_implied_equalities_for_column(PlannerInfo *root, * match. See also get_eclass_for_sort_expr.) */ cur_em = NULL; - i = -1; - while ((i = bms_next_member(cur_ec->ec_member_indexes, i)) >= 0) + j = -1; + while ((j = bms_next_member(cur_ec->ec_member_indexes, j)) >= 0) { - cur_em = (EquivalenceMember *) list_nth(root->eq_members, i); + cur_em = (EquivalenceMember *) list_nth(root->eq_members, j); if (bms_equal(cur_em->em_relids, rel->relids) && callback(root, rel, cur_ec, cur_em, callback_arg)) @@ -2955,10 +2980,10 @@ generate_implied_equalities_for_column(PlannerInfo *root, * Found our match. Scan the other EC members and attempt to generate * joinclauses. */ - i = -1; - while ((i = bms_next_member(cur_ec->ec_member_indexes, i)) >= 0) + j = -1; + while ((j = bms_next_member(cur_ec->ec_member_indexes, j)) >= 0) { - EquivalenceMember *other_em = (EquivalenceMember *) list_nth(root->eq_members, i); + EquivalenceMember *other_em = (EquivalenceMember *) list_nth(root->eq_members, j); Oid eq_op; RestrictInfo *rinfo; diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index 1a38aa57a7..de864023b2 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -1490,11 +1490,11 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel, * outer query. */ int best_score = -1; - int i = -1; + int j = -1; - while ((i = bms_next_member(sub_eclass->ec_member_indexes, i)) >= 0) + while ((j = bms_next_member(sub_eclass->ec_member_indexes, j)) >= 0) { - EquivalenceMember *sub_member = (EquivalenceMember *) list_nth(rel->subroot->eq_members, i); + EquivalenceMember *sub_member = (EquivalenceMember *) list_nth(rel->subroot->eq_members, j); Expr *sub_expr = sub_member->em_expr; Oid sub_expr_type = sub_member->em_datatype; Oid sub_expr_coll = sub_eclass->ec_collation; -- 2.35.3.windows.1