Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * var.c
4 : * Var node manipulation routines
5 : *
6 : * Note: for most purposes, PlaceHolderVar is considered a Var too,
7 : * even if its contained expression is variable-free. Also, CurrentOfExpr
8 : * is treated as a Var for purposes of determining whether an expression
9 : * contains variables.
10 : *
11 : *
12 : * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
13 : * Portions Copyright (c) 1994, Regents of the University of California
14 : *
15 : *
16 : * IDENTIFICATION
17 : * src/backend/optimizer/util/var.c
18 : *
19 : *-------------------------------------------------------------------------
20 : */
21 : #include "postgres.h"
22 :
23 : #include "access/sysattr.h"
24 : #include "nodes/nodeFuncs.h"
25 : #include "optimizer/optimizer.h"
26 : #include "optimizer/placeholder.h"
27 : #include "optimizer/prep.h"
28 : #include "parser/parsetree.h"
29 : #include "rewrite/rewriteManip.h"
30 :
31 :
32 : typedef struct
33 : {
34 : Relids varnos;
35 : PlannerInfo *root;
36 : int sublevels_up;
37 : } pull_varnos_context;
38 :
39 : typedef struct
40 : {
41 : Bitmapset *varattnos;
42 : Index varno;
43 : } pull_varattnos_context;
44 :
45 : typedef struct
46 : {
47 : List *vars;
48 : int sublevels_up;
49 : } pull_vars_context;
50 :
51 : typedef struct
52 : {
53 : int var_location;
54 : int sublevels_up;
55 : } locate_var_of_level_context;
56 :
57 : typedef struct
58 : {
59 : List *varlist;
60 : int flags;
61 : } pull_var_clause_context;
62 :
63 : typedef struct
64 : {
65 : Query *query; /* outer Query */
66 : int sublevels_up;
67 : bool possible_sublink; /* could aliases include a SubLink? */
68 : bool inserted_sublink; /* have we inserted a SubLink? */
69 : } flatten_join_alias_vars_context;
70 :
71 : static bool pull_varnos_walker(Node *node,
72 : pull_varnos_context *context);
73 : static bool pull_varattnos_walker(Node *node, pull_varattnos_context *context);
74 : static bool pull_vars_walker(Node *node, pull_vars_context *context);
75 : static bool contain_var_clause_walker(Node *node, void *context);
76 : static bool contain_vars_of_level_walker(Node *node, int *sublevels_up);
77 : static bool locate_var_of_level_walker(Node *node,
78 : locate_var_of_level_context *context);
79 : static bool pull_var_clause_walker(Node *node,
80 : pull_var_clause_context *context);
81 : static Node *flatten_join_alias_vars_mutator(Node *node,
82 : flatten_join_alias_vars_context *context);
83 : static Relids alias_relid_set(Query *query, Relids relids);
84 :
85 :
86 : /*
87 : * pull_varnos
88 : * Create a set of all the distinct varnos present in a parsetree.
89 : * Only varnos that reference level-zero rtable entries are considered.
90 : *
91 : * NOTE: this is used on not-yet-planned expressions. It may therefore find
92 : * bare SubLinks, and if so it needs to recurse into them to look for uplevel
93 : * references to the desired rtable level! But when we find a completed
94 : * SubPlan, we only need to look at the parameters passed to the subplan.
95 : */
96 : Relids
97 1758540 : pull_varnos(PlannerInfo *root, Node *node)
98 : {
99 : pull_varnos_context context;
100 :
101 1758540 : context.varnos = NULL;
102 1758540 : context.root = root;
103 1758540 : context.sublevels_up = 0;
104 :
105 : /*
106 : * Must be prepared to start with a Query or a bare expression tree; if
107 : * it's a Query, we don't want to increment sublevels_up.
108 : */
109 1758540 : query_or_expression_tree_walker(node,
110 : pull_varnos_walker,
111 : (void *) &context,
112 : 0);
113 :
114 1758540 : return context.varnos;
115 : }
116 :
117 : /*
118 : * pull_varnos_of_level
119 : * Create a set of all the distinct varnos present in a parsetree.
120 : * Only Vars of the specified level are considered.
121 : */
122 : Relids
123 692 : pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup)
124 : {
125 : pull_varnos_context context;
126 :
127 692 : context.varnos = NULL;
128 692 : context.root = root;
129 692 : context.sublevels_up = levelsup;
130 :
131 : /*
132 : * Must be prepared to start with a Query or a bare expression tree; if
133 : * it's a Query, we don't want to increment sublevels_up.
134 : */
135 692 : query_or_expression_tree_walker(node,
136 : pull_varnos_walker,
137 : (void *) &context,
138 : 0);
139 :
140 692 : return context.varnos;
141 : }
142 :
143 : static bool
144 2913354 : pull_varnos_walker(Node *node, pull_varnos_context *context)
145 : {
146 2913354 : if (node == NULL)
147 19156 : return false;
148 2894198 : if (IsA(node, Var))
149 : {
150 1425990 : Var *var = (Var *) node;
151 :
152 1425990 : if (var->varlevelsup == context->sublevels_up)
153 1425058 : context->varnos = bms_add_member(context->varnos, var->varno);
154 1425990 : return false;
155 : }
156 1468208 : if (IsA(node, CurrentOfExpr))
157 : {
158 760 : CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
159 :
160 760 : if (context->sublevels_up == 0)
161 760 : context->varnos = bms_add_member(context->varnos, cexpr->cvarno);
162 760 : return false;
163 : }
164 1467448 : if (IsA(node, PlaceHolderVar))
165 : {
166 2004 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
167 :
168 : /*
169 : * If a PlaceHolderVar is not of the target query level, ignore it,
170 : * instead recursing into its expression to see if it contains any
171 : * vars that are of the target level.
172 : */
173 2004 : if (phv->phlevelsup == context->sublevels_up)
174 : {
175 : /*
176 : * Ideally, the PHV's contribution to context->varnos is its
177 : * ph_eval_at set. However, this code can be invoked before
178 : * that's been computed. If we cannot find a PlaceHolderInfo,
179 : * fall back to the conservative assumption that the PHV will be
180 : * evaluated at its syntactic level (phv->phrels).
181 : *
182 : * There is a second hazard: this code is also used to examine
183 : * qual clauses during deconstruct_jointree, when we may have a
184 : * PlaceHolderInfo but its ph_eval_at value is not yet final, so
185 : * that theoretically we could obtain a relid set that's smaller
186 : * than we'd see later on. That should never happen though,
187 : * because we deconstruct the jointree working upwards. Any outer
188 : * join that forces delay of evaluation of a given qual clause
189 : * will be processed before we examine that clause here, so the
190 : * ph_eval_at value should have been updated to include it.
191 : */
192 2004 : PlaceHolderInfo *phinfo = NULL;
193 :
194 2004 : if (phv->phlevelsup == 0)
195 : {
196 : ListCell *lc;
197 :
198 2608 : foreach(lc, context->root->placeholder_list)
199 : {
200 2452 : phinfo = (PlaceHolderInfo *) lfirst(lc);
201 2452 : if (phinfo->phid == phv->phid)
202 1832 : break;
203 620 : phinfo = NULL;
204 : }
205 : }
206 2004 : if (phinfo != NULL)
207 1832 : context->varnos = bms_add_members(context->varnos,
208 1832 : phinfo->ph_eval_at);
209 : else
210 172 : context->varnos = bms_add_members(context->varnos,
211 172 : phv->phrels);
212 2004 : return false; /* don't recurse into expression */
213 : }
214 : }
215 1465444 : else if (IsA(node, Query))
216 : {
217 : /* Recurse into RTE subquery or not-yet-planned sublink subquery */
218 : bool result;
219 :
220 24 : context->sublevels_up++;
221 24 : result = query_tree_walker((Query *) node, pull_varnos_walker,
222 : (void *) context, 0);
223 24 : context->sublevels_up--;
224 24 : return result;
225 : }
226 1465420 : return expression_tree_walker(node, pull_varnos_walker,
227 : (void *) context);
228 : }
229 :
230 :
231 : /*
232 : * pull_varattnos
233 : * Find all the distinct attribute numbers present in an expression tree,
234 : * and add them to the initial contents of *varattnos.
235 : * Only Vars of the given varno and rtable level zero are considered.
236 : *
237 : * Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
238 : * we can include system attributes (e.g., OID) in the bitmap representation.
239 : *
240 : * Currently, this does not support unplanned subqueries; that is not needed
241 : * for current uses. It will handle already-planned SubPlan nodes, though,
242 : * looking into only the "testexpr" and the "args" list. (The subplan cannot
243 : * contain any other references to Vars of the current level.)
244 : */
245 : void
246 1004406 : pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
247 : {
248 : pull_varattnos_context context;
249 :
250 1004406 : context.varattnos = *varattnos;
251 1004406 : context.varno = varno;
252 :
253 1004406 : (void) pull_varattnos_walker(node, &context);
254 :
255 1004406 : *varattnos = context.varattnos;
256 1004406 : }
257 :
258 : static bool
259 3827728 : pull_varattnos_walker(Node *node, pull_varattnos_context *context)
260 : {
261 3827728 : if (node == NULL)
262 47582 : return false;
263 3780146 : if (IsA(node, Var))
264 : {
265 2368656 : Var *var = (Var *) node;
266 :
267 2368656 : if (var->varno == context->varno && var->varlevelsup == 0)
268 2368598 : context->varattnos =
269 2368598 : bms_add_member(context->varattnos,
270 2368598 : var->varattno - FirstLowInvalidHeapAttributeNumber);
271 2368656 : return false;
272 : }
273 :
274 : /* Should not find an unplanned subquery */
275 : Assert(!IsA(node, Query));
276 :
277 1411490 : return expression_tree_walker(node, pull_varattnos_walker,
278 : (void *) context);
279 : }
280 :
281 :
282 : /*
283 : * pull_vars_of_level
284 : * Create a list of all Vars (and PlaceHolderVars) referencing the
285 : * specified query level in the given parsetree.
286 : *
287 : * Caution: the Vars are not copied, only linked into the list.
288 : */
289 : List *
290 842 : pull_vars_of_level(Node *node, int levelsup)
291 : {
292 : pull_vars_context context;
293 :
294 842 : context.vars = NIL;
295 842 : context.sublevels_up = levelsup;
296 :
297 : /*
298 : * Must be prepared to start with a Query or a bare expression tree; if
299 : * it's a Query, we don't want to increment sublevels_up.
300 : */
301 842 : query_or_expression_tree_walker(node,
302 : pull_vars_walker,
303 : (void *) &context,
304 : 0);
305 :
306 842 : return context.vars;
307 : }
308 :
309 : static bool
310 15132 : pull_vars_walker(Node *node, pull_vars_context *context)
311 : {
312 15132 : if (node == NULL)
313 5600 : return false;
314 9532 : if (IsA(node, Var))
315 : {
316 2164 : Var *var = (Var *) node;
317 :
318 2164 : if (var->varlevelsup == context->sublevels_up)
319 1116 : context->vars = lappend(context->vars, var);
320 2164 : return false;
321 : }
322 7368 : if (IsA(node, PlaceHolderVar))
323 : {
324 40 : PlaceHolderVar *phv = (PlaceHolderVar *) node;
325 :
326 40 : if (phv->phlevelsup == context->sublevels_up)
327 40 : context->vars = lappend(context->vars, phv);
328 : /* we don't want to look into the contained expression */
329 40 : return false;
330 : }
331 7328 : if (IsA(node, Query))
332 : {
333 : /* Recurse into RTE subquery or not-yet-planned sublink subquery */
334 : bool result;
335 :
336 188 : context->sublevels_up++;
337 188 : result = query_tree_walker((Query *) node, pull_vars_walker,
338 : (void *) context, 0);
339 188 : context->sublevels_up--;
340 188 : return result;
341 : }
342 7140 : return expression_tree_walker(node, pull_vars_walker,
343 : (void *) context);
344 : }
345 :
346 :
347 : /*
348 : * contain_var_clause
349 : * Recursively scan a clause to discover whether it contains any Var nodes
350 : * (of the current query level).
351 : *
352 : * Returns true if any varnode found.
353 : *
354 : * Does not examine subqueries, therefore must only be used after reduction
355 : * of sublinks to subplans!
356 : */
357 : bool
358 28118 : contain_var_clause(Node *node)
359 : {
360 28118 : return contain_var_clause_walker(node, NULL);
361 : }
362 :
363 : static bool
364 35838 : contain_var_clause_walker(Node *node, void *context)
365 : {
366 35838 : if (node == NULL)
367 60 : return false;
368 35778 : if (IsA(node, Var))
369 : {
370 1644 : if (((Var *) node)->varlevelsup == 0)
371 1644 : return true; /* abort the tree traversal and return true */
372 0 : return false;
373 : }
374 34134 : if (IsA(node, CurrentOfExpr))
375 0 : return true;
376 34134 : if (IsA(node, PlaceHolderVar))
377 : {
378 0 : if (((PlaceHolderVar *) node)->phlevelsup == 0)
379 0 : return true; /* abort the tree traversal and return true */
380 : /* else fall through to check the contained expr */
381 : }
382 34134 : return expression_tree_walker(node, contain_var_clause_walker, context);
383 : }
384 :
385 :
386 : /*
387 : * contain_vars_of_level
388 : * Recursively scan a clause to discover whether it contains any Var nodes
389 : * of the specified query level.
390 : *
391 : * Returns true if any such Var found.
392 : *
393 : * Will recurse into sublinks. Also, may be invoked directly on a Query.
394 : */
395 : bool
396 192498 : contain_vars_of_level(Node *node, int levelsup)
397 : {
398 192498 : int sublevels_up = levelsup;
399 :
400 192498 : return query_or_expression_tree_walker(node,
401 : contain_vars_of_level_walker,
402 : (void *) &sublevels_up,
403 : 0);
404 : }
405 :
406 : static bool
407 678170 : contain_vars_of_level_walker(Node *node, int *sublevels_up)
408 : {
409 678170 : if (node == NULL)
410 153844 : return false;
411 524326 : if (IsA(node, Var))
412 : {
413 93592 : if (((Var *) node)->varlevelsup == *sublevels_up)
414 28342 : return true; /* abort tree traversal and return true */
415 65250 : return false;
416 : }
417 430734 : if (IsA(node, CurrentOfExpr))
418 : {
419 124 : if (*sublevels_up == 0)
420 124 : return true;
421 0 : return false;
422 : }
423 430610 : if (IsA(node, PlaceHolderVar))
424 : {
425 24 : if (((PlaceHolderVar *) node)->phlevelsup == *sublevels_up)
426 24 : return true; /* abort the tree traversal and return true */
427 : /* else fall through to check the contained expr */
428 : }
429 430586 : if (IsA(node, Query))
430 : {
431 : /* Recurse into subselects */
432 : bool result;
433 :
434 2852 : (*sublevels_up)++;
435 2852 : result = query_tree_walker((Query *) node,
436 : contain_vars_of_level_walker,
437 : (void *) sublevels_up,
438 : 0);
439 2852 : (*sublevels_up)--;
440 2852 : return result;
441 : }
442 427734 : return expression_tree_walker(node,
443 : contain_vars_of_level_walker,
444 : (void *) sublevels_up);
445 : }
446 :
447 :
448 : /*
449 : * locate_var_of_level
450 : * Find the parse location of any Var of the specified query level.
451 : *
452 : * Returns -1 if no such Var is in the querytree, or if they all have
453 : * unknown parse location. (The former case is probably caller error,
454 : * but we don't bother to distinguish it from the latter case.)
455 : *
456 : * Will recurse into sublinks. Also, may be invoked directly on a Query.
457 : *
458 : * Note: it might seem appropriate to merge this functionality into
459 : * contain_vars_of_level, but that would complicate that function's API.
460 : * Currently, the only uses of this function are for error reporting,
461 : * and so shaving cycles probably isn't very important.
462 : */
463 : int
464 4 : locate_var_of_level(Node *node, int levelsup)
465 : {
466 : locate_var_of_level_context context;
467 :
468 4 : context.var_location = -1; /* in case we find nothing */
469 4 : context.sublevels_up = levelsup;
470 :
471 4 : (void) query_or_expression_tree_walker(node,
472 : locate_var_of_level_walker,
473 : (void *) &context,
474 : 0);
475 :
476 4 : return context.var_location;
477 : }
478 :
479 : static bool
480 12 : locate_var_of_level_walker(Node *node,
481 : locate_var_of_level_context *context)
482 : {
483 12 : if (node == NULL)
484 0 : return false;
485 12 : if (IsA(node, Var))
486 : {
487 4 : Var *var = (Var *) node;
488 :
489 4 : if (var->varlevelsup == context->sublevels_up &&
490 4 : var->location >= 0)
491 : {
492 4 : context->var_location = var->location;
493 4 : return true; /* abort tree traversal and return true */
494 : }
495 0 : return false;
496 : }
497 8 : if (IsA(node, CurrentOfExpr))
498 : {
499 : /* since CurrentOfExpr doesn't carry location, nothing we can do */
500 0 : return false;
501 : }
502 : /* No extra code needed for PlaceHolderVar; just look in contained expr */
503 8 : if (IsA(node, Query))
504 : {
505 : /* Recurse into subselects */
506 : bool result;
507 :
508 0 : context->sublevels_up++;
509 0 : result = query_tree_walker((Query *) node,
510 : locate_var_of_level_walker,
511 : (void *) context,
512 : 0);
513 0 : context->sublevels_up--;
514 0 : return result;
515 : }
516 8 : return expression_tree_walker(node,
517 : locate_var_of_level_walker,
518 : (void *) context);
519 : }
520 :
521 :
522 : /*
523 : * pull_var_clause
524 : * Recursively pulls all Var nodes from an expression clause.
525 : *
526 : * Aggrefs are handled according to these bits in 'flags':
527 : * PVC_INCLUDE_AGGREGATES include Aggrefs in output list
528 : * PVC_RECURSE_AGGREGATES recurse into Aggref arguments
529 : * neither flag throw error if Aggref found
530 : * Vars within an Aggref's expression are included in the result only
531 : * when PVC_RECURSE_AGGREGATES is specified.
532 : *
533 : * WindowFuncs are handled according to these bits in 'flags':
534 : * PVC_INCLUDE_WINDOWFUNCS include WindowFuncs in output list
535 : * PVC_RECURSE_WINDOWFUNCS recurse into WindowFunc arguments
536 : * neither flag throw error if WindowFunc found
537 : * Vars within a WindowFunc's expression are included in the result only
538 : * when PVC_RECURSE_WINDOWFUNCS is specified.
539 : *
540 : * PlaceHolderVars are handled according to these bits in 'flags':
541 : * PVC_INCLUDE_PLACEHOLDERS include PlaceHolderVars in output list
542 : * PVC_RECURSE_PLACEHOLDERS recurse into PlaceHolderVar arguments
543 : * neither flag throw error if PlaceHolderVar found
544 : * Vars within a PHV's expression are included in the result only
545 : * when PVC_RECURSE_PLACEHOLDERS is specified.
546 : *
547 : * GroupingFuncs are treated mostly like Aggrefs, and so do not need
548 : * their own flag bits.
549 : *
550 : * CurrentOfExpr nodes are ignored in all cases.
551 : *
552 : * Upper-level vars (with varlevelsup > 0) should not be seen here,
553 : * likewise for upper-level Aggrefs and PlaceHolderVars.
554 : *
555 : * Returns list of nodes found. Note the nodes themselves are not
556 : * copied, only referenced.
557 : *
558 : * Does not examine subqueries, therefore must only be used after reduction
559 : * of sublinks to subplans!
560 : */
561 : List *
562 386336 : pull_var_clause(Node *node, int flags)
563 : {
564 : pull_var_clause_context context;
565 :
566 : /* Assert that caller has not specified inconsistent flags */
567 : Assert((flags & (PVC_INCLUDE_AGGREGATES | PVC_RECURSE_AGGREGATES))
568 : != (PVC_INCLUDE_AGGREGATES | PVC_RECURSE_AGGREGATES));
569 : Assert((flags & (PVC_INCLUDE_WINDOWFUNCS | PVC_RECURSE_WINDOWFUNCS))
570 : != (PVC_INCLUDE_WINDOWFUNCS | PVC_RECURSE_WINDOWFUNCS));
571 : Assert((flags & (PVC_INCLUDE_PLACEHOLDERS | PVC_RECURSE_PLACEHOLDERS))
572 : != (PVC_INCLUDE_PLACEHOLDERS | PVC_RECURSE_PLACEHOLDERS));
573 :
574 386336 : context.varlist = NIL;
575 386336 : context.flags = flags;
576 :
577 386336 : pull_var_clause_walker(node, &context);
578 386336 : return context.varlist;
579 : }
580 :
581 : static bool
582 3260408 : pull_var_clause_walker(Node *node, pull_var_clause_context *context)
583 : {
584 3260408 : if (node == NULL)
585 134150 : return false;
586 3126258 : if (IsA(node, Var))
587 : {
588 1161132 : if (((Var *) node)->varlevelsup != 0)
589 0 : elog(ERROR, "Upper-level Var found where not expected");
590 1161132 : context->varlist = lappend(context->varlist, node);
591 1161132 : return false;
592 : }
593 1965126 : else if (IsA(node, Aggref))
594 : {
595 65556 : if (((Aggref *) node)->agglevelsup != 0)
596 0 : elog(ERROR, "Upper-level Aggref found where not expected");
597 65556 : if (context->flags & PVC_INCLUDE_AGGREGATES)
598 : {
599 2974 : context->varlist = lappend(context->varlist, node);
600 : /* we do NOT descend into the contained expression */
601 2974 : return false;
602 : }
603 62582 : else if (context->flags & PVC_RECURSE_AGGREGATES)
604 : {
605 : /* fall through to recurse into the aggregate's arguments */
606 : }
607 : else
608 0 : elog(ERROR, "Aggref found where not expected");
609 : }
610 1899570 : else if (IsA(node, GroupingFunc))
611 : {
612 320 : if (((GroupingFunc *) node)->agglevelsup != 0)
613 0 : elog(ERROR, "Upper-level GROUPING found where not expected");
614 320 : if (context->flags & PVC_INCLUDE_AGGREGATES)
615 : {
616 4 : context->varlist = lappend(context->varlist, node);
617 : /* we do NOT descend into the contained expression */
618 4 : return false;
619 : }
620 316 : else if (context->flags & PVC_RECURSE_AGGREGATES)
621 : {
622 : /*
623 : * We do NOT descend into the contained expression, even if the
624 : * caller asked for it, because we never actually evaluate it -
625 : * the result is driven entirely off the associated GROUP BY
626 : * clause, so we never need to extract the actual Vars here.
627 : */
628 316 : return false;
629 : }
630 : else
631 0 : elog(ERROR, "GROUPING found where not expected");
632 : }
633 1899250 : else if (IsA(node, WindowFunc))
634 : {
635 : /* WindowFuncs have no levelsup field to check ... */
636 3072 : if (context->flags & PVC_INCLUDE_WINDOWFUNCS)
637 : {
638 8 : context->varlist = lappend(context->varlist, node);
639 : /* we do NOT descend into the contained expressions */
640 8 : return false;
641 : }
642 3064 : else if (context->flags & PVC_RECURSE_WINDOWFUNCS)
643 : {
644 : /* fall through to recurse into the windowfunc's arguments */
645 : }
646 : else
647 0 : elog(ERROR, "WindowFunc found where not expected");
648 : }
649 1896178 : else if (IsA(node, PlaceHolderVar))
650 : {
651 1112 : if (((PlaceHolderVar *) node)->phlevelsup != 0)
652 0 : elog(ERROR, "Upper-level PlaceHolderVar found where not expected");
653 1112 : if (context->flags & PVC_INCLUDE_PLACEHOLDERS)
654 : {
655 1016 : context->varlist = lappend(context->varlist, node);
656 : /* we do NOT descend into the contained expression */
657 1016 : return false;
658 : }
659 96 : else if (context->flags & PVC_RECURSE_PLACEHOLDERS)
660 : {
661 : /* fall through to recurse into the placeholder's expression */
662 : }
663 : else
664 0 : elog(ERROR, "PlaceHolderVar found where not expected");
665 : }
666 1960808 : return expression_tree_walker(node, pull_var_clause_walker,
667 : (void *) context);
668 : }
669 :
670 :
671 : /*
672 : * flatten_join_alias_vars
673 : * Replace Vars that reference JOIN outputs with references to the original
674 : * relation variables instead. This allows quals involving such vars to be
675 : * pushed down. Whole-row Vars that reference JOIN relations are expanded
676 : * into RowExpr constructs that name the individual output Vars. This
677 : * is necessary since we will not scan the JOIN as a base relation, which
678 : * is the only way that the executor can directly handle whole-row Vars.
679 : *
680 : * This also adjusts relid sets found in some expression node types to
681 : * substitute the contained base rels for any join relid.
682 : *
683 : * If a JOIN contains sub-selects that have been flattened, its join alias
684 : * entries might now be arbitrary expressions, not just Vars. This affects
685 : * this function in one important way: we might find ourselves inserting
686 : * SubLink expressions into subqueries, and we must make sure that their
687 : * Query.hasSubLinks fields get set to true if so. If there are any
688 : * SubLinks in the join alias lists, the outer Query should already have
689 : * hasSubLinks = true, so this is only relevant to un-flattened subqueries.
690 : *
691 : * NOTE: this is used on not-yet-planned expressions. We do not expect it
692 : * to be applied directly to the whole Query, so if we see a Query to start
693 : * with, we do want to increment sublevels_up (this occurs for LATERAL
694 : * subqueries).
695 : */
696 : Node *
697 188794 : flatten_join_alias_vars(Query *query, Node *node)
698 : {
699 : flatten_join_alias_vars_context context;
700 :
701 188794 : context.query = query;
702 188794 : context.sublevels_up = 0;
703 : /* flag whether join aliases could possibly contain SubLinks */
704 188794 : context.possible_sublink = query->hasSubLinks;
705 : /* if hasSubLinks is already true, no need to work hard */
706 188794 : context.inserted_sublink = query->hasSubLinks;
707 :
708 188794 : return flatten_join_alias_vars_mutator(node, &context);
709 : }
710 :
711 : static Node *
712 3988950 : flatten_join_alias_vars_mutator(Node *node,
713 : flatten_join_alias_vars_context *context)
714 : {
715 3988950 : if (node == NULL)
716 587972 : return NULL;
717 3400978 : if (IsA(node, Var))
718 : {
719 929382 : Var *var = (Var *) node;
720 : RangeTblEntry *rte;
721 : Node *newvar;
722 :
723 : /* No change unless Var belongs to a JOIN of the target level */
724 929382 : if (var->varlevelsup != context->sublevels_up)
725 158644 : return node; /* no need to copy, really */
726 770738 : rte = rt_fetch(var->varno, context->query->rtable);
727 770738 : if (rte->rtekind != RTE_JOIN)
728 770414 : return node;
729 324 : if (var->varattno == InvalidAttrNumber)
730 : {
731 : /* Must expand whole-row reference */
732 : RowExpr *rowexpr;
733 4 : List *fields = NIL;
734 4 : List *colnames = NIL;
735 : AttrNumber attnum;
736 : ListCell *lv;
737 : ListCell *ln;
738 :
739 4 : attnum = 0;
740 : Assert(list_length(rte->joinaliasvars) == list_length(rte->eref->colnames));
741 32 : forboth(lv, rte->joinaliasvars, ln, rte->eref->colnames)
742 : {
743 28 : newvar = (Node *) lfirst(lv);
744 28 : attnum++;
745 : /* Ignore dropped columns */
746 28 : if (newvar == NULL)
747 0 : continue;
748 28 : newvar = copyObject(newvar);
749 :
750 : /*
751 : * If we are expanding an alias carried down from an upper
752 : * query, must adjust its varlevelsup fields.
753 : */
754 28 : if (context->sublevels_up != 0)
755 0 : IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
756 : /* Preserve original Var's location, if possible */
757 28 : if (IsA(newvar, Var))
758 28 : ((Var *) newvar)->location = var->location;
759 : /* Recurse in case join input is itself a join */
760 : /* (also takes care of setting inserted_sublink if needed) */
761 28 : newvar = flatten_join_alias_vars_mutator(newvar, context);
762 28 : fields = lappend(fields, newvar);
763 : /* We need the names of non-dropped columns, too */
764 28 : colnames = lappend(colnames, copyObject((Node *) lfirst(ln)));
765 : }
766 4 : rowexpr = makeNode(RowExpr);
767 4 : rowexpr->args = fields;
768 4 : rowexpr->row_typeid = var->vartype;
769 4 : rowexpr->row_format = COERCE_IMPLICIT_CAST;
770 4 : rowexpr->colnames = colnames;
771 4 : rowexpr->location = var->location;
772 :
773 4 : return (Node *) rowexpr;
774 : }
775 :
776 : /* Expand join alias reference */
777 : Assert(var->varattno > 0);
778 320 : newvar = (Node *) list_nth(rte->joinaliasvars, var->varattno - 1);
779 : Assert(newvar != NULL);
780 320 : newvar = copyObject(newvar);
781 :
782 : /*
783 : * If we are expanding an alias carried down from an upper query, must
784 : * adjust its varlevelsup fields.
785 : */
786 320 : if (context->sublevels_up != 0)
787 0 : IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
788 :
789 : /* Preserve original Var's location, if possible */
790 320 : if (IsA(newvar, Var))
791 0 : ((Var *) newvar)->location = var->location;
792 :
793 : /* Recurse in case join input is itself a join */
794 320 : newvar = flatten_join_alias_vars_mutator(newvar, context);
795 :
796 : /* Detect if we are adding a sublink to query */
797 320 : if (context->possible_sublink && !context->inserted_sublink)
798 0 : context->inserted_sublink = checkExprHasSubLink(newvar);
799 :
800 320 : return newvar;
801 : }
802 2471596 : if (IsA(node, PlaceHolderVar))
803 : {
804 : /* Copy the PlaceHolderVar node with correct mutation of subnodes */
805 : PlaceHolderVar *phv;
806 :
807 852 : phv = (PlaceHolderVar *) expression_tree_mutator(node,
808 : flatten_join_alias_vars_mutator,
809 : (void *) context);
810 : /* now fix PlaceHolderVar's relid sets */
811 852 : if (phv->phlevelsup == context->sublevels_up)
812 : {
813 812 : phv->phrels = alias_relid_set(context->query,
814 : phv->phrels);
815 : }
816 852 : return (Node *) phv;
817 : }
818 :
819 2470744 : if (IsA(node, Query))
820 : {
821 : /* Recurse into RTE subquery or not-yet-planned sublink subquery */
822 : Query *newnode;
823 : bool save_inserted_sublink;
824 :
825 43962 : context->sublevels_up++;
826 43962 : save_inserted_sublink = context->inserted_sublink;
827 43962 : context->inserted_sublink = ((Query *) node)->hasSubLinks;
828 43962 : newnode = query_tree_mutator((Query *) node,
829 : flatten_join_alias_vars_mutator,
830 : (void *) context,
831 : QTW_IGNORE_JOINALIASES);
832 43962 : newnode->hasSubLinks |= context->inserted_sublink;
833 43962 : context->inserted_sublink = save_inserted_sublink;
834 43962 : context->sublevels_up--;
835 43962 : return (Node *) newnode;
836 : }
837 : /* Already-planned tree not supported */
838 : Assert(!IsA(node, SubPlan));
839 : /* Shouldn't need to handle these planner auxiliary nodes here */
840 : Assert(!IsA(node, SpecialJoinInfo));
841 : Assert(!IsA(node, PlaceHolderInfo));
842 : Assert(!IsA(node, MinMaxAggInfo));
843 :
844 2426782 : return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
845 : (void *) context);
846 : }
847 :
848 : /*
849 : * alias_relid_set: in a set of RT indexes, replace joins by their
850 : * underlying base relids
851 : */
852 : static Relids
853 812 : alias_relid_set(Query *query, Relids relids)
854 : {
855 812 : Relids result = NULL;
856 : int rtindex;
857 :
858 812 : rtindex = -1;
859 1860 : while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
860 : {
861 1048 : RangeTblEntry *rte = rt_fetch(rtindex, query->rtable);
862 :
863 1048 : if (rte->rtekind == RTE_JOIN)
864 0 : result = bms_join(result, get_relids_for_join(query, rtindex));
865 : else
866 1048 : result = bms_add_member(result, rtindex);
867 : }
868 812 : return result;
869 : }
|