diff-v33-v34.txt

text/plain

Filename: diff-v33-v34.txt
Type: text/plain
Part: 0
Message: Re: [PoC] Reducing planning time when tables have many partitions
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index d4a26b59330..2eb0f16b0f6 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -7830,11 +7830,11 @@ EquivalenceMember *
 find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
 {
 	PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
-	EquivalenceChildMemberIterator it;
+	EquivalenceAllMemberIterator it;
 	EquivalenceMember *em;
 
-	setup_eclass_child_member_iterator(&it, root, ec, rel->relids);
-	while ((em = eclass_child_member_iterator_next(&it)) != NULL)
+	setup_eclass_all_member_iterator_for_relids(&it, root, ec, rel->relids);
+	while ((em = eclass_all_member_iterator_for_relids_next(&it)) != NULL)
 	{
 		/*
 		 * Note we require !bms_is_empty, else we'd accept constant
@@ -7846,7 +7846,7 @@ find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel)
 			is_foreign_expr(root, rel, em->em_expr))
 			return em;
 	}
-	dispose_eclass_child_member_iterator(&it);
+	dispose_eclass_all_member_iterator_for_relids(&it);
 
 	return NULL;
 }
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index 21c2593e959..5aecf96cbb7 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -1302,8 +1302,8 @@ bms_join(Bitmapset *a, Bitmapset *b)
  * It makes no difference in simple loop usage, but complex iteration logic
  * might need such an ability.
  *
- * NOTE: The routine here is similar to eclass_rinfo_iterator_next(). If you
- * change here, you should adjust the logic there.
+ * NOTE: The routine here is similar to eclass_rinfo_iterator_for_relids_next().
+ * If you change here, you should adjust the logic there.
  */
 int
 bms_next_member(const Bitmapset *a, int prevbit)
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index e0f95da9a18..c6ecfb874c8 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -76,10 +76,10 @@ static bool reconsider_outer_join_clause(PlannerInfo *root,
 static bool reconsider_full_join_clause(PlannerInfo *root,
 										OuterJoinClauseInfo *ojcinfo);
 static JoinDomain *find_join_domain(PlannerInfo *root, Relids relids);
-static void add_transformed_child_version(EquivalenceChildMemberIterator *it,
-										  PlannerInfo *root,
-										  EquivalenceClass *ec,
-										  RelOptInfo *child_rel);
+static void add_eclass_child_members_to_iterator(EquivalenceAllMemberIterator *it,
+												 PlannerInfo *root,
+												 EquivalenceClass *ec,
+												 RelOptInfo *child_rel);
 static Bitmapset *get_eclass_indexes_for_relids(PlannerInfo *root,
 												Relids relids);
 static Bitmapset *get_common_eclass_indexes(PlannerInfo *root, Relids relids1,
@@ -821,7 +821,7 @@ get_eclass_for_sort_expr(PlannerInfo *root,
 	foreach(lc1, root->eq_classes)
 	{
 		EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1);
-		EquivalenceChildMemberIterator it;
+		EquivalenceAllMemberIterator it;
 		EquivalenceMember *cur_em;
 
 		/*
@@ -837,8 +837,8 @@ get_eclass_for_sort_expr(PlannerInfo *root,
 		if (!equal(opfamilies, cur_ec->ec_opfamilies))
 			continue;
 
-		setup_eclass_child_member_iterator(&it, root, cur_ec, rel);
-		while ((cur_em = eclass_child_member_iterator_next(&it)) != NULL)
+		setup_eclass_all_member_iterator_for_relids(&it, root, cur_ec, rel);
+		while ((cur_em = eclass_all_member_iterator_for_relids_next(&it)) != NULL)
 		{
 			/*
 			 * Ignore child members unless they match the request.
@@ -858,7 +858,7 @@ get_eclass_for_sort_expr(PlannerInfo *root,
 				equal(expr, cur_em->em_expr))
 				return cur_ec;	/* Match! */
 		}
-		dispose_eclass_child_member_iterator(&it);
+		dispose_eclass_all_member_iterator_for_relids(&it);
 	}
 
 	/* No match; does caller want a NULL result? */
@@ -970,15 +970,15 @@ find_ec_member_matching_expr(PlannerInfo *root, EquivalenceClass *ec,
 							 Expr *expr,
 							 Relids relids)
 {
-	EquivalenceChildMemberIterator it;
+	EquivalenceAllMemberIterator it;
 	EquivalenceMember *em;
 
 	/* We ignore binary-compatible relabeling on both ends */
 	while (expr && IsA(expr, RelabelType))
 		expr = ((RelabelType *) expr)->arg;
 
-	setup_eclass_child_member_iterator(&it, root, ec, relids);
-	while ((em = eclass_child_member_iterator_next(&it)) != NULL)
+	setup_eclass_all_member_iterator_for_relids(&it, root, ec, relids);
+	while ((em = eclass_all_member_iterator_for_relids_next(&it)) != NULL)
 	{
 		Expr	   *emexpr;
 
@@ -1006,7 +1006,7 @@ find_ec_member_matching_expr(PlannerInfo *root, EquivalenceClass *ec,
 		if (equal(emexpr, expr))
 			return em;
 	}
-	dispose_eclass_child_member_iterator(&it);
+	dispose_eclass_all_member_iterator_for_relids(&it);
 
 	return NULL;
 }
@@ -1049,7 +1049,7 @@ find_computable_ec_member(PlannerInfo *root,
 						  bool require_parallel_safe)
 {
 	List	   *exprvars;
-	EquivalenceChildMemberIterator it;
+	EquivalenceAllMemberIterator it;
 	EquivalenceMember *em;
 
 	/*
@@ -1064,8 +1064,8 @@ find_computable_ec_member(PlannerInfo *root,
 							   PVC_INCLUDE_PLACEHOLDERS |
 							   PVC_INCLUDE_CONVERTROWTYPES);
 
-	setup_eclass_child_member_iterator(&it, root, ec, relids);
-	while ((em = eclass_child_member_iterator_next(&it)) != NULL)
+	setup_eclass_all_member_iterator_for_relids(&it, root, ec, relids);
+	while ((em = eclass_all_member_iterator_for_relids_next(&it)) != NULL)
 	{
 		List	   *emvars;
 		ListCell   *lc2;
@@ -1110,7 +1110,7 @@ find_computable_ec_member(PlannerInfo *root,
 
 		return em;				/* found usable expression */
 	}
-	dispose_eclass_child_member_iterator(&it);
+	dispose_eclass_all_member_iterator_for_relids(&it);
 
 	return NULL;
 }
@@ -1777,7 +1777,7 @@ generate_join_implied_equalities_normal(PlannerInfo *root,
 	List	   *new_members = NIL;
 	List	   *outer_members = NIL;
 	List	   *inner_members = NIL;
-	EquivalenceChildMemberIterator it;
+	EquivalenceAllMemberIterator it;
 	EquivalenceMember *cur_em;
 
 	/*
@@ -1789,8 +1789,8 @@ 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.
 	 */
-	setup_eclass_child_member_iterator(&it, root, ec, join_relids);
-	while ((cur_em = eclass_child_member_iterator_next(&it)) != NULL)
+	setup_eclass_all_member_iterator_for_relids(&it, root, ec, join_relids);
+	while ((cur_em = eclass_all_member_iterator_for_relids_next(&it)) != NULL)
 	{
 		/*
 		 * We don't need to check explicitly for child EC members.  This test
@@ -1807,7 +1807,7 @@ generate_join_implied_equalities_normal(PlannerInfo *root,
 		else
 			new_members = lappend(new_members, cur_em);
 	}
-	dispose_eclass_child_member_iterator(&it);
+	dispose_eclass_all_member_iterator_for_relids(&it);
 
 	/*
 	 * First, select the joinclause if needed.  We can equate any one outer
@@ -1957,9 +1957,9 @@ generate_join_implied_equalities_broken(PlannerInfo *root,
 	RestrictInfo *restrictinfo;
 	RestrictInfoIterator iter;
 
-	setup_eclass_rinfo_iterator(&iter, root, ec, nominal_join_relids, true,
-								false);
-	while ((restrictinfo = eclass_rinfo_iterator_next(&iter)) != NULL)
+	setup_eclass_rinfo_iterator_for_relids(&iter, root, ec, nominal_join_relids, true,
+										   false);
+	while ((restrictinfo = eclass_rinfo_iterator_for_relids_next(&iter)) != NULL)
 	{
 		Relids		clause_relids = restrictinfo->required_relids;
 
@@ -1968,7 +1968,7 @@ generate_join_implied_equalities_broken(PlannerInfo *root,
 			!bms_is_subset(clause_relids, nominal_inner_relids))
 			result = lappend(result, restrictinfo);
 	}
-	dispose_eclass_rinfo_iterator(&iter);
+	dispose_eclass_rinfo_iterator_for_relids(&iter);
 
 	/*
 	 * If we have to translate, just brute-force apply adjust_appendrel_attrs
@@ -2054,10 +2054,10 @@ create_join_clause(PlannerInfo *root,
 	 * it's not identical, it'd better have the same effects, or the operator
 	 * families we're using are broken.
 	 */
-	setup_eclass_rinfo_iterator(&iter, root, ec,
-								bms_union(leftem->em_relids, rightem->em_relids),
-								true, true);
-	while ((rinfo = eclass_rinfo_iterator_next(&iter)) != NULL)
+	setup_eclass_rinfo_iterator_for_relids(&iter, root, ec,
+										   bms_union(leftem->em_relids, rightem->em_relids),
+										   true, true);
+	while ((rinfo = eclass_rinfo_iterator_for_relids_next(&iter)) != NULL)
 	{
 		if (rinfo->left_em == leftem &&
 			rinfo->right_em == rightem &&
@@ -2068,12 +2068,12 @@ create_join_clause(PlannerInfo *root,
 			rinfo->parent_ec == parent_ec)
 			return rinfo;
 	}
-	dispose_eclass_rinfo_iterator(&iter);
+	dispose_eclass_rinfo_iterator_for_relids(&iter);
 
-	setup_eclass_rinfo_iterator(&iter, root, ec,
-								bms_union(leftem->em_relids, rightem->em_relids),
-								false, true);
-	while ((rinfo = eclass_rinfo_iterator_next(&iter)) != NULL)
+	setup_eclass_rinfo_iterator_for_relids(&iter, root, ec,
+										   bms_union(leftem->em_relids, rightem->em_relids),
+										   false, true);
+	while ((rinfo = eclass_rinfo_iterator_for_relids_next(&iter)) != NULL)
 	{
 		if (rinfo->left_em == leftem &&
 			rinfo->right_em == rightem &&
@@ -2084,7 +2084,7 @@ create_join_clause(PlannerInfo *root,
 			rinfo->parent_ec == parent_ec)
 			return rinfo;
 	}
-	dispose_eclass_rinfo_iterator(&iter);
+	dispose_eclass_rinfo_iterator_for_relids(&iter);
 
 	/*
 	 * Not there, so build it, in planner context so we can re-use it. (Not
@@ -3159,12 +3159,12 @@ 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
-					 * EquivalenceChildMemberIterator. Since the iterator
-					 * needs EquivalenceMembers whose em_relids has child
-					 * relations, skipping the update of this inverted index
-					 * allows for faster iteration.
+					 * EquivalenceAllMemberIterator. Since the iterator needs
+					 * EquivalenceMembers whose em_relids has child relations,
+					 * skipping the update of this inverted index allows for
+					 * faster iteration.
 					 */
-					if (root->top_parent_relid_array[j] == -1)
+					if (root->append_rel_array[j] == NULL)
 						continue;
 					indexes->joinrel_indexes =
 						bms_add_member(indexes->joinrel_indexes,
@@ -3203,7 +3203,6 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel,
 		EquivalenceMember *parent_em;
 		EquivalenceMember *child_em;
 		PathKey    *pk;
-		Index		parent_relid;
 
 		if (tle->resjunk)
 			continue;
@@ -3232,28 +3231,26 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel,
 		/*
 		 * Make an UNION parent-child relationship between parent_em and
 		 * child_rel->relid. We record this relationship in
-		 * root->top_parent_relid_array, which generally has AppendRelInfo
+		 * root->append_rel_array, which generally has AppendRelInfo
 		 * relationships. We use the same array here to retrieve UNION child
 		 * members.
 		 *
+		 * XXX Here we create a dummy AppendRelInfo object to know that the
+		 * relation of 'child_rel->relid' is a child and there are some
+		 * children because root->append_rel_array is not NULL. However this
+		 * is just a workaround. We must consider better way.
+		 *
 		 * XXX Here we treat the first member of parent_em->em_relids as a
 		 * parent of child_rel. Is this correct? What happens if
 		 * parent_em->em_relids has two or more members?
 		 */
-		parent_relid = bms_next_member(parent_em->em_relids, -1);
-		if (root->top_parent_relid_array == NULL)
-		{
-			/*
-			 * If the array is NULL, allocate it here.
-			 */
-			root->top_parent_relid_array = (Index *)
-				palloc(root->simple_rel_array_size * sizeof(Index));
-			MemSet(root->top_parent_relid_array, -1,
-				   sizeof(Index) * root->simple_rel_array_size);
-		}
-		Assert(root->top_parent_relid_array[child_rel->relid] == -1 ||
-			   root->top_parent_relid_array[child_rel->relid] == parent_relid);
-		root->top_parent_relid_array[child_rel->relid] = parent_relid;
+		if (root->append_rel_array == NULL)
+			root->append_rel_array = palloc0_array(AppendRelInfo *, root->simple_rel_array_size);
+		root->append_rel_array[child_rel->relid] = makeNode(AppendRelInfo);
+		root->append_rel_array[child_rel->relid]->parent_relid =
+			bms_next_member(parent_em->em_relids, -1);
+		root->append_rel_array[child_rel->relid]->child_relid =
+			child_rel->relid;
 
 		lc2 = lnext(setop_pathkeys, lc2);
 	}
@@ -3269,18 +3266,32 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel,
 }
 
 /*
- * setup_eclass_child_member_iterator
- *	  Setup an EquivalenceChildMemberIterator 'it' so that it can iterate over
- *	  EquivalenceMembers in 'ec'.
+ * setup_eclass_all_member_iterator_for_relids
+ *	  Setup an EquivalenceAllMemberIterator 'it' to iterate over all parent
+ *	  EquivalenceMembers and child members associated with the given 'ec' that
+ *	  are relevant to the specified 'relids'.
  *
- * Once used, the caller should dispose of the iterator by calling
- * dispose_eclass_child_member_iterator().
+ * This iterator returns:
+ *	- All parent members stored directly in ec->ec_members.
+ *	- The child members whose em_relids is a subset of the given 'relids'.
+ *
+ * Note:
+ *	- The iterator may return false positives, i.e., child members whose
+ *	  em_relids is not a subset. So the caller must check that they satisfy
+ *	  the desired condition.
+ *	- Once used, the caller should dispose of the iterator by calling
+ *	  dispose_eclass_all_member_iterator_for_relids().
+ *
+ * Parameters:
+ *	root - The PlannerInfo context.
+ *	ec - The EquivalenceClass from which to iterate members.
+ *	relids - The Relids used to filter for relevant child members.
  */
 void
-setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
-								   PlannerInfo *root,
-								   EquivalenceClass *ec,
-								   Relids relids)
+setup_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it,
+											PlannerInfo *root,
+											EquivalenceClass *ec,
+											Relids relids)
 {
 	Bitmapset  *matching_indexes;
 	int			i;
@@ -3296,7 +3307,7 @@ setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
 	 * 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)
+	if (root->append_rel_array == NULL)
 		return;
 
 	/*
@@ -3339,7 +3350,7 @@ setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
 		/*
 		 * If this relation is a parent, we don't have to do anything.
 		 */
-		if (root->top_parent_relid_array[i] == -1)
+		if (root->append_rel_array[i] == NULL)
 			continue;
 
 		/*
@@ -3347,7 +3358,7 @@ setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
 		 */
 		child_rel = root->simple_rel_array[i];
 		if (child_rel != NULL)
-			add_transformed_child_version(it, root, ec, child_rel);
+			add_eclass_child_members_to_iterator(it, root, ec, child_rel);
 
 		/*
 		 * Union indexes for join rels.
@@ -3373,7 +3384,7 @@ setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
 		 * 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);
+			add_eclass_child_members_to_iterator(it, root, ec, child_joinrel);
 #ifdef USE_ASSERT_CHECKING
 		else
 		{
@@ -3400,18 +3411,18 @@ setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
 }
 
 /*
- * add_transformed_child_version
- *	  Add a transformed EquivalenceMember referencing the given child_rel to
- *	  the iterator.
+ * add_eclass_child_members_to_iterator
+ *	  Add a child EquivalenceMember referencing the given child_rel to
+ *	  the iterator from RelOptInfo.
  *
  * This function is expected to be called only from
- * setup_eclass_child_member_iterator().
+ * setup_eclass_all_member_iterator_for_relids().
  */
 static void
-add_transformed_child_version(EquivalenceChildMemberIterator *it,
-							  PlannerInfo *root,
-							  EquivalenceClass *ec,
-							  RelOptInfo *child_rel)
+add_eclass_child_members_to_iterator(EquivalenceAllMemberIterator *it,
+									 PlannerInfo *root,
+									 EquivalenceClass *ec,
+									 RelOptInfo *child_rel)
 {
 	ListCell   *lc;
 
@@ -3439,13 +3450,13 @@ add_transformed_child_version(EquivalenceChildMemberIterator *it,
 }
 
 /*
- * 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.
+ * eclass_all_member_iterator_for_relids_next
+ *	  Get a next EquivalenceMember from an EquivalenceAllMemberIterator 'it'
+ *	  that was setup by setup_eclass_all_member_iterator_for_relids(). NULL is
+ *	  returned if there are no members left.
  */
 EquivalenceMember *
-eclass_child_member_iterator_next(EquivalenceChildMemberIterator *it)
+eclass_all_member_iterator_for_relids_next(EquivalenceAllMemberIterator *it)
 {
 	if (++it->index < list_length(it->ec_members))
 		return list_nth_node(EquivalenceMember, it->ec_members, it->index);
@@ -3453,11 +3464,11 @@ eclass_child_member_iterator_next(EquivalenceChildMemberIterator *it)
 }
 
 /*
- * dispose_eclass_child_member_iterator
+ * dispose_eclass_all_member_iterator_for_relids
  *	  Free any memory allocated by the iterator.
  */
 void
-dispose_eclass_child_member_iterator(EquivalenceChildMemberIterator *it)
+dispose_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it)
 {
 	/*
 	 * XXX Should we use list_free()? I decided to use this style to take
@@ -3521,7 +3532,7 @@ generate_implied_equalities_for_column(PlannerInfo *root,
 		EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
 		EquivalenceMember *cur_em;
 		ListCell   *lc2;
-		EquivalenceChildMemberIterator it;
+		EquivalenceAllMemberIterator it;
 
 		/* Sanity check eclass_indexes only contain ECs for rel */
 		Assert(is_child_rel || bms_is_subset(rel->relids, cur_ec->ec_relids));
@@ -3543,14 +3554,14 @@ 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.)
 		 */
-		setup_eclass_child_member_iterator(&it, root, cur_ec, rel->relids);
-		while ((cur_em = eclass_child_member_iterator_next(&it)) != NULL)
+		setup_eclass_all_member_iterator_for_relids(&it, root, cur_ec, rel->relids);
+		while ((cur_em = eclass_all_member_iterator_for_relids_next(&it)) != NULL)
 		{
 			if (bms_equal(cur_em->em_relids, rel->relids) &&
 				callback(root, rel, cur_ec, cur_em, callback_arg))
 				break;
 		}
-		dispose_eclass_child_member_iterator(&it);
+		dispose_eclass_all_member_iterator_for_relids(&it);
 
 		if (!cur_em)
 			continue;
@@ -3921,20 +3932,21 @@ get_common_eclass_indexes(PlannerInfo *root, Relids relids1, Relids relids2)
 }
 
 /*
- * setup_eclass_rinfo_iterator
- *	  Setup a RestrictInfoIterator 'iter' so that it can iterate over
- *	  RestrictInfos. We iterate through root->eq_sources if 'is_source' is
- *	  true, or root->eq_derives otherwise. The members must be from 'ec' and
- *	  satisfy "bms_is_subset(relids, rinfo->clause_relids)" if 'is_strict' is
- *	  true, or "bms_overlap(relids, rinfo->clause_relids)" otherwise.
+ * setup_eclass_rinfo_iterator_for_relids
+ *	  Setup a RestrictInfoIterator 'iter' to iterate over RestrictInfos
+ *	  associated with the given 'ec'. It iterates through root->eq_sources if
+ *	  'is_source' is true, or root->eq_derives otherwise. The members must be
+ *	  from 'ec' and satisfy "bms_is_subset(relids, rinfo->clause_relids)" if
+ *	  'is_strict' is true, or "bms_overlap(relids, rinfo->clause_relids)"
+ *	  otherwise.
  *
  * Once used, the caller should dispose of the iterator by calling
- * dispose_eclass_rinfo_iterator().
+ * dispose_eclass_rinfo_iterator_for_relids().
  */
 void
-setup_eclass_rinfo_iterator(RestrictInfoIterator *iter, PlannerInfo *root,
-							EquivalenceClass *ec, Relids relids,
-							bool is_source, bool is_strict)
+setup_eclass_rinfo_iterator_for_relids(RestrictInfoIterator *iter, PlannerInfo *root,
+									   EquivalenceClass *ec, Relids relids,
+									   bool is_source, bool is_strict)
 {
 	iter->root = root;
 	iter->ec = ec;
@@ -3947,13 +3959,13 @@ setup_eclass_rinfo_iterator(RestrictInfoIterator *iter, PlannerInfo *root,
 }
 
 /*
- * eclass_rinfo_iterator_next
+ * eclass_rinfo_iterator_for_relids_next
  *	  Get a next RestrictInfo from an RestrictInfoIterator 'iter' that was
- *	  setup by setup_eclass_rinfo_iterator(). NULL is returned if there are no
- *	  members left.
+ *	  setup by setup_eclass_rinfo_iterator_for_relids(). NULL is returned if
+ *	  there are no members left.
  */
 RestrictInfo *
-eclass_rinfo_iterator_next(RestrictInfoIterator *iter)
+eclass_rinfo_iterator_for_relids_next(RestrictInfoIterator *iter)
 {
 	RestrictInfo *rinfo;
 	bitmapword	mask;
@@ -4074,11 +4086,11 @@ eclass_rinfo_iterator_next(RestrictInfoIterator *iter)
 }
 
 /*
- * dispose_eclass_rinfo_iterator
+ * dispose_eclass_rinfo_iterator_for_relids
  *	  Free any memory allocated by the iterator.
  */
 void
-dispose_eclass_rinfo_iterator(RestrictInfoIterator *iter)
+dispose_eclass_rinfo_iterator_for_relids(RestrictInfoIterator *iter)
 {
 	/* Do nothing */
 }
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 30e443d1554..38f7322caf9 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -3756,7 +3756,7 @@ match_pathkeys_to_index(PlannerInfo *root, IndexOptInfo *index, List *pathkeys,
 	{
 		PathKey    *pathkey = (PathKey *) lfirst(lc1);
 		bool		found = false;
-		EquivalenceChildMemberIterator it;
+		EquivalenceAllMemberIterator it;
 		EquivalenceMember *member;
 
 
@@ -3777,9 +3777,9 @@ match_pathkeys_to_index(PlannerInfo *root, IndexOptInfo *index, List *pathkeys,
 		 * be considered to match more than one pathkey list, which is OK
 		 * here.  See also get_eclass_for_sort_expr.)
 		 */
-		setup_eclass_child_member_iterator(&it, root, pathkey->pk_eclass,
-										   index->rel->relids);
-		while ((member = eclass_child_member_iterator_next(&it)) != NULL)
+		setup_eclass_all_member_iterator_for_relids(&it, root, pathkey->pk_eclass,
+													index->rel->relids);
+		while ((member = eclass_all_member_iterator_for_relids_next(&it)) != NULL)
 		{
 			int			indexcol;
 
@@ -3815,7 +3815,7 @@ match_pathkeys_to_index(PlannerInfo *root, IndexOptInfo *index, List *pathkeys,
 			if (found)			/* don't want to look at remaining members */
 				break;
 		}
-		dispose_eclass_child_member_iterator(&it);
+		dispose_eclass_all_member_iterator_for_relids(&it);
 
 		/*
 		 * Return the matches found so far when this pathkey couldn't be
diff --git a/src/backend/optimizer/util/inherit.c b/src/backend/optimizer/util/inherit.c
index 08cd39a6c85..17e51cd75d7 100644
--- a/src/backend/optimizer/util/inherit.c
+++ b/src/backend/optimizer/util/inherit.c
@@ -470,7 +470,6 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
 		RelationGetRelid(parentrel);
 	Oid			childOID = RelationGetRelid(childrel);
 	RangeTblEntry *childrte;
-	Index		topParentRTindex;
 	Index		childRTindex;
 	AppendRelInfo *appinfo;
 	TupleDesc	child_tupdesc;
@@ -578,23 +577,6 @@ expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte,
 	Assert(root->append_rel_array[childRTindex] == NULL);
 	root->append_rel_array[childRTindex] = appinfo;
 
-	/*
-	 * Find a top parent rel's index and save it to top_parent_relid_array.
-	 */
-	if (root->top_parent_relid_array == NULL)
-	{
-		root->top_parent_relid_array =
-			(Index *) palloc(root->simple_rel_array_size * sizeof(Index));
-		MemSet(root->top_parent_relid_array, -1,
-			   sizeof(Index) * root->simple_rel_array_size);
-	}
-	Assert(root->top_parent_relid_array[childRTindex] == -1);
-	topParentRTindex = parentRTindex;
-	while (root->append_rel_array[topParentRTindex] != NULL &&
-		   root->append_rel_array[topParentRTindex]->parent_relid != 0)
-		topParentRTindex = root->append_rel_array[topParentRTindex]->parent_relid;
-	root->top_parent_relid_array[childRTindex] = topParentRTindex;
-
 	/*
 	 * Build a PlanRowMark if parent is marked FOR UPDATE/SHARE.
 	 */
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index ff25cd86448..8dc51353791 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -126,16 +126,11 @@ setup_simple_rel_arrays(PlannerInfo *root)
 	if (root->append_rel_list == NIL)
 	{
 		root->append_rel_array = NULL;
-		root->top_parent_relid_array = NULL;
 		return;
 	}
 
 	root->append_rel_array = (AppendRelInfo **)
 		palloc0(size * sizeof(AppendRelInfo *));
-	root->top_parent_relid_array = (Index *)
-		palloc(size * sizeof(Index));
-	MemSet(root->top_parent_relid_array, -1,
-		   sizeof(Index) * size);
 
 	/*
 	 * append_rel_array is filled with any already-existing AppendRelInfos,
@@ -156,27 +151,6 @@ setup_simple_rel_arrays(PlannerInfo *root)
 
 		root->append_rel_array[child_relid] = appinfo;
 	}
-
-	/*
-	 * Find a top parent rel's relid for each AppendRelInfo. We cannot do this
-	 * in the last foreach loop because there may be multi-level parent-child
-	 * relations.
-	 */
-	for (int i = 0; i < size; i++)
-	{
-		int			top_parent_relid;
-
-		if (root->append_rel_array[i] == NULL)
-			continue;
-
-		top_parent_relid = root->append_rel_array[i]->parent_relid;
-
-		while (root->append_rel_array[top_parent_relid] != NULL &&
-			   root->append_rel_array[top_parent_relid]->parent_relid != 0)
-			top_parent_relid = root->append_rel_array[top_parent_relid]->parent_relid;
-
-		root->top_parent_relid_array[i] = top_parent_relid;
-	}
 }
 
 /*
@@ -204,27 +178,12 @@ expand_planner_arrays(PlannerInfo *root, int add_size)
 		repalloc0_array(root->simple_rte_array, RangeTblEntry *, root->simple_rel_array_size, new_size);
 
 	if (root->append_rel_array)
-	{
 		root->append_rel_array =
 			repalloc0_array(root->append_rel_array, AppendRelInfo *, root->simple_rel_array_size, new_size);
-		root->top_parent_relid_array =
-			repalloc_array(root->top_parent_relid_array, Index, new_size);
-		MemSet(root->top_parent_relid_array + root->simple_rel_array_size, -1,
-			   sizeof(Index) * add_size);
-	}
 	else
-	{
 		root->append_rel_array =
 			palloc0_array(AppendRelInfo *, new_size);
 
-		/*
-		 * We do not allocate top_parent_relid_array here so that
-		 * setup_eclass_child_member_iterator() can early find all of the
-		 * given Relids are top-level.
-		 */
-		root->top_parent_relid_array = NULL;
-	}
-
 	root->eclass_indexes_array =
 		repalloc0_array(root->eclass_indexes_array, EquivalenceClassIndexes, root->simple_rel_array_size, new_size);
 
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index 3f0d686108c..0abd8dd4d9b 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -278,14 +278,6 @@ struct PlannerInfo
 	 */
 	struct EquivalenceClassIndexes *eclass_indexes_array pg_node_attr(read_write_ignore);
 
-	/*
-	 * top_parent_relid_array is the same length as simple_rel_array and holds
-	 * the top-level parent indexes of the corresponding rels within
-	 * simple_rel_array. The element can be -1 if the rel has no parents,
-	 * i.e., is itself in a top-level.
-	 */
-	Index	   *top_parent_relid_array pg_node_attr(read_write_ignore);
-
 	/*
 	 * all_baserels is a Relids set of all base relids (but not joins or
 	 * "other" rels) in the query.  This is computed in deconstruct_jointree.
@@ -1436,9 +1428,9 @@ typedef struct JoinDomain
  *
  * EquivalenceClass->ec_members can only have parent members, and child members
  * are stored in RelOptInfos, from which those child members are translated. To
- * lookup child EquivalenceMembers, we use EquivalenceChildMemberIterator. See
+ * lookup child EquivalenceMembers, we use EquivalenceAllMemberIterator. See
  * its comment for usage. The approach to lookup child members quickly is
- * described as iterate_child_rel_equivalences() comment.
+ * described as setup_eclass_all_member_iterator_for_relids() comment.
  *
  * At various locations in the query planner, we must search for source and
  * derived RestrictInfos regarding a given EquivalenceClass.  For the common
@@ -1538,28 +1530,33 @@ typedef struct EquivalenceMember
 } EquivalenceMember;
 
 /*
- * EquivalenceChildMemberIterator
+ * EquivalenceAllMemberIterator
  *
- * 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.
+ * EquivalenceAllMemberIterator is designed to iterate over all parent
+ * EquivalenceMembers and child members associated with the given 'ec' that
+ * are relevant to the specified 'relids'. In particular, it iterates over:
+ *	- All parent members stored directly in ec->ec_members.
+ *	- The child members whose em_relids is a subset of the given 'relids'.
  *
- * The most common way to use this struct is as follows:
+ * Note:
+ *	- The iterator may return false positives, i.e., child members whose
+ *	  em_relids is not a subset. So the caller must check that they satisfy
+ *	  the desired condition.
+ *
+ * The most common way to use this iterator is as follows:
  * -----
  * PlannerInfo					   *root = given;
  * EquivalenceClass				   *ec = given;
  * Relids							rel = given;
- * EquivalenceChildMemberIterator	it;
+ * EquivalenceAllMemberIterator		it;
  * EquivalenceMember			   *em;
  *
- * setup_eclass_child_member_iterator(&it, root, ec, rel);
- * while ((em = eclass_child_member_iterator_next(&it)) != NULL)
+ * setup_eclass_all_member_iterator_for_relids(&it, root, ec, rel);
+ * while ((em = eclass_all_member_iterator_for_relids_next(&it)) != NULL)
  * {
  *     use em ...;
  * }
- * dispose_eclass_child_member_iterator(&it);
+ * dispose_eclass_all_member_iterator_for_relids(&it);
  * -----
  */
 typedef struct
@@ -1567,7 +1564,7 @@ typedef struct
 	int			index;			/* current index within 'ec_members'. */
 	bool		modified;		/* is 'ec_members' a newly allocated one? */
 	List	   *ec_members;		/* parent and child members */
-} EquivalenceChildMemberIterator;
+} EquivalenceAllMemberIterator;
 
 /*
  * RestrictInfoIterator
@@ -1576,7 +1573,7 @@ typedef struct
  * EquivalenceClass that satisfy a certain condition. You need to first
  * initialize an iterator, and then use move next during the iteration. You
  * can specify the condition during initialization. For more details, see the
- * comment in setup_eclass_rinfo_iterator().
+ * comment in setup_eclass_rinfo_iterator_for_relids().
  *
  * The most common way to use this struct is as follows:
  * -----
@@ -1586,12 +1583,12 @@ typedef struct
  * RestrictInfoIterator iter;
  * RestrictInfo		   *rinfo;
  *
- * setup_eclass_rinfo_iterator(&iter, root, ec, relids, true, true);
- * while ((rinfo = eclass_rinfo_iterator_next(&iter)) != NULL)
+ * setup_eclass_rinfo_iterator_for_relids(&iter, root, ec, relids, true, true);
+ * while ((rinfo = eclass_rinfo_iterator_for_relids_next(&iter)) != NULL)
  * {
  *     use rinfo ...;
  * }
- * dispose_eclass_rinfo_iterator(&iter);
+ * dispose_eclass_rinfo_iterator_for_relids(&iter);
  * -----
  */
 typedef struct
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 1361e20641a..e8706b2774c 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -185,12 +185,12 @@ extern void add_setop_child_rel_equivalences(PlannerInfo *root,
 											 RelOptInfo *child_rel,
 											 List *child_tlist,
 											 List *setop_pathkeys);
-extern void setup_eclass_child_member_iterator(EquivalenceChildMemberIterator *it,
-											   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 setup_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it,
+														PlannerInfo *root,
+														EquivalenceClass *ec,
+														Relids relids);
+extern EquivalenceMember *eclass_all_member_iterator_for_relids_next(EquivalenceAllMemberIterator *it);
+extern void dispose_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it);
 extern List *generate_implied_equalities_for_column(PlannerInfo *root,
 													RelOptInfo *rel,
 													ec_matches_callback_type callback,
@@ -206,14 +206,14 @@ extern bool eclass_useful_for_merging(PlannerInfo *root,
 extern bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist);
 extern bool is_redundant_with_indexclauses(RestrictInfo *rinfo,
 										   List *indexclauses);
-extern void setup_eclass_rinfo_iterator(RestrictInfoIterator *iter,
-										PlannerInfo *root,
-										EquivalenceClass *ec,
-										Relids relids,
-										bool is_source,
-										bool is_strict);
-extern RestrictInfo *eclass_rinfo_iterator_next(RestrictInfoIterator *iter);
-extern void dispose_eclass_rinfo_iterator(RestrictInfoIterator *iter);
+extern void setup_eclass_rinfo_iterator_for_relids(RestrictInfoIterator *iter,
+												   PlannerInfo *root,
+												   EquivalenceClass *ec,
+												   Relids relids,
+												   bool is_source,
+												   bool is_strict);
+extern RestrictInfo *eclass_rinfo_iterator_for_relids_next(RestrictInfoIterator *iter);
+extern void dispose_eclass_rinfo_iterator_for_relids(RestrictInfoIterator *iter);
 #ifdef USE_ASSERT_CHECKING
 extern void verify_eclass_indexes(PlannerInfo *root,
 								  EquivalenceClass *ec);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 433577a3d8a..51d45b6677c 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -696,7 +696,7 @@ EphemeralNamedRelation
 EphemeralNamedRelationData
 EphemeralNamedRelationMetadata
 EphemeralNamedRelationMetadataData
-EquivalenceChildMemberIterator
+EquivalenceAllMemberIterator
 EquivalenceClass
 EquivalenceClassIndexes
 EquivalenceMember