diff options
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 16 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 7 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 52 | ||||
-rw-r--r-- | src/backend/optimizer/path/joinpath.c | 103 | ||||
-rw-r--r-- | src/backend/optimizer/path/joinrels.c | 10 | ||||
-rw-r--r-- | src/backend/optimizer/path/orindxpath.c | 2 | ||||
-rw-r--r-- | src/backend/optimizer/path/tidpath.c | 3 |
7 files changed, 121 insertions, 72 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 4b8a73d60f4..bfd3809a007 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -386,8 +386,7 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) /* * We don't support pushing join clauses into the quals of a seqscan, but * it could still have required parameterization due to LATERAL refs in - * its tlist. (That can only happen if the seqscan is on a relation - * pulled up out of a UNION ALL appendrel.) + * its tlist. */ required_outer = rel->lateral_relids; @@ -550,8 +549,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, * Note: the resulting childrel->reltargetlist may contain arbitrary * expressions, which otherwise would not occur in a reltargetlist. * Code that might be looking at an appendrel child must cope with - * such. Note in particular that "arbitrary expression" can include - * "Var belonging to another relation", due to LATERAL references. + * such. (Normally, a reltargetlist would only include Vars and + * PlaceHolderVars.) */ childrel->joininfo = (List *) adjust_appendrel_attrs(root, @@ -1355,8 +1354,7 @@ set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) /* * We don't support pushing join clauses into the quals of a CTE scan, but * it could still have required parameterization due to LATERAL refs in - * its tlist. (That can only happen if the CTE scan is on a relation - * pulled up out of a UNION ALL appendrel.) + * its tlist. */ required_outer = rel->lateral_relids; @@ -1408,10 +1406,8 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) /* * We don't support pushing join clauses into the quals of a worktable * scan, but it could still have required parameterization due to LATERAL - * refs in its tlist. (That can only happen if the worktable scan is on a - * relation pulled up out of a UNION ALL appendrel. I'm not sure this is - * actually possible given the restrictions on recursive references, but - * it's easy enough to support.) + * refs in its tlist. (I'm not sure this is actually possible given the + * restrictions on recursive references, but it's easy enough to support.) */ required_outer = rel->lateral_relids; diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 3507f18007e..a2cc6979594 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -3935,10 +3935,9 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel) /* * Ordinarily, a Var in a rel's reltargetlist must belong to that rel; - * but there are corner cases involving LATERAL references in - * appendrel members where that isn't so (see set_append_rel_size()). - * If the Var has the wrong varno, fall through to the generic case - * (it doesn't seem worth the trouble to be any smarter). + * but there are corner cases involving LATERAL references where that + * isn't so. If the Var has the wrong varno, fall through to the + * generic case (it doesn't seem worth the trouble to be any smarter). */ if (IsA(node, Var) && ((Var *) node)->varno == rel->relid) diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 65eb344cde4..606734a1221 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -141,12 +141,10 @@ static void match_restriction_clauses_to_index(RelOptInfo *rel, IndexClauseSet *clauseset); static void match_join_clauses_to_index(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, - Relids lateral_referencers, IndexClauseSet *clauseset, List **joinorclauses); static void match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, - Relids lateral_referencers, IndexClauseSet *clauseset); static void match_clauses_to_index(IndexOptInfo *index, List *clauses, @@ -220,14 +218,14 @@ static Const *string_to_const(const char *str, Oid datatype); * * Note: check_partial_indexes() must have been run previously for this rel. * - * Note: in corner cases involving LATERAL appendrel children, it's possible - * that rel->lateral_relids is nonempty. Currently, we include lateral_relids - * into the parameterization reported for each path, but don't take it into - * account otherwise. The fact that any such rels *must* be available as - * parameter sources perhaps should influence our choices of index quals ... - * but for now, it doesn't seem worth troubling over. In particular, comments - * below about "unparameterized" paths should be read as meaning - * "unparameterized so far as the indexquals are concerned". + * Note: in cases involving LATERAL references in the relation's tlist, it's + * possible that rel->lateral_relids is nonempty. Currently, we include + * lateral_relids into the parameterization reported for each path, but don't + * take it into account otherwise. The fact that any such rels *must* be + * available as parameter sources perhaps should influence our choices of + * index quals ... but for now, it doesn't seem worth troubling over. + * In particular, comments below about "unparameterized" paths should be read + * as meaning "unparameterized so far as the indexquals are concerned". */ void create_index_paths(PlannerInfo *root, RelOptInfo *rel) @@ -236,7 +234,6 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) List *bitindexpaths; List *bitjoinpaths; List *joinorclauses; - Relids lateral_referencers; IndexClauseSet rclauseset; IndexClauseSet jclauseset; IndexClauseSet eclauseset; @@ -246,23 +243,6 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) if (rel->indexlist == NIL) return; - /* - * If there are any rels that have LATERAL references to this one, we - * cannot use join quals referencing them as index quals for this one, - * since such rels would have to be on the inside not the outside of a - * nestloop join relative to this one. Create a Relids set listing all - * such rels, for use in checks of potential join clauses. - */ - lateral_referencers = NULL; - foreach(lc, root->lateral_info_list) - { - LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc); - - if (bms_is_member(rel->relid, ljinfo->lateral_lhs)) - lateral_referencers = bms_add_member(lateral_referencers, - ljinfo->lateral_rhs); - } - /* Bitmap paths are collected and then dealt with at the end */ bitindexpaths = bitjoinpaths = joinorclauses = NIL; @@ -303,7 +283,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) * EquivalenceClasses. Also, collect join OR clauses for later. */ MemSet(&jclauseset, 0, sizeof(jclauseset)); - match_join_clauses_to_index(root, rel, index, lateral_referencers, + match_join_clauses_to_index(root, rel, index, &jclauseset, &joinorclauses); /* @@ -311,7 +291,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) * the index. */ MemSet(&eclauseset, 0, sizeof(eclauseset)); - match_eclass_clauses_to_index(root, index, lateral_referencers, + match_eclass_clauses_to_index(root, index, &eclauseset); /* @@ -1957,7 +1937,6 @@ match_restriction_clauses_to_index(RelOptInfo *rel, IndexOptInfo *index, static void match_join_clauses_to_index(PlannerInfo *root, RelOptInfo *rel, IndexOptInfo *index, - Relids lateral_referencers, IndexClauseSet *clauseset, List **joinorclauses) { @@ -1969,11 +1948,7 @@ match_join_clauses_to_index(PlannerInfo *root, RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); /* Check if clause can be moved to this rel */ - if (!join_clause_is_movable_to(rinfo, rel->relid)) - continue; - - /* Not useful if it conflicts with any LATERAL references */ - if (bms_overlap(rinfo->clause_relids, lateral_referencers)) + if (!join_clause_is_movable_to(rinfo, rel)) continue; /* Potentially usable, so see if it matches the index or is an OR */ @@ -1991,7 +1966,6 @@ match_join_clauses_to_index(PlannerInfo *root, */ static void match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, - Relids lateral_referencers, IndexClauseSet *clauseset) { int indexcol; @@ -2012,7 +1986,7 @@ match_eclass_clauses_to_index(PlannerInfo *root, IndexOptInfo *index, index->rel, ec_member_matches_indexcol, (void *) &arg, - lateral_referencers); + index->rel->lateral_referencers); /* * We have to check whether the results actually do match the index, @@ -2644,7 +2618,7 @@ check_partial_indexes(PlannerInfo *root, RelOptInfo *rel) RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc); /* Check if clause can be moved to this rel */ - if (!join_clause_is_movable_to(rinfo, rel->relid)) + if (!join_clause_is_movable_to(rinfo, rel)) continue; clauselist = lappend(clauselist, rinfo); diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index d6050a616c7..5b477e52d3f 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -29,19 +29,19 @@ static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, List *mergeclause_list, JoinType jointype, SpecialJoinInfo *sjinfo, - Relids param_source_rels); + Relids param_source_rels, Relids extra_lateral_rels); static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, List *mergeclause_list, JoinType jointype, SpecialJoinInfo *sjinfo, SemiAntiJoinFactors *semifactors, - Relids param_source_rels); + Relids param_source_rels, Relids extra_lateral_rels); static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, List *restrictlist, JoinType jointype, SpecialJoinInfo *sjinfo, SemiAntiJoinFactors *semifactors, - Relids param_source_rels); + Relids param_source_rels, Relids extra_lateral_rels); static List *select_mergejoin_clauses(PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, @@ -87,6 +87,7 @@ add_paths_to_joinrel(PlannerInfo *root, bool mergejoin_allowed = true; SemiAntiJoinFactors semifactors; Relids param_source_rels = NULL; + Relids extra_lateral_rels = NULL; ListCell *lc; /* @@ -162,20 +163,58 @@ add_paths_to_joinrel(PlannerInfo *root, { LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(lc); - if (bms_is_member(ljinfo->lateral_rhs, joinrel->relids)) + if (bms_is_subset(ljinfo->lateral_rhs, joinrel->relids)) param_source_rels = bms_join(param_source_rels, bms_difference(ljinfo->lateral_lhs, joinrel->relids)); } /* + * Another issue created by LATERAL references is that PlaceHolderVars + * that need to be computed at this join level might contain lateral + * references to rels not in the join, meaning that the paths for the join + * would need to be marked as parameterized by those rels, independently + * of all other considerations. Set extra_lateral_rels to the set of such + * rels. This will not affect our decisions as to which paths to + * generate; we merely add these rels to their required_outer sets. + */ + foreach(lc, root->placeholder_list) + { + PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); + + /* PHVs without lateral refs can be skipped over quickly */ + if (phinfo->ph_lateral == NULL) + continue; + /* Is it due to be evaluated at this join, and not in either input? */ + if (bms_is_subset(phinfo->ph_eval_at, joinrel->relids) && + !bms_is_subset(phinfo->ph_eval_at, outerrel->relids) && + !bms_is_subset(phinfo->ph_eval_at, innerrel->relids)) + { + /* Yes, remember its lateral rels */ + extra_lateral_rels = bms_add_members(extra_lateral_rels, + phinfo->ph_lateral); + } + } + + /* + * Make sure extra_lateral_rels doesn't list anything within the join, and + * that it's NULL if empty. (This allows us to use bms_add_members to add + * it to required_outer below, while preserving the property that + * required_outer is exactly NULL if empty.) + */ + extra_lateral_rels = bms_del_members(extra_lateral_rels, joinrel->relids); + if (bms_is_empty(extra_lateral_rels)) + extra_lateral_rels = NULL; + + /* * 1. Consider mergejoin paths where both relations must be explicitly * sorted. Skip this if we can't mergejoin. */ if (mergejoin_allowed) sort_inner_and_outer(root, joinrel, outerrel, innerrel, restrictlist, mergeclause_list, jointype, - sjinfo, param_source_rels); + sjinfo, + param_source_rels, extra_lateral_rels); /* * 2. Consider paths where the outer relation need not be explicitly @@ -187,7 +226,8 @@ add_paths_to_joinrel(PlannerInfo *root, if (mergejoin_allowed) match_unsorted_outer(root, joinrel, outerrel, innerrel, restrictlist, mergeclause_list, jointype, - sjinfo, &semifactors, param_source_rels); + sjinfo, &semifactors, + param_source_rels, extra_lateral_rels); #ifdef NOT_USED @@ -205,7 +245,8 @@ add_paths_to_joinrel(PlannerInfo *root, if (mergejoin_allowed) match_unsorted_inner(root, joinrel, outerrel, innerrel, restrictlist, mergeclause_list, jointype, - sjinfo, &semifactors, param_source_rels); + sjinfo, &semifactors, + param_source_rels, extra_lateral_rels); #endif /* @@ -216,7 +257,8 @@ add_paths_to_joinrel(PlannerInfo *root, if (enable_hashjoin || jointype == JOIN_FULL) hash_inner_and_outer(root, joinrel, outerrel, innerrel, restrictlist, jointype, - sjinfo, &semifactors, param_source_rels); + sjinfo, &semifactors, + param_source_rels, extra_lateral_rels); } /* @@ -231,6 +273,7 @@ try_nestloop_path(PlannerInfo *root, SpecialJoinInfo *sjinfo, SemiAntiJoinFactors *semifactors, Relids param_source_rels, + Relids extra_lateral_rels, Path *outer_path, Path *inner_path, List *restrict_clauses, @@ -254,6 +297,12 @@ try_nestloop_path(PlannerInfo *root, } /* + * Independently of that, add parameterization needed for any + * PlaceHolderVars that need to be computed at the join. + */ + required_outer = bms_add_members(required_outer, extra_lateral_rels); + + /* * Do a precheck to quickly eliminate obviously-inferior paths. We * calculate a cheap lower bound on the path's cost and then use * add_path_precheck() to see if the path is clearly going to be dominated @@ -301,6 +350,7 @@ try_mergejoin_path(PlannerInfo *root, JoinType jointype, SpecialJoinInfo *sjinfo, Relids param_source_rels, + Relids extra_lateral_rels, Path *outer_path, Path *inner_path, List *restrict_clauses, @@ -327,6 +377,12 @@ try_mergejoin_path(PlannerInfo *root, } /* + * Independently of that, add parameterization needed for any + * PlaceHolderVars that need to be computed at the join. + */ + required_outer = bms_add_members(required_outer, extra_lateral_rels); + + /* * If the given paths are already well enough ordered, we can skip doing * an explicit sort. */ @@ -383,6 +439,7 @@ try_hashjoin_path(PlannerInfo *root, SpecialJoinInfo *sjinfo, SemiAntiJoinFactors *semifactors, Relids param_source_rels, + Relids extra_lateral_rels, Path *outer_path, Path *inner_path, List *restrict_clauses, @@ -406,6 +463,12 @@ try_hashjoin_path(PlannerInfo *root, } /* + * Independently of that, add parameterization needed for any + * PlaceHolderVars that need to be computed at the join. + */ + required_outer = bms_add_members(required_outer, extra_lateral_rels); + + /* * See comments in try_nestloop_path(). Also note that hashjoin paths * never have any output pathkeys, per comments in create_hashjoin_path. */ @@ -483,6 +546,7 @@ clause_sides_match_join(RestrictInfo *rinfo, RelOptInfo *outerrel, * 'jointype' is the type of join to do * 'sjinfo' is extra info about the join for selectivity estimation * 'param_source_rels' are OK targets for parameterization of result paths + * 'extra_lateral_rels' are additional parameterization for result paths */ static void sort_inner_and_outer(PlannerInfo *root, @@ -493,7 +557,8 @@ sort_inner_and_outer(PlannerInfo *root, List *mergeclause_list, JoinType jointype, SpecialJoinInfo *sjinfo, - Relids param_source_rels) + Relids param_source_rels, + Relids extra_lateral_rels) { Path *outer_path; Path *inner_path; @@ -623,6 +688,7 @@ sort_inner_and_outer(PlannerInfo *root, jointype, sjinfo, param_source_rels, + extra_lateral_rels, outer_path, inner_path, restrictlist, @@ -668,6 +734,7 @@ sort_inner_and_outer(PlannerInfo *root, * 'sjinfo' is extra info about the join for selectivity estimation * 'semifactors' contains valid data if jointype is SEMI or ANTI * 'param_source_rels' are OK targets for parameterization of result paths + * 'extra_lateral_rels' are additional parameterization for result paths */ static void match_unsorted_outer(PlannerInfo *root, @@ -679,7 +746,8 @@ match_unsorted_outer(PlannerInfo *root, JoinType jointype, SpecialJoinInfo *sjinfo, SemiAntiJoinFactors *semifactors, - Relids param_source_rels) + Relids param_source_rels, + Relids extra_lateral_rels) { JoinType save_jointype = jointype; bool nestjoinOK; @@ -809,6 +877,7 @@ match_unsorted_outer(PlannerInfo *root, sjinfo, semifactors, param_source_rels, + extra_lateral_rels, outerpath, inner_cheapest_total, restrictlist, @@ -834,6 +903,7 @@ match_unsorted_outer(PlannerInfo *root, sjinfo, semifactors, param_source_rels, + extra_lateral_rels, outerpath, innerpath, restrictlist, @@ -848,6 +918,7 @@ match_unsorted_outer(PlannerInfo *root, sjinfo, semifactors, param_source_rels, + extra_lateral_rels, outerpath, matpath, restrictlist, @@ -903,6 +974,7 @@ match_unsorted_outer(PlannerInfo *root, jointype, sjinfo, param_source_rels, + extra_lateral_rels, outerpath, inner_cheapest_total, restrictlist, @@ -1001,6 +1073,7 @@ match_unsorted_outer(PlannerInfo *root, jointype, sjinfo, param_source_rels, + extra_lateral_rels, outerpath, innerpath, restrictlist, @@ -1046,6 +1119,7 @@ match_unsorted_outer(PlannerInfo *root, jointype, sjinfo, param_source_rels, + extra_lateral_rels, outerpath, innerpath, restrictlist, @@ -1080,6 +1154,7 @@ match_unsorted_outer(PlannerInfo *root, * 'sjinfo' is extra info about the join for selectivity estimation * 'semifactors' contains valid data if jointype is SEMI or ANTI * 'param_source_rels' are OK targets for parameterization of result paths + * 'extra_lateral_rels' are additional parameterization for result paths */ static void hash_inner_and_outer(PlannerInfo *root, @@ -1090,7 +1165,8 @@ hash_inner_and_outer(PlannerInfo *root, JoinType jointype, SpecialJoinInfo *sjinfo, SemiAntiJoinFactors *semifactors, - Relids param_source_rels) + Relids param_source_rels, + Relids extra_lateral_rels) { bool isouterjoin = IS_OUTER_JOIN(jointype); List *hashclauses; @@ -1164,6 +1240,7 @@ hash_inner_and_outer(PlannerInfo *root, sjinfo, semifactors, param_source_rels, + extra_lateral_rels, cheapest_total_outer, cheapest_total_inner, restrictlist, @@ -1183,6 +1260,7 @@ hash_inner_and_outer(PlannerInfo *root, sjinfo, semifactors, param_source_rels, + extra_lateral_rels, cheapest_total_outer, cheapest_total_inner, restrictlist, @@ -1195,6 +1273,7 @@ hash_inner_and_outer(PlannerInfo *root, sjinfo, semifactors, param_source_rels, + extra_lateral_rels, cheapest_startup_outer, cheapest_total_inner, restrictlist, @@ -1219,6 +1298,7 @@ hash_inner_and_outer(PlannerInfo *root, sjinfo, semifactors, param_source_rels, + extra_lateral_rels, cheapest_startup_outer, cheapest_total_inner, restrictlist, @@ -1256,6 +1336,7 @@ hash_inner_and_outer(PlannerInfo *root, sjinfo, semifactors, param_source_rels, + extra_lateral_rels, outerpath, innerpath, restrictlist, diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c index 819498a4281..d627f9e130c 100644 --- a/src/backend/optimizer/path/joinrels.c +++ b/src/backend/optimizer/path/joinrels.c @@ -526,7 +526,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, { LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l); - if (bms_is_member(ljinfo->lateral_rhs, rel2->relids) && + if (bms_is_subset(ljinfo->lateral_rhs, rel2->relids) && bms_overlap(ljinfo->lateral_lhs, rel1->relids)) { /* has to be implemented as nestloop with rel1 on left */ @@ -539,7 +539,7 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2, (reversed || match_sjinfo->jointype == JOIN_FULL)) return false; /* not implementable as nestloop */ } - if (bms_is_member(ljinfo->lateral_rhs, rel1->relids) && + if (bms_is_subset(ljinfo->lateral_rhs, rel1->relids) && bms_overlap(ljinfo->lateral_lhs, rel2->relids)) { /* has to be implemented as nestloop with rel2 on left */ @@ -829,10 +829,10 @@ have_join_order_restriction(PlannerInfo *root, { LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l); - if (bms_is_member(ljinfo->lateral_rhs, rel2->relids) && + if (bms_is_subset(ljinfo->lateral_rhs, rel2->relids) && bms_overlap(ljinfo->lateral_lhs, rel1->relids)) return true; - if (bms_is_member(ljinfo->lateral_rhs, rel1->relids) && + if (bms_is_subset(ljinfo->lateral_rhs, rel1->relids) && bms_overlap(ljinfo->lateral_lhs, rel2->relids)) return true; } @@ -928,7 +928,7 @@ has_join_restriction(PlannerInfo *root, RelOptInfo *rel) { LateralJoinInfo *ljinfo = (LateralJoinInfo *) lfirst(l); - if (bms_is_member(ljinfo->lateral_rhs, rel->relids) || + if (bms_is_subset(ljinfo->lateral_rhs, rel->relids) || bms_overlap(ljinfo->lateral_lhs, rel->relids)) return true; } diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c index e51e5c08b52..16f29d350fd 100644 --- a/src/backend/optimizer/path/orindxpath.c +++ b/src/backend/optimizer/path/orindxpath.c @@ -103,7 +103,7 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel) RestrictInfo *rinfo = (RestrictInfo *) lfirst(i); if (restriction_is_or_clause(rinfo) && - join_clause_is_movable_to(rinfo, rel->relid)) + join_clause_is_movable_to(rinfo, rel)) { /* * Use the generate_bitmap_or_paths() machinery to estimate the diff --git a/src/backend/optimizer/path/tidpath.c b/src/backend/optimizer/path/tidpath.c index f49d0f96d04..256856da35e 100644 --- a/src/backend/optimizer/path/tidpath.c +++ b/src/backend/optimizer/path/tidpath.c @@ -255,8 +255,7 @@ create_tidscan_paths(PlannerInfo *root, RelOptInfo *rel) /* * We don't support pushing join clauses into the quals of a tidscan, but * it could still have required parameterization due to LATERAL refs in - * its tlist. (That can only happen if the tidscan is on a relation - * pulled up out of a UNION ALL appendrel.) + * its tlist. */ required_outer = rel->lateral_relids; |