2424
2525/* Local functions */
2626static Relids find_placeholders_recurse (PlannerInfo * root ,Node * jtnode );
27- static void find_placeholders_in_qual (PlannerInfo * root ,Node * qual ,
27+ static void mark_placeholders_in_expr (PlannerInfo * root ,Node * expr ,
2828Relids relids );
2929
3030
@@ -50,18 +50,24 @@ make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels)
5050
5151/*
5252 * find_placeholder_info
53- *Fetch the PlaceHolderInfo for the given PHV; create it if not found
53+ *Fetch the PlaceHolderInfo for the given PHV
54+ *
55+ * If the PlaceHolderInfo doesn't exist yet, create it if create_new_ph is
56+ * true, else throw an error.
5457 *
5558 * This is separate from make_placeholder_expr because subquery pullup has
5659 * to make PlaceHolderVars for expressions that might not be used at all in
5760 * the upper query, or might not remain after const-expression simplification.
5861 * We build PlaceHolderInfos only for PHVs that are still present in the
5962 * simplified query passed to query_planner().
6063 *
61- * Note: this should only be called after query_planner() has started.
64+ * Note: this should only be called after query_planner() has started. Also,
65+ * create_new_ph must not be TRUE after deconstruct_jointree begins, because
66+ * make_outerjoininfo assumes that we already know about all placeholders.
6267 */
6368PlaceHolderInfo *
64- find_placeholder_info (PlannerInfo * root ,PlaceHolderVar * phv )
69+ find_placeholder_info (PlannerInfo * root ,PlaceHolderVar * phv ,
70+ bool create_new_ph )
6571{
6672PlaceHolderInfo * phinfo ;
6773ListCell * lc ;
@@ -77,6 +83,9 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
7783}
7884
7985/* Not found, so create it */
86+ if (!create_new_ph )
87+ elog (ERROR ,"too late to create a new PlaceHolderInfo" );
88+
8089phinfo = makeNode (PlaceHolderInfo );
8190
8291phinfo -> phid = phv -> phid ;
@@ -157,7 +166,7 @@ find_placeholders_recurse(PlannerInfo *root, Node *jtnode)
157166/*
158167 * Now process the top-level quals.
159168 */
160- find_placeholders_in_qual (root ,f -> quals ,jtrelids );
169+ mark_placeholders_in_expr (root ,f -> quals ,jtrelids );
161170}
162171else if (IsA (jtnode ,JoinExpr ))
163172{
@@ -173,7 +182,7 @@ find_placeholders_recurse(PlannerInfo *root, Node *jtnode)
173182jtrelids = bms_join (leftids ,rightids );
174183
175184/* Process the qual clauses */
176- find_placeholders_in_qual (root ,j -> quals ,jtrelids );
185+ mark_placeholders_in_expr (root ,j -> quals ,jtrelids );
177186}
178187else
179188{
@@ -185,14 +194,15 @@ find_placeholders_recurse(PlannerInfo *root, Node *jtnode)
185194}
186195
187196/*
188- * find_placeholders_in_qual
189- *Process a qual clause for find_placeholders_in_jointree.
197+ * mark_placeholders_in_expr
198+ *Find all PlaceHolderVars in the given expression, and mark them
199+ *as possibly needed at the specified join level.
190200 *
191201 * relids is the syntactic join level to mark as the "maybe needed" level
192- * for each PlaceHolderVar found in thequal clause .
202+ * for each PlaceHolderVar found in theexpression .
193203 */
194204static void
195- find_placeholders_in_qual (PlannerInfo * root ,Node * qual ,Relids relids )
205+ mark_placeholders_in_expr (PlannerInfo * root ,Node * expr ,Relids relids )
196206{
197207List * vars ;
198208ListCell * vl ;
@@ -201,7 +211,7 @@ find_placeholders_in_qual(PlannerInfo *root, Node *qual, Relids relids)
201211 * pull_var_clause does more than we need here, but it'll do and it's
202212 * convenient to use.
203213 */
204- vars = pull_var_clause (qual ,
214+ vars = pull_var_clause (expr ,
205215PVC_RECURSE_AGGREGATES ,
206216PVC_INCLUDE_PLACEHOLDERS );
207217foreach (vl ,vars )
@@ -214,25 +224,47 @@ find_placeholders_in_qual(PlannerInfo *root, Node *qual, Relids relids)
214224continue ;
215225
216226/* Create a PlaceHolderInfo entry if there's not one already */
217- phinfo = find_placeholder_info (root ,phv );
218-
219- /* Mark the PHV as possibly needed at the qual's syntactic level */
220- phinfo -> ph_may_need = bms_add_members (phinfo -> ph_may_need ,relids );
227+ phinfo = find_placeholder_info (root ,phv , true);
221228
222- /*
223- * This is a bit tricky: the PHV's contained expression may contain
224- * other, lower-level PHVs. We need to get those into the
225- * PlaceHolderInfo list, but they aren't going to be needed where the
226- * outer PHV is referenced. Rather, they'll be needed where the outer
227- * PHV is evaluated. We can estimate that (conservatively) as the
228- * syntactic location of the PHV's expression. Recurse to take care
229- * of any such PHVs.
230- */
231- find_placeholders_in_qual (root , (Node * )phv -> phexpr ,phv -> phrels );
229+ /* Mark it, and recursively process any contained placeholders */
230+ mark_placeholder_maybe_needed (root ,phinfo ,relids );
232231}
233232list_free (vars );
234233}
235234
235+ /*
236+ * mark_placeholder_maybe_needed
237+ *Mark a placeholder as possibly needed at the specified join level.
238+ *
239+ * relids is the syntactic join level to mark as the "maybe needed" level
240+ * for the placeholder.
241+ *
242+ * This is called during an initial scan of the query's targetlist and quals
243+ * before we begin deconstruct_jointree. Once we begin deconstruct_jointree,
244+ * all active placeholders must be present in root->placeholder_list with
245+ * their correct ph_may_need values, because make_outerjoininfo and
246+ * update_placeholder_eval_levels require this info to be available while
247+ * we crawl up the join tree.
248+ */
249+ void
250+ mark_placeholder_maybe_needed (PlannerInfo * root ,PlaceHolderInfo * phinfo ,
251+ Relids relids )
252+ {
253+ /* Mark the PHV as possibly needed at the given syntactic level */
254+ phinfo -> ph_may_need = bms_add_members (phinfo -> ph_may_need ,relids );
255+
256+ /*
257+ * This is a bit tricky: the PHV's contained expression may contain other,
258+ * lower-level PHVs. We need to get those into the PlaceHolderInfo list,
259+ * but they aren't going to be needed where the outer PHV is referenced.
260+ * Rather, they'll be needed where the outer PHV is evaluated. We can
261+ * estimate that (conservatively) as the syntactic location of the PHV's
262+ * expression. Recurse to take care of any such PHVs.
263+ */
264+ mark_placeholders_in_expr (root , (Node * )phinfo -> ph_var -> phexpr ,
265+ phinfo -> ph_var -> phrels );
266+ }
267+
236268/*
237269 * update_placeholder_eval_levels
238270 *Adjust the target evaluation levels for placeholders
@@ -353,7 +385,7 @@ fix_placeholder_input_needed_levels(PlannerInfo *root)
353385PVC_RECURSE_AGGREGATES ,
354386PVC_INCLUDE_PLACEHOLDERS );
355387
356- add_vars_to_targetlist (root ,vars ,eval_at );
388+ add_vars_to_targetlist (root ,vars ,eval_at , false );
357389list_free (vars );
358390}
359391}