PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
prepjointree.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * prepjointree.c
4 * Planner preprocessing for subqueries and join tree manipulation.
5 *
6 * NOTE: the intended sequence for invoking these operations is
7 * replace_empty_jointree
8 * pull_up_sublinks
9 * preprocess_function_rtes
10 * expand_virtual_generated_columns
11 * pull_up_subqueries
12 * flatten_simple_union_all
13 * do expression preprocessing (including flattening JOIN alias vars)
14 * reduce_outer_joins
15 * remove_useless_result_rtes
16 *
17 *
18 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
19 * Portions Copyright (c) 1994, Regents of the University of California
20 *
21 *
22 * IDENTIFICATION
23 * src/backend/optimizer/prep/prepjointree.c
24 *
25 *-------------------------------------------------------------------------
26 */
27#include "postgres.h"
28
29#include "access/table.h"
30#include "catalog/pg_type.h"
31#include "funcapi.h"
32#include "miscadmin.h"
33#include "nodes/makefuncs.h"
35#include "nodes/nodeFuncs.h"
36#include "optimizer/clauses.h"
37#include "optimizer/optimizer.h"
39#include "optimizer/prep.h"
40#include "optimizer/subselect.h"
41#include "optimizer/tlist.h"
43#include "parser/parsetree.h"
46#include "utils/rel.h"
47
48
49typedef struct nullingrel_info
50{
51 /*
52 * For each leaf RTE, nullingrels[rti] is the set of relids of outer joins
53 * that potentially null that RTE.
54 */
56 /* Length of range table (maximum index in nullingrels[]) */
57 int rtlength; /* used only for assertion checks */
59
60/* Options for wrapping an expression for identification purposes */
62{
63 REPLACE_WRAP_NONE, /* no expressions need to be wrapped */
64 REPLACE_WRAP_ALL, /* all expressions need to be wrapped */
65 REPLACE_WRAP_VARFREE, /* variable-free expressions need to be
66 * wrapped */
68
70{
72 List *targetlist; /* tlist of subquery being pulled up */
73 RangeTblEntry *target_rte; /* RTE of subquery */
74 int result_relation; /* the index of the result relation in the
75 * rewritten query */
76 Relids relids; /* relids within subquery, as numbered after
77 * pullup (set only if target_rte->lateral) */
78 nullingrel_info *nullinfo; /* per-RTE nullingrel info (set only if
79 * target_rte->lateral) */
80 bool *outer_hasSubLinks; /* -> outer query's hasSubLinks */
81 int varno; /* varno of subquery */
82 ReplaceWrapOption wrap_option; /* do we need certain outputs to be PHVs? */
83 Node **rv_cache; /* cache for results with PHVs */
85
87{
88 Relids relids; /* base relids within this subtree */
89 bool contains_outer; /* does subtree contain outer join(s)? */
90 List *sub_states; /* List of states for subtree components */
92
94{
95 Relids inner_reduced; /* OJ relids reduced to plain inner joins */
96 List *partial_reduced; /* List of partially reduced FULL joins */
98
100{
101 int full_join_rti; /* RT index of a formerly-FULL join */
102 Relids unreduced_side; /* relids in its still-nullable side */
104
106 Relids *relids);
108 Node **jtlink1, Relids available_rels1,
109 Node **jtlink2, Relids available_rels2);
111 JoinExpr *lowest_outer_join,
112 AppendRelInfo *containing_appendrel);
114 RangeTblEntry *rte,
115 JoinExpr *lowest_outer_join,
116 AppendRelInfo *containing_appendrel);
118 RangeTblEntry *rte);
120 int parentRTindex, Query *setOpQuery,
121 int childRToffset);
122static void make_setop_translation_list(Query *query, int newvarno,
123 AppendRelInfo *appinfo);
124static bool is_simple_subquery(PlannerInfo *root, Query *subquery,
125 RangeTblEntry *rte,
126 JoinExpr *lowest_outer_join);
128 RangeTblEntry *rte);
131 RangeTblEntry *rte,
132 AppendRelInfo *containing_appendrel);
133static bool is_simple_union_all(Query *subquery);
134static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
135 List *colTypes);
136static bool is_safe_append_member(Query *subquery);
138 Node *jtnode, bool restricted,
139 Relids safe_upper_varnos);
142 AppendRelInfo *containing_appendrel);
143static void replace_vars_in_jointree(Node *jtnode,
145static Node *pullup_replace_vars(Node *expr,
152static void reduce_outer_joins_pass2(Node *jtnode,
156 Relids nonnullable_rels,
157 List *forced_null_vars);
159 int rtindex, Relids relids);
161 Node **parent_quals,
162 Relids *dropped_outer_joins);
163static int get_result_relid(PlannerInfo *root, Node *jtnode);
164static void remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc);
165static bool find_dependent_phvs(PlannerInfo *root, int varno);
167 Node *node, int varno);
168static void substitute_phv_relids(Node *node,
169 int varno, Relids subrelids);
170static void fix_append_rel_relids(PlannerInfo *root, int varno,
171 Relids subrelids);
172static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
174static void get_nullingrels_recurse(Node *jtnode, Relids upper_nullingrels,
175 nullingrel_info *info);
176
177
178/*
179 * transform_MERGE_to_join
180 * Replace a MERGE's jointree to also include the target relation.
181 */
182void
184{
185 RangeTblEntry *joinrte;
186 JoinExpr *joinexpr;
187 bool have_action[NUM_MERGE_MATCH_KINDS];
188 JoinType jointype;
189 int joinrti;
190 List *vars;
191 RangeTblRef *rtr;
192 FromExpr *target;
193 Node *source;
194 int sourcerti;
195
196 if (parse->commandType != CMD_MERGE)
197 return;
198
199 /* XXX probably bogus */
200 vars = NIL;
201
202 /*
203 * Work out what kind of join is required. If there any WHEN NOT MATCHED
204 * BY SOURCE/TARGET actions, an outer join is required so that we process
205 * all unmatched tuples from the source and/or target relations.
206 * Otherwise, we can use an inner join.
207 */
208 have_action[MERGE_WHEN_MATCHED] = false;
209 have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE] = false;
210 have_action[MERGE_WHEN_NOT_MATCHED_BY_TARGET] = false;
211
212 foreach_node(MergeAction, action, parse->mergeActionList)
213 {
214 if (action->commandType != CMD_NOTHING)
215 have_action[action->matchKind] = true;
216 }
217
218 if (have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE] &&
220 jointype = JOIN_FULL;
221 else if (have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE])
222 jointype = JOIN_LEFT;
223 else if (have_action[MERGE_WHEN_NOT_MATCHED_BY_TARGET])
224 jointype = JOIN_RIGHT;
225 else
226 jointype = JOIN_INNER;
227
228 /* Manufacture a join RTE to use. */
229 joinrte = makeNode(RangeTblEntry);
230 joinrte->rtekind = RTE_JOIN;
231 joinrte->jointype = jointype;
232 joinrte->joinmergedcols = 0;
233 joinrte->joinaliasvars = vars;
234 joinrte->joinleftcols = NIL; /* MERGE does not allow JOIN USING */
235 joinrte->joinrightcols = NIL; /* ditto */
236 joinrte->join_using_alias = NULL;
237
238 joinrte->alias = NULL;
239 joinrte->eref = makeAlias("*MERGE*", NIL);
240 joinrte->lateral = false;
241 joinrte->inh = false;
242 joinrte->inFromCl = true;
243
244 /*
245 * Add completed RTE to pstate's range table list, so that we know its
246 * index.
247 */
248 parse->rtable = lappend(parse->rtable, joinrte);
249 joinrti = list_length(parse->rtable);
250
251 /*
252 * Create a JOIN between the target and the source relation.
253 *
254 * Here the target is identified by parse->mergeTargetRelation. For a
255 * regular table, this will equal parse->resultRelation, but for a
256 * trigger-updatable view, it will be the expanded view subquery that we
257 * need to pull data from.
258 *
259 * The source relation is in parse->jointree->fromlist, but any quals in
260 * parse->jointree->quals are restrictions on the target relation (if the
261 * target relation is an auto-updatable view).
262 */
263 /* target rel, with any quals */
264 rtr = makeNode(RangeTblRef);
265 rtr->rtindex = parse->mergeTargetRelation;
266 target = makeFromExpr(list_make1(rtr), parse->jointree->quals);
267
268 /* source rel (expect exactly one -- see transformMergeStmt()) */
269 Assert(list_length(parse->jointree->fromlist) == 1);
270 source = linitial(parse->jointree->fromlist);
271
272 /*
273 * index of source rel (expect either a RangeTblRef or a JoinExpr -- see
274 * transformFromClauseItem()).
275 */
276 if (IsA(source, RangeTblRef))
277 sourcerti = ((RangeTblRef *) source)->rtindex;
278 else if (IsA(source, JoinExpr))
279 sourcerti = ((JoinExpr *) source)->rtindex;
280 else
281 {
282 elog(ERROR, "unrecognized source node type: %d",
283 (int) nodeTag(source));
284 sourcerti = 0; /* keep compiler quiet */
285 }
286
287 /* Join the source and target */
288 joinexpr = makeNode(JoinExpr);
289 joinexpr->jointype = jointype;
290 joinexpr->isNatural = false;
291 joinexpr->larg = (Node *) target;
292 joinexpr->rarg = source;
293 joinexpr->usingClause = NIL;
294 joinexpr->join_using_alias = NULL;
295 joinexpr->quals = parse->mergeJoinCondition;
296 joinexpr->alias = NULL;
297 joinexpr->rtindex = joinrti;
298
299 /* Make the new join be the sole entry in the query's jointree */
300 parse->jointree->fromlist = list_make1(joinexpr);
301 parse->jointree->quals = NULL;
302
303 /*
304 * If necessary, mark parse->targetlist entries that refer to the target
305 * as nullable by the join. Normally the targetlist will be empty for a
306 * MERGE, but if the target is a trigger-updatable view, it will contain a
307 * whole-row Var referring to the expanded view query.
308 */
309 if (parse->targetList != NIL &&
310 (jointype == JOIN_RIGHT || jointype == JOIN_FULL))
311 parse->targetList = (List *)
312 add_nulling_relids((Node *) parse->targetList,
313 bms_make_singleton(parse->mergeTargetRelation),
314 bms_make_singleton(joinrti));
315
316 /*
317 * If the source relation is on the outer side of the join, mark any
318 * source relation Vars in the join condition, actions, and RETURNING list
319 * as nullable by the join. These Vars will be added to the targetlist by
320 * preprocess_targetlist(), so it's important to mark them correctly here.
321 *
322 * It might seem that this is not necessary for Vars in the join
323 * condition, since it is inside the join, but it is also needed above the
324 * join (in the ModifyTable node) to distinguish between the MATCHED and
325 * NOT MATCHED BY SOURCE cases -- see ExecMergeMatched(). Note that this
326 * creates a modified copy of the join condition, for use above the join,
327 * without modifying the original join condition, inside the join.
328 */
329 if (jointype == JOIN_LEFT || jointype == JOIN_FULL)
330 {
331 parse->mergeJoinCondition =
332 add_nulling_relids(parse->mergeJoinCondition,
333 bms_make_singleton(sourcerti),
334 bms_make_singleton(joinrti));
335
336 foreach_node(MergeAction, action, parse->mergeActionList)
337 {
338 action->qual =
340 bms_make_singleton(sourcerti),
341 bms_make_singleton(joinrti));
342
343 action->targetList = (List *)
344 add_nulling_relids((Node *) action->targetList,
345 bms_make_singleton(sourcerti),
346 bms_make_singleton(joinrti));
347 }
348
349 parse->returningList = (List *)
350 add_nulling_relids((Node *) parse->returningList,
351 bms_make_singleton(sourcerti),
352 bms_make_singleton(joinrti));
353 }
354
355 /*
356 * If there are any WHEN NOT MATCHED BY SOURCE actions, the executor will
357 * use the join condition to distinguish between MATCHED and NOT MATCHED
358 * BY SOURCE cases. Otherwise, it's no longer needed, and we set it to
359 * NULL, saving cycles during planning and execution.
360 *
361 * We need to be careful though: the executor evaluates this condition
362 * using the output of the join subplan node, which nulls the output from
363 * the source relation when the join condition doesn't match. That risks
364 * producing incorrect results when rechecking using a "non-strict" join
365 * condition, such as "src.col IS NOT DISTINCT FROM tgt.col". To guard
366 * against that, we add an additional "src IS NOT NULL" check to the join
367 * condition, so that it does the right thing when performing a recheck
368 * based on the output of the join subplan.
369 */
370 if (have_action[MERGE_WHEN_NOT_MATCHED_BY_SOURCE])
371 {
372 Var *var;
373 NullTest *ntest;
374
375 /* source wholerow Var (nullable by the new join) */
376 var = makeWholeRowVar(rt_fetch(sourcerti, parse->rtable),
377 sourcerti, 0, false);
378 var->varnullingrels = bms_make_singleton(joinrti);
379
380 /* "src IS NOT NULL" check */
381 ntest = makeNode(NullTest);
382 ntest->arg = (Expr *) var;
383 ntest->nulltesttype = IS_NOT_NULL;
384 ntest->argisrow = false;
385 ntest->location = -1;
386
387 /* combine it with the original join condition */
388 parse->mergeJoinCondition =
389 (Node *) make_and_qual((Node *) ntest, parse->mergeJoinCondition);
390 }
391 else
392 parse->mergeJoinCondition = NULL; /* join condition not needed */
393}
394
395/*
396 * replace_empty_jointree
397 * If the Query's jointree is empty, replace it with a dummy RTE_RESULT
398 * relation.
399 *
400 * By doing this, we can avoid a bunch of corner cases that formerly existed
401 * for SELECTs with omitted FROM clauses. An example is that a subquery
402 * with empty jointree previously could not be pulled up, because that would
403 * have resulted in an empty relid set, making the subquery not uniquely
404 * identifiable for join or PlaceHolderVar processing.
405 *
406 * Unlike most other functions in this file, this function doesn't recurse;
407 * we rely on other processing to invoke it on sub-queries at suitable times.
408 */
409void
411{
412 RangeTblEntry *rte;
413 Index rti;
414 RangeTblRef *rtr;
415
416 /* Nothing to do if jointree is already nonempty */
417 if (parse->jointree->fromlist != NIL)
418 return;
419
420 /* We mustn't change it in the top level of a setop tree, either */
421 if (parse->setOperations)
422 return;
423
424 /* Create suitable RTE */
425 rte = makeNode(RangeTblEntry);
426 rte->rtekind = RTE_RESULT;
427 rte->eref = makeAlias("*RESULT*", NIL);
428
429 /* Add it to rangetable */
430 parse->rtable = lappend(parse->rtable, rte);
431 rti = list_length(parse->rtable);
432
433 /* And jam a reference into the jointree */
434 rtr = makeNode(RangeTblRef);
435 rtr->rtindex = rti;
436 parse->jointree->fromlist = list_make1(rtr);
437}
438
439/*
440 * pull_up_sublinks
441 * Attempt to pull up ANY and EXISTS SubLinks to be treated as
442 * semijoins or anti-semijoins.
443 *
444 * A clause "foo op ANY (sub-SELECT)" can be processed by pulling the
445 * sub-SELECT up to become a rangetable entry and treating the implied
446 * comparisons as quals of a semijoin. However, this optimization *only*
447 * works at the top level of WHERE or a JOIN/ON clause, because we cannot
448 * distinguish whether the ANY ought to return FALSE or NULL in cases
449 * involving NULL inputs. Also, in an outer join's ON clause we can only
450 * do this if the sublink is degenerate (ie, references only the nullable
451 * side of the join). In that case it is legal to push the semijoin
452 * down into the nullable side of the join. If the sublink references any
453 * nonnullable-side variables then it would have to be evaluated as part
454 * of the outer join, which makes things way too complicated.
455 *
456 * Under similar conditions, EXISTS and NOT EXISTS clauses can be handled
457 * by pulling up the sub-SELECT and creating a semijoin or anti-semijoin.
458 *
459 * This routine searches for such clauses and does the necessary parsetree
460 * transformations if any are found.
461 *
462 * This routine has to run before preprocess_expression(), so the quals
463 * clauses are not yet reduced to implicit-AND format, and are not guaranteed
464 * to be AND/OR-flat either. That means we need to recursively search through
465 * explicit AND clauses. We stop as soon as we hit a non-AND item.
466 */
467void
469{
470 Node *jtnode;
471 Relids relids;
472
473 /* Begin recursion through the jointree */
475 (Node *) root->parse->jointree,
476 &relids);
477
478 /*
479 * root->parse->jointree must always be a FromExpr, so insert a dummy one
480 * if we got a bare RangeTblRef or JoinExpr out of the recursion.
481 */
482 if (IsA(jtnode, FromExpr))
483 root->parse->jointree = (FromExpr *) jtnode;
484 else
485 root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
486}
487
488/*
489 * Recurse through jointree nodes for pull_up_sublinks()
490 *
491 * In addition to returning the possibly-modified jointree node, we return
492 * a relids set of the contained rels into *relids.
493 */
494static Node *
496 Relids *relids)
497{
498 /* Since this function recurses, it could be driven to stack overflow. */
500
501 if (jtnode == NULL)
502 {
503 *relids = NULL;
504 }
505 else if (IsA(jtnode, RangeTblRef))
506 {
507 int varno = ((RangeTblRef *) jtnode)->rtindex;
508
509 *relids = bms_make_singleton(varno);
510 /* jtnode is returned unmodified */
511 }
512 else if (IsA(jtnode, FromExpr))
513 {
514 FromExpr *f = (FromExpr *) jtnode;
515 List *newfromlist = NIL;
516 Relids frelids = NULL;
517 FromExpr *newf;
518 Node *jtlink;
519 ListCell *l;
520
521 /* First, recurse to process children and collect their relids */
522 foreach(l, f->fromlist)
523 {
524 Node *newchild;
525 Relids childrelids;
526
528 lfirst(l),
529 &childrelids);
530 newfromlist = lappend(newfromlist, newchild);
531 frelids = bms_join(frelids, childrelids);
532 }
533 /* Build the replacement FromExpr; no quals yet */
534 newf = makeFromExpr(newfromlist, NULL);
535 /* Set up a link representing the rebuilt jointree */
536 jtlink = (Node *) newf;
537 /* Now process qual --- all children are available for use */
539 &jtlink, frelids,
540 NULL, NULL);
541
542 /*
543 * Note that the result will be either newf, or a stack of JoinExprs
544 * with newf at the base. We rely on subsequent optimization steps to
545 * flatten this and rearrange the joins as needed.
546 *
547 * Although we could include the pulled-up subqueries in the returned
548 * relids, there's no need since upper quals couldn't refer to their
549 * outputs anyway.
550 */
551 *relids = frelids;
552 jtnode = jtlink;
553 }
554 else if (IsA(jtnode, JoinExpr))
555 {
556 JoinExpr *j;
557 Relids leftrelids;
558 Relids rightrelids;
559 Node *jtlink;
560
561 /*
562 * Make a modifiable copy of join node, but don't bother copying its
563 * subnodes (yet).
564 */
565 j = (JoinExpr *) palloc(sizeof(JoinExpr));
566 memcpy(j, jtnode, sizeof(JoinExpr));
567 jtlink = (Node *) j;
568
569 /* Recurse to process children and collect their relids */
571 &leftrelids);
573 &rightrelids);
574
575 /*
576 * Now process qual, showing appropriate child relids as available,
577 * and attach any pulled-up jointree items at the right place. In the
578 * inner-join case we put new JoinExprs above the existing one (much
579 * as for a FromExpr-style join). In outer-join cases the new
580 * JoinExprs must go into the nullable side of the outer join. The
581 * point of the available_rels machinations is to ensure that we only
582 * pull up quals for which that's okay.
583 *
584 * We don't expect to see any pre-existing JOIN_SEMI, JOIN_ANTI,
585 * JOIN_RIGHT_SEMI, or JOIN_RIGHT_ANTI jointypes here.
586 */
587 switch (j->jointype)
588 {
589 case JOIN_INNER:
590 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
591 &jtlink,
592 bms_union(leftrelids,
593 rightrelids),
594 NULL, NULL);
595 break;
596 case JOIN_LEFT:
597 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
598 &j->rarg,
599 rightrelids,
600 NULL, NULL);
601 break;
602 case JOIN_FULL:
603 /* can't do anything with full-join quals */
604 break;
605 case JOIN_RIGHT:
606 j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
607 &j->larg,
608 leftrelids,
609 NULL, NULL);
610 break;
611 default:
612 elog(ERROR, "unrecognized join type: %d",
613 (int) j->jointype);
614 break;
615 }
616
617 /*
618 * Although we could include the pulled-up subqueries in the returned
619 * relids, there's no need since upper quals couldn't refer to their
620 * outputs anyway. But we *do* need to include the join's own rtindex
621 * because we haven't yet collapsed join alias variables, so upper
622 * levels would mistakenly think they couldn't use references to this
623 * join.
624 */
625 *relids = bms_join(leftrelids, rightrelids);
626 if (j->rtindex)
627 *relids = bms_add_member(*relids, j->rtindex);
628 jtnode = jtlink;
629 }
630 else
631 elog(ERROR, "unrecognized node type: %d",
632 (int) nodeTag(jtnode));
633 return jtnode;
634}
635
636/*
637 * Recurse through top-level qual nodes for pull_up_sublinks()
638 *
639 * jtlink1 points to the link in the jointree where any new JoinExprs should
640 * be inserted if they reference available_rels1 (i.e., available_rels1
641 * denotes the relations present underneath jtlink1). Optionally, jtlink2 can
642 * point to a second link where new JoinExprs should be inserted if they
643 * reference available_rels2 (pass NULL for both those arguments if not used).
644 * Note that SubLinks referencing both sets of variables cannot be optimized.
645 * If we find multiple pull-up-able SubLinks, they'll get stacked onto jtlink1
646 * and/or jtlink2 in the order we encounter them. We rely on subsequent
647 * optimization to rearrange the stack if appropriate.
648 *
649 * Returns the replacement qual node, or NULL if the qual should be removed.
650 */
651static Node *
653 Node **jtlink1, Relids available_rels1,
654 Node **jtlink2, Relids available_rels2)
655{
656 if (node == NULL)
657 return NULL;
658 if (IsA(node, SubLink))
659 {
660 SubLink *sublink = (SubLink *) node;
661 JoinExpr *j;
662 Relids child_rels;
663
664 /* Is it a convertible ANY or EXISTS clause? */
665 if (sublink->subLinkType == ANY_SUBLINK)
666 {
667 ScalarArrayOpExpr *saop;
668
669 if ((saop = convert_VALUES_to_ANY(root,
670 sublink->testexpr,
671 (Query *) sublink->subselect)) != NULL)
672
673 /*
674 * The VALUES sequence was simplified. Nothing more to do
675 * here.
676 */
677 return (Node *) saop;
678
679 if ((j = convert_ANY_sublink_to_join(root, sublink,
680 available_rels1)) != NULL)
681 {
682 /* Yes; insert the new join node into the join tree */
683 j->larg = *jtlink1;
684 *jtlink1 = (Node *) j;
685 /* Recursively process pulled-up jointree nodes */
687 j->rarg,
688 &child_rels);
689
690 /*
691 * Now recursively process the pulled-up quals. Any inserted
692 * joins can get stacked onto either j->larg or j->rarg,
693 * depending on which rels they reference.
694 */
696 j->quals,
697 &j->larg,
698 available_rels1,
699 &j->rarg,
700 child_rels);
701 /* Return NULL representing constant TRUE */
702 return NULL;
703 }
704 if (available_rels2 != NULL &&
706 available_rels2)) != NULL)
707 {
708 /* Yes; insert the new join node into the join tree */
709 j->larg = *jtlink2;
710 *jtlink2 = (Node *) j;
711 /* Recursively process pulled-up jointree nodes */
713 j->rarg,
714 &child_rels);
715
716 /*
717 * Now recursively process the pulled-up quals. Any inserted
718 * joins can get stacked onto either j->larg or j->rarg,
719 * depending on which rels they reference.
720 */
722 j->quals,
723 &j->larg,
724 available_rels2,
725 &j->rarg,
726 child_rels);
727 /* Return NULL representing constant TRUE */
728 return NULL;
729 }
730 }
731 else if (sublink->subLinkType == EXISTS_SUBLINK)
732 {
733 if ((j = convert_EXISTS_sublink_to_join(root, sublink, false,
734 available_rels1)) != NULL)
735 {
736 /* Yes; insert the new join node into the join tree */
737 j->larg = *jtlink1;
738 *jtlink1 = (Node *) j;
739 /* Recursively process pulled-up jointree nodes */
741 j->rarg,
742 &child_rels);
743
744 /*
745 * Now recursively process the pulled-up quals. Any inserted
746 * joins can get stacked onto either j->larg or j->rarg,
747 * depending on which rels they reference.
748 */
750 j->quals,
751 &j->larg,
752 available_rels1,
753 &j->rarg,
754 child_rels);
755 /* Return NULL representing constant TRUE */
756 return NULL;
757 }
758 if (available_rels2 != NULL &&
759 (j = convert_EXISTS_sublink_to_join(root, sublink, false,
760 available_rels2)) != NULL)
761 {
762 /* Yes; insert the new join node into the join tree */
763 j->larg = *jtlink2;
764 *jtlink2 = (Node *) j;
765 /* Recursively process pulled-up jointree nodes */
767 j->rarg,
768 &child_rels);
769
770 /*
771 * Now recursively process the pulled-up quals. Any inserted
772 * joins can get stacked onto either j->larg or j->rarg,
773 * depending on which rels they reference.
774 */
776 j->quals,
777 &j->larg,
778 available_rels2,
779 &j->rarg,
780 child_rels);
781 /* Return NULL representing constant TRUE */
782 return NULL;
783 }
784 }
785 /* Else return it unmodified */
786 return node;
787 }
788 if (is_notclause(node))
789 {
790 /* If the immediate argument of NOT is EXISTS, try to convert */
791 SubLink *sublink = (SubLink *) get_notclausearg((Expr *) node);
792 JoinExpr *j;
793 Relids child_rels;
794
795 if (sublink && IsA(sublink, SubLink))
796 {
797 if (sublink->subLinkType == EXISTS_SUBLINK)
798 {
799 if ((j = convert_EXISTS_sublink_to_join(root, sublink, true,
800 available_rels1)) != NULL)
801 {
802 /* Yes; insert the new join node into the join tree */
803 j->larg = *jtlink1;
804 *jtlink1 = (Node *) j;
805 /* Recursively process pulled-up jointree nodes */
807 j->rarg,
808 &child_rels);
809
810 /*
811 * Now recursively process the pulled-up quals. Because
812 * we are underneath a NOT, we can't pull up sublinks that
813 * reference the left-hand stuff, but it's still okay to
814 * pull up sublinks referencing j->rarg.
815 */
817 j->quals,
818 &j->rarg,
819 child_rels,
820 NULL, NULL);
821 /* Return NULL representing constant TRUE */
822 return NULL;
823 }
824 if (available_rels2 != NULL &&
825 (j = convert_EXISTS_sublink_to_join(root, sublink, true,
826 available_rels2)) != NULL)
827 {
828 /* Yes; insert the new join node into the join tree */
829 j->larg = *jtlink2;
830 *jtlink2 = (Node *) j;
831 /* Recursively process pulled-up jointree nodes */
833 j->rarg,
834 &child_rels);
835
836 /*
837 * Now recursively process the pulled-up quals. Because
838 * we are underneath a NOT, we can't pull up sublinks that
839 * reference the left-hand stuff, but it's still okay to
840 * pull up sublinks referencing j->rarg.
841 */
843 j->quals,
844 &j->rarg,
845 child_rels,
846 NULL, NULL);
847 /* Return NULL representing constant TRUE */
848 return NULL;
849 }
850 }
851 }
852 /* Else return it unmodified */
853 return node;
854 }
855 if (is_andclause(node))
856 {
857 /* Recurse into AND clause */
858 List *newclauses = NIL;
859 ListCell *l;
860
861 foreach(l, ((BoolExpr *) node)->args)
862 {
863 Node *oldclause = (Node *) lfirst(l);
864 Node *newclause;
865
867 oldclause,
868 jtlink1,
869 available_rels1,
870 jtlink2,
871 available_rels2);
872 if (newclause)
873 newclauses = lappend(newclauses, newclause);
874 }
875 /* We might have got back fewer clauses than we started with */
876 if (newclauses == NIL)
877 return NULL;
878 else if (list_length(newclauses) == 1)
879 return (Node *) linitial(newclauses);
880 else
881 return (Node *) make_andclause(newclauses);
882 }
883 /* Stop if not an AND */
884 return node;
885}
886
887/*
888 * preprocess_function_rtes
889 * Constant-simplify any FUNCTION RTEs in the FROM clause, and then
890 * attempt to "inline" any that are set-returning functions.
891 *
892 * If an RTE_FUNCTION rtable entry invokes a set-returning function that
893 * contains just a simple SELECT, we can convert the rtable entry to an
894 * RTE_SUBQUERY entry exposing the SELECT directly. This is especially
895 * useful if the subquery can then be "pulled up" for further optimization,
896 * but we do it even if not, to reduce executor overhead.
897 *
898 * This has to be done before we have started to do any optimization of
899 * subqueries, else any such steps wouldn't get applied to subqueries
900 * obtained via inlining. However, we do it after pull_up_sublinks
901 * so that we can inline any functions used in SubLink subselects.
902 *
903 * The reason for applying const-simplification at this stage is that
904 * (a) we'd need to do it anyway to inline a SRF, and (b) by doing it now,
905 * we can be sure that pull_up_constant_function() will see constants
906 * if there are constants to be seen. This approach also guarantees
907 * that every FUNCTION RTE has been const-simplified, allowing planner.c's
908 * preprocess_expression() to skip doing it again.
909 *
910 * Like most of the planner, this feels free to scribble on its input data
911 * structure.
912 */
913void
915{
916 ListCell *rt;
917
918 foreach(rt, root->parse->rtable)
919 {
920 RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
921
922 if (rte->rtekind == RTE_FUNCTION)
923 {
924 Query *funcquery;
925
926 /* Apply const-simplification */
927 rte->functions = (List *)
929
930 /* Check safety of expansion, and expand if possible */
931 funcquery = inline_set_returning_function(root, rte);
932 if (funcquery)
933 {
934 /* Successful expansion, convert the RTE to a subquery */
935 rte->rtekind = RTE_SUBQUERY;
936 rte->subquery = funcquery;
937 rte->security_barrier = false;
938
939 /*
940 * Clear fields that should not be set in a subquery RTE.
941 * However, we leave rte->functions filled in for the moment,
942 * in case makeWholeRowVar needs to consult it. We'll clear
943 * it in setrefs.c (see add_rte_to_flat_rtable) so that this
944 * abuse of the data structure doesn't escape the planner.
945 */
946 rte->funcordinality = false;
947 }
948 }
949 }
950}
951
952/*
953 * expand_virtual_generated_columns
954 * Expand all virtual generated column references in a query.
955 *
956 * This scans the rangetable for relations with virtual generated columns, and
957 * replaces all Var nodes in the query that reference these columns with the
958 * generation expressions. Note that we do not descend into subqueries; that
959 * is taken care of when the subqueries are planned.
960 *
961 * This has to be done after we have pulled up any SubLinks within the query's
962 * quals; otherwise any virtual generated column references within the SubLinks
963 * that should be transformed into joins wouldn't get expanded.
964 *
965 * Returns a modified copy of the query tree, if any relations with virtual
966 * generated columns are present.
967 */
968Query *
970{
971 Query *parse = root->parse;
972 int rt_index;
973 ListCell *lc;
974
975 rt_index = 0;
976 foreach(lc, parse->rtable)
977 {
978 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
979 Relation rel;
980 TupleDesc tupdesc;
981
982 ++rt_index;
983
984 /*
985 * Only normal relations can have virtual generated columns.
986 */
987 if (rte->rtekind != RTE_RELATION)
988 continue;
989
990 rel = table_open(rte->relid, NoLock);
991
992 tupdesc = RelationGetDescr(rel);
993 if (tupdesc->constr && tupdesc->constr->has_generated_virtual)
994 {
995 List *tlist = NIL;
997
998 for (int i = 0; i < tupdesc->natts; i++)
999 {
1000 Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
1001 TargetEntry *tle;
1002
1003 if (attr->attgenerated == ATTRIBUTE_GENERATED_VIRTUAL)
1004 {
1005 Node *defexpr;
1006
1007 defexpr = build_generation_expression(rel, i + 1);
1008 ChangeVarNodes(defexpr, 1, rt_index, 0);
1009
1010 tle = makeTargetEntry((Expr *) defexpr, i + 1, 0, false);
1011 tlist = lappend(tlist, tle);
1012 }
1013 else
1014 {
1015 Var *var;
1016
1017 var = makeVar(rt_index,
1018 i + 1,
1019 attr->atttypid,
1020 attr->atttypmod,
1021 attr->attcollation,
1022 0);
1023
1024 tle = makeTargetEntry((Expr *) var, i + 1, 0, false);
1025 tlist = lappend(tlist, tle);
1026 }
1027 }
1028
1029 Assert(list_length(tlist) > 0);
1030 Assert(!rte->lateral);
1031
1032 /*
1033 * The relation's targetlist items are now in the appropriate form
1034 * to insert into the query, except that we may need to wrap them
1035 * in PlaceHolderVars. Set up required context data for
1036 * pullup_replace_vars.
1037 */
1038 rvcontext.root = root;
1039 rvcontext.targetlist = tlist;
1040 rvcontext.target_rte = rte;
1041 rvcontext.result_relation = parse->resultRelation;
1042 /* won't need these values */
1043 rvcontext.relids = NULL;
1044 rvcontext.nullinfo = NULL;
1045 /* pass NULL for outer_hasSubLinks */
1046 rvcontext.outer_hasSubLinks = NULL;
1047 rvcontext.varno = rt_index;
1048 /* this flag will be set below, if needed */
1049 rvcontext.wrap_option = REPLACE_WRAP_NONE;
1050 /* initialize cache array with indexes 0 .. length(tlist) */
1051 rvcontext.rv_cache = palloc0((list_length(tlist) + 1) *
1052 sizeof(Node *));
1053
1054 /*
1055 * If the query uses grouping sets, we need a PlaceHolderVar for
1056 * each expression of the relation's targetlist items. (See
1057 * comments in pull_up_simple_subquery().)
1058 */
1059 if (parse->groupingSets)
1060 rvcontext.wrap_option = REPLACE_WRAP_ALL;
1061
1062 /*
1063 * Apply pullup variable replacement throughout the query tree.
1064 */
1065 parse = (Query *) pullup_replace_vars((Node *) parse, &rvcontext);
1066 }
1067
1068 table_close(rel, NoLock);
1069 }
1070
1071 return parse;
1072}
1073
1074/*
1075 * pull_up_subqueries
1076 * Look for subqueries in the rangetable that can be pulled up into
1077 * the parent query. If the subquery has no special features like
1078 * grouping/aggregation then we can merge it into the parent's jointree.
1079 * Also, subqueries that are simple UNION ALL structures can be
1080 * converted into "append relations".
1081 */
1082void
1084{
1085 /* Top level of jointree must always be a FromExpr */
1086 Assert(IsA(root->parse->jointree, FromExpr));
1087 /* Recursion starts with no containing join nor appendrel */
1088 root->parse->jointree = (FromExpr *)
1089 pull_up_subqueries_recurse(root, (Node *) root->parse->jointree,
1090 NULL, NULL);
1091 /* We should still have a FromExpr */
1092 Assert(IsA(root->parse->jointree, FromExpr));
1093}
1094
1095/*
1096 * pull_up_subqueries_recurse
1097 * Recursive guts of pull_up_subqueries.
1098 *
1099 * This recursively processes the jointree and returns a modified jointree.
1100 *
1101 * If this jointree node is within either side of an outer join, then
1102 * lowest_outer_join references the lowest such JoinExpr node; otherwise
1103 * it is NULL. We use this to constrain the effects of LATERAL subqueries.
1104 *
1105 * If we are looking at a member subquery of an append relation,
1106 * containing_appendrel describes that relation; else it is NULL.
1107 * This forces use of the PlaceHolderVar mechanism for all non-Var targetlist
1108 * items, and puts some additional restrictions on what can be pulled up.
1109 *
1110 * A tricky aspect of this code is that if we pull up a subquery we have
1111 * to replace Vars that reference the subquery's outputs throughout the
1112 * parent query, including quals attached to jointree nodes above the one
1113 * we are currently processing! We handle this by being careful to maintain
1114 * validity of the jointree structure while recursing, in the following sense:
1115 * whenever we recurse, all qual expressions in the tree must be reachable
1116 * from the top level, in case the recursive call needs to modify them.
1117 *
1118 * Notice also that we can't turn pullup_replace_vars loose on the whole
1119 * jointree, because it'd return a mutated copy of the tree; we have to
1120 * invoke it just on the quals, instead. This behavior is what makes it
1121 * reasonable to pass lowest_outer_join as a pointer rather than some
1122 * more-indirect way of identifying the lowest OJ. Likewise, we don't
1123 * replace append_rel_list members but only their substructure, so the
1124 * containing_appendrel reference is safe to use.
1125 */
1126static Node *
1128 JoinExpr *lowest_outer_join,
1129 AppendRelInfo *containing_appendrel)
1130{
1131 /* Since this function recurses, it could be driven to stack overflow. */
1133 /* Also, since it's a bit expensive, let's check for query cancel. */
1135
1136 Assert(jtnode != NULL);
1137 if (IsA(jtnode, RangeTblRef))
1138 {
1139 int varno = ((RangeTblRef *) jtnode)->rtindex;
1140 RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);
1141
1142 /*
1143 * Is this a subquery RTE, and if so, is the subquery simple enough to
1144 * pull up?
1145 *
1146 * If we are looking at an append-relation member, we can't pull it up
1147 * unless is_safe_append_member says so.
1148 */
1149 if (rte->rtekind == RTE_SUBQUERY &&
1150 is_simple_subquery(root, rte->subquery, rte, lowest_outer_join) &&
1151 (containing_appendrel == NULL ||
1153 return pull_up_simple_subquery(root, jtnode, rte,
1154 lowest_outer_join,
1155 containing_appendrel);
1156
1157 /*
1158 * Alternatively, is it a simple UNION ALL subquery? If so, flatten
1159 * into an "append relation".
1160 *
1161 * It's safe to do this regardless of whether this query is itself an
1162 * appendrel member. (If you're thinking we should try to flatten the
1163 * two levels of appendrel together, you're right; but we handle that
1164 * in set_append_rel_pathlist, not here.)
1165 */
1166 if (rte->rtekind == RTE_SUBQUERY &&
1168 return pull_up_simple_union_all(root, jtnode, rte);
1169
1170 /*
1171 * Or perhaps it's a simple VALUES RTE?
1172 *
1173 * We don't allow VALUES pullup below an outer join nor into an
1174 * appendrel (such cases are impossible anyway at the moment).
1175 */
1176 if (rte->rtekind == RTE_VALUES &&
1177 lowest_outer_join == NULL &&
1178 containing_appendrel == NULL &&
1179 is_simple_values(root, rte))
1180 return pull_up_simple_values(root, jtnode, rte);
1181
1182 /*
1183 * Or perhaps it's a FUNCTION RTE that we could inline?
1184 */
1185 if (rte->rtekind == RTE_FUNCTION)
1186 return pull_up_constant_function(root, jtnode, rte,
1187 containing_appendrel);
1188
1189 /* Otherwise, do nothing at this node. */
1190 }
1191 else if (IsA(jtnode, FromExpr))
1192 {
1193 FromExpr *f = (FromExpr *) jtnode;
1194 ListCell *l;
1195
1196 Assert(containing_appendrel == NULL);
1197 /* Recursively transform all the child nodes */
1198 foreach(l, f->fromlist)
1199 {
1201 lowest_outer_join,
1202 NULL);
1203 }
1204 }
1205 else if (IsA(jtnode, JoinExpr))
1206 {
1207 JoinExpr *j = (JoinExpr *) jtnode;
1208
1209 Assert(containing_appendrel == NULL);
1210 /* Recurse, being careful to tell myself when inside outer join */
1211 switch (j->jointype)
1212 {
1213 case JOIN_INNER:
1214 j->larg = pull_up_subqueries_recurse(root, j->larg,
1215 lowest_outer_join,
1216 NULL);
1217 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
1218 lowest_outer_join,
1219 NULL);
1220 break;
1221 case JOIN_LEFT:
1222 case JOIN_SEMI:
1223 case JOIN_ANTI:
1224 j->larg = pull_up_subqueries_recurse(root, j->larg,
1225 j,
1226 NULL);
1227 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
1228 j,
1229 NULL);
1230 break;
1231 case JOIN_FULL:
1232 j->larg = pull_up_subqueries_recurse(root, j->larg,
1233 j,
1234 NULL);
1235 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
1236 j,
1237 NULL);
1238 break;
1239 case JOIN_RIGHT:
1240 j->larg = pull_up_subqueries_recurse(root, j->larg,
1241 j,
1242 NULL);
1243 j->rarg = pull_up_subqueries_recurse(root, j->rarg,
1244 j,
1245 NULL);
1246 break;
1247 default:
1248 elog(ERROR, "unrecognized join type: %d",
1249 (int) j->jointype);
1250 break;
1251 }
1252 }
1253 else
1254 elog(ERROR, "unrecognized node type: %d",
1255 (int) nodeTag(jtnode));
1256 return jtnode;
1257}
1258
1259/*
1260 * pull_up_simple_subquery
1261 * Attempt to pull up a single simple subquery.
1262 *
1263 * jtnode is a RangeTblRef that has been tentatively identified as a simple
1264 * subquery by pull_up_subqueries. We return the replacement jointree node,
1265 * or jtnode itself if we determine that the subquery can't be pulled up
1266 * after all.
1267 *
1268 * rte is the RangeTblEntry referenced by jtnode. Remaining parameters are
1269 * as for pull_up_subqueries_recurse.
1270 */
1271static Node *
1273 JoinExpr *lowest_outer_join,
1274 AppendRelInfo *containing_appendrel)
1275{
1276 Query *parse = root->parse;
1277 int varno = ((RangeTblRef *) jtnode)->rtindex;
1278 Query *subquery;
1279 PlannerInfo *subroot;
1280 int rtoffset;
1282 ListCell *lc;
1283
1284 /*
1285 * Make a modifiable copy of the subquery to hack on, so that the RTE will
1286 * be left unchanged in case we decide below that we can't pull it up
1287 * after all.
1288 */
1289 subquery = copyObject(rte->subquery);
1290
1291 /*
1292 * Create a PlannerInfo data structure for this subquery.
1293 *
1294 * NOTE: the next few steps should match the first processing in
1295 * subquery_planner(). Can we refactor to avoid code duplication, or
1296 * would that just make things uglier?
1297 */
1298 subroot = makeNode(PlannerInfo);
1299 subroot->parse = subquery;
1300 subroot->glob = root->glob;
1301 subroot->query_level = root->query_level;
1302 subroot->parent_root = root->parent_root;
1303 subroot->plan_params = NIL;
1304 subroot->outer_params = NULL;
1305 subroot->planner_cxt = CurrentMemoryContext;
1306 subroot->init_plans = NIL;
1307 subroot->cte_plan_ids = NIL;
1308 subroot->multiexpr_params = NIL;
1309 subroot->join_domains = NIL;
1310 subroot->eq_classes = NIL;
1311 subroot->ec_merging_done = false;
1312 subroot->last_rinfo_serial = 0;
1313 subroot->all_result_relids = NULL;
1314 subroot->leaf_result_relids = NULL;
1315 subroot->append_rel_list = NIL;
1316 subroot->row_identity_vars = NIL;
1317 subroot->rowMarks = NIL;
1318 memset(subroot->upper_rels, 0, sizeof(subroot->upper_rels));
1319 memset(subroot->upper_targets, 0, sizeof(subroot->upper_targets));
1320 subroot->processed_groupClause = NIL;
1321 subroot->processed_distinctClause = NIL;
1322 subroot->processed_tlist = NIL;
1323 subroot->update_colnos = NIL;
1324 subroot->grouping_map = NULL;
1325 subroot->minmax_aggs = NIL;
1326 subroot->qual_security_level = 0;
1327 subroot->placeholdersFrozen = false;
1328 subroot->hasRecursion = false;
1329 subroot->wt_param_id = -1;
1330 subroot->non_recursive_path = NULL;
1331 /* We don't currently need a top JoinDomain for the subroot */
1332
1333 /* No CTEs to worry about */
1334 Assert(subquery->cteList == NIL);
1335
1336 /*
1337 * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
1338 * that we don't need so many special cases to deal with that situation.
1339 */
1340 replace_empty_jointree(subquery);
1341
1342 /*
1343 * Pull up any SubLinks within the subquery's quals, so that we don't
1344 * leave unoptimized SubLinks behind.
1345 */
1346 if (subquery->hasSubLinks)
1347 pull_up_sublinks(subroot);
1348
1349 /*
1350 * Similarly, preprocess its function RTEs to inline any set-returning
1351 * functions in its rangetable.
1352 */
1353 preprocess_function_rtes(subroot);
1354
1355 /*
1356 * Scan the rangetable for relations with virtual generated columns, and
1357 * replace all Var nodes in the query that reference these columns with
1358 * the generation expressions.
1359 */
1360 subquery = subroot->parse = expand_virtual_generated_columns(subroot);
1361
1362 /*
1363 * Recursively pull up the subquery's subqueries, so that
1364 * pull_up_subqueries' processing is complete for its jointree and
1365 * rangetable.
1366 *
1367 * Note: it's okay that the subquery's recursion starts with NULL for
1368 * containing-join info, even if we are within an outer join in the upper
1369 * query; the lower query starts with a clean slate for outer-join
1370 * semantics. Likewise, we needn't pass down appendrel state.
1371 */
1372 pull_up_subqueries(subroot);
1373
1374 /*
1375 * Now we must recheck whether the subquery is still simple enough to pull
1376 * up. If not, abandon processing it.
1377 *
1378 * We don't really need to recheck all the conditions involved, but it's
1379 * easier just to keep this "if" looking the same as the one in
1380 * pull_up_subqueries_recurse.
1381 */
1382 if (is_simple_subquery(root, subquery, rte, lowest_outer_join) &&
1383 (containing_appendrel == NULL || is_safe_append_member(subquery)))
1384 {
1385 /* good to go */
1386 }
1387 else
1388 {
1389 /*
1390 * Give up, return unmodified RangeTblRef.
1391 *
1392 * Note: The work we just did will be redone when the subquery gets
1393 * planned on its own. Perhaps we could avoid that by storing the
1394 * modified subquery back into the rangetable, but I'm not gonna risk
1395 * it now.
1396 */
1397 return jtnode;
1398 }
1399
1400 /*
1401 * We must flatten any join alias Vars in the subquery's targetlist,
1402 * because pulling up the subquery's subqueries might have changed their
1403 * expansions into arbitrary expressions, which could affect
1404 * pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
1405 * are needed for tlist entries. (Likely it'd be better to do
1406 * flatten_join_alias_vars on the whole query tree at some earlier stage,
1407 * maybe even in the rewriter; but for now let's just fix this case here.)
1408 */
1409 subquery->targetList = (List *)
1410 flatten_join_alias_vars(subroot, subroot->parse,
1411 (Node *) subquery->targetList);
1412
1413 /*
1414 * Adjust level-0 varnos in subquery so that we can append its rangetable
1415 * to upper query's. We have to fix the subquery's append_rel_list as
1416 * well.
1417 */
1418 rtoffset = list_length(parse->rtable);
1419 OffsetVarNodes((Node *) subquery, rtoffset, 0);
1420 OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
1421
1422 /*
1423 * Upper-level vars in subquery are now one level closer to their parent
1424 * than before.
1425 */
1426 IncrementVarSublevelsUp((Node *) subquery, -1, 1);
1427 IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
1428
1429 /*
1430 * The subquery's targetlist items are now in the appropriate form to
1431 * insert into the top query, except that we may need to wrap them in
1432 * PlaceHolderVars. Set up required context data for pullup_replace_vars.
1433 * (Note that we should include the subquery's inner joins in relids,
1434 * since it may include join alias vars referencing them.)
1435 */
1436 rvcontext.root = root;
1437 rvcontext.targetlist = subquery->targetList;
1438 rvcontext.target_rte = rte;
1439 rvcontext.result_relation = 0;
1440 if (rte->lateral)
1441 {
1442 rvcontext.relids = get_relids_in_jointree((Node *) subquery->jointree,
1443 true, true);
1444 rvcontext.nullinfo = get_nullingrels(parse);
1445 }
1446 else /* won't need these values */
1447 {
1448 rvcontext.relids = NULL;
1449 rvcontext.nullinfo = NULL;
1450 }
1451 rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1452 rvcontext.varno = varno;
1453 /* this flag will be set below, if needed */
1454 rvcontext.wrap_option = REPLACE_WRAP_NONE;
1455 /* initialize cache array with indexes 0 .. length(tlist) */
1456 rvcontext.rv_cache = palloc0((list_length(subquery->targetList) + 1) *
1457 sizeof(Node *));
1458
1459 /*
1460 * If the parent query uses grouping sets, we need a PlaceHolderVar for
1461 * each expression of the subquery's targetlist items. This ensures that
1462 * expressions retain their separate identity so that they will match
1463 * grouping set columns when appropriate. (It'd be sufficient to wrap
1464 * values used in grouping set columns, and do so only in non-aggregated
1465 * portions of the tlist and havingQual, but that would require a lot of
1466 * infrastructure that pullup_replace_vars hasn't currently got.)
1467 */
1468 if (parse->groupingSets)
1469 rvcontext.wrap_option = REPLACE_WRAP_ALL;
1470
1471 /*
1472 * Replace all of the top query's references to the subquery's outputs
1473 * with copies of the adjusted subtlist items, being careful not to
1474 * replace any of the jointree structure.
1475 */
1477 containing_appendrel);
1478
1479 /*
1480 * If the subquery had a LATERAL marker, propagate that to any of its
1481 * child RTEs that could possibly now contain lateral cross-references.
1482 * The children might or might not contain any actual lateral
1483 * cross-references, but we have to mark the pulled-up child RTEs so that
1484 * later planner stages will check for such.
1485 */
1486 if (rte->lateral)
1487 {
1488 foreach(lc, subquery->rtable)
1489 {
1490 RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(lc);
1491
1492 switch (child_rte->rtekind)
1493 {
1494 case RTE_RELATION:
1495 if (child_rte->tablesample)
1496 child_rte->lateral = true;
1497 break;
1498 case RTE_SUBQUERY:
1499 case RTE_FUNCTION:
1500 case RTE_VALUES:
1501 case RTE_TABLEFUNC:
1502 child_rte->lateral = true;
1503 break;
1504 case RTE_JOIN:
1505 case RTE_CTE:
1507 case RTE_RESULT:
1508 case RTE_GROUP:
1509 /* these can't contain any lateral references */
1510 break;
1511 }
1512 }
1513 }
1514
1515 /*
1516 * Now append the adjusted rtable entries and their perminfos to upper
1517 * query. (We hold off until after fixing the upper rtable entries; no
1518 * point in running that code on the subquery ones too.)
1519 */
1520 CombineRangeTables(&parse->rtable, &parse->rteperminfos,
1521 subquery->rtable, subquery->rteperminfos);
1522
1523 /*
1524 * Pull up any FOR UPDATE/SHARE markers, too. (OffsetVarNodes already
1525 * adjusted the marker rtindexes, so just concat the lists.)
1526 */
1527 parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
1528
1529 /*
1530 * We also have to fix the relid sets of any PlaceHolderVar nodes in the
1531 * parent query. (This could perhaps be done by pullup_replace_vars(),
1532 * but it seems cleaner to use two passes.) Note in particular that any
1533 * PlaceHolderVar nodes just created by pullup_replace_vars() will be
1534 * adjusted, so having created them with the subquery's varno is correct.
1535 *
1536 * Likewise, relids appearing in AppendRelInfo nodes have to be fixed. We
1537 * already checked that this won't require introducing multiple subrelids
1538 * into the single-slot AppendRelInfo structs.
1539 */
1540 if (root->glob->lastPHId != 0 || root->append_rel_list)
1541 {
1542 Relids subrelids;
1543
1544 subrelids = get_relids_in_jointree((Node *) subquery->jointree,
1545 true, false);
1546 if (root->glob->lastPHId != 0)
1547 substitute_phv_relids((Node *) parse, varno, subrelids);
1548 fix_append_rel_relids(root, varno, subrelids);
1549 }
1550
1551 /*
1552 * And now add subquery's AppendRelInfos to our list.
1553 */
1554 root->append_rel_list = list_concat(root->append_rel_list,
1555 subroot->append_rel_list);
1556
1557 /*
1558 * We don't have to do the equivalent bookkeeping for outer-join info,
1559 * because that hasn't been set up yet. placeholder_list likewise.
1560 */
1561 Assert(root->join_info_list == NIL);
1562 Assert(subroot->join_info_list == NIL);
1563 Assert(root->placeholder_list == NIL);
1564 Assert(subroot->placeholder_list == NIL);
1565
1566 /*
1567 * We no longer need the RTE's copy of the subquery's query tree. Getting
1568 * rid of it saves nothing in particular so far as this level of query is
1569 * concerned; but if this query level is in turn pulled up into a parent,
1570 * we'd waste cycles copying the now-unused query tree.
1571 */
1572 rte->subquery = NULL;
1573
1574 /*
1575 * Miscellaneous housekeeping.
1576 *
1577 * Although replace_rte_variables() faithfully updated parse->hasSubLinks
1578 * if it copied any SubLinks out of the subquery's targetlist, we still
1579 * could have SubLinks added to the query in the expressions of FUNCTION
1580 * and VALUES RTEs copied up from the subquery. So it's necessary to copy
1581 * subquery->hasSubLinks anyway. Perhaps this can be improved someday.
1582 */
1583 parse->hasSubLinks |= subquery->hasSubLinks;
1584
1585 /* If subquery had any RLS conditions, now main query does too */
1586 parse->hasRowSecurity |= subquery->hasRowSecurity;
1587
1588 /*
1589 * subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
1590 * hasTargetSRFs, so no work needed on those flags
1591 */
1592
1593 /*
1594 * Return the adjusted subquery jointree to replace the RangeTblRef entry
1595 * in parent's jointree; or, if the FromExpr is degenerate, just return
1596 * its single member.
1597 */
1598 Assert(IsA(subquery->jointree, FromExpr));
1599 Assert(subquery->jointree->fromlist != NIL);
1600 if (subquery->jointree->quals == NULL &&
1601 list_length(subquery->jointree->fromlist) == 1)
1602 return (Node *) linitial(subquery->jointree->fromlist);
1603
1604 return (Node *) subquery->jointree;
1605}
1606
1607/*
1608 * pull_up_simple_union_all
1609 * Pull up a single simple UNION ALL subquery.
1610 *
1611 * jtnode is a RangeTblRef that has been identified as a simple UNION ALL
1612 * subquery by pull_up_subqueries. We pull up the leaf subqueries and
1613 * build an "append relation" for the union set. The result value is just
1614 * jtnode, since we don't actually need to change the query jointree.
1615 */
1616static Node *
1618{
1619 int varno = ((RangeTblRef *) jtnode)->rtindex;
1620 Query *subquery = rte->subquery;
1621 int rtoffset = list_length(root->parse->rtable);
1622 List *rtable;
1623
1624 /*
1625 * Make a modifiable copy of the subquery's rtable, so we can adjust
1626 * upper-level Vars in it. There are no such Vars in the setOperations
1627 * tree proper, so fixing the rtable should be sufficient.
1628 */
1629 rtable = copyObject(subquery->rtable);
1630
1631 /*
1632 * Upper-level vars in subquery are now one level closer to their parent
1633 * than before. We don't have to worry about offsetting varnos, though,
1634 * because the UNION leaf queries can't cross-reference each other.
1635 */
1636 IncrementVarSublevelsUp_rtable(rtable, -1, 1);
1637
1638 /*
1639 * If the UNION ALL subquery had a LATERAL marker, propagate that to all
1640 * its children. The individual children might or might not contain any
1641 * actual lateral cross-references, but we have to mark the pulled-up
1642 * child RTEs so that later planner stages will check for such.
1643 */
1644 if (rte->lateral)
1645 {
1646 ListCell *rt;
1647
1648 foreach(rt, rtable)
1649 {
1650 RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(rt);
1651
1652 Assert(child_rte->rtekind == RTE_SUBQUERY);
1653 child_rte->lateral = true;
1654 }
1655 }
1656
1657 /*
1658 * Append child RTEs (and their perminfos) to parent rtable.
1659 */
1660 CombineRangeTables(&root->parse->rtable, &root->parse->rteperminfos,
1661 rtable, subquery->rteperminfos);
1662
1663 /*
1664 * Recursively scan the subquery's setOperations tree and add
1665 * AppendRelInfo nodes for leaf subqueries to the parent's
1666 * append_rel_list. Also apply pull_up_subqueries to the leaf subqueries.
1667 */
1668 Assert(subquery->setOperations);
1669 pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
1670 rtoffset);
1671
1672 /*
1673 * Mark the parent as an append relation.
1674 */
1675 rte->inh = true;
1676
1677 return jtnode;
1678}
1679
1680/*
1681 * pull_up_union_leaf_queries -- recursive guts of pull_up_simple_union_all
1682 *
1683 * Build an AppendRelInfo for each leaf query in the setop tree, and then
1684 * apply pull_up_subqueries to the leaf query.
1685 *
1686 * Note that setOpQuery is the Query containing the setOp node, whose tlist
1687 * contains references to all the setop output columns. When called from
1688 * pull_up_simple_union_all, this is *not* the same as root->parse, which is
1689 * the parent Query we are pulling up into.
1690 *
1691 * parentRTindex is the appendrel parent's index in root->parse->rtable.
1692 *
1693 * The child RTEs have already been copied to the parent. childRToffset
1694 * tells us where in the parent's range table they were copied. When called
1695 * from flatten_simple_union_all, childRToffset is 0 since the child RTEs
1696 * were already in root->parse->rtable and no RT index adjustment is needed.
1697 */
1698static void
1700 Query *setOpQuery, int childRToffset)
1701{
1702 if (IsA(setOp, RangeTblRef))
1703 {
1704 RangeTblRef *rtr = (RangeTblRef *) setOp;
1705 int childRTindex;
1706 AppendRelInfo *appinfo;
1707
1708 /*
1709 * Calculate the index in the parent's range table
1710 */
1711 childRTindex = childRToffset + rtr->rtindex;
1712
1713 /*
1714 * Build a suitable AppendRelInfo, and attach to parent's list.
1715 */
1716 appinfo = makeNode(AppendRelInfo);
1717 appinfo->parent_relid = parentRTindex;
1718 appinfo->child_relid = childRTindex;
1719 appinfo->parent_reltype = InvalidOid;
1720 appinfo->child_reltype = InvalidOid;
1721 make_setop_translation_list(setOpQuery, childRTindex, appinfo);
1722 appinfo->parent_reloid = InvalidOid;
1723 root->append_rel_list = lappend(root->append_rel_list, appinfo);
1724
1725 /*
1726 * Recursively apply pull_up_subqueries to the new child RTE. (We
1727 * must build the AppendRelInfo first, because this will modify it;
1728 * indeed, that's the only part of the upper query where Vars
1729 * referencing childRTindex can exist at this point.)
1730 *
1731 * Note that we can pass NULL for containing-join info even if we're
1732 * actually under an outer join, because the child's expressions
1733 * aren't going to propagate up to the join. Also, we ignore the
1734 * possibility that pull_up_subqueries_recurse() returns a different
1735 * jointree node than what we pass it; if it does, the important thing
1736 * is that it replaced the child relid in the AppendRelInfo node.
1737 */
1738 rtr = makeNode(RangeTblRef);
1739 rtr->rtindex = childRTindex;
1740 (void) pull_up_subqueries_recurse(root, (Node *) rtr,
1741 NULL, appinfo);
1742 }
1743 else if (IsA(setOp, SetOperationStmt))
1744 {
1745 SetOperationStmt *op = (SetOperationStmt *) setOp;
1746
1747 /* Recurse to reach leaf queries */
1748 pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
1749 childRToffset);
1750 pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
1751 childRToffset);
1752 }
1753 else
1754 {
1755 elog(ERROR, "unrecognized node type: %d",
1756 (int) nodeTag(setOp));
1757 }
1758}
1759
1760/*
1761 * make_setop_translation_list
1762 * Build the list of translations from parent Vars to child Vars for
1763 * a UNION ALL member. (At this point it's just a simple list of
1764 * referencing Vars, but if we succeed in pulling up the member
1765 * subquery, the Vars will get replaced by pulled-up expressions.)
1766 * Also create the rather trivial reverse-translation array.
1767 */
1768static void
1770 AppendRelInfo *appinfo)
1771{
1772 List *vars = NIL;
1773 AttrNumber *pcolnos;
1774 ListCell *l;
1775
1776 /* Initialize reverse-translation array with all entries zero */
1777 /* (entries for resjunk columns will stay that way) */
1778 appinfo->num_child_cols = list_length(query->targetList);
1779 appinfo->parent_colnos = pcolnos =
1780 (AttrNumber *) palloc0(appinfo->num_child_cols * sizeof(AttrNumber));
1781
1782 foreach(l, query->targetList)
1783 {
1784 TargetEntry *tle = (TargetEntry *) lfirst(l);
1785
1786 if (tle->resjunk)
1787 continue;
1788
1789 vars = lappend(vars, makeVarFromTargetEntry(newvarno, tle));
1790 pcolnos[tle->resno - 1] = tle->resno;
1791 }
1792
1793 appinfo->translated_vars = vars;
1794}
1795
1796/*
1797 * is_simple_subquery
1798 * Check a subquery in the range table to see if it's simple enough
1799 * to pull up into the parent query.
1800 *
1801 * rte is the RTE_SUBQUERY RangeTblEntry that contained the subquery.
1802 * (Note subquery is not necessarily equal to rte->subquery; it could be a
1803 * processed copy of that.)
1804 * lowest_outer_join is the lowest outer join above the subquery, or NULL.
1805 */
1806static bool
1808 JoinExpr *lowest_outer_join)
1809{
1810 /*
1811 * Let's just make sure it's a valid subselect ...
1812 */
1813 if (!IsA(subquery, Query) ||
1814 subquery->commandType != CMD_SELECT)
1815 elog(ERROR, "subquery is bogus");
1816
1817 /*
1818 * Can't currently pull up a query with setops (unless it's simple UNION
1819 * ALL, which is handled by a different code path). Maybe after querytree
1820 * redesign...
1821 */
1822 if (subquery->setOperations)
1823 return false;
1824
1825 /*
1826 * Can't pull up a subquery involving grouping, aggregation, SRFs,
1827 * sorting, limiting, or WITH. (XXX WITH could possibly be allowed later)
1828 *
1829 * We also don't pull up a subquery that has explicit FOR UPDATE/SHARE
1830 * clauses, because pullup would cause the locking to occur semantically
1831 * higher than it should. Implicit FOR UPDATE/SHARE is okay because in
1832 * that case the locking was originally declared in the upper query
1833 * anyway.
1834 */
1835 if (subquery->hasAggs ||
1836 subquery->hasWindowFuncs ||
1837 subquery->hasTargetSRFs ||
1838 subquery->groupClause ||
1839 subquery->groupingSets ||
1840 subquery->havingQual ||
1841 subquery->sortClause ||
1842 subquery->distinctClause ||
1843 subquery->limitOffset ||
1844 subquery->limitCount ||
1845 subquery->hasForUpdate ||
1846 subquery->cteList)
1847 return false;
1848
1849 /*
1850 * Don't pull up if the RTE represents a security-barrier view; we
1851 * couldn't prevent information leakage once the RTE's Vars are scattered
1852 * about in the upper query.
1853 */
1854 if (rte->security_barrier)
1855 return false;
1856
1857 /*
1858 * If the subquery is LATERAL, check for pullup restrictions from that.
1859 */
1860 if (rte->lateral)
1861 {
1862 bool restricted;
1863 Relids safe_upper_varnos;
1864
1865 /*
1866 * The subquery's WHERE and JOIN/ON quals mustn't contain any lateral
1867 * references to rels outside a higher outer join (including the case
1868 * where the outer join is within the subquery itself). In such a
1869 * case, pulling up would result in a situation where we need to
1870 * postpone quals from below an outer join to above it, which is
1871 * probably completely wrong and in any case is a complication that
1872 * doesn't seem worth addressing at the moment.
1873 */
1874 if (lowest_outer_join != NULL)
1875 {
1876 restricted = true;
1877 safe_upper_varnos = get_relids_in_jointree((Node *) lowest_outer_join,
1878 true, true);
1879 }
1880 else
1881 {
1882 restricted = false;
1883 safe_upper_varnos = NULL; /* doesn't matter */
1884 }
1885
1887 (Node *) subquery->jointree,
1888 restricted, safe_upper_varnos))
1889 return false;
1890
1891 /*
1892 * If there's an outer join above the LATERAL subquery, also disallow
1893 * pullup if the subquery's targetlist has any references to rels
1894 * outside the outer join, since these might get pulled into quals
1895 * above the subquery (but in or below the outer join) and then lead
1896 * to qual-postponement issues similar to the case checked for above.
1897 * (We wouldn't need to prevent pullup if no such references appear in
1898 * outer-query quals, but we don't have enough info here to check
1899 * that. Also, maybe this restriction could be removed if we forced
1900 * such refs to be wrapped in PlaceHolderVars, even when they're below
1901 * the nearest outer join? But it's a pretty hokey usage, so not
1902 * clear this is worth sweating over.)
1903 *
1904 * If you change this, see also the comments about lateral references
1905 * in pullup_replace_vars_callback().
1906 */
1907 if (lowest_outer_join != NULL)
1908 {
1910 (Node *) subquery->targetList,
1911 1);
1912
1913 if (!bms_is_subset(lvarnos, safe_upper_varnos))
1914 return false;
1915 }
1916 }
1917
1918 /*
1919 * Don't pull up a subquery that has any volatile functions in its
1920 * targetlist. Otherwise we might introduce multiple evaluations of these
1921 * functions, if they get copied to multiple places in the upper query,
1922 * leading to surprising results. (Note: the PlaceHolderVar mechanism
1923 * doesn't quite guarantee single evaluation; else we could pull up anyway
1924 * and just wrap such items in PlaceHolderVars ...)
1925 */
1926 if (contain_volatile_functions((Node *) subquery->targetList))
1927 return false;
1928
1929 return true;
1930}
1931
1932/*
1933 * pull_up_simple_values
1934 * Pull up a single simple VALUES RTE.
1935 *
1936 * jtnode is a RangeTblRef that has been identified as a simple VALUES RTE
1937 * by pull_up_subqueries. We always return a RangeTblRef representing a
1938 * RESULT RTE to replace it (all failure cases should have been detected by
1939 * is_simple_values()). Actually, what we return is just jtnode, because
1940 * we replace the VALUES RTE in the rangetable with the RESULT RTE.
1941 *
1942 * rte is the RangeTblEntry referenced by jtnode. Because of the limited
1943 * possible usage of VALUES RTEs, we do not need the remaining parameters
1944 * of pull_up_subqueries_recurse.
1945 */
1946static Node *
1948{
1949 Query *parse = root->parse;
1950 int varno = ((RangeTblRef *) jtnode)->rtindex;
1951 List *values_list;
1952 List *tlist;
1953 AttrNumber attrno;
1955 ListCell *lc;
1956
1957 Assert(rte->rtekind == RTE_VALUES);
1958 Assert(list_length(rte->values_lists) == 1);
1959
1960 /*
1961 * Need a modifiable copy of the VALUES list to hack on, just in case it's
1962 * multiply referenced.
1963 */
1964 values_list = copyObject(linitial(rte->values_lists));
1965
1966 /*
1967 * The VALUES RTE can't contain any Vars of level zero, let alone any that
1968 * are join aliases, so no need to flatten join alias Vars.
1969 */
1970 Assert(!contain_vars_of_level((Node *) values_list, 0));
1971
1972 /*
1973 * Set up required context data for pullup_replace_vars. In particular,
1974 * we have to make the VALUES list look like a subquery targetlist.
1975 */
1976 tlist = NIL;
1977 attrno = 1;
1978 foreach(lc, values_list)
1979 {
1980 tlist = lappend(tlist,
1981 makeTargetEntry((Expr *) lfirst(lc),
1982 attrno,
1983 NULL,
1984 false));
1985 attrno++;
1986 }
1987 rvcontext.root = root;
1988 rvcontext.targetlist = tlist;
1989 rvcontext.target_rte = rte;
1990 rvcontext.result_relation = 0;
1991 rvcontext.relids = NULL; /* can't be any lateral references here */
1992 rvcontext.nullinfo = NULL;
1993 rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1994 rvcontext.varno = varno;
1995 rvcontext.wrap_option = REPLACE_WRAP_NONE;
1996 /* initialize cache array with indexes 0 .. length(tlist) */
1997 rvcontext.rv_cache = palloc0((list_length(tlist) + 1) *
1998 sizeof(Node *));
1999
2000 /*
2001 * Replace all of the top query's references to the RTE's outputs with
2002 * copies of the adjusted VALUES expressions, being careful not to replace
2003 * any of the jointree structure. We can assume there's no outer joins or
2004 * appendrels in the dummy Query that surrounds a VALUES RTE.
2005 */
2006 perform_pullup_replace_vars(root, &rvcontext, NULL);
2007
2008 /*
2009 * There should be no appendrels to fix, nor any outer joins and hence no
2010 * PlaceHolderVars.
2011 */
2012 Assert(root->append_rel_list == NIL);
2013 Assert(root->join_info_list == NIL);
2014 Assert(root->placeholder_list == NIL);
2015
2016 /*
2017 * Replace the VALUES RTE with a RESULT RTE. The VALUES RTE is the only
2018 * rtable entry in the current query level, so this is easy.
2019 */
2020 Assert(list_length(parse->rtable) == 1);
2021
2022 /* Create suitable RTE */
2023 rte = makeNode(RangeTblEntry);
2024 rte->rtekind = RTE_RESULT;
2025 rte->eref = makeAlias("*RESULT*", NIL);
2026
2027 /* Replace rangetable */
2028 parse->rtable = list_make1(rte);
2029
2030 /* We could manufacture a new RangeTblRef, but the one we have is fine */
2031 Assert(varno == 1);
2032
2033 return jtnode;
2034}
2035
2036/*
2037 * is_simple_values
2038 * Check a VALUES RTE in the range table to see if it's simple enough
2039 * to pull up into the parent query.
2040 *
2041 * rte is the RTE_VALUES RangeTblEntry to check.
2042 */
2043static bool
2045{
2046 Assert(rte->rtekind == RTE_VALUES);
2047
2048 /*
2049 * There must be exactly one VALUES list, else it's not semantically
2050 * correct to replace the VALUES RTE with a RESULT RTE, nor would we have
2051 * a unique set of expressions to substitute into the parent query.
2052 */
2053 if (list_length(rte->values_lists) != 1)
2054 return false;
2055
2056 /*
2057 * Because VALUES can't appear under an outer join (or at least, we won't
2058 * try to pull it up if it does), we need not worry about LATERAL, nor
2059 * about validity of PHVs for the VALUES' outputs.
2060 */
2061
2062 /*
2063 * Don't pull up a VALUES that contains any set-returning or volatile
2064 * functions. The considerations here are basically identical to the
2065 * restrictions on a pull-able subquery's targetlist.
2066 */
2069 return false;
2070
2071 /*
2072 * Do not pull up a VALUES that's not the only RTE in its parent query.
2073 * This is actually the only case that the parser will generate at the
2074 * moment, and assuming this is true greatly simplifies
2075 * pull_up_simple_values().
2076 */
2077 if (list_length(root->parse->rtable) != 1 ||
2078 rte != (RangeTblEntry *) linitial(root->parse->rtable))
2079 return false;
2080
2081 return true;
2082}
2083
2084/*
2085 * pull_up_constant_function
2086 * Pull up an RTE_FUNCTION expression that was simplified to a constant.
2087 *
2088 * jtnode is a RangeTblRef that has been identified as a FUNCTION RTE by
2089 * pull_up_subqueries. If its expression is just a Const, hoist that value
2090 * up into the parent query, and replace the RTE_FUNCTION with RTE_RESULT.
2091 *
2092 * In principle we could pull up any immutable expression, but we don't.
2093 * That might result in multiple evaluations of the expression, which could
2094 * be costly if it's not just a Const. Also, the main value of this is
2095 * to let the constant participate in further const-folding, and of course
2096 * that won't happen for a non-Const.
2097 *
2098 * The pulled-up value might need to be wrapped in a PlaceHolderVar if the
2099 * RTE is below an outer join or is part of an appendrel; the extra
2100 * parameters show whether that's needed.
2101 */
2102static Node *
2104 RangeTblEntry *rte,
2105 AppendRelInfo *containing_appendrel)
2106{
2107 Query *parse = root->parse;
2108 RangeTblFunction *rtf;
2109 TypeFuncClass functypclass;
2110 Oid funcrettype;
2111 TupleDesc tupdesc;
2113
2114 /* Fail if the RTE has ORDINALITY - we don't implement that here. */
2115 if (rte->funcordinality)
2116 return jtnode;
2117
2118 /* Fail if RTE isn't a single, simple Const expr */
2119 if (list_length(rte->functions) != 1)
2120 return jtnode;
2122 if (!IsA(rtf->funcexpr, Const))
2123 return jtnode;
2124
2125 /*
2126 * If the function's result is not a scalar, we punt. In principle we
2127 * could break the composite constant value apart into per-column
2128 * constants, but for now it seems not worth the work.
2129 */
2130 if (rtf->funccolcount != 1)
2131 return jtnode; /* definitely composite */
2132
2133 /* If it has a coldeflist, it certainly returns RECORD */
2134 if (rtf->funccolnames != NIL)
2135 return jtnode; /* must be a one-column RECORD type */
2136
2137 functypclass = get_expr_result_type(rtf->funcexpr,
2138 &funcrettype,
2139 &tupdesc);
2140 if (functypclass != TYPEFUNC_SCALAR)
2141 return jtnode; /* must be a one-column composite type */
2142
2143 /* Create context for applying pullup_replace_vars */
2144 rvcontext.root = root;
2145 rvcontext.targetlist = list_make1(makeTargetEntry((Expr *) rtf->funcexpr,
2146 1, /* resno */
2147 NULL, /* resname */
2148 false)); /* resjunk */
2149 rvcontext.target_rte = rte;
2150 rvcontext.result_relation = 0;
2151
2152 /*
2153 * Since this function was reduced to a Const, it doesn't contain any
2154 * lateral references, even if it's marked as LATERAL. This means we
2155 * don't need to fill relids or nullinfo.
2156 */
2157 rvcontext.relids = NULL;
2158 rvcontext.nullinfo = NULL;
2159
2160 rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
2161 rvcontext.varno = ((RangeTblRef *) jtnode)->rtindex;
2162 /* this flag will be set below, if needed */
2163 rvcontext.wrap_option = REPLACE_WRAP_NONE;
2164 /* initialize cache array with indexes 0 .. length(tlist) */
2165 rvcontext.rv_cache = palloc0((list_length(rvcontext.targetlist) + 1) *
2166 sizeof(Node *));
2167
2168 /*
2169 * If the parent query uses grouping sets, we need a PlaceHolderVar for
2170 * each expression of the subquery's targetlist items. (See comments in
2171 * pull_up_simple_subquery().)
2172 */
2173 if (parse->groupingSets)
2174 rvcontext.wrap_option = REPLACE_WRAP_ALL;
2175
2176 /*
2177 * Replace all of the top query's references to the RTE's output with
2178 * copies of the funcexpr, being careful not to replace any of the
2179 * jointree structure.
2180 */
2182 containing_appendrel);
2183
2184 /*
2185 * We don't need to bother with changing PlaceHolderVars in the parent
2186 * query. Their references to the RT index are still good for now, and
2187 * will get removed later if we're able to drop the RTE_RESULT.
2188 */
2189
2190 /*
2191 * Convert the RTE to be RTE_RESULT type, signifying that we don't need to
2192 * scan it anymore, and zero out RTE_FUNCTION-specific fields. Also make
2193 * sure the RTE is not marked LATERAL, since elsewhere we don't expect
2194 * RTE_RESULTs to be LATERAL.
2195 */
2196 rte->rtekind = RTE_RESULT;
2197 rte->functions = NIL;
2198 rte->lateral = false;
2199
2200 /*
2201 * We can reuse the RangeTblRef node.
2202 */
2203 return jtnode;
2204}
2205
2206/*
2207 * is_simple_union_all
2208 * Check a subquery to see if it's a simple UNION ALL.
2209 *
2210 * We require all the setops to be UNION ALL (no mixing) and there can't be
2211 * any datatype coercions involved, ie, all the leaf queries must emit the
2212 * same datatypes.
2213 */
2214static bool
2216{
2217 SetOperationStmt *topop;
2218
2219 /* Let's just make sure it's a valid subselect ... */
2220 if (!IsA(subquery, Query) ||
2221 subquery->commandType != CMD_SELECT)
2222 elog(ERROR, "subquery is bogus");
2223
2224 /* Is it a set-operation query at all? */
2225 topop = castNode(SetOperationStmt, subquery->setOperations);
2226 if (!topop)
2227 return false;
2228
2229 /* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */
2230 if (subquery->sortClause ||
2231 subquery->limitOffset ||
2232 subquery->limitCount ||
2233 subquery->rowMarks ||
2234 subquery->cteList)
2235 return false;
2236
2237 /* Recursively check the tree of set operations */
2238 return is_simple_union_all_recurse((Node *) topop, subquery,
2239 topop->colTypes);
2240}
2241
2242static bool
2243is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
2244{
2245 /* Since this function recurses, it could be driven to stack overflow. */
2247
2248 if (IsA(setOp, RangeTblRef))
2249 {
2250 RangeTblRef *rtr = (RangeTblRef *) setOp;
2251 RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
2252 Query *subquery = rte->subquery;
2253
2254 Assert(subquery != NULL);
2255
2256 /* Leaf nodes are OK if they match the toplevel column types */
2257 /* We don't have to compare typmods or collations here */
2258 return tlist_same_datatypes(subquery->targetList, colTypes, true);
2259 }
2260 else if (IsA(setOp, SetOperationStmt))
2261 {
2262 SetOperationStmt *op = (SetOperationStmt *) setOp;
2263
2264 /* Must be UNION ALL */
2265 if (op->op != SETOP_UNION || !op->all)
2266 return false;
2267
2268 /* Recurse to check inputs */
2269 return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) &&
2270 is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes);
2271 }
2272 else
2273 {
2274 elog(ERROR, "unrecognized node type: %d",
2275 (int) nodeTag(setOp));
2276 return false; /* keep compiler quiet */
2277 }
2278}
2279
2280/*
2281 * is_safe_append_member
2282 * Check a subquery that is a leaf of a UNION ALL appendrel to see if it's
2283 * safe to pull up.
2284 */
2285static bool
2287{
2288 FromExpr *jtnode;
2289
2290 /*
2291 * It's only safe to pull up the child if its jointree contains exactly
2292 * one RTE, else the AppendRelInfo data structure breaks. The one base RTE
2293 * could be buried in several levels of FromExpr, however. Also, if the
2294 * child's jointree is completely empty, we can pull up because
2295 * pull_up_simple_subquery will insert a single RTE_RESULT RTE instead.
2296 *
2297 * Also, the child can't have any WHERE quals because there's no place to
2298 * put them in an appendrel. (This is a bit annoying...) If we didn't
2299 * need to check this, we'd just test whether get_relids_in_jointree()
2300 * yields a singleton set, to be more consistent with the coding of
2301 * fix_append_rel_relids().
2302 */
2303 jtnode = subquery->jointree;
2304 Assert(IsA(jtnode, FromExpr));
2305 /* Check the completely-empty case */
2306 if (jtnode->fromlist == NIL && jtnode->quals == NULL)
2307 return true;
2308 /* Check the more general case */
2309 while (IsA(jtnode, FromExpr))
2310 {
2311 if (jtnode->quals != NULL)
2312 return false;
2313 if (list_length(jtnode->fromlist) != 1)
2314 return false;
2315 jtnode = linitial(jtnode->fromlist);
2316 }
2317 if (!IsA(jtnode, RangeTblRef))
2318 return false;
2319
2320 return true;
2321}
2322
2323/*
2324 * jointree_contains_lateral_outer_refs
2325 * Check for disallowed lateral references in a jointree's quals
2326 *
2327 * If restricted is false, all level-1 Vars are allowed (but we still must
2328 * search the jointree, since it might contain outer joins below which there
2329 * will be restrictions). If restricted is true, return true when any qual
2330 * in the jointree contains level-1 Vars coming from outside the rels listed
2331 * in safe_upper_varnos.
2332 */
2333static bool
2335 bool restricted,
2336 Relids safe_upper_varnos)
2337{
2338 if (jtnode == NULL)
2339 return false;
2340 if (IsA(jtnode, RangeTblRef))
2341 return false;
2342 else if (IsA(jtnode, FromExpr))
2343 {
2344 FromExpr *f = (FromExpr *) jtnode;
2345 ListCell *l;
2346
2347 /* First, recurse to check child joins */
2348 foreach(l, f->fromlist)
2349 {
2351 lfirst(l),
2352 restricted,
2353 safe_upper_varnos))
2354 return true;
2355 }
2356
2357 /* Then check the top-level quals */
2358 if (restricted &&
2360 safe_upper_varnos))
2361 return true;
2362 }
2363 else if (IsA(jtnode, JoinExpr))
2364 {
2365 JoinExpr *j = (JoinExpr *) jtnode;
2366
2367 /*
2368 * If this is an outer join, we mustn't allow any upper lateral
2369 * references in or below it.
2370 */
2371 if (j->jointype != JOIN_INNER)
2372 {
2373 restricted = true;
2374 safe_upper_varnos = NULL;
2375 }
2376
2377 /* Check the child joins */
2379 j->larg,
2380 restricted,
2381 safe_upper_varnos))
2382 return true;
2384 j->rarg,
2385 restricted,
2386 safe_upper_varnos))
2387 return true;
2388
2389 /* Check the JOIN's qual clauses */
2390 if (restricted &&
2392 safe_upper_varnos))
2393 return true;
2394 }
2395 else
2396 elog(ERROR, "unrecognized node type: %d",
2397 (int) nodeTag(jtnode));
2398 return false;
2399}
2400
2401/*
2402 * Perform pullup_replace_vars everyplace it's needed in the query tree.
2403 *
2404 * Caller has already filled *rvcontext with data describing what to
2405 * substitute for Vars referencing the target subquery. In addition
2406 * we need the identity of the containing appendrel if any.
2407 */
2408static void
2410 pullup_replace_vars_context *rvcontext,
2411 AppendRelInfo *containing_appendrel)
2412{
2413 Query *parse = root->parse;
2414 ListCell *lc;
2415
2416 /*
2417 * If we are considering an appendrel child subquery (that is, a UNION ALL
2418 * member query that we're pulling up), then the only part of the upper
2419 * query that could reference the child yet is the translated_vars list of
2420 * the associated AppendRelInfo. Furthermore, we do not want to force use
2421 * of PHVs in the AppendRelInfo --- there isn't any outer join between.
2422 */
2423 if (containing_appendrel)
2424 {
2425 ReplaceWrapOption save_wrap_option = rvcontext->wrap_option;
2426
2427 rvcontext->wrap_option = REPLACE_WRAP_NONE;
2428 containing_appendrel->translated_vars = (List *)
2429 pullup_replace_vars((Node *) containing_appendrel->translated_vars,
2430 rvcontext);
2431 rvcontext->wrap_option = save_wrap_option;
2432 return;
2433 }
2434
2435 /*
2436 * Replace all of the top query's references to the subquery's outputs
2437 * with copies of the adjusted subtlist items, being careful not to
2438 * replace any of the jointree structure. (This'd be a lot cleaner if we
2439 * could use query_tree_mutator.) We have to use PHVs in the targetList,
2440 * returningList, and havingQual, since those are certainly above any
2441 * outer join. replace_vars_in_jointree tracks its location in the
2442 * jointree and uses PHVs or not appropriately.
2443 */
2444 parse->targetList = (List *)
2445 pullup_replace_vars((Node *) parse->targetList, rvcontext);
2446 parse->returningList = (List *)
2447 pullup_replace_vars((Node *) parse->returningList, rvcontext);
2448
2449 if (parse->onConflict)
2450 {
2451 parse->onConflict->onConflictSet = (List *)
2452 pullup_replace_vars((Node *) parse->onConflict->onConflictSet,
2453 rvcontext);
2454 parse->onConflict->onConflictWhere =
2455 pullup_replace_vars(parse->onConflict->onConflictWhere,
2456 rvcontext);
2457
2458 /*
2459 * We assume ON CONFLICT's arbiterElems, arbiterWhere, exclRelTlist
2460 * can't contain any references to a subquery.
2461 */
2462 }
2463 if (parse->mergeActionList)
2464 {
2465 foreach(lc, parse->mergeActionList)
2466 {
2467 MergeAction *action = lfirst(lc);
2468
2469 action->qual = pullup_replace_vars(action->qual, rvcontext);
2470 action->targetList = (List *)
2471 pullup_replace_vars((Node *) action->targetList, rvcontext);
2472 }
2473 }
2474 parse->mergeJoinCondition = pullup_replace_vars(parse->mergeJoinCondition,
2475 rvcontext);
2476 replace_vars_in_jointree((Node *) parse->jointree, rvcontext);
2477 Assert(parse->setOperations == NULL);
2478 parse->havingQual = pullup_replace_vars(parse->havingQual, rvcontext);
2479
2480 /*
2481 * Replace references in the translated_vars lists of appendrels.
2482 */
2483 foreach(lc, root->append_rel_list)
2484 {
2485 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
2486
2487 appinfo->translated_vars = (List *)
2488 pullup_replace_vars((Node *) appinfo->translated_vars, rvcontext);
2489 }
2490
2491 /*
2492 * Replace references in the joinaliasvars lists of join RTEs and the
2493 * groupexprs list of group RTE.
2494 */
2495 foreach(lc, parse->rtable)
2496 {
2497 RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(lc);
2498
2499 if (otherrte->rtekind == RTE_JOIN)
2500 otherrte->joinaliasvars = (List *)
2501 pullup_replace_vars((Node *) otherrte->joinaliasvars,
2502 rvcontext);
2503 else if (otherrte->rtekind == RTE_GROUP)
2504 otherrte->groupexprs = (List *)
2505 pullup_replace_vars((Node *) otherrte->groupexprs,
2506 rvcontext);
2507 }
2508}
2509
2510/*
2511 * Helper routine for perform_pullup_replace_vars: do pullup_replace_vars on
2512 * every expression in the jointree, without changing the jointree structure
2513 * itself. Ugly, but there's no other way...
2514 */
2515static void
2518{
2519 if (jtnode == NULL)
2520 return;
2521 if (IsA(jtnode, RangeTblRef))
2522 {
2523 /*
2524 * If the RangeTblRef refers to a LATERAL subquery (that isn't the
2525 * same subquery we're pulling up), it might contain references to the
2526 * target subquery, which we must replace. We drive this from the
2527 * jointree scan, rather than a scan of the rtable, so that we can
2528 * avoid processing no-longer-referenced RTEs.
2529 */
2530 int varno = ((RangeTblRef *) jtnode)->rtindex;
2531
2532 if (varno != context->varno) /* ignore target subquery itself */
2533 {
2534 RangeTblEntry *rte = rt_fetch(varno, context->root->parse->rtable);
2535
2536 Assert(rte != context->target_rte);
2537 if (rte->lateral)
2538 {
2539 switch (rte->rtekind)
2540 {
2541 case RTE_RELATION:
2542 /* shouldn't be marked LATERAL unless tablesample */
2543 Assert(rte->tablesample);
2546 context);
2547 break;
2548 case RTE_SUBQUERY:
2549 rte->subquery =
2551 context);
2552 break;
2553 case RTE_FUNCTION:
2554 rte->functions = (List *)
2556 context);
2557 break;
2558 case RTE_TABLEFUNC:
2559 rte->tablefunc = (TableFunc *)
2561 context);
2562 break;
2563 case RTE_VALUES:
2564 rte->values_lists = (List *)
2566 context);
2567 break;
2568 case RTE_JOIN:
2569 case RTE_CTE:
2571 case RTE_RESULT:
2572 case RTE_GROUP:
2573 /* these shouldn't be marked LATERAL */
2574 Assert(false);
2575 break;
2576 }
2577 }
2578 }
2579 }
2580 else if (IsA(jtnode, FromExpr))
2581 {
2582 FromExpr *f = (FromExpr *) jtnode;
2583 ListCell *l;
2584
2585 foreach(l, f->fromlist)
2586 replace_vars_in_jointree(lfirst(l), context);
2587 f->quals = pullup_replace_vars(f->quals, context);
2588 }
2589 else if (IsA(jtnode, JoinExpr))
2590 {
2591 JoinExpr *j = (JoinExpr *) jtnode;
2592 ReplaceWrapOption save_wrap_option = context->wrap_option;
2593
2594 replace_vars_in_jointree(j->larg, context);
2595 replace_vars_in_jointree(j->rarg, context);
2596
2597 /*
2598 * Use PHVs within the join quals of a full join for variable-free
2599 * expressions. Otherwise, we cannot identify which side of the join
2600 * a pulled-up variable-free expression came from, which can lead to
2601 * failure to make a plan at all because none of the quals appear to
2602 * be mergeable or hashable conditions.
2603 */
2604 if (j->jointype == JOIN_FULL)
2606
2607 j->quals = pullup_replace_vars(j->quals, context);
2608
2609 context->wrap_option = save_wrap_option;
2610 }
2611 else
2612 elog(ERROR, "unrecognized node type: %d",
2613 (int) nodeTag(jtnode));
2614}
2615
2616/*
2617 * Apply pullup variable replacement throughout an expression tree
2618 *
2619 * Returns a modified copy of the tree, so this can't be used where we
2620 * need to do in-place replacement.
2621 */
2622static Node *
2624{
2625 return replace_rte_variables(expr,
2626 context->varno, 0,
2628 context,
2629 context->outer_hasSubLinks);
2630}
2631
2632static Node *
2635{
2637 int varattno = var->varattno;
2638 bool need_phv;
2639 Node *newnode;
2640
2641 /* System columns are not replaced. */
2642 if (varattno < InvalidAttrNumber)
2643 return (Node *) copyObject(var);
2644
2645 /*
2646 * We need a PlaceHolderVar if the Var-to-be-replaced has nonempty
2647 * varnullingrels (unless we find below that the replacement expression is
2648 * a Var or PlaceHolderVar that we can just add the nullingrels to). We
2649 * also need one if the caller has instructed us that certain expression
2650 * replacements need to be wrapped for identification purposes.
2651 */
2652 need_phv = (var->varnullingrels != NULL) ||
2653 (rcon->wrap_option != REPLACE_WRAP_NONE);
2654
2655 /*
2656 * If PlaceHolderVars are needed, we cache the modified expressions in
2657 * rcon->rv_cache[]. This is not in hopes of any material speed gain
2658 * within this function, but to avoid generating identical PHVs with
2659 * different IDs. That would result in duplicate evaluations at runtime,
2660 * and possibly prevent optimizations that rely on recognizing different
2661 * references to the same subquery output as being equal(). So it's worth
2662 * a bit of extra effort to avoid it.
2663 *
2664 * The cached items have phlevelsup = 0 and phnullingrels = NULL; we'll
2665 * copy them and adjust those values for this reference site below.
2666 */
2667 if (need_phv &&
2668 varattno >= InvalidAttrNumber &&
2669 varattno <= list_length(rcon->targetlist) &&
2670 rcon->rv_cache[varattno] != NULL)
2671 {
2672 /* Just copy the entry and fall through to adjust phlevelsup etc */
2673 newnode = copyObject(rcon->rv_cache[varattno]);
2674 }
2675 else
2676 {
2677 /*
2678 * Generate the replacement expression. This takes care of expanding
2679 * wholerow references and dealing with non-default varreturningtype.
2680 */
2681 newnode = ReplaceVarFromTargetList(var,
2682 rcon->target_rte,
2683 rcon->targetlist,
2684 rcon->result_relation,
2686 0);
2687
2688 /* Insert PlaceHolderVar if needed */
2689 if (need_phv)
2690 {
2691 bool wrap;
2692
2693 if (rcon->wrap_option == REPLACE_WRAP_ALL)
2694 {
2695 /* Caller told us to wrap all expressions in a PlaceHolderVar */
2696 wrap = true;
2697 }
2698 else if (varattno == InvalidAttrNumber)
2699 {
2700 /*
2701 * Insert PlaceHolderVar for whole-tuple reference. Notice
2702 * that we are wrapping one PlaceHolderVar around the whole
2703 * RowExpr, rather than putting one around each element of the
2704 * row. This is because we need the expression to yield NULL,
2705 * not ROW(NULL,NULL,...) when it is forced to null by an
2706 * outer join.
2707 */
2708 wrap = true;
2709 }
2710 else if (newnode && IsA(newnode, Var) &&
2711 ((Var *) newnode)->varlevelsup == 0)
2712 {
2713 /*
2714 * Simple Vars always escape being wrapped, unless they are
2715 * lateral references to something outside the subquery being
2716 * pulled up and the referenced rel is not under the same
2717 * lowest nulling outer join.
2718 */
2719 wrap = false;
2720 if (rcon->target_rte->lateral &&
2721 !bms_is_member(((Var *) newnode)->varno, rcon->relids))
2722 {
2723 nullingrel_info *nullinfo = rcon->nullinfo;
2724 int lvarno = ((Var *) newnode)->varno;
2725
2726 Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
2727 if (!bms_is_subset(nullinfo->nullingrels[rcon->varno],
2728 nullinfo->nullingrels[lvarno]))
2729 wrap = true;
2730 }
2731 }
2732 else if (newnode && IsA(newnode, PlaceHolderVar) &&
2733 ((PlaceHolderVar *) newnode)->phlevelsup == 0)
2734 {
2735 /* The same rules apply for a PlaceHolderVar */
2736 wrap = false;
2737 if (rcon->target_rte->lateral &&
2738 !bms_is_subset(((PlaceHolderVar *) newnode)->phrels,
2739 rcon->relids))
2740 {
2741 nullingrel_info *nullinfo = rcon->nullinfo;
2742 Relids lvarnos = ((PlaceHolderVar *) newnode)->phrels;
2743 int lvarno;
2744
2745 lvarno = -1;
2746 while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0)
2747 {
2748 Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
2749 if (!bms_is_subset(nullinfo->nullingrels[rcon->varno],
2750 nullinfo->nullingrels[lvarno]))
2751 {
2752 wrap = true;
2753 break;
2754 }
2755 }
2756 }
2757 }
2758 else
2759 {
2760 /*
2761 * If the node contains Var(s) or PlaceHolderVar(s) of the
2762 * subquery being pulled up, or of rels that are under the
2763 * same lowest nulling outer join as the subquery, and does
2764 * not contain any non-strict constructs, then instead of
2765 * adding a PHV on top we can add the required nullingrels to
2766 * those Vars/PHVs. (This is fundamentally a generalization
2767 * of the above cases for bare Vars and PHVs.)
2768 *
2769 * This test is somewhat expensive, but it avoids pessimizing
2770 * the plan in cases where the nullingrels get removed again
2771 * later by outer join reduction.
2772 *
2773 * Note that we don't force wrapping of expressions containing
2774 * lateral references, so long as they also contain Vars/PHVs
2775 * of the subquery, or of rels that are under the same lowest
2776 * nulling outer join as the subquery. This is okay because
2777 * of the restriction to strict constructs: if those Vars/PHVs
2778 * have been forced to NULL by an outer join then the end
2779 * result of the expression will be NULL too, regardless of
2780 * the lateral references. So it's not necessary to force the
2781 * expression to be evaluated below the outer join. This can
2782 * be a very valuable optimization, because it may allow us to
2783 * avoid using a nested loop to pass the lateral reference
2784 * down.
2785 *
2786 * This analysis could be tighter: in particular, a non-strict
2787 * construct hidden within a lower-level PlaceHolderVar is not
2788 * reason to add another PHV. But for now it doesn't seem
2789 * worth the code to be more exact. This is also why it's
2790 * preferable to handle bare PHVs in the above branch, rather
2791 * than this branch. We also prefer to handle bare Vars in a
2792 * separate branch, as it's cheaper this way and parallels the
2793 * handling of PHVs.
2794 *
2795 * For a LATERAL subquery, we have to check the actual var
2796 * membership of the node, but if it's non-lateral then any
2797 * level-zero var must belong to the subquery.
2798 */
2799 bool contain_nullable_vars = false;
2800
2801 if (!rcon->target_rte->lateral)
2802 {
2803 if (contain_vars_of_level(newnode, 0))
2804 contain_nullable_vars = true;
2805 }
2806 else
2807 {
2808 Relids all_varnos;
2809
2810 all_varnos = pull_varnos(rcon->root, newnode);
2811 if (bms_overlap(all_varnos, rcon->relids))
2812 contain_nullable_vars = true;
2813 else
2814 {
2815 nullingrel_info *nullinfo = rcon->nullinfo;
2816 int varno;
2817
2818 varno = -1;
2819 while ((varno = bms_next_member(all_varnos, varno)) >= 0)
2820 {
2821 Assert(varno > 0 && varno <= nullinfo->rtlength);
2822 if (bms_is_subset(nullinfo->nullingrels[rcon->varno],
2823 nullinfo->nullingrels[varno]))
2824 {
2825 contain_nullable_vars = true;
2826 break;
2827 }
2828 }
2829 }
2830 }
2831
2832 if (contain_nullable_vars &&
2834 {
2835 /* No wrap needed */
2836 wrap = false;
2837 }
2838 else
2839 {
2840 /* Else wrap it in a PlaceHolderVar */
2841 wrap = true;
2842 }
2843 }
2844
2845 if (wrap)
2846 {
2847 newnode = (Node *)
2849 (Expr *) newnode,
2850 bms_make_singleton(rcon->varno));
2851
2852 /*
2853 * Cache it if possible (ie, if the attno is in range, which
2854 * it probably always should be).
2855 */
2856 if (varattno >= InvalidAttrNumber &&
2857 varattno <= list_length(rcon->targetlist))
2858 rcon->rv_cache[varattno] = copyObject(newnode);
2859 }
2860 }
2861 }
2862
2863 /* Propagate any varnullingrels into the replacement expression */
2864 if (var->varnullingrels != NULL)
2865 {
2866 if (IsA(newnode, Var))
2867 {
2868 Var *newvar = (Var *) newnode;
2869
2870 Assert(newvar->varlevelsup == 0);
2871 newvar->varnullingrels = bms_add_members(newvar->varnullingrels,
2872 var->varnullingrels);
2873 }
2874 else if (IsA(newnode, PlaceHolderVar))
2875 {
2876 PlaceHolderVar *newphv = (PlaceHolderVar *) newnode;
2877
2878 Assert(newphv->phlevelsup == 0);
2880 var->varnullingrels);
2881 }
2882 else
2883 {
2884 /*
2885 * There should be Vars/PHVs within the expression that we can
2886 * modify. Vars/PHVs of the subquery should have the full
2887 * var->varnullingrels added to them, but if there are lateral
2888 * references within the expression, those must be marked with
2889 * only the nullingrels that potentially apply to them. (This
2890 * corresponds to the fact that the expression will now be
2891 * evaluated at the join level of the Var that we are replacing:
2892 * the lateral references may have bubbled up through fewer outer
2893 * joins than the subquery's Vars have. Per the discussion above,
2894 * we'll still get the right answers.) That relid set could be
2895 * different for different lateral relations, so we have to do
2896 * this work for each one.
2897 *
2898 * (Currently, the restrictions in is_simple_subquery() mean that
2899 * at most we have to remove the lowest outer join's relid from
2900 * the nullingrels of a lateral reference. However, we might
2901 * relax those restrictions someday, so let's do this right.)
2902 */
2903 if (rcon->target_rte->lateral)
2904 {
2905 nullingrel_info *nullinfo = rcon->nullinfo;
2906 Relids lvarnos;
2907 int lvarno;
2908
2909 /*
2910 * Identify lateral varnos used within newnode. We must do
2911 * this before injecting var->varnullingrels into the tree.
2912 */
2913 lvarnos = pull_varnos(rcon->root, newnode);
2914 lvarnos = bms_del_members(lvarnos, rcon->relids);
2915 /* For each one, add relevant nullingrels if any */
2916 lvarno = -1;
2917 while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0)
2918 {
2919 Relids lnullingrels;
2920
2921 Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
2922 lnullingrels = bms_intersect(var->varnullingrels,
2923 nullinfo->nullingrels[lvarno]);
2924 if (!bms_is_empty(lnullingrels))
2925 newnode = add_nulling_relids(newnode,
2926 bms_make_singleton(lvarno),
2927 lnullingrels);
2928 }
2929 }
2930
2931 /* Finally, deal with Vars/PHVs of the subquery itself */
2932 newnode = add_nulling_relids(newnode,
2933 rcon->relids,
2934 var->varnullingrels);
2935 /* Assert we did put the varnullingrels into the expression */
2936 Assert(bms_is_subset(var->varnullingrels,
2937 pull_varnos(rcon->root, newnode)));
2938 }
2939 }
2940
2941 /* Must adjust varlevelsup if replaced Var is within a subquery */
2942 if (var->varlevelsup > 0)
2943 IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
2944
2945 return newnode;
2946}
2947
2948/*
2949 * Apply pullup variable replacement to a subquery
2950 *
2951 * This needs to be different from pullup_replace_vars() because
2952 * replace_rte_variables will think that it shouldn't increment sublevels_up
2953 * before entering the Query; so we need to call it with sublevels_up == 1.
2954 */
2955static Query *
2958{
2959 Assert(IsA(query, Query));
2960 return (Query *) replace_rte_variables((Node *) query,
2961 context->varno, 1,
2963 context,
2964 NULL);
2965}
2966
2967
2968/*
2969 * flatten_simple_union_all
2970 * Try to optimize top-level UNION ALL structure into an appendrel
2971 *
2972 * If a query's setOperations tree consists entirely of simple UNION ALL
2973 * operations, flatten it into an append relation, which we can process more
2974 * intelligently than the general setops case. Otherwise, do nothing.
2975 *
2976 * In most cases, this can succeed only for a top-level query, because for a
2977 * subquery in FROM, the parent query's invocation of pull_up_subqueries would
2978 * already have flattened the UNION via pull_up_simple_union_all. But there
2979 * are a few cases we can support here but not in that code path, for example
2980 * when the subquery also contains ORDER BY.
2981 */
2982void
2984{
2985 Query *parse = root->parse;
2986 SetOperationStmt *topop;
2987 Node *leftmostjtnode;
2988 int leftmostRTI;
2989 RangeTblEntry *leftmostRTE;
2990 int childRTI;
2991 RangeTblEntry *childRTE;
2992 RangeTblRef *rtr;
2993
2994 /* Shouldn't be called unless query has setops */
2995 topop = castNode(SetOperationStmt, parse->setOperations);
2996 Assert(topop);
2997
2998 /* Can't optimize away a recursive UNION */
2999 if (root->hasRecursion)
3000 return;
3001
3002 /*
3003 * Recursively check the tree of set operations. If not all UNION ALL
3004 * with identical column types, punt.
3005 */
3006 if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
3007 return;
3008
3009 /*
3010 * Locate the leftmost leaf query in the setops tree. The upper query's
3011 * Vars all refer to this RTE (see transformSetOperationStmt).
3012 */
3013 leftmostjtnode = topop->larg;
3014 while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
3015 leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
3016 Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
3017 leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
3018 leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
3019 Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
3020
3021 /*
3022 * Make a copy of the leftmost RTE and add it to the rtable. This copy
3023 * will represent the leftmost leaf query in its capacity as a member of
3024 * the appendrel. The original will represent the appendrel as a whole.
3025 * (We must do things this way because the upper query's Vars have to be
3026 * seen as referring to the whole appendrel.)
3027 */
3028 childRTE = copyObject(leftmostRTE);
3029 parse->rtable = lappend(parse->rtable, childRTE);
3030 childRTI = list_length(parse->rtable);
3031
3032 /* Modify the setops tree to reference the child copy */
3033 ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
3034
3035 /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
3036 leftmostRTE->inh = true;
3037
3038 /*
3039 * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
3040 * Query of a setops tree should have had an empty FromClause initially.
3041 */
3042 rtr = makeNode(RangeTblRef);
3043 rtr->rtindex = leftmostRTI;
3044 Assert(parse->jointree->fromlist == NIL);
3045 parse->jointree->fromlist = list_make1(rtr);
3046
3047 /*
3048 * Now pretend the query has no setops. We must do this before trying to
3049 * do subquery pullup, because of Assert in pull_up_simple_subquery.
3050 */
3051 parse->setOperations = NULL;
3052
3053 /*
3054 * Build AppendRelInfo information, and apply pull_up_subqueries to the
3055 * leaf queries of the UNION ALL. (We must do that now because they
3056 * weren't previously referenced by the jointree, and so were missed by
3057 * the main invocation of pull_up_subqueries.)
3058 */
3059 pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
3060}
3061
3062
3063/*
3064 * reduce_outer_joins
3065 * Attempt to reduce outer joins to plain inner joins.
3066 *
3067 * The idea here is that given a query like
3068 * SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
3069 * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
3070 * is strict. The strict operator will always return NULL, causing the outer
3071 * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
3072 * columns. Therefore, there's no need for the join to produce null-extended
3073 * rows in the first place --- which makes it a plain join not an outer join.
3074 * (This scenario may not be very likely in a query written out by hand, but
3075 * it's reasonably likely when pushing quals down into complex views.)
3076 *
3077 * More generally, an outer join can be reduced in strength if there is a
3078 * strict qual above it in the qual tree that constrains a Var from the
3079 * nullable side of the join to be non-null. (For FULL joins this applies
3080 * to each side separately.)
3081 *
3082 * Another transformation we apply here is to recognize cases like
3083 * SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.y IS NULL;
3084 * If the join clause is strict for b.y, then only null-extended rows could
3085 * pass the upper WHERE, and we can conclude that what the query is really
3086 * specifying is an anti-semijoin. We change the join type from JOIN_LEFT
3087 * to JOIN_ANTI. The IS NULL clause then becomes redundant, and must be
3088 * removed to prevent bogus selectivity calculations, but we leave it to
3089 * distribute_qual_to_rels to get rid of such clauses.
3090 *
3091 * Also, we get rid of JOIN_RIGHT cases by flipping them around to become
3092 * JOIN_LEFT. This saves some code here and in some later planner routines;
3093 * the main benefit is to reduce the number of jointypes that can appear in
3094 * SpecialJoinInfo nodes. Note that we can still generate Paths and Plans
3095 * that use JOIN_RIGHT (or JOIN_RIGHT_ANTI) by switching the inputs again.
3096 *
3097 * To ease recognition of strict qual clauses, we require this routine to be
3098 * run after expression preprocessing (i.e., qual canonicalization and JOIN
3099 * alias-var expansion).
3100 */
3101void
3103{
3106 ListCell *lc;
3107
3108 /*
3109 * To avoid doing strictness checks on more quals than necessary, we want
3110 * to stop descending the jointree as soon as there are no outer joins
3111 * below our current point. This consideration forces a two-pass process.
3112 * The first pass gathers information about which base rels appear below
3113 * each side of each join clause, and about whether there are outer
3114 * join(s) below each side of each join clause. The second pass examines
3115 * qual clauses and changes join types as it descends the tree.
3116 */
3117 state1 = reduce_outer_joins_pass1((Node *) root->parse->jointree);
3118
3119 /* planner.c shouldn't have called me if no outer joins */
3120 if (state1 == NULL || !state1->contains_outer)
3121 elog(ERROR, "so where are the outer joins?");
3122
3123 state2.inner_reduced = NULL;
3124 state2.partial_reduced = NIL;
3125
3126 reduce_outer_joins_pass2((Node *) root->parse->jointree,
3127 state1, &state2,
3128 root, NULL, NIL);
3129
3130 /*
3131 * If we successfully reduced the strength of any outer joins, we must
3132 * remove references to those joins as nulling rels. This is handled as
3133 * an additional pass, for simplicity and because we can handle all
3134 * fully-reduced joins in a single pass over the parse tree.
3135 */
3136 if (!bms_is_empty(state2.inner_reduced))
3137 {
3138 root->parse = (Query *)
3139 remove_nulling_relids((Node *) root->parse,
3140 state2.inner_reduced,
3141 NULL);
3142 /* There could be references in the append_rel_list, too */
3143 root->append_rel_list = (List *)
3144 remove_nulling_relids((Node *) root->append_rel_list,
3145 state2.inner_reduced,
3146 NULL);
3147 }
3148
3149 /*
3150 * Partially-reduced full joins have to be done one at a time, since
3151 * they'll each need a different setting of except_relids.
3152 */
3153 foreach(lc, state2.partial_reduced)
3154 {
3156 Relids full_join_relids = bms_make_singleton(statep->full_join_rti);
3157
3158 root->parse = (Query *)
3159 remove_nulling_relids((Node *) root->parse,
3160 full_join_relids,
3161 statep->unreduced_side);
3162 root->append_rel_list = (List *)
3163 remove_nulling_relids((Node *) root->append_rel_list,
3164 full_join_relids,
3165 statep->unreduced_side);
3166 }
3167}
3168
3169/*
3170 * reduce_outer_joins_pass1 - phase 1 data collection
3171 *
3172 * Returns a state node describing the given jointree node.
3173 */
3176{
3178
3181 result->relids = NULL;
3182 result->contains_outer = false;
3183 result->sub_states = NIL;
3184
3185 if (jtnode == NULL)
3186 return result;
3187 if (IsA(jtnode, RangeTblRef))
3188 {
3189 int varno = ((RangeTblRef *) jtnode)->rtindex;
3190
3191 result->relids = bms_make_singleton(varno);
3192 }
3193 else if (IsA(jtnode, FromExpr))
3194 {
3195 FromExpr *f = (FromExpr *) jtnode;
3196 ListCell *l;
3197
3198 foreach(l, f->fromlist)
3199 {
3201
3202 sub_state = reduce_outer_joins_pass1(lfirst(l));
3203 result->relids = bms_add_members(result->relids,
3204 sub_state->relids);
3205 result->contains_outer |= sub_state->contains_outer;
3206 result->sub_states = lappend(result->sub_states, sub_state);
3207 }
3208 }
3209 else if (IsA(jtnode, JoinExpr))
3210 {
3211 JoinExpr *j = (JoinExpr *) jtnode;
3213
3214 /* join's own RT index is not wanted in result->relids */
3215 if (IS_OUTER_JOIN(j->jointype))
3216 result->contains_outer = true;
3217
3218 sub_state = reduce_outer_joins_pass1(j->larg);
3219 result->relids = bms_add_members(result->relids,
3220 sub_state->relids);
3221 result->contains_outer |= sub_state->contains_outer;
3222 result->sub_states = lappend(result->sub_states, sub_state);
3223
3224 sub_state = reduce_outer_joins_pass1(j->rarg);
3225 result->relids = bms_add_members(result->relids,
3226 sub_state->relids);
3227 result->contains_outer |= sub_state->contains_outer;
3228 result->sub_states = lappend(result->sub_states, sub_state);
3229 }
3230 else
3231 elog(ERROR, "unrecognized node type: %d",
3232 (int) nodeTag(jtnode));
3233 return result;
3234}
3235
3236/*
3237 * reduce_outer_joins_pass2 - phase 2 processing
3238 *
3239 * jtnode: current jointree node
3240 * state1: state data collected by phase 1 for this node
3241 * state2: where to accumulate info about successfully-reduced joins
3242 * root: toplevel planner state
3243 * nonnullable_rels: set of base relids forced non-null by upper quals
3244 * forced_null_vars: multibitmapset of Vars forced null by upper quals
3245 *
3246 * Returns info in state2 about outer joins that were successfully simplified.
3247 * Joins that were fully reduced to inner joins are all added to
3248 * state2->inner_reduced. If a full join is reduced to a left join,
3249 * it needs its own entry in state2->partial_reduced, since that will
3250 * require custom processing to remove only the correct nullingrel markers.
3251 */
3252static void
3257 Relids nonnullable_rels,
3258 List *forced_null_vars)
3259{
3260 /*
3261 * pass 2 should never descend as far as an empty subnode or base rel,
3262 * because it's only called on subtrees marked as contains_outer.
3263 */
3264 if (jtnode == NULL)
3265 elog(ERROR, "reached empty jointree");
3266 if (IsA(jtnode, RangeTblRef))
3267 elog(ERROR, "reached base rel");
3268 else if (IsA(jtnode, FromExpr))
3269 {
3270 FromExpr *f = (FromExpr *) jtnode;
3271 ListCell *l;
3272 ListCell *s;
3273 Relids pass_nonnullable_rels;
3274 List *pass_forced_null_vars;
3275
3276 /* Scan quals to see if we can add any constraints */
3277 pass_nonnullable_rels = find_nonnullable_rels(f->quals);
3278 pass_nonnullable_rels = bms_add_members(pass_nonnullable_rels,
3279 nonnullable_rels);
3280 pass_forced_null_vars = find_forced_null_vars(f->quals);
3281 pass_forced_null_vars = mbms_add_members(pass_forced_null_vars,
3282 forced_null_vars);
3283 /* And recurse --- but only into interesting subtrees */
3285 forboth(l, f->fromlist, s, state1->sub_states)
3286 {
3287 reduce_outer_joins_pass1_state *sub_state = lfirst(s);
3288
3289 if (sub_state->contains_outer)
3290 reduce_outer_joins_pass2(lfirst(l), sub_state,
3291 state2, root,
3292 pass_nonnullable_rels,
3293 pass_forced_null_vars);
3294 }
3295 bms_free(pass_nonnullable_rels);
3296 /* can't so easily clean up var lists, unfortunately */
3297 }
3298 else if (IsA(jtnode, JoinExpr))
3299 {
3300 JoinExpr *j = (JoinExpr *) jtnode;
3301 int rtindex = j->rtindex;
3302 JoinType jointype = j->jointype;
3303 reduce_outer_joins_pass1_state *left_state = linitial(state1->sub_states);
3304 reduce_outer_joins_pass1_state *right_state = lsecond(state1->sub_states);
3305
3306 /* Can we simplify this join? */
3307 switch (jointype)
3308 {
3309 case JOIN_INNER:
3310 break;
3311 case JOIN_LEFT:
3312 if (bms_overlap(nonnullable_rels, right_state->relids))
3313 jointype = JOIN_INNER;
3314 break;
3315 case JOIN_RIGHT:
3316 if (bms_overlap(nonnullable_rels, left_state->relids))
3317 jointype = JOIN_INNER;
3318 break;
3319 case JOIN_FULL:
3320 if (bms_overlap(nonnullable_rels, left_state->relids))
3321 {
3322 if (bms_overlap(nonnullable_rels, right_state->relids))
3323 jointype = JOIN_INNER;
3324 else
3325 {
3326 jointype = JOIN_LEFT;
3327 /* Also report partial reduction in state2 */
3328 report_reduced_full_join(state2, rtindex,
3329 right_state->relids);
3330 }
3331 }
3332 else
3333 {
3334 if (bms_overlap(nonnullable_rels, right_state->relids))
3335 {
3336 jointype = JOIN_RIGHT;
3337 /* Also report partial reduction in state2 */
3338 report_reduced_full_join(state2, rtindex,
3339 left_state->relids);
3340 }
3341 }
3342 break;
3343 case JOIN_SEMI:
3344 case JOIN_ANTI:
3345
3346 /*
3347 * These could only have been introduced by pull_up_sublinks,
3348 * so there's no way that upper quals could refer to their
3349 * righthand sides, and no point in checking. We don't expect
3350 * to see JOIN_RIGHT_SEMI or JOIN_RIGHT_ANTI yet.
3351 */
3352 break;
3353 default:
3354 elog(ERROR, "unrecognized join type: %d",
3355 (int) jointype);
3356 break;
3357 }
3358
3359 /*
3360 * Convert JOIN_RIGHT to JOIN_LEFT. Note that in the case where we
3361 * reduced JOIN_FULL to JOIN_RIGHT, this will mean the JoinExpr no
3362 * longer matches the internal ordering of any CoalesceExpr's built to
3363 * represent merged join variables. We don't care about that at
3364 * present, but be wary of it ...
3365 */
3366 if (jointype == JOIN_RIGHT)
3367 {
3368 Node *tmparg;
3369
3370 tmparg = j->larg;
3371 j->larg = j->rarg;
3372 j->rarg = tmparg;
3373 jointype = JOIN_LEFT;
3374 right_state = linitial(state1->sub_states);
3375 left_state = lsecond(state1->sub_states);
3376 }
3377
3378 /*
3379 * See if we can reduce JOIN_LEFT to JOIN_ANTI. This is the case if
3380 * the join's own quals are strict for any var that was forced null by
3381 * higher qual levels. NOTE: there are other ways that we could
3382 * detect an anti-join, in particular if we were to check whether Vars
3383 * coming from the RHS must be non-null because of table constraints.
3384 * That seems complicated and expensive though (in particular, one
3385 * would have to be wary of lower outer joins). For the moment this
3386 * seems sufficient.
3387 */
3388 if (jointype == JOIN_LEFT)
3389 {
3390 List *nonnullable_vars;
3391 Bitmapset *overlap;
3392
3393 /* Find Vars in j->quals that must be non-null in joined rows */
3394 nonnullable_vars = find_nonnullable_vars(j->quals);
3395
3396 /*
3397 * It's not sufficient to check whether nonnullable_vars and
3398 * forced_null_vars overlap: we need to know if the overlap
3399 * includes any RHS variables.
3400 */
3401 overlap = mbms_overlap_sets(nonnullable_vars, forced_null_vars);
3402 if (bms_overlap(overlap, right_state->relids))
3403 jointype = JOIN_ANTI;
3404 }
3405
3406 /*
3407 * Apply the jointype change, if any, to both jointree node and RTE.
3408 * Also, if we changed an RTE to INNER, add its RTI to inner_reduced.
3409 */
3410 if (rtindex && jointype != j->jointype)
3411 {
3412 RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
3413
3414 Assert(rte->rtekind == RTE_JOIN);
3415 Assert(rte->jointype == j->jointype);
3416 rte->jointype = jointype;
3417 if (jointype == JOIN_INNER)
3418 state2->inner_reduced = bms_add_member(state2->inner_reduced,
3419 rtindex);
3420 }
3421 j->jointype = jointype;
3422
3423 /* Only recurse if there's more to do below here */
3424 if (left_state->contains_outer || right_state->contains_outer)
3425 {
3426 Relids local_nonnullable_rels;
3427 List *local_forced_null_vars;
3428 Relids pass_nonnullable_rels;
3429 List *pass_forced_null_vars;
3430
3431 /*
3432 * If this join is (now) inner, we can add any constraints its
3433 * quals provide to those we got from above. But if it is outer,
3434 * we can pass down the local constraints only into the nullable
3435 * side, because an outer join never eliminates any rows from its
3436 * non-nullable side. Also, there is no point in passing upper
3437 * constraints into the nullable side, since if there were any
3438 * we'd have been able to reduce the join. (In the case of upper
3439 * forced-null constraints, we *must not* pass them into the
3440 * nullable side --- they either applied here, or not.) The upshot
3441 * is that we pass either the local or the upper constraints,
3442 * never both, to the children of an outer join.
3443 *
3444 * Note that a SEMI join works like an inner join here: it's okay
3445 * to pass down both local and upper constraints. (There can't be
3446 * any upper constraints affecting its inner side, but it's not
3447 * worth having a separate code path to avoid passing them.)
3448 *
3449 * At a FULL join we just punt and pass nothing down --- is it
3450 * possible to be smarter?
3451 */
3452 if (jointype != JOIN_FULL)
3453 {
3454 local_nonnullable_rels = find_nonnullable_rels(j->quals);
3455 local_forced_null_vars = find_forced_null_vars(j->quals);
3456 if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
3457 {
3458 /* OK to merge upper and local constraints */
3459 local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
3460 nonnullable_rels);
3461 local_forced_null_vars = mbms_add_members(local_forced_null_vars,
3462 forced_null_vars);
3463 }
3464 }
3465 else
3466 {
3467 /* no use in calculating these */
3468 local_nonnullable_rels = NULL;
3469 local_forced_null_vars = NIL;
3470 }
3471
3472 if (left_state->contains_outer)
3473 {
3474 if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
3475 {
3476 /* pass union of local and upper constraints */
3477 pass_nonnullable_rels = local_nonnullable_rels;
3478 pass_forced_null_vars = local_forced_null_vars;
3479 }
3480 else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
3481 {
3482 /* can't pass local constraints to non-nullable side */
3483 pass_nonnullable_rels = nonnullable_rels;
3484 pass_forced_null_vars = forced_null_vars;
3485 }
3486 else
3487 {
3488 /* no constraints pass through JOIN_FULL */
3489 pass_nonnullable_rels = NULL;
3490 pass_forced_null_vars = NIL;
3491 }
3492 reduce_outer_joins_pass2(j->larg, left_state,
3493 state2, root,
3494 pass_nonnullable_rels,
3495 pass_forced_null_vars);
3496 }
3497
3498 if (right_state->contains_outer)
3499 {
3500 if (jointype != JOIN_FULL) /* ie, INNER/LEFT/SEMI/ANTI */
3501 {
3502 /* pass appropriate constraints, per comment above */
3503 pass_nonnullable_rels = local_nonnullable_rels;
3504 pass_forced_null_vars = local_forced_null_vars;
3505 }
3506 else
3507 {
3508 /* no constraints pass through JOIN_FULL */
3509 pass_nonnullable_rels = NULL;
3510 pass_forced_null_vars = NIL;
3511 }
3512 reduce_outer_joins_pass2(j->rarg, right_state,
3513 state2, root,
3514 pass_nonnullable_rels,
3515 pass_forced_null_vars);
3516 }
3517 bms_free(local_nonnullable_rels);
3518 }
3519 }
3520 else
3521 elog(ERROR, "unrecognized node type: %d",
3522 (int) nodeTag(jtnode));
3523}
3524
3525/* Helper for reduce_outer_joins_pass2 */
3526static void
3528 int rtindex, Relids relids)
3529{
3531
3532 statep = palloc(sizeof(reduce_outer_joins_partial_state));
3533 statep->full_join_rti = rtindex;
3534 statep->unreduced_side = relids;
3535 state2->partial_reduced = lappend(state2->partial_reduced, statep);
3536}
3537
3538
3539/*
3540 * remove_useless_result_rtes
3541 * Attempt to remove RTE_RESULT RTEs from the join tree.
3542 * Also, elide single-child FromExprs where possible.
3543 *
3544 * We can remove RTE_RESULT entries from the join tree using the knowledge
3545 * that RTE_RESULT returns exactly one row and has no output columns. Hence,
3546 * if one is inner-joined to anything else, we can delete it. Optimizations
3547 * are also possible for some outer-join cases, as detailed below.
3548 *
3549 * This pass also replaces single-child FromExprs with their child node
3550 * where possible. It's appropriate to do that here and not earlier because
3551 * RTE_RESULT removal might reduce a multiple-child FromExpr to have only one
3552 * child. We can remove such a FromExpr if its quals are empty, or if it's
3553 * semantically valid to merge the quals into those of the parent node.
3554 * While removing unnecessary join tree nodes has some micro-efficiency value,
3555 * the real reason to do this is to eliminate cases where the nullable side of
3556 * an outer join node is a FromExpr whose single child is another outer join.
3557 * To correctly determine whether the two outer joins can commute,
3558 * deconstruct_jointree() must treat any quals of such a FromExpr as being
3559 * degenerate quals of the upper outer join. The best way to do that is to
3560 * make them actually *be* quals of the upper join, by dropping the FromExpr
3561 * and hoisting the quals up into the upper join's quals. (Note that there is
3562 * no hazard when the intermediate FromExpr has multiple children, since then
3563 * it represents an inner join that cannot commute with the upper outer join.)
3564 * As long as we have to do that, we might as well elide such FromExprs
3565 * everywhere.
3566 *
3567 * Some of these optimizations depend on recognizing empty (constant-true)
3568 * quals for FromExprs and JoinExprs. That makes it useful to apply this
3569 * optimization pass after expression preprocessing, since that will have
3570 * eliminated constant-true quals, allowing more cases to be recognized as
3571 * optimizable. What's more, the usual reason for an RTE_RESULT to be present
3572 * is that we pulled up a subquery or VALUES clause, thus very possibly
3573 * replacing Vars with constants, making it more likely that a qual can be
3574 * reduced to constant true. Also, because some optimizations depend on
3575 * the outer-join type, it's best to have done reduce_outer_joins() first.
3576 *
3577 * A PlaceHolderVar referencing an RTE_RESULT RTE poses an obstacle to this
3578 * process: we must remove the RTE_RESULT's relid from the PHV's phrels, but
3579 * we must not reduce the phrels set to empty. If that would happen, and
3580 * the RTE_RESULT is an immediate child of an outer join, we have to give up
3581 * and not remove the RTE_RESULT: there is noplace else to evaluate the
3582 * PlaceHolderVar. (That is, in such cases the RTE_RESULT *does* have output
3583 * columns.) But if the RTE_RESULT is an immediate child of an inner join,
3584 * we can usually change the PlaceHolderVar's phrels so as to evaluate it at
3585 * the inner join instead. This is OK because we really only care that PHVs
3586 * are evaluated above or below the correct outer joins. We can't, however,
3587 * postpone the evaluation of a PHV to above where it is used; so there are
3588 * some checks below on whether output PHVs are laterally referenced in the
3589 * other join input rel(s).
3590 *
3591 * We used to try to do this work as part of pull_up_subqueries() where the
3592 * potentially-optimizable cases get introduced; but it's way simpler, and
3593 * more effective, to do it separately.
3594 */
3595void
3597{
3598 Relids dropped_outer_joins = NULL;
3599 ListCell *cell;
3600
3601 /* Top level of jointree must always be a FromExpr */
3602 Assert(IsA(root->parse->jointree, FromExpr));
3603 /* Recurse ... */
3604 root->parse->jointree = (FromExpr *)
3606 (Node *) root->parse->jointree,
3607 NULL,
3608 &dropped_outer_joins);
3609 /* We should still have a FromExpr */
3610 Assert(IsA(root->parse->jointree, FromExpr));
3611
3612 /*
3613 * If we removed any outer-join nodes from the jointree, run around and
3614 * remove references to those joins as nulling rels. (There could be such
3615 * references in PHVs that we pulled up out of the original subquery that
3616 * the RESULT rel replaced. This is kosher on the grounds that we now
3617 * know that such an outer join wouldn't really have nulled anything.) We
3618 * don't do this during the main recursion, for simplicity and because we
3619 * can handle all such joins in a single pass over the parse tree.
3620 */
3621 if (!bms_is_empty(dropped_outer_joins))
3622 {
3623 root->parse = (Query *)
3624 remove_nulling_relids((Node *) root->parse,
3625 dropped_outer_joins,
3626 NULL);
3627 /* There could be references in the append_rel_list, too */
3628 root->append_rel_list = (List *)
3629 remove_nulling_relids((Node *) root->append_rel_list,
3630 dropped_outer_joins,
3631 NULL);
3632 }
3633
3634 /*
3635 * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
3636 * must do that for any RTE_RESULT that we just removed. But one for a
3637 * RTE that we did not remove can be dropped anyway: since the RTE has
3638 * only one possible output row, there is no need for EPQ to mark and
3639 * restore that row.
3640 *
3641 * It's necessary, not optional, to remove the PlanRowMark for a surviving
3642 * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
3643 * RTE_RESULT, which the executor has no support for.
3644 */
3645 foreach(cell, root->rowMarks)
3646 {
3647 PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3648
3649 if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
3650 root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3651 }
3652}
3653
3654/*
3655 * remove_useless_results_recurse
3656 * Recursive guts of remove_useless_result_rtes.
3657 *
3658 * This recursively processes the jointree and returns a modified jointree.
3659 * In addition, the RT indexes of any removed outer-join nodes are added to
3660 * *dropped_outer_joins.
3661 *
3662 * jtnode is the current jointree node. If it could be valid to merge
3663 * its quals into those of the parent node, parent_quals should point to
3664 * the parent's quals list; otherwise, pass NULL for parent_quals.
3665 * (Note that in some cases, parent_quals points to the quals of a parent
3666 * more than one level up in the tree.)
3667 */
3668static Node *
3670 Node **parent_quals,
3671 Relids *dropped_outer_joins)
3672{
3673 Assert(jtnode != NULL);
3674 if (IsA(jtnode, RangeTblRef))
3675 {
3676 /* Can't immediately do anything with a RangeTblRef */
3677 }
3678 else if (IsA(jtnode, FromExpr))
3679 {
3680 FromExpr *f = (FromExpr *) jtnode;
3681 Relids result_relids = NULL;
3682 ListCell *cell;
3683
3684 /*
3685 * We can drop RTE_RESULT rels from the fromlist so long as at least
3686 * one child remains, since joining to a one-row table changes
3687 * nothing. (But we can't drop a RTE_RESULT that computes PHV(s) that
3688 * are needed by some sibling. The cleanup transformation below would
3689 * reassign the PHVs to be computed at the join, which is too late for
3690 * the sibling's use.) The easiest way to mechanize this rule is to
3691 * modify the list in-place.
3692 */
3693 foreach(cell, f->fromlist)
3694 {
3695 Node *child = (Node *) lfirst(cell);
3696 int varno;
3697
3698 /* Recursively transform child, allowing it to push up quals ... */
3699 child = remove_useless_results_recurse(root, child,
3700 &f->quals,
3701 dropped_outer_joins);
3702 /* ... and stick it back into the tree */
3703 lfirst(cell) = child;
3704
3705 /*
3706 * If it's an RTE_RESULT with at least one sibling, and no sibling
3707 * references dependent PHVs, we can drop it. We don't yet know
3708 * what the inner join's final relid set will be, so postpone
3709 * cleanup of PHVs etc till after this loop.
3710 */
3711 if (list_length(f->fromlist) > 1 &&
3712 (varno = get_result_relid(root, child)) != 0 &&
3714 {
3715 f->fromlist = foreach_delete_current(f->fromlist, cell);
3716 result_relids = bms_add_member(result_relids, varno);
3717 }
3718 }
3719
3720 /*
3721 * Clean up if we dropped any RTE_RESULT RTEs. This is a bit
3722 * inefficient if there's more than one, but it seems better to
3723 * optimize the support code for the single-relid case.
3724 */
3725 if (result_relids)
3726 {
3727 int varno = -1;
3728
3729 while ((varno = bms_next_member(result_relids, varno)) >= 0)
3730 remove_result_refs(root, varno, (Node *) f);
3731 }
3732
3733 /*
3734 * If the FromExpr now has only one child, see if we can elide it.
3735 * This is always valid if there are no quals, except at the top of
3736 * the jointree (since Query.jointree is required to point to a
3737 * FromExpr). Otherwise, we can do it if we can push the quals up to
3738 * the parent node.
3739 *
3740 * Note: while it would not be terribly hard to generalize this
3741 * transformation to merge multi-child FromExprs into their parent
3742 * FromExpr, that risks making the parent join too expensive to plan.
3743 * We leave it to later processing to decide heuristically whether
3744 * that's a good idea. Pulling up a single child is always OK,
3745 * however.
3746 */
3747 if (list_length(f->fromlist) == 1 &&
3748 f != root->parse->jointree &&
3749 (f->quals == NULL || parent_quals != NULL))
3750 {
3751 /*
3752 * Merge any quals up to parent. They should be in implicit-AND
3753 * format by now, so we just need to concatenate lists. Put the
3754 * child quals at the front, on the grounds that they should
3755 * nominally be evaluated earlier.
3756 */
3757 if (f->quals != NULL)
3758 *parent_quals = (Node *)
3760 castNode(List, *parent_quals));
3761 return (Node *) linitial(f->fromlist);
3762 }
3763 }
3764 else if (IsA(jtnode, JoinExpr))
3765 {
3766 JoinExpr *j = (JoinExpr *) jtnode;
3767 int varno;
3768
3769 /*
3770 * First, recurse. We can absorb pushed-up FromExpr quals from either
3771 * child into this node if the jointype is INNER, since then this is
3772 * equivalent to a FromExpr. When the jointype is LEFT, we can absorb
3773 * quals from the RHS child into the current node, as they're
3774 * essentially degenerate quals of the outer join. Moreover, if we've
3775 * been passed down a parent_quals pointer then we can allow quals of
3776 * the LHS child to be absorbed into the parent. (This is important
3777 * to ensure we remove single-child FromExprs immediately below
3778 * commutable left joins.) For other jointypes, we can't move child
3779 * quals up, or at least there's no particular reason to.
3780 */
3781 j->larg = remove_useless_results_recurse(root, j->larg,
3782 (j->jointype == JOIN_INNER) ?
3783 &j->quals :
3784 (j->jointype == JOIN_LEFT) ?
3785 parent_quals : NULL,
3786 dropped_outer_joins);
3787 j->rarg = remove_useless_results_recurse(root, j->rarg,
3788 (j->jointype == JOIN_INNER ||
3789 j->jointype == JOIN_LEFT) ?
3790 &j->quals : NULL,
3791 dropped_outer_joins);
3792
3793 /* Apply join-type-specific optimization rules */
3794 switch (j->jointype)
3795 {
3796 case JOIN_INNER:
3797
3798 /*
3799 * An inner join is equivalent to a FromExpr, so if either
3800 * side was simplified to an RTE_RESULT rel, we can replace
3801 * the join with a FromExpr with just the other side.
3802 * Furthermore, we can elide that FromExpr according to the
3803 * same rules as above.
3804 *
3805 * Just as in the FromExpr case, we can't simplify if the
3806 * other input rel references any PHVs that are marked as to
3807 * be evaluated at the RTE_RESULT rel, because we can't
3808 * postpone their evaluation in that case. But we only have
3809 * to check this in cases where it's syntactically legal for
3810 * the other input to have a LATERAL reference to the
3811 * RTE_RESULT rel. Only RHSes of inner and left joins are
3812 * allowed to have such refs.
3813 */
3814 if ((varno = get_result_relid(root, j->larg)) != 0 &&
3815 !find_dependent_phvs_in_jointree(root, j->rarg, varno))
3816 {
3817 remove_result_refs(root, varno, j->rarg);
3818 if (j->quals != NULL && parent_quals == NULL)
3819 jtnode = (Node *)
3820 makeFromExpr(list_make1(j->rarg), j->quals);
3821 else
3822 {
3823 /* Merge any quals up to parent */
3824 if (j->quals != NULL)
3825 *parent_quals = (Node *)
3826 list_concat(castNode(List, j->quals),
3827 castNode(List, *parent_quals));
3828 jtnode = j->rarg;
3829 }
3830 }
3831 else if ((varno = get_result_relid(root, j->rarg)) != 0)
3832 {
3833 remove_result_refs(root, varno, j->larg);
3834 if (j->quals != NULL && parent_quals == NULL)
3835 jtnode = (Node *)
3836 makeFromExpr(list_make1(j->larg), j->quals);
3837 else
3838 {
3839 /* Merge any quals up to parent */
3840 if (j->quals != NULL)
3841 *parent_quals = (Node *)
3842 list_concat(castNode(List, j->quals),
3843 castNode(List, *parent_quals));
3844 jtnode = j->larg;
3845 }
3846 }
3847 break;
3848 case JOIN_LEFT:
3849
3850 /*
3851 * We can simplify this case if the RHS is an RTE_RESULT, with
3852 * two different possibilities:
3853 *
3854 * If the qual is empty (JOIN ON TRUE), then the join can be
3855 * strength-reduced to a plain inner join, since each LHS row
3856 * necessarily has exactly one join partner. So we can always
3857 * discard the RHS, much as in the JOIN_INNER case above.
3858 * (Again, the LHS could not contain a lateral reference to
3859 * the RHS.)
3860 *
3861 * Otherwise, it's still true that each LHS row should be
3862 * returned exactly once, and since the RHS returns no columns
3863 * (unless there are PHVs that have to be evaluated there), we
3864 * don't much care if it's null-extended or not. So in this
3865 * case also, we can just ignore the qual and discard the left
3866 * join.
3867 */
3868 if ((varno = get_result_relid(root, j->rarg)) != 0 &&
3869 (j->quals == NULL ||
3870 !find_dependent_phvs(root, varno)))
3871 {
3872 remove_result_refs(root, varno, j->larg);
3873 *dropped_outer_joins = bms_add_member(*dropped_outer_joins,
3874 j->rtindex);
3875 jtnode = j->larg;
3876 }
3877 break;
3878 case JOIN_SEMI:
3879
3880 /*
3881 * We may simplify this case if the RHS is an RTE_RESULT; the
3882 * join qual becomes effectively just a filter qual for the
3883 * LHS, since we should either return the LHS row or not. The
3884 * filter clause must go into a new FromExpr if we can't push
3885 * it up to the parent.
3886 *
3887 * There is a fine point about PHVs that are supposed to be
3888 * evaluated at the RHS. Such PHVs could only appear in the
3889 * semijoin's qual, since the rest of the query cannot
3890 * reference any outputs of the semijoin's RHS. Therefore,
3891 * they can't actually go to null before being examined, and
3892 * it'd be OK to just remove the PHV wrapping. We don't have
3893 * infrastructure for that, but remove_result_refs() will
3894 * relabel them as to be evaluated at the LHS, which is fine.
3895 *
3896 * Also, we don't need to worry about removing traces of the
3897 * join's rtindex, since it hasn't got one.
3898 */
3899 if ((varno = get_result_relid(root, j->rarg)) != 0)
3900 {
3901 Assert(j->rtindex == 0);
3902 remove_result_refs(root, varno, j->larg);
3903 if (j->quals != NULL && parent_quals == NULL)
3904 jtnode = (Node *)
3905 makeFromExpr(list_make1(j->larg), j->quals);
3906 else
3907 {
3908 /* Merge any quals up to parent */
3909 if (j->quals != NULL)
3910 *parent_quals = (Node *)
3911 list_concat(castNode(List, j->quals),
3912 castNode(List, *parent_quals));
3913 jtnode = j->larg;
3914 }
3915 }
3916 break;
3917 case JOIN_FULL:
3918 case JOIN_ANTI:
3919 /* We have no special smarts for these cases */
3920 break;
3921 default:
3922 /* Note: JOIN_RIGHT should be gone at this point */
3923 elog(ERROR, "unrecognized join type: %d",
3924 (int) j->jointype);
3925 break;
3926 }
3927 }
3928 else
3929 elog(ERROR, "unrecognized node type: %d",
3930 (int) nodeTag(jtnode));
3931 return jtnode;
3932}
3933
3934/*
3935 * get_result_relid
3936 * If jtnode is a RangeTblRef for an RTE_RESULT RTE, return its relid;
3937 * otherwise return 0.
3938 */
3939static int
3941{
3942 int varno;
3943
3944 if (!IsA(jtnode, RangeTblRef))
3945 return 0;
3946 varno = ((RangeTblRef *) jtnode)->rtindex;
3947 if (rt_fetch(varno, root->parse->rtable)->rtekind != RTE_RESULT)
3948 return 0;
3949 return varno;
3950}
3951
3952/*
3953 * remove_result_refs
3954 * Helper routine for dropping an unneeded RTE_RESULT RTE.
3955 *
3956 * This doesn't physically remove the RTE from the jointree, because that's
3957 * more easily handled in remove_useless_results_recurse. What it does do
3958 * is the necessary cleanup in the rest of the tree: we must adjust any PHVs
3959 * that may reference the RTE. Be sure to call this at a point where the
3960 * jointree is valid (no disconnected nodes).
3961 *
3962 * Note that we don't need to process the append_rel_list, since RTEs
3963 * referenced directly in the jointree won't be appendrel members.
3964 *
3965 * varno is the RTE_RESULT's relid.
3966 * newjtloc is the jointree location at which any PHVs referencing the
3967 * RTE_RESULT should be evaluated instead.
3968 */
3969static void
3971{
3972 /* Fix up PlaceHolderVars as needed */
3973 /* If there are no PHVs anywhere, we can skip this bit */
3974 if (root->glob->lastPHId != 0)
3975 {
3976 Relids subrelids;
3977
3978 subrelids = get_relids_in_jointree(newjtloc, true, false);
3979 Assert(!bms_is_empty(subrelids));
3980 substitute_phv_relids((Node *) root->parse, varno, subrelids);
3981 fix_append_rel_relids(root, varno, subrelids);
3982 }
3983
3984 /*
3985 * We also need to remove any PlanRowMark referencing the RTE, but we
3986 * postpone that work until we return to remove_useless_result_rtes.
3987 */
3988}
3989
3990
3991/*
3992 * find_dependent_phvs - are there any PlaceHolderVars whose relids are
3993 * exactly the given varno?
3994 *
3995 * find_dependent_phvs should be used when we want to see if there are
3996 * any such PHVs anywhere in the Query. Another use-case is to see if
3997 * a subtree of the join tree contains such PHVs; but for that, we have
3998 * to look not only at the join tree nodes themselves but at the
3999 * referenced RTEs. For that, use find_dependent_phvs_in_jointree.
4000 */
4001
4002typedef struct
4003{
4007
4008static bool
4011{
4012 if (node == NULL)
4013 return false;
4014 if (IsA(node, PlaceHolderVar))
4015 {
4016 PlaceHolderVar *phv = (PlaceHolderVar *) node;
4017
4018 if (phv->phlevelsup == context->sublevels_up &&
4019 bms_equal(context->relids, phv->phrels))
4020 return true;
4021 /* fall through to examine children */
4022 }
4023 if (IsA(node, Query))
4024 {
4025 /* Recurse into subselects */
4026 bool result;
4027
4028 context->sublevels_up++;
4029 result = query_tree_walker((Query *) node,
4031 context, 0);
4032 context->sublevels_up--;
4033 return result;
4034 }
4035 /* Shouldn't need to handle most planner auxiliary nodes here */
4036 Assert(!IsA(node, SpecialJoinInfo));
4037 Assert(!IsA(node, PlaceHolderInfo));
4038 Assert(!IsA(node, MinMaxAggInfo));
4039
4041}
4042
4043static bool
4045{
4047
4048 /* If there are no PHVs anywhere, we needn't work hard */
4049 if (root->glob->lastPHId == 0)
4050 return false;
4051
4052 context.relids = bms_make_singleton(varno);
4053 context.sublevels_up = 0;
4054
4055 if (query_tree_walker(root->parse, find_dependent_phvs_walker, &context, 0))
4056 return true;
4057 /* The append_rel_list could be populated already, so check it too */
4058 if (expression_tree_walker((Node *) root->append_rel_list,
4060 &context))
4061 return true;
4062 return false;
4063}
4064
4065static bool
4067{
4069 Relids subrelids;
4070 int relid;
4071
4072 /* If there are no PHVs anywhere, we needn't work hard */
4073 if (root->glob->lastPHId == 0)
4074 return false;
4075
4076 context.relids = bms_make_singleton(varno);
4077 context.sublevels_up = 0;
4078
4079 /*
4080 * See if the jointree fragment itself contains references (in join quals)
4081 */
4082 if (find_dependent_phvs_walker(node, &context))
4083 return true;
4084
4085 /*
4086 * Otherwise, identify the set of referenced RTEs (we can ignore joins,
4087 * since they should be flattened already, so their join alias lists no
4088 * longer matter), and tediously check each RTE. We can ignore RTEs that
4089 * are not marked LATERAL, though, since they couldn't possibly contain
4090 * any cross-references to other RTEs.
4091 */
4092 subrelids = get_relids_in_jointree(node, false, false);
4093 relid = -1;
4094 while ((relid = bms_next_member(subrelids, relid)) >= 0)
4095 {
4096 RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
4097
4098 if (rte->lateral &&
4100 return true;
4101 }
4102
4103 return false;
4104}
4105
4106/*
4107 * substitute_phv_relids - adjust PlaceHolderVar relid sets after pulling up
4108 * a subquery or removing an RTE_RESULT jointree item
4109 *
4110 * Find any PlaceHolderVar nodes in the given tree that reference the
4111 * pulled-up relid, and change them to reference the replacement relid(s).
4112 *
4113 * NOTE: although this has the form of a walker, we cheat and modify the
4114 * nodes in-place. This should be OK since the tree was copied by
4115 * pullup_replace_vars earlier. Avoid scribbling on the original values of
4116 * the bitmapsets, though, because expression_tree_mutator doesn't copy those.
4117 */
4118
4119typedef struct
4120{
4125
4126static bool
4129{
4130 if (node == NULL)
4131 return false;
4132 if (IsA(node, PlaceHolderVar))
4133 {
4134 PlaceHolderVar *phv = (PlaceHolderVar *) node;
4135
4136 if (phv->phlevelsup == context->sublevels_up &&
4137 bms_is_member(context->varno, phv->phrels))
4138 {
4139 phv->phrels = bms_union(phv->phrels,
4140 context->subrelids);
4141 phv->phrels = bms_del_member(phv->phrels,
4142 context->varno);
4143 /* Assert we haven't broken the PHV */
4144 Assert(!bms_is_empty(phv->phrels));
4145 }
4146 /* fall through to examine children */
4147 }
4148 if (IsA(node, Query))
4149 {
4150 /* Recurse into subselects */
4151 bool result;
4152
4153 context->sublevels_up++;
4154 result = query_tree_walker((Query *) node,
4156 context, 0);
4157 context->sublevels_up--;
4158 return result;
4159 }
4160 /* Shouldn't need to handle planner auxiliary nodes here */
4161 Assert(!IsA(node, SpecialJoinInfo));
4162 Assert(!IsA(node, AppendRelInfo));
4163 Assert(!IsA(node, PlaceHolderInfo));
4164 Assert(!IsA(node, MinMaxAggInfo));
4165
4167}
4168
4169static void
4170substitute_phv_relids(Node *node, int varno, Relids subrelids)
4171{
4173
4174 context.varno = varno;
4175 context.sublevels_up = 0;
4176 context.subrelids = subrelids;
4177
4178 /*
4179 * Must be prepared to start with a Query or a bare expression tree.
4180 */
4183 &context,
4184 0);
4185}
4186
4187/*
4188 * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
4189 *
4190 * When we pull up a subquery, any AppendRelInfo references to the subquery's
4191 * RT index have to be replaced by the substituted relid (and there had better
4192 * be only one). We also need to apply substitute_phv_relids to their
4193 * translated_vars lists, since those might contain PlaceHolderVars.
4194 *
4195 * We assume we may modify the AppendRelInfo nodes in-place.
4196 */
4197static void
4199{
4200 ListCell *l;
4201 int subvarno = -1;
4202
4203 /*
4204 * We only want to extract the member relid once, but we mustn't fail
4205 * immediately if there are multiple members; it could be that none of the
4206 * AppendRelInfo nodes refer to it. So compute it on first use. Note that
4207 * bms_singleton_member will complain if set is not singleton.
4208 */
4209 foreach(l, root->append_rel_list)
4210 {
4211 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
4212
4213 /* The parent_relid shouldn't ever be a pullup target */
4214 Assert(appinfo->parent_relid != varno);
4215
4216 if (appinfo->child_relid == varno)
4217 {
4218 if (subvarno < 0)
4219 subvarno = bms_singleton_member(subrelids);
4220 appinfo->child_relid = subvarno;
4221 }
4222
4223 /* Also fix up any PHVs in its translated vars */
4224 if (root->glob->lastPHId != 0)
4226 varno, subrelids);
4227 }
4228}
4229
4230/*
4231 * get_relids_in_jointree: get set of RT indexes present in a jointree
4232 *
4233 * Base-relation relids are always included in the result.
4234 * If include_outer_joins is true, outer-join RT indexes are included.
4235 * If include_inner_joins is true, inner-join RT indexes are included.
4236 *
4237 * Note that for most purposes in the planner, outer joins are included
4238 * in standard relid sets. Setting include_inner_joins true is only
4239 * appropriate for special purposes during subquery flattening.
4240 */
4241Relids
4242get_relids_in_jointree(Node *jtnode, bool include_outer_joins,
4243 bool include_inner_joins)
4244{
4245 Relids result = NULL;
4246
4247 if (jtnode == NULL)
4248 return result;
4249 if (IsA(jtnode, RangeTblRef))
4250 {
4251 int varno = ((RangeTblRef *) jtnode)->rtindex;
4252
4253 result = bms_make_singleton(varno);
4254 }
4255 else if (IsA(jtnode, FromExpr))
4256 {
4257 FromExpr *f = (FromExpr *) jtnode;
4258 ListCell *l;
4259
4260 foreach(l, f->fromlist)
4261 {
4262 result = bms_join(result,
4264 include_outer_joins,
4265 include_inner_joins));
4266 }
4267 }
4268 else if (IsA(jtnode, JoinExpr))
4269 {
4270 JoinExpr *j = (JoinExpr *) jtnode;
4271
4272 result = get_relids_in_jointree(j->larg,
4273 include_outer_joins,
4274 include_inner_joins);
4275 result = bms_join(result,
4277 include_outer_joins,
4278 include_inner_joins));
4279 if (j->rtindex)
4280 {
4281 if (j->jointype == JOIN_INNER)
4282 {
4283 if (include_inner_joins)
4284 result = bms_add_member(result, j->rtindex);
4285 }
4286 else
4287 {
4288 if (include_outer_joins)
4289 result = bms_add_member(result, j->rtindex);
4290 }
4291 }
4292 }
4293 else
4294 elog(ERROR, "unrecognized node type: %d",
4295 (int) nodeTag(jtnode));
4296 return result;
4297}
4298
4299/*
4300 * get_relids_for_join: get set of base+OJ RT indexes making up a join
4301 */
4302Relids
4303get_relids_for_join(Query *query, int joinrelid)
4304{
4305 Node *jtnode;
4306
4307 jtnode = find_jointree_node_for_rel((Node *) query->jointree,
4308 joinrelid);
4309 if (!jtnode)
4310 elog(ERROR, "could not find join node %d", joinrelid);
4311 return get_relids_in_jointree(jtnode, true, false);
4312}
4313
4314/*
4315 * find_jointree_node_for_rel: locate jointree node for a base or join RT index
4316 *
4317 * Returns NULL if not found
4318 */
4319static Node *
4321{
4322 if (jtnode == NULL)
4323 return NULL;
4324 if (IsA(jtnode, RangeTblRef))
4325 {
4326 int varno = ((RangeTblRef *) jtnode)->rtindex;
4327
4328 if (relid == varno)
4329 return jtnode;
4330 }
4331 else if (IsA(jtnode, FromExpr))
4332 {
4333 FromExpr *f = (FromExpr *) jtnode;
4334 ListCell *l;
4335
4336 foreach(l, f->fromlist)
4337 {
4338 jtnode = find_jointree_node_for_rel(lfirst(l), relid);
4339 if (jtnode)
4340 return jtnode;
4341 }
4342 }
4343 else if (IsA(jtnode, JoinExpr))
4344 {
4345 JoinExpr *j = (JoinExpr *) jtnode;
4346
4347 if (relid == j->rtindex)
4348 return jtnode;
4349 jtnode = find_jointree_node_for_rel(j->larg, relid);
4350 if (jtnode)
4351 return jtnode;
4352 jtnode = find_jointree_node_for_rel(j->rarg, relid);
4353 if (jtnode)
4354 return jtnode;
4355 }
4356 else
4357 elog(ERROR, "unrecognized node type: %d",
4358 (int) nodeTag(jtnode));
4359 return NULL;
4360}
4361
4362/*
4363 * get_nullingrels: collect info about which outer joins null which relations
4364 *
4365 * The result struct contains, for each leaf relation used in the query,
4366 * the set of relids of outer joins that potentially null that rel.
4367 */
4368static nullingrel_info *
4370{
4372
4373 result->rtlength = list_length(parse->rtable);
4374 result->nullingrels = palloc0_array(Relids, result->rtlength + 1);
4375 get_nullingrels_recurse((Node *) parse->jointree, NULL, result);
4376 return result;
4377}
4378
4379/*
4380 * Recursive guts of get_nullingrels().
4381 *
4382 * Note: at any recursion level, the passed-down upper_nullingrels must be
4383 * treated as a constant, but it can be stored directly into *info
4384 * if we're at leaf level. Upper recursion levels do not free their mutated
4385 * copies of the nullingrels, because those are probably referenced by
4386 * at least one leaf rel.
4387 */
4388static void
4389get_nullingrels_recurse(Node *jtnode, Relids upper_nullingrels,
4390 nullingrel_info *info)
4391{
4392 if (jtnode == NULL)
4393 return;
4394 if (IsA(jtnode, RangeTblRef))
4395 {
4396 int varno = ((RangeTblRef *) jtnode)->rtindex;
4397
4398 Assert(varno > 0 && varno <= info->rtlength);
4399 info->nullingrels[varno] = upper_nullingrels;
4400 }
4401 else if (IsA(jtnode, FromExpr))
4402 {
4403 FromExpr *f = (FromExpr *) jtnode;
4404 ListCell *l;
4405
4406 foreach(l, f->fromlist)
4407 {
4408 get_nullingrels_recurse(lfirst(l), upper_nullingrels, info);
4409 }
4410 }
4411 else if (IsA(jtnode, JoinExpr))
4412 {
4413 JoinExpr *j = (JoinExpr *) jtnode;
4414 Relids local_nullingrels;
4415
4416 switch (j->jointype)
4417 {
4418 case JOIN_INNER:
4419 get_nullingrels_recurse(j->larg, upper_nullingrels, info);
4420 get_nullingrels_recurse(j->rarg, upper_nullingrels, info);
4421 break;
4422 case JOIN_LEFT:
4423 case JOIN_SEMI:
4424 case JOIN_ANTI:
4425 local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
4426 j->rtindex);
4427 get_nullingrels_recurse(j->larg, upper_nullingrels, info);
4428 get_nullingrels_recurse(j->rarg, local_nullingrels, info);
4429 break;
4430 case JOIN_FULL:
4431 local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
4432 j->rtindex);
4433 get_nullingrels_recurse(j->larg, local_nullingrels, info);
4434 get_nullingrels_recurse(j->rarg, local_nullingrels, info);
4435 break;
4436 case JOIN_RIGHT:
4437 local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
4438 j->rtindex);
4439 get_nullingrels_recurse(j->larg, local_nullingrels, info);
4440 get_nullingrels_recurse(j->rarg, upper_nullingrels, info);
4441 break;
4442 default:
4443 elog(ERROR, "unrecognized join type: %d",
4444 (int) j->jointype);
4445 break;
4446 }
4447 }
4448 else
4449 elog(ERROR, "unrecognized node type: %d",
4450 (int) nodeTag(jtnode));
4451}
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:216
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:292
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:142
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1306
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:1161
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:868
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
int bms_singleton_member(const Bitmapset *a)
Definition: bitmapset.c:672
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:917
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:251
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:582
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:1230
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:122
#define bms_is_empty(a)
Definition: bitmapset.h:118
unsigned int Index
Definition: c.h:585
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1918
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:5068
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2256
List * find_nonnullable_vars(Node *clause)
Definition: clauses.c:1709
Relids find_nonnullable_rels(Node *clause)
Definition: clauses.c:1458
bool contain_nonstrict_functions(Node *clause)
Definition: clauses.c:994
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:539
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define palloc_object(type)
Definition: fe_memutils.h:74
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:299
TypeFuncClass
Definition: funcapi.h:147
@ TYPEFUNC_SCALAR
Definition: funcapi.h:148
Assert(PointerIsAligned(start, uint64))
int j
Definition: isn.c:78
int i
Definition: isn.c:77
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
List * lappend(List *list, void *datum)
Definition: list.c:339
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
#define NoLock
Definition: lockdefs.h:34
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:438
Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)
Definition: makefuncs.c:107
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:336
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:137
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:727
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:289
Node * make_and_qual(Node *qual1, Node *qual2)
Definition: makefuncs.c:780
void * palloc0(Size size)
Definition: mcxt.c:1973
void * palloc(Size size)
Definition: mcxt.c:1943
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
List * mbms_add_members(List *a, const List *b)
Bitmapset * mbms_overlap_sets(const List *a, const List *b)
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:763
static bool is_andclause(const void *clause)
Definition: nodeFuncs.h:107
#define query_tree_walker(q, w, c, f)
Definition: nodeFuncs.h:158
#define query_or_expression_tree_walker(n, w, c, f)
Definition: nodeFuncs.h:171
#define range_table_entry_walker(r, w, c, f)
Definition: nodeFuncs.h:168
#define expression_tree_walker(n, w, c)
Definition: nodeFuncs.h:153
static bool is_notclause(const void *clause)
Definition: nodeFuncs.h:125
static Expr * get_notclausearg(const void *notclause)
Definition: nodeFuncs.h:134
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
#define copyObject(obj)
Definition: nodes.h:230
#define nodeTag(nodeptr)
Definition: nodes.h:139
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:344
@ CMD_MERGE
Definition: nodes.h:275
@ CMD_SELECT
Definition: nodes.h:271
@ CMD_NOTHING
Definition: nodes.h:278
#define makeNode(_type_)
Definition: nodes.h:161
#define castNode(_type_, nodeptr)
Definition: nodes.h:182
JoinType
Definition: nodes.h:294
@ JOIN_SEMI
Definition: nodes.h:313
@ JOIN_FULL
Definition: nodes.h:301
@ JOIN_INNER
Definition: nodes.h:299
@ JOIN_RIGHT
Definition: nodes.h:302
@ JOIN_LEFT
Definition: nodes.h:300
@ JOIN_ANTI
Definition: nodes.h:314
@ SETOP_UNION
Definition: parsenodes.h:2168
@ RTE_JOIN
Definition: parsenodes.h:1028
@ RTE_CTE
Definition: parsenodes.h:1032
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1033
@ RTE_VALUES
Definition: parsenodes.h:1031
@ RTE_SUBQUERY
Definition: parsenodes.h:1027
@ RTE_RESULT
Definition: parsenodes.h:1034
@ RTE_FUNCTION
Definition: parsenodes.h:1029
@ RTE_TABLEFUNC
Definition: parsenodes.h:1030
@ RTE_GROUP
Definition: parsenodes.h:1037
@ RTE_RELATION
Definition: parsenodes.h:1026
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
#define foreach_delete_current(lst, var_or_cell)
Definition: pg_list.h:391
#define list_make1(x1)
Definition: pg_list.h:212
#define linitial(l)
Definition: pg_list.h:178
#define lsecond(l)
Definition: pg_list.h:183
#define foreach_node(type, var, lst)
Definition: pg_list.h:496
static rewind_source * source
Definition: pg_rewind.c:89
PlaceHolderVar * make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels)
Definition: placeholder.c:54
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
static Node * pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode, JoinExpr *lowest_outer_join, AppendRelInfo *containing_appendrel)
static nullingrel_info * get_nullingrels(Query *parse)
static void remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
static Node * pull_up_constant_function(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, AppendRelInfo *containing_appendrel)
void preprocess_function_rtes(PlannerInfo *root)
Definition: prepjointree.c:914
static bool find_dependent_phvs_walker(Node *node, find_dependent_phvs_context *context)
static Node * find_jointree_node_for_rel(Node *jtnode, int relid)
static Node * pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
static void reduce_outer_joins_pass2(Node *jtnode, reduce_outer_joins_pass1_state *state1, reduce_outer_joins_pass2_state *state2, PlannerInfo *root, Relids nonnullable_rels, List *forced_null_vars)
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex, Query *setOpQuery, int childRToffset)
static bool is_simple_values(PlannerInfo *root, RangeTblEntry *rte)
static void make_setop_translation_list(Query *query, int newvarno, AppendRelInfo *appinfo)
void flatten_simple_union_all(PlannerInfo *root)
void transform_MERGE_to_join(Query *parse)
Definition: prepjointree.c:183
static void report_reduced_full_join(reduce_outer_joins_pass2_state *state2, int rtindex, Relids relids)
static void perform_pullup_replace_vars(PlannerInfo *root, pullup_replace_vars_context *rvcontext, AppendRelInfo *containing_appendrel)
struct nullingrel_info nullingrel_info
void remove_useless_result_rtes(PlannerInfo *root)
static Node * pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode, Relids *relids)
Definition: prepjointree.c:495
static void get_nullingrels_recurse(Node *jtnode, Relids upper_nullingrels, nullingrel_info *info)
ReplaceWrapOption
Definition: prepjointree.c:62
@ REPLACE_WRAP_VARFREE
Definition: prepjointree.c:65
@ REPLACE_WRAP_ALL
Definition: prepjointree.c:64
@ REPLACE_WRAP_NONE
Definition: prepjointree.c:63
static reduce_outer_joins_pass1_state * reduce_outer_joins_pass1(Node *jtnode)
static void replace_vars_in_jointree(Node *jtnode, pullup_replace_vars_context *context)
static bool is_simple_subquery(PlannerInfo *root, Query *subquery, RangeTblEntry *rte, JoinExpr *lowest_outer_join)
static void substitute_phv_relids(Node *node, int varno, Relids subrelids)
Query * expand_virtual_generated_columns(PlannerInfo *root)
Definition: prepjointree.c:969
void pull_up_sublinks(PlannerInfo *root)
Definition: prepjointree.c:468
static Node * pullup_replace_vars_callback(Var *var, replace_rte_variables_context *context)
static Node * pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, JoinExpr *lowest_outer_join, AppendRelInfo *containing_appendrel)
void replace_empty_jointree(Query *parse)
Definition: prepjointree.c:410
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
static bool substitute_phv_relids_walker(Node *node, substitute_phv_relids_context *context)
static void fix_append_rel_relids(PlannerInfo *root, int varno, Relids subrelids)
static Node * remove_useless_results_recurse(PlannerInfo *root, Node *jtnode, Node **parent_quals, Relids *dropped_outer_joins)
static Query * pullup_replace_vars_subquery(Query *query, pullup_replace_vars_context *context)
Relids get_relids_for_join(Query *query, int joinrelid)
void pull_up_subqueries(PlannerInfo *root)
Relids get_relids_in_jointree(Node *jtnode, bool include_outer_joins, bool include_inner_joins)
static int get_result_relid(PlannerInfo *root, Node *jtnode)
static Node * pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
struct reduce_outer_joins_pass1_state reduce_outer_joins_pass1_state
struct reduce_outer_joins_partial_state reduce_outer_joins_partial_state
static bool is_safe_append_member(Query *subquery)
struct pullup_replace_vars_context pullup_replace_vars_context
static Node * pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, Node **jtlink1, Relids available_rels1, Node **jtlink2, Relids available_rels2)
Definition: prepjointree.c:652
void reduce_outer_joins(PlannerInfo *root)
static bool find_dependent_phvs(PlannerInfo *root, int varno)
static bool jointree_contains_lateral_outer_refs(PlannerInfo *root, Node *jtnode, bool restricted, Relids safe_upper_varnos)
struct reduce_outer_joins_pass2_state reduce_outer_joins_pass2_state
static Node * pullup_replace_vars(Node *expr, pullup_replace_vars_context *context)
static bool is_simple_union_all(Query *subquery)
static bool find_dependent_phvs_in_jointree(PlannerInfo *root, Node *node, int varno)
@ ANY_SUBLINK
Definition: primnodes.h:1016
@ EXISTS_SUBLINK
Definition: primnodes.h:1014
#define NUM_MERGE_MATCH_KINDS
Definition: primnodes.h:2006
@ IS_NOT_NULL
Definition: primnodes.h:1957
@ MERGE_WHEN_NOT_MATCHED_BY_TARGET
Definition: primnodes.h:2003
@ MERGE_WHEN_NOT_MATCHED_BY_SOURCE
Definition: primnodes.h:2002
@ MERGE_WHEN_MATCHED
Definition: primnodes.h:2001
tree ctl root
Definition: radixtree.h:1857
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717
#define RelationGetDescr(relation)
Definition: rel.h:542
Node * build_generation_expression(Relation rel, int attrno)
void IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up, int min_sublevels_up)
Definition: rewriteManip.c:951
void ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
Definition: rewriteManip.c:793
void OffsetVarNodes(Node *node, int offset, int sublevels_up)
Definition: rewriteManip.c:476
void CombineRangeTables(List **dst_rtable, List **dst_perminfos, List *src_rtable, List *src_perminfos)
Definition: rewriteManip.c:347
Node * add_nulling_relids(Node *node, const Bitmapset *target_relids, const Bitmapset *added_relids)
Node * remove_nulling_relids(Node *node, const Bitmapset *removable_relids, const Bitmapset *except_relids)
Node * replace_rte_variables(Node *node, int target_varno, int sublevels_up, replace_rte_variables_callback callback, void *callback_arg, bool *outer_hasSubLinks)
Node * ReplaceVarFromTargetList(Var *var, RangeTblEntry *target_rte, List *targetlist, int result_relation, ReplaceVarsNoMatchOption nomatch_option, int nomatch_varno)
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
Definition: rewriteManip.c:928
@ REPLACEVARS_REPORT_ERROR
Definition: rewriteManip.h:39
void check_stack_depth(void)
Definition: stack_depth.c:95
Index child_relid
Definition: pathnodes.h:3106
List * translated_vars
Definition: pathnodes.h:3133
Index parent_relid
Definition: pathnodes.h:3105
int num_child_cols
Definition: pathnodes.h:3141
Oid parent_reltype
Definition: pathnodes.h:3114
Node * quals
Definition: primnodes.h:2338
List * fromlist
Definition: primnodes.h:2337
Node * quals
Definition: primnodes.h:2318
JoinType jointype
Definition: primnodes.h:2309
int rtindex
Definition: primnodes.h:2322
Node * larg
Definition: primnodes.h:2311
bool isNatural
Definition: primnodes.h:2310
Node * rarg
Definition: primnodes.h:2312
Definition: pg_list.h:54
Definition: nodes.h:135
NullTestType nulltesttype
Definition: primnodes.h:1964
ParseLoc location
Definition: primnodes.h:1967
Expr * arg
Definition: primnodes.h:1963
Relids phnullingrels
Definition: pathnodes.h:2927
Index phlevelsup
Definition: pathnodes.h:2933
List * minmax_aggs
Definition: pathnodes.h:502
List * processed_tlist
Definition: pathnodes.h:486
bool hasRecursion
Definition: pathnodes.h:534
List * cte_plan_ids
Definition: pathnodes.h:329
int last_rinfo_serial
Definition: pathnodes.h:367
Index qual_security_level
Definition: pathnodes.h:519
List * init_plans
Definition: pathnodes.h:323
List * multiexpr_params
Definition: pathnodes.h:332
List * row_identity_vars
Definition: pathnodes.h:392
bool ec_merging_done
Definition: pathnodes.h:341
Bitmapset * outer_params
Definition: pathnodes.h:245
Index query_level
Definition: pathnodes.h:232
List * append_rel_list
Definition: pathnodes.h:389
struct Path * non_recursive_path
Definition: pathnodes.h:562
List * placeholder_list
Definition: pathnodes.h:398
PlannerGlobal * glob
Definition: pathnodes.h:229
List * join_domains
Definition: pathnodes.h:335
List * eq_classes
Definition: pathnodes.h:338
int wt_param_id
Definition: pathnodes.h:560
List * plan_params
Definition: pathnodes.h:244
List * processed_groupClause
Definition: pathnodes.h:463
List * processed_distinctClause
Definition: pathnodes.h:475
Query * parse
Definition: pathnodes.h:226
List * rowMarks
Definition: pathnodes.h:395
List * update_colnos
Definition: pathnodes.h:494
bool placeholdersFrozen
Definition: pathnodes.h:532
List * join_info_list
Definition: pathnodes.h:364
Relids all_result_relids
Definition: pathnodes.h:378
Relids leaf_result_relids
Definition: pathnodes.h:380
List * rowMarks
Definition: parsenodes.h:228
Node * limitCount
Definition: parsenodes.h:225
FromExpr * jointree
Definition: parsenodes.h:177
Node * setOperations
Definition: parsenodes.h:230
List * cteList
Definition: parsenodes.h:168
List * groupClause
Definition: parsenodes.h:211
Node * havingQual
Definition: parsenodes.h:216
List * rtable
Definition: parsenodes.h:170
Node * limitOffset
Definition: parsenodes.h:224
CmdType commandType
Definition: parsenodes.h:121
List * targetList
Definition: parsenodes.h:193
List * groupingSets
Definition: parsenodes.h:214
List * distinctClause
Definition: parsenodes.h:220
List * sortClause
Definition: parsenodes.h:222
TableFunc * tablefunc
Definition: parsenodes.h:1198
bool funcordinality
Definition: parsenodes.h:1193
struct TableSampleClause * tablesample
Definition: parsenodes.h:1112
Query * subquery
Definition: parsenodes.h:1118
List * values_lists
Definition: parsenodes.h:1204
JoinType jointype
Definition: parsenodes.h:1165
List * functions
Definition: parsenodes.h:1191
RTEKind rtekind
Definition: parsenodes.h:1061
SetOperation op
Definition: parsenodes.h:2247
AttrNumber resno
Definition: primnodes.h:2221
bool has_generated_virtual
Definition: tupdesc.h:47
TupleConstr * constr
Definition: tupdesc.h:141
Definition: primnodes.h:262
AttrNumber varattno
Definition: primnodes.h:274
Index varlevelsup
Definition: primnodes.h:294
Relids * nullingrels
Definition: prepjointree.c:55
nullingrel_info * nullinfo
Definition: prepjointree.c:78
ReplaceWrapOption wrap_option
Definition: prepjointree.c:82
RangeTblEntry * target_rte
Definition: prepjointree.c:73
Definition: regcomp.c:282
JoinExpr * convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink, Relids available_rels)
Definition: subselect.c:1333
ScalarArrayOpExpr * convert_VALUES_to_ANY(PlannerInfo *root, Node *testexpr, Query *values)
Definition: subselect.c:1227
JoinExpr * convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink, bool under_not, Relids available_rels)
Definition: subselect.c:1450
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
Definition: tlist.c:248
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:444
Relids pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup)
Definition: var.c:140
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:114
Node * flatten_join_alias_vars(PlannerInfo *root, Query *query, Node *node)
Definition: var.c:789