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