From 4da6439bd8553059766011e2a42c6e39df08717f Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 1 Sep 2012 13:56:14 -0400 Subject: Fix mark_placeholder_maybe_needed to handle LATERAL references. If a PlaceHolderVar contains a pulled-up LATERAL reference, its minimum possible evaluation level might be higher in the join tree than its original syntactic location. That in turn affects the ph_needed level for any contained PlaceHolderVars (that is, those PHVs had better propagate up the join tree at least to the evaluation level of the outer PHV). We got this mostly right, but mark_placeholder_maybe_needed() failed to account for the effect, and in consequence could leave the inner PHVs with ph_may_need less than what their ultimate ph_needed value will be. That's bad because it could lead to failure to select a join order that will allow evaluation of the inner PHV at a valid location. Fix that, and add an Assert that checks that we don't ever set ph_needed to more than ph_may_need. --- src/backend/optimizer/plan/initsplan.c | 5 ++++- src/backend/optimizer/util/placeholder.c | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) (limited to 'src/backend/optimizer') diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index f582d4067b..9565e2d607 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -199,10 +199,13 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars, /* * If we are creating PlaceHolderInfos, mark them with the correct * maybe-needed locations. Otherwise, it's too late to change - * that. + * that, so we'd better not have set ph_needed to more than + * ph_may_need. */ if (create_new_ph) mark_placeholder_maybe_needed(root, phinfo, where_needed); + else + Assert(bms_is_subset(phinfo->ph_needed, phinfo->ph_may_need)); } else elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c index 317a01940e..345a0277a5 100644 --- a/src/backend/optimizer/util/placeholder.c +++ b/src/backend/optimizer/util/placeholder.c @@ -250,6 +250,8 @@ void mark_placeholder_maybe_needed(PlannerInfo *root, PlaceHolderInfo *phinfo, Relids relids) { + Relids est_eval_level; + /* Mark the PHV as possibly needed at the given syntactic level */ phinfo->ph_may_need = bms_add_members(phinfo->ph_may_need, relids); @@ -258,11 +260,18 @@ mark_placeholder_maybe_needed(PlannerInfo *root, PlaceHolderInfo *phinfo, * lower-level PHVs. We need to get those into the PlaceHolderInfo list, * but they aren't going to be needed where the outer PHV is referenced. * Rather, they'll be needed where the outer PHV is evaluated. We can - * estimate that (conservatively) as the syntactic location of the PHV's - * expression. Recurse to take care of any such PHVs. + * estimate that conservatively as the syntactic location of the PHV's + * expression, but not less than the level of any Vars it contains. + * (Normally the Vars would come from below the syntactic location anyway, + * but this might not be true if the PHV contains any LATERAL references.) */ + est_eval_level = bms_union(phinfo->ph_var->phrels, phinfo->ph_eval_at); + + /* Now recurse to take care of any such PHVs */ mark_placeholders_in_expr(root, (Node *) phinfo->ph_var->phexpr, - phinfo->ph_var->phrels); + est_eval_level); + + bms_free(est_eval_level); } /* -- cgit v1.2.3