diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index dbf92c9b7ca..adcf6417468 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -7829,11 +7829,11 @@ EquivalenceMember * find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel) { PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private; - EquivalenceAllMemberIterator it; + EquivalenceMemberIterator it; EquivalenceMember *em; - setup_eclass_all_member_iterator_for_relids(&it, root, ec, rel->relids); - while ((em = eclass_all_member_iterator_for_relids_next(&it)) != NULL) + setup_eclass_member_iterator_with_children(&it, root, ec, rel->relids); + while ((em = eclass_member_iterator_next(&it)) != NULL) { /* * Note we require !bms_is_empty, else we'd accept constant @@ -7845,7 +7845,7 @@ find_em_for_rel(PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *rel) is_foreign_expr(root, rel, em->em_expr)) return em; } - dispose_eclass_all_member_iterator_for_relids(&it); + dispose_eclass_member_iterator(&it); return NULL; } diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c index c6ecfb874c8..1ffd2ce0a04 100644 --- a/src/backend/optimizer/path/equivclass.c +++ b/src/backend/optimizer/path/equivclass.c @@ -38,10 +38,10 @@ static EquivalenceMember *make_eq_member(EquivalenceClass *ec, JoinDomain *jdomain, EquivalenceMember *parent, Oid datatype); -static EquivalenceMember *add_parent_eq_member(EquivalenceClass *ec, - Expr *expr, Relids relids, - JoinDomain *jdomain, - Oid datatype); +static EquivalenceMember *add_eq_member(EquivalenceClass *ec, + Expr *expr, Relids relids, + JoinDomain *jdomain, + Oid datatype); static void add_eq_source(PlannerInfo *root, EquivalenceClass *ec, RestrictInfo *rinfo); static void add_eq_derive(PlannerInfo *root, EquivalenceClass *ec, @@ -76,7 +76,7 @@ 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_eclass_child_members_to_iterator(EquivalenceAllMemberIterator *it, +static void add_eclass_child_members_to_iterator(EquivalenceMemberIterator *it, PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *child_rel); @@ -280,7 +280,8 @@ process_equivalence(PlannerInfo *root, { EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2); - Assert(!cur_em->em_is_child); /* no children yet */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); /* * Match constants only within the same JoinDomain (see @@ -388,8 +389,8 @@ process_equivalence(PlannerInfo *root, else if (ec1) { /* Case 3: add item2 to ec1 */ - em2 = add_parent_eq_member(ec1, item2, item2_relids, - jdomain, item2_type); + em2 = add_eq_member(ec1, item2, item2_relids, + jdomain, item2_type); ec1->ec_min_security = Min(ec1->ec_min_security, restrictinfo->security_level); ec1->ec_max_security = Max(ec1->ec_max_security, @@ -406,8 +407,8 @@ process_equivalence(PlannerInfo *root, else if (ec2) { /* Case 3: add item1 to ec2 */ - em1 = add_parent_eq_member(ec2, item1, item1_relids, - jdomain, item1_type); + em1 = add_eq_member(ec2, item1, item1_relids, + jdomain, item1_type); ec2->ec_min_security = Min(ec2->ec_min_security, restrictinfo->security_level); ec2->ec_max_security = Max(ec2->ec_max_security, @@ -439,10 +440,10 @@ process_equivalence(PlannerInfo *root, ec->ec_min_security = restrictinfo->security_level; ec->ec_max_security = restrictinfo->security_level; ec->ec_merged = NULL; - em1 = add_parent_eq_member(ec, item1, item1_relids, - jdomain, item1_type); - em2 = add_parent_eq_member(ec, item2, item2_relids, - jdomain, item2_type); + em1 = add_eq_member(ec, item1, item1_relids, + jdomain, item1_type); + em2 = add_eq_member(ec, item2, item2_relids, + jdomain, item2_type); root->eq_classes = lappend(root->eq_classes, ec); @@ -576,7 +577,7 @@ make_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, } /* - * add_parent_eq_member - build a new parent EquivalenceMember and add it to an EC + * add_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 @@ -585,8 +586,8 @@ make_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, * to see how to add child members. */ static EquivalenceMember * -add_parent_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, - JoinDomain *jdomain, Oid datatype) +add_eq_member(EquivalenceClass *ec, Expr *expr, Relids relids, + JoinDomain *jdomain, Oid datatype) { EquivalenceMember *em = make_eq_member(ec, expr, relids, jdomain, NULL, datatype); @@ -821,7 +822,7 @@ get_eclass_for_sort_expr(PlannerInfo *root, foreach(lc1, root->eq_classes) { EquivalenceClass *cur_ec = (EquivalenceClass *) lfirst(lc1); - EquivalenceAllMemberIterator it; + EquivalenceMemberIterator it; EquivalenceMember *cur_em; /* @@ -837,8 +838,8 @@ get_eclass_for_sort_expr(PlannerInfo *root, if (!equal(opfamilies, cur_ec->ec_opfamilies)) continue; - setup_eclass_all_member_iterator_for_relids(&it, root, cur_ec, rel); - while ((cur_em = eclass_all_member_iterator_for_relids_next(&it)) != NULL) + setup_eclass_member_iterator_with_children(&it, root, cur_ec, rel); + while ((cur_em = eclass_member_iterator_next(&it)) != NULL) { /* * Ignore child members unless they match the request. @@ -858,7 +859,7 @@ get_eclass_for_sort_expr(PlannerInfo *root, equal(expr, cur_em->em_expr)) return cur_ec; /* Match! */ } - dispose_eclass_all_member_iterator_for_relids(&it); + dispose_eclass_member_iterator(&it); } /* No match; does caller want a NULL result? */ @@ -895,14 +896,14 @@ get_eclass_for_sort_expr(PlannerInfo *root, */ expr_relids = pull_varnos(root, (Node *) expr); - newem = add_parent_eq_member(newec, copyObject(expr), expr_relids, - jdomain, opcintype); + newem = add_eq_member(newec, copyObject(expr), expr_relids, + jdomain, opcintype); /* - * add_parent_eq_member doesn't check for volatile functions, - * set-returning functions, aggregates, or window functions, but such - * could appear in sort expressions; so we have to check whether its - * const-marking was correct. + * add_eq_member doesn't check for volatile functions, set-returning + * functions, aggregates, or window functions, but such could appear in + * sort expressions; so we have to check whether its const-marking was + * correct. */ if (newec->ec_has_const) { @@ -970,15 +971,15 @@ find_ec_member_matching_expr(PlannerInfo *root, EquivalenceClass *ec, Expr *expr, Relids relids) { - EquivalenceAllMemberIterator it; + EquivalenceMemberIterator it; EquivalenceMember *em; /* We ignore binary-compatible relabeling on both ends */ while (expr && IsA(expr, RelabelType)) expr = ((RelabelType *) expr)->arg; - setup_eclass_all_member_iterator_for_relids(&it, root, ec, relids); - while ((em = eclass_all_member_iterator_for_relids_next(&it)) != NULL) + setup_eclass_member_iterator_with_children(&it, root, ec, relids); + while ((em = eclass_member_iterator_next(&it)) != NULL) { Expr *emexpr; @@ -1006,7 +1007,7 @@ find_ec_member_matching_expr(PlannerInfo *root, EquivalenceClass *ec, if (equal(emexpr, expr)) return em; } - dispose_eclass_all_member_iterator_for_relids(&it); + dispose_eclass_member_iterator(&it); return NULL; } @@ -1049,7 +1050,7 @@ find_computable_ec_member(PlannerInfo *root, bool require_parallel_safe) { List *exprvars; - EquivalenceAllMemberIterator it; + EquivalenceMemberIterator it; EquivalenceMember *em; /* @@ -1064,8 +1065,8 @@ find_computable_ec_member(PlannerInfo *root, PVC_INCLUDE_PLACEHOLDERS | PVC_INCLUDE_CONVERTROWTYPES); - setup_eclass_all_member_iterator_for_relids(&it, root, ec, relids); - while ((em = eclass_all_member_iterator_for_relids_next(&it)) != NULL) + setup_eclass_member_iterator_with_children(&it, root, ec, relids); + while ((em = eclass_member_iterator_next(&it)) != NULL) { List *emvars; ListCell *lc2; @@ -1110,7 +1111,7 @@ find_computable_ec_member(PlannerInfo *root, return em; /* found usable expression */ } - dispose_eclass_all_member_iterator_for_relids(&it); + dispose_eclass_member_iterator(&it); return NULL; } @@ -1373,7 +1374,8 @@ generate_base_implied_equalities_const(PlannerInfo *root, Oid eq_op; RestrictInfo *rinfo; - Assert(!cur_em->em_is_child); /* no children yet */ + Assert(!cur_em->em_is_child); /* Child members should not exist in + * ec_members */ if (cur_em == const_em) continue; eq_op = select_equality_operator(ec, @@ -1443,7 +1445,8 @@ generate_base_implied_equalities_no_const(PlannerInfo *root, EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc); int relid; - Assert(!cur_em->em_is_child); /* no children yet */ + Assert(!cur_em->em_is_child); /* Child members should not exist in + * ec_members */ if (!bms_get_singleton_member(cur_em->em_relids, &relid)) continue; Assert(relid < root->simple_rel_array_size); @@ -1777,7 +1780,7 @@ generate_join_implied_equalities_normal(PlannerInfo *root, List *new_members = NIL; List *outer_members = NIL; List *inner_members = NIL; - EquivalenceAllMemberIterator it; + EquivalenceMemberIterator it; EquivalenceMember *cur_em; /* @@ -1789,8 +1792,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_all_member_iterator_for_relids(&it, root, ec, join_relids); - while ((cur_em = eclass_all_member_iterator_for_relids_next(&it)) != NULL) + setup_eclass_member_iterator_with_children(&it, root, ec, join_relids); + while ((cur_em = eclass_member_iterator_next(&it)) != NULL) { /* * We don't need to check explicitly for child EC members. This test @@ -1807,7 +1810,7 @@ generate_join_implied_equalities_normal(PlannerInfo *root, else new_members = lappend(new_members, cur_em); } - dispose_eclass_all_member_iterator_for_relids(&it); + dispose_eclass_member_iterator(&it); /* * First, select the joinclause if needed. We can equate any one outer @@ -2406,7 +2409,8 @@ reconsider_outer_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo, { EquivalenceMember *cur_em = (EquivalenceMember *) lfirst(lc2); - Assert(!cur_em->em_is_child); /* no children yet */ + Assert(!cur_em->em_is_child); /* Child members should not exist + * in ec_members */ if (equal(outervar, cur_em->em_expr)) { match = true; @@ -2533,7 +2537,8 @@ reconsider_full_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo) foreach(lc2, cur_ec->ec_members) { coal_em = (EquivalenceMember *) lfirst(lc2); - Assert(!coal_em->em_is_child); /* no children yet */ + Assert(!coal_em->em_is_child); /* Child members should not exist + * in ec_members */ if (IsA(coal_em->em_expr, CoalesceExpr)) { CoalesceExpr *cexpr = (CoalesceExpr *) coal_em->em_expr; @@ -2630,7 +2635,6 @@ reconsider_full_join_clause(PlannerInfo *root, OuterJoinClauseInfo *ojcinfo) if (matchleft && matchright) { cur_ec->ec_members = list_delete_nth_cell(cur_ec->ec_members, coal_idx); - Assert(!bms_is_empty(coal_em->em_relids)); return true; } @@ -2752,8 +2756,8 @@ exprs_known_equal(PlannerInfo *root, Node *item1, Node *item2, Oid opfamily) { EquivalenceMember *em = (EquivalenceMember *) lfirst(lc2); - /* Child members should not exist in ec_members */ - Assert(!em->em_is_child); + Assert(!em->em_is_child); /* Child members should not exist in + * ec_members */ if (equal(item1, em->em_expr)) item1member = true; else if (equal(item2, em->em_expr)) @@ -2957,16 +2961,8 @@ add_child_rel_equivalences(PlannerInfo *root, if (cur_em->em_is_const) continue; /* ignore consts here */ - /* - * We consider only original EC members here, not - * already-transformed child members. Otherwise, if some original - * member expression references more than one appendrel, we'd get - * an O(N^2) explosion of useless derived expressions for - * combinations of children. (But add_child_join_rel_equivalences - * may add targeted combinations for partitionwise-join purposes.) - */ - Assert(!cur_em->em_is_child); /* Child members should not exist - * in ec_members */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); /* * Consider only members that reference and can be computed at @@ -3045,7 +3041,6 @@ add_child_join_rel_equivalences(PlannerInfo *root, Relids child_relids = child_joinrel->relids; Bitmapset *matching_ecs; MemoryContext oldcontext; - ListCell *lc; int i; Assert(IS_JOIN_REL(child_joinrel) && IS_JOIN_REL(parent_joinrel)); @@ -3067,6 +3062,7 @@ add_child_join_rel_equivalences(PlannerInfo *root, while ((i = bms_next_member(matching_ecs, i)) >= 0) { EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i); + ListCell *lc; /* * If this EC contains a volatile expression, then generating child @@ -3086,12 +3082,8 @@ add_child_join_rel_equivalences(PlannerInfo *root, if (cur_em->em_is_const) continue; /* ignore consts here */ - /* - * We consider only original EC members here, not - * already-transformed child members. - */ - Assert(!cur_em->em_is_child); /* Child members should not exist - * in ec_members */ + /* Child members should not exist in ec_members */ + Assert(!cur_em->em_is_child); /* * We may ignore expressions that reference a single baserel, @@ -3159,7 +3151,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 - * EquivalenceAllMemberIterator. Since the iterator needs + * EquivalenceMemberIterator. Since the iterator needs * EquivalenceMembers whose em_relids has child relations, * skipping the update of this inverted index allows for * faster iteration. @@ -3266,8 +3258,8 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, } /* - * setup_eclass_all_member_iterator_for_relids - * Setup an EquivalenceAllMemberIterator 'it' to iterate over all parent + * setup_eclass_member_iterator_with_children + * Setup an EquivalenceMemberIterator 'it' to iterate over all parent * EquivalenceMembers and child members associated with the given 'ec' that * are relevant to the specified 'relids'. * @@ -3280,7 +3272,7 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, * 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(). + * dispose_eclass_member_iterator(). * * Parameters: * root - The PlannerInfo context. @@ -3288,10 +3280,10 @@ add_setop_child_rel_equivalences(PlannerInfo *root, RelOptInfo *child_rel, * relids - The Relids used to filter for relevant child members. */ void -setup_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it, - PlannerInfo *root, - EquivalenceClass *ec, - Relids relids) +setup_eclass_member_iterator_with_children(EquivalenceMemberIterator *it, + PlannerInfo *root, + EquivalenceClass *ec, + Relids relids) { Bitmapset *matching_indexes; int i; @@ -3300,7 +3292,7 @@ setup_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it, * Initialize the iterator. */ it->index = -1; - it->modified = false; + it->list_is_copy = false; it->ec_members = ec->ec_members; /* @@ -3321,13 +3313,13 @@ setup_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it, * 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. + * whose em_relids is a subset of the given '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 '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 @@ -3416,10 +3408,10 @@ setup_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it, * the iterator from RelOptInfo. * * This function is expected to be called only from - * setup_eclass_all_member_iterator_for_relids(). + * setup_eclass_member_iterator_with_children(). */ static void -add_eclass_child_members_to_iterator(EquivalenceAllMemberIterator *it, +add_eclass_child_members_to_iterator(EquivalenceMemberIterator *it, PlannerInfo *root, EquivalenceClass *ec, RelOptInfo *child_rel) @@ -3438,10 +3430,10 @@ add_eclass_child_members_to_iterator(EquivalenceAllMemberIterator *it, * If this is the first time the iterator's list has been modified, we * need to make a copy of it. */ - if (!it->modified) + if (!it->list_is_copy) { it->ec_members = list_copy(it->ec_members); - it->modified = true; + it->list_is_copy = true; } /* Add this child EquivalenceMember to the list */ @@ -3450,13 +3442,13 @@ add_eclass_child_members_to_iterator(EquivalenceAllMemberIterator *it, } /* - * 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 + * eclass_member_iterator_next + * Get a next EquivalenceMember from an EquivalenceMemberIterator 'it' + * that was setup by setup_eclass_member_iterator_with_children(). NULL is * returned if there are no members left. */ EquivalenceMember * -eclass_all_member_iterator_for_relids_next(EquivalenceAllMemberIterator *it) +eclass_member_iterator_next(EquivalenceMemberIterator *it) { if (++it->index < list_length(it->ec_members)) return list_nth_node(EquivalenceMember, it->ec_members, it->index); @@ -3464,17 +3456,17 @@ eclass_all_member_iterator_for_relids_next(EquivalenceAllMemberIterator *it) } /* - * dispose_eclass_all_member_iterator_for_relids + * dispose_eclass_member_iterator * Free any memory allocated by the iterator. */ void -dispose_eclass_all_member_iterator_for_relids(EquivalenceAllMemberIterator *it) +dispose_eclass_member_iterator(EquivalenceMemberIterator *it) { /* * XXX Should we use list_free()? I decided to use this style to take * advantage of speculative execution. */ - if (unlikely(it->modified)) + if (unlikely(it->list_is_copy)) pfree(it->ec_members); } @@ -3532,7 +3524,7 @@ generate_implied_equalities_for_column(PlannerInfo *root, EquivalenceClass *cur_ec = (EquivalenceClass *) list_nth(root->eq_classes, i); EquivalenceMember *cur_em; ListCell *lc2; - EquivalenceAllMemberIterator it; + EquivalenceMemberIterator it; /* Sanity check eclass_indexes only contain ECs for rel */ Assert(is_child_rel || bms_is_subset(rel->relids, cur_ec->ec_relids)); @@ -3554,14 +3546,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_all_member_iterator_for_relids(&it, root, cur_ec, rel->relids); - while ((cur_em = eclass_all_member_iterator_for_relids_next(&it)) != NULL) + setup_eclass_member_iterator_with_children(&it, root, cur_ec, rel->relids); + while ((cur_em = eclass_member_iterator_next(&it)) != NULL) { if (bms_equal(cur_em->em_relids, rel->relids) && callback(root, rel, cur_ec, cur_em, callback_arg)) break; } - dispose_eclass_all_member_iterator_for_relids(&it); + dispose_eclass_member_iterator(&it); if (!cur_em) continue; diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 38f7322caf9..c206f260633 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; - EquivalenceAllMemberIterator it; + EquivalenceMemberIterator 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_all_member_iterator_for_relids(&it, root, pathkey->pk_eclass, - index->rel->relids); - while ((member = eclass_all_member_iterator_for_relids_next(&it)) != NULL) + setup_eclass_member_iterator_with_children(&it, root, pathkey->pk_eclass, + index->rel->relids); + while ((member = eclass_member_iterator_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_all_member_iterator_for_relids(&it); + dispose_eclass_member_iterator(&it); /* * Return the matches found so far when this pathkey couldn't be diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index eff5d93aa3a..163923072df 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -6201,6 +6201,7 @@ make_incrementalsort(Plan *lefttree, int numCols, int nPresortedCols, * adjusts the plan targetlist if needed to add resjunk sort columns. * * Input parameters: + * 'root' is the PlannerInfo context * 'lefttree' is the plan node which yields input tuples * 'pathkeys' is the list of pathkeys by which the result is to be sorted * 'relids' identifies the child relation being sorted, if any @@ -6411,6 +6412,7 @@ prepare_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, * make_sort_from_pathkeys * Create sort plan to sort according to given pathkeys * + * 'root' is the PlannerInfo context * 'lefttree' is the node which yields input tuples * 'pathkeys' is the list of pathkeys by which the result is to be sorted * 'relids' is the set of relations required by prepare_sort_from_pathkeys() @@ -6446,6 +6448,7 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys, * make_incrementalsort_from_pathkeys * Create sort plan to sort according to given pathkeys * + * 'root' is the PlannerInfo context * 'lefttree' is the node which yields input tuples * 'pathkeys' is the list of pathkeys by which the result is to be sorted * 'relids' is the set of relations required by prepare_sort_from_pathkeys() diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c index 8dc51353791..aa37dda82b8 100644 --- a/src/backend/optimizer/util/relnode.c +++ b/src/backend/optimizer/util/relnode.c @@ -119,6 +119,11 @@ setup_simple_rel_arrays(PlannerInfo *root) root->simple_rte_array[rti++] = rte; } + /* + * eclass_indexes_array is always needed, even if there are no + * AppendRelInfos, because it stores indexes for RestrictInfos on base + * rels. + */ root->eclass_indexes_array = (EquivalenceClassIndexes *) palloc0(size * sizeof(EquivalenceClassIndexes)); @@ -240,6 +245,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent) rel->subplan_params = NIL; rel->rel_parallel_workers = -1; /* set up in get_relation_info */ rel->amflags = 0; + rel->join_rel_list_index = -1; rel->eclass_child_members = NIL; rel->serverid = InvalidOid; if (rte->rtekind == RTE_RELATION) @@ -633,14 +639,14 @@ set_foreign_rel_properties(RelOptInfo *joinrel, RelOptInfo *outer_rel, static void add_join_rel(PlannerInfo *root, RelOptInfo *joinrel) { - /* GEQO requires us to append the new joinrel to the end of the list! */ - root->join_rel_list = lappend(root->join_rel_list, joinrel); - /* * Store the index of this joinrel to use in * add_child_join_rel_equivalences(). */ - joinrel->join_rel_list_index = list_length(root->join_rel_list) - 1; + joinrel->join_rel_list_index = list_length(root->join_rel_list); + + /* GEQO requires us to append the new joinrel to the end of the list! */ + root->join_rel_list = lappend(root->join_rel_list, joinrel); /* store it into the auxiliary hashtable if there is one. */ if (root->join_rel_hash) @@ -754,6 +760,7 @@ build_join_rel(PlannerInfo *root, joinrel->subplan_params = NIL; joinrel->rel_parallel_workers = -1; joinrel->amflags = 0; + joinrel->join_rel_list_index = -1; joinrel->eclass_child_members = NIL; joinrel->serverid = InvalidOid; joinrel->userid = InvalidOid; @@ -942,6 +949,7 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel, joinrel->subroot = NULL; joinrel->subplan_params = NIL; joinrel->amflags = 0; + joinrel->join_rel_list_index = -1; joinrel->eclass_child_members = NIL; joinrel->serverid = InvalidOid; joinrel->userid = InvalidOid; @@ -1505,7 +1513,8 @@ fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids) upperrel->cheapest_total_path = NULL; upperrel->cheapest_unique_path = NULL; upperrel->cheapest_parameterized_paths = NIL; - upperrel->eclass_child_members = NIL; /* XXX Is this required? */ + upperrel->join_rel_list_index = -1; + upperrel->eclass_child_members = NIL; root->upper_rels[kind] = lappend(root->upper_rels[kind], upperrel); diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 899165b20d8..c7cf1328d7a 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -276,8 +276,8 @@ struct PlannerInfo /* * eclass_indexes_array is the same length as simple_rel_array and holds - * the indexes of the corresponding rels for faster lookups of - * RestrictInfo. See the EquivalenceClass comment for more details. + * the indexes of the corresponding rels for faster EquivalenceMember + * lookups. See the EquivalenceClass comment for more details. */ struct EquivalenceClassIndexes *eclass_indexes_array pg_node_attr(read_write_ignore); @@ -1003,7 +1003,7 @@ typedef struct RelOptInfo * information about a join rel */ /* index in root->join_rel_list of this rel */ - Index join_rel_list_index; + int join_rel_list_index; /* * EquivalenceMembers referencing this rel @@ -1431,9 +1431,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 EquivalenceAllMemberIterator. See + * lookup child EquivalenceMembers, we use EquivalenceMemberIterator. See * its comment for usage. The approach to lookup child members quickly is - * described as setup_eclass_all_member_iterator_for_relids() comment. + * described as setup_eclass_member_iterator_with_children() comment. * * At various locations in the query planner, we must search for source and * derived RestrictInfos regarding a given EquivalenceClass. For the common @@ -1533,9 +1533,9 @@ typedef struct EquivalenceMember } EquivalenceMember; /* - * EquivalenceAllMemberIterator + * EquivalenceMemberIterator * - * EquivalenceAllMemberIterator is designed to iterate over all parent + * EquivalenceMemberIterator 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. @@ -1551,23 +1551,23 @@ typedef struct EquivalenceMember * PlannerInfo *root = given; * EquivalenceClass *ec = given; * Relids rel = given; - * EquivalenceAllMemberIterator it; + * EquivalenceMemberIterator it; * EquivalenceMember *em; * - * setup_eclass_all_member_iterator_for_relids(&it, root, ec, rel); - * while ((em = eclass_all_member_iterator_for_relids_next(&it)) != NULL) + * setup_eclass_member_iterator_with_children(&it, root, ec, rel); + * while ((em = eclass_member_iterator_next(&it)) != NULL) * { * use em ...; * } - * dispose_eclass_all_member_iterator_for_relids(&it); + * dispose_eclass_member_iterator(&it); * ----- */ typedef struct { int index; /* current index within 'ec_members'. */ - bool modified; /* is 'ec_members' a newly allocated one? */ + bool list_is_copy; /* is 'ec_members' a newly allocated one? */ List *ec_members; /* parent and child members */ -} EquivalenceAllMemberIterator; +} EquivalenceMemberIterator; /* * RestrictInfoIterator diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index e8706b2774c..13c739965ba 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_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 void setup_eclass_member_iterator_with_children(EquivalenceMemberIterator *it, + PlannerInfo *root, + EquivalenceClass *ec, + Relids relids); +extern EquivalenceMember *eclass_member_iterator_next(EquivalenceMemberIterator *it); +extern void dispose_eclass_member_iterator(EquivalenceMemberIterator *it); extern List *generate_implied_equalities_for_column(PlannerInfo *root, RelOptInfo *rel, ec_matches_callback_type callback, diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index 85b330df4dd..d2fc11ae19c 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -699,10 +699,10 @@ EphemeralNamedRelation EphemeralNamedRelationData EphemeralNamedRelationMetadata EphemeralNamedRelationMetadataData -EquivalenceAllMemberIterator EquivalenceClass EquivalenceClassIndexes EquivalenceMember +EquivalenceMemberIterator ErrorContextCallback ErrorData ErrorSaveContext