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