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