0002-Fix-bugs.patch
application/octet-stream
Filename: 0002-Fix-bugs.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch 0002
Subject: Fix bugs
| File | + | − |
|---|---|---|
| contrib/postgres_fdw/postgres_fdw.c | 4 | 4 |
| src/backend/optimizer/path/equivclass.c | 47 | 22 |
| src/backend/optimizer/path/pathkeys.c | 3 | 3 |
From e5be91deda817cec4752b87555e50b6944a96a00 Mon Sep 17 00:00:00 2001
From: Yuya Watari <watari.yuya@gmail.com>
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