1 /*-------------------------------------------------------------------------
2 *
3 * prepjointree.c
4 * Planner preprocessing for subqueries and join tree manipulation.
5 *
6 * NOTE: the intended sequence for invoking these operations is
7 * replace_empty_jointree
8 * pull_up_sublinks
9 * preprocess_function_rtes
10 * pull_up_subqueries
11 * flatten_simple_union_all
12 * do expression preprocessing (including flattening JOIN alias vars)
13 * reduce_outer_joins
14 * remove_useless_result_rtes
15 *
16 *
17 * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
18 * Portions Copyright (c) 1994, Regents of the University of California
19 *
20 *
21 * IDENTIFICATION
22 * src/backend/optimizer/prep/prepjointree.c
23 *
24 *-------------------------------------------------------------------------
25 */
26 #include "postgres.h"
27
28 #include "catalog/pg_type.h"
29 #include "funcapi.h"
30 #include "nodes/makefuncs.h"
31 #include "nodes/nodeFuncs.h"
32 #include "optimizer/clauses.h"
33 #include "optimizer/optimizer.h"
34 #include "optimizer/placeholder.h"
35 #include "optimizer/prep.h"
36 #include "optimizer/subselect.h"
37 #include "optimizer/tlist.h"
38 #include "parser/parse_relation.h"
39 #include "parser/parsetree.h"
40 #include "rewrite/rewriteManip.h"
41
42
43 typedef struct pullup_replace_vars_context
44 {
45 PlannerInfo *root;
46 List *targetlist; /* tlist of subquery being pulled up */
47 RangeTblEntry *target_rte; /* RTE of subquery */
48 Relids relids; /* relids within subquery, as numbered after
49 * pullup (set only if target_rte->lateral) */
50 bool *outer_hasSubLinks; /* -> outer query's hasSubLinks */
51 int varno; /* varno of subquery */
52 bool need_phvs; /* do we need PlaceHolderVars? */
53 bool wrap_non_vars; /* do we need 'em on *all* non-Vars? */
54 Node **rv_cache; /* cache for results with PHVs */
55 } pullup_replace_vars_context;
56
57 typedef struct reduce_outer_joins_state
58 {
59 Relids relids; /* base relids within this subtree */
60 bool contains_outer; /* does subtree contain outer join(s)? */
61 List *sub_states; /* List of states for subtree components */
62 } reduce_outer_joins_state;
63
64 static Node *pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
65 Relids *relids);
66 static Node *pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
67 Node **jtlink1, Relids available_rels1,
68 Node **jtlink2, Relids available_rels2);
69 static Node *pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
70 JoinExpr *lowest_outer_join,
71 JoinExpr *lowest_nulling_outer_join,
72 AppendRelInfo *containing_appendrel);
73 static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
74 RangeTblEntry *rte,
75 JoinExpr *lowest_outer_join,
76 JoinExpr *lowest_nulling_outer_join,
77 AppendRelInfo *containing_appendrel);
78 static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
79 RangeTblEntry *rte);
80 static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
81 int parentRTindex, Query *setOpQuery,
82 int childRToffset);
83 static void make_setop_translation_list(Query *query, Index newvarno,
84 AppendRelInfo *appinfo);
85 static bool is_simple_subquery(PlannerInfo *root, Query *subquery,
86 RangeTblEntry *rte,
87 JoinExpr *lowest_outer_join);
88 static Node *pull_up_simple_values(PlannerInfo *root, Node *jtnode,
89 RangeTblEntry *rte);
90 static bool is_simple_values(PlannerInfo *root, RangeTblEntry *rte);
91 static Node *pull_up_constant_function(PlannerInfo *root, Node *jtnode,
92 RangeTblEntry *rte,
93 JoinExpr *lowest_nulling_outer_join,
94 AppendRelInfo *containing_appendrel);
95 static bool is_simple_union_all(Query *subquery);
96 static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
97 List *colTypes);
98 static bool is_safe_append_member(Query *subquery);
99 static bool jointree_contains_lateral_outer_refs(PlannerInfo *root,
100 Node *jtnode, bool restricted,
101 Relids safe_upper_varnos);
102 static void perform_pullup_replace_vars(PlannerInfo *root,
103 pullup_replace_vars_context *rvcontext,
104 JoinExpr *lowest_nulling_outer_join,
105 AppendRelInfo *containing_appendrel);
106 static void replace_vars_in_jointree(Node *jtnode,
107 pullup_replace_vars_context *context,
108 JoinExpr *lowest_nulling_outer_join);
109 static Node *pullup_replace_vars(Node *expr,
110 pullup_replace_vars_context *context);
111 static Node *pullup_replace_vars_callback(Var *var,
112 replace_rte_variables_context *context);
113 static Query *pullup_replace_vars_subquery(Query *query,
114 pullup_replace_vars_context *context);
115 static reduce_outer_joins_state *reduce_outer_joins_pass1(Node *jtnode);
116 static void reduce_outer_joins_pass2(Node *jtnode,
117 reduce_outer_joins_state *state,
118 PlannerInfo *root,
119 Relids nonnullable_rels,
120 List *nonnullable_vars,
121 List *forced_null_vars);
122 static Node *remove_useless_results_recurse(PlannerInfo *root, Node *jtnode);
123 static int get_result_relid(PlannerInfo *root, Node *jtnode);
124 static void remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc);
125 static bool find_dependent_phvs(PlannerInfo *root, int varno);
126 static bool find_dependent_phvs_in_jointree(PlannerInfo *root,
127 Node *node, int varno);
128 static void substitute_phv_relids(Node *node,
129 int varno, Relids subrelids);
130 static void fix_append_rel_relids(List *append_rel_list, int varno,
131 Relids subrelids);
132 static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
133
134
135 /*
136 * replace_empty_jointree
137 * If the Query's jointree is empty, replace it with a dummy RTE_RESULT
138 * relation.
139 *
140 * By doing this, we can avoid a bunch of corner cases that formerly existed
141 * for SELECTs with omitted FROM clauses. An example is that a subquery
142 * with empty jointree previously could not be pulled up, because that would
143 * have resulted in an empty relid set, making the subquery not uniquely
144 * identifiable for join or PlaceHolderVar processing.
145 *
146 * Unlike most other functions in this file, this function doesn't recurse;
147 * we rely on other processing to invoke it on sub-queries at suitable times.
148 */
149 void
replace_empty_jointree(Query * parse)150 replace_empty_jointree(Query *parse)
151 {
152 RangeTblEntry *rte;
153 Index rti;
154 RangeTblRef *rtr;
155
156 /* Nothing to do if jointree is already nonempty */
157 if (parse->jointree->fromlist != NIL)
158 return;
159
160 /* We mustn't change it in the top level of a setop tree, either */
161 if (parse->setOperations)
162 return;
163
164 /* Create suitable RTE */
165 rte = makeNode(RangeTblEntry);
166 rte->rtekind = RTE_RESULT;
167 rte->eref = makeAlias("*RESULT*", NIL);
168
169 /* Add it to rangetable */
170 parse->rtable = lappend(parse->rtable, rte);
171 rti = list_length(parse->rtable);
172
173 /* And jam a reference into the jointree */
174 rtr = makeNode(RangeTblRef);
175 rtr->rtindex = rti;
176 parse->jointree->fromlist = list_make1(rtr);
177 }
178
179 /*
180 * pull_up_sublinks
181 * Attempt to pull up ANY and EXISTS SubLinks to be treated as
182 * semijoins or anti-semijoins.
183 *
184 * A clause "foo op ANY (sub-SELECT)" can be processed by pulling the
185 * sub-SELECT up to become a rangetable entry and treating the implied
186 * comparisons as quals of a semijoin. However, this optimization *only*
187 * works at the top level of WHERE or a JOIN/ON clause, because we cannot
188 * distinguish whether the ANY ought to return FALSE or NULL in cases
189 * involving NULL inputs. Also, in an outer join's ON clause we can only
190 * do this if the sublink is degenerate (ie, references only the nullable
191 * side of the join). In that case it is legal to push the semijoin
192 * down into the nullable side of the join. If the sublink references any
193 * nonnullable-side variables then it would have to be evaluated as part
194 * of the outer join, which makes things way too complicated.
195 *
196 * Under similar conditions, EXISTS and NOT EXISTS clauses can be handled
197 * by pulling up the sub-SELECT and creating a semijoin or anti-semijoin.
198 *
199 * This routine searches for such clauses and does the necessary parsetree
200 * transformations if any are found.
201 *
202 * This routine has to run before preprocess_expression(), so the quals
203 * clauses are not yet reduced to implicit-AND format, and are not guaranteed
204 * to be AND/OR-flat either. That means we need to recursively search through
205 * explicit AND clauses. We stop as soon as we hit a non-AND item.
206 */
207 void
pull_up_sublinks(PlannerInfo * root)208 pull_up_sublinks(PlannerInfo *root)
209 {
210 Node *jtnode;
211 Relids relids;
212
213 /* Begin recursion through the jointree */
214 jtnode = pull_up_sublinks_jointree_recurse(root,
215 (Node *) root->parse->jointree,
216 &relids);
217
218 /*
219 * root->parse->jointree must always be a FromExpr, so insert a dummy one
220 * if we got a bare RangeTblRef or JoinExpr out of the recursion.
221 */
222 if (IsA(jtnode, FromExpr))
223 root->parse->jointree = (FromExpr *) jtnode;
224 else
225 root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
226 }
227
228 /*
229 * Recurse through jointree nodes for pull_up_sublinks()
230 *
231 * In addition to returning the possibly-modified jointree node, we return
232 * a relids set of the contained rels into *relids.
233 */
234 static Node *
pull_up_sublinks_jointree_recurse(PlannerInfo * root,Node * jtnode,Relids * relids)235 pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
236 Relids *relids)
237 {
238 if (jtnode == NULL)
239 {
240 *relids = NULL;
241 }
242 else if (IsA(jtnode, RangeTblRef))
243 {
244 int varno = ((RangeTblRef *) jtnode)->rtindex;
245
246 *relids = bms_make_singleton(varno);
247 /* jtnode is returned unmodified */
248 }
249 else if (IsA(jtnode, FromExpr))
250 {
251 FromExpr *f = (FromExpr *) jtnode;
252 List *newfromlist = NIL;
253 Relids frelids = NULL;
254 FromExpr *newf;
255 Node *jtlink;
256 ListCell *l;
257
258 /* First, recurse to process children and collect their relids */
259 foreach(l, f->fromlist)
260 {
261 Node *newchild;
262 Relids childrelids;
263
264 newchild = pull_up_sublinks_jointree_recurse(root,
265 lfirst(l),
266 &childrelids);
267 newfromlist = lappend(newfromlist, newchild);
268 frelids = bms_join(frelids, childrelids);
269 }
270 /* Build the replacement FromExpr; no quals yet */
271 newf = makeFromExpr(newfromlist, NULL);
272 /* Set up a link representing the rebuilt jointree */
273 jtlink = (Node *) newf;
274 /* Now process qual --- all children are available for use */
275 newf->quals = pull_up_sublinks_qual_recurse(root, f->quals,
276 &jtlink, frelids,
277 NULL, NULL);
278
279 /*
280 * Note that the result will be either newf, or a stack of JoinExprs
281 * with newf at the base. We rely on subsequent optimization steps to
282 * flatten this and rearrange the joins as needed.
283 *
284 * Although we could include the pulled-up subqueries in the returned
285 * relids, there's no need since upper quals couldn't refer to their
286 * outputs anyway.
287 */
288 *relids = frelids;
289 jtnode = jtlink;
290 }
291 else if (IsA(jtnode, JoinExpr))
292 {
293 JoinExpr *j;
294 Relids leftrelids;
295 Relids rightrelids;
296 Node *jtlink;
297
298 /*
299 * Make a modifiable copy of join node, but don't bother copying its
300 * subnodes (yet).
301 */
302 j = (JoinExpr *) palloc(sizeof(JoinExpr));
303 memcpy(j, jtnode, sizeof(JoinExpr));
304 jtlink = (Node *) j;
305
306 /* Recurse to process children and collect their relids */
307 j->larg = pull_up_sublinks_jointree_recurse(root, j->larg,
308 &leftrelids);
309 j->rarg = pull_up_sublinks_jointree_recurse(root, j->rarg,
310 &rightrelids);
311
312 /*
313 * Now process qual, showing appropriate child relids as available,
314 * and attach any pulled-up jointree items at the right place. In the
315 * inner-join case we put new JoinExprs above the existing one (much
316 * as for a FromExpr-style join). In outer-join cases the new
317 * JoinExprs must go into the nullable side of the outer join. The
318 * point of the available_rels machinations is to ensure that we only
319 * pull up quals for which that's okay.
320 *
321 * We don't expect to see any pre-existing JOIN_SEMI or JOIN_ANTI
322 * nodes here.
323 */
324 switch (j->jointype)
325 {
326 case JOIN_INNER:
327 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
328 &jtlink,
329 bms_union(leftrelids,
330 rightrelids),
331 NULL, NULL);
332 break;
333 case JOIN_LEFT:
334 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
335 &j->rarg,
336 rightrelids,
337 NULL, NULL);
338 break;
339 case JOIN_FULL:
340 /* can't do anything with full-join quals */
341 break;
342 case JOIN_RIGHT:
343 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
344 &j->larg,
345 leftrelids,
346 NULL, NULL);
347 break;
348 default:
349 elog(ERROR, "unrecognized join type: %d",
350 (int) j->jointype);
351 break;
352 }
353
354 /*
355 * Although we could include the pulled-up subqueries in the returned
356 * relids, there's no need since upper quals couldn't refer to their
357 * outputs anyway. But we *do* need to include the join's own rtindex
358 * because we haven't yet collapsed join alias variables, so upper
359 * levels would mistakenly think they couldn't use references to this
360 * join.
361 */
362 *relids = bms_join(leftrelids, rightrelids);
363 if (j->rtindex)
364 *relids = bms_add_member(*relids, j->rtindex);
365 jtnode = jtlink;
366 }
367 else
368 elog(ERROR, "unrecognized node type: %d",
369 (int) nodeTag(jtnode));
370 return jtnode;
371 }
372
373 /*
374 * Recurse through top-level qual nodes for pull_up_sublinks()
375 *
376 * jtlink1 points to the link in the jointree where any new JoinExprs should
377 * be inserted if they reference available_rels1 (i.e., available_rels1
378 * denotes the relations present underneath jtlink1). Optionally, jtlink2 can
379 * point to a second link where new JoinExprs should be inserted if they
380 * reference available_rels2 (pass NULL for both those arguments if not used).
381 * Note that SubLinks referencing both sets of variables cannot be optimized.
382 * If we find multiple pull-up-able SubLinks, they'll get stacked onto jtlink1
383 * and/or jtlink2 in the order we encounter them. We rely on subsequent
384 * optimization to rearrange the stack if appropriate.
385 *
386 * Returns the replacement qual node, or NULL if the qual should be removed.
387 */
388 static Node *
pull_up_sublinks_qual_recurse(PlannerInfo * root,Node * node,Node ** jtlink1,Relids available_rels1,Node ** jtlink2,Relids available_rels2)389 pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
390 Node **jtlink1, Relids available_rels1,
391 Node **jtlink2, Relids available_rels2)
392 {
393 if (node == NULL)
394 return NULL;
395 if (IsA(node, SubLink))
396 {
397 SubLink *sublink = (SubLink *) node;
398 JoinExpr *j;
399 Relids child_rels;
400
401 /* Is it a convertible ANY or EXISTS clause? */
402 if (sublink->subLinkType == ANY_SUBLINK)
403 {
404 if ((j = convert_ANY_sublink_to_join(root, sublink,
405 available_rels1)) != NULL)
406 {
407 /* Yes; insert the new join node into the join tree */
408 j->larg = *jtlink1;
409 *jtlink1 = (Node *) j;
410 /* Recursively process pulled-up jointree nodes */
411 j->rarg = pull_up_sublinks_jointree_recurse(root,
412 j->rarg,
413 &child_rels);
414
415 /*
416 * Now recursively process the pulled-up quals. Any inserted
417 * joins can get stacked onto either j->larg or j->rarg,
418 * depending on which rels they reference.
419 */
420 j->quals = pull_up_sublinks_qual_recurse(root,
421 j->quals,
422 &j->larg,
423 available_rels1,
424 &j->rarg,
425 child_rels);
426 /* Return NULL representing constant TRUE */
427 return NULL;
428 }
429 if (available_rels2 != NULL &&
430 (j = convert_ANY_sublink_to_join(root, sublink,
431 available_rels2)) != NULL)
432 {
433 /* Yes; insert the new join node into the join tree */
434 j->larg = *jtlink2;
435 *jtlink2 = (Node *) j;
436 /* Recursively process pulled-up jointree nodes */
437 j->rarg = pull_up_sublinks_jointree_recurse(root,
438 j->rarg,
439 &child_rels);
440
441 /*
442 * Now recursively process the pulled-up quals. Any inserted
443 * joins can get stacked onto either j->larg or j->rarg,
444 * depending on which rels they reference.
445 */
446 j->quals = pull_up_sublinks_qual_recurse(root,
447 j->quals,
448 &j->larg,
449 available_rels2,
450 &j->rarg,
451 child_rels);
452 /* Return NULL representing constant TRUE */
453 return NULL;
454 }
455 }
456 else if (sublink->subLinkType == EXISTS_SUBLINK)
457 {
458 if ((j = convert_EXISTS_sublink_to_join(root, sublink, false,
459 available_rels1)) != NULL)
460 {
461 /* Yes; insert the new join node into the join tree */
462 j->larg = *jtlink1;
463 *jtlink1 = (Node *) j;
464 /* Recursively process pulled-up jointree nodes */
465 j->rarg = pull_up_sublinks_jointree_recurse(root,
466 j->rarg,
467 &child_rels);
468
469 /*
470 * Now recursively process the pulled-up quals. Any inserted
471 * joins can get stacked onto either j->larg or j->rarg,
472 * depending on which rels they reference.
473 */
474 j->quals = pull_up_sublinks_qual_recurse(root,
475 j->quals,
476 &j->larg,
477 available_rels1,
478 &j->rarg,
479 child_rels);
480 /* Return NULL representing constant TRUE */
481 return NULL;
482 }
483 if (available_rels2 != NULL &&
484 (j = convert_EXISTS_sublink_to_join(root, sublink, false,
485 available_rels2)) != NULL)
486 {
487 /* Yes; insert the new join node into the join tree */
488 j->larg = *jtlink2;
489 *jtlink2 = (Node *) j;
490 /* Recursively process pulled-up jointree nodes */
491 j->rarg = pull_up_sublinks_jointree_recurse(root,
492 j->rarg,
493 &child_rels);
494
495 /*
496 * Now recursively process the pulled-up quals. Any inserted
497 * joins can get stacked onto either j->larg or j->rarg,
498 * depending on which rels they reference.
499 */
500 j->quals = pull_up_sublinks_qual_recurse(root,
501 j->quals,
502 &j->larg,
503 available_rels2,
504 &j->rarg,
505 child_rels);
506 /* Return NULL representing constant TRUE */
507 return NULL;
508 }
509 }
510 /* Else return it unmodified */
511 return node;
512 }
513 if (is_notclause(node))
514 {
515 /* If the immediate argument of NOT is EXISTS, try to convert */
516 SubLink *sublink = (SubLink *) get_notclausearg((Expr *) node);
517 JoinExpr *j;
518 Relids child_rels;
519
520 if (sublink && IsA(sublink, SubLink))
521 {
522 if (sublink->subLinkType == EXISTS_SUBLINK)
523 {
524 if ((j = convert_EXISTS_sublink_to_join(root, sublink, true,
525 available_rels1)) != NULL)
526 {
527 /* Yes; insert the new join node into the join tree */
528 j->larg = *jtlink1;
529 *jtlink1 = (Node *) j;
530 /* Recursively process pulled-up jointree nodes */
531 j->rarg = pull_up_sublinks_jointree_recurse(root,
532 j->rarg,
533 &child_rels);
534
535 /*
536 * Now recursively process the pulled-up quals. Because
537 * we are underneath a NOT, we can't pull up sublinks that
538 * reference the left-hand stuff, but it's still okay to
539 * pull up sublinks referencing j->rarg.
540 */
541 j->quals = pull_up_sublinks_qual_recurse(root,
542 j->quals,
543 &j->rarg,
544 child_rels,
545 NULL, NULL);
546 /* Return NULL representing constant TRUE */
547 return NULL;
548 }
549 if (available_rels2 != NULL &&
550 (j = convert_EXISTS_sublink_to_join(root, sublink, true,
551 available_rels2)) != NULL)
552 {
553 /* Yes; insert the new join node into the join tree */
554 j->larg = *jtlink2;
555 *jtlink2 = (Node *) j;
556 /* Recursively process pulled-up jointree nodes */
557 j->rarg = pull_up_sublinks_jointree_recurse(root,
558 j->rarg,
559 &child_rels);
560
561 /*
562 * Now recursively process the pulled-up quals. Because
563 * we are underneath a NOT, we can't pull up sublinks that
564 * reference the left-hand stuff, but it's still okay to
565 * pull up sublinks referencing j->rarg.
566 */
567 j->quals = pull_up_sublinks_qual_recurse(root,
568 j->quals,
569 &j->rarg,
570 child_rels,
571 NULL, NULL);
572 /* Return NULL representing constant TRUE */
573 return NULL;
574 }
575 }
576 }
577 /* Else return it unmodified */
578 return node;
579 }
580 if (is_andclause(node))
581 {
582 /* Recurse into AND clause */
583 List *newclauses = NIL;
584 ListCell *l;
585
586 foreach(l, ((BoolExpr *) node)->args)
587 {
588 Node *oldclause = (Node *) lfirst(l);
589 Node *newclause;
590
591 newclause = pull_up_sublinks_qual_recurse(root,
592 oldclause,
593 jtlink1,
594 available_rels1,
595 jtlink2,
596 available_rels2);
597 if (newclause)
598 newclauses = lappend(newclauses, newclause);
599 }
600 /* We might have got back fewer clauses than we started with */
601 if (newclauses == NIL)
602 return NULL;
603 else if (list_length(newclauses) == 1)
604 return (Node *) linitial(newclauses);
605 else
606 return (Node *) make_andclause(newclauses);
607 }
608 /* Stop if not an AND */
609 return node;
610 }
611
612 /*
613 * preprocess_function_rtes
614 * Constant-simplify any FUNCTION RTEs in the FROM clause, and then
615 * attempt to "inline" any that are set-returning functions.
616 *
617 * If an RTE_FUNCTION rtable entry invokes a set-returning function that
618 * contains just a simple SELECT, we can convert the rtable entry to an
619 * RTE_SUBQUERY entry exposing the SELECT directly. This is especially
620 * useful if the subquery can then be "pulled up" for further optimization,
621 * but we do it even if not, to reduce executor overhead.
622 *
623 * This has to be done before we have started to do any optimization of
624 * subqueries, else any such steps wouldn't get applied to subqueries
625 * obtained via inlining. However, we do it after pull_up_sublinks
626 * so that we can inline any functions used in SubLink subselects.
627 *
628 * The reason for applying const-simplification at this stage is that
629 * (a) we'd need to do it anyway to inline a SRF, and (b) by doing it now,
630 * we can be sure that pull_up_constant_function() will see constants
631 * if there are constants to be seen. This approach also guarantees
632 * that every FUNCTION RTE has been const-simplified, allowing planner.c's
633 * preprocess_expression() to skip doing it again.
634 *
635 * Like most of the planner, this feels free to scribble on its input data
636 * structure.
637 */
638 void
preprocess_function_rtes(PlannerInfo * root)639 preprocess_function_rtes(PlannerInfo *root)
640 {
641 ListCell *rt;
642
643 foreach(rt, root->parse->rtable)
644 {
645 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
646
647 if (rte->rtekind == RTE_FUNCTION)
648 {
649 Query *funcquery;
650
651 /* Apply const-simplification */
652 rte->functions = (List *)
653 eval_const_expressions(root, (Node *) rte->functions);
654
655 /* Check safety of expansion, and expand if possible */
656 funcquery = inline_set_returning_function(root, rte);
657 if (funcquery)
658 {
659 /* Successful expansion, convert the RTE to a subquery */
660 rte->rtekind = RTE_SUBQUERY;
661 rte->subquery = funcquery;
662 rte->security_barrier = false;
663 /* Clear fields that should not be set in a subquery RTE */
664 rte->functions = NIL;
665 rte->funcordinality = false;
666 }
667 }
668 }
669 }
670
671 /*
672 * pull_up_subqueries
673 * Look for subqueries in the rangetable that can be pulled up into
674 * the parent query. If the subquery has no special features like
675 * grouping/aggregation then we can merge it into the parent's jointree.
676 * Also, subqueries that are simple UNION ALL structures can be
677 * converted into "append relations".
678 */
679 void
pull_up_subqueries(PlannerInfo * root)680 pull_up_subqueries(PlannerInfo *root)
681 {
682 /* Top level of jointree must always be a FromExpr */
683 Assert(IsA(root->parse->jointree, FromExpr));
684 /* Recursion starts with no containing join nor appendrel */
685 root->parse->jointree = (FromExpr *)
686 pull_up_subqueries_recurse(root, (Node *) root->parse->jointree,
687 NULL, NULL, NULL);
688 /* We should still have a FromExpr */
689 Assert(IsA(root->parse->jointree, FromExpr));
690 }
691
692 /*
693 * pull_up_subqueries_recurse
694 * Recursive guts of pull_up_subqueries.
695 *
696 * This recursively processes the jointree and returns a modified jointree.
697 *
698 * If this jointree node is within either side of an outer join, then
699 * lowest_outer_join references the lowest such JoinExpr node; otherwise
700 * it is NULL. We use this to constrain the effects of LATERAL subqueries.
701 *
702 * If this jointree node is within the nullable side of an outer join, then
703 * lowest_nulling_outer_join references the lowest such JoinExpr node;
704 * otherwise it is NULL. This forces use of the PlaceHolderVar mechanism for
705 * references to non-nullable targetlist items, but only for references above
706 * that join.
707 *
708 * If we are looking at a member subquery of an append relation,
709 * containing_appendrel describes that relation; else it is NULL.
710 * This forces use of the PlaceHolderVar mechanism for all non-Var targetlist
711 * items, and puts some additional restrictions on what can be pulled up.
712 *
713 * A tricky aspect of this code is that if we pull up a subquery we have
714 * to replace Vars that reference the subquery's outputs throughout the
715 * parent query, including quals attached to jointree nodes above the one
716 * we are currently processing! We handle this by being careful to maintain
717 * validity of the jointree structure while recursing, in the following sense:
718 * whenever we recurse, all qual expressions in the tree must be reachable
719 * from the top level, in case the recursive call needs to modify them.
720 *
721 * Notice also that we can't turn pullup_replace_vars loose on the whole
722 * jointree, because it'd return a mutated copy of the tree; we have to
723 * invoke it just on the quals, instead. This behavior is what makes it
724 * reasonable to pass lowest_outer_join and lowest_nulling_outer_join as
725 * pointers rather than some more-indirect way of identifying the lowest
726 * OJs. Likewise, we don't replace append_rel_list members but only their
727 * substructure, so the containing_appendrel reference is safe to use.
728 */
729 static Node *
pull_up_subqueries_recurse(PlannerInfo * root,Node * jtnode,JoinExpr * lowest_outer_join,JoinExpr * lowest_nulling_outer_join,AppendRelInfo * containing_appendrel)730 pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
731 JoinExpr *lowest_outer_join,
732 JoinExpr *lowest_nulling_outer_join,
733 AppendRelInfo *containing_appendrel)
734 {
735 Assert(jtnode != NULL);
736 if (IsA(jtnode, RangeTblRef))
737 {
738 int varno = ((RangeTblRef *) jtnode)->rtindex;
739 RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);
740
741 /*
742 * Is this a subquery RTE, and if so, is the subquery simple enough to
743 * pull up?
744 *
745 * If we are looking at an append-relation member, we can't pull it up
746 * unless is_safe_append_member says so.
747 */
748 if (rte->rtekind == RTE_SUBQUERY &&
749 is_simple_subquery(root, rte->subquery, rte, lowest_outer_join) &&
750 (containing_appendrel == NULL ||
751 is_safe_append_member(rte->subquery)))
752 return pull_up_simple_subquery(root, jtnode, rte,
753 lowest_outer_join,
754 lowest_nulling_outer_join,
755 containing_appendrel);
756
757 /*
758 * Alternatively, is it a simple UNION ALL subquery? If so, flatten
759 * into an "append relation".
760 *
761 * It's safe to do this regardless of whether this query is itself an
762 * appendrel member. (If you're thinking we should try to flatten the
763 * two levels of appendrel together, you're right; but we handle that
764 * in set_append_rel_pathlist, not here.)
765 */
766 if (rte->rtekind == RTE_SUBQUERY &&
767 is_simple_union_all(rte->subquery))
768 return pull_up_simple_union_all(root, jtnode, rte);
769
770 /*
771 * Or perhaps it's a simple VALUES RTE?
772 *
773 * We don't allow VALUES pullup below an outer join nor into an
774 * appendrel (such cases are impossible anyway at the moment).
775 */
776 if (rte->rtekind == RTE_VALUES &&
777 lowest_outer_join == NULL &&
778 containing_appendrel == NULL &&
779 is_simple_values(root, rte))
780 return pull_up_simple_values(root, jtnode, rte);
781
782 /*
783 * Or perhaps it's a FUNCTION RTE that we could inline?
784 */
785 if (rte->rtekind == RTE_FUNCTION)
786 return pull_up_constant_function(root, jtnode, rte,
787 lowest_nulling_outer_join,
788 containing_appendrel);
789
790 /* Otherwise, do nothing at this node. */
791 }
792 else if (IsA(jtnode, FromExpr))
793 {
794 FromExpr *f = (FromExpr *) jtnode;
795 ListCell *l;
796
797 Assert(containing_appendrel == NULL);
798 /* Recursively transform all the child nodes */
799 foreach(l, f->fromlist)
800 {
801 lfirst(l) = pull_up_subqueries_recurse(root, lfirst(l),
802 lowest_outer_join,
803 lowest_nulling_outer_join,
804 NULL);
805 }
806 }
807 else if (IsA(jtnode, JoinExpr))
808 {
809 JoinExpr *j = (JoinExpr *) jtnode;
810
811 Assert(containing_appendrel == NULL);
812 /* Recurse, being careful to tell myself when inside outer join */
813 switch (j->jointype)
814 {
815 case JOIN_INNER:
816 j->larg = pull_up_subqueries_recurse(root, j->larg,
817 lowest_outer_join,
818 lowest_nulling_outer_join,
819 NULL);
820 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
821 lowest_outer_join,
822 lowest_nulling_outer_join,
823 NULL);
824 break;
825 case JOIN_LEFT:
826 case JOIN_SEMI:
827 case JOIN_ANTI:
828 j->larg = pull_up_subqueries_recurse(root, j->larg,
829 j,
830 lowest_nulling_outer_join,
831 NULL);
832 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
833 j,
834 j,
835 NULL);
836 break;
837 case JOIN_FULL:
838 j->larg = pull_up_subqueries_recurse(root, j->larg,
839 j,
840 j,
841 NULL);
842 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
843 j,
844 j,
845 NULL);
846 break;
847 case JOIN_RIGHT:
848 j->larg = pull_up_subqueries_recurse(root, j->larg,
849 j,
850 j,
851 NULL);
852 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
853 j,
854 lowest_nulling_outer_join,
855 NULL);
856 break;
857 default:
858 elog(ERROR, "unrecognized join type: %d",
859 (int) j->jointype);
860 break;
861 }
862 }
863 else
864 elog(ERROR, "unrecognized node type: %d",
865 (int) nodeTag(jtnode));
866 return jtnode;
867 }
868
869 /*
870 * pull_up_simple_subquery
871 * Attempt to pull up a single simple subquery.
872 *
873 * jtnode is a RangeTblRef that has been tentatively identified as a simple
874 * subquery by pull_up_subqueries. We return the replacement jointree node,
875 * or jtnode itself if we determine that the subquery can't be pulled up
876 * after all.
877 *
878 * rte is the RangeTblEntry referenced by jtnode. Remaining parameters are
879 * as for pull_up_subqueries_recurse.
880 */
881 static Node *
pull_up_simple_subquery(PlannerInfo * root,Node * jtnode,RangeTblEntry * rte,JoinExpr * lowest_outer_join,JoinExpr * lowest_nulling_outer_join,AppendRelInfo * containing_appendrel)882 pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
883 JoinExpr *lowest_outer_join,
884 JoinExpr *lowest_nulling_outer_join,
885 AppendRelInfo *containing_appendrel)
886 {
887 Query *parse = root->parse;
888 int varno = ((RangeTblRef *) jtnode)->rtindex;
889 Query *subquery;
890 PlannerInfo *subroot;
891 int rtoffset;
892 pullup_replace_vars_context rvcontext;
893 ListCell *lc;
894
895 /*
896 * Need a modifiable copy of the subquery to hack on. Even if we didn't
897 * sometimes choose not to pull up below, we must do this to avoid
898 * problems if the same subquery is referenced from multiple jointree
899 * items (which can't happen normally, but might after rule rewriting).
900 */
901 subquery = copyObject(rte->subquery);
902
903 /*
904 * Create a PlannerInfo data structure for this subquery.
905 *
906 * NOTE: the next few steps should match the first processing in
907 * subquery_planner(). Can we refactor to avoid code duplication, or
908 * would that just make things uglier?
909 */
910 subroot = makeNode(PlannerInfo);
911 subroot->parse = subquery;
912 subroot->glob = root->glob;
913 subroot->query_level = root->query_level;
914 subroot->parent_root = root->parent_root;
915 subroot->plan_params = NIL;
916 subroot->outer_params = NULL;
917 subroot->planner_cxt = CurrentMemoryContext;
918 subroot->init_plans = NIL;
919 subroot->cte_plan_ids = NIL;
920 subroot->multiexpr_params = NIL;
921 subroot->eq_classes = NIL;
922 subroot->ec_merging_done = false;
923 subroot->all_result_relids = NULL;
924 subroot->leaf_result_relids = NULL;
925 subroot->append_rel_list = NIL;
926 subroot->row_identity_vars = NIL;
927 subroot->rowMarks = NIL;
928 memset(subroot->upper_rels, 0, sizeof(subroot->upper_rels));
929 memset(subroot->upper_targets, 0, sizeof(subroot->upper_targets));
930 subroot->processed_tlist = NIL;
931 subroot->update_colnos = NIL;
932 subroot->grouping_map = NULL;
933 subroot->minmax_aggs = NIL;
934 subroot->qual_security_level = 0;
935 subroot->hasRecursion = false;
936 subroot->wt_param_id = -1;
937 subroot->non_recursive_path = NULL;
938
939 /* No CTEs to worry about */
940 Assert(subquery->cteList == NIL);
941
942 /*
943 * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
944 * that we don't need so many special cases to deal with that situation.
945 */
946 replace_empty_jointree(subquery);
947
948 /*
949 * Pull up any SubLinks within the subquery's quals, so that we don't
950 * leave unoptimized SubLinks behind.
951 */
952 if (subquery->hasSubLinks)
953 pull_up_sublinks(subroot);
954
955 /*
956 * Similarly, preprocess its function RTEs to inline any set-returning
957 * functions in its rangetable.
958 */
959 preprocess_function_rtes(subroot);
960
961 /*
962 * Recursively pull up the subquery's subqueries, so that
963 * pull_up_subqueries' processing is complete for its jointree and
964 * rangetable.
965 *
966 * Note: it's okay that the subquery's recursion starts with NULL for
967 * containing-join info, even if we are within an outer join in the upper
968 * query; the lower query starts with a clean slate for outer-join
969 * semantics. Likewise, we needn't pass down appendrel state.
970 */
971 pull_up_subqueries(subroot);
972
973 /*
974 * Now we must recheck whether the subquery is still simple enough to pull
975 * up. If not, abandon processing it.
976 *
977 * We don't really need to recheck all the conditions involved, but it's
978 * easier just to keep this "if" looking the same as the one in
979 * pull_up_subqueries_recurse.
980 */
981 if (is_simple_subquery(root, subquery, rte, lowest_outer_join) &&
982 (containing_appendrel == NULL || is_safe_append_member(subquery)))
983 {
984 /* good to go */
985 }
986 else
987 {
988 /*
989 * Give up, return unmodified RangeTblRef.
990 *
991 * Note: The work we just did will be redone when the subquery gets
992 * planned on its own. Perhaps we could avoid that by storing the
993 * modified subquery back into the rangetable, but I'm not gonna risk
994 * it now.
995 */
996 return jtnode;
997 }
998
999 /*
1000 * We must flatten any join alias Vars in the subquery's targetlist,
1001 * because pulling up the subquery's subqueries might have changed their
1002 * expansions into arbitrary expressions, which could affect
1003 * pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
1004 * are needed for tlist entries. (Likely it'd be better to do
1005 * flatten_join_alias_vars on the whole query tree at some earlier stage,
1006 * maybe even in the rewriter; but for now let's just fix this case here.)
1007 */
1008 subquery->targetList = (List *)
1009 flatten_join_alias_vars(subroot->parse, (Node *) subquery->targetList);
1010
1011 /*
1012 * Adjust level-0 varnos in subquery so that we can append its rangetable
1013 * to upper query's. We have to fix the subquery's append_rel_list as
1014 * well.
1015 */
1016 rtoffset = list_length(parse->rtable);
1017 OffsetVarNodes((Node *) subquery, rtoffset, 0);
1018 OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
1019
1020 /*
1021 * Upper-level vars in subquery are now one level closer to their parent
1022 * than before.
1023 */
1024 IncrementVarSublevelsUp((Node *) subquery, -1, 1);
1025 IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
1026
1027 /*
1028 * The subquery's targetlist items are now in the appropriate form to
1029 * insert into the top query, except that we may need to wrap them in
1030 * PlaceHolderVars. Set up required context data for pullup_replace_vars.
1031 */
1032 rvcontext.root = root;
1033 rvcontext.targetlist = subquery->targetList;
1034 rvcontext.target_rte = rte;
1035 if (rte->lateral)
1036 rvcontext.relids = get_relids_in_jointree((Node *) subquery->jointree,
1037 true);
1038 else /* won't need relids */
1039 rvcontext.relids = NULL;
1040 rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1041 rvcontext.varno = varno;
1042 /* these flags will be set below, if needed */
1043 rvcontext.need_phvs = false;
1044 rvcontext.wrap_non_vars = false;
1045 /* initialize cache array with indexes 0 .. length(tlist) */
1046 rvcontext.rv_cache = palloc0((list_length(subquery->targetList) + 1) *
1047 sizeof(Node *));
1048
1049 /*
1050 * If we are under an outer join then non-nullable items and lateral
1051 * references may have to be turned into PlaceHolderVars.
1052 */
1053 if (lowest_nulling_outer_join != NULL)
1054 rvcontext.need_phvs = true;
1055
1056 /*
1057 * If we are dealing with an appendrel member then anything that's not a
1058 * simple Var has to be turned into a PlaceHolderVar. We force this to
1059 * ensure that what we pull up doesn't get merged into a surrounding
1060 * expression during later processing and then fail to match the
1061 * expression actually available from the appendrel.
1062 */
1063 if (containing_appendrel != NULL)
1064 {
1065 rvcontext.need_phvs = true;
1066 rvcontext.wrap_non_vars = true;
1067 }
1068
1069 /*
1070 * If the parent query uses grouping sets, we need a PlaceHolderVar for
1071 * anything that's not a simple Var. Again, this ensures that expressions
1072 * retain their separate identity so that they will match grouping set
1073 * columns when appropriate. (It'd be sufficient to wrap values used in
1074 * grouping set columns, and do so only in non-aggregated portions of the
1075 * tlist and havingQual, but that would require a lot of infrastructure
1076 * that pullup_replace_vars hasn't currently got.)
1077 */
1078 if (parse->groupingSets)
1079 {
1080 rvcontext.need_phvs = true;
1081 rvcontext.wrap_non_vars = true;
1082 }
1083
1084 /*
1085 * Replace all of the top query's references to the subquery's outputs
1086 * with copies of the adjusted subtlist items, being careful not to
1087 * replace any of the jointree structure.
1088 */
1089 perform_pullup_replace_vars(root, &rvcontext,
1090 lowest_nulling_outer_join,
1091 containing_appendrel);
1092
1093 /*
1094 * If the subquery had a LATERAL marker, propagate that to any of its
1095 * child RTEs that could possibly now contain lateral cross-references.
1096 * The children might or might not contain any actual lateral
1097 * cross-references, but we have to mark the pulled-up child RTEs so that
1098 * later planner stages will check for such.
1099 */
1100 if (rte->lateral)
1101 {
1102 foreach(lc, subquery->rtable)
1103 {
1104 RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(lc);
1105
1106 switch (child_rte->rtekind)
1107 {
1108 case RTE_RELATION:
1109 if (child_rte->tablesample)
1110 child_rte->lateral = true;
1111 break;
1112 case RTE_SUBQUERY:
1113 case RTE_FUNCTION:
1114 case RTE_VALUES:
1115 case RTE_TABLEFUNC:
1116 child_rte->lateral = true;
1117 break;
1118 case RTE_JOIN:
1119 case RTE_CTE:
1120 case RTE_NAMEDTUPLESTORE:
1121 case RTE_RESULT:
1122 /* these can't contain any lateral references */
1123 break;
1124 }
1125 }
1126 }
1127
1128 /*
1129 * Now append the adjusted rtable entries to upper query. (We hold off
1130 * until after fixing the upper rtable entries; no point in running that
1131 * code on the subquery ones too.)
1132 */
1133 parse->rtable = list_concat(parse->rtable, subquery->rtable);
1134
1135 /*
1136 * Pull up any FOR UPDATE/SHARE markers, too. (OffsetVarNodes already
1137 * adjusted the marker rtindexes, so just concat the lists.)
1138 */
1139 parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
1140
1141 /*
1142 * We also have to fix the relid sets of any PlaceHolderVar nodes in the
1143 * parent query. (This could perhaps be done by pullup_replace_vars(),
1144 * but it seems cleaner to use two passes.) Note in particular that any
1145 * PlaceHolderVar nodes just created by pullup_replace_vars() will be
1146 * adjusted, so having created them with the subquery's varno is correct.
1147 *
1148 * Likewise, relids appearing in AppendRelInfo nodes have to be fixed. We
1149 * already checked that this won't require introducing multiple subrelids
1150 * into the single-slot AppendRelInfo structs.
1151 */
1152 if (parse->hasSubLinks || root->glob->lastPHId != 0 ||
1153 root->append_rel_list)
1154 {
1155 Relids subrelids;
1156
1157 subrelids = get_relids_in_jointree((Node *) subquery->jointree, false);
1158 substitute_phv_relids((Node *) parse, varno, subrelids);
1159 fix_append_rel_relids(root->append_rel_list, varno, subrelids);
1160 }
1161
1162 /*
1163 * And now add subquery's AppendRelInfos to our list.
1164 */
1165 root->append_rel_list = list_concat(root->append_rel_list,
1166 subroot->append_rel_list);
1167
1168 /*
1169 * We don't have to do the equivalent bookkeeping for outer-join info,
1170 * because that hasn't been set up yet. placeholder_list likewise.
1171 */
1172 Assert(root->join_info_list == NIL);
1173 Assert(subroot->join_info_list == NIL);
1174 Assert(root->placeholder_list == NIL);
1175 Assert(subroot->placeholder_list == NIL);
1176
1177 /*
1178 * Miscellaneous housekeeping.
1179 *
1180 * Although replace_rte_variables() faithfully updated parse->hasSubLinks
1181 * if it copied any SubLinks out of the subquery's targetlist, we still
1182 * could have SubLinks added to the query in the expressions of FUNCTION
1183 * and VALUES RTEs copied up from the subquery. So it's necessary to copy
1184 * subquery->hasSubLinks anyway. Perhaps this can be improved someday.
1185 */
1186 parse->hasSubLinks |= subquery->hasSubLinks;
1187
1188 /* If subquery had any RLS conditions, now main query does too */
1189 parse->hasRowSecurity |= subquery->hasRowSecurity;
1190
1191 /*
1192 * subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
1193 * hasTargetSRFs, so no work needed on those flags
1194 */
1195
1196 /*
1197 * Return the adjusted subquery jointree to replace the RangeTblRef entry
1198 * in parent's jointree; or, if the FromExpr is degenerate, just return
1199 * its single member.
1200 */
1201 Assert(IsA(subquery->jointree, FromExpr));
1202 Assert(subquery->jointree->fromlist != NIL);
1203 if (subquery->jointree->quals == NULL &&
1204 list_length(subquery->jointree->fromlist) == 1)
1205 return (Node *) linitial(subquery->jointree->fromlist);
1206
1207 return (Node *) subquery->jointree;
1208 }
1209
1210 /*
1211 * pull_up_simple_union_all
1212 * Pull up a single simple UNION ALL subquery.
1213 *
1214 * jtnode is a RangeTblRef that has been identified as a simple UNION ALL
1215 * subquery by pull_up_subqueries. We pull up the leaf subqueries and
1216 * build an "append relation" for the union set. The result value is just
1217 * jtnode, since we don't actually need to change the query jointree.
1218 */
1219 static Node *
pull_up_simple_union_all(PlannerInfo * root,Node * jtnode,RangeTblEntry * rte)1220 pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
1221 {
1222 int varno = ((RangeTblRef *) jtnode)->rtindex;
1223 Query *subquery = rte->subquery;
1224 int rtoffset = list_length(root->parse->rtable);
1225 List *rtable;
1226
1227 /*
1228 * Make a modifiable copy of the subquery's rtable, so we can adjust
1229 * upper-level Vars in it. There are no such Vars in the setOperations
1230 * tree proper, so fixing the rtable should be sufficient.
1231 */
1232 rtable = copyObject(subquery->rtable);
1233
1234 /*
1235 * Upper-level vars in subquery are now one level closer to their parent
1236 * than before. We don't have to worry about offsetting varnos, though,
1237 * because the UNION leaf queries can't cross-reference each other.
1238 */
1239 IncrementVarSublevelsUp_rtable(rtable, -1, 1);
1240
1241 /*
1242 * If the UNION ALL subquery had a LATERAL marker, propagate that to all
1243 * its children. The individual children might or might not contain any
1244 * actual lateral cross-references, but we have to mark the pulled-up
1245 * child RTEs so that later planner stages will check for such.
1246 */
1247 if (rte->lateral)
1248 {
1249 ListCell *rt;
1250
1251 foreach(rt, rtable)
1252 {
1253 RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(rt);
1254
1255 Assert(child_rte->rtekind == RTE_SUBQUERY);
1256 child_rte->lateral = true;
1257 }
1258 }
1259
1260 /*
1261 * Append child RTEs to parent rtable.
1262 */
1263 root->parse->rtable = list_concat(root->parse->rtable, rtable);
1264
1265 /*
1266 * Recursively scan the subquery's setOperations tree and add
1267 * AppendRelInfo nodes for leaf subqueries to the parent's
1268 * append_rel_list. Also apply pull_up_subqueries to the leaf subqueries.
1269 */
1270 Assert(subquery->setOperations);
1271 pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
1272 rtoffset);
1273
1274 /*
1275 * Mark the parent as an append relation.
1276 */
1277 rte->inh = true;
1278
1279 return jtnode;
1280 }
1281
1282 /*
1283 * pull_up_union_leaf_queries -- recursive guts of pull_up_simple_union_all
1284 *
1285 * Build an AppendRelInfo for each leaf query in the setop tree, and then
1286 * apply pull_up_subqueries to the leaf query.
1287 *
1288 * Note that setOpQuery is the Query containing the setOp node, whose tlist
1289 * contains references to all the setop output columns. When called from
1290 * pull_up_simple_union_all, this is *not* the same as root->parse, which is
1291 * the parent Query we are pulling up into.
1292 *
1293 * parentRTindex is the appendrel parent's index in root->parse->rtable.
1294 *
1295 * The child RTEs have already been copied to the parent. childRToffset
1296 * tells us where in the parent's range table they were copied. When called
1297 * from flatten_simple_union_all, childRToffset is 0 since the child RTEs
1298 * were already in root->parse->rtable and no RT index adjustment is needed.
1299 */
1300 static void
pull_up_union_leaf_queries(Node * setOp,PlannerInfo * root,int parentRTindex,Query * setOpQuery,int childRToffset)1301 pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
1302 Query *setOpQuery, int childRToffset)
1303 {
1304 if (IsA(setOp, RangeTblRef))
1305 {
1306 RangeTblRef *rtr = (RangeTblRef *) setOp;
1307 int childRTindex;
1308 AppendRelInfo *appinfo;
1309
1310 /*
1311 * Calculate the index in the parent's range table
1312 */
1313 childRTindex = childRToffset + rtr->rtindex;
1314
1315 /*
1316 * Build a suitable AppendRelInfo, and attach to parent's list.
1317 */
1318 appinfo = makeNode(AppendRelInfo);
1319 appinfo->parent_relid = parentRTindex;
1320 appinfo->child_relid = childRTindex;
1321 appinfo->parent_reltype = InvalidOid;
1322 appinfo->child_reltype = InvalidOid;
1323 make_setop_translation_list(setOpQuery, childRTindex, appinfo);
1324 appinfo->parent_reloid = InvalidOid;
1325 root->append_rel_list = lappend(root->append_rel_list, appinfo);
1326
1327 /*
1328 * Recursively apply pull_up_subqueries to the new child RTE. (We
1329 * must build the AppendRelInfo first, because this will modify it.)
1330 * Note that we can pass NULL for containing-join info even if we're
1331 * actually under an outer join, because the child's expressions
1332 * aren't going to propagate up to the join. Also, we ignore the
1333 * possibility that pull_up_subqueries_recurse() returns a different
1334 * jointree node than what we pass it; if it does, the important thing
1335 * is that it replaced the child relid in the AppendRelInfo node.
1336 */
1337 rtr = makeNode(RangeTblRef);
1338 rtr->rtindex = childRTindex;
1339 (void) pull_up_subqueries_recurse(root, (Node *) rtr,
1340 NULL, NULL, appinfo);
1341 }
1342 else if (IsA(setOp, SetOperationStmt))
1343 {
1344 SetOperationStmt *op = (SetOperationStmt *) setOp;
1345
1346 /* Recurse to reach leaf queries */
1347 pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
1348 childRToffset);
1349 pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
1350 childRToffset);
1351 }
1352 else
1353 {
1354 elog(ERROR, "unrecognized node type: %d",
1355 (int) nodeTag(setOp));
1356 }
1357 }
1358
1359 /*
1360 * make_setop_translation_list
1361 * Build the list of translations from parent Vars to child Vars for
1362 * a UNION ALL member. (At this point it's just a simple list of
1363 * referencing Vars, but if we succeed in pulling up the member
1364 * subquery, the Vars will get replaced by pulled-up expressions.)
1365 * Also create the rather trivial reverse-translation array.
1366 */
1367 static void
make_setop_translation_list(Query * query,Index newvarno,AppendRelInfo * appinfo)1368 make_setop_translation_list(Query *query, Index newvarno,
1369 AppendRelInfo *appinfo)
1370 {
1371 List *vars = NIL;
1372 AttrNumber *pcolnos;
1373 ListCell *l;
1374
1375 /* Initialize reverse-translation array with all entries zero */
1376 /* (entries for resjunk columns will stay that way) */
1377 appinfo->num_child_cols = list_length(query->targetList);
1378 appinfo->parent_colnos = pcolnos =
1379 (AttrNumber *) palloc0(appinfo->num_child_cols * sizeof(AttrNumber));
1380
1381 foreach(l, query->targetList)
1382 {
1383 TargetEntry *tle = (TargetEntry *) lfirst(l);
1384
1385 if (tle->resjunk)
1386 continue;
1387
1388 vars = lappend(vars, makeVarFromTargetEntry(newvarno, tle));
1389 pcolnos[tle->resno - 1] = tle->resno;
1390 }
1391
1392 appinfo->translated_vars = vars;
1393 }
1394
1395 /*
1396 * is_simple_subquery
1397 * Check a subquery in the range table to see if it's simple enough
1398 * to pull up into the parent query.
1399 *
1400 * rte is the RTE_SUBQUERY RangeTblEntry that contained the subquery.
1401 * (Note subquery is not necessarily equal to rte->subquery; it could be a
1402 * processed copy of that.)
1403 * lowest_outer_join is the lowest outer join above the subquery, or NULL.
1404 */
1405 static bool
is_simple_subquery(PlannerInfo * root,Query * subquery,RangeTblEntry * rte,JoinExpr * lowest_outer_join)1406 is_simple_subquery(PlannerInfo *root, Query *subquery, RangeTblEntry *rte,
1407 JoinExpr *lowest_outer_join)
1408 {
1409 /*
1410 * Let's just make sure it's a valid subselect ...
1411 */
1412 if (!IsA(subquery, Query) ||
1413 subquery->commandType != CMD_SELECT)
1414 elog(ERROR, "subquery is bogus");
1415
1416 /*
1417 * Can't currently pull up a query with setops (unless it's simple UNION
1418 * ALL, which is handled by a different code path). Maybe after querytree
1419 * redesign...
1420 */
1421 if (subquery->setOperations)
1422 return false;
1423
1424 /*
1425 * Can't pull up a subquery involving grouping, aggregation, SRFs,
1426 * sorting, limiting, or WITH. (XXX WITH could possibly be allowed later)
1427 *
1428 * We also don't pull up a subquery that has explicit FOR UPDATE/SHARE
1429 * clauses, because pullup would cause the locking to occur semantically
1430 * higher than it should. Implicit FOR UPDATE/SHARE is okay because in
1431 * that case the locking was originally declared in the upper query
1432 * anyway.
1433 */
1434 if (subquery->hasAggs ||
1435 subquery->hasWindowFuncs ||
1436 subquery->hasTargetSRFs ||
1437 subquery->groupClause ||
1438 subquery->groupingSets ||
1439 subquery->havingQual ||
1440 subquery->sortClause ||
1441 subquery->distinctClause ||
1442 subquery->limitOffset ||
1443 subquery->limitCount ||
1444 subquery->hasForUpdate ||
1445 subquery->cteList)
1446 return false;
1447
1448 /*
1449 * Don't pull up if the RTE represents a security-barrier view; we
1450 * couldn't prevent information leakage once the RTE's Vars are scattered
1451 * about in the upper query.
1452 */
1453 if (rte->security_barrier)
1454 return false;
1455
1456 /*
1457 * If the subquery is LATERAL, check for pullup restrictions from that.
1458 */
1459 if (rte->lateral)
1460 {
1461 bool restricted;
1462 Relids safe_upper_varnos;
1463
1464 /*
1465 * The subquery's WHERE and JOIN/ON quals mustn't contain any lateral
1466 * references to rels outside a higher outer join (including the case
1467 * where the outer join is within the subquery itself). In such a
1468 * case, pulling up would result in a situation where we need to
1469 * postpone quals from below an outer join to above it, which is
1470 * probably completely wrong and in any case is a complication that
1471 * doesn't seem worth addressing at the moment.
1472 */
1473 if (lowest_outer_join != NULL)
1474 {
1475 restricted = true;
1476 safe_upper_varnos = get_relids_in_jointree((Node *) lowest_outer_join,
1477 true);
1478 }
1479 else
1480 {
1481 restricted = false;
1482 safe_upper_varnos = NULL; /* doesn't matter */
1483 }
1484
1485 if (jointree_contains_lateral_outer_refs(root,
1486 (Node *) subquery->jointree,
1487 restricted, safe_upper_varnos))
1488 return false;
1489
1490 /*
1491 * If there's an outer join above the LATERAL subquery, also disallow
1492 * pullup if the subquery's targetlist has any references to rels
1493 * outside the outer join, since these might get pulled into quals
1494 * above the subquery (but in or below the outer join) and then lead
1495 * to qual-postponement issues similar to the case checked for above.
1496 * (We wouldn't need to prevent pullup if no such references appear in
1497 * outer-query quals, but we don't have enough info here to check
1498 * that. Also, maybe this restriction could be removed if we forced
1499 * such refs to be wrapped in PlaceHolderVars, even when they're below
1500 * the nearest outer join? But it's a pretty hokey usage, so not
1501 * clear this is worth sweating over.)
1502 */
1503 if (lowest_outer_join != NULL)
1504 {
1505 Relids lvarnos = pull_varnos_of_level(root,
1506 (Node *) subquery->targetList,
1507 1);
1508
1509 if (!bms_is_subset(lvarnos, safe_upper_varnos))
1510 return false;
1511 }
1512 }
1513
1514 /*
1515 * Don't pull up a subquery that has any volatile functions in its
1516 * targetlist. Otherwise we might introduce multiple evaluations of these
1517 * functions, if they get copied to multiple places in the upper query,
1518 * leading to surprising results. (Note: the PlaceHolderVar mechanism
1519 * doesn't quite guarantee single evaluation; else we could pull up anyway
1520 * and just wrap such items in PlaceHolderVars ...)
1521 */
1522 if (contain_volatile_functions((Node *) subquery->targetList))
1523 return false;
1524
1525 return true;
1526 }
1527
1528 /*
1529 * pull_up_simple_values
1530 * Pull up a single simple VALUES RTE.
1531 *
1532 * jtnode is a RangeTblRef that has been identified as a simple VALUES RTE
1533 * by pull_up_subqueries. We always return a RangeTblRef representing a
1534 * RESULT RTE to replace it (all failure cases should have been detected by
1535 * is_simple_values()). Actually, what we return is just jtnode, because
1536 * we replace the VALUES RTE in the rangetable with the RESULT RTE.
1537 *
1538 * rte is the RangeTblEntry referenced by jtnode. Because of the limited
1539 * possible usage of VALUES RTEs, we do not need the remaining parameters
1540 * of pull_up_subqueries_recurse.
1541 */
1542 static Node *
pull_up_simple_values(PlannerInfo * root,Node * jtnode,RangeTblEntry * rte)1543 pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
1544 {
1545 Query *parse = root->parse;
1546 int varno = ((RangeTblRef *) jtnode)->rtindex;
1547 List *values_list;
1548 List *tlist;
1549 AttrNumber attrno;
1550 pullup_replace_vars_context rvcontext;
1551 ListCell *lc;
1552
1553 Assert(rte->rtekind == RTE_VALUES);
1554 Assert(list_length(rte->values_lists) == 1);
1555
1556 /*
1557 * Need a modifiable copy of the VALUES list to hack on, just in case it's
1558 * multiply referenced.
1559 */
1560 values_list = copyObject(linitial(rte->values_lists));
1561
1562 /*
1563 * The VALUES RTE can't contain any Vars of level zero, let alone any that
1564 * are join aliases, so no need to flatten join alias Vars.
1565 */
1566 Assert(!contain_vars_of_level((Node *) values_list, 0));
1567
1568 /*
1569 * Set up required context data for pullup_replace_vars. In particular,
1570 * we have to make the VALUES list look like a subquery targetlist.
1571 */
1572 tlist = NIL;
1573 attrno = 1;
1574 foreach(lc, values_list)
1575 {
1576 tlist = lappend(tlist,
1577 makeTargetEntry((Expr *) lfirst(lc),
1578 attrno,
1579 NULL,
1580 false));
1581 attrno++;
1582 }
1583 rvcontext.root = root;
1584 rvcontext.targetlist = tlist;
1585 rvcontext.target_rte = rte;
1586 rvcontext.relids = NULL;
1587 rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1588 rvcontext.varno = varno;
1589 rvcontext.need_phvs = false;
1590 rvcontext.wrap_non_vars = false;
1591 /* initialize cache array with indexes 0 .. length(tlist) */
1592 rvcontext.rv_cache = palloc0((list_length(tlist) + 1) *
1593 sizeof(Node *));
1594
1595 /*
1596 * Replace all of the top query's references to the RTE's outputs with
1597 * copies of the adjusted VALUES expressions, being careful not to replace
1598 * any of the jointree structure. We can assume there's no outer joins or
1599 * appendrels in the dummy Query that surrounds a VALUES RTE.
1600 */
1601 perform_pullup_replace_vars(root, &rvcontext, NULL, NULL);
1602
1603 /*
1604 * There should be no appendrels to fix, nor any outer joins and hence no
1605 * PlaceHolderVars.
1606 */
1607 Assert(root->append_rel_list == NIL);
1608 Assert(root->join_info_list == NIL);
1609 Assert(root->placeholder_list == NIL);
1610
1611 /*
1612 * Replace the VALUES RTE with a RESULT RTE. The VALUES RTE is the only
1613 * rtable entry in the current query level, so this is easy.
1614 */
1615 Assert(list_length(parse->rtable) == 1);
1616
1617 /* Create suitable RTE */
1618 rte = makeNode(RangeTblEntry);
1619 rte->rtekind = RTE_RESULT;
1620 rte->eref = makeAlias("*RESULT*", NIL);
1621
1622 /* Replace rangetable */
1623 parse->rtable = list_make1(rte);
1624
1625 /* We could manufacture a new RangeTblRef, but the one we have is fine */
1626 Assert(varno == 1);
1627
1628 return jtnode;
1629 }
1630
1631 /*
1632 * is_simple_values
1633 * Check a VALUES RTE in the range table to see if it's simple enough
1634 * to pull up into the parent query.
1635 *
1636 * rte is the RTE_VALUES RangeTblEntry to check.
1637 */
1638 static bool
is_simple_values(PlannerInfo * root,RangeTblEntry * rte)1639 is_simple_values(PlannerInfo *root, RangeTblEntry *rte)
1640 {
1641 Assert(rte->rtekind == RTE_VALUES);
1642
1643 /*
1644 * There must be exactly one VALUES list, else it's not semantically
1645 * correct to replace the VALUES RTE with a RESULT RTE, nor would we have
1646 * a unique set of expressions to substitute into the parent query.
1647 */
1648 if (list_length(rte->values_lists) != 1)
1649 return false;
1650
1651 /*
1652 * Because VALUES can't appear under an outer join (or at least, we won't
1653 * try to pull it up if it does), we need not worry about LATERAL, nor
1654 * about validity of PHVs for the VALUES' outputs.
1655 */
1656
1657 /*
1658 * Don't pull up a VALUES that contains any set-returning or volatile
1659 * functions. The considerations here are basically identical to the
1660 * restrictions on a pull-able subquery's targetlist.
1661 */
1662 if (expression_returns_set((Node *) rte->values_lists) ||
1663 contain_volatile_functions((Node *) rte->values_lists))
1664 return false;
1665
1666 /*
1667 * Do not pull up a VALUES that's not the only RTE in its parent query.
1668 * This is actually the only case that the parser will generate at the
1669 * moment, and assuming this is true greatly simplifies
1670 * pull_up_simple_values().
1671 */
1672 if (list_length(root->parse->rtable) != 1 ||
1673 rte != (RangeTblEntry *) linitial(root->parse->rtable))
1674 return false;
1675
1676 return true;
1677 }
1678
1679 /*
1680 * pull_up_constant_function
1681 * Pull up an RTE_FUNCTION expression that was simplified to a constant.
1682 *
1683 * jtnode is a RangeTblRef that has been identified as a FUNCTION RTE by
1684 * pull_up_subqueries. If its expression is just a Const, hoist that value
1685 * up into the parent query, and replace the RTE_FUNCTION with RTE_RESULT.
1686 *
1687 * In principle we could pull up any immutable expression, but we don't.
1688 * That might result in multiple evaluations of the expression, which could
1689 * be costly if it's not just a Const. Also, the main value of this is
1690 * to let the constant participate in further const-folding, and of course
1691 * that won't happen for a non-Const.
1692 *
1693 * The pulled-up value might need to be wrapped in a PlaceHolderVar if the
1694 * RTE is below an outer join or is part of an appendrel; the extra
1695 * parameters show whether that's needed.
1696 */
1697 static Node *
pull_up_constant_function(PlannerInfo * root,Node * jtnode,RangeTblEntry * rte,JoinExpr * lowest_nulling_outer_join,AppendRelInfo * containing_appendrel)1698 pull_up_constant_function(PlannerInfo *root, Node *jtnode,
1699 RangeTblEntry *rte,
1700 JoinExpr *lowest_nulling_outer_join,
1701 AppendRelInfo *containing_appendrel)
1702 {
1703 Query *parse = root->parse;
1704 RangeTblFunction *rtf;
1705 TypeFuncClass functypclass;
1706 Oid funcrettype;
1707 TupleDesc tupdesc;
1708 pullup_replace_vars_context rvcontext;
1709
1710 /* Fail if the RTE has ORDINALITY - we don't implement that here. */
1711 if (rte->funcordinality)
1712 return jtnode;
1713
1714 /* Fail if RTE isn't a single, simple Const expr */
1715 if (list_length(rte->functions) != 1)
1716 return jtnode;
1717 rtf = linitial_node(RangeTblFunction, rte->functions);
1718 if (!IsA(rtf->funcexpr, Const))
1719 return jtnode;
1720
1721 /*
1722 * If the function's result is not a scalar, we punt. In principle we
1723 * could break the composite constant value apart into per-column
1724 * constants, but for now it seems not worth the work.
1725 */
1726 if (rtf->funccolcount != 1)
1727 return jtnode; /* definitely composite */
1728
1729 functypclass = get_expr_result_type(rtf->funcexpr,
1730 &funcrettype,
1731 &tupdesc);
1732 if (functypclass != TYPEFUNC_SCALAR)
1733 return jtnode; /* must be a one-column composite type */
1734
1735 /* Create context for applying pullup_replace_vars */
1736 rvcontext.root = root;
1737 rvcontext.targetlist = list_make1(makeTargetEntry((Expr *) rtf->funcexpr,
1738 1, /* resno */
1739 NULL, /* resname */
1740 false)); /* resjunk */
1741 rvcontext.target_rte = rte;
1742
1743 /*
1744 * Since this function was reduced to a Const, it doesn't contain any
1745 * lateral references, even if it's marked as LATERAL. This means we
1746 * don't need to fill relids.
1747 */
1748 rvcontext.relids = NULL;
1749
1750 rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1751 rvcontext.varno = ((RangeTblRef *) jtnode)->rtindex;
1752 /* these flags will be set below, if needed */
1753 rvcontext.need_phvs = false;
1754 rvcontext.wrap_non_vars = false;
1755 /* initialize cache array with indexes 0 .. length(tlist) */
1756 rvcontext.rv_cache = palloc0((list_length(rvcontext.targetlist) + 1) *
1757 sizeof(Node *));
1758
1759 /*
1760 * If we are under an outer join then non-nullable items and lateral
1761 * references may have to be turned into PlaceHolderVars.
1762 */
1763 if (lowest_nulling_outer_join != NULL)
1764 rvcontext.need_phvs = true;
1765
1766 /*
1767 * If we are dealing with an appendrel member then anything that's not a
1768 * simple Var has to be turned into a PlaceHolderVar. (See comments in
1769 * pull_up_simple_subquery().)
1770 */
1771 if (containing_appendrel != NULL)
1772 {
1773 rvcontext.need_phvs = true;
1774 rvcontext.wrap_non_vars = true;
1775 }
1776
1777 /*
1778 * If the parent query uses grouping sets, we need a PlaceHolderVar for
1779 * anything that's not a simple Var.
1780 */
1781 if (parse->groupingSets)
1782 {
1783 rvcontext.need_phvs = true;
1784 rvcontext.wrap_non_vars = true;
1785 }
1786
1787 /*
1788 * Replace all of the top query's references to the RTE's output with
1789 * copies of the funcexpr, being careful not to replace any of the
1790 * jointree structure.
1791 */
1792 perform_pullup_replace_vars(root, &rvcontext,
1793 lowest_nulling_outer_join,
1794 containing_appendrel);
1795
1796 /*
1797 * We don't need to bother with changing PlaceHolderVars in the parent
1798 * query. Their references to the RT index are still good for now, and
1799 * will get removed later if we're able to drop the RTE_RESULT.
1800 */
1801
1802 /*
1803 * Convert the RTE to be RTE_RESULT type, signifying that we don't need to
1804 * scan it anymore, and zero out RTE_FUNCTION-specific fields. Also make
1805 * sure the RTE is not marked LATERAL, since elsewhere we don't expect
1806 * RTE_RESULTs to be LATERAL.
1807 */
1808 rte->rtekind = RTE_RESULT;
1809 rte->functions = NIL;
1810 rte->lateral = false;
1811
1812 /*
1813 * We can reuse the RangeTblRef node.
1814 */
1815 return jtnode;
1816 }
1817
1818 /*
1819 * is_simple_union_all
1820 * Check a subquery to see if it's a simple UNION ALL.
1821 *
1822 * We require all the setops to be UNION ALL (no mixing) and there can't be
1823 * any datatype coercions involved, ie, all the leaf queries must emit the
1824 * same datatypes.
1825 */
1826 static bool
is_simple_union_all(Query * subquery)1827 is_simple_union_all(Query *subquery)
1828 {
1829 SetOperationStmt *topop;
1830
1831 /* Let's just make sure it's a valid subselect ... */
1832 if (!IsA(subquery, Query) ||
1833 subquery->commandType != CMD_SELECT)
1834 elog(ERROR, "subquery is bogus");
1835
1836 /* Is it a set-operation query at all? */
1837 topop = castNode(SetOperationStmt, subquery->setOperations);
1838 if (!topop)
1839 return false;
1840
1841 /* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */
1842 if (subquery->sortClause ||
1843 subquery->limitOffset ||
1844 subquery->limitCount ||
1845 subquery->rowMarks ||
1846 subquery->cteList)
1847 return false;
1848
1849 /* Recursively check the tree of set operations */
1850 return is_simple_union_all_recurse((Node *) topop, subquery,
1851 topop->colTypes);
1852 }
1853
1854 static bool
is_simple_union_all_recurse(Node * setOp,Query * setOpQuery,List * colTypes)1855 is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
1856 {
1857 if (IsA(setOp, RangeTblRef))
1858 {
1859 RangeTblRef *rtr = (RangeTblRef *) setOp;
1860 RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
1861 Query *subquery = rte->subquery;
1862
1863 Assert(subquery != NULL);
1864
1865 /* Leaf nodes are OK if they match the toplevel column types */
1866 /* We don't have to compare typmods or collations here */
1867 return tlist_same_datatypes(subquery->targetList, colTypes, true);
1868 }
1869 else if (IsA(setOp, SetOperationStmt))
1870 {
1871 SetOperationStmt *op = (SetOperationStmt *) setOp;
1872
1873 /* Must be UNION ALL */
1874 if (op->op != SETOP_UNION || !op->all)
1875 return false;
1876
1877 /* Recurse to check inputs */
1878 return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) &&
1879 is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes);
1880 }
1881 else
1882 {
1883 elog(ERROR, "unrecognized node type: %d",
1884 (int) nodeTag(setOp));
1885 return false; /* keep compiler quiet */
1886 }
1887 }
1888
1889 /*
1890 * is_safe_append_member
1891 * Check a subquery that is a leaf of a UNION ALL appendrel to see if it's
1892 * safe to pull up.
1893 */
1894 static bool
is_safe_append_member(Query * subquery)1895 is_safe_append_member(Query *subquery)
1896 {
1897 FromExpr *jtnode;
1898
1899 /*
1900 * It's only safe to pull up the child if its jointree contains exactly
1901 * one RTE, else the AppendRelInfo data structure breaks. The one base RTE
1902 * could be buried in several levels of FromExpr, however. Also, if the
1903 * child's jointree is completely empty, we can pull up because
1904 * pull_up_simple_subquery will insert a single RTE_RESULT RTE instead.
1905 *
1906 * Also, the child can't have any WHERE quals because there's no place to
1907 * put them in an appendrel. (This is a bit annoying...) If we didn't
1908 * need to check this, we'd just test whether get_relids_in_jointree()
1909 * yields a singleton set, to be more consistent with the coding of
1910 * fix_append_rel_relids().
1911 */
1912 jtnode = subquery->jointree;
1913 Assert(IsA(jtnode, FromExpr));
1914 /* Check the completely-empty case */
1915 if (jtnode->fromlist == NIL && jtnode->quals == NULL)
1916 return true;
1917 /* Check the more general case */
1918 while (IsA(jtnode, FromExpr))
1919 {
1920 if (jtnode->quals != NULL)
1921 return false;
1922 if (list_length(jtnode->fromlist) != 1)
1923 return false;
1924 jtnode = linitial(jtnode->fromlist);
1925 }
1926 if (!IsA(jtnode, RangeTblRef))
1927 return false;
1928
1929 return true;
1930 }
1931
1932 /*
1933 * jointree_contains_lateral_outer_refs
1934 * Check for disallowed lateral references in a jointree's quals
1935 *
1936 * If restricted is false, all level-1 Vars are allowed (but we still must
1937 * search the jointree, since it might contain outer joins below which there
1938 * will be restrictions). If restricted is true, return true when any qual
1939 * in the jointree contains level-1 Vars coming from outside the rels listed
1940 * in safe_upper_varnos.
1941 */
1942 static bool
jointree_contains_lateral_outer_refs(PlannerInfo * root,Node * jtnode,bool restricted,Relids safe_upper_varnos)1943 jointree_contains_lateral_outer_refs(PlannerInfo *root, Node *jtnode,
1944 bool restricted,
1945 Relids safe_upper_varnos)
1946 {
1947 if (jtnode == NULL)
1948 return false;
1949 if (IsA(jtnode, RangeTblRef))
1950 return false;
1951 else if (IsA(jtnode, FromExpr))
1952 {
1953 FromExpr *f = (FromExpr *) jtnode;
1954 ListCell *l;
1955
1956 /* First, recurse to check child joins */
1957 foreach(l, f->fromlist)
1958 {
1959 if (jointree_contains_lateral_outer_refs(root,
1960 lfirst(l),
1961 restricted,
1962 safe_upper_varnos))
1963 return true;
1964 }
1965
1966 /* Then check the top-level quals */
1967 if (restricted &&
1968 !bms_is_subset(pull_varnos_of_level(root, f->quals, 1),
1969 safe_upper_varnos))
1970 return true;
1971 }
1972 else if (IsA(jtnode, JoinExpr))
1973 {
1974 JoinExpr *j = (JoinExpr *) jtnode;
1975
1976 /*
1977 * If this is an outer join, we mustn't allow any upper lateral
1978 * references in or below it.
1979 */
1980 if (j->jointype != JOIN_INNER)
1981 {
1982 restricted = true;
1983 safe_upper_varnos = NULL;
1984 }
1985
1986 /* Check the child joins */
1987 if (jointree_contains_lateral_outer_refs(root,
1988 j->larg,
1989 restricted,
1990 safe_upper_varnos))
1991 return true;
1992 if (jointree_contains_lateral_outer_refs(root,
1993 j->rarg,
1994 restricted,
1995 safe_upper_varnos))
1996 return true;
1997
1998 /* Check the JOIN's qual clauses */
1999 if (restricted &&
2000 !bms_is_subset(pull_varnos_of_level(root, j->quals, 1),
2001 safe_upper_varnos))
2002 return true;
2003 }
2004 else
2005 elog(ERROR, "unrecognized node type: %d",
2006 (int) nodeTag(jtnode));
2007 return false;
2008 }
2009
2010 /*
2011 * Perform pullup_replace_vars everyplace it's needed in the query tree.
2012 *
2013 * Caller has already filled *rvcontext with data describing what to
2014 * substitute for Vars referencing the target subquery. In addition
2015 * we need the identity of the lowest outer join that can null the
2016 * target subquery, and its containing appendrel if any.
2017 */
2018 static void
perform_pullup_replace_vars(PlannerInfo * root,pullup_replace_vars_context * rvcontext,JoinExpr * lowest_nulling_outer_join,AppendRelInfo * containing_appendrel)2019 perform_pullup_replace_vars(PlannerInfo *root,
2020 pullup_replace_vars_context *rvcontext,
2021 JoinExpr *lowest_nulling_outer_join,
2022 AppendRelInfo *containing_appendrel)
2023 {
2024 Query *parse = root->parse;
2025 ListCell *lc;
2026
2027 /*
2028 * Replace all of the top query's references to the subquery's outputs
2029 * with copies of the adjusted subtlist items, being careful not to
2030 * replace any of the jointree structure. (This'd be a lot cleaner if we
2031 * could use query_tree_mutator.) We have to use PHVs in the targetList,
2032 * returningList, and havingQual, since those are certainly above any
2033 * outer join. replace_vars_in_jointree tracks its location in the
2034 * jointree and uses PHVs or not appropriately.
2035 */
2036 parse->targetList = (List *)
2037 pullup_replace_vars((Node *) parse->targetList, rvcontext);
2038 parse->returningList = (List *)
2039 pullup_replace_vars((Node *) parse->returningList, rvcontext);
2040 if (parse->onConflict)
2041 {
2042 parse->onConflict->onConflictSet = (List *)
2043 pullup_replace_vars((Node *) parse->onConflict->onConflictSet,
2044 rvcontext);
2045 parse->onConflict->onConflictWhere =
2046 pullup_replace_vars(parse->onConflict->onConflictWhere,
2047 rvcontext);
2048
2049 /*
2050 * We assume ON CONFLICT's arbiterElems, arbiterWhere, exclRelTlist
2051 * can't contain any references to a subquery.
2052 */
2053 }
2054 replace_vars_in_jointree((Node *) parse->jointree, rvcontext,
2055 lowest_nulling_outer_join);
2056 Assert(parse->setOperations == NULL);
2057 parse->havingQual = pullup_replace_vars(parse->havingQual, rvcontext);
2058
2059 /*
2060 * Replace references in the translated_vars lists of appendrels. When
2061 * pulling up an appendrel member, we do not need PHVs in the list of the
2062 * parent appendrel --- there isn't any outer join between. Elsewhere,
2063 * use PHVs for safety. (This analysis could be made tighter but it seems
2064 * unlikely to be worth much trouble.)
2065 */
2066 foreach(lc, root->append_rel_list)
2067 {
2068 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
2069 bool save_need_phvs = rvcontext->need_phvs;
2070
2071 if (appinfo == containing_appendrel)
2072 rvcontext->need_phvs = false;
2073 appinfo->translated_vars = (List *)
2074 pullup_replace_vars((Node *) appinfo->translated_vars, rvcontext);
2075 rvcontext->need_phvs = save_need_phvs;
2076 }
2077
2078 /*
2079 * Replace references in the joinaliasvars lists of join RTEs.
2080 *
2081 * You might think that we could avoid using PHVs for alias vars of joins
2082 * below lowest_nulling_outer_join, but that doesn't work because the
2083 * alias vars could be referenced above that join; we need the PHVs to be
2084 * present in such references after the alias vars get flattened. (It
2085 * might be worth trying to be smarter here, someday.)
2086 */
2087 foreach(lc, parse->rtable)
2088 {
2089 RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(lc);
2090
2091 if (otherrte->rtekind == RTE_JOIN)
2092 otherrte->joinaliasvars = (List *)
2093 pullup_replace_vars((Node *) otherrte->joinaliasvars,
2094 rvcontext);
2095 }
2096 }
2097
2098 /*
2099 * Helper routine for perform_pullup_replace_vars: do pullup_replace_vars on
2100 * every expression in the jointree, without changing the jointree structure
2101 * itself. Ugly, but there's no other way...
2102 *
2103 * If we are at or below lowest_nulling_outer_join, we can suppress use of
2104 * PlaceHolderVars wrapped around the replacement expressions.
2105 */
2106 static void
replace_vars_in_jointree(Node * jtnode,pullup_replace_vars_context * context,JoinExpr * lowest_nulling_outer_join)2107 replace_vars_in_jointree(Node *jtnode,
2108 pullup_replace_vars_context *context,
2109 JoinExpr *lowest_nulling_outer_join)
2110 {
2111 if (jtnode == NULL)
2112 return;
2113 if (IsA(jtnode, RangeTblRef))
2114 {
2115 /*
2116 * If the RangeTblRef refers to a LATERAL subquery (that isn't the
2117 * same subquery we're pulling up), it might contain references to the
2118 * target subquery, which we must replace. We drive this from the
2119 * jointree scan, rather than a scan of the rtable, for a couple of
2120 * reasons: we can avoid processing no-longer-referenced RTEs, and we
2121 * can use the appropriate setting of need_phvs depending on whether
2122 * the RTE is above possibly-nulling outer joins or not.
2123 */
2124 int varno = ((RangeTblRef *) jtnode)->rtindex;
2125
2126 if (varno != context->varno) /* ignore target subquery itself */
2127 {
2128 RangeTblEntry *rte = rt_fetch(varno, context->root->parse->rtable);
2129
2130 Assert(rte != context->target_rte);
2131 if (rte->lateral)
2132 {
2133 switch (rte->rtekind)
2134 {
2135 case RTE_RELATION:
2136 /* shouldn't be marked LATERAL unless tablesample */
2137 Assert(rte->tablesample);
2138 rte->tablesample = (TableSampleClause *)
2139 pullup_replace_vars((Node *) rte->tablesample,
2140 context);
2141 break;
2142 case RTE_SUBQUERY:
2143 rte->subquery =
2144 pullup_replace_vars_subquery(rte->subquery,
2145 context);
2146 break;
2147 case RTE_FUNCTION:
2148 rte->functions = (List *)
2149 pullup_replace_vars((Node *) rte->functions,
2150 context);
2151 break;
2152 case RTE_TABLEFUNC:
2153 rte->tablefunc = (TableFunc *)
2154 pullup_replace_vars((Node *) rte->tablefunc,
2155 context);
2156 break;
2157 case RTE_VALUES:
2158 rte->values_lists = (List *)
2159 pullup_replace_vars((Node *) rte->values_lists,
2160 context);
2161 break;
2162 case RTE_JOIN:
2163 case RTE_CTE:
2164 case RTE_NAMEDTUPLESTORE:
2165 case RTE_RESULT:
2166 /* these shouldn't be marked LATERAL */
2167 Assert(false);
2168 break;
2169 }
2170 }
2171 }
2172 }
2173 else if (IsA(jtnode, FromExpr))
2174 {
2175 FromExpr *f = (FromExpr *) jtnode;
2176 ListCell *l;
2177
2178 foreach(l, f->fromlist)
2179 replace_vars_in_jointree(lfirst(l), context,
2180 lowest_nulling_outer_join);
2181 f->quals = pullup_replace_vars(f->quals, context);
2182 }
2183 else if (IsA(jtnode, JoinExpr))
2184 {
2185 JoinExpr *j = (JoinExpr *) jtnode;
2186 bool save_need_phvs = context->need_phvs;
2187
2188 if (j == lowest_nulling_outer_join)
2189 {
2190 /* no more PHVs in or below this join */
2191 context->need_phvs = false;
2192 lowest_nulling_outer_join = NULL;
2193 }
2194 replace_vars_in_jointree(j->larg, context, lowest_nulling_outer_join);
2195 replace_vars_in_jointree(j->rarg, context, lowest_nulling_outer_join);
2196
2197 /*
2198 * Use PHVs within the join quals of a full join, even when it's the
2199 * lowest nulling outer join. Otherwise, we cannot identify which
2200 * side of the join a pulled-up var-free expression came from, which
2201 * can lead to failure to make a plan at all because none of the quals
2202 * appear to be mergeable or hashable conditions. For this purpose we
2203 * don't care about the state of wrap_non_vars, so leave it alone.
2204 */
2205 if (j->jointype == JOIN_FULL)
2206 context->need_phvs = true;
2207
2208 j->quals = pullup_replace_vars(j->quals, context);
2209
2210 /*
2211 * We don't bother to update the colvars list, since it won't be used
2212 * again ...
2213 */
2214 context->need_phvs = save_need_phvs;
2215 }
2216 else
2217 elog(ERROR, "unrecognized node type: %d",
2218 (int) nodeTag(jtnode));
2219 }
2220
2221 /*
2222 * Apply pullup variable replacement throughout an expression tree
2223 *
2224 * Returns a modified copy of the tree, so this can't be used where we
2225 * need to do in-place replacement.
2226 */
2227 static Node *
pullup_replace_vars(Node * expr,pullup_replace_vars_context * context)2228 pullup_replace_vars(Node *expr, pullup_replace_vars_context *context)
2229 {
2230 return replace_rte_variables(expr,
2231 context->varno, 0,
2232 pullup_replace_vars_callback,
2233 (void *) context,
2234 context->outer_hasSubLinks);
2235 }
2236
2237 static Node *
pullup_replace_vars_callback(Var * var,replace_rte_variables_context * context)2238 pullup_replace_vars_callback(Var *var,
2239 replace_rte_variables_context *context)
2240 {
2241 pullup_replace_vars_context *rcon = (pullup_replace_vars_context *) context->callback_arg;
2242 int varattno = var->varattno;
2243 Node *newnode;
2244
2245 /*
2246 * If PlaceHolderVars are needed, we cache the modified expressions in
2247 * rcon->rv_cache[]. This is not in hopes of any material speed gain
2248 * within this function, but to avoid generating identical PHVs with
2249 * different IDs. That would result in duplicate evaluations at runtime,
2250 * and possibly prevent optimizations that rely on recognizing different
2251 * references to the same subquery output as being equal(). So it's worth
2252 * a bit of extra effort to avoid it.
2253 */
2254 if (rcon->need_phvs &&
2255 varattno >= InvalidAttrNumber &&
2256 varattno <= list_length(rcon->targetlist) &&
2257 rcon->rv_cache[varattno] != NULL)
2258 {
2259 /* Just copy the entry and fall through to adjust its varlevelsup */
2260 newnode = copyObject(rcon->rv_cache[varattno]);
2261 }
2262 else if (varattno == InvalidAttrNumber)
2263 {
2264 /* Must expand whole-tuple reference into RowExpr */
2265 RowExpr *rowexpr;
2266 List *colnames;
2267 List *fields;
2268 bool save_need_phvs = rcon->need_phvs;
2269 int save_sublevelsup = context->sublevels_up;
2270
2271 /*
2272 * If generating an expansion for a var of a named rowtype (ie, this
2273 * is a plain relation RTE), then we must include dummy items for
2274 * dropped columns. If the var is RECORD (ie, this is a JOIN), then
2275 * omit dropped columns. Either way, attach column names to the
2276 * RowExpr for use of ruleutils.c.
2277 *
2278 * In order to be able to cache the results, we always generate the
2279 * expansion with varlevelsup = 0, and then adjust if needed.
2280 */
2281 expandRTE(rcon->target_rte,
2282 var->varno, 0 /* not varlevelsup */ , var->location,
2283 (var->vartype != RECORDOID),
2284 &colnames, &fields);
2285 /* Adjust the generated per-field Vars, but don't insert PHVs */
2286 rcon->need_phvs = false;
2287 context->sublevels_up = 0; /* to match the expandRTE output */
2288 fields = (List *) replace_rte_variables_mutator((Node *) fields,
2289 context);
2290 rcon->need_phvs = save_need_phvs;
2291 context->sublevels_up = save_sublevelsup;
2292
2293 rowexpr = makeNode(RowExpr);
2294 rowexpr->args = fields;
2295 rowexpr->row_typeid = var->vartype;
2296 rowexpr->row_format = COERCE_IMPLICIT_CAST;
2297 rowexpr->colnames = colnames;
2298 rowexpr->location = var->location;
2299 newnode = (Node *) rowexpr;
2300
2301 /*
2302 * Insert PlaceHolderVar if needed. Notice that we are wrapping one
2303 * PlaceHolderVar around the whole RowExpr, rather than putting one
2304 * around each element of the row. This is because we need the
2305 * expression to yield NULL, not ROW(NULL,NULL,...) when it is forced
2306 * to null by an outer join.
2307 */
2308 if (rcon->need_phvs)
2309 {
2310 /* RowExpr is certainly not strict, so always need PHV */
2311 newnode = (Node *)
2312 make_placeholder_expr(rcon->root,
2313 (Expr *) newnode,
2314 bms_make_singleton(rcon->varno));
2315 /* cache it with the PHV, and with varlevelsup still zero */
2316 rcon->rv_cache[InvalidAttrNumber] = copyObject(newnode);
2317 }
2318 }
2319 else
2320 {
2321 /* Normal case referencing one targetlist element */
2322 TargetEntry *tle = get_tle_by_resno(rcon->targetlist, varattno);
2323
2324 if (tle == NULL) /* shouldn't happen */
2325 elog(ERROR, "could not find attribute %d in subquery targetlist",
2326 varattno);
2327
2328 /* Make a copy of the tlist item to return */
2329 newnode = (Node *) copyObject(tle->expr);
2330
2331 /* Insert PlaceHolderVar if needed */
2332 if (rcon->need_phvs)
2333 {
2334 bool wrap;
2335
2336 if (newnode && IsA(newnode, Var) &&
2337 ((Var *) newnode)->varlevelsup == 0)
2338 {
2339 /*
2340 * Simple Vars always escape being wrapped, unless they are
2341 * lateral references to something outside the subquery being
2342 * pulled up. (Even then, we could omit the PlaceHolderVar if
2343 * the referenced rel is under the same lowest outer join, but
2344 * it doesn't seem worth the trouble to check that.)
2345 */
2346 if (rcon->target_rte->lateral &&
2347 !bms_is_member(((Var *) newnode)->varno, rcon->relids))
2348 wrap = true;
2349 else
2350 wrap = false;
2351 }
2352 else if (newnode && IsA(newnode, PlaceHolderVar) &&
2353 ((PlaceHolderVar *) newnode)->phlevelsup == 0)
2354 {
2355 /* No need to wrap a PlaceHolderVar with another one, either */
2356 wrap = false;
2357 }
2358 else if (rcon->wrap_non_vars)
2359 {
2360 /* Wrap all non-Vars in a PlaceHolderVar */
2361 wrap = true;
2362 }
2363 else
2364 {
2365 /*
2366 * If it contains a Var of the subquery being pulled up, and
2367 * does not contain any non-strict constructs, then it's
2368 * certainly nullable so we don't need to insert a
2369 * PlaceHolderVar.
2370 *
2371 * This analysis could be tighter: in particular, a non-strict
2372 * construct hidden within a lower-level PlaceHolderVar is not
2373 * reason to add another PHV. But for now it doesn't seem
2374 * worth the code to be more exact.
2375 *
2376 * Note: in future maybe we should insert a PlaceHolderVar
2377 * anyway, if the tlist item is expensive to evaluate?
2378 *
2379 * For a LATERAL subquery, we have to check the actual var
2380 * membership of the node, but if it's non-lateral then any
2381 * level-zero var must belong to the subquery.
2382 */
2383 if ((rcon->target_rte->lateral ?
2384 bms_overlap(pull_varnos(rcon->root, (Node *) newnode),
2385 rcon->relids) :
2386 contain_vars_of_level((Node *) newnode, 0)) &&
2387 !contain_nonstrict_functions((Node *) newnode))
2388 {
2389 /* No wrap needed */
2390 wrap = false;
2391 }
2392 else
2393 {
2394 /* Else wrap it in a PlaceHolderVar */
2395 wrap = true;
2396 }
2397 }
2398
2399 if (wrap)
2400 newnode = (Node *)
2401 make_placeholder_expr(rcon->root,
2402 (Expr *) newnode,
2403 bms_make_singleton(rcon->varno));
2404
2405 /*
2406 * Cache it if possible (ie, if the attno is in range, which it
2407 * probably always should be). We can cache the value even if we
2408 * decided we didn't need a PHV, since this result will be
2409 * suitable for any request that has need_phvs.
2410 */
2411 if (varattno > InvalidAttrNumber &&
2412 varattno <= list_length(rcon->targetlist))
2413 rcon->rv_cache[varattno] = copyObject(newnode);
2414 }
2415 }
2416
2417 /* Must adjust varlevelsup if tlist item is from higher query */
2418 if (var->varlevelsup > 0)
2419 IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
2420
2421 return newnode;
2422 }
2423
2424 /*
2425 * Apply pullup variable replacement to a subquery
2426 *
2427 * This needs to be different from pullup_replace_vars() because
2428 * replace_rte_variables will think that it shouldn't increment sublevels_up
2429 * before entering the Query; so we need to call it with sublevels_up == 1.
2430 */
2431 static Query *
pullup_replace_vars_subquery(Query * query,pullup_replace_vars_context * context)2432 pullup_replace_vars_subquery(Query *query,
2433 pullup_replace_vars_context *context)
2434 {
2435 Assert(IsA(query, Query));
2436 return (Query *) replace_rte_variables((Node *) query,
2437 context->varno, 1,
2438 pullup_replace_vars_callback,
2439 (void *) context,
2440 NULL);
2441 }
2442
2443
2444 /*
2445 * flatten_simple_union_all
2446 * Try to optimize top-level UNION ALL structure into an appendrel
2447 *
2448 * If a query's setOperations tree consists entirely of simple UNION ALL
2449 * operations, flatten it into an append relation, which we can process more
2450 * intelligently than the general setops case. Otherwise, do nothing.
2451 *
2452 * In most cases, this can succeed only for a top-level query, because for a
2453 * subquery in FROM, the parent query's invocation of pull_up_subqueries would
2454 * already have flattened the UNION via pull_up_simple_union_all. But there
2455 * are a few cases we can support here but not in that code path, for example
2456 * when the subquery also contains ORDER BY.
2457 */
2458 void
flatten_simple_union_all(PlannerInfo * root)2459 flatten_simple_union_all(PlannerInfo *root)
2460 {
2461 Query *parse = root->parse;
2462 SetOperationStmt *topop;
2463 Node *leftmostjtnode;
2464 int leftmostRTI;
2465 RangeTblEntry *leftmostRTE;
2466 int childRTI;
2467 RangeTblEntry *childRTE;
2468 RangeTblRef *rtr;
2469
2470 /* Shouldn't be called unless query has setops */
2471 topop = castNode(SetOperationStmt, parse->setOperations);
2472 Assert(topop);
2473
2474 /* Can't optimize away a recursive UNION */
2475 if (root->hasRecursion)
2476 return;
2477
2478 /*
2479 * Recursively check the tree of set operations. If not all UNION ALL
2480 * with identical column types, punt.
2481 */
2482 if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2483 return;
2484
2485 /*
2486 * Locate the leftmost leaf query in the setops tree. The upper query's
2487 * Vars all refer to this RTE (see transformSetOperationStmt).
2488 */
2489 leftmostjtnode = topop->larg;
2490 while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2491 leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2492 Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2493 leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2494 leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2495 Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2496
2497 /*
2498 * Make a copy of the leftmost RTE and add it to the rtable. This copy
2499 * will represent the leftmost leaf query in its capacity as a member of
2500 * the appendrel. The original will represent the appendrel as a whole.
2501 * (We must do things this way because the upper query's Vars have to be
2502 * seen as referring to the whole appendrel.)
2503 */
2504 childRTE = copyObject(leftmostRTE);
2505 parse->rtable = lappend(parse->rtable, childRTE);
2506 childRTI = list_length(parse->rtable);
2507
2508 /* Modify the setops tree to reference the child copy */
2509 ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2510
2511 /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2512 leftmostRTE->inh = true;
2513
2514 /*
2515 * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2516 * Query of a setops tree should have had an empty FromClause initially.
2517 */
2518 rtr = makeNode(RangeTblRef);
2519 rtr->rtindex = leftmostRTI;
2520 Assert(parse->jointree->fromlist == NIL);
2521 parse->jointree->fromlist = list_make1(rtr);
2522
2523 /*
2524 * Now pretend the query has no setops. We must do this before trying to
2525 * do subquery pullup, because of Assert in pull_up_simple_subquery.
2526 */
2527 parse->setOperations = NULL;
2528
2529 /*
2530 * Build AppendRelInfo information, and apply pull_up_subqueries to the
2531 * leaf queries of the UNION ALL. (We must do that now because they
2532 * weren't previously referenced by the jointree, and so were missed by
2533 * the main invocation of pull_up_subqueries.)
2534 */
2535 pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2536 }
2537
2538
2539 /*
2540 * reduce_outer_joins
2541 * Attempt to reduce outer joins to plain inner joins.
2542 *
2543 * The idea here is that given a query like
2544 * SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
2545 * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
2546 * is strict. The strict operator will always return NULL, causing the outer
2547 * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
2548 * columns. Therefore, there's no need for the join to produce null-extended
2549 * rows in the first place --- which makes it a plain join not an outer join.
2550 * (This scenario may not be very likely in a query written out by hand, but
2551 * it's reasonably likely when pushing quals down into complex views.)
2552 *
2553 * More generally, an outer join can be reduced in strength if there is a
2554 * strict qual above it in the qual tree that constrains a Var from the
2555 * nullable side of the join to be non-null. (For FULL joins this applies
2556 * to each side separately.)
2557 *
2558 * Another transformation we apply here is to recognize cases like
2559 * SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.y IS NULL;
2560 * If the join clause is strict for b.y, then only null-extended rows could
2561 * pass the upper WHERE, and we can conclude that what the query is really
2562 * specifying is an anti-semijoin. We change the join type from JOIN_LEFT
2563 * to JOIN_ANTI. The IS NULL clause then becomes redundant, and must be
2564 * removed to prevent bogus selectivity calculations, but we leave it to
2565 * distribute_qual_to_rels to get rid of such clauses.
2566 *
2567 * Also, we get rid of JOIN_RIGHT cases by flipping them around to become
2568 * JOIN_LEFT. This saves some code here and in some later planner routines,
2569 * but the main reason to do it is to not need to invent a JOIN_REVERSE_ANTI
2570 * join type.
2571 *
2572 * To ease recognition of strict qual clauses, we require this routine to be
2573 * run after expression preprocessing (i.e., qual canonicalization and JOIN
2574 * alias-var expansion).
2575 */
2576 void
reduce_outer_joins(PlannerInfo * root)2577 reduce_outer_joins(PlannerInfo *root)
2578 {
2579 reduce_outer_joins_state *state;
2580
2581 /*
2582 * To avoid doing strictness checks on more quals than necessary, we want
2583 * to stop descending the jointree as soon as there are no outer joins
2584 * below our current point. This consideration forces a two-pass process.
2585 * The first pass gathers information about which base rels appear below
2586 * each side of each join clause, and about whether there are outer
2587 * join(s) below each side of each join clause. The second pass examines
2588 * qual clauses and changes join types as it descends the tree.
2589 */
2590 state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
2591
2592 /* planner.c shouldn't have called me if no outer joins */
2593 if (state == NULL || !state->contains_outer)
2594 elog(ERROR, "so where are the outer joins?");
2595
2596 reduce_outer_joins_pass2((Node *) root->parse->jointree,
2597 state, root, NULL, NIL, NIL);
2598 }
2599
2600 /*
2601 * reduce_outer_joins_pass1 - phase 1 data collection
2602 *
2603 * Returns a state node describing the given jointree node.
2604 */
2605 static reduce_outer_joins_state *
reduce_outer_joins_pass1(Node * jtnode)2606 reduce_outer_joins_pass1(Node *jtnode)
2607 {
2608 reduce_outer_joins_state *result;
2609
2610 result = (reduce_outer_joins_state *)
2611 palloc(sizeof(reduce_outer_joins_state));
2612 result->relids = NULL;
2613 result->contains_outer = false;
2614 result->sub_states = NIL;
2615
2616 if (jtnode == NULL)
2617 return result;
2618 if (IsA(jtnode, RangeTblRef))
2619 {
2620 int varno = ((RangeTblRef *) jtnode)->rtindex;
2621
2622 result->relids = bms_make_singleton(varno);
2623 }
2624 else if (IsA(jtnode, FromExpr))
2625 {
2626 FromExpr *f = (FromExpr *) jtnode;
2627 ListCell *l;
2628
2629 foreach(l, f->fromlist)
2630 {
2631 reduce_outer_joins_state *sub_state;
2632
2633 sub_state = reduce_outer_joins_pass1(lfirst(l));
2634 result->relids = bms_add_members(result->relids,
2635 sub_state->relids);
2636 result->contains_outer |= sub_state->contains_outer;
2637 result->sub_states = lappend(result->sub_states, sub_state);
2638 }
2639 }
2640 else if (IsA(jtnode, JoinExpr))
2641 {
2642 JoinExpr *j = (JoinExpr *) jtnode;
2643 reduce_outer_joins_state *sub_state;
2644
2645 /* join's own RT index is not wanted in result->relids */
2646 if (IS_OUTER_JOIN(j->jointype))
2647 result->contains_outer = true;
2648
2649 sub_state = reduce_outer_joins_pass1(j->larg);
2650 result->relids = bms_add_members(result->relids,
2651 sub_state->relids);
2652 result->contains_outer |= sub_state->contains_outer;
2653 result->sub_states = lappend(result->sub_states, sub_state);
2654
2655 sub_state = reduce_outer_joins_pass1(j->rarg);
2656 result->relids = bms_add_members(result->relids,
2657 sub_state->relids);
2658 result->contains_outer |= sub_state->contains_outer;
2659 result->sub_states = lappend(result->sub_states, sub_state);
2660 }
2661 else
2662 elog(ERROR, "unrecognized node type: %d",
2663 (int) nodeTag(jtnode));
2664 return result;
2665 }
2666
2667 /*
2668 * reduce_outer_joins_pass2 - phase 2 processing
2669 *
2670 * jtnode: current jointree node
2671 * state: state data collected by phase 1 for this node
2672 * root: toplevel planner state
2673 * nonnullable_rels: set of base relids forced non-null by upper quals
2674 * nonnullable_vars: list of Vars forced non-null by upper quals
2675 * forced_null_vars: list of Vars forced null by upper quals
2676 */
2677 static void
reduce_outer_joins_pass2(Node * jtnode,reduce_outer_joins_state * state,PlannerInfo * root,Relids nonnullable_rels,List * nonnullable_vars,List * forced_null_vars)2678 reduce_outer_joins_pass2(Node *jtnode,
2679 reduce_outer_joins_state *state,
2680 PlannerInfo *root,
2681 Relids nonnullable_rels,
2682 List *nonnullable_vars,
2683 List *forced_null_vars)
2684 {
2685 /*
2686 * pass 2 should never descend as far as an empty subnode or base rel,
2687 * because it's only called on subtrees marked as contains_outer.
2688 */
2689 if (jtnode == NULL)
2690 elog(ERROR, "reached empty jointree");
2691 if (IsA(jtnode, RangeTblRef))
2692 elog(ERROR, "reached base rel");
2693 else if (IsA(jtnode, FromExpr))
2694 {
2695 FromExpr *f = (FromExpr *) jtnode;
2696 ListCell *l;
2697 ListCell *s;
2698 Relids pass_nonnullable_rels;
2699 List *pass_nonnullable_vars;
2700 List *pass_forced_null_vars;
2701
2702 /* Scan quals to see if we can add any constraints */
2703 pass_nonnullable_rels = find_nonnullable_rels(f->quals);
2704 pass_nonnullable_rels = bms_add_members(pass_nonnullable_rels,
2705 nonnullable_rels);
2706 pass_nonnullable_vars = find_nonnullable_vars(f->quals);
2707 pass_nonnullable_vars = list_concat(pass_nonnullable_vars,
2708 nonnullable_vars);
2709 pass_forced_null_vars = find_forced_null_vars(f->quals);
2710 pass_forced_null_vars = list_concat(pass_forced_null_vars,
2711 forced_null_vars);
2712 /* And recurse --- but only into interesting subtrees */
2713 Assert(list_length(f->fromlist) == list_length(state->sub_states));
2714 forboth(l, f->fromlist, s, state->sub_states)
2715 {
2716 reduce_outer_joins_state *sub_state = lfirst(s);
2717
2718 if (sub_state->contains_outer)
2719 reduce_outer_joins_pass2(lfirst(l), sub_state, root,
2720 pass_nonnullable_rels,
2721 pass_nonnullable_vars,
2722 pass_forced_null_vars);
2723 }
2724 bms_free(pass_nonnullable_rels);
2725 /* can't so easily clean up var lists, unfortunately */
2726 }
2727 else if (IsA(jtnode, JoinExpr))
2728 {
2729 JoinExpr *j = (JoinExpr *) jtnode;
2730 int rtindex = j->rtindex;
2731 JoinType jointype = j->jointype;
2732 reduce_outer_joins_state *left_state = linitial(state->sub_states);
2733 reduce_outer_joins_state *right_state = lsecond(state->sub_states);
2734 List *local_nonnullable_vars = NIL;
2735 bool computed_local_nonnullable_vars = false;
2736
2737 /* Can we simplify this join? */
2738 switch (jointype)
2739 {
2740 case JOIN_INNER:
2741 break;
2742 case JOIN_LEFT:
2743 if (bms_overlap(nonnullable_rels, right_state->relids))
2744 jointype = JOIN_INNER;
2745 break;
2746 case JOIN_RIGHT:
2747 if (bms_overlap(nonnullable_rels, left_state->relids))
2748 jointype = JOIN_INNER;
2749 break;
2750 case JOIN_FULL:
2751 if (bms_overlap(nonnullable_rels, left_state->relids))
2752 {
2753 if (bms_overlap(nonnullable_rels, right_state->relids))
2754 jointype = JOIN_INNER;
2755 else
2756 jointype = JOIN_LEFT;
2757 }
2758 else
2759 {
2760 if (bms_overlap(nonnullable_rels, right_state->relids))
2761 jointype = JOIN_RIGHT;
2762 }
2763 break;
2764 case JOIN_SEMI:
2765 case JOIN_ANTI:
2766
2767 /*
2768 * These could only have been introduced by pull_up_sublinks,
2769 * so there's no way that upper quals could refer to their
2770 * righthand sides, and no point in checking.
2771 */
2772 break;
2773 default:
2774 elog(ERROR, "unrecognized join type: %d",
2775 (int) jointype);
2776 break;
2777 }
2778
2779 /*
2780 * Convert JOIN_RIGHT to JOIN_LEFT. Note that in the case where we
2781 * reduced JOIN_FULL to JOIN_RIGHT, this will mean the JoinExpr no
2782 * longer matches the internal ordering of any CoalesceExpr's built to
2783 * represent merged join variables. We don't care about that at
2784 * present, but be wary of it ...
2785 */
2786 if (jointype == JOIN_RIGHT)
2787 {
2788 Node *tmparg;
2789
2790 tmparg = j->larg;
2791 j->larg = j->rarg;
2792 j->rarg = tmparg;
2793 jointype = JOIN_LEFT;
2794 right_state = linitial(state->sub_states);
2795 left_state = lsecond(state->sub_states);
2796 }
2797
2798 /*
2799 * See if we can reduce JOIN_LEFT to JOIN_ANTI. This is the case if
2800 * the join's own quals are strict for any var that was forced null by
2801 * higher qual levels. NOTE: there are other ways that we could
2802 * detect an anti-join, in particular if we were to check whether Vars
2803 * coming from the RHS must be non-null because of table constraints.
2804 * That seems complicated and expensive though (in particular, one
2805 * would have to be wary of lower outer joins). For the moment this
2806 * seems sufficient.
2807 */
2808 if (jointype == JOIN_LEFT)
2809 {
2810 List *overlap;
2811
2812 local_nonnullable_vars = find_nonnullable_vars(j->quals);
2813 computed_local_nonnullable_vars = true;
2814
2815 /*
2816 * It's not sufficient to check whether local_nonnullable_vars and
2817 * forced_null_vars overlap: we need to know if the overlap
2818 * includes any RHS variables.
2819 */
2820 overlap = list_intersection(local_nonnullable_vars,
2821 forced_null_vars);
2822 if (overlap != NIL &&
2823 bms_overlap(pull_varnos(root, (Node *) overlap),
2824 right_state->relids))
2825 jointype = JOIN_ANTI;
2826 }
2827
2828 /* Apply the jointype change, if any, to both jointree node and RTE */
2829 if (rtindex && jointype != j->jointype)
2830 {
2831 RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
2832
2833 Assert(rte->rtekind == RTE_JOIN);
2834 Assert(rte->jointype == j->jointype);
2835 rte->jointype = jointype;
2836 }
2837 j->jointype = jointype;
2838
2839 /* Only recurse if there's more to do below here */
2840 if (left_state->contains_outer || right_state->contains_outer)
2841 {
2842 Relids local_nonnullable_rels;
2843 List *local_forced_null_vars;
2844 Relids pass_nonnullable_rels;
2845 List *pass_nonnullable_vars;
2846 List *pass_forced_null_vars;
2847
2848 /*
2849 * If this join is (now) inner, we can add any constraints its
2850 * quals provide to those we got from above. But if it is outer,
2851 * we can pass down the local constraints only into the nullable
2852 * side, because an outer join never eliminates any rows from its
2853 * non-nullable side. Also, there is no point in passing upper
2854 * constraints into the nullable side, since if there were any
2855 * we'd have been able to reduce the join. (In the case of upper
2856 * forced-null constraints, we *must not* pass them into the
2857 * nullable side --- they either applied here, or not.) The upshot
2858 * is that we pass either the local or the upper constraints,
2859 * never both, to the children of an outer join.
2860 *
2861 * Note that a SEMI join works like an inner join here: it's okay
2862 * to pass down both local and upper constraints. (There can't be
2863 * any upper constraints affecting its inner side, but it's not
2864 * worth having a separate code path to avoid passing them.)
2865 *
2866 * At a FULL join we just punt and pass nothing down --- is it
2867 * possible to be smarter?
2868 */
2869 if (jointype != JOIN_FULL)
2870 {
2871 local_nonnullable_rels = find_nonnullable_rels(j->quals);
2872 if (!computed_local_nonnullable_vars)
2873 local_nonnullable_vars = find_nonnullable_vars(j->quals);
2874 local_forced_null_vars = find_forced_null_vars(j->quals);
2875 if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
2876 {
2877 /* OK to merge upper and local constraints */
2878 local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
2879 nonnullable_rels);
2880 local_nonnullable_vars = list_concat(local_nonnullable_vars,
2881 nonnullable_vars);
2882 local_forced_null_vars = list_concat(local_forced_null_vars,
2883 forced_null_vars);
2884 }
2885 }
2886 else
2887 {
2888 /* no use in calculating these */
2889 local_nonnullable_rels = NULL;
2890 local_forced_null_vars = NIL;
2891 }
2892
2893 if (left_state->contains_outer)
2894 {
2895 if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
2896 {
2897 /* pass union of local and upper constraints */
2898 pass_nonnullable_rels = local_nonnullable_rels;
2899 pass_nonnullable_vars = local_nonnullable_vars;
2900 pass_forced_null_vars = local_forced_null_vars;
2901 }
2902 else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
2903 {
2904 /* can't pass local constraints to non-nullable side */
2905 pass_nonnullable_rels = nonnullable_rels;
2906 pass_nonnullable_vars = nonnullable_vars;
2907 pass_forced_null_vars = forced_null_vars;
2908 }
2909 else
2910 {
2911 /* no constraints pass through JOIN_FULL */
2912 pass_nonnullable_rels = NULL;
2913 pass_nonnullable_vars = NIL;
2914 pass_forced_null_vars = NIL;
2915 }
2916 reduce_outer_joins_pass2(j->larg, left_state, root,
2917 pass_nonnullable_rels,
2918 pass_nonnullable_vars,
2919 pass_forced_null_vars);
2920 }
2921
2922 if (right_state->contains_outer)
2923 {
2924 if (jointype != JOIN_FULL) /* ie, INNER/LEFT/SEMI/ANTI */
2925 {
2926 /* pass appropriate constraints, per comment above */
2927 pass_nonnullable_rels = local_nonnullable_rels;
2928 pass_nonnullable_vars = local_nonnullable_vars;
2929 pass_forced_null_vars = local_forced_null_vars;
2930 }
2931 else
2932 {
2933 /* no constraints pass through JOIN_FULL */
2934 pass_nonnullable_rels = NULL;
2935 pass_nonnullable_vars = NIL;
2936 pass_forced_null_vars = NIL;
2937 }
2938 reduce_outer_joins_pass2(j->rarg, right_state, root,
2939 pass_nonnullable_rels,
2940 pass_nonnullable_vars,
2941 pass_forced_null_vars);
2942 }
2943 bms_free(local_nonnullable_rels);
2944 }
2945 }
2946 else
2947 elog(ERROR, "unrecognized node type: %d",
2948 (int) nodeTag(jtnode));
2949 }
2950
2951
2952 /*
2953 * remove_useless_result_rtes
2954 * Attempt to remove RTE_RESULT RTEs from the join tree.
2955 *
2956 * We can remove RTE_RESULT entries from the join tree using the knowledge
2957 * that RTE_RESULT returns exactly one row and has no output columns. Hence,
2958 * if one is inner-joined to anything else, we can delete it. Optimizations
2959 * are also possible for some outer-join cases, as detailed below.
2960 *
2961 * Some of these optimizations depend on recognizing empty (constant-true)
2962 * quals for FromExprs and JoinExprs. That makes it useful to apply this
2963 * optimization pass after expression preprocessing, since that will have
2964 * eliminated constant-true quals, allowing more cases to be recognized as
2965 * optimizable. What's more, the usual reason for an RTE_RESULT to be present
2966 * is that we pulled up a subquery or VALUES clause, thus very possibly
2967 * replacing Vars with constants, making it more likely that a qual can be
2968 * reduced to constant true. Also, because some optimizations depend on
2969 * the outer-join type, it's best to have done reduce_outer_joins() first.
2970 *
2971 * A PlaceHolderVar referencing an RTE_RESULT RTE poses an obstacle to this
2972 * process: we must remove the RTE_RESULT's relid from the PHV's phrels, but
2973 * we must not reduce the phrels set to empty. If that would happen, and
2974 * the RTE_RESULT is an immediate child of an outer join, we have to give up
2975 * and not remove the RTE_RESULT: there is noplace else to evaluate the
2976 * PlaceHolderVar. (That is, in such cases the RTE_RESULT *does* have output
2977 * columns.) But if the RTE_RESULT is an immediate child of an inner join,
2978 * we can usually change the PlaceHolderVar's phrels so as to evaluate it at
2979 * the inner join instead. This is OK because we really only care that PHVs
2980 * are evaluated above or below the correct outer joins. We can't, however,
2981 * postpone the evaluation of a PHV to above where it is used; so there are
2982 * some checks below on whether output PHVs are laterally referenced in the
2983 * other join input rel(s).
2984 *
2985 * We used to try to do this work as part of pull_up_subqueries() where the
2986 * potentially-optimizable cases get introduced; but it's way simpler, and
2987 * more effective, to do it separately.
2988 */
2989 void
remove_useless_result_rtes(PlannerInfo * root)2990 remove_useless_result_rtes(PlannerInfo *root)
2991 {
2992 ListCell *cell;
2993
2994 /* Top level of jointree must always be a FromExpr */
2995 Assert(IsA(root->parse->jointree, FromExpr));
2996 /* Recurse ... */
2997 root->parse->jointree = (FromExpr *)
2998 remove_useless_results_recurse(root, (Node *) root->parse->jointree);
2999 /* We should still have a FromExpr */
3000 Assert(IsA(root->parse->jointree, FromExpr));
3001
3002 /*
3003 * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
3004 * must do that for any RTE_RESULT that we just removed. But one for a
3005 * RTE that we did not remove can be dropped anyway: since the RTE has
3006 * only one possible output row, there is no need for EPQ to mark and
3007 * restore that row.
3008 *
3009 * It's necessary, not optional, to remove the PlanRowMark for a surviving
3010 * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
3011 * RTE_RESULT, which the executor has no support for.
3012 */
3013 foreach(cell, root->rowMarks)
3014 {
3015 PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3016
3017 if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
3018 root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3019 }
3020 }
3021
3022 /*
3023 * remove_useless_results_recurse
3024 * Recursive guts of remove_useless_result_rtes.
3025 *
3026 * This recursively processes the jointree and returns a modified jointree.
3027 */
3028 static Node *
remove_useless_results_recurse(PlannerInfo * root,Node * jtnode)3029 remove_useless_results_recurse(PlannerInfo *root, Node *jtnode)
3030 {
3031 Assert(jtnode != NULL);
3032 if (IsA(jtnode, RangeTblRef))
3033 {
3034 /* Can't immediately do anything with a RangeTblRef */
3035 }
3036 else if (IsA(jtnode, FromExpr))
3037 {
3038 FromExpr *f = (FromExpr *) jtnode;
3039 Relids result_relids = NULL;
3040 ListCell *cell;
3041
3042 /*
3043 * We can drop RTE_RESULT rels from the fromlist so long as at least
3044 * one child remains, since joining to a one-row table changes
3045 * nothing. (But we can't drop a RTE_RESULT that computes PHV(s) that
3046 * are needed by some sibling. The cleanup transformation below would
3047 * reassign the PHVs to be computed at the join, which is too late for
3048 * the sibling's use.) The easiest way to mechanize this rule is to
3049 * modify the list in-place.
3050 */
3051 foreach(cell, f->fromlist)
3052 {
3053 Node *child = (Node *) lfirst(cell);
3054 int varno;
3055
3056 /* Recursively transform child ... */
3057 child = remove_useless_results_recurse(root, child);
3058 /* ... and stick it back into the tree */
3059 lfirst(cell) = child;
3060
3061 /*
3062 * If it's an RTE_RESULT with at least one sibling, and no sibling
3063 * references dependent PHVs, we can drop it. We don't yet know
3064 * what the inner join's final relid set will be, so postpone
3065 * cleanup of PHVs etc till after this loop.
3066 */
3067 if (list_length(f->fromlist) > 1 &&
3068 (varno = get_result_relid(root, child)) != 0 &&
3069 !find_dependent_phvs_in_jointree(root, (Node *) f, varno))
3070 {
3071 f->fromlist = foreach_delete_current(f->fromlist, cell);
3072 result_relids = bms_add_member(result_relids, varno);
3073 }
3074 }
3075
3076 /*
3077 * Clean up if we dropped any RTE_RESULT RTEs. This is a bit
3078 * inefficient if there's more than one, but it seems better to
3079 * optimize the support code for the single-relid case.
3080 */
3081 if (result_relids)
3082 {
3083 int varno = -1;
3084
3085 while ((varno = bms_next_member(result_relids, varno)) >= 0)
3086 remove_result_refs(root, varno, (Node *) f);
3087 }
3088
3089 /*
3090 * If we're not at the top of the jointree, it's valid to simplify a
3091 * degenerate FromExpr into its single child. (At the top, we must
3092 * keep the FromExpr since Query.jointree is required to point to a
3093 * FromExpr.)
3094 */
3095 if (f != root->parse->jointree &&
3096 f->quals == NULL &&
3097 list_length(f->fromlist) == 1)
3098 return (Node *) linitial(f->fromlist);
3099 }
3100 else if (IsA(jtnode, JoinExpr))
3101 {
3102 JoinExpr *j = (JoinExpr *) jtnode;
3103 int varno;
3104
3105 /* First, recurse */
3106 j->larg = remove_useless_results_recurse(root, j->larg);
3107 j->rarg = remove_useless_results_recurse(root, j->rarg);
3108
3109 /* Apply join-type-specific optimization rules */
3110 switch (j->jointype)
3111 {
3112 case JOIN_INNER:
3113
3114 /*
3115 * An inner join is equivalent to a FromExpr, so if either
3116 * side was simplified to an RTE_RESULT rel, we can replace
3117 * the join with a FromExpr with just the other side; and if
3118 * the qual is empty (JOIN ON TRUE) then we can omit the
3119 * FromExpr as well.
3120 *
3121 * Just as in the FromExpr case, we can't simplify if the
3122 * other input rel references any PHVs that are marked as to
3123 * be evaluated at the RTE_RESULT rel, because we can't
3124 * postpone their evaluation in that case. But we only have
3125 * to check this in cases where it's syntactically legal for
3126 * the other input to have a LATERAL reference to the
3127 * RTE_RESULT rel. Only RHSes of inner and left joins are
3128 * allowed to have such refs.
3129 */
3130 if ((varno = get_result_relid(root, j->larg)) != 0 &&
3131 !find_dependent_phvs_in_jointree(root, j->rarg, varno))
3132 {
3133 remove_result_refs(root, varno, j->rarg);
3134 if (j->quals)
3135 jtnode = (Node *)
3136 makeFromExpr(list_make1(j->rarg), j->quals);
3137 else
3138 jtnode = j->rarg;
3139 }
3140 else if ((varno = get_result_relid(root, j->rarg)) != 0)
3141 {
3142 remove_result_refs(root, varno, j->larg);
3143 if (j->quals)
3144 jtnode = (Node *)
3145 makeFromExpr(list_make1(j->larg), j->quals);
3146 else
3147 jtnode = j->larg;
3148 }
3149 break;
3150 case JOIN_LEFT:
3151
3152 /*
3153 * We can simplify this case if the RHS is an RTE_RESULT, with
3154 * two different possibilities:
3155 *
3156 * If the qual is empty (JOIN ON TRUE), then the join can be
3157 * strength-reduced to a plain inner join, since each LHS row
3158 * necessarily has exactly one join partner. So we can always
3159 * discard the RHS, much as in the JOIN_INNER case above.
3160 * (Again, the LHS could not contain a lateral reference to
3161 * the RHS.)
3162 *
3163 * Otherwise, it's still true that each LHS row should be
3164 * returned exactly once, and since the RHS returns no columns
3165 * (unless there are PHVs that have to be evaluated there), we
3166 * don't much care if it's null-extended or not. So in this
3167 * case also, we can just ignore the qual and discard the left
3168 * join.
3169 */
3170 if ((varno = get_result_relid(root, j->rarg)) != 0 &&
3171 (j->quals == NULL ||
3172 !find_dependent_phvs(root, varno)))
3173 {
3174 remove_result_refs(root, varno, j->larg);
3175 jtnode = j->larg;
3176 }
3177 break;
3178 case JOIN_RIGHT:
3179 /* Mirror-image of the JOIN_LEFT case */
3180 if ((varno = get_result_relid(root, j->larg)) != 0 &&
3181 (j->quals == NULL ||
3182 !find_dependent_phvs(root, varno)))
3183 {
3184 remove_result_refs(root, varno, j->rarg);
3185 jtnode = j->rarg;
3186 }
3187 break;
3188 case JOIN_SEMI:
3189
3190 /*
3191 * We may simplify this case if the RHS is an RTE_RESULT; the
3192 * join qual becomes effectively just a filter qual for the
3193 * LHS, since we should either return the LHS row or not. For
3194 * simplicity we inject the filter qual into a new FromExpr.
3195 *
3196 * Unlike the LEFT/RIGHT cases, we just Assert that there are
3197 * no PHVs that need to be evaluated at the semijoin's RHS,
3198 * since the rest of the query couldn't reference any outputs
3199 * of the semijoin's RHS.
3200 */
3201 if ((varno = get_result_relid(root, j->rarg)) != 0)
3202 {
3203 Assert(!find_dependent_phvs(root, varno));
3204 remove_result_refs(root, varno, j->larg);
3205 if (j->quals)
3206 jtnode = (Node *)
3207 makeFromExpr(list_make1(j->larg), j->quals);
3208 else
3209 jtnode = j->larg;
3210 }
3211 break;
3212 case JOIN_FULL:
3213 case JOIN_ANTI:
3214 /* We have no special smarts for these cases */
3215 break;
3216 default:
3217 elog(ERROR, "unrecognized join type: %d",
3218 (int) j->jointype);
3219 break;
3220 }
3221 }
3222 else
3223 elog(ERROR, "unrecognized node type: %d",
3224 (int) nodeTag(jtnode));
3225 return jtnode;
3226 }
3227
3228 /*
3229 * get_result_relid
3230 * If jtnode is a RangeTblRef for an RTE_RESULT RTE, return its relid;
3231 * otherwise return 0.
3232 */
3233 static int
get_result_relid(PlannerInfo * root,Node * jtnode)3234 get_result_relid(PlannerInfo *root, Node *jtnode)
3235 {
3236 int varno;
3237
3238 if (!IsA(jtnode, RangeTblRef))
3239 return 0;
3240 varno = ((RangeTblRef *) jtnode)->rtindex;
3241 if (rt_fetch(varno, root->parse->rtable)->rtekind != RTE_RESULT)
3242 return 0;
3243 return varno;
3244 }
3245
3246 /*
3247 * remove_result_refs
3248 * Helper routine for dropping an unneeded RTE_RESULT RTE.
3249 *
3250 * This doesn't physically remove the RTE from the jointree, because that's
3251 * more easily handled in remove_useless_results_recurse. What it does do
3252 * is the necessary cleanup in the rest of the tree: we must adjust any PHVs
3253 * that may reference the RTE. Be sure to call this at a point where the
3254 * jointree is valid (no disconnected nodes).
3255 *
3256 * Note that we don't need to process the append_rel_list, since RTEs
3257 * referenced directly in the jointree won't be appendrel members.
3258 *
3259 * varno is the RTE_RESULT's relid.
3260 * newjtloc is the jointree location at which any PHVs referencing the
3261 * RTE_RESULT should be evaluated instead.
3262 */
3263 static void
remove_result_refs(PlannerInfo * root,int varno,Node * newjtloc)3264 remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
3265 {
3266 /* Fix up PlaceHolderVars as needed */
3267 /* If there are no PHVs anywhere, we can skip this bit */
3268 if (root->glob->lastPHId != 0)
3269 {
3270 Relids subrelids;
3271
3272 subrelids = get_relids_in_jointree(newjtloc, false);
3273 Assert(!bms_is_empty(subrelids));
3274 substitute_phv_relids((Node *) root->parse, varno, subrelids);
3275 fix_append_rel_relids(root->append_rel_list, varno, subrelids);
3276 }
3277
3278 /*
3279 * We also need to remove any PlanRowMark referencing the RTE, but we
3280 * postpone that work until we return to remove_useless_result_rtes.
3281 */
3282 }
3283
3284
3285 /*
3286 * find_dependent_phvs - are there any PlaceHolderVars whose relids are
3287 * exactly the given varno?
3288 *
3289 * find_dependent_phvs should be used when we want to see if there are
3290 * any such PHVs anywhere in the Query. Another use-case is to see if
3291 * a subtree of the join tree contains such PHVs; but for that, we have
3292 * to look not only at the join tree nodes themselves but at the
3293 * referenced RTEs. For that, use find_dependent_phvs_in_jointree.
3294 */
3295
3296 typedef struct
3297 {
3298 Relids relids;
3299 int sublevels_up;
3300 } find_dependent_phvs_context;
3301
3302 static bool
find_dependent_phvs_walker(Node * node,find_dependent_phvs_context * context)3303 find_dependent_phvs_walker(Node *node,
3304 find_dependent_phvs_context *context)
3305 {
3306 if (node == NULL)
3307 return false;
3308 if (IsA(node, PlaceHolderVar))
3309 {
3310 PlaceHolderVar *phv = (PlaceHolderVar *) node;
3311
3312 if (phv->phlevelsup == context->sublevels_up &&
3313 bms_equal(context->relids, phv->phrels))
3314 return true;
3315 /* fall through to examine children */
3316 }
3317 if (IsA(node, Query))
3318 {
3319 /* Recurse into subselects */
3320 bool result;
3321
3322 context->sublevels_up++;
3323 result = query_tree_walker((Query *) node,
3324 find_dependent_phvs_walker,
3325 (void *) context, 0);
3326 context->sublevels_up--;
3327 return result;
3328 }
3329 /* Shouldn't need to handle planner auxiliary nodes here */
3330 Assert(!IsA(node, SpecialJoinInfo));
3331 Assert(!IsA(node, AppendRelInfo));
3332 Assert(!IsA(node, PlaceHolderInfo));
3333 Assert(!IsA(node, MinMaxAggInfo));
3334
3335 return expression_tree_walker(node, find_dependent_phvs_walker,
3336 (void *) context);
3337 }
3338
3339 static bool
find_dependent_phvs(PlannerInfo * root,int varno)3340 find_dependent_phvs(PlannerInfo *root, int varno)
3341 {
3342 find_dependent_phvs_context context;
3343
3344 /* If there are no PHVs anywhere, we needn't work hard */
3345 if (root->glob->lastPHId == 0)
3346 return false;
3347
3348 context.relids = bms_make_singleton(varno);
3349 context.sublevels_up = 0;
3350
3351 return query_tree_walker(root->parse,
3352 find_dependent_phvs_walker,
3353 (void *) &context,
3354 0);
3355 }
3356
3357 static bool
find_dependent_phvs_in_jointree(PlannerInfo * root,Node * node,int varno)3358 find_dependent_phvs_in_jointree(PlannerInfo *root, Node *node, int varno)
3359 {
3360 find_dependent_phvs_context context;
3361 Relids subrelids;
3362 int relid;
3363
3364 /* If there are no PHVs anywhere, we needn't work hard */
3365 if (root->glob->lastPHId == 0)
3366 return false;
3367
3368 context.relids = bms_make_singleton(varno);
3369 context.sublevels_up = 0;
3370
3371 /*
3372 * See if the jointree fragment itself contains references (in join quals)
3373 */
3374 if (find_dependent_phvs_walker(node, &context))
3375 return true;
3376
3377 /*
3378 * Otherwise, identify the set of referenced RTEs (we can ignore joins,
3379 * since they should be flattened already, so their join alias lists no
3380 * longer matter), and tediously check each RTE. We can ignore RTEs that
3381 * are not marked LATERAL, though, since they couldn't possibly contain
3382 * any cross-references to other RTEs.
3383 */
3384 subrelids = get_relids_in_jointree(node, false);
3385 relid = -1;
3386 while ((relid = bms_next_member(subrelids, relid)) >= 0)
3387 {
3388 RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
3389
3390 if (rte->lateral &&
3391 range_table_entry_walker(rte,
3392 find_dependent_phvs_walker,
3393 (void *) &context,
3394 0))
3395 return true;
3396 }
3397
3398 return false;
3399 }
3400
3401 /*
3402 * substitute_phv_relids - adjust PlaceHolderVar relid sets after pulling up
3403 * a subquery or removing an RTE_RESULT jointree item
3404 *
3405 * Find any PlaceHolderVar nodes in the given tree that reference the
3406 * pulled-up relid, and change them to reference the replacement relid(s).
3407 *
3408 * NOTE: although this has the form of a walker, we cheat and modify the
3409 * nodes in-place. This should be OK since the tree was copied by
3410 * pullup_replace_vars earlier. Avoid scribbling on the original values of
3411 * the bitmapsets, though, because expression_tree_mutator doesn't copy those.
3412 */
3413
3414 typedef struct
3415 {
3416 int varno;
3417 int sublevels_up;
3418 Relids subrelids;
3419 } substitute_phv_relids_context;
3420
3421 static bool
substitute_phv_relids_walker(Node * node,substitute_phv_relids_context * context)3422 substitute_phv_relids_walker(Node *node,
3423 substitute_phv_relids_context *context)
3424 {
3425 if (node == NULL)
3426 return false;
3427 if (IsA(node, PlaceHolderVar))
3428 {
3429 PlaceHolderVar *phv = (PlaceHolderVar *) node;
3430
3431 if (phv->phlevelsup == context->sublevels_up &&
3432 bms_is_member(context->varno, phv->phrels))
3433 {
3434 phv->phrels = bms_union(phv->phrels,
3435 context->subrelids);
3436 phv->phrels = bms_del_member(phv->phrels,
3437 context->varno);
3438 /* Assert we haven't broken the PHV */
3439 Assert(!bms_is_empty(phv->phrels));
3440 }
3441 /* fall through to examine children */
3442 }
3443 if (IsA(node, Query))
3444 {
3445 /* Recurse into subselects */
3446 bool result;
3447
3448 context->sublevels_up++;
3449 result = query_tree_walker((Query *) node,
3450 substitute_phv_relids_walker,
3451 (void *) context, 0);
3452 context->sublevels_up--;
3453 return result;
3454 }
3455 /* Shouldn't need to handle planner auxiliary nodes here */
3456 Assert(!IsA(node, SpecialJoinInfo));
3457 Assert(!IsA(node, AppendRelInfo));
3458 Assert(!IsA(node, PlaceHolderInfo));
3459 Assert(!IsA(node, MinMaxAggInfo));
3460
3461 return expression_tree_walker(node, substitute_phv_relids_walker,
3462 (void *) context);
3463 }
3464
3465 static void
substitute_phv_relids(Node * node,int varno,Relids subrelids)3466 substitute_phv_relids(Node *node, int varno, Relids subrelids)
3467 {
3468 substitute_phv_relids_context context;
3469
3470 context.varno = varno;
3471 context.sublevels_up = 0;
3472 context.subrelids = subrelids;
3473
3474 /*
3475 * Must be prepared to start with a Query or a bare expression tree.
3476 */
3477 query_or_expression_tree_walker(node,
3478 substitute_phv_relids_walker,
3479 (void *) &context,
3480 0);
3481 }
3482
3483 /*
3484 * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
3485 *
3486 * When we pull up a subquery, any AppendRelInfo references to the subquery's
3487 * RT index have to be replaced by the substituted relid (and there had better
3488 * be only one). We also need to apply substitute_phv_relids to their
3489 * translated_vars lists, since those might contain PlaceHolderVars.
3490 *
3491 * We assume we may modify the AppendRelInfo nodes in-place.
3492 */
3493 static void
fix_append_rel_relids(List * append_rel_list,int varno,Relids subrelids)3494 fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
3495 {
3496 ListCell *l;
3497 int subvarno = -1;
3498
3499 /*
3500 * We only want to extract the member relid once, but we mustn't fail
3501 * immediately if there are multiple members; it could be that none of the
3502 * AppendRelInfo nodes refer to it. So compute it on first use. Note that
3503 * bms_singleton_member will complain if set is not singleton.
3504 */
3505 foreach(l, append_rel_list)
3506 {
3507 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
3508
3509 /* The parent_relid shouldn't ever be a pullup target */
3510 Assert(appinfo->parent_relid != varno);
3511
3512 if (appinfo->child_relid == varno)
3513 {
3514 if (subvarno < 0)
3515 subvarno = bms_singleton_member(subrelids);
3516 appinfo->child_relid = subvarno;
3517 }
3518
3519 /* Also fix up any PHVs in its translated vars */
3520 substitute_phv_relids((Node *) appinfo->translated_vars,
3521 varno, subrelids);
3522 }
3523 }
3524
3525 /*
3526 * get_relids_in_jointree: get set of RT indexes present in a jointree
3527 *
3528 * If include_joins is true, join RT indexes are included; if false,
3529 * only base rels are included.
3530 */
3531 Relids
get_relids_in_jointree(Node * jtnode,bool include_joins)3532 get_relids_in_jointree(Node *jtnode, bool include_joins)
3533 {
3534 Relids result = NULL;
3535
3536 if (jtnode == NULL)
3537 return result;
3538 if (IsA(jtnode, RangeTblRef))
3539 {
3540 int varno = ((RangeTblRef *) jtnode)->rtindex;
3541
3542 result = bms_make_singleton(varno);
3543 }
3544 else if (IsA(jtnode, FromExpr))
3545 {
3546 FromExpr *f = (FromExpr *) jtnode;
3547 ListCell *l;
3548
3549 foreach(l, f->fromlist)
3550 {
3551 result = bms_join(result,
3552 get_relids_in_jointree(lfirst(l),
3553 include_joins));
3554 }
3555 }
3556 else if (IsA(jtnode, JoinExpr))
3557 {
3558 JoinExpr *j = (JoinExpr *) jtnode;
3559
3560 result = get_relids_in_jointree(j->larg, include_joins);
3561 result = bms_join(result,
3562 get_relids_in_jointree(j->rarg, include_joins));
3563 if (include_joins && j->rtindex)
3564 result = bms_add_member(result, j->rtindex);
3565 }
3566 else
3567 elog(ERROR, "unrecognized node type: %d",
3568 (int) nodeTag(jtnode));
3569 return result;
3570 }
3571
3572 /*
3573 * get_relids_for_join: get set of base RT indexes making up a join
3574 */
3575 Relids
get_relids_for_join(Query * query,int joinrelid)3576 get_relids_for_join(Query *query, int joinrelid)
3577 {
3578 Node *jtnode;
3579
3580 jtnode = find_jointree_node_for_rel((Node *) query->jointree,
3581 joinrelid);
3582 if (!jtnode)
3583 elog(ERROR, "could not find join node %d", joinrelid);
3584 return get_relids_in_jointree(jtnode, false);
3585 }
3586
3587 /*
3588 * find_jointree_node_for_rel: locate jointree node for a base or join RT index
3589 *
3590 * Returns NULL if not found
3591 */
3592 static Node *
find_jointree_node_for_rel(Node * jtnode,int relid)3593 find_jointree_node_for_rel(Node *jtnode, int relid)
3594 {
3595 if (jtnode == NULL)
3596 return NULL;
3597 if (IsA(jtnode, RangeTblRef))
3598 {
3599 int varno = ((RangeTblRef *) jtnode)->rtindex;
3600
3601 if (relid == varno)
3602 return jtnode;
3603 }
3604 else if (IsA(jtnode, FromExpr))
3605 {
3606 FromExpr *f = (FromExpr *) jtnode;
3607 ListCell *l;
3608
3609 foreach(l, f->fromlist)
3610 {
3611 jtnode = find_jointree_node_for_rel(lfirst(l), relid);
3612 if (jtnode)
3613 return jtnode;
3614 }
3615 }
3616 else if (IsA(jtnode, JoinExpr))
3617 {
3618 JoinExpr *j = (JoinExpr *) jtnode;
3619
3620 if (relid == j->rtindex)
3621 return jtnode;
3622 jtnode = find_jointree_node_for_rel(j->larg, relid);
3623 if (jtnode)
3624 return jtnode;
3625 jtnode = find_jointree_node_for_rel(j->rarg, relid);
3626 if (jtnode)
3627 return jtnode;
3628 }
3629 else
3630 elog(ERROR, "unrecognized node type: %d",
3631 (int) nodeTag(jtnode));
3632 return NULL;
3633 }
3634