diff-v30-v31.txt
text/plain
Filename: diff-v30-v31.txt
Type: text/plain
Part: 0
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 7444622a527..d6a0dd524c4 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -7829,35 +7829,12 @@ EquivalenceMember *
find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
{
PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
- Relids top_parent_rel_relids;
EquivalenceChildMemberIterator it;
EquivalenceMember *em;
- /*
- * First, we translate the given Relids to their top-level parents. This
- * is required because an EquivalenceClass contains only parent
- * EquivalenceMembers, and we have to translate top-level ones to get
- * child members. We can skip such translations if we now see top-level
- * ones, i.e., when top_parent_rel is NULL. See the
- * find_relids_top_parents()'s definition for more details.
- */
- top_parent_rel_relids = find_relids_top_parents(root, rel->relids);
-
- /*
- * If we need to see child EquivalenceMembers, we access them via
- * EquivalenceChildMemberIterator during the iteration.
- */
- setup_eclass_child_member_iterator(&it, ec);
+ setup_eclass_child_member_iterator(&it, root, ec, rel->relids);
while ((em = eclass_child_member_iterator_next(&it)))
{
- /*
- * If child EquivalenceMembers may match the request, we add and
- * iterate over them by calling iterate_child_rel_equivalences().
- */
- if (top_parent_rel_relids != NULL && !em->em_is_child &&
- bms_is_subset(em->em_relids, top_parent_rel_relids))
- iterate_child_rel_equivalences(&it, root, ec, em, rel->relids);
-
/*
* Note we require !bms_is_empty, else we'd accept constant
* expressions which are not suitable for the purpose.
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index 0395cee9a7c..173449080f0 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -79,7 +79,6 @@ static JoinDomain *find_join_domain(PlannerInfo *root, Relids relids);
static void add_transformed_child_version(EquivalenceChildMemberIterator *it,
PlannerInfo *root,
EquivalenceClass *ec,
- EquivalenceMember *parent_em,
RelOptInfo *child_rel);
static Bitmapset *get_eclass_indexes_for_relids(PlannerInfo *root,
Relids relids);
@@ -551,8 +550,7 @@ make_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids,
em->em_datatype = datatype;
em->em_jdomain = jdomain;
em->em_parent = parent;
- em->em_child_relids = NULL;
- em->em_child_joinrel_relids = NULL;
+ em->em_ec = ec;
if (bms_is_empty(relids))
{
@@ -581,9 +579,10 @@ make_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids,
* add_parent_eq_member - build a new parent EquivalenceMember and add it to an EC
*
* Note: We don't have a function to add a child member like
- * add_child_eq_member() because how to do it depends on the relations they are
- * translated from. See add_child_rel_equivalences() and
- * add_child_join_rel_equivalences() to see how to add child members.
+ * add_child_eq_member() because how to do it depends on the relations they
+ * are translated from. See add_child_rel_equivalences(),
+ * add_child_join_rel_equivalences() and add_setop_child_rel_equivalences()
+ * to see how to add child members.
*/
static EquivalenceMember *
add_parent_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids,
@@ -805,17 +804,6 @@ get_eclass_for_sort_expr(PlannerInfo *root,
EquivalenceMember *newem;
ListCell *lc1;
MemoryContext oldcontext;
- Relids top_parent_rel;
-
- /*
- * First, we translate the given Relids to their top-level parents. This
- * is required because an EquivalenceClass contains only parent
- * EquivalenceMembers, and we have to translate top-level ones to get
- * child members. We can skip such translations if we now see top-level
- * ones, i.e., when top_parent_rel is NULL. See the
- * find_relids_top_parents()'s definition for more details.
- */
- top_parent_rel = find_relids_top_parents(root, rel);
/*
* Ensure the expression exposes the correct type and collation.
@@ -850,28 +838,15 @@ get_eclass_for_sort_expr(PlannerInfo *root,
if (!equal(opfamilies, cur_ec->ec_opfamilies))
continue;
- /*
- * If we need to see child EquivalenceMembers, we access them via
- * EquivalenceChildMemberIterator during the iteration.
- */
- setup_eclass_child_member_iterator(&it, cur_ec);
+ setup_eclass_child_member_iterator(&it, root, cur_ec, rel);
while ((cur_em = eclass_child_member_iterator_next(&it)) != NULL)
{
/*
- * If child EquivalenceMembers may match the request, we add and
- * iterate over them by calling iterate_child_rel_equivalences().
- */
- if (top_parent_rel != NULL && !cur_em->em_is_child &&
- bms_equal(cur_em->em_relids, top_parent_rel))
- iterate_child_rel_equivalences(&it, root, cur_ec, cur_em, rel);
-
- /*
- * Ignore child members unless they match the request. If this
- * EquivalenceMember is a child, i.e., translated above, it should
- * match the request. We cannot assert this if a request is
- * bms_is_subset().
+ * Ignore child members unless they match the request.
*/
- Assert(!cur_em->em_is_child || bms_equal(cur_em->em_relids, rel));
+ if (cur_em->em_is_child &&
+ !bms_equal(cur_em->em_relids, rel))
+ continue;
/*
* Match constants only within the same JoinDomain (see
@@ -996,29 +971,14 @@ find_ec_member_matching_expr(PlannerInfo *root, EquivalenceClass *ec,
Expr *expr,
Relids relids)
{
- Relids top_parent_relids;
EquivalenceChildMemberIterator it;
EquivalenceMember *em;
- /*
- * First, we translate the given Relids to their top-level parents. This
- * is required because an EquivalenceClass contains only parent
- * EquivalenceMembers, and we have to translate top-level ones to get
- * child members. We can skip such translations if we now see top-level
- * ones, i.e., when top_parent_rel is NULL. See the
- * find_relids_top_parents()'s definition for more details.
- */
- top_parent_relids = find_relids_top_parents(root, relids);
-
/* We ignore binary-compatible relabeling on both ends */
while (expr && IsA(expr, RelabelType))
expr = ((RelabelType *) expr)->arg;
- /*
- * If we need to see child EquivalenceMembers, we access them via
- * EquivalenceChildMemberIterator during the iteration.
- */
- setup_eclass_child_member_iterator(&it, ec);
+ setup_eclass_child_member_iterator(&it, root, ec, relids);
while ((em = eclass_child_member_iterator_next(&it)) != NULL)
{
Expr *emexpr;
@@ -1030,14 +990,6 @@ find_ec_member_matching_expr(PlannerInfo *root, EquivalenceClass *ec,
if (em->em_is_const)
continue;
- /*
- * If child EquivalenceMembers may match the request, we add and
- * iterate over them by calling iterate_child_rel_equivalences().
- */
- if (top_parent_relids != NULL && !em->em_is_child &&
- bms_is_subset(em->em_relids, top_parent_relids))
- iterate_child_rel_equivalences(&it, root, ec, em, relids);
-
/*
* Ignore child members unless they belong to the requested rel.
*/
@@ -1098,7 +1050,6 @@ find_computable_ec_member(PlannerInfo *root,
bool require_parallel_safe)
{
List *exprvars;
- Relids top_parent_relids;
EquivalenceChildMemberIterator it;
EquivalenceMember *em;
@@ -1113,21 +1064,7 @@ find_computable_ec_member(PlannerInfo *root,
PVC_INCLUDE_WINDOWFUNCS |
PVC_INCLUDE_PLACEHOLDERS);
- /*
- * First, we translate the given Relids to their top-level parents. This
- * is required because an EquivalenceClass contains only parent
- * EquivalenceMembers, and we have to translate top-level ones to get
- * child members. We can skip such translations if we now see top-level
- * ones, i.e., when top_parent_rel is NULL. See the
- * find_relids_top_parents()'s definition for more details.
- */
- top_parent_relids = find_relids_top_parents(root, relids);
-
- /*
- * If we need to see child EquivalenceMembers, we access them via
- * EquivalenceChildMemberIterator during the iteration.
- */
- setup_eclass_child_member_iterator(&it, ec);
+ setup_eclass_child_member_iterator(&it, root, ec, relids);
while ((em = eclass_child_member_iterator_next(&it)) != NULL)
{
List *emvars;
@@ -1140,14 +1077,6 @@ find_computable_ec_member(PlannerInfo *root,
if (em->em_is_const)
continue;
- /*
- * If child EquivalenceMembers may match the request, we add and
- * iterate over them by calling iterate_child_rel_equivalences().
- */
- if (top_parent_relids != NULL && !em->em_is_child &&
- bms_is_subset(em->em_relids, top_parent_relids))
- iterate_child_rel_equivalences(&it, root, ec, em, relids);
-
/*
* Ignore child members unless they belong to the requested rel.
*/
@@ -1848,20 +1777,9 @@ generate_join_implied_equalities_normal(PlannerInfo *root,
List *new_members = NIL;
List *outer_members = NIL;
List *inner_members = NIL;
- Relids top_parent_join_relids;
EquivalenceChildMemberIterator it;
EquivalenceMember *cur_em;
- /*
- * First, we translate the given Relids to their top-level parents. This
- * is required because an EquivalenceClass contains only parent
- * EquivalenceMembers, and we have to translate top-level ones to get
- * child members. We can skip such translations if we now see top-level
- * ones, i.e., when top_parent_rel is NULL. See the
- * find_relids_top_parents()'s definition for more details.
- */
- top_parent_join_relids = find_relids_top_parents(root, join_relids);
-
/*
* First, scan the EC to identify member values that are computable at the
* outer rel, at the inner rel, or at this relation but not in either
@@ -1870,21 +1788,10 @@ generate_join_implied_equalities_normal(PlannerInfo *root,
* enforce that any newly computable members are all equal to each other
* 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.
- *
- * If we need to see child EquivalenceMembers, we access them via
- * EquivalenceChildMemberIterator during the iteration.
*/
- setup_eclass_child_member_iterator(&it, ec);
+ setup_eclass_child_member_iterator(&it, root, ec, join_relids);
while ((cur_em = eclass_child_member_iterator_next(&it)) != NULL)
{
- /*
- * If child EquivalenceMembers may match the request, we add and
- * iterate over them by calling iterate_child_rel_equivalences().
- */
- if (top_parent_join_relids != NULL && !cur_em->em_is_child &&
- bms_is_subset(cur_em->em_relids, top_parent_join_relids))
- iterate_child_rel_equivalences(&it, root, ec, cur_em, join_relids);
-
/*
* We don't need to check explicitly for child EC members. This test
* against join_relids will cause them to be ignored except when
@@ -3058,8 +2965,8 @@ add_child_rel_equivalences(PlannerInfo *root,
* combinations of children. (But add_child_join_rel_equivalences
* may add targeted combinations for partitionwise-join purposes.)
*/
- /* Child members should not exist in ec_members */
- Assert(!cur_em->em_is_child);
+ Assert(!cur_em->em_is_child); /* Child members should not exist
+ * in ec_members */
/*
* Consider only members that reference and can be computed at
@@ -3111,15 +3018,6 @@ add_child_rel_equivalences(PlannerInfo *root,
child_rel->eclass_child_members = lappend(child_rel->eclass_child_members,
child_em);
- /*
- * We save the knowledge that 'child_em' can be translated
- * using 'child_rel'. This knowledge is useful for
- * iterate_child_rel_equivalences() to find child members from
- * the given Relids.
- */
- cur_em->em_child_relids = bms_add_member(cur_em->em_child_relids,
- child_rel->relid);
-
/* Record this EC index for the child rel */
child_rel->eclass_indexes = bms_add_member(child_rel->eclass_indexes, i);
}
@@ -3192,8 +3090,8 @@ add_child_join_rel_equivalences(PlannerInfo *root,
* We consider only original EC members here, not
* already-transformed child members.
*/
- /* Child members should not exist in ec_members */
- Assert(!cur_em->em_is_child);
+ Assert(!cur_em->em_is_child); /* Child members should not exist
+ * in ec_members */
/*
* We may ignore expressions that reference a single baserel,
@@ -3246,16 +3144,6 @@ add_child_join_rel_equivalences(PlannerInfo *root,
child_joinrel->eclass_child_members =
lappend(child_joinrel->eclass_child_members, child_em);
- /*
- * We save the knowledge that 'child_em' can be translated
- * using 'child_joinrel'. This knowledge is useful for
- * iterate_child_rel_equivalences() to find child members from
- * the given Relids.
- */
- cur_em->em_child_joinrel_relids =
- bms_add_member(cur_em->em_child_joinrel_relids,
- child_joinrel->join_rel_list_index);
-
/*
* Update the corresponding inverted indexes.
*/
@@ -3271,7 +3159,7 @@ add_child_join_rel_equivalences(PlannerInfo *root,
* that have only such parent relations as em_relids are
* already present in the ec_members, and so cannot be
* candidates for additional iteration by
- * iterate_child_rel_equivalences(). Since the function
+ * EquivalenceChildMemberIterator. Since the iterator
* needs EquivalenceMembers whose em_relids has child
* relations, skipping the update of this inverted index
* allows for faster iteration.
@@ -3341,15 +3229,6 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel,
child_rel->eclass_child_members =
lappend(child_rel->eclass_child_members, child_em);
- /*
- * We save the knowledge that 'child_em' can be translated using
- * 'child_rel'. This knowledge is useful for
- * iterate_child_rel_equivalences() to find child members from the
- * given Relids.
- */
- parent_em->em_child_relids =
- bms_add_member(parent_em->em_child_relids, child_rel->relid);
-
/*
* Make an UNION parent-child relationship between parent_em and
* child_rel->relid. We record this relationship in
@@ -3399,40 +3278,125 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel,
*/
void
setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
- EquivalenceClass *ec)
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids)
{
+ Bitmapset *matching_indexes;
+ int i;
+
+ /*
+ * Initialize the iterator.
+ */
it->index = -1;
it->modified = false;
it->ec_members = ec->ec_members;
-}
-/*
- * eclass_child_member_iterator_next
- * Get a next EquivalenceMember from an EquivalenceChildMemberIterator 'it'
- * that was setup by setup_eclass_child_member_iterator(). NULL is returned
- * if there are no members left.
- */
-EquivalenceMember *
-eclass_child_member_iterator_next(EquivalenceChildMemberIterator *it)
-{
- if (++it->index < list_length(it->ec_members))
- return list_nth_node(EquivalenceMember, it->ec_members, it->index);
- return NULL;
-}
+ /*
+ * If there are no child relations, there is nothing to do. This
+ * effectively avoids regression for non-partitioned cases.
+ */
+ if (root->top_parent_relid_array == NULL)
+ return;
-/*
- * dispose_eclass_child_member_iterator
- * Free any memory allocated by the iterator.
- */
-void
-dispose_eclass_child_member_iterator(EquivalenceChildMemberIterator *it)
-{
/*
- * XXX Should we use list_free()? I decided to use this style to take
- * advantage of speculative execution.
+ * EquivalenceClass->ec_members has only parent EquivalenceMembers. Child
+ * members are translated using child RelOptInfos and stored in them. This
+ * is done in add_child_rel_equivalences(),
+ * add_child_join_rel_equivalences(), and
+ * add_setop_child_rel_equivalences(). To retrieve child
+ * EquivalenceMembers of some parent, we need to know which RelOptInfos
+ * have such child members. We can know this information using indexes
+ * like EquivalenceClassIndexes->joinrel_indexes.
+ *
+ * We use an inverted index mechanism to quickly iterate over the members
+ * whose em_relids is a subset of the given 'child_relids'. The inverted
+ * indexes store RelOptInfo indices that have EquivalenceMembers
+ * mentioning them. Taking the union of these indexes allows to find which
+ * RelOptInfos have the EquivalenceMember we are looking for. With this
+ * method, the em_relids of the newly iterated ones overlap the given
+ * 'child_relids', but may not be subsets, so the caller must check that
+ * they satisfy the desired condition.
+ *
+ * The above comments are about joinrels, and for simple rels, this
+ * mechanism is simpler. It is sufficient to simply add the child
+ * EquivalenceMembers of RelOptInfo to the iterator.
+ *
+ * We need to perform these steps for each of the two types of relations.
*/
- if (unlikely(it->modified))
- pfree(it->ec_members);
+
+ /*
+ * Iterate over the given relids, adding child members for simple rels and
+ * taking union indexes for join rels.
+ */
+ i = -1;
+ matching_indexes = NULL;
+ while ((i = bms_next_member(relids, i)) >= 0)
+ {
+ RelOptInfo *child_rel;
+ EquivalenceClassIndexes *indexes;
+
+ /*
+ * If this relation is a parent, we don't have to do anything.
+ */
+ if (root->top_parent_relid_array[i] == -1)
+ continue;
+
+ /*
+ * Add child members that mention this relation to the iterator.
+ */
+ child_rel = root->simple_rel_array[i];
+ if (child_rel != NULL)
+ add_transformed_child_version(it, root, ec, child_rel);
+
+ /*
+ * Union indexes for join rels.
+ */
+ indexes = &root->eclass_indexes_array[i];
+ matching_indexes =
+ bms_add_members(matching_indexes, indexes->joinrel_indexes);
+ }
+
+ /*
+ * For join rels, add child members using 'matching_indexes'.
+ */
+ i = -1;
+ while ((i = bms_next_member(matching_indexes, i)) >= 0)
+ {
+ RelOptInfo *child_joinrel =
+ list_nth_node(RelOptInfo, root->join_rel_list, i);
+
+ Assert(child_joinrel != NULL);
+
+ /*
+ * If this joinrel's Relids is not a subset of the given one, then the
+ * child EquivalenceMembers it holds should never be a subset either.
+ */
+ if (bms_is_subset(child_joinrel->relids, relids))
+ add_transformed_child_version(it, root, ec, child_joinrel);
+#ifdef USE_ASSERT_CHECKING
+ else
+ {
+ /*
+ * Verify that the above comment is correct.
+ *
+ * NOTE: We may remove this assertion after the beta process.
+ */
+
+ ListCell *lc;
+
+ foreach(lc, child_joinrel->eclass_child_members)
+ {
+ EquivalenceMember *child_em = lfirst_node(EquivalenceMember, lc);
+
+ if (child_em->em_ec != ec)
+ continue;
+ Assert(!bms_is_subset(child_em->em_relids, relids));
+ }
+ }
+#endif
+ }
+ bms_free(matching_indexes);
}
/*
@@ -3441,13 +3405,12 @@ dispose_eclass_child_member_iterator(EquivalenceChildMemberIterator *it)
* the iterator.
*
* This function is expected to be called only from
- * iterate_child_rel_equivalences().
+ * setup_eclass_child_member_iterator().
*/
static void
add_transformed_child_version(EquivalenceChildMemberIterator *it,
PlannerInfo *root,
EquivalenceClass *ec,
- EquivalenceMember *parent_em,
RelOptInfo *child_rel)
{
ListCell *lc;
@@ -3457,7 +3420,7 @@ add_transformed_child_version(EquivalenceChildMemberIterator *it,
EquivalenceMember *child_em = lfirst_node(EquivalenceMember, lc);
/* Skip unwanted EquivalenceMembers */
- if (child_em->em_parent != parent_em)
+ if (child_em->em_ec != ec)
continue;
/*
@@ -3476,136 +3439,32 @@ add_transformed_child_version(EquivalenceChildMemberIterator *it,
}
/*
- * iterate_child_rel_equivalences
- * Add child EquivalenceMembers whose em_relids is a subset of the given
- * 'child_relids' to the iterator. Note that this function may add false
- * positives, so callers must check that the members that this function adds
- * satisfy the desired condition.
- *
- * The transformation is done in add_transformed_child_version().
+ * eclass_child_member_iterator_next
+ * Get a next EquivalenceMember from an EquivalenceChildMemberIterator 'it'
+ * that was setup by setup_eclass_child_member_iterator(). NULL is returned
+ * if there are no members left.
*/
-void
-iterate_child_rel_equivalences(EquivalenceChildMemberIterator *it,
- PlannerInfo *root,
- EquivalenceClass *ec,
- EquivalenceMember *parent_em,
- Relids child_relids)
+EquivalenceMember *
+eclass_child_member_iterator_next(EquivalenceChildMemberIterator *it)
{
- /* The given EquivalenceMember should be parent */
- Assert(!parent_em->em_is_child);
-
- /*
- * EquivalenceClass->ec_members has only parent EquivalenceMembers. Child
- * members are translated using child RelOptInfos and stored in them. This
- * is done in add_child_rel_equivalences() and
- * add_child_join_rel_equivalences(). To retrieve child EquivalenceMembers
- * of some parent, we need to know which RelOptInfos have such child
- * members. We can know this information using indexes named
- * EquivalenceMember->em_child_relids,
- * EquivalenceMember->em_child_joinrel_relids, and
- * EquivalenceClassIndexes->joinrel_indexes.
- *
- * We use an inverted index mechanism to quickly iterate over the members
- * whose em_relids is a subset of the given 'child_relids'. The inverted
- * indexes store RelOptInfo indices that have EquivalenceMembers
- * mentioning them. Taking the union of these indexes allows to find which
- * RelOptInfos have the EquivalenceMember we are looking for. With this
- * method, the em_relids of the newly iterated ones overlap the given
- * 'child_relids', but may not be subsets, so the caller must check that
- * they satisfy the desired condition.
- *
- * The above comments are about joinrels, and for simple rels, this
- * mechanism is simpler. It is sufficient to simply add the child
- * EquivalenceMembers of RelOptInfo to the iterator.
- *
- * We need to perform these steps for each of the two types of relations.
- */
-
- /*
- * First, we translate simple rels.
- */
- if (!bms_is_empty(parent_em->em_child_relids))
- {
- Relids matching_relids;
- int i;
-
- /* Step 1: Get simple rels' Relids that have wanted EMs. */
- matching_relids = bms_intersect(parent_em->em_child_relids,
- child_relids);
-
- /* Step 2: Fetch wanted EMs. */
- i = -1;
- while ((i = bms_next_member(matching_relids, i)) >= 0)
- {
- RelOptInfo *child_rel = root->simple_rel_array[i];
-
- Assert(child_rel != NULL);
- add_transformed_child_version(it, root, ec, parent_em, child_rel);
- }
- bms_free(matching_relids);
- }
+ if (++it->index < list_length(it->ec_members))
+ return list_nth_node(EquivalenceMember, it->ec_members, it->index);
+ return NULL;
+}
+/*
+ * dispose_eclass_child_member_iterator
+ * Free any memory allocated by the iterator.
+ */
+void
+dispose_eclass_child_member_iterator(EquivalenceChildMemberIterator *it)
+{
/*
- * Next, we try to translate join rels.
+ * XXX Should we use list_free()? I decided to use this style to take
+ * advantage of speculative execution.
*/
- if (!bms_is_empty(parent_em->em_child_joinrel_relids))
- {
- Bitmapset *matching_indexes;
- int i;
-
- /* Step 1: Get join rels' indices that have wanted EMs. */
- i = -1;
- matching_indexes = NULL;
- while ((i = bms_next_member(child_relids, i)) >= 0)
- {
- EquivalenceClassIndexes *indexes = &root->eclass_indexes_array[i];
-
- matching_indexes =
- bms_add_members(matching_indexes, indexes->joinrel_indexes);
- }
- matching_indexes = bms_int_members(matching_indexes,
- parent_em->em_child_joinrel_relids);
-
- /* Step 2: Fetch wanted EMs. */
- i = -1;
- while ((i = bms_next_member(matching_indexes, i)) >= 0)
- {
- RelOptInfo *child_joinrel =
- list_nth_node(RelOptInfo, root->join_rel_list, i);
-
- Assert(child_joinrel != NULL);
-
- /*
- * If this joinrel's Relids is not a subset of the given one, then
- * the child EquivalenceMembers it holds should never be a subset
- * either.
- */
- if (bms_is_subset(child_joinrel->relids, child_relids))
- add_transformed_child_version(it, root, ec, parent_em, child_joinrel);
-#ifdef USE_ASSERT_CHECKING
- else
- {
- /*
- * Verify that the above comment is correct.
- *
- * NOTE: We may remove this assertion after the beta process.
- */
-
- ListCell *lc;
-
- foreach(lc, child_joinrel->eclass_child_members)
- {
- EquivalenceMember *child_em = lfirst_node(EquivalenceMember, lc);
-
- if (child_em->em_parent != parent_em)
- continue;
- Assert(!bms_is_subset(child_em->em_relids, child_relids));
- }
- }
-#endif
- }
- bms_free(matching_indexes);
- }
+ if (unlikely(it->modified))
+ pfree(it->ec_members);
}
@@ -3641,8 +3500,7 @@ generate_implied_equalities_for_column(PlannerInfo *root,
{
List *result = NIL;
bool is_child_rel = (rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
- Relids parent_relids,
- top_parent_rel_relids;
+ Relids parent_relids;
int i;
/* Should be OK to rely on eclass_indexes */
@@ -3651,16 +3509,6 @@ generate_implied_equalities_for_column(PlannerInfo *root,
/* Indexes are available only on base or "other" member relations. */
Assert(IS_SIMPLE_REL(rel));
- /*
- * First, we translate the given Relids to their top-level parents. This
- * is required because an EquivalenceClass contains only parent
- * EquivalenceMembers, and we have to translate top-level ones to get
- * child members. We can skip such translations if we now see top-level
- * ones, i.e., when top_parent_rel is NULL. See the
- * find_relids_top_parents()'s definition for more details.
- */
- top_parent_rel_relids = find_relids_top_parents(root, rel->relids);
-
/* If it's a child rel, we'll need to know what its parent(s) are */
if (is_child_rel)
parent_relids = find_childrel_parents(root, rel);
@@ -3694,20 +3542,10 @@ generate_implied_equalities_for_column(PlannerInfo *root,
* column gets matched to. This is annoying but it only happens in
* corner cases, so for now we live with just reporting the first
* match. See also get_eclass_for_sort_expr.)
- *
- * If we need to see child EquivalenceMembers, we access them via
- * EquivalenceChildMemberIterator during the iteration.
*/
- setup_eclass_child_member_iterator(&it, cur_ec);
+ setup_eclass_child_member_iterator(&it, root, cur_ec, rel->relids);
while ((cur_em = eclass_child_member_iterator_next(&it)) != NULL)
{
- /*
- * If child EquivalenceMembers may match the request, we add and
- * iterate over them by calling iterate_child_rel_equivalences().
- */
- if (top_parent_rel_relids != NULL && !cur_em->em_is_child &&
- bms_equal(cur_em->em_relids, top_parent_rel_relids))
- iterate_child_rel_equivalences(&it, root, cur_ec, cur_em, rel->relids);
if (bms_equal(cur_em->em_relids, rel->relids) &&
callback(root, rel, cur_ec, cur_em, callback_arg))
break;
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 7ced5e33798..d19b45a1293 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -3743,19 +3743,8 @@ match_pathkeys_to_index(PlannerInfo *root, IndexOptInfo *index, List *pathkeys,
List **orderby_clauses_p,
List **clause_columns_p)
{
- Relids top_parent_index_relids;
ListCell *lc1;
- /*
- * First, we translate the given Relids to their top-level parents. This
- * is required because an EquivalenceClass contains only parent
- * EquivalenceMembers, and we have to translate top-level ones to get
- * child members. We can skip such translations if we now see top-level
- * ones, i.e., when top_parent_rel is NULL. See the
- * find_relids_top_parents()'s definition for more details.
- */
- top_parent_index_relids = find_relids_top_parents(root, index->rel->relids);
-
*orderby_clauses_p = NIL; /* set default results */
*clause_columns_p = NIL;
@@ -3787,36 +3776,17 @@ match_pathkeys_to_index(PlannerInfo *root, IndexOptInfo *index, List *pathkeys,
* child member of more than one EC. Therefore, the same index could
* be considered to match more than one pathkey list, which is OK
* here. See also get_eclass_for_sort_expr.)
- *
- * If we need to see child EquivalenceMembers, we access them via
- * EquivalenceChildMemberIterator during the iteration.
*/
- setup_eclass_child_member_iterator(&it, pathkey->pk_eclass);
+ setup_eclass_child_member_iterator(&it, root, pathkey->pk_eclass,
+ index->rel->relids);
while ((member = eclass_child_member_iterator_next(&it)))
{
int indexcol;
- /*
- * If child EquivalenceMembers may match the request, we add and
- * iterate over them by calling iterate_child_rel_equivalences().
- */
- if (top_parent_index_relids != NULL && !member->em_is_child &&
- bms_equal(member->em_relids, top_parent_index_relids))
- iterate_child_rel_equivalences(&it, root, pathkey->pk_eclass, member,
- index->rel->relids);
-
/* No possibility of match if it references other relations */
- if (!member->em_is_child &&
- !bms_equal(member->em_relids, index->rel->relids))
+ if (!bms_equal(member->em_relids, index->rel->relids))
continue;
- /*
- * If this EquivalenceMember is a child, i.e., translated above,
- * it should match the request. We cannot assert this if a request
- * is bms_is_subset().
- */
- Assert(bms_equal(member->em_relids, index->rel->relids));
-
/*
* We allow any column of the index to match each pathkey; they
* don't have to match left-to-right as you might expect. This is
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 48517ddaf86..c8e535617b8 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -1587,48 +1587,6 @@ find_childrel_parents(PlannerInfo *root, RelOptInfo *rel)
}
-/*
- * find_relids_top_parents_slow
- * Slow path of find_relids_top_parents() macro.
- *
- * Do not call this directly; use the macro instead. See the macro comment for
- * more details.
- */
-Relids
-find_relids_top_parents_slow(PlannerInfo *root, Relids relids)
-{
- Index *top_parent_relid_array = root->top_parent_relid_array;
- Relids result;
- bool is_top_parent;
- int i;
-
- /* This function should be called in the slow path */
- Assert(top_parent_relid_array != NULL);
-
- result = NULL;
- is_top_parent = true;
- i = -1;
- while ((i = bms_next_member(relids, i)) >= 0)
- {
- int top_parent_relid = (int) top_parent_relid_array[i];
-
- if (top_parent_relid == -1)
- top_parent_relid = i; /* 'i' has no parents, so add itself */
- else if (top_parent_relid != i)
- is_top_parent = false;
- result = bms_add_member(result, top_parent_relid);
- }
-
- if (is_top_parent)
- {
- bms_free(result);
- return NULL;
- }
-
- return result;
-}
-
-
/*
* get_baserel_parampathinfo
* Get the ParamPathInfo for a parameterized path for a base relation,
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index a408051faba..8b4c8319aad 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -1527,35 +1527,32 @@ typedef struct EquivalenceMember
bool em_is_child; /* derived version for a child relation? */
Oid em_datatype; /* the "nominal type" used by the opfamily */
JoinDomain *em_jdomain; /* join domain containing the source clause */
- Relids em_child_relids; /* all relids of child rels */
- Bitmapset *em_child_joinrel_relids; /* indexes in root->join_rel_list
- * of join rel children */
/* if em_is_child is true, this links to corresponding EM for top parent */
struct EquivalenceMember *em_parent pg_node_attr(read_write_ignore);
+ EquivalenceClass *em_ec; /* EquivalenceClass which has this member */
} EquivalenceMember;
/*
* EquivalenceChildMemberIterator
*
- * EquivalenceClass has only parent EquivalenceMembers, so we need to translate
- * child members if necessary. EquivalenceChildMemberIterator provides a way to
- * iterate over translated child members during the loop in addition to all of
- * the parent EquivalenceMembers.
+ * EquivalenceClass contains only parent members. Use the
+ * EquivalenceChildMemberIterator to iterate over child members whose em_relids
+ * is a subset of the specified 'child_relids' in addition to the parent
+ * members. Note that the iterator may yield false positives, so callers must
+ * verify that each member satisfies the condition.
*
* The most common way to use this struct is as follows:
* -----
+ * PlannerInfo *root = given;
* EquivalenceClass *ec = given;
* Relids rel = given;
* EquivalenceChildMemberIterator it;
* EquivalenceMember *em;
*
- * setup_eclass_child_member_iterator(&it, ec);
+ * setup_eclass_child_member_iterator(&it, root, ec, rel);
* while ((em = eclass_child_member_iterator_next(&it)) != NULL)
* {
* use em ...;
- * if (we need to iterate over child EquivalenceMembers)
- * iterate_child_rel_equivalences(&it, root, ec, em, rel);
- * use em ...;
* }
* dispose_eclass_child_member_iterator(&it);
* -----
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index b6208928bf9..719be3897f6 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -331,24 +331,6 @@ extern Relids min_join_parameterization(PlannerInfo *root,
extern RelOptInfo *fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind,
Relids relids);
extern Relids find_childrel_parents(PlannerInfo *root, RelOptInfo *rel);
-
-/*
- * find_relids_top_parents
- * Compute the set of top-parent relids of rel.
- *
- * Replaces all Relids appearing in the given 'relids' as their top-level
- * parents. The result will be NULL if and only if all of the given relids are
- * top-level.
- *
- * The motivation for having this feature as a macro rather than a function is
- * that Relids are top-level in most cases. We can quickly determine when
- * root->top_parent_relid_array is NULL.
- */
-#define find_relids_top_parents(root, relids) \
- ((root)->top_parent_relid_array == NULL \
- ? NULL : find_relids_top_parents_slow(root, relids))
-extern Relids find_relids_top_parents_slow(PlannerInfo *root, Relids relids);
-
extern ParamPathInfo *get_baserel_parampathinfo(PlannerInfo *root,
RelOptInfo *baserel,
Relids required_outer);
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index a91fb41335a..07525dca66d 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -184,14 +184,11 @@ extern void add_setop_child_rel_equivalences(PlannerInfo *root,
List *child_tlist,
List *setop_pathkeys);
extern void setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
- EquivalenceClass *ec);
+ PlannerInfo *root,
+ EquivalenceClass *ec,
+ Relids relids);
extern EquivalenceMember *eclass_child_member_iterator_next(EquivalenceChildMemberIterator *it);
extern void dispose_eclass_child_member_iterator(EquivalenceChildMemberIterator *it);
-extern void iterate_child_rel_equivalences(EquivalenceChildMemberIterator *it,
- PlannerInfo *root,
- EquivalenceClass *ec,
- EquivalenceMember *parent_em,
- Relids child_relids);
extern List *generate_implied_equalities_for_column(PlannerInfo *root,
RelOptInfo *rel,
ec_matches_callback_type callback,