2323#include "utils/lsyscache.h"
2424
2525/* Local functions */
26- static Relids find_placeholders_recurse (PlannerInfo * root , Node * jtnode );
27- static void mark_placeholders_in_expr (PlannerInfo * root , Node * expr ,
28- Relids relids );
26+ static void find_placeholders_recurse (PlannerInfo * root , Node * jtnode );
27+ static void find_placeholders_in_expr (PlannerInfo * root , Node * expr );
2928
3029
3130/*
@@ -90,16 +89,23 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv,
9089
9190 phinfo -> phid = phv -> phid ;
9291 phinfo -> ph_var = copyObject (phv );
92+ /* initialize ph_eval_at as the set of contained relids */
9393 phinfo -> ph_eval_at = pull_varnos ((Node * ) phv );
9494 /* ph_eval_at may change later, see update_placeholder_eval_levels */
9595 phinfo -> ph_needed = NULL ; /* initially it's unused */
96- phinfo -> ph_may_need = NULL ;
9796 /* for the moment, estimate width using just the datatype info */
9897 phinfo -> ph_width = get_typavgwidth (exprType ((Node * ) phv -> phexpr ),
9998 exprTypmod ((Node * ) phv -> phexpr ));
10099
101100 root -> placeholder_list = lappend (root -> placeholder_list , phinfo );
102101
102+ /*
103+ * The PHV's contained expression may contain other, lower-level PHVs. We
104+ * now know we need to get those into the PlaceHolderInfo list, too, so we
105+ * may as well do that immediately.
106+ */
107+ find_placeholders_in_expr (root , (Node * ) phinfo -> ph_var -> phexpr );
108+
103109 return phinfo ;
104110}
105111
@@ -119,7 +125,7 @@ find_placeholders_in_jointree(PlannerInfo *root)
119125 /* Start recursion at top of jointree */
120126 Assert (root -> parse -> jointree != NULL &&
121127 IsA (root -> parse -> jointree , FromExpr ));
122- ( void ) find_placeholders_recurse (root , (Node * ) root -> parse -> jointree );
128+ find_placeholders_recurse (root , (Node * ) root -> parse -> jointree );
123129 }
124130}
125131
@@ -128,81 +134,59 @@ find_placeholders_in_jointree(PlannerInfo *root)
128134 * One recursion level of find_placeholders_in_jointree.
129135 *
130136 * jtnode is the current jointree node to examine.
131- *
132- * The result is the set of base Relids contained in or below jtnode.
133- * This is just an internal convenience, it's not used at the top level.
134137 */
135- static Relids
138+ static void
136139find_placeholders_recurse (PlannerInfo * root , Node * jtnode )
137140{
138- Relids jtrelids ;
139-
140141 if (jtnode == NULL )
141- return NULL ;
142+ return ;
142143 if (IsA (jtnode , RangeTblRef ))
143144 {
144- int varno = ((RangeTblRef * ) jtnode )-> rtindex ;
145-
146- /* No quals to deal with, just return correct result */
147- jtrelids = bms_make_singleton (varno );
145+ /* No quals to deal with here */
148146 }
149147 else if (IsA (jtnode , FromExpr ))
150148 {
151149 FromExpr * f = (FromExpr * ) jtnode ;
152150 ListCell * l ;
153151
154152 /*
155- * First, recurse to handle child joins, and form their relid set .
153+ * First, recurse to handle child joins.
156154 */
157- jtrelids = NULL ;
158155 foreach (l , f -> fromlist )
159156 {
160- Relids sub_relids ;
161-
162- sub_relids = find_placeholders_recurse (root , lfirst (l ));
163- jtrelids = bms_join (jtrelids , sub_relids );
157+ find_placeholders_recurse (root , lfirst (l ));
164158 }
165159
166160 /*
167161 * Now process the top-level quals.
168162 */
169- mark_placeholders_in_expr (root , f -> quals , jtrelids );
163+ find_placeholders_in_expr (root , f -> quals );
170164 }
171165 else if (IsA (jtnode , JoinExpr ))
172166 {
173167 JoinExpr * j = (JoinExpr * ) jtnode ;
174- Relids leftids ,
175- rightids ;
176168
177169 /*
178- * First, recurse to handle child joins, and form their relid set .
170+ * First, recurse to handle child joins.
179171 */
180- leftids = find_placeholders_recurse (root , j -> larg );
181- rightids = find_placeholders_recurse (root , j -> rarg );
182- jtrelids = bms_join (leftids , rightids );
172+ find_placeholders_recurse (root , j -> larg );
173+ find_placeholders_recurse (root , j -> rarg );
183174
184175 /* Process the qual clauses */
185- mark_placeholders_in_expr (root , j -> quals , jtrelids );
176+ find_placeholders_in_expr (root , j -> quals );
186177 }
187178 else
188- {
189179 elog (ERROR , "unrecognized node type: %d" ,
190180 (int ) nodeTag (jtnode ));
191- jtrelids = NULL ; /* keep compiler quiet */
192- }
193- return jtrelids ;
194181}
195182
196183/*
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.
200- *
201- * relids is the syntactic join level to mark as the "maybe needed" level
202- * for each PlaceHolderVar found in the expression.
184+ * find_placeholders_in_expr
185+ * Find all PlaceHolderVars in the given expression, and create
186+ * PlaceHolderInfo entries for them.
203187 */
204188static void
205- mark_placeholders_in_expr (PlannerInfo * root , Node * expr , Relids relids )
189+ find_placeholders_in_expr (PlannerInfo * root , Node * expr )
206190{
207191 List * vars ;
208192 ListCell * vl ;
@@ -217,63 +201,17 @@ mark_placeholders_in_expr(PlannerInfo *root, Node *expr, Relids relids)
217201 foreach (vl , vars )
218202 {
219203 PlaceHolderVar * phv = (PlaceHolderVar * ) lfirst (vl );
220- PlaceHolderInfo * phinfo ;
221204
222205 /* Ignore any plain Vars */
223206 if (!IsA (phv , PlaceHolderVar ))
224207 continue ;
225208
226209 /* Create a PlaceHolderInfo entry if there's not one already */
227- phinfo = find_placeholder_info (root , phv , true);
228-
229- /* Mark it, and recursively process any contained placeholders */
230- mark_placeholder_maybe_needed (root , phinfo , relids );
210+ (void ) find_placeholder_info (root , phv , true);
231211 }
232212 list_free (vars );
233213}
234214
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- Relids est_eval_level ;
254-
255- /* Mark the PHV as possibly needed at the given syntactic level */
256- phinfo -> ph_may_need = bms_add_members (phinfo -> ph_may_need , relids );
257-
258- /*
259- * This is a bit tricky: the PHV's contained expression may contain other,
260- * lower-level PHVs. We need to get those into the PlaceHolderInfo list,
261- * but they aren't going to be needed where the outer PHV is referenced.
262- * Rather, they'll be needed where the outer PHV is evaluated. We can
263- * estimate that conservatively as the syntactic location of the PHV's
264- * expression, but not less than the level of any Vars it contains.
265- * (Normally the Vars would come from below the syntactic location anyway,
266- * but this might not be true if the PHV contains any LATERAL references.)
267- */
268- est_eval_level = bms_union (phinfo -> ph_var -> phrels , phinfo -> ph_eval_at );
269-
270- /* Now recurse to take care of any such PHVs */
271- mark_placeholders_in_expr (root , (Node * ) phinfo -> ph_var -> phexpr ,
272- est_eval_level );
273-
274- bms_free (est_eval_level );
275- }
276-
277215/*
278216 * update_placeholder_eval_levels
279217 * Adjust the target evaluation levels for placeholders
0 commit comments