PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
prepjointree.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * prepjointree.c
4 * Planner preprocessing for subqueries and join tree manipulation.
5 *
6 * NOTE: the intended sequence for invoking these operations is
7 * replace_empty_jointree
8 * pull_up_sublinks
9 * preprocess_function_rtes
10 * 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-2024, 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)
2440 }
2441 else if (IsA(jtnode, JoinExpr))
2442 {
2443 JoinExpr *j = (JoinExpr *) jtnode;
2444 bool save_wrap_non_vars = context->wrap_non_vars;
2445
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 */ , var->location,
2543 (var->vartype != RECORDOID),
2544 &colnames, &fields);
2545 /* Expand the generated per-field Vars, but don't insert PHVs there */
2546 rcon->wrap_non_vars = false;
2547 context->sublevels_up = 0; /* to match the expandRTE output */
2548 fields = (List *) replace_rte_variables_mutator((Node *) fields,
2549 context);
2550 rcon->wrap_non_vars = save_wrap_non_vars;
2551 context->sublevels_up = save_sublevelsup;
2552
2553 rowexpr = makeNode(RowExpr);
2554 rowexpr->args = fields;
2555 rowexpr->row_typeid = var->vartype;
2556 rowexpr->row_format = COERCE_IMPLICIT_CAST;
2557 rowexpr->colnames = (var->vartype == RECORDOID) ? colnames : NIL;
2558 rowexpr->location = var->location;
2559 newnode = (Node *) rowexpr;
2560
2561 /*
2562 * Insert PlaceHolderVar if needed. Notice that we are wrapping one
2563 * PlaceHolderVar around the whole RowExpr, rather than putting one
2564 * around each element of the row. This is because we need the
2565 * expression to yield NULL, not ROW(NULL,NULL,...) when it is forced
2566 * to null by an outer join.
2567 */
2568 if (need_phv)
2569 {
2570 newnode = (Node *)
2572 (Expr *) newnode,
2573 bms_make_singleton(rcon->varno));
2574 /* cache it with the PHV, and with phlevelsup etc not set yet */
2575 rcon->rv_cache[InvalidAttrNumber] = copyObject(newnode);
2576 }
2577 }
2578 else
2579 {
2580 /* Normal case referencing one targetlist element */
2581 TargetEntry *tle = get_tle_by_resno(rcon->targetlist, varattno);
2582
2583 if (tle == NULL) /* shouldn't happen */
2584 elog(ERROR, "could not find attribute %d in subquery targetlist",
2585 varattno);
2586
2587 /* Make a copy of the tlist item to return */
2588 newnode = (Node *) copyObject(tle->expr);
2589
2590 /* Insert PlaceHolderVar if needed */
2591 if (need_phv)
2592 {
2593 bool wrap;
2594
2595 if (newnode && IsA(newnode, Var) &&
2596 ((Var *) newnode)->varlevelsup == 0)
2597 {
2598 /*
2599 * Simple Vars always escape being wrapped, unless they are
2600 * lateral references to something outside the subquery being
2601 * pulled up and the referenced rel is not under the same
2602 * lowest nulling outer join.
2603 */
2604 wrap = false;
2605 if (rcon->target_rte->lateral &&
2606 !bms_is_member(((Var *) newnode)->varno, rcon->relids))
2607 {
2608 nullingrel_info *nullinfo = rcon->nullinfo;
2609 int lvarno = ((Var *) newnode)->varno;
2610
2611 Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
2612 if (!bms_is_subset(nullinfo->nullingrels[rcon->varno],
2613 nullinfo->nullingrels[lvarno]))
2614 wrap = true;
2615 }
2616 }
2617 else if (newnode && IsA(newnode, PlaceHolderVar) &&
2618 ((PlaceHolderVar *) newnode)->phlevelsup == 0)
2619 {
2620 /* The same rules apply for a PlaceHolderVar */
2621 wrap = false;
2622 if (rcon->target_rte->lateral &&
2623 !bms_is_subset(((PlaceHolderVar *) newnode)->phrels,
2624 rcon->relids))
2625 {
2626 nullingrel_info *nullinfo = rcon->nullinfo;
2627 Relids lvarnos = ((PlaceHolderVar *) newnode)->phrels;
2628 int lvarno;
2629
2630 lvarno = -1;
2631 while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0)
2632 {
2633 Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
2634 if (!bms_is_subset(nullinfo->nullingrels[rcon->varno],
2635 nullinfo->nullingrels[lvarno]))
2636 {
2637 wrap = true;
2638 break;
2639 }
2640 }
2641 }
2642 }
2643 else if (rcon->wrap_non_vars)
2644 {
2645 /* Caller told us to wrap all non-Vars in a PlaceHolderVar */
2646 wrap = true;
2647 }
2648 else
2649 {
2650 /*
2651 * If the node contains Var(s) or PlaceHolderVar(s) of the
2652 * subquery being pulled up, or of rels that are under the
2653 * same lowest nulling outer join as the subquery, and does
2654 * not contain any non-strict constructs, then instead of
2655 * adding a PHV on top we can add the required nullingrels to
2656 * those Vars/PHVs. (This is fundamentally a generalization
2657 * of the above cases for bare Vars and PHVs.)
2658 *
2659 * This test is somewhat expensive, but it avoids pessimizing
2660 * the plan in cases where the nullingrels get removed again
2661 * later by outer join reduction.
2662 *
2663 * Note that we don't force wrapping of expressions containing
2664 * lateral references, so long as they also contain Vars/PHVs
2665 * of the subquery, or of rels that are under the same lowest
2666 * nulling outer join as the subquery. This is okay because
2667 * of the restriction to strict constructs: if those Vars/PHVs
2668 * have been forced to NULL by an outer join then the end
2669 * result of the expression will be NULL too, regardless of
2670 * the lateral references. So it's not necessary to force the
2671 * expression to be evaluated below the outer join. This can
2672 * be a very valuable optimization, because it may allow us to
2673 * avoid using a nested loop to pass the lateral reference
2674 * down.
2675 *
2676 * This analysis could be tighter: in particular, a non-strict
2677 * construct hidden within a lower-level PlaceHolderVar is not
2678 * reason to add another PHV. But for now it doesn't seem
2679 * worth the code to be more exact.
2680 *
2681 * For a LATERAL subquery, we have to check the actual var
2682 * membership of the node, but if it's non-lateral then any
2683 * level-zero var must belong to the subquery.
2684 */
2685 bool contain_nullable_vars = false;
2686
2687 if (!rcon->target_rte->lateral)
2688 {
2689 if (contain_vars_of_level(newnode, 0))
2690 contain_nullable_vars = true;
2691 }
2692 else
2693 {
2694 Relids all_varnos;
2695
2696 all_varnos = pull_varnos(rcon->root, newnode);
2697 if (bms_overlap(all_varnos, rcon->relids))
2698 contain_nullable_vars = true;
2699 else
2700 {
2701 nullingrel_info *nullinfo = rcon->nullinfo;
2702 int varno;
2703
2704 varno = -1;
2705 while ((varno = bms_next_member(all_varnos, varno)) >= 0)
2706 {
2707 Assert(varno > 0 && varno <= nullinfo->rtlength);
2708 if (bms_is_subset(nullinfo->nullingrels[rcon->varno],
2709 nullinfo->nullingrels[varno]))
2710 {
2711 contain_nullable_vars = true;
2712 break;
2713 }
2714 }
2715 }
2716 }
2717
2718 if (contain_nullable_vars &&
2720 {
2721 /* No wrap needed */
2722 wrap = false;
2723 }
2724 else
2725 {
2726 /* Else wrap it in a PlaceHolderVar */
2727 wrap = true;
2728 }
2729 }
2730
2731 if (wrap)
2732 {
2733 newnode = (Node *)
2735 (Expr *) newnode,
2736 bms_make_singleton(rcon->varno));
2737
2738 /*
2739 * Cache it if possible (ie, if the attno is in range, which
2740 * it probably always should be).
2741 */
2742 if (varattno > InvalidAttrNumber &&
2743 varattno <= list_length(rcon->targetlist))
2744 rcon->rv_cache[varattno] = copyObject(newnode);
2745 }
2746 }
2747 }
2748
2749 /* Propagate any varnullingrels into the replacement expression */
2750 if (var->varnullingrels != NULL)
2751 {
2752 if (IsA(newnode, Var))
2753 {
2754 Var *newvar = (Var *) newnode;
2755
2756 Assert(newvar->varlevelsup == 0);
2757 newvar->varnullingrels = bms_add_members(newvar->varnullingrels,
2758 var->varnullingrels);
2759 }
2760 else if (IsA(newnode, PlaceHolderVar))
2761 {
2762 PlaceHolderVar *newphv = (PlaceHolderVar *) newnode;
2763
2764 Assert(newphv->phlevelsup == 0);
2766 var->varnullingrels);
2767 }
2768 else
2769 {
2770 /*
2771 * There should be Vars/PHVs within the expression that we can
2772 * modify. Vars/PHVs of the subquery should have the full
2773 * var->varnullingrels added to them, but if there are lateral
2774 * references within the expression, those must be marked with
2775 * only the nullingrels that potentially apply to them. (This
2776 * corresponds to the fact that the expression will now be
2777 * evaluated at the join level of the Var that we are replacing:
2778 * the lateral references may have bubbled up through fewer outer
2779 * joins than the subquery's Vars have. Per the discussion above,
2780 * we'll still get the right answers.) That relid set could be
2781 * different for different lateral relations, so we have to do
2782 * this work for each one.
2783 *
2784 * (Currently, the restrictions in is_simple_subquery() mean that
2785 * at most we have to remove the lowest outer join's relid from
2786 * the nullingrels of a lateral reference. However, we might
2787 * relax those restrictions someday, so let's do this right.)
2788 */
2789 if (rcon->target_rte->lateral)
2790 {
2791 nullingrel_info *nullinfo = rcon->nullinfo;
2792 Relids lvarnos;
2793 int lvarno;
2794
2795 /*
2796 * Identify lateral varnos used within newnode. We must do
2797 * this before injecting var->varnullingrels into the tree.
2798 */
2799 lvarnos = pull_varnos(rcon->root, newnode);
2800 lvarnos = bms_del_members(lvarnos, rcon->relids);
2801 /* For each one, add relevant nullingrels if any */
2802 lvarno = -1;
2803 while ((lvarno = bms_next_member(lvarnos, lvarno)) >= 0)
2804 {
2805 Relids lnullingrels;
2806
2807 Assert(lvarno > 0 && lvarno <= nullinfo->rtlength);
2808 lnullingrels = bms_intersect(var->varnullingrels,
2809 nullinfo->nullingrels[lvarno]);
2810 if (!bms_is_empty(lnullingrels))
2811 newnode = add_nulling_relids(newnode,
2812 bms_make_singleton(lvarno),
2813 lnullingrels);
2814 }
2815 }
2816
2817 /* Finally, deal with Vars/PHVs of the subquery itself */
2818 newnode = add_nulling_relids(newnode,
2819 rcon->relids,
2820 var->varnullingrels);
2821 /* Assert we did put the varnullingrels into the expression */
2822 Assert(bms_is_subset(var->varnullingrels,
2823 pull_varnos(rcon->root, newnode)));
2824 }
2825 }
2826
2827 /* Must adjust varlevelsup if replaced Var is within a subquery */
2828 if (var->varlevelsup > 0)
2829 IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
2830
2831 return newnode;
2832}
2833
2834/*
2835 * Apply pullup variable replacement to a subquery
2836 *
2837 * This needs to be different from pullup_replace_vars() because
2838 * replace_rte_variables will think that it shouldn't increment sublevels_up
2839 * before entering the Query; so we need to call it with sublevels_up == 1.
2840 */
2841static Query *
2844{
2845 Assert(IsA(query, Query));
2846 return (Query *) replace_rte_variables((Node *) query,
2847 context->varno, 1,
2849 context,
2850 NULL);
2851}
2852
2853
2854/*
2855 * flatten_simple_union_all
2856 * Try to optimize top-level UNION ALL structure into an appendrel
2857 *
2858 * If a query's setOperations tree consists entirely of simple UNION ALL
2859 * operations, flatten it into an append relation, which we can process more
2860 * intelligently than the general setops case. Otherwise, do nothing.
2861 *
2862 * In most cases, this can succeed only for a top-level query, because for a
2863 * subquery in FROM, the parent query's invocation of pull_up_subqueries would
2864 * already have flattened the UNION via pull_up_simple_union_all. But there
2865 * are a few cases we can support here but not in that code path, for example
2866 * when the subquery also contains ORDER BY.
2867 */
2868void
2870{
2871 Query *parse = root->parse;
2872 SetOperationStmt *topop;
2873 Node *leftmostjtnode;
2874 int leftmostRTI;
2875 RangeTblEntry *leftmostRTE;
2876 int childRTI;
2877 RangeTblEntry *childRTE;
2878 RangeTblRef *rtr;
2879
2880 /* Shouldn't be called unless query has setops */
2881 topop = castNode(SetOperationStmt, parse->setOperations);
2882 Assert(topop);
2883
2884 /* Can't optimize away a recursive UNION */
2885 if (root->hasRecursion)
2886 return;
2887
2888 /*
2889 * Recursively check the tree of set operations. If not all UNION ALL
2890 * with identical column types, punt.
2891 */
2892 if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2893 return;
2894
2895 /*
2896 * Locate the leftmost leaf query in the setops tree. The upper query's
2897 * Vars all refer to this RTE (see transformSetOperationStmt).
2898 */
2899 leftmostjtnode = topop->larg;
2900 while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2901 leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2902 Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2903 leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2904 leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2905 Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2906
2907 /*
2908 * Make a copy of the leftmost RTE and add it to the rtable. This copy
2909 * will represent the leftmost leaf query in its capacity as a member of
2910 * the appendrel. The original will represent the appendrel as a whole.
2911 * (We must do things this way because the upper query's Vars have to be
2912 * seen as referring to the whole appendrel.)
2913 */
2914 childRTE = copyObject(leftmostRTE);
2915 parse->rtable = lappend(parse->rtable, childRTE);
2916 childRTI = list_length(parse->rtable);
2917
2918 /* Modify the setops tree to reference the child copy */
2919 ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2920
2921 /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2922 leftmostRTE->inh = true;
2923
2924 /*
2925 * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2926 * Query of a setops tree should have had an empty FromClause initially.
2927 */
2928 rtr = makeNode(RangeTblRef);
2929 rtr->rtindex = leftmostRTI;
2930 Assert(parse->jointree->fromlist == NIL);
2931 parse->jointree->fromlist = list_make1(rtr);
2932
2933 /*
2934 * Now pretend the query has no setops. We must do this before trying to
2935 * do subquery pullup, because of Assert in pull_up_simple_subquery.
2936 */
2937 parse->setOperations = NULL;
2938
2939 /*
2940 * Build AppendRelInfo information, and apply pull_up_subqueries to the
2941 * leaf queries of the UNION ALL. (We must do that now because they
2942 * weren't previously referenced by the jointree, and so were missed by
2943 * the main invocation of pull_up_subqueries.)
2944 */
2945 pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2946}
2947
2948
2949/*
2950 * reduce_outer_joins
2951 * Attempt to reduce outer joins to plain inner joins.
2952 *
2953 * The idea here is that given a query like
2954 * SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
2955 * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
2956 * is strict. The strict operator will always return NULL, causing the outer
2957 * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
2958 * columns. Therefore, there's no need for the join to produce null-extended
2959 * rows in the first place --- which makes it a plain join not an outer join.
2960 * (This scenario may not be very likely in a query written out by hand, but
2961 * it's reasonably likely when pushing quals down into complex views.)
2962 *
2963 * More generally, an outer join can be reduced in strength if there is a
2964 * strict qual above it in the qual tree that constrains a Var from the
2965 * nullable side of the join to be non-null. (For FULL joins this applies
2966 * to each side separately.)
2967 *
2968 * Another transformation we apply here is to recognize cases like
2969 * SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.y IS NULL;
2970 * If the join clause is strict for b.y, then only null-extended rows could
2971 * pass the upper WHERE, and we can conclude that what the query is really
2972 * specifying is an anti-semijoin. We change the join type from JOIN_LEFT
2973 * to JOIN_ANTI. The IS NULL clause then becomes redundant, and must be
2974 * removed to prevent bogus selectivity calculations, but we leave it to
2975 * distribute_qual_to_rels to get rid of such clauses.
2976 *
2977 * Also, we get rid of JOIN_RIGHT cases by flipping them around to become
2978 * JOIN_LEFT. This saves some code here and in some later planner routines;
2979 * the main benefit is to reduce the number of jointypes that can appear in
2980 * SpecialJoinInfo nodes. Note that we can still generate Paths and Plans
2981 * that use JOIN_RIGHT (or JOIN_RIGHT_ANTI) by switching the inputs again.
2982 *
2983 * To ease recognition of strict qual clauses, we require this routine to be
2984 * run after expression preprocessing (i.e., qual canonicalization and JOIN
2985 * alias-var expansion).
2986 */
2987void
2989{
2992 ListCell *lc;
2993
2994 /*
2995 * To avoid doing strictness checks on more quals than necessary, we want
2996 * to stop descending the jointree as soon as there are no outer joins
2997 * below our current point. This consideration forces a two-pass process.
2998 * The first pass gathers information about which base rels appear below
2999 * each side of each join clause, and about whether there are outer
3000 * join(s) below each side of each join clause. The second pass examines
3001 * qual clauses and changes join types as it descends the tree.
3002 */
3003 state1 = reduce_outer_joins_pass1((Node *) root->parse->jointree);
3004
3005 /* planner.c shouldn't have called me if no outer joins */
3006 if (state1 == NULL || !state1->contains_outer)
3007 elog(ERROR, "so where are the outer joins?");
3008
3009 state2.inner_reduced = NULL;
3010 state2.partial_reduced = NIL;
3011
3012 reduce_outer_joins_pass2((Node *) root->parse->jointree,
3013 state1, &state2,
3014 root, NULL, NIL);
3015
3016 /*
3017 * If we successfully reduced the strength of any outer joins, we must
3018 * remove references to those joins as nulling rels. This is handled as
3019 * an additional pass, for simplicity and because we can handle all
3020 * fully-reduced joins in a single pass over the parse tree.
3021 */
3022 if (!bms_is_empty(state2.inner_reduced))
3023 {
3024 root->parse = (Query *)
3025 remove_nulling_relids((Node *) root->parse,
3026 state2.inner_reduced,
3027 NULL);
3028 /* There could be references in the append_rel_list, too */
3029 root->append_rel_list = (List *)
3030 remove_nulling_relids((Node *) root->append_rel_list,
3031 state2.inner_reduced,
3032 NULL);
3033 }
3034
3035 /*
3036 * Partially-reduced full joins have to be done one at a time, since
3037 * they'll each need a different setting of except_relids.
3038 */
3039 foreach(lc, state2.partial_reduced)
3040 {
3042 Relids full_join_relids = bms_make_singleton(statep->full_join_rti);
3043
3044 root->parse = (Query *)
3045 remove_nulling_relids((Node *) root->parse,
3046 full_join_relids,
3047 statep->unreduced_side);
3048 root->append_rel_list = (List *)
3049 remove_nulling_relids((Node *) root->append_rel_list,
3050 full_join_relids,
3051 statep->unreduced_side);
3052 }
3053}
3054
3055/*
3056 * reduce_outer_joins_pass1 - phase 1 data collection
3057 *
3058 * Returns a state node describing the given jointree node.
3059 */
3062{
3064
3067 result->relids = NULL;
3068 result->contains_outer = false;
3069 result->sub_states = NIL;
3070
3071 if (jtnode == NULL)
3072 return result;
3073 if (IsA(jtnode, RangeTblRef))
3074 {
3075 int varno = ((RangeTblRef *) jtnode)->rtindex;
3076
3077 result->relids = bms_make_singleton(varno);
3078 }
3079 else if (IsA(jtnode, FromExpr))
3080 {
3081 FromExpr *f = (FromExpr *) jtnode;
3082 ListCell *l;
3083
3084 foreach(l, f->fromlist)
3085 {
3087
3088 sub_state = reduce_outer_joins_pass1(lfirst(l));
3089 result->relids = bms_add_members(result->relids,
3090 sub_state->relids);
3091 result->contains_outer |= sub_state->contains_outer;
3092 result->sub_states = lappend(result->sub_states, sub_state);
3093 }
3094 }
3095 else if (IsA(jtnode, JoinExpr))
3096 {
3097 JoinExpr *j = (JoinExpr *) jtnode;
3099
3100 /* join's own RT index is not wanted in result->relids */
3101 if (IS_OUTER_JOIN(j->jointype))
3102 result->contains_outer = true;
3103
3104 sub_state = reduce_outer_joins_pass1(j->larg);
3105 result->relids = bms_add_members(result->relids,
3106 sub_state->relids);
3107 result->contains_outer |= sub_state->contains_outer;
3108 result->sub_states = lappend(result->sub_states, sub_state);
3109
3110 sub_state = reduce_outer_joins_pass1(j->rarg);
3111 result->relids = bms_add_members(result->relids,
3112 sub_state->relids);
3113 result->contains_outer |= sub_state->contains_outer;
3114 result->sub_states = lappend(result->sub_states, sub_state);
3115 }
3116 else
3117 elog(ERROR, "unrecognized node type: %d",
3118 (int) nodeTag(jtnode));
3119 return result;
3120}
3121
3122/*
3123 * reduce_outer_joins_pass2 - phase 2 processing
3124 *
3125 * jtnode: current jointree node
3126 * state1: state data collected by phase 1 for this node
3127 * state2: where to accumulate info about successfully-reduced joins
3128 * root: toplevel planner state
3129 * nonnullable_rels: set of base relids forced non-null by upper quals
3130 * forced_null_vars: multibitmapset of Vars forced null by upper quals
3131 *
3132 * Returns info in state2 about outer joins that were successfully simplified.
3133 * Joins that were fully reduced to inner joins are all added to
3134 * state2->inner_reduced. If a full join is reduced to a left join,
3135 * it needs its own entry in state2->partial_reduced, since that will
3136 * require custom processing to remove only the correct nullingrel markers.
3137 */
3138static void
3143 Relids nonnullable_rels,
3144 List *forced_null_vars)
3145{
3146 /*
3147 * pass 2 should never descend as far as an empty subnode or base rel,
3148 * because it's only called on subtrees marked as contains_outer.
3149 */
3150 if (jtnode == NULL)
3151 elog(ERROR, "reached empty jointree");
3152 if (IsA(jtnode, RangeTblRef))
3153 elog(ERROR, "reached base rel");
3154 else if (IsA(jtnode, FromExpr))
3155 {
3156 FromExpr *f = (FromExpr *) jtnode;
3157 ListCell *l;
3158 ListCell *s;
3159 Relids pass_nonnullable_rels;
3160 List *pass_forced_null_vars;
3161
3162 /* Scan quals to see if we can add any constraints */
3163 pass_nonnullable_rels = find_nonnullable_rels(f->quals);
3164 pass_nonnullable_rels = bms_add_members(pass_nonnullable_rels,
3165 nonnullable_rels);
3166 pass_forced_null_vars = find_forced_null_vars(f->quals);
3167 pass_forced_null_vars = mbms_add_members(pass_forced_null_vars,
3168 forced_null_vars);
3169 /* And recurse --- but only into interesting subtrees */
3171 forboth(l, f->fromlist, s, state1->sub_states)
3172 {
3173 reduce_outer_joins_pass1_state *sub_state = lfirst(s);
3174
3175 if (sub_state->contains_outer)
3176 reduce_outer_joins_pass2(lfirst(l), sub_state,
3177 state2, root,
3178 pass_nonnullable_rels,
3179 pass_forced_null_vars);
3180 }
3181 bms_free(pass_nonnullable_rels);
3182 /* can't so easily clean up var lists, unfortunately */
3183 }
3184 else if (IsA(jtnode, JoinExpr))
3185 {
3186 JoinExpr *j = (JoinExpr *) jtnode;
3187 int rtindex = j->rtindex;
3188 JoinType jointype = j->jointype;
3189 reduce_outer_joins_pass1_state *left_state = linitial(state1->sub_states);
3190 reduce_outer_joins_pass1_state *right_state = lsecond(state1->sub_states);
3191
3192 /* Can we simplify this join? */
3193 switch (jointype)
3194 {
3195 case JOIN_INNER:
3196 break;
3197 case JOIN_LEFT:
3198 if (bms_overlap(nonnullable_rels, right_state->relids))
3199 jointype = JOIN_INNER;
3200 break;
3201 case JOIN_RIGHT:
3202 if (bms_overlap(nonnullable_rels, left_state->relids))
3203 jointype = JOIN_INNER;
3204 break;
3205 case JOIN_FULL:
3206 if (bms_overlap(nonnullable_rels, left_state->relids))
3207 {
3208 if (bms_overlap(nonnullable_rels, right_state->relids))
3209 jointype = JOIN_INNER;
3210 else
3211 {
3212 jointype = JOIN_LEFT;
3213 /* Also report partial reduction in state2 */
3214 report_reduced_full_join(state2, rtindex,
3215 right_state->relids);
3216 }
3217 }
3218 else
3219 {
3220 if (bms_overlap(nonnullable_rels, right_state->relids))
3221 {
3222 jointype = JOIN_RIGHT;
3223 /* Also report partial reduction in state2 */
3224 report_reduced_full_join(state2, rtindex,
3225 left_state->relids);
3226 }
3227 }
3228 break;
3229 case JOIN_SEMI:
3230 case JOIN_ANTI:
3231
3232 /*
3233 * These could only have been introduced by pull_up_sublinks,
3234 * so there's no way that upper quals could refer to their
3235 * righthand sides, and no point in checking. We don't expect
3236 * to see JOIN_RIGHT_SEMI or JOIN_RIGHT_ANTI yet.
3237 */
3238 break;
3239 default:
3240 elog(ERROR, "unrecognized join type: %d",
3241 (int) jointype);
3242 break;
3243 }
3244
3245 /*
3246 * Convert JOIN_RIGHT to JOIN_LEFT. Note that in the case where we
3247 * reduced JOIN_FULL to JOIN_RIGHT, this will mean the JoinExpr no
3248 * longer matches the internal ordering of any CoalesceExpr's built to
3249 * represent merged join variables. We don't care about that at
3250 * present, but be wary of it ...
3251 */
3252 if (jointype == JOIN_RIGHT)
3253 {
3254 Node *tmparg;
3255
3256 tmparg = j->larg;
3257 j->larg = j->rarg;
3258 j->rarg = tmparg;
3259 jointype = JOIN_LEFT;
3260 right_state = linitial(state1->sub_states);
3261 left_state = lsecond(state1->sub_states);
3262 }
3263
3264 /*
3265 * See if we can reduce JOIN_LEFT to JOIN_ANTI. This is the case if
3266 * the join's own quals are strict for any var that was forced null by
3267 * higher qual levels. NOTE: there are other ways that we could
3268 * detect an anti-join, in particular if we were to check whether Vars
3269 * coming from the RHS must be non-null because of table constraints.
3270 * That seems complicated and expensive though (in particular, one
3271 * would have to be wary of lower outer joins). For the moment this
3272 * seems sufficient.
3273 */
3274 if (jointype == JOIN_LEFT)
3275 {
3276 List *nonnullable_vars;
3277 Bitmapset *overlap;
3278
3279 /* Find Vars in j->quals that must be non-null in joined rows */
3280 nonnullable_vars = find_nonnullable_vars(j->quals);
3281
3282 /*
3283 * It's not sufficient to check whether nonnullable_vars and
3284 * forced_null_vars overlap: we need to know if the overlap
3285 * includes any RHS variables.
3286 */
3287 overlap = mbms_overlap_sets(nonnullable_vars, forced_null_vars);
3288 if (bms_overlap(overlap, right_state->relids))
3289 jointype = JOIN_ANTI;
3290 }
3291
3292 /*
3293 * Apply the jointype change, if any, to both jointree node and RTE.
3294 * Also, if we changed an RTE to INNER, add its RTI to inner_reduced.
3295 */
3296 if (rtindex && jointype != j->jointype)
3297 {
3298 RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
3299
3300 Assert(rte->rtekind == RTE_JOIN);
3301 Assert(rte->jointype == j->jointype);
3302 rte->jointype = jointype;
3303 if (jointype == JOIN_INNER)
3304 state2->inner_reduced = bms_add_member(state2->inner_reduced,
3305 rtindex);
3306 }
3307 j->jointype = jointype;
3308
3309 /* Only recurse if there's more to do below here */
3310 if (left_state->contains_outer || right_state->contains_outer)
3311 {
3312 Relids local_nonnullable_rels;
3313 List *local_forced_null_vars;
3314 Relids pass_nonnullable_rels;
3315 List *pass_forced_null_vars;
3316
3317 /*
3318 * If this join is (now) inner, we can add any constraints its
3319 * quals provide to those we got from above. But if it is outer,
3320 * we can pass down the local constraints only into the nullable
3321 * side, because an outer join never eliminates any rows from its
3322 * non-nullable side. Also, there is no point in passing upper
3323 * constraints into the nullable side, since if there were any
3324 * we'd have been able to reduce the join. (In the case of upper
3325 * forced-null constraints, we *must not* pass them into the
3326 * nullable side --- they either applied here, or not.) The upshot
3327 * is that we pass either the local or the upper constraints,
3328 * never both, to the children of an outer join.
3329 *
3330 * Note that a SEMI join works like an inner join here: it's okay
3331 * to pass down both local and upper constraints. (There can't be
3332 * any upper constraints affecting its inner side, but it's not
3333 * worth having a separate code path to avoid passing them.)
3334 *
3335 * At a FULL join we just punt and pass nothing down --- is it
3336 * possible to be smarter?
3337 */
3338 if (jointype != JOIN_FULL)
3339 {
3340 local_nonnullable_rels = find_nonnullable_rels(j->quals);
3341 local_forced_null_vars = find_forced_null_vars(j->quals);
3342 if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
3343 {
3344 /* OK to merge upper and local constraints */
3345 local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
3346 nonnullable_rels);
3347 local_forced_null_vars = mbms_add_members(local_forced_null_vars,
3348 forced_null_vars);
3349 }
3350 }
3351 else
3352 {
3353 /* no use in calculating these */
3354 local_nonnullable_rels = NULL;
3355 local_forced_null_vars = NIL;
3356 }
3357
3358 if (left_state->contains_outer)
3359 {
3360 if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
3361 {
3362 /* pass union of local and upper constraints */
3363 pass_nonnullable_rels = local_nonnullable_rels;
3364 pass_forced_null_vars = local_forced_null_vars;
3365 }
3366 else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
3367 {
3368 /* can't pass local constraints to non-nullable side */
3369 pass_nonnullable_rels = nonnullable_rels;
3370 pass_forced_null_vars = forced_null_vars;
3371 }
3372 else
3373 {
3374 /* no constraints pass through JOIN_FULL */
3375 pass_nonnullable_rels = NULL;
3376 pass_forced_null_vars = NIL;
3377 }
3378 reduce_outer_joins_pass2(j->larg, left_state,
3379 state2, root,
3380 pass_nonnullable_rels,
3381 pass_forced_null_vars);
3382 }
3383
3384 if (right_state->contains_outer)
3385 {
3386 if (jointype != JOIN_FULL) /* ie, INNER/LEFT/SEMI/ANTI */
3387 {
3388 /* pass appropriate constraints, per comment above */
3389 pass_nonnullable_rels = local_nonnullable_rels;
3390 pass_forced_null_vars = local_forced_null_vars;
3391 }
3392 else
3393 {
3394 /* no constraints pass through JOIN_FULL */
3395 pass_nonnullable_rels = NULL;
3396 pass_forced_null_vars = NIL;
3397 }
3398 reduce_outer_joins_pass2(j->rarg, right_state,
3399 state2, root,
3400 pass_nonnullable_rels,
3401 pass_forced_null_vars);
3402 }
3403 bms_free(local_nonnullable_rels);
3404 }
3405 }
3406 else
3407 elog(ERROR, "unrecognized node type: %d",
3408 (int) nodeTag(jtnode));
3409}
3410
3411/* Helper for reduce_outer_joins_pass2 */
3412static void
3414 int rtindex, Relids relids)
3415{
3417
3418 statep = palloc(sizeof(reduce_outer_joins_partial_state));
3419 statep->full_join_rti = rtindex;
3420 statep->unreduced_side = relids;
3421 state2->partial_reduced = lappend(state2->partial_reduced, statep);
3422}
3423
3424
3425/*
3426 * remove_useless_result_rtes
3427 * Attempt to remove RTE_RESULT RTEs from the join tree.
3428 * Also, elide single-child FromExprs where possible.
3429 *
3430 * We can remove RTE_RESULT entries from the join tree using the knowledge
3431 * that RTE_RESULT returns exactly one row and has no output columns. Hence,
3432 * if one is inner-joined to anything else, we can delete it. Optimizations
3433 * are also possible for some outer-join cases, as detailed below.
3434 *
3435 * This pass also replaces single-child FromExprs with their child node
3436 * where possible. It's appropriate to do that here and not earlier because
3437 * RTE_RESULT removal might reduce a multiple-child FromExpr to have only one
3438 * child. We can remove such a FromExpr if its quals are empty, or if it's
3439 * semantically valid to merge the quals into those of the parent node.
3440 * While removing unnecessary join tree nodes has some micro-efficiency value,
3441 * the real reason to do this is to eliminate cases where the nullable side of
3442 * an outer join node is a FromExpr whose single child is another outer join.
3443 * To correctly determine whether the two outer joins can commute,
3444 * deconstruct_jointree() must treat any quals of such a FromExpr as being
3445 * degenerate quals of the upper outer join. The best way to do that is to
3446 * make them actually *be* quals of the upper join, by dropping the FromExpr
3447 * and hoisting the quals up into the upper join's quals. (Note that there is
3448 * no hazard when the intermediate FromExpr has multiple children, since then
3449 * it represents an inner join that cannot commute with the upper outer join.)
3450 * As long as we have to do that, we might as well elide such FromExprs
3451 * everywhere.
3452 *
3453 * Some of these optimizations depend on recognizing empty (constant-true)
3454 * quals for FromExprs and JoinExprs. That makes it useful to apply this
3455 * optimization pass after expression preprocessing, since that will have
3456 * eliminated constant-true quals, allowing more cases to be recognized as
3457 * optimizable. What's more, the usual reason for an RTE_RESULT to be present
3458 * is that we pulled up a subquery or VALUES clause, thus very possibly
3459 * replacing Vars with constants, making it more likely that a qual can be
3460 * reduced to constant true. Also, because some optimizations depend on
3461 * the outer-join type, it's best to have done reduce_outer_joins() first.
3462 *
3463 * A PlaceHolderVar referencing an RTE_RESULT RTE poses an obstacle to this
3464 * process: we must remove the RTE_RESULT's relid from the PHV's phrels, but
3465 * we must not reduce the phrels set to empty. If that would happen, and
3466 * the RTE_RESULT is an immediate child of an outer join, we have to give up
3467 * and not remove the RTE_RESULT: there is noplace else to evaluate the
3468 * PlaceHolderVar. (That is, in such cases the RTE_RESULT *does* have output
3469 * columns.) But if the RTE_RESULT is an immediate child of an inner join,
3470 * we can usually change the PlaceHolderVar's phrels so as to evaluate it at
3471 * the inner join instead. This is OK because we really only care that PHVs
3472 * are evaluated above or below the correct outer joins. We can't, however,
3473 * postpone the evaluation of a PHV to above where it is used; so there are
3474 * some checks below on whether output PHVs are laterally referenced in the
3475 * other join input rel(s).
3476 *
3477 * We used to try to do this work as part of pull_up_subqueries() where the
3478 * potentially-optimizable cases get introduced; but it's way simpler, and
3479 * more effective, to do it separately.
3480 */
3481void
3483{
3484 Relids dropped_outer_joins = NULL;
3485 ListCell *cell;
3486
3487 /* Top level of jointree must always be a FromExpr */
3488 Assert(IsA(root->parse->jointree, FromExpr));
3489 /* Recurse ... */
3490 root->parse->jointree = (FromExpr *)
3492 (Node *) root->parse->jointree,
3493 NULL,
3494 &dropped_outer_joins);
3495 /* We should still have a FromExpr */
3496 Assert(IsA(root->parse->jointree, FromExpr));
3497
3498 /*
3499 * If we removed any outer-join nodes from the jointree, run around and
3500 * remove references to those joins as nulling rels. (There could be such
3501 * references in PHVs that we pulled up out of the original subquery that
3502 * the RESULT rel replaced. This is kosher on the grounds that we now
3503 * know that such an outer join wouldn't really have nulled anything.) We
3504 * don't do this during the main recursion, for simplicity and because we
3505 * can handle all such joins in a single pass over the parse tree.
3506 */
3507 if (!bms_is_empty(dropped_outer_joins))
3508 {
3509 root->parse = (Query *)
3510 remove_nulling_relids((Node *) root->parse,
3511 dropped_outer_joins,
3512 NULL);
3513 /* There could be references in the append_rel_list, too */
3514 root->append_rel_list = (List *)
3515 remove_nulling_relids((Node *) root->append_rel_list,
3516 dropped_outer_joins,
3517 NULL);
3518 }
3519
3520 /*
3521 * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
3522 * must do that for any RTE_RESULT that we just removed. But one for a
3523 * RTE that we did not remove can be dropped anyway: since the RTE has
3524 * only one possible output row, there is no need for EPQ to mark and
3525 * restore that row.
3526 *
3527 * It's necessary, not optional, to remove the PlanRowMark for a surviving
3528 * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
3529 * RTE_RESULT, which the executor has no support for.
3530 */
3531 foreach(cell, root->rowMarks)
3532 {
3533 PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3534
3535 if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
3536 root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3537 }
3538}
3539
3540/*
3541 * remove_useless_results_recurse
3542 * Recursive guts of remove_useless_result_rtes.
3543 *
3544 * This recursively processes the jointree and returns a modified jointree.
3545 * In addition, the RT indexes of any removed outer-join nodes are added to
3546 * *dropped_outer_joins.
3547 *
3548 * jtnode is the current jointree node. If it could be valid to merge
3549 * its quals into those of the parent node, parent_quals should point to
3550 * the parent's quals list; otherwise, pass NULL for parent_quals.
3551 * (Note that in some cases, parent_quals points to the quals of a parent
3552 * more than one level up in the tree.)
3553 */
3554static Node *
3556 Node **parent_quals,
3557 Relids *dropped_outer_joins)
3558{
3559 Assert(jtnode != NULL);
3560 if (IsA(jtnode, RangeTblRef))
3561 {
3562 /* Can't immediately do anything with a RangeTblRef */
3563 }
3564 else if (IsA(jtnode, FromExpr))
3565 {
3566 FromExpr *f = (FromExpr *) jtnode;
3567 Relids result_relids = NULL;
3568 ListCell *cell;
3569
3570 /*
3571 * We can drop RTE_RESULT rels from the fromlist so long as at least
3572 * one child remains, since joining to a one-row table changes
3573 * nothing. (But we can't drop a RTE_RESULT that computes PHV(s) that
3574 * are needed by some sibling. The cleanup transformation below would
3575 * reassign the PHVs to be computed at the join, which is too late for
3576 * the sibling's use.) The easiest way to mechanize this rule is to
3577 * modify the list in-place.
3578 */
3579 foreach(cell, f->fromlist)
3580 {
3581 Node *child = (Node *) lfirst(cell);
3582 int varno;
3583
3584 /* Recursively transform child, allowing it to push up quals ... */
3585 child = remove_useless_results_recurse(root, child,
3586 &f->quals,
3587 dropped_outer_joins);
3588 /* ... and stick it back into the tree */
3589 lfirst(cell) = child;
3590
3591 /*
3592 * If it's an RTE_RESULT with at least one sibling, and no sibling
3593 * references dependent PHVs, we can drop it. We don't yet know
3594 * what the inner join's final relid set will be, so postpone
3595 * cleanup of PHVs etc till after this loop.
3596 */
3597 if (list_length(f->fromlist) > 1 &&
3598 (varno = get_result_relid(root, child)) != 0 &&
3600 {
3601 f->fromlist = foreach_delete_current(f->fromlist, cell);
3602 result_relids = bms_add_member(result_relids, varno);
3603 }
3604 }
3605
3606 /*
3607 * Clean up if we dropped any RTE_RESULT RTEs. This is a bit
3608 * inefficient if there's more than one, but it seems better to
3609 * optimize the support code for the single-relid case.
3610 */
3611 if (result_relids)
3612 {
3613 int varno = -1;
3614
3615 while ((varno = bms_next_member(result_relids, varno)) >= 0)
3616 remove_result_refs(root, varno, (Node *) f);
3617 }
3618
3619 /*
3620 * If the FromExpr now has only one child, see if we can elide it.
3621 * This is always valid if there are no quals, except at the top of
3622 * the jointree (since Query.jointree is required to point to a
3623 * FromExpr). Otherwise, we can do it if we can push the quals up to
3624 * the parent node.
3625 *
3626 * Note: while it would not be terribly hard to generalize this
3627 * transformation to merge multi-child FromExprs into their parent
3628 * FromExpr, that risks making the parent join too expensive to plan.
3629 * We leave it to later processing to decide heuristically whether
3630 * that's a good idea. Pulling up a single child is always OK,
3631 * however.
3632 */
3633 if (list_length(f->fromlist) == 1 &&
3634 f != root->parse->jointree &&
3635 (f->quals == NULL || parent_quals != NULL))
3636 {
3637 /*
3638 * Merge any quals up to parent. They should be in implicit-AND
3639 * format by now, so we just need to concatenate lists. Put the
3640 * child quals at the front, on the grounds that they should
3641 * nominally be evaluated earlier.
3642 */
3643 if (f->quals != NULL)
3644 *parent_quals = (Node *)
3646 castNode(List, *parent_quals));
3647 return (Node *) linitial(f->fromlist);
3648 }
3649 }
3650 else if (IsA(jtnode, JoinExpr))
3651 {
3652 JoinExpr *j = (JoinExpr *) jtnode;
3653 int varno;
3654
3655 /*
3656 * First, recurse. We can absorb pushed-up FromExpr quals from either
3657 * child into this node if the jointype is INNER, since then this is
3658 * equivalent to a FromExpr. When the jointype is LEFT, we can absorb
3659 * quals from the RHS child into the current node, as they're
3660 * essentially degenerate quals of the outer join. Moreover, if we've
3661 * been passed down a parent_quals pointer then we can allow quals of
3662 * the LHS child to be absorbed into the parent. (This is important
3663 * to ensure we remove single-child FromExprs immediately below
3664 * commutable left joins.) For other jointypes, we can't move child
3665 * quals up, or at least there's no particular reason to.
3666 */
3667 j->larg = remove_useless_results_recurse(root, j->larg,
3668 (j->jointype == JOIN_INNER) ?
3669 &j->quals :
3670 (j->jointype == JOIN_LEFT) ?
3671 parent_quals : NULL,
3672 dropped_outer_joins);
3673 j->rarg = remove_useless_results_recurse(root, j->rarg,
3674 (j->jointype == JOIN_INNER ||
3675 j->jointype == JOIN_LEFT) ?
3676 &j->quals : NULL,
3677 dropped_outer_joins);
3678
3679 /* Apply join-type-specific optimization rules */
3680 switch (j->jointype)
3681 {
3682 case JOIN_INNER:
3683
3684 /*
3685 * An inner join is equivalent to a FromExpr, so if either
3686 * side was simplified to an RTE_RESULT rel, we can replace
3687 * the join with a FromExpr with just the other side.
3688 * Furthermore, we can elide that FromExpr according to the
3689 * same rules as above.
3690 *
3691 * Just as in the FromExpr case, we can't simplify if the
3692 * other input rel references any PHVs that are marked as to
3693 * be evaluated at the RTE_RESULT rel, because we can't
3694 * postpone their evaluation in that case. But we only have
3695 * to check this in cases where it's syntactically legal for
3696 * the other input to have a LATERAL reference to the
3697 * RTE_RESULT rel. Only RHSes of inner and left joins are
3698 * allowed to have such refs.
3699 */
3700 if ((varno = get_result_relid(root, j->larg)) != 0 &&
3701 !find_dependent_phvs_in_jointree(root, j->rarg, varno))
3702 {
3703 remove_result_refs(root, varno, j->rarg);
3704 if (j->quals != NULL && parent_quals == NULL)
3705 jtnode = (Node *)
3706 makeFromExpr(list_make1(j->rarg), j->quals);
3707 else
3708 {
3709 /* Merge any quals up to parent */
3710 if (j->quals != NULL)
3711 *parent_quals = (Node *)
3712 list_concat(castNode(List, j->quals),
3713 castNode(List, *parent_quals));
3714 jtnode = j->rarg;
3715 }
3716 }
3717 else if ((varno = get_result_relid(root, j->rarg)) != 0)
3718 {
3719 remove_result_refs(root, varno, j->larg);
3720 if (j->quals != NULL && parent_quals == NULL)
3721 jtnode = (Node *)
3722 makeFromExpr(list_make1(j->larg), j->quals);
3723 else
3724 {
3725 /* Merge any quals up to parent */
3726 if (j->quals != NULL)
3727 *parent_quals = (Node *)
3728 list_concat(castNode(List, j->quals),
3729 castNode(List, *parent_quals));
3730 jtnode = j->larg;
3731 }
3732 }
3733 break;
3734 case JOIN_LEFT:
3735
3736 /*
3737 * We can simplify this case if the RHS is an RTE_RESULT, with
3738 * two different possibilities:
3739 *
3740 * If the qual is empty (JOIN ON TRUE), then the join can be
3741 * strength-reduced to a plain inner join, since each LHS row
3742 * necessarily has exactly one join partner. So we can always
3743 * discard the RHS, much as in the JOIN_INNER case above.
3744 * (Again, the LHS could not contain a lateral reference to
3745 * the RHS.)
3746 *
3747 * Otherwise, it's still true that each LHS row should be
3748 * returned exactly once, and since the RHS returns no columns
3749 * (unless there are PHVs that have to be evaluated there), we
3750 * don't much care if it's null-extended or not. So in this
3751 * case also, we can just ignore the qual and discard the left
3752 * join.
3753 */
3754 if ((varno = get_result_relid(root, j->rarg)) != 0 &&
3755 (j->quals == NULL ||
3756 !find_dependent_phvs(root, varno)))
3757 {
3758 remove_result_refs(root, varno, j->larg);
3759 *dropped_outer_joins = bms_add_member(*dropped_outer_joins,
3760 j->rtindex);
3761 jtnode = j->larg;
3762 }
3763 break;
3764 case JOIN_SEMI:
3765
3766 /*
3767 * We may simplify this case if the RHS is an RTE_RESULT; the
3768 * join qual becomes effectively just a filter qual for the
3769 * LHS, since we should either return the LHS row or not. The
3770 * filter clause must go into a new FromExpr if we can't push
3771 * it up to the parent.
3772 *
3773 * There is a fine point about PHVs that are supposed to be
3774 * evaluated at the RHS. Such PHVs could only appear in the
3775 * semijoin's qual, since the rest of the query cannot
3776 * reference any outputs of the semijoin's RHS. Therefore,
3777 * they can't actually go to null before being examined, and
3778 * it'd be OK to just remove the PHV wrapping. We don't have
3779 * infrastructure for that, but remove_result_refs() will
3780 * relabel them as to be evaluated at the LHS, which is fine.
3781 *
3782 * Also, we don't need to worry about removing traces of the
3783 * join's rtindex, since it hasn't got one.
3784 */
3785 if ((varno = get_result_relid(root, j->rarg)) != 0)
3786 {
3787 Assert(j->rtindex == 0);
3788 remove_result_refs(root, varno, j->larg);
3789 if (j->quals != NULL && parent_quals == NULL)
3790 jtnode = (Node *)
3791 makeFromExpr(list_make1(j->larg), j->quals);
3792 else
3793 {
3794 /* Merge any quals up to parent */
3795 if (j->quals != NULL)
3796 *parent_quals = (Node *)
3797 list_concat(castNode(List, j->quals),
3798 castNode(List, *parent_quals));
3799 jtnode = j->larg;
3800 }
3801 }
3802 break;
3803 case JOIN_FULL:
3804 case JOIN_ANTI:
3805 /* We have no special smarts for these cases */
3806 break;
3807 default:
3808 /* Note: JOIN_RIGHT should be gone at this point */
3809 elog(ERROR, "unrecognized join type: %d",
3810 (int) j->jointype);
3811 break;
3812 }
3813 }
3814 else
3815 elog(ERROR, "unrecognized node type: %d",
3816 (int) nodeTag(jtnode));
3817 return jtnode;
3818}
3819
3820/*
3821 * get_result_relid
3822 * If jtnode is a RangeTblRef for an RTE_RESULT RTE, return its relid;
3823 * otherwise return 0.
3824 */
3825static int
3827{
3828 int varno;
3829
3830 if (!IsA(jtnode, RangeTblRef))
3831 return 0;
3832 varno = ((RangeTblRef *) jtnode)->rtindex;
3833 if (rt_fetch(varno, root->parse->rtable)->rtekind != RTE_RESULT)
3834 return 0;
3835 return varno;
3836}
3837
3838/*
3839 * remove_result_refs
3840 * Helper routine for dropping an unneeded RTE_RESULT RTE.
3841 *
3842 * This doesn't physically remove the RTE from the jointree, because that's
3843 * more easily handled in remove_useless_results_recurse. What it does do
3844 * is the necessary cleanup in the rest of the tree: we must adjust any PHVs
3845 * that may reference the RTE. Be sure to call this at a point where the
3846 * jointree is valid (no disconnected nodes).
3847 *
3848 * Note that we don't need to process the append_rel_list, since RTEs
3849 * referenced directly in the jointree won't be appendrel members.
3850 *
3851 * varno is the RTE_RESULT's relid.
3852 * newjtloc is the jointree location at which any PHVs referencing the
3853 * RTE_RESULT should be evaluated instead.
3854 */
3855static void
3857{
3858 /* Fix up PlaceHolderVars as needed */
3859 /* If there are no PHVs anywhere, we can skip this bit */
3860 if (root->glob->lastPHId != 0)
3861 {
3862 Relids subrelids;
3863
3864 subrelids = get_relids_in_jointree(newjtloc, true, false);
3865 Assert(!bms_is_empty(subrelids));
3866 substitute_phv_relids((Node *) root->parse, varno, subrelids);
3867 fix_append_rel_relids(root, varno, subrelids);
3868 }
3869
3870 /*
3871 * We also need to remove any PlanRowMark referencing the RTE, but we
3872 * postpone that work until we return to remove_useless_result_rtes.
3873 */
3874}
3875
3876
3877/*
3878 * find_dependent_phvs - are there any PlaceHolderVars whose relids are
3879 * exactly the given varno?
3880 *
3881 * find_dependent_phvs should be used when we want to see if there are
3882 * any such PHVs anywhere in the Query. Another use-case is to see if
3883 * a subtree of the join tree contains such PHVs; but for that, we have
3884 * to look not only at the join tree nodes themselves but at the
3885 * referenced RTEs. For that, use find_dependent_phvs_in_jointree.
3886 */
3887
3888typedef struct
3889{
3893
3894static bool
3897{
3898 if (node == NULL)
3899 return false;
3900 if (IsA(node, PlaceHolderVar))
3901 {
3902 PlaceHolderVar *phv = (PlaceHolderVar *) node;
3903
3904 if (phv->phlevelsup == context->sublevels_up &&
3905 bms_equal(context->relids, phv->phrels))
3906 return true;
3907 /* fall through to examine children */
3908 }
3909 if (IsA(node, Query))
3910 {
3911 /* Recurse into subselects */
3912 bool result;
3913
3914 context->sublevels_up++;
3915 result = query_tree_walker((Query *) node,
3917 context, 0);
3918 context->sublevels_up--;
3919 return result;
3920 }
3921 /* Shouldn't need to handle most planner auxiliary nodes here */
3922 Assert(!IsA(node, SpecialJoinInfo));
3923 Assert(!IsA(node, PlaceHolderInfo));
3924 Assert(!IsA(node, MinMaxAggInfo));
3925
3927}
3928
3929static bool
3931{
3933
3934 /* If there are no PHVs anywhere, we needn't work hard */
3935 if (root->glob->lastPHId == 0)
3936 return false;
3937
3938 context.relids = bms_make_singleton(varno);
3939 context.sublevels_up = 0;
3940
3942 return true;
3943 /* The append_rel_list could be populated already, so check it too */
3944 if (expression_tree_walker((Node *) root->append_rel_list,
3946 &context))
3947 return true;
3948 return false;
3949}
3950
3951static bool
3953{
3955 Relids subrelids;
3956 int relid;
3957
3958 /* If there are no PHVs anywhere, we needn't work hard */
3959 if (root->glob->lastPHId == 0)
3960 return false;
3961
3962 context.relids = bms_make_singleton(varno);
3963 context.sublevels_up = 0;
3964
3965 /*
3966 * See if the jointree fragment itself contains references (in join quals)
3967 */
3969 return true;
3970
3971 /*
3972 * Otherwise, identify the set of referenced RTEs (we can ignore joins,
3973 * since they should be flattened already, so their join alias lists no
3974 * longer matter), and tediously check each RTE. We can ignore RTEs that
3975 * are not marked LATERAL, though, since they couldn't possibly contain
3976 * any cross-references to other RTEs.
3977 */
3978 subrelids = get_relids_in_jointree(node, false, false);
3979 relid = -1;
3980 while ((relid = bms_next_member(subrelids, relid)) >= 0)
3981 {
3982 RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
3983
3984 if (rte->lateral &&
3986 return true;
3987 }
3988
3989 return false;
3990}
3991
3992/*
3993 * substitute_phv_relids - adjust PlaceHolderVar relid sets after pulling up
3994 * a subquery or removing an RTE_RESULT jointree item
3995 *
3996 * Find any PlaceHolderVar nodes in the given tree that reference the
3997 * pulled-up relid, and change them to reference the replacement relid(s).
3998 *
3999 * NOTE: although this has the form of a walker, we cheat and modify the
4000 * nodes in-place. This should be OK since the tree was copied by
4001 * pullup_replace_vars earlier. Avoid scribbling on the original values of
4002 * the bitmapsets, though, because expression_tree_mutator doesn't copy those.
4003 */
4004
4005typedef struct
4006{
4011
4012static bool
4015{
4016 if (node == NULL)
4017 return false;
4018 if (IsA(node, PlaceHolderVar))
4019 {
4020 PlaceHolderVar *phv = (PlaceHolderVar *) node;
4021
4022 if (phv->phlevelsup == context->sublevels_up &&
4023 bms_is_member(context->varno, phv->phrels))
4024 {
4025 phv->phrels = bms_union(phv->phrels,
4026 context->subrelids);
4027 phv->phrels = bms_del_member(phv->phrels,
4028 context->varno);
4029 /* Assert we haven't broken the PHV */
4030 Assert(!bms_is_empty(phv->phrels));
4031 }
4032 /* fall through to examine children */
4033 }
4034 if (IsA(node, Query))
4035 {
4036 /* Recurse into subselects */
4037 bool result;
4038
4039 context->sublevels_up++;
4040 result = query_tree_walker((Query *) node,
4042 context, 0);
4043 context->sublevels_up--;
4044 return result;
4045 }
4046 /* Shouldn't need to handle planner auxiliary nodes here */
4047 Assert(!IsA(node, SpecialJoinInfo));
4048 Assert(!IsA(node, AppendRelInfo));
4049 Assert(!IsA(node, PlaceHolderInfo));
4050 Assert(!IsA(node, MinMaxAggInfo));
4051
4053}
4054
4055static void
4056substitute_phv_relids(Node *node, int varno, Relids subrelids)
4057{
4059
4060 context.varno = varno;
4061 context.sublevels_up = 0;
4062 context.subrelids = subrelids;
4063
4064 /*
4065 * Must be prepared to start with a Query or a bare expression tree.
4066 */
4069 &context,
4070 0);
4071}
4072
4073/*
4074 * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
4075 *
4076 * When we pull up a subquery, any AppendRelInfo references to the subquery's
4077 * RT index have to be replaced by the substituted relid (and there had better
4078 * be only one). We also need to apply substitute_phv_relids to their
4079 * translated_vars lists, since those might contain PlaceHolderVars.
4080 *
4081 * We assume we may modify the AppendRelInfo nodes in-place.
4082 */
4083static void
4085{
4086 ListCell *l;
4087 int subvarno = -1;
4088
4089 /*
4090 * We only want to extract the member relid once, but we mustn't fail
4091 * immediately if there are multiple members; it could be that none of the
4092 * AppendRelInfo nodes refer to it. So compute it on first use. Note that
4093 * bms_singleton_member will complain if set is not singleton.
4094 */
4095 foreach(l, root->append_rel_list)
4096 {
4097 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
4098
4099 /* The parent_relid shouldn't ever be a pullup target */
4100 Assert(appinfo->parent_relid != varno);
4101
4102 if (appinfo->child_relid == varno)
4103 {
4104 if (subvarno < 0)
4105 subvarno = bms_singleton_member(subrelids);
4106 appinfo->child_relid = subvarno;
4107 }
4108
4109 /* Also fix up any PHVs in its translated vars */
4110 if (root->glob->lastPHId != 0)
4112 varno, subrelids);
4113 }
4114}
4115
4116/*
4117 * get_relids_in_jointree: get set of RT indexes present in a jointree
4118 *
4119 * Base-relation relids are always included in the result.
4120 * If include_outer_joins is true, outer-join RT indexes are included.
4121 * If include_inner_joins is true, inner-join RT indexes are included.
4122 *
4123 * Note that for most purposes in the planner, outer joins are included
4124 * in standard relid sets. Setting include_inner_joins true is only
4125 * appropriate for special purposes during subquery flattening.
4126 */
4127Relids
4128get_relids_in_jointree(Node *jtnode, bool include_outer_joins,
4129 bool include_inner_joins)
4130{
4131 Relids result = NULL;
4132
4133 if (jtnode == NULL)
4134 return result;
4135 if (IsA(jtnode, RangeTblRef))
4136 {
4137 int varno = ((RangeTblRef *) jtnode)->rtindex;
4138
4139 result = bms_make_singleton(varno);
4140 }
4141 else if (IsA(jtnode, FromExpr))
4142 {
4143 FromExpr *f = (FromExpr *) jtnode;
4144 ListCell *l;
4145
4146 foreach(l, f->fromlist)
4147 {
4148 result = bms_join(result,
4150 include_outer_joins,
4151 include_inner_joins));
4152 }
4153 }
4154 else if (IsA(jtnode, JoinExpr))
4155 {
4156 JoinExpr *j = (JoinExpr *) jtnode;
4157
4158 result = get_relids_in_jointree(j->larg,
4159 include_outer_joins,
4160 include_inner_joins);
4161 result = bms_join(result,
4163 include_outer_joins,
4164 include_inner_joins));
4165 if (j->rtindex)
4166 {
4167 if (j->jointype == JOIN_INNER)
4168 {
4169 if (include_inner_joins)
4170 result = bms_add_member(result, j->rtindex);
4171 }
4172 else
4173 {
4174 if (include_outer_joins)
4175 result = bms_add_member(result, j->rtindex);
4176 }
4177 }
4178 }
4179 else
4180 elog(ERROR, "unrecognized node type: %d",
4181 (int) nodeTag(jtnode));
4182 return result;
4183}
4184
4185/*
4186 * get_relids_for_join: get set of base+OJ RT indexes making up a join
4187 */
4188Relids
4189get_relids_for_join(Query *query, int joinrelid)
4190{
4191 Node *jtnode;
4192
4193 jtnode = find_jointree_node_for_rel((Node *) query->jointree,
4194 joinrelid);
4195 if (!jtnode)
4196 elog(ERROR, "could not find join node %d", joinrelid);
4197 return get_relids_in_jointree(jtnode, true, false);
4198}
4199
4200/*
4201 * find_jointree_node_for_rel: locate jointree node for a base or join RT index
4202 *
4203 * Returns NULL if not found
4204 */
4205static Node *
4207{
4208 if (jtnode == NULL)
4209 return NULL;
4210 if (IsA(jtnode, RangeTblRef))
4211 {
4212 int varno = ((RangeTblRef *) jtnode)->rtindex;
4213
4214 if (relid == varno)
4215 return jtnode;
4216 }
4217 else if (IsA(jtnode, FromExpr))
4218 {
4219 FromExpr *f = (FromExpr *) jtnode;
4220 ListCell *l;
4221
4222 foreach(l, f->fromlist)
4223 {
4224 jtnode = find_jointree_node_for_rel(lfirst(l), relid);
4225 if (jtnode)
4226 return jtnode;
4227 }
4228 }
4229 else if (IsA(jtnode, JoinExpr))
4230 {
4231 JoinExpr *j = (JoinExpr *) jtnode;
4232
4233 if (relid == j->rtindex)
4234 return jtnode;
4235 jtnode = find_jointree_node_for_rel(j->larg, relid);
4236 if (jtnode)
4237 return jtnode;
4238 jtnode = find_jointree_node_for_rel(j->rarg, relid);
4239 if (jtnode)
4240 return jtnode;
4241 }
4242 else
4243 elog(ERROR, "unrecognized node type: %d",
4244 (int) nodeTag(jtnode));
4245 return NULL;
4246}
4247
4248/*
4249 * get_nullingrels: collect info about which outer joins null which relations
4250 *
4251 * The result struct contains, for each leaf relation used in the query,
4252 * the set of relids of outer joins that potentially null that rel.
4253 */
4254static nullingrel_info *
4256{
4258
4259 result->rtlength = list_length(parse->rtable);
4260 result->nullingrels = palloc0_array(Relids, result->rtlength + 1);
4261 get_nullingrels_recurse((Node *) parse->jointree, NULL, result);
4262 return result;
4263}
4264
4265/*
4266 * Recursive guts of get_nullingrels().
4267 *
4268 * Note: at any recursion level, the passed-down upper_nullingrels must be
4269 * treated as a constant, but it can be stored directly into *info
4270 * if we're at leaf level. Upper recursion levels do not free their mutated
4271 * copies of the nullingrels, because those are probably referenced by
4272 * at least one leaf rel.
4273 */
4274static void
4275get_nullingrels_recurse(Node *jtnode, Relids upper_nullingrels,
4276 nullingrel_info *info)
4277{
4278 if (jtnode == NULL)
4279 return;
4280 if (IsA(jtnode, RangeTblRef))
4281 {
4282 int varno = ((RangeTblRef *) jtnode)->rtindex;
4283
4284 Assert(varno > 0 && varno <= info->rtlength);
4285 info->nullingrels[varno] = upper_nullingrels;
4286 }
4287 else if (IsA(jtnode, FromExpr))
4288 {
4289 FromExpr *f = (FromExpr *) jtnode;
4290 ListCell *l;
4291
4292 foreach(l, f->fromlist)
4293 {
4294 get_nullingrels_recurse(lfirst(l), upper_nullingrels, info);
4295 }
4296 }
4297 else if (IsA(jtnode, JoinExpr))
4298 {
4299 JoinExpr *j = (JoinExpr *) jtnode;
4300 Relids local_nullingrels;
4301
4302 switch (j->jointype)
4303 {
4304 case JOIN_INNER:
4305 get_nullingrels_recurse(j->larg, upper_nullingrels, info);
4306 get_nullingrels_recurse(j->rarg, upper_nullingrels, info);
4307 break;
4308 case JOIN_LEFT:
4309 case JOIN_SEMI:
4310 case JOIN_ANTI:
4311 local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
4312 j->rtindex);
4313 get_nullingrels_recurse(j->larg, upper_nullingrels, info);
4314 get_nullingrels_recurse(j->rarg, local_nullingrels, info);
4315 break;
4316 case JOIN_FULL:
4317 local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
4318 j->rtindex);
4319 get_nullingrels_recurse(j->larg, local_nullingrels, info);
4320 get_nullingrels_recurse(j->rarg, local_nullingrels, info);
4321 break;
4322 case JOIN_RIGHT:
4323 local_nullingrels = bms_add_member(bms_copy(upper_nullingrels),
4324 j->rtindex);
4325 get_nullingrels_recurse(j->larg, local_nullingrels, info);
4326 get_nullingrels_recurse(j->rarg, upper_nullingrels, info);
4327 break;
4328 default:
4329 elog(ERROR, "unrecognized join type: %d",
4330 (int) j->jointype);
4331 break;
4332 }
4333 }
4334 else
4335 elog(ERROR, "unrecognized node type: %d",
4336 (int) nodeTag(jtnode));
4337}
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:812
unsigned int Index
Definition: c.h:568
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1915
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:5063
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2253
List * find_nonnullable_vars(Node *clause)
Definition: clauses.c:1706
Relids find_nonnullable_rels(Node *clause)
Definition: clauses.c:1455
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:389
Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)
Definition: makefuncs.c:105
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:287
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:135
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:677
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:240
Node * make_and_qual(Node *qual1, Node *qual2)
Definition: makefuncs.c:730
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:758
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, int location, bool include_dropped, List **colnames, List **colvars)
@ SETOP_UNION
Definition: parsenodes.h:2119
@ RTE_JOIN
Definition: parsenodes.h:1019
@ RTE_CTE
Definition: parsenodes.h:1023
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1024
@ RTE_VALUES
Definition: parsenodes.h:1022
@ RTE_SUBQUERY
Definition: parsenodes.h:1018
@ RTE_RESULT
Definition: parsenodes.h:1025
@ RTE_FUNCTION
Definition: parsenodes.h:1020
@ RTE_TABLEFUNC
Definition: parsenodes.h:1021
@ RTE_GROUP
Definition: parsenodes.h:1028
@ RTE_RELATION
Definition: parsenodes.h:1017
#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:36
unsigned int Oid
Definition: postgres_ext.h:31
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:999
@ EXISTS_SUBLINK
Definition: primnodes.h:997
#define NUM_MERGE_MATCH_KINDS
Definition: primnodes.h:2001
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:736
@ IS_NOT_NULL
Definition: primnodes.h:1952
@ MERGE_WHEN_NOT_MATCHED_BY_TARGET
Definition: primnodes.h:1998
@ MERGE_WHEN_NOT_MATCHED_BY_SOURCE
Definition: primnodes.h:1997
@ MERGE_WHEN_MATCHED
Definition: primnodes.h:1996
tree context
Definition: radixtree.h:1837
tree ctl root
Definition: radixtree.h:1888
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:864
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:841
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:2309
List * fromlist
Definition: primnodes.h:2308
Node * quals
Definition: primnodes.h:2289
JoinType jointype
Definition: primnodes.h:2280
int rtindex
Definition: primnodes.h:2293
Node * larg
Definition: primnodes.h:2282
bool isNatural
Definition: primnodes.h:2281
Node * rarg
Definition: primnodes.h:2283
Definition: pg_list.h:54
Definition: nodes.h:129
NullTestType nulltesttype
Definition: primnodes.h:1959
ParseLoc location
Definition: primnodes.h:1962
Expr * arg
Definition: primnodes.h:1958
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:219
Node * limitCount
Definition: parsenodes.h:216
FromExpr * jointree
Definition: parsenodes.h:177
Node * setOperations
Definition: parsenodes.h:221
List * cteList
Definition: parsenodes.h:168
List * groupClause
Definition: parsenodes.h:202
Node * havingQual
Definition: parsenodes.h:207
List * rtable
Definition: parsenodes.h:170
Node * limitOffset
Definition: parsenodes.h:215
CmdType commandType
Definition: parsenodes.h:121
List * targetList
Definition: parsenodes.h:193
List * groupingSets
Definition: parsenodes.h:205
List * distinctClause
Definition: parsenodes.h:211
List * sortClause
Definition: parsenodes.h:213
TableFunc * tablefunc
Definition: parsenodes.h:1184
bool funcordinality
Definition: parsenodes.h:1179
struct TableSampleClause * tablesample
Definition: parsenodes.h:1098
Query * subquery
Definition: parsenodes.h:1104
List * values_lists
Definition: parsenodes.h:1190
JoinType jointype
Definition: parsenodes.h:1151
List * functions
Definition: parsenodes.h:1177
RTEKind rtekind
Definition: parsenodes.h:1047
List * args
Definition: primnodes.h:1411
ParseLoc location
Definition: primnodes.h:1435
SetOperation op
Definition: parsenodes.h:2198
Expr * expr
Definition: primnodes.h:2190
AttrNumber resno
Definition: primnodes.h:2192
Definition: primnodes.h:248
ParseLoc location
Definition: primnodes.h:293
AttrNumber varattno
Definition: primnodes.h:260
int varno
Definition: primnodes.h:255
Index varlevelsup
Definition: primnodes.h:280
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:1251
JoinExpr * convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink, bool under_not, Relids available_rels)
Definition: subselect.c:1368
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:443
Relids pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup)
Definition: var.c:139
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:113
Node * flatten_join_alias_vars(PlannerInfo *root, Query *query, Node *node)
Definition: var.c:745