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