23
23
#include "utils/lsyscache.h"
24
24
25
25
/* 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 );
29
28
30
29
31
30
/*
@@ -90,16 +89,23 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv,
90
89
91
90
phinfo -> phid = phv -> phid ;
92
91
phinfo -> ph_var = copyObject (phv );
92
+ /* initialize ph_eval_at as the set of contained relids */
93
93
phinfo -> ph_eval_at = pull_varnos ((Node * ) phv );
94
94
/* ph_eval_at may change later, see update_placeholder_eval_levels */
95
95
phinfo -> ph_needed = NULL ; /* initially it's unused */
96
- phinfo -> ph_may_need = NULL ;
97
96
/* for the moment, estimate width using just the datatype info */
98
97
phinfo -> ph_width = get_typavgwidth (exprType ((Node * ) phv -> phexpr ),
99
98
exprTypmod ((Node * ) phv -> phexpr ));
100
99
101
100
root -> placeholder_list = lappend (root -> placeholder_list , phinfo );
102
101
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
+
103
109
return phinfo ;
104
110
}
105
111
@@ -119,7 +125,7 @@ find_placeholders_in_jointree(PlannerInfo *root)
119
125
/* Start recursion at top of jointree */
120
126
Assert (root -> parse -> jointree != NULL &&
121
127
IsA (root -> parse -> jointree , FromExpr ));
122
- ( void ) find_placeholders_recurse (root , (Node * ) root -> parse -> jointree );
128
+ find_placeholders_recurse (root , (Node * ) root -> parse -> jointree );
123
129
}
124
130
}
125
131
@@ -128,81 +134,59 @@ find_placeholders_in_jointree(PlannerInfo *root)
128
134
* One recursion level of find_placeholders_in_jointree.
129
135
*
130
136
* 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.
134
137
*/
135
- static Relids
138
+ static void
136
139
find_placeholders_recurse (PlannerInfo * root , Node * jtnode )
137
140
{
138
- Relids jtrelids ;
139
-
140
141
if (jtnode == NULL )
141
- return NULL ;
142
+ return ;
142
143
if (IsA (jtnode , RangeTblRef ))
143
144
{
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 */
148
146
}
149
147
else if (IsA (jtnode , FromExpr ))
150
148
{
151
149
FromExpr * f = (FromExpr * ) jtnode ;
152
150
ListCell * l ;
153
151
154
152
/*
155
- * First, recurse to handle child joins, and form their relid set .
153
+ * First, recurse to handle child joins.
156
154
*/
157
- jtrelids = NULL ;
158
155
foreach (l , f -> fromlist )
159
156
{
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 ));
164
158
}
165
159
166
160
/*
167
161
* Now process the top-level quals.
168
162
*/
169
- mark_placeholders_in_expr (root , f -> quals , jtrelids );
163
+ find_placeholders_in_expr (root , f -> quals );
170
164
}
171
165
else if (IsA (jtnode , JoinExpr ))
172
166
{
173
167
JoinExpr * j = (JoinExpr * ) jtnode ;
174
- Relids leftids ,
175
- rightids ;
176
168
177
169
/*
178
- * First, recurse to handle child joins, and form their relid set .
170
+ * First, recurse to handle child joins.
179
171
*/
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 );
183
174
184
175
/* Process the qual clauses */
185
- mark_placeholders_in_expr (root , j -> quals , jtrelids );
176
+ find_placeholders_in_expr (root , j -> quals );
186
177
}
187
178
else
188
- {
189
179
elog (ERROR , "unrecognized node type: %d" ,
190
180
(int ) nodeTag (jtnode ));
191
- jtrelids = NULL ; /* keep compiler quiet */
192
- }
193
- return jtrelids ;
194
181
}
195
182
196
183
/*
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.
203
187
*/
204
188
static void
205
- mark_placeholders_in_expr (PlannerInfo * root , Node * expr , Relids relids )
189
+ find_placeholders_in_expr (PlannerInfo * root , Node * expr )
206
190
{
207
191
List * vars ;
208
192
ListCell * vl ;
@@ -217,63 +201,17 @@ mark_placeholders_in_expr(PlannerInfo *root, Node *expr, Relids relids)
217
201
foreach (vl , vars )
218
202
{
219
203
PlaceHolderVar * phv = (PlaceHolderVar * ) lfirst (vl );
220
- PlaceHolderInfo * phinfo ;
221
204
222
205
/* Ignore any plain Vars */
223
206
if (!IsA (phv , PlaceHolderVar ))
224
207
continue ;
225
208
226
209
/* 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);
231
211
}
232
212
list_free (vars );
233
213
}
234
214
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
-
277
215
/*
278
216
* update_placeholder_eval_levels
279
217
* Adjust the target evaluation levels for placeholders
0 commit comments