diff options
Diffstat (limited to 'src/backend/optimizer/util/placeholder.c')
-rw-r--r-- | src/backend/optimizer/util/placeholder.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c index 4dc632dcb52..09a24f54ec8 100644 --- a/src/backend/optimizer/util/placeholder.c +++ b/src/backend/optimizer/util/placeholder.c @@ -404,8 +404,10 @@ add_placeholders_to_base_rels(PlannerInfo *root) * and if they contain lateral references, add those references to the * joinrel's direct_lateral_relids. * - * A join rel should emit a PlaceHolderVar if (a) the PHV is needed above - * this join level and (b) the PHV can be computed at or below this level. + * A join rel should emit a PlaceHolderVar if (a) the PHV can be computed + * at or below this join level and (b) the PHV is needed above this level. + * However, condition (a) is sufficient to add to direct_lateral_relids, + * as explained below. */ void add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, @@ -418,11 +420,11 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, { PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc); - /* Is it still needed above this joinrel? */ - if (bms_nonempty_difference(phinfo->ph_needed, relids)) + /* Is it computable here? */ + if (bms_is_subset(phinfo->ph_eval_at, relids)) { - /* Is it computable here? */ - if (bms_is_subset(phinfo->ph_eval_at, relids)) + /* Is it still needed above this joinrel? */ + if (bms_nonempty_difference(phinfo->ph_needed, relids)) { /* Yup, add it to the output */ joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs, @@ -450,12 +452,26 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel, joinrel->reltarget->cost.startup += cost.startup; joinrel->reltarget->cost.per_tuple += cost.per_tuple; } - - /* Adjust joinrel's direct_lateral_relids as needed */ - joinrel->direct_lateral_relids = - bms_add_members(joinrel->direct_lateral_relids, - phinfo->ph_lateral); } + + /* + * Also adjust joinrel's direct_lateral_relids to include the + * PHV's source rel(s). We must do this even if we're not + * actually going to emit the PHV, otherwise join_is_legal() will + * reject valid join orderings. (In principle maybe we could + * instead remove the joinrel's lateral_relids dependency; but + * that's complicated to get right, and cases where we're not + * going to emit the PHV are too rare to justify the work.) + * + * In principle we should only do this if the join doesn't yet + * include the PHV's source rel(s). But our caller + * build_join_rel() will clean things up by removing the join's + * own relids from its direct_lateral_relids, so we needn't + * account for that here. + */ + joinrel->direct_lateral_relids = + bms_add_members(joinrel->direct_lateral_relids, + phinfo->ph_lateral); } } } |