v6-0003-Implement-iterators.patch
application/octet-stream
Filename: v6-0003-Implement-iterators.patch
Type: application/octet-stream
Part: 8
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 v6-0003
Subject: Implement iterators
| File | + | − |
|---|---|---|
| contrib/postgres_fdw/postgres_fdw.c | 9 | 15 |
| src/backend/optimizer/path/equivclass.c | 312 | 70 |
| src/include/nodes/pathnodes.h | 68 | 0 |
| src/include/optimizer/paths.h | 148 | 2 |
From fcef5092a17e36fdd5798096ee362aff2b23f55c Mon Sep 17 00:00:00 2001
From: Yuya Watari <watari.yuya@gmail.com>
Date: Wed, 14 Sep 2022 09:56:42 +0900
Subject: [PATCH v6 3/3] Implement iterators
---
contrib/postgres_fdw/postgres_fdw.c | 24 +-
src/backend/optimizer/path/equivclass.c | 382 +++++++++++++++++++-----
src/include/nodes/pathnodes.h | 68 +++++
src/include/optimizer/paths.h | 150 +++++++++-
4 files changed, 537 insertions(+), 87 deletions(-)
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index e8996456be..e4f6aa33b1 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -7412,15 +7412,13 @@ conversion_error_callback(void *arg)
EquivalenceMember *
find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
{
- Bitmapset *matching_ems;
- int i = -1;
+ EquivalenceMember *em;
+ EquivalenceMemberIterator it;
- matching_ems = get_ecmember_indexes(root, ec, rel->relids, true, false);
+ get_ecmember_indexes_iterator(&it, root, ec, rel->relids, true, false, false);
- while ((i = bms_next_member(matching_ems, i)) >= 0)
+ while ((em = get_next_matching_member(root, &it)) != NULL)
{
- EquivalenceMember *em = list_nth_node(EquivalenceMember, root->eq_members, i);
-
/*
* Note we require !bms_is_empty, else we'd accept constant
* expressions which are not suitable for the purpose.
@@ -7459,9 +7457,9 @@ find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec,
{
Expr *expr = (Expr *) lfirst(lc1);
Index sgref = get_pathtarget_sortgroupref(target, i);
- Bitmapset *matching_ems;
+ EquivalenceMember *em;
+ EquivalenceMemberStrictIterator it;
Relids expr_relids;
- int j;
/* Ignore non-sort expressions */
if (sgref == 0 ||
@@ -7477,14 +7475,11 @@ find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec,
expr = ((RelabelType *) expr)->arg;
expr_relids = pull_varnos(root, (Node *) expr);
- matching_ems = get_ecmember_indexes_strict(root, ec, expr_relids,
- false, false);
+ get_ecmember_indexes_strict_iterator(&it, root, ec, expr_relids,
+ false, false, false);
/* Locate an EquivalenceClass member matching this expr, if any */
- j = -1;
- while ((j = bms_next_member(matching_ems, j)) >= 0)
+ while ((em = get_next_matching_member_strict(root, &it)) != NULL)
{
- EquivalenceMember *em = list_nth_node(EquivalenceMember,
- root->eq_members, j);
Expr *em_expr;
/* don't expect constants */
@@ -7507,7 +7502,6 @@ find_em_for_rel_target(PlannerInfo *root, EquivalenceClass *ec,
}
i++;
bms_free(expr_relids);
- bms_free(matching_ems);
}
return NULL;
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index 5f0d2bafd4..3207c7e35a 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -663,7 +663,34 @@ add_eq_member(PlannerInfo *root, EquivalenceClass *ec, Expr *expr,
root->eq_members = lappend(root->eq_members, em);
/* record exprs with no relids */
- if (bms_is_empty(expr_relids))
+ /*
+ * TODO: I had to use relids instead of expr_relids to pass regression tests.
+ * This is probably related to get_ecmember_indexes[_strict]_iterator
+ * functions, which is quoted below.
+ *
+ * =====
+ * void
+ * get_ecmember_indexes_iterator(...)
+ * {
+ * ...
+ * else
+ * {
+ * Bitmapset *index;
+ *
+ * it->check_on_iterate = !caller_needs_recheck;
+ *
+ * index =
+ * with_children ? ec->ec_member_indexes : ec->ec_nonchild_indexes;
+ * if (!with_norel_members)
+ * index = bms_difference(index, ec->ec_norel_indexes);
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * it->index = index;
+ * }
+ * }
+ * =====
+ */
+ if (bms_is_empty(relids))
ec->ec_norel_indexes = bms_add_member(ec->ec_norel_indexes, em_index);
if (is_child)
@@ -748,8 +775,8 @@ get_eclass_for_sort_expr(PlannerInfo *root,
foreach(lc1, root->eq_classes)
{
EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
- Bitmapset *matching_ems;
- int i;
+ EquivalenceMember *cur_em;
+ EquivalenceMemberStrictIterator it;
/*
* Never match to a volatile EC, except when we are looking at another
@@ -764,15 +791,11 @@ get_eclass_for_sort_expr(PlannerInfo *root,
if (!equal(opfamilies, cur_ec->ec_opfamilies))
continue;
- matching_ems = get_ecmember_indexes_strict(root, cur_ec, expr_relids,
- true, true);
+ get_ecmember_indexes_strict_iterator(&it, root, cur_ec, expr_relids,
+ true, true, true);
- i = -1;
- while ((i = bms_next_member(matching_ems, i)) >= 0)
+ while ((cur_em = get_next_matching_member_strict(root, &it)) != NULL)
{
- EquivalenceMember *cur_em = list_nth_node(EquivalenceMember,
- root->eq_members, i);
-
/*
* Ignore child members unless they match the request.
*/
@@ -909,22 +932,19 @@ find_ec_member_matching_expr(PlannerInfo *root,
Expr *expr,
Relids relids)
{
- Bitmapset *matching_ems;
Relids expr_relids;
- int i;
+ EquivalenceMember *em;
+ EquivalenceMemberStrictIterator it;
/* We ignore binary-compatible relabeling on both ends */
while (expr && IsA(expr, RelabelType))
expr = ((RelabelType *) expr)->arg;
expr_relids = pull_varnos(root, (Node *) expr);
- matching_ems = get_ecmember_indexes_strict(root, ec, expr_relids, true, true);
+ get_ecmember_indexes_strict_iterator(&it, root, ec, expr_relids, true, true, true);
- i = -1;
- while ((i = bms_next_member(matching_ems, i)) >= 0)
+ while ((em = get_next_matching_member_strict(root, &it)) != NULL)
{
- EquivalenceMember *em = list_nth_node(EquivalenceMember,
- root->eq_members, i);
Expr *emexpr;
/*
@@ -1693,9 +1713,9 @@ generate_join_implied_equalities_normal(PlannerInfo *root,
List *new_members = NIL;
List *outer_members = NIL;
List *inner_members = NIL;
- Bitmapset *matching_ems;
+ EquivalenceMember *cur_em;
+ EquivalenceMemberIterator it;
ListCell *lc1;
- int i;
/*
* First, scan the EC to identify member values that are computable at the
@@ -1706,14 +1726,10 @@ generate_join_implied_equalities_normal(PlannerInfo *root,
* as well as to at least one input member, plus enforce at least one
* outer-rel member equal to at least one inner-rel member.
*/
- matching_ems = get_ecmember_indexes(root, ec, join_relids, true, false);
+ get_ecmember_indexes_iterator(&it, root, ec, join_relids, true, false, true);
- i = -1;
- while ((i = bms_next_member(matching_ems, i)) >= 0)
+ while ((cur_em = get_next_matching_member(root, &it)) != NULL)
{
- EquivalenceMember *cur_em = list_nth_node(EquivalenceMember,
- root->eq_members, i);
-
/*
* We don't need to check explicitly for child EC members. This test
* against join_relids will cause them to be ignored except when
@@ -1872,16 +1888,13 @@ generate_join_implied_equalities_broken(PlannerInfo *root,
Relids nominal_inner_relids,
RelOptInfo *inner_rel)
{
- Bitmapset *matching_es;
List *result = NIL;
- int i;
+ RestrictInfo *restrictinfo;
+ RestrictInfoIterator it;
- matching_es = get_ec_source_indexes(root, ec, nominal_join_relids);
- i = -1;
- while ((i = bms_next_member(matching_es, i)) >= 0)
+ get_ec_source_indexes_iterator(&it, root, ec, nominal_join_relids, true);
+ while ((restrictinfo = get_next_matching_rinfo(root, &it)) != NULL)
{
- RestrictInfo *restrictinfo = list_nth_node(RestrictInfo,
- root->eq_sources, i);
Relids clause_relids = restrictinfo->required_relids;
if (bms_is_subset(clause_relids, nominal_join_relids) &&
@@ -2258,7 +2271,8 @@ reconsider_outer_join_clause(PlannerInfo *root, RestrictInfo *rinfo,
foreach(lc1, root->eq_classes)
{
EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
- Bitmapset *matching_ems;
+ EquivalenceMember *cur_em;
+ EquivalenceMemberStrictIterator it;
bool match;
int i;
@@ -2275,15 +2289,11 @@ reconsider_outer_join_clause(PlannerInfo *root, RestrictInfo *rinfo,
continue;
/* Does it contain a match to outervar? */
match = false;
- matching_ems = get_ecmember_indexes_strict(root, cur_ec,
- outer_relids,
- false, true);
- i = -1;
- while ((i = bms_next_member(matching_ems, i)) >= 0)
+ get_ecmember_indexes_strict_iterator(&it, root, cur_ec,
+ outer_relids,
+ false, true, true);
+ while ((cur_em = get_next_matching_member_strict(root, &it)) != NULL)
{
- EquivalenceMember *cur_em = list_nth_node(EquivalenceMember,
- root->eq_members, i);
-
Assert(!cur_em->em_is_child); /* no children yet */
if (equal(outervar, cur_em->em_expr))
{
@@ -2383,7 +2393,7 @@ reconsider_full_join_clause(PlannerInfo *root, RestrictInfo *rinfo)
{
EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
EquivalenceMember *coal_em = NULL;
- Bitmapset *matching_ems;
+ EquivalenceMemberStrictIterator it;
bool match;
bool matchleft;
bool matchright;
@@ -2415,14 +2425,12 @@ reconsider_full_join_clause(PlannerInfo *root, RestrictInfo *rinfo)
* the two column types). Is it OK to strip implicit coercions from
* the COALESCE arguments?
*/
- matching_ems = get_ecmember_indexes_strict(root, cur_ec,
- rinfo->clause_relids, true,
- false);
+ get_ecmember_indexes_strict_iterator(&it, root, cur_ec,
+ rinfo->clause_relids, true,
+ false, true);
match = false;
- i = -1;
- while ((i = bms_next_member(matching_ems, i)) >= 0)
+ while ((coal_em = get_next_matching_member_strict(root, &it)) != NULL)
{
- coal_em = list_nth_node(EquivalenceMember, root->eq_members, i);
Assert(!coal_em->em_is_child); /* no children yet */
if (IsA(coal_em->em_expr, CoalesceExpr))
{
@@ -2437,7 +2445,7 @@ reconsider_full_join_clause(PlannerInfo *root, RestrictInfo *rinfo)
if (equal(leftvar, cfirst) && equal(rightvar, csecond))
{
- coal_idx = i;
+ coal_idx = it.position;
match = true;
break;
}
@@ -2766,8 +2774,9 @@ add_child_rel_equivalences(PlannerInfo *root,
while ((i = bms_next_member(parent_rel->eclass_indexes, i)) >= 0)
{
EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
- Bitmapset *matching_ems;
- int j;
+ EquivalenceMember *cur_em;
+ EquivalenceMemberIterator it;
+ int final_member;
/*
* If this EC contains a volatile expression, then generating child
@@ -2784,13 +2793,18 @@ add_child_rel_equivalences(PlannerInfo *root,
* Looping over matching_ems means we only loop over existing members,
* not any newly added ones.
*/
- matching_ems = get_ecmember_indexes(root, cur_ec, top_parent_relids, false, false);
+ get_ecmember_indexes_iterator(&it, root, cur_ec, top_parent_relids, false, false, false);
- j = -1;
- while ((j = bms_next_member(matching_ems, j)) >= 0)
- {
- EquivalenceMember *cur_em = list_nth_node(EquivalenceMember, root->eq_members, j);
+ /*
+ * TODO: To skip newly added EMs, we get final member's index.
+ * However, touching inside of EquivalenceMemberIterator is not ideal
+ * solution.
+ */
+ final_member = bms_prev_member(cur_ec->ec_member_indexes, -1);
+ while ((cur_em = get_next_matching_member(root, &it)) != NULL
+ && it.position <= final_member)
+ {
Assert(!cur_em->em_is_const);
Assert(!cur_em->em_is_child);
Assert(bms_overlap(cur_em->em_relids, top_parent_relids));
@@ -2893,8 +2907,9 @@ add_child_join_rel_equivalences(PlannerInfo *root,
while ((i = bms_next_member(matching_ecs, i)) >= 0)
{
EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
- Bitmapset *matching_ems;
- int j;
+ EquivalenceMember *cur_em;
+ EquivalenceMemberIterator it;
+ int final_member;
/*
* If this EC contains a volatile expression, then generating child
@@ -2911,13 +2926,18 @@ add_child_join_rel_equivalences(PlannerInfo *root,
* Looping over matching_ems means we only loop over existing members,
* not any newly added ones.
*/
- matching_ems = get_ecmember_indexes(root, cur_ec, top_parent_relids, false, false);
+ get_ecmember_indexes_iterator(&it, root, cur_ec, top_parent_relids, false, false, false);
- j = -1;
- while ((j = bms_next_member(matching_ems, j)) >= 0)
- {
- EquivalenceMember *cur_em = list_nth_node(EquivalenceMember, root->eq_members, j);
+ /*
+ * TODO: To skip newly added EMs, we get final member's index.
+ * However, touching inside of EquivalenceMemberIterator is not ideal
+ * solution.
+ */
+ final_member = bms_prev_member(cur_ec->ec_member_indexes, -1);
+ while ((cur_em = get_next_matching_member(root, &it)) != NULL
+ && it.position <= final_member)
+ {
Assert(!cur_em->em_is_const);
Assert(!cur_em->em_is_child);
Assert(bms_overlap(cur_em->em_relids, top_parent_relids));
@@ -3038,7 +3058,7 @@ generate_implied_equalities_for_column(PlannerInfo *root,
{
EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
EquivalenceMember *cur_em;
- Bitmapset *matching_ems;
+ EquivalenceMemberIterator it;
int j;
/* Sanity check eclass_indexes only contain ECs for rel */
@@ -3062,13 +3082,9 @@ generate_implied_equalities_for_column(PlannerInfo *root,
* corner cases, so for now we live with just reporting the first
* match. See also get_eclass_for_sort_expr.)
*/
- matching_ems = get_ecmember_indexes(root, cur_ec, rel->relids, true, false);
- cur_em = NULL;
- j = -1;
- while ((j = bms_next_member(matching_ems, j)) >= 0)
+ get_ecmember_indexes_iterator(&it, root, cur_ec, rel->relids, true, false, true);
+ while ((cur_em = get_next_matching_member(root, &it)) != NULL)
{
- cur_em = list_nth_node(EquivalenceMember, root->eq_members, j);
-
if (bms_equal(cur_em->em_relids, rel->relids) &&
callback(root, rel, cur_ec, cur_em, callback_arg))
break;
@@ -3477,6 +3493,51 @@ get_ecmember_indexes(PlannerInfo *root, EquivalenceClass *ec, Relids relids,
return matching_ems;
}
+/*
+ * get_ecmember_indexes_iterator
+ * Initializes an EquivalenceMemberIterator for the given arguments so
+ * that the iterator enumerates the EquivalenceMembers obtained by
+ * get_ecmember_indexes().
+ * If the caller_needs_recheck is true, the EquivalenceMembers to be
+ * iterated may have false positives, so the caller must check the
+ * desired condition.
+ */
+void
+get_ecmember_indexes_iterator(EquivalenceMemberIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool with_children,
+ bool with_norel_members,
+ bool caller_needs_recheck)
+{
+ it->relids = relids;
+ it->position = -1;
+
+ if (root->simple_rel_array_size > EC_MEMBER_ITERATOR_THRESHOLD)
+ {
+ /* We use index */
+ it->check_on_iterate = false;
+ it->index = get_ecmember_indexes(root, ec, relids,
+ with_children,
+ with_norel_members);
+ }
+ else
+ {
+ Bitmapset *index;
+
+ /* We don't use index, perform linear search instead */
+ it->check_on_iterate = !caller_needs_recheck;
+
+ index =
+ with_children ? ec->ec_member_indexes : ec->ec_nonchild_indexes;
+ if (!with_norel_members)
+ index = bms_difference(index, ec->ec_norel_indexes);
+
+ it->index = index;
+ }
+}
+
/*
* get_ecmember_indexes_strict
* Returns a Bitmapset with indexes into root->eq_members for all
@@ -3524,6 +3585,51 @@ get_ecmember_indexes_strict(PlannerInfo *root, EquivalenceClass *ec,
return matching_ems;
}
+/*
+ * get_ecmember_indexes_strict_iterator
+ * Initializes an EquivalenceMemberIterator for the given arguments so
+ * that the iterator enumerates the EquivalenceMembers obtained by
+ * get_ecmember_indexes_strict().
+ * If the caller_needs_recheck is true, the EquivalenceMembers to be
+ * iterated may have false positives, so the caller must check the
+ * desired condition.
+ */
+void
+get_ecmember_indexes_strict_iterator(EquivalenceMemberStrictIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool with_children,
+ bool with_norel_members,
+ bool caller_needs_recheck)
+{
+ it->relids = relids;
+ it->position = -1;
+
+ if (root->simple_rel_array_size > EC_MEMBER_ITERATOR_THRESHOLD)
+ {
+ /* We use index */
+ it->check_on_iterate = false;
+ it->index = get_ecmember_indexes_strict(root, ec, relids,
+ with_children,
+ with_norel_members);
+ }
+ else
+ {
+ Bitmapset *index;
+
+ /* We don't use index, perform linear search instead */
+ it->check_on_iterate = !caller_needs_recheck;
+
+ index =
+ with_children ? ec->ec_member_indexes : ec->ec_nonchild_indexes;
+ if (!with_norel_members)
+ index = bms_difference(index, ec->ec_norel_indexes);
+
+ it->index = index;
+ }
+}
+
/*
* get_ec_source_indexes
* Returns a Bitmapset with indexes into root->eq_sources for all
@@ -3569,6 +3675,40 @@ get_ec_source_indexes(PlannerInfo *root, EquivalenceClass *ec, Relids relids)
return matching_es;
}
+/*
+ * get_ec_source_indexes_iterator
+ * Initializes an RestrictInfoIterator for the given arguments so
+ * that the iterator enumerates the RestrictInfos obtained by
+ * get_ec_source_indexes().
+ * If the caller_needs_recheck is true, the RestrictInfos to be
+ * iterated may have false positives, so the caller must check the
+ * desired condition.
+ */
+void
+get_ec_source_indexes_iterator(RestrictInfoIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool caller_needs_recheck)
+{
+ it->relids = relids;
+ it->position = -1;
+ it->members = root->eq_sources;
+
+ if (root->simple_rel_array_size > EC_MEMBER_ITERATOR_THRESHOLD)
+ {
+ /* We use index */
+ it->check_on_iterate = false;
+ it->indexes = get_ec_source_indexes(root, ec, relids);
+ }
+ else
+ {
+ /* We don't use index, perform linear search instead */
+ it->check_on_iterate = !caller_needs_recheck;
+ it->indexes = ec->ec_source_indexes;
+ }
+}
+
/*
* get_ec_source_indexes_strict
* Returns a Bitmapset with indexes into root->eq_sources for all
@@ -3614,6 +3754,40 @@ get_ec_source_indexes_strict(PlannerInfo *root, EquivalenceClass *ec, Relids rel
return matching_es;
}
+/*
+ * get_ec_source_indexes_strict_iterator
+ * Initializes an RestrictInfoIterator for the given arguments so
+ * that the iterator enumerates the RestrictInfos obtained by
+ * get_ec_source_indexes_strict().
+ * If the caller_needs_recheck is true, the RestrictInfos to be
+ * iterated may have false positives, so the caller must check the
+ * desired condition.
+ */
+void
+get_ec_source_indexes_strict_iterator(RestrictInfoStrictIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool caller_needs_recheck)
+{
+ it->relids = relids;
+ it->position = -1;
+ it->members = root->eq_sources;
+
+ if (root->simple_rel_array_size > EC_MEMBER_ITERATOR_THRESHOLD)
+ {
+ /* We use index */
+ it->check_on_iterate = false;
+ it->indexes = get_ec_source_indexes_strict(root, ec, relids);
+ }
+ else
+ {
+ /* We don't use index, perform linear search instead */
+ it->check_on_iterate = !caller_needs_recheck;
+ it->indexes = ec->ec_source_indexes;
+ }
+}
+
/*
* get_ec_derive_indexes
* Returns a Bitmapset with indexes into root->eq_derives for all
@@ -3659,6 +3833,40 @@ get_ec_derive_indexes(PlannerInfo *root, EquivalenceClass *ec, Relids relids)
return matching_eds;
}
+/*
+ * get_ec_derive_indexes_iterator
+ * Initializes an RestrictInfoIterator for the given arguments so
+ * that the iterator enumerates the RestrictInfos obtained by
+ * get_ec_derive_indexes().
+ * If the caller_needs_recheck is true, the RestrictInfos to be
+ * iterated may have false positives, so the caller must check the
+ * desired condition.
+ */
+void
+get_ec_derive_indexes_iterator(RestrictInfoIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool caller_needs_recheck)
+{
+ it->relids = relids;
+ it->position = -1;
+ it->members = root->eq_derives;
+
+ if (root->simple_rel_array_size > EC_MEMBER_ITERATOR_THRESHOLD)
+ {
+ /* We use index */
+ it->check_on_iterate = false;
+ it->indexes = get_ec_derive_indexes(root, ec, relids);
+ }
+ else
+ {
+ /* We don't use index, perform linear search instead */
+ it->check_on_iterate = !caller_needs_recheck;
+ it->indexes = ec->ec_derive_indexes;
+ }
+}
+
/*
* get_ec_derive_indexes_strict
* Returns a Bitmapset with indexes into root->eq_derives for all
@@ -3703,3 +3911,37 @@ get_ec_derive_indexes_strict(PlannerInfo *root, EquivalenceClass *ec, Relids rel
return matching_eds;
}
+
+/*
+ * get_ec_derive_indexes_strict_iterator
+ * Initializes an RestrictInfoIterator for the given arguments so
+ * that the iterator enumerates the RestrictInfos obtained by
+ * get_ec_derive_indexes_strict().
+ * If the caller_needs_recheck is true, the RestrictInfos to be
+ * iterated may have false positives, so the caller must check the
+ * desired condition.
+ */
+void
+get_ec_derive_indexes_strict_iterator(RestrictInfoStrictIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool caller_needs_recheck)
+{
+ it->relids = relids;
+ it->position = -1;
+ it->members = root->eq_derives;
+
+ if (root->simple_rel_array_size > EC_MEMBER_ITERATOR_THRESHOLD)
+ {
+ /* We use index */
+ it->check_on_iterate = false;
+ it->indexes = get_ec_derive_indexes_strict(root, ec, relids);
+ }
+ else
+ {
+ /* We don't use index, perform linear search instead */
+ it->check_on_iterate = !caller_needs_recheck;
+ it->indexes = ec->ec_derive_indexes;
+ }
+}
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index bf6389fee4..64306990fa 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -1378,6 +1378,38 @@ typedef struct EquivalenceMember
Oid em_datatype; /* the "nominal type" used by the opfamily */
} EquivalenceMember;
+typedef struct EquivalenceMemberIterator
+{
+ /* Do we have to check the condition on iterate? */
+ bool check_on_iterate;
+
+ /* Last found index of the Bitmapset 'index' or -1 */
+ int position;
+
+ /* Relids for checking the condition */
+ Relids relids;
+
+ /* Indexes of the EquivalenceMembers to be iterated */
+ Bitmapset *index;
+} EquivalenceMemberIterator;
+
+typedef struct EquivalenceMemberStrictIterator
+{
+ /* Do we have to check the condition on iterate? */
+ bool check_on_iterate;
+
+ /* Last found index of the Bitmapset 'index' or -1 */
+ int position;
+
+ /* Relids for checking the condition */
+ Relids relids;
+
+ /* Indexes of the EquivalenceMembers to be iterated */
+ Bitmapset *index;
+} EquivalenceMemberStrictIterator;
+
+#define EC_MEMBER_ITERATOR_THRESHOLD 32
+
/*
* PathKeys
*
@@ -2607,6 +2639,42 @@ typedef struct RestrictInfo
((rinfo)->is_pushed_down || \
!bms_is_subset((rinfo)->required_relids, joinrelids))
+typedef struct RestrictInfoIterator
+{
+ /* Do we have to check the condition on iterate? */
+ bool check_on_iterate;
+
+ /* Last found index of the Bitmapset 'index' or -1 */
+ int position;
+
+ /* Relids for checking the condition */
+ Relids relids;
+
+ /* Indexes of the RestrictInfos to be iterated */
+ Bitmapset *indexes;
+
+ /* RestrictInfos that the 'indexes' point to */
+ List *members;
+} RestrictInfoIterator;
+
+typedef struct RestrictInfoStrictIterator
+{
+ /* Do we have to check the condition on iterate? */
+ bool check_on_iterate;
+
+ /* Last found index of the Bitmapset 'index' or -1 */
+ int position;
+
+ /* Relids for checking the condition */
+ Relids relids;
+
+ /* Indexes of the RestrictInfos to be iterated */
+ Bitmapset *indexes;
+
+ /* RestrictInfos that the 'indexes' point to */
+ List *members;
+} RestrictInfoStrictIterator;
+
/*
* Since mergejoinscansel() is a relatively expensive function, and would
* otherwise be invoked many times while planning a large join tree,
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index f6835f80f5..d78dadb074 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -194,23 +194,169 @@ extern Bitmapset *get_ecmember_indexes(PlannerInfo *root,
Relids relids,
bool with_children,
bool with_norel_members);
+extern void get_ecmember_indexes_iterator(EquivalenceMemberIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool with_children,
+ bool with_norel_members,
+ bool caller_needs_recheck);
extern Bitmapset *get_ecmember_indexes_strict(PlannerInfo *root,
EquivalenceClass *ec,
Relids relids,
bool with_children,
bool with_norel_members);
+extern void get_ecmember_indexes_strict_iterator(EquivalenceMemberStrictIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool with_children,
+ bool with_norel_members,
+ bool caller_needs_recheck);
extern Bitmapset *get_ec_source_indexes(PlannerInfo *root,
EquivalenceClass *ec,
Relids relids);
+extern void get_ec_source_indexes_iterator(RestrictInfoIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool caller_needs_recheck);
extern Bitmapset *get_ec_source_indexes_strict(PlannerInfo *root,
EquivalenceClass *ec,
Relids relids);
+extern void get_ec_source_indexes_strict_iterator(RestrictInfoStrictIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool caller_needs_recheck);
extern Bitmapset *get_ec_derive_indexes(PlannerInfo *root,
EquivalenceClass *ec,
Relids relids);
+extern void get_ec_derive_indexes_iterator(RestrictInfoIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool caller_needs_recheck);
extern Bitmapset *get_ec_derive_indexes_strict(PlannerInfo *root,
- EquivalenceClass *ec,
- Relids relids);
+ EquivalenceClass *ec,
+ Relids relids);
+extern void get_ec_derive_indexes_strict_iterator(RestrictInfoStrictIterator *it,
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids,
+ bool caller_needs_recheck);
+
+/*
+ * Returns the next EquivalenceMember. If the iteration was done, returns NULL.
+ */
+static inline EquivalenceMember *
+get_next_matching_member(PlannerInfo *root, EquivalenceMemberIterator *it)
+{
+ if (!it->check_on_iterate)
+ {
+ if ((it->position = bms_next_member(it->index, it->position)) >= 0)
+ return list_nth_node(EquivalenceMember, root->eq_members, it->position);
+ }
+ else
+ {
+ while ((it->position = bms_next_member(it->index, it->position)) >= 0)
+ {
+ EquivalenceMember *member =
+ list_nth_node(EquivalenceMember, root->eq_members, it->position);
+
+ if (bms_overlap(it->relids, member->em_relids))
+ {
+ return member;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Returns the next EquivalenceMember. If the iteration was done, returns NULL.
+ */
+static inline EquivalenceMember *
+get_next_matching_member_strict(PlannerInfo *root, EquivalenceMemberStrictIterator *it)
+{
+ if (!it->check_on_iterate)
+ {
+ if ((it->position = bms_next_member(it->index, it->position)) >= 0)
+ return list_nth_node(EquivalenceMember, root->eq_members, it->position);
+ }
+ else
+ {
+ while ((it->position = bms_next_member(it->index, it->position)) >= 0)
+ {
+ EquivalenceMember *member =
+ list_nth_node(EquivalenceMember, root->eq_members, it->position);
+
+ if (bms_is_subset(it->relids, member->em_relids))
+ {
+ return member;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Returns the next RestrictInfo. If the iteration was done, returns NULL.
+ */
+static inline RestrictInfo *
+get_next_matching_rinfo(PlannerInfo *root, RestrictInfoIterator *it)
+{
+ if (!it->check_on_iterate)
+ {
+ if ((it->position = bms_next_member(it->indexes, it->position)) >= 0)
+ return list_nth_node(RestrictInfo, it->members, it->position);
+ }
+ else
+ {
+ while ((it->position = bms_next_member(it->indexes, it->position)) >= 0)
+ {
+ RestrictInfo *member =
+ list_nth_node(RestrictInfo, it->members, it->position);
+
+ if (bms_overlap(it->relids, member->clause_relids))
+ {
+ return member;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ * Returns the next RestrictInfo. If the iteration was done, returns NULL.
+ */
+static inline RestrictInfo *
+get_next_matching_rinfo_strict(PlannerInfo *root, RestrictInfoStrictIterator *it)
+{
+ if (!it->check_on_iterate)
+ {
+ if ((it->position = bms_next_member(it->indexes, it->position)) >= 0)
+ return list_nth_node(RestrictInfo, it->members, it->position);
+ }
+ else
+ {
+ while ((it->position = bms_next_member(it->indexes, it->position)) >= 0)
+ {
+ RestrictInfo *member =
+ list_nth_node(RestrictInfo, it->members, it->position);
+
+ if (bms_is_subset(it->relids, member->clause_relids))
+ {
+ return member;
+ }
+ }
+ }
+
+ return NULL;
+}
/*
* pathkeys.c
--
2.35.3.windows.1