1 /*-------------------------------------------------------------------------
4 * Planner preprocessing for subqueries and join tree manipulation.
6 * NOTE: the intended sequence for invoking these operations is
8 * inline_set_returning_functions
10 * do expression preprocessing (including flattening JOIN alias vars)
14 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
15 * Portions Copyright (c) 1994, Regents of the University of California
21 *-------------------------------------------------------------------------
25 #include "nodes/makefuncs.h"
26 #include "nodes/nodeFuncs.h"
27 #include "optimizer/clauses.h"
28 #include "optimizer/placeholder.h"
29 #include "optimizer/prep.h"
30 #include "optimizer/subselect.h"
31 #include "optimizer/tlist.h"
32 #include "optimizer/var.h"
33 #include "parser/parsetree.h"
34 #include "rewrite/rewriteManip.h"
37 typedef struct reduce_outer_joins_state
39 Relids relids
; /* base relids within this subtree */
40 bool contains_outer
; /* does subtree contain outer join(s)? */
41 List
*sub_states
; /* List of states for subtree components */
42 } reduce_outer_joins_state
;
44 static Node
*pull_up_sublinks_jointree_recurse(PlannerInfo
*root
, Node
*jtnode
,
46 static Node
*pull_up_sublinks_qual_recurse(PlannerInfo
*root
, Node
*node
,
47 Relids available_rels
, Node
**jtlink
);
48 static Node
*pull_up_simple_subquery(PlannerInfo
*root
, Node
*jtnode
,
50 JoinExpr
*lowest_outer_join
,
51 AppendRelInfo
*containing_appendrel
);
52 static Node
*pull_up_simple_union_all(PlannerInfo
*root
, Node
*jtnode
,
54 static void pull_up_union_leaf_queries(Node
*setOp
, PlannerInfo
*root
,
55 int parentRTindex
, Query
*setOpQuery
,
57 static void make_setop_translation_list(Query
*query
, Index newvarno
,
58 List
**translated_vars
);
59 static bool is_simple_subquery(Query
*subquery
);
60 static bool is_simple_union_all(Query
*subquery
);
61 static bool is_simple_union_all_recurse(Node
*setOp
, Query
*setOpQuery
,
63 static List
*insert_targetlist_placeholders(PlannerInfo
*root
, List
*tlist
,
64 int varno
, bool wrap_non_vars
);
65 static bool is_safe_append_member(Query
*subquery
);
66 static void resolvenew_in_jointree(Node
*jtnode
, int varno
, RangeTblEntry
*rte
,
67 List
*subtlist
, List
*subtlist_with_phvs
,
68 JoinExpr
*lowest_outer_join
);
69 static reduce_outer_joins_state
*reduce_outer_joins_pass1(Node
*jtnode
);
70 static void reduce_outer_joins_pass2(Node
*jtnode
,
71 reduce_outer_joins_state
*state
,
73 Relids nonnullable_rels
,
74 List
*nonnullable_vars
,
75 List
*forced_null_vars
);
76 static void substitute_multiple_relids(Node
*node
,
77 int varno
, Relids subrelids
);
78 static void fix_append_rel_relids(List
*append_rel_list
, int varno
,
80 static Node
*find_jointree_node_for_rel(Node
*jtnode
, int relid
);
85 * Attempt to pull up ANY and EXISTS SubLinks to be treated as
86 * semijoins or anti-semijoins.
88 * A clause "foo op ANY (sub-SELECT)" can be processed by pulling the
89 * sub-SELECT up to become a rangetable entry and treating the implied
90 * comparisons as quals of a semijoin. However, this optimization *only*
91 * works at the top level of WHERE or a JOIN/ON clause, because we cannot
92 * distinguish whether the ANY ought to return FALSE or NULL in cases
93 * involving NULL inputs. Also, in an outer join's ON clause we can only
94 * do this if the sublink is degenerate (ie, references only the nullable
95 * side of the join). In that case it is legal to push the semijoin
96 * down into the nullable side of the join. If the sublink references any
97 * nonnullable-side variables then it would have to be evaluated as part
98 * of the outer join, which makes things way too complicated.
100 * Under similar conditions, EXISTS and NOT EXISTS clauses can be handled
101 * by pulling up the sub-SELECT and creating a semijoin or anti-semijoin.
103 * This routine searches for such clauses and does the necessary parsetree
104 * transformations if any are found.
106 * This routine has to run before preprocess_expression(), so the quals
107 * clauses are not yet reduced to implicit-AND format. That means we need
108 * to recursively search through explicit AND clauses, which are
109 * probably only binary ANDs. We stop as soon as we hit a non-AND item.
112 pull_up_sublinks(PlannerInfo
*root
)
117 /* Begin recursion through the jointree */
118 jtnode
= pull_up_sublinks_jointree_recurse(root
,
119 (Node
*) root
->parse
->jointree
,
123 * root->parse->jointree must always be a FromExpr, so insert a dummy one
124 * if we got a bare RangeTblRef or JoinExpr out of the recursion.
126 if (IsA(jtnode
, FromExpr
))
127 root
->parse
->jointree
= (FromExpr
*) jtnode
;
129 root
->parse
->jointree
= makeFromExpr(list_make1(jtnode
), NULL
);
133 * Recurse through jointree nodes for pull_up_sublinks()
135 * In addition to returning the possibly-modified jointree node, we return
136 * a relids set of the contained rels into *relids.
139 pull_up_sublinks_jointree_recurse(PlannerInfo
*root
, Node
*jtnode
,
146 else if (IsA(jtnode
, RangeTblRef
))
148 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
150 *relids
= bms_make_singleton(varno
);
151 /* jtnode is returned unmodified */
153 else if (IsA(jtnode
, FromExpr
))
155 FromExpr
*f
= (FromExpr
*) jtnode
;
156 List
*newfromlist
= NIL
;
157 Relids frelids
= NULL
;
162 /* First, recurse to process children and collect their relids */
163 foreach(l
, f
->fromlist
)
168 newchild
= pull_up_sublinks_jointree_recurse(root
,
171 newfromlist
= lappend(newfromlist
, newchild
);
172 frelids
= bms_join(frelids
, childrelids
);
174 /* Build the replacement FromExpr; no quals yet */
175 newf
= makeFromExpr(newfromlist
, NULL
);
176 /* Set up a link representing the rebuilt jointree */
177 jtlink
= (Node
*) newf
;
178 /* Now process qual --- all children are available for use */
179 newf
->quals
= pull_up_sublinks_qual_recurse(root
, f
->quals
, frelids
,
183 * Note that the result will be either newf, or a stack of JoinExprs
184 * with newf at the base. We rely on subsequent optimization steps to
185 * flatten this and rearrange the joins as needed.
187 * Although we could include the pulled-up subqueries in the returned
188 * relids, there's no need since upper quals couldn't refer to their
194 else if (IsA(jtnode
, JoinExpr
))
202 * Make a modifiable copy of join node, but don't bother copying its
205 j
= (JoinExpr
*) palloc(sizeof(JoinExpr
));
206 memcpy(j
, jtnode
, sizeof(JoinExpr
));
209 /* Recurse to process children and collect their relids */
210 j
->larg
= pull_up_sublinks_jointree_recurse(root
, j
->larg
,
212 j
->rarg
= pull_up_sublinks_jointree_recurse(root
, j
->rarg
,
216 * Now process qual, showing appropriate child relids as available,
217 * and attach any pulled-up jointree items at the right place. In the
218 * inner-join case we put new JoinExprs above the existing one (much
219 * as for a FromExpr-style join). In outer-join cases the new
220 * JoinExprs must go into the nullable side of the outer join. The
221 * point of the available_rels machinations is to ensure that we only
222 * pull up quals for which that's okay.
224 * XXX for the moment, we refrain from pulling up IN/EXISTS clauses
225 * appearing in LEFT or RIGHT join conditions. Although it is
226 * semantically valid to do so under the above conditions, we end up
227 * with a query in which the semijoin or antijoin must be evaluated
228 * below the outer join, which could perform far worse than leaving it
229 * as a sublink that is executed only for row pairs that meet the
230 * other join conditions. Fixing this seems to require considerable
231 * restructuring of the executor, but maybe someday it can happen.
233 * We don't expect to see any pre-existing JOIN_SEMI or JOIN_ANTI
239 j
->quals
= pull_up_sublinks_qual_recurse(root
, j
->quals
,
240 bms_union(leftrelids
,
245 #ifdef NOT_USED /* see XXX comment above */
246 j
->quals
= pull_up_sublinks_qual_recurse(root
, j
->quals
,
252 /* can't do anything with full-join quals */
255 #ifdef NOT_USED /* see XXX comment above */
256 j
->quals
= pull_up_sublinks_qual_recurse(root
, j
->quals
,
262 elog(ERROR
, "unrecognized join type: %d",
268 * Although we could include the pulled-up subqueries in the returned
269 * relids, there's no need since upper quals couldn't refer to their
270 * outputs anyway. But we *do* need to include the join's own rtindex
271 * because we haven't yet collapsed join alias variables, so upper
272 * levels would mistakenly think they couldn't use references to this
275 *relids
= bms_join(leftrelids
, rightrelids
);
277 *relids
= bms_add_member(*relids
, j
->rtindex
);
281 elog(ERROR
, "unrecognized node type: %d",
282 (int) nodeTag(jtnode
));
287 * Recurse through top-level qual nodes for pull_up_sublinks()
289 * jtlink points to the link in the jointree where any new JoinExprs should be
290 * inserted. If we find multiple pull-up-able SubLinks, they'll get stacked
291 * there in the order we encounter them. We rely on subsequent optimization
292 * to rearrange the stack if appropriate.
295 pull_up_sublinks_qual_recurse(PlannerInfo
*root
, Node
*node
,
296 Relids available_rels
, Node
**jtlink
)
300 if (IsA(node
, SubLink
))
302 SubLink
*sublink
= (SubLink
*) node
;
305 /* Is it a convertible ANY or EXISTS clause? */
306 if (sublink
->subLinkType
== ANY_SUBLINK
)
308 j
= convert_ANY_sublink_to_join(root
, sublink
,
312 /* Yes, insert the new join node into the join tree */
314 *jtlink
= (Node
*) j
;
315 /* and return NULL representing constant TRUE */
319 else if (sublink
->subLinkType
== EXISTS_SUBLINK
)
321 j
= convert_EXISTS_sublink_to_join(root
, sublink
, false,
325 /* Yes, insert the new join node into the join tree */
327 *jtlink
= (Node
*) j
;
328 /* and return NULL representing constant TRUE */
332 /* Else return it unmodified */
335 if (not_clause(node
))
337 /* If the immediate argument of NOT is EXISTS, try to convert */
338 SubLink
*sublink
= (SubLink
*) get_notclausearg((Expr
*) node
);
341 if (sublink
&& IsA(sublink
, SubLink
))
343 if (sublink
->subLinkType
== EXISTS_SUBLINK
)
345 j
= convert_EXISTS_sublink_to_join(root
, sublink
, true,
349 /* Yes, insert the new join node into the join tree */
351 *jtlink
= (Node
*) j
;
352 /* and return NULL representing constant TRUE */
357 /* Else return it unmodified */
360 if (and_clause(node
))
362 /* Recurse into AND clause */
363 List
*newclauses
= NIL
;
366 foreach(l
, ((BoolExpr
*) node
)->args
)
368 Node
*oldclause
= (Node
*) lfirst(l
);
371 newclause
= pull_up_sublinks_qual_recurse(root
,
376 newclauses
= lappend(newclauses
, newclause
);
378 /* We might have got back fewer clauses than we started with */
379 if (newclauses
== NIL
)
381 else if (list_length(newclauses
) == 1)
382 return (Node
*) linitial(newclauses
);
384 return (Node
*) make_andclause(newclauses
);
386 /* Stop if not an AND */
391 * inline_set_returning_functions
392 * Attempt to "inline" set-returning functions in the FROM clause.
394 * If an RTE_FUNCTION rtable entry invokes a set-returning function that
395 * contains just a simple SELECT, we can convert the rtable entry to an
396 * RTE_SUBQUERY entry exposing the SELECT directly. This is especially
397 * useful if the subquery can then be "pulled up" for further optimization,
398 * but we do it even if not, to reduce executor overhead.
400 * This has to be done before we have started to do any optimization of
401 * subqueries, else any such steps wouldn't get applied to subqueries
402 * obtained via inlining. However, we do it after pull_up_sublinks
403 * so that we can inline any functions used in SubLink subselects.
405 * Like most of the planner, this feels free to scribble on its input data
409 inline_set_returning_functions(PlannerInfo
*root
)
413 foreach(rt
, root
->parse
->rtable
)
415 RangeTblEntry
*rte
= (RangeTblEntry
*) lfirst(rt
);
417 if (rte
->rtekind
== RTE_FUNCTION
)
421 /* Check safety of expansion, and expand if possible */
422 funcquery
= inline_set_returning_function(root
, rte
);
425 /* Successful expansion, replace the rtable entry */
426 rte
->rtekind
= RTE_SUBQUERY
;
427 rte
->subquery
= funcquery
;
428 rte
->funcexpr
= NULL
;
429 rte
->funccoltypes
= NIL
;
430 rte
->funccoltypmods
= NIL
;
438 * Look for subqueries in the rangetable that can be pulled up into
439 * the parent query. If the subquery has no special features like
440 * grouping/aggregation then we can merge it into the parent's jointree.
441 * Also, subqueries that are simple UNION ALL structures can be
442 * converted into "append relations".
444 * If this jointree node is within the nullable side of an outer join, then
445 * lowest_outer_join references the lowest such JoinExpr node; otherwise it
446 * is NULL. This forces use of the PlaceHolderVar mechanism for references
447 * to non-nullable targetlist items, but only for references above that join.
449 * If we are looking at a member subquery of an append relation,
450 * containing_appendrel describes that relation; else it is NULL.
451 * This forces use of the PlaceHolderVar mechanism for all non-Var targetlist
452 * items, and puts some additional restrictions on what can be pulled up.
454 * A tricky aspect of this code is that if we pull up a subquery we have
455 * to replace Vars that reference the subquery's outputs throughout the
456 * parent query, including quals attached to jointree nodes above the one
457 * we are currently processing! We handle this by being careful not to
458 * change the jointree structure while recursing: no nodes other than
459 * subquery RangeTblRef entries will be replaced. Also, we can't turn
460 * ResolveNew loose on the whole jointree, because it'll return a mutated
461 * copy of the tree; we have to invoke it just on the quals, instead.
462 * This behavior is what makes it reasonable to pass lowest_outer_join as a
463 * pointer rather than some more-indirect way of identifying the lowest OJ.
464 * Likewise, we don't replace append_rel_list members but only their
465 * substructure, so the containing_appendrel reference is safe to use.
468 pull_up_subqueries(PlannerInfo
*root
, Node
*jtnode
,
469 JoinExpr
*lowest_outer_join
,
470 AppendRelInfo
*containing_appendrel
)
474 if (IsA(jtnode
, RangeTblRef
))
476 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
477 RangeTblEntry
*rte
= rt_fetch(varno
, root
->parse
->rtable
);
480 * Is this a subquery RTE, and if so, is the subquery simple enough to
483 * If we are looking at an append-relation member, we can't pull it up
484 * unless is_safe_append_member says so.
486 if (rte
->rtekind
== RTE_SUBQUERY
&&
487 is_simple_subquery(rte
->subquery
) &&
488 (containing_appendrel
== NULL
||
489 is_safe_append_member(rte
->subquery
)))
490 return pull_up_simple_subquery(root
, jtnode
, rte
,
492 containing_appendrel
);
495 * Alternatively, is it a simple UNION ALL subquery? If so, flatten
496 * into an "append relation".
498 * It's safe to do this regardless of whether this query is itself an
499 * appendrel member. (If you're thinking we should try to flatten the
500 * two levels of appendrel together, you're right; but we handle that
501 * in set_append_rel_pathlist, not here.)
503 if (rte
->rtekind
== RTE_SUBQUERY
&&
504 is_simple_union_all(rte
->subquery
))
505 return pull_up_simple_union_all(root
, jtnode
, rte
);
507 /* Otherwise, do nothing at this node. */
509 else if (IsA(jtnode
, FromExpr
))
511 FromExpr
*f
= (FromExpr
*) jtnode
;
514 Assert(containing_appendrel
== NULL
);
515 foreach(l
, f
->fromlist
)
516 lfirst(l
) = pull_up_subqueries(root
, lfirst(l
),
517 lowest_outer_join
, NULL
);
519 else if (IsA(jtnode
, JoinExpr
))
521 JoinExpr
*j
= (JoinExpr
*) jtnode
;
523 Assert(containing_appendrel
== NULL
);
524 /* Recurse, being careful to tell myself when inside outer join */
528 j
->larg
= pull_up_subqueries(root
, j
->larg
,
529 lowest_outer_join
, NULL
);
530 j
->rarg
= pull_up_subqueries(root
, j
->rarg
,
531 lowest_outer_join
, NULL
);
536 j
->larg
= pull_up_subqueries(root
, j
->larg
,
537 lowest_outer_join
, NULL
);
538 j
->rarg
= pull_up_subqueries(root
, j
->rarg
,
542 j
->larg
= pull_up_subqueries(root
, j
->larg
,
544 j
->rarg
= pull_up_subqueries(root
, j
->rarg
,
548 j
->larg
= pull_up_subqueries(root
, j
->larg
,
550 j
->rarg
= pull_up_subqueries(root
, j
->rarg
,
551 lowest_outer_join
, NULL
);
554 elog(ERROR
, "unrecognized join type: %d",
560 elog(ERROR
, "unrecognized node type: %d",
561 (int) nodeTag(jtnode
));
566 * pull_up_simple_subquery
567 * Attempt to pull up a single simple subquery.
569 * jtnode is a RangeTblRef that has been tentatively identified as a simple
570 * subquery by pull_up_subqueries. We return the replacement jointree node,
571 * or jtnode itself if we determine that the subquery can't be pulled up after
574 * rte is the RangeTblEntry referenced by jtnode. Remaining parameters are
575 * as for pull_up_subqueries.
578 pull_up_simple_subquery(PlannerInfo
*root
, Node
*jtnode
, RangeTblEntry
*rte
,
579 JoinExpr
*lowest_outer_join
,
580 AppendRelInfo
*containing_appendrel
)
582 Query
*parse
= root
->parse
;
583 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
585 PlannerInfo
*subroot
;
588 List
*subtlist_with_phvs
;
592 * Need a modifiable copy of the subquery to hack on. Even if we didn't
593 * sometimes choose not to pull up below, we must do this to avoid
594 * problems if the same subquery is referenced from multiple jointree
595 * items (which can't happen normally, but might after rule rewriting).
597 subquery
= copyObject(rte
->subquery
);
600 * Create a PlannerInfo data structure for this subquery.
602 * NOTE: the next few steps should match the first processing in
603 * subquery_planner(). Can we refactor to avoid code duplication, or
604 * would that just make things uglier?
606 subroot
= makeNode(PlannerInfo
);
607 subroot
->parse
= subquery
;
608 subroot
->glob
= root
->glob
;
609 subroot
->query_level
= root
->query_level
;
610 subroot
->parent_root
= root
->parent_root
;
611 subroot
->planner_cxt
= CurrentMemoryContext
;
612 subroot
->init_plans
= NIL
;
613 subroot
->cte_plan_ids
= NIL
;
614 subroot
->eq_classes
= NIL
;
615 subroot
->append_rel_list
= NIL
;
616 subroot
->hasRecursion
= false;
617 subroot
->wt_param_id
= -1;
618 subroot
->non_recursive_plan
= NULL
;
620 /* No CTEs to worry about */
621 Assert(subquery
->cteList
== NIL
);
624 * Pull up any SubLinks within the subquery's quals, so that we don't
625 * leave unoptimized SubLinks behind.
627 if (subquery
->hasSubLinks
)
628 pull_up_sublinks(subroot
);
631 * Similarly, inline any set-returning functions in its rangetable.
633 inline_set_returning_functions(subroot
);
636 * Recursively pull up the subquery's subqueries, so that
637 * pull_up_subqueries' processing is complete for its jointree and
640 * Note: we should pass NULL for containing-join info even if we are
641 * within an outer join in the upper query; the lower query starts with a
642 * clean slate for outer-join semantics. Likewise, we say we aren't
643 * handling an appendrel member.
645 subquery
->jointree
= (FromExpr
*)
646 pull_up_subqueries(subroot
, (Node
*) subquery
->jointree
, NULL
, NULL
);
649 * Now we must recheck whether the subquery is still simple enough to pull
650 * up. If not, abandon processing it.
652 * We don't really need to recheck all the conditions involved, but it's
653 * easier just to keep this "if" looking the same as the one in
654 * pull_up_subqueries.
656 if (is_simple_subquery(subquery
) &&
657 (containing_appendrel
== NULL
|| is_safe_append_member(subquery
)))
664 * Give up, return unmodified RangeTblRef.
666 * Note: The work we just did will be redone when the subquery gets
667 * planned on its own. Perhaps we could avoid that by storing the
668 * modified subquery back into the rangetable, but I'm not gonna risk
675 * Adjust level-0 varnos in subquery so that we can append its rangetable
676 * to upper query's. We have to fix the subquery's append_rel_list as
679 rtoffset
= list_length(parse
->rtable
);
680 OffsetVarNodes((Node
*) subquery
, rtoffset
, 0);
681 OffsetVarNodes((Node
*) subroot
->append_rel_list
, rtoffset
, 0);
684 * Upper-level vars in subquery are now one level closer to their parent
687 IncrementVarSublevelsUp((Node
*) subquery
, -1, 1);
688 IncrementVarSublevelsUp((Node
*) subroot
->append_rel_list
, -1, 1);
691 * The subquery's targetlist items are now in the appropriate form to
692 * insert into the top query, but if we are under an outer join then
693 * non-nullable items may have to be turned into PlaceHolderVars. If we
694 * are dealing with an appendrel member then anything that's not a simple
695 * Var has to be turned into a PlaceHolderVar.
697 subtlist
= subquery
->targetList
;
698 if (lowest_outer_join
!= NULL
|| containing_appendrel
!= NULL
)
699 subtlist_with_phvs
= insert_targetlist_placeholders(root
,
702 containing_appendrel
!= NULL
);
704 subtlist_with_phvs
= subtlist
;
707 * Replace all of the top query's references to the subquery's outputs
708 * with copies of the adjusted subtlist items, being careful not to
709 * replace any of the jointree structure. (This'd be a lot cleaner if we
710 * could use query_tree_mutator.) We have to use PHVs in the targetList,
711 * returningList, and havingQual, since those are certainly above any
712 * outer join. resolvenew_in_jointree tracks its location in the jointree
713 * and uses PHVs or not appropriately.
715 parse
->targetList
= (List
*)
716 ResolveNew((Node
*) parse
->targetList
,
718 subtlist_with_phvs
, CMD_SELECT
, 0);
719 parse
->returningList
= (List
*)
720 ResolveNew((Node
*) parse
->returningList
,
722 subtlist_with_phvs
, CMD_SELECT
, 0);
723 resolvenew_in_jointree((Node
*) parse
->jointree
, varno
, rte
,
724 subtlist
, subtlist_with_phvs
,
726 Assert(parse
->setOperations
== NULL
);
728 ResolveNew(parse
->havingQual
,
730 subtlist_with_phvs
, CMD_SELECT
, 0);
733 * Replace references in the translated_vars lists of appendrels. When
734 * pulling up an appendrel member, we do not need PHVs in the list of the
735 * parent appendrel --- there isn't any outer join between. Elsewhere, use
736 * PHVs for safety. (This analysis could be made tighter but it seems
737 * unlikely to be worth much trouble.)
739 foreach(lc
, root
->append_rel_list
)
741 AppendRelInfo
*appinfo
= (AppendRelInfo
*) lfirst(lc
);
743 appinfo
->translated_vars
= (List
*)
744 ResolveNew((Node
*) appinfo
->translated_vars
,
746 (appinfo
== containing_appendrel
) ?
747 subtlist
: subtlist_with_phvs
,
752 * Replace references in the joinaliasvars lists of join RTEs.
754 * You might think that we could avoid using PHVs for alias vars of joins
755 * below lowest_outer_join, but that doesn't work because the alias vars
756 * could be referenced above that join; we need the PHVs to be present in
757 * such references after the alias vars get flattened. (It might be worth
758 * trying to be smarter here, someday.)
760 foreach(lc
, parse
->rtable
)
762 RangeTblEntry
*otherrte
= (RangeTblEntry
*) lfirst(lc
);
764 if (otherrte
->rtekind
== RTE_JOIN
)
765 otherrte
->joinaliasvars
= (List
*)
766 ResolveNew((Node
*) otherrte
->joinaliasvars
,
768 subtlist_with_phvs
, CMD_SELECT
, 0);
772 * Now append the adjusted rtable entries to upper query. (We hold off
773 * until after fixing the upper rtable entries; no point in running that
774 * code on the subquery ones too.)
776 parse
->rtable
= list_concat(parse
->rtable
, subquery
->rtable
);
779 * Pull up any FOR UPDATE/SHARE markers, too. (OffsetVarNodes already
780 * adjusted the marker rtindexes, so just concat the lists.)
782 parse
->rowMarks
= list_concat(parse
->rowMarks
, subquery
->rowMarks
);
785 * We also have to fix the relid sets of any PlaceHolderVar nodes in the
786 * parent query. (This could perhaps be done by ResolveNew, but it would
787 * clutter that routine's API unreasonably.) Note in particular that any
788 * PlaceHolderVar nodes just created by insert_targetlist_placeholders()
789 * will be adjusted, so having created them with the subquery's varno is
792 * Likewise, relids appearing in AppendRelInfo nodes have to be fixed. We
793 * already checked that this won't require introducing multiple subrelids
794 * into the single-slot AppendRelInfo structs.
796 if (parse
->hasSubLinks
|| root
->glob
->lastPHId
!= 0 ||
797 root
->append_rel_list
)
801 subrelids
= get_relids_in_jointree((Node
*) subquery
->jointree
, false);
802 substitute_multiple_relids((Node
*) parse
, varno
, subrelids
);
803 fix_append_rel_relids(root
->append_rel_list
, varno
, subrelids
);
807 * And now add subquery's AppendRelInfos to our list.
809 root
->append_rel_list
= list_concat(root
->append_rel_list
,
810 subroot
->append_rel_list
);
813 * We don't have to do the equivalent bookkeeping for outer-join info,
814 * because that hasn't been set up yet. placeholder_list likewise.
816 Assert(root
->join_info_list
== NIL
);
817 Assert(subroot
->join_info_list
== NIL
);
818 Assert(root
->placeholder_list
== NIL
);
819 Assert(subroot
->placeholder_list
== NIL
);
822 * Miscellaneous housekeeping.
824 parse
->hasSubLinks
|= subquery
->hasSubLinks
;
827 * subquery won't be pulled up if it hasAggs or hasWindowFuncs, so no work
828 * needed on those flags
832 * Return the adjusted subquery jointree to replace the RangeTblRef entry
833 * in parent's jointree.
835 return (Node
*) subquery
->jointree
;
839 * pull_up_simple_union_all
840 * Pull up a single simple UNION ALL subquery.
842 * jtnode is a RangeTblRef that has been identified as a simple UNION ALL
843 * subquery by pull_up_subqueries. We pull up the leaf subqueries and
844 * build an "append relation" for the union set. The result value is just
845 * jtnode, since we don't actually need to change the query jointree.
848 pull_up_simple_union_all(PlannerInfo
*root
, Node
*jtnode
, RangeTblEntry
*rte
)
850 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
851 Query
*subquery
= rte
->subquery
;
856 * Append the subquery rtable entries to upper query.
858 rtoffset
= list_length(root
->parse
->rtable
);
861 * Append child RTEs to parent rtable.
863 * Upper-level vars in subquery are now one level closer to their parent
864 * than before. We don't have to worry about offsetting varnos, though,
865 * because any such vars must refer to stuff above the level of the query
866 * we are pulling into.
868 rtable
= copyObject(subquery
->rtable
);
869 IncrementVarSublevelsUp_rtable(rtable
, -1, 1);
870 root
->parse
->rtable
= list_concat(root
->parse
->rtable
, rtable
);
873 * Recursively scan the subquery's setOperations tree and add
874 * AppendRelInfo nodes for leaf subqueries to the parent's
877 Assert(subquery
->setOperations
);
878 pull_up_union_leaf_queries(subquery
->setOperations
, root
, varno
, subquery
,
882 * Mark the parent as an append relation.
890 * pull_up_union_leaf_queries -- recursive guts of pull_up_simple_union_all
892 * Note that setOpQuery is the Query containing the setOp node, whose rtable
893 * is where to look up the RTE if setOp is a RangeTblRef. This is *not* the
894 * same as root->parse, which is the top-level Query we are pulling up into.
896 * parentRTindex is the appendrel parent's index in root->parse->rtable.
898 * The child RTEs have already been copied to the parent. childRToffset
899 * tells us where in the parent's range table they were copied.
902 pull_up_union_leaf_queries(Node
*setOp
, PlannerInfo
*root
, int parentRTindex
,
903 Query
*setOpQuery
, int childRToffset
)
905 if (IsA(setOp
, RangeTblRef
))
907 RangeTblRef
*rtr
= (RangeTblRef
*) setOp
;
909 AppendRelInfo
*appinfo
;
912 * Calculate the index in the parent's range table
914 childRTindex
= childRToffset
+ rtr
->rtindex
;
917 * Build a suitable AppendRelInfo, and attach to parent's list.
919 appinfo
= makeNode(AppendRelInfo
);
920 appinfo
->parent_relid
= parentRTindex
;
921 appinfo
->child_relid
= childRTindex
;
922 appinfo
->parent_reltype
= InvalidOid
;
923 appinfo
->child_reltype
= InvalidOid
;
924 make_setop_translation_list(setOpQuery
, childRTindex
,
925 &appinfo
->translated_vars
);
926 appinfo
->parent_reloid
= InvalidOid
;
927 root
->append_rel_list
= lappend(root
->append_rel_list
, appinfo
);
930 * Recursively apply pull_up_subqueries to the new child RTE. (We
931 * must build the AppendRelInfo first, because this will modify it.)
932 * Note that we can pass NULL for containing-join info even if we're
933 * actually under an outer join, because the child's expressions
934 * aren't going to propagate up above the join.
936 rtr
= makeNode(RangeTblRef
);
937 rtr
->rtindex
= childRTindex
;
938 (void) pull_up_subqueries(root
, (Node
*) rtr
, NULL
, appinfo
);
940 else if (IsA(setOp
, SetOperationStmt
))
942 SetOperationStmt
*op
= (SetOperationStmt
*) setOp
;
944 /* Recurse to reach leaf queries */
945 pull_up_union_leaf_queries(op
->larg
, root
, parentRTindex
, setOpQuery
,
947 pull_up_union_leaf_queries(op
->rarg
, root
, parentRTindex
, setOpQuery
,
952 elog(ERROR
, "unrecognized node type: %d",
953 (int) nodeTag(setOp
));
958 * make_setop_translation_list
959 * Build the list of translations from parent Vars to child Vars for
960 * a UNION ALL member. (At this point it's just a simple list of
961 * referencing Vars, but if we succeed in pulling up the member
962 * subquery, the Vars will get replaced by pulled-up expressions.)
965 make_setop_translation_list(Query
*query
, Index newvarno
,
966 List
**translated_vars
)
971 foreach(l
, query
->targetList
)
973 TargetEntry
*tle
= (TargetEntry
*) lfirst(l
);
978 vars
= lappend(vars
, makeVar(newvarno
,
980 exprType((Node
*) tle
->expr
),
981 exprTypmod((Node
*) tle
->expr
),
985 *translated_vars
= vars
;
990 * Check a subquery in the range table to see if it's simple enough
991 * to pull up into the parent query.
994 is_simple_subquery(Query
*subquery
)
997 * Let's just make sure it's a valid subselect ...
999 if (!IsA(subquery
, Query
) ||
1000 subquery
->commandType
!= CMD_SELECT
||
1001 subquery
->utilityStmt
!= NULL
||
1002 subquery
->intoClause
!= NULL
)
1003 elog(ERROR
, "subquery is bogus");
1006 * Can't currently pull up a query with setops (unless it's simple UNION
1007 * ALL, which is handled by a different code path). Maybe after querytree
1010 if (subquery
->setOperations
)
1014 * Can't pull up a subquery involving grouping, aggregation, sorting,
1015 * limiting, or WITH. (XXX WITH could possibly be allowed later)
1017 if (subquery
->hasAggs
||
1018 subquery
->hasWindowFuncs
||
1019 subquery
->groupClause
||
1020 subquery
->havingQual
||
1021 subquery
->sortClause
||
1022 subquery
->distinctClause
||
1023 subquery
->limitOffset
||
1024 subquery
->limitCount
||
1029 * Don't pull up a subquery that has any set-returning functions in its
1030 * targetlist. Otherwise we might well wind up inserting set-returning
1031 * functions into places where they mustn't go, such as quals of higher
1034 if (expression_returns_set((Node
*) subquery
->targetList
))
1038 * Don't pull up a subquery that has any volatile functions in its
1039 * targetlist. Otherwise we might introduce multiple evaluations of these
1040 * functions, if they get copied to multiple places in the upper query,
1041 * leading to surprising results. (Note: the PlaceHolderVar mechanism
1042 * doesn't quite guarantee single evaluation; else we could pull up anyway
1043 * and just wrap such items in PlaceHolderVars ...)
1045 if (contain_volatile_functions((Node
*) subquery
->targetList
))
1049 * Hack: don't try to pull up a subquery with an empty jointree.
1050 * query_planner() will correctly generate a Result plan for a jointree
1051 * that's totally empty, but I don't think the right things happen if an
1052 * empty FromExpr appears lower down in a jointree. It would pose a
1053 * problem for the PlaceHolderVar mechanism too, since we'd have no way to
1054 * identify where to evaluate a PHV coming out of the subquery. Not worth
1055 * working hard on this, just to collapse SubqueryScan/Result into Result;
1056 * especially since the SubqueryScan can often be optimized away by
1059 if (subquery
->jointree
->fromlist
== NIL
)
1066 * is_simple_union_all
1067 * Check a subquery to see if it's a simple UNION ALL.
1069 * We require all the setops to be UNION ALL (no mixing) and there can't be
1070 * any datatype coercions involved, ie, all the leaf queries must emit the
1074 is_simple_union_all(Query
*subquery
)
1076 SetOperationStmt
*topop
;
1078 /* Let's just make sure it's a valid subselect ... */
1079 if (!IsA(subquery
, Query
) ||
1080 subquery
->commandType
!= CMD_SELECT
||
1081 subquery
->utilityStmt
!= NULL
||
1082 subquery
->intoClause
!= NULL
)
1083 elog(ERROR
, "subquery is bogus");
1085 /* Is it a set-operation query at all? */
1086 topop
= (SetOperationStmt
*) subquery
->setOperations
;
1089 Assert(IsA(topop
, SetOperationStmt
));
1091 /* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */
1092 if (subquery
->sortClause
||
1093 subquery
->limitOffset
||
1094 subquery
->limitCount
||
1095 subquery
->rowMarks
||
1099 /* Recursively check the tree of set operations */
1100 return is_simple_union_all_recurse((Node
*) topop
, subquery
,
1105 is_simple_union_all_recurse(Node
*setOp
, Query
*setOpQuery
, List
*colTypes
)
1107 if (IsA(setOp
, RangeTblRef
))
1109 RangeTblRef
*rtr
= (RangeTblRef
*) setOp
;
1110 RangeTblEntry
*rte
= rt_fetch(rtr
->rtindex
, setOpQuery
->rtable
);
1111 Query
*subquery
= rte
->subquery
;
1113 Assert(subquery
!= NULL
);
1115 /* Leaf nodes are OK if they match the toplevel column types */
1116 /* We don't have to compare typmods here */
1117 return tlist_same_datatypes(subquery
->targetList
, colTypes
, true);
1119 else if (IsA(setOp
, SetOperationStmt
))
1121 SetOperationStmt
*op
= (SetOperationStmt
*) setOp
;
1123 /* Must be UNION ALL */
1124 if (op
->op
!= SETOP_UNION
|| !op
->all
)
1127 /* Recurse to check inputs */
1128 return is_simple_union_all_recurse(op
->larg
, setOpQuery
, colTypes
) &&
1129 is_simple_union_all_recurse(op
->rarg
, setOpQuery
, colTypes
);
1133 elog(ERROR
, "unrecognized node type: %d",
1134 (int) nodeTag(setOp
));
1135 return false; /* keep compiler quiet */
1140 * insert_targetlist_placeholders
1141 * Insert PlaceHolderVar nodes into any non-junk targetlist items that are
1142 * not simple variables or strict functions of simple variables (and hence
1143 * might not correctly go to NULL when examined above the point of an outer
1146 * varno is the upper-query relid of the subquery; this is used as the
1147 * syntactic location of the PlaceHolderVars.
1148 * If wrap_non_vars is true then *only* simple Var references escape being
1149 * wrapped with PlaceHolderVars.
1152 insert_targetlist_placeholders(PlannerInfo
*root
, List
*tlist
,
1153 int varno
, bool wrap_non_vars
)
1160 TargetEntry
*tle
= (TargetEntry
*) lfirst(lc
);
1161 TargetEntry
*newtle
;
1163 /* resjunk columns need not be changed */
1166 result
= lappend(result
, tle
);
1171 * Simple Vars always escape being wrapped. This is common enough to
1172 * deserve a fast path even if we aren't doing wrap_non_vars.
1174 if (tle
->expr
&& IsA(tle
->expr
, Var
) &&
1175 ((Var
*) tle
->expr
)->varlevelsup
== 0)
1177 result
= lappend(result
, tle
);
1184 * If it contains a Var of current level, and does not contain any
1185 * non-strict constructs, then it's certainly nullable and we
1186 * don't need to insert a PlaceHolderVar. (Note: in future maybe
1187 * we should insert PlaceHolderVars anyway, when a tlist item is
1188 * expensive to evaluate?
1190 if (contain_vars_of_level((Node
*) tle
->expr
, 0) &&
1191 !contain_nonstrict_functions((Node
*) tle
->expr
))
1193 result
= lappend(result
, tle
);
1198 /* Else wrap it in a PlaceHolderVar */
1199 newtle
= makeNode(TargetEntry
);
1200 memcpy(newtle
, tle
, sizeof(TargetEntry
));
1201 newtle
->expr
= (Expr
*)
1202 make_placeholder_expr(root
,
1204 bms_make_singleton(varno
));
1205 result
= lappend(result
, newtle
);
1211 * is_safe_append_member
1212 * Check a subquery that is a leaf of a UNION ALL appendrel to see if it's
1216 is_safe_append_member(Query
*subquery
)
1221 * It's only safe to pull up the child if its jointree contains exactly
1222 * one RTE, else the AppendRelInfo data structure breaks. The one base RTE
1223 * could be buried in several levels of FromExpr, however.
1225 * Also, the child can't have any WHERE quals because there's no place to
1226 * put them in an appendrel. (This is a bit annoying...) If we didn't
1227 * need to check this, we'd just test whether get_relids_in_jointree()
1228 * yields a singleton set, to be more consistent with the coding of
1229 * fix_append_rel_relids().
1231 jtnode
= subquery
->jointree
;
1232 while (IsA(jtnode
, FromExpr
))
1234 if (jtnode
->quals
!= NULL
)
1236 if (list_length(jtnode
->fromlist
) != 1)
1238 jtnode
= linitial(jtnode
->fromlist
);
1240 if (!IsA(jtnode
, RangeTblRef
))
1247 * Helper routine for pull_up_subqueries: do ResolveNew on every expression
1248 * in the jointree, without changing the jointree structure itself. Ugly,
1249 * but there's no other way...
1251 * If we are above lowest_outer_join then use subtlist_with_phvs; at or
1252 * below it, use subtlist. (When no outer joins are in the picture,
1253 * these will be the same list.)
1256 resolvenew_in_jointree(Node
*jtnode
, int varno
, RangeTblEntry
*rte
,
1257 List
*subtlist
, List
*subtlist_with_phvs
,
1258 JoinExpr
*lowest_outer_join
)
1262 if (IsA(jtnode
, RangeTblRef
))
1264 /* nothing to do here */
1266 else if (IsA(jtnode
, FromExpr
))
1268 FromExpr
*f
= (FromExpr
*) jtnode
;
1271 foreach(l
, f
->fromlist
)
1272 resolvenew_in_jointree(lfirst(l
), varno
, rte
,
1273 subtlist
, subtlist_with_phvs
,
1275 f
->quals
= ResolveNew(f
->quals
,
1277 subtlist_with_phvs
, CMD_SELECT
, 0);
1279 else if (IsA(jtnode
, JoinExpr
))
1281 JoinExpr
*j
= (JoinExpr
*) jtnode
;
1283 if (j
== lowest_outer_join
)
1285 /* no more PHVs in or below this join */
1286 subtlist_with_phvs
= subtlist
;
1287 lowest_outer_join
= NULL
;
1289 resolvenew_in_jointree(j
->larg
, varno
, rte
,
1290 subtlist
, subtlist_with_phvs
,
1292 resolvenew_in_jointree(j
->rarg
, varno
, rte
,
1293 subtlist
, subtlist_with_phvs
,
1295 j
->quals
= ResolveNew(j
->quals
,
1297 subtlist_with_phvs
, CMD_SELECT
, 0);
1300 * We don't bother to update the colvars list, since it won't be used
1305 elog(ERROR
, "unrecognized node type: %d",
1306 (int) nodeTag(jtnode
));
1310 * reduce_outer_joins
1311 * Attempt to reduce outer joins to plain inner joins.
1313 * The idea here is that given a query like
1314 * SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
1315 * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
1316 * is strict. The strict operator will always return NULL, causing the outer
1317 * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
1318 * columns. Therefore, there's no need for the join to produce null-extended
1319 * rows in the first place --- which makes it a plain join not an outer join.
1320 * (This scenario may not be very likely in a query written out by hand, but
1321 * it's reasonably likely when pushing quals down into complex views.)
1323 * More generally, an outer join can be reduced in strength if there is a
1324 * strict qual above it in the qual tree that constrains a Var from the
1325 * nullable side of the join to be non-null. (For FULL joins this applies
1326 * to each side separately.)
1328 * Another transformation we apply here is to recognize cases like
1329 * SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.y IS NULL;
1330 * If the join clause is strict for b.y, then only null-extended rows could
1331 * pass the upper WHERE, and we can conclude that what the query is really
1332 * specifying is an anti-semijoin. We change the join type from JOIN_LEFT
1333 * to JOIN_ANTI. The IS NULL clause then becomes redundant, and must be
1334 * removed to prevent bogus selectivity calculations, but we leave it to
1335 * distribute_qual_to_rels to get rid of such clauses.
1337 * Also, we get rid of JOIN_RIGHT cases by flipping them around to become
1338 * JOIN_LEFT. This saves some code here and in some later planner routines,
1339 * but the main reason to do it is to not need to invent a JOIN_REVERSE_ANTI
1342 * To ease recognition of strict qual clauses, we require this routine to be
1343 * run after expression preprocessing (i.e., qual canonicalization and JOIN
1344 * alias-var expansion).
1347 reduce_outer_joins(PlannerInfo
*root
)
1349 reduce_outer_joins_state
*state
;
1352 * To avoid doing strictness checks on more quals than necessary, we want
1353 * to stop descending the jointree as soon as there are no outer joins
1354 * below our current point. This consideration forces a two-pass process.
1355 * The first pass gathers information about which base rels appear below
1356 * each side of each join clause, and about whether there are outer
1357 * join(s) below each side of each join clause. The second pass examines
1358 * qual clauses and changes join types as it descends the tree.
1360 state
= reduce_outer_joins_pass1((Node
*) root
->parse
->jointree
);
1362 /* planner.c shouldn't have called me if no outer joins */
1363 if (state
== NULL
|| !state
->contains_outer
)
1364 elog(ERROR
, "so where are the outer joins?");
1366 reduce_outer_joins_pass2((Node
*) root
->parse
->jointree
,
1367 state
, root
, NULL
, NIL
, NIL
);
1371 * reduce_outer_joins_pass1 - phase 1 data collection
1373 * Returns a state node describing the given jointree node.
1375 static reduce_outer_joins_state
*
1376 reduce_outer_joins_pass1(Node
*jtnode
)
1378 reduce_outer_joins_state
*result
;
1380 result
= (reduce_outer_joins_state
*)
1381 palloc(sizeof(reduce_outer_joins_state
));
1382 result
->relids
= NULL
;
1383 result
->contains_outer
= false;
1384 result
->sub_states
= NIL
;
1388 if (IsA(jtnode
, RangeTblRef
))
1390 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
1392 result
->relids
= bms_make_singleton(varno
);
1394 else if (IsA(jtnode
, FromExpr
))
1396 FromExpr
*f
= (FromExpr
*) jtnode
;
1399 foreach(l
, f
->fromlist
)
1401 reduce_outer_joins_state
*sub_state
;
1403 sub_state
= reduce_outer_joins_pass1(lfirst(l
));
1404 result
->relids
= bms_add_members(result
->relids
,
1406 result
->contains_outer
|= sub_state
->contains_outer
;
1407 result
->sub_states
= lappend(result
->sub_states
, sub_state
);
1410 else if (IsA(jtnode
, JoinExpr
))
1412 JoinExpr
*j
= (JoinExpr
*) jtnode
;
1413 reduce_outer_joins_state
*sub_state
;
1415 /* join's own RT index is not wanted in result->relids */
1416 if (IS_OUTER_JOIN(j
->jointype
))
1417 result
->contains_outer
= true;
1419 sub_state
= reduce_outer_joins_pass1(j
->larg
);
1420 result
->relids
= bms_add_members(result
->relids
,
1422 result
->contains_outer
|= sub_state
->contains_outer
;
1423 result
->sub_states
= lappend(result
->sub_states
, sub_state
);
1425 sub_state
= reduce_outer_joins_pass1(j
->rarg
);
1426 result
->relids
= bms_add_members(result
->relids
,
1428 result
->contains_outer
|= sub_state
->contains_outer
;
1429 result
->sub_states
= lappend(result
->sub_states
, sub_state
);
1432 elog(ERROR
, "unrecognized node type: %d",
1433 (int) nodeTag(jtnode
));
1438 * reduce_outer_joins_pass2 - phase 2 processing
1440 * jtnode: current jointree node
1441 * state: state data collected by phase 1 for this node
1442 * root: toplevel planner state
1443 * nonnullable_rels: set of base relids forced non-null by upper quals
1444 * nonnullable_vars: list of Vars forced non-null by upper quals
1445 * forced_null_vars: list of Vars forced null by upper quals
1448 reduce_outer_joins_pass2(Node
*jtnode
,
1449 reduce_outer_joins_state
*state
,
1451 Relids nonnullable_rels
,
1452 List
*nonnullable_vars
,
1453 List
*forced_null_vars
)
1456 * pass 2 should never descend as far as an empty subnode or base rel,
1457 * because it's only called on subtrees marked as contains_outer.
1460 elog(ERROR
, "reached empty jointree");
1461 if (IsA(jtnode
, RangeTblRef
))
1462 elog(ERROR
, "reached base rel");
1463 else if (IsA(jtnode
, FromExpr
))
1465 FromExpr
*f
= (FromExpr
*) jtnode
;
1468 Relids pass_nonnullable_rels
;
1469 List
*pass_nonnullable_vars
;
1470 List
*pass_forced_null_vars
;
1472 /* Scan quals to see if we can add any constraints */
1473 pass_nonnullable_rels
= find_nonnullable_rels(f
->quals
);
1474 pass_nonnullable_rels
= bms_add_members(pass_nonnullable_rels
,
1476 /* NB: we rely on list_concat to not damage its second argument */
1477 pass_nonnullable_vars
= find_nonnullable_vars(f
->quals
);
1478 pass_nonnullable_vars
= list_concat(pass_nonnullable_vars
,
1480 pass_forced_null_vars
= find_forced_null_vars(f
->quals
);
1481 pass_forced_null_vars
= list_concat(pass_forced_null_vars
,
1483 /* And recurse --- but only into interesting subtrees */
1484 Assert(list_length(f
->fromlist
) == list_length(state
->sub_states
));
1485 forboth(l
, f
->fromlist
, s
, state
->sub_states
)
1487 reduce_outer_joins_state
*sub_state
= lfirst(s
);
1489 if (sub_state
->contains_outer
)
1490 reduce_outer_joins_pass2(lfirst(l
), sub_state
, root
,
1491 pass_nonnullable_rels
,
1492 pass_nonnullable_vars
,
1493 pass_forced_null_vars
);
1495 bms_free(pass_nonnullable_rels
);
1496 /* can't so easily clean up var lists, unfortunately */
1498 else if (IsA(jtnode
, JoinExpr
))
1500 JoinExpr
*j
= (JoinExpr
*) jtnode
;
1501 int rtindex
= j
->rtindex
;
1502 JoinType jointype
= j
->jointype
;
1503 reduce_outer_joins_state
*left_state
= linitial(state
->sub_states
);
1504 reduce_outer_joins_state
*right_state
= lsecond(state
->sub_states
);
1505 List
*local_nonnullable_vars
= NIL
;
1506 bool computed_local_nonnullable_vars
= false;
1508 /* Can we simplify this join? */
1514 if (bms_overlap(nonnullable_rels
, right_state
->relids
))
1515 jointype
= JOIN_INNER
;
1518 if (bms_overlap(nonnullable_rels
, left_state
->relids
))
1519 jointype
= JOIN_INNER
;
1522 if (bms_overlap(nonnullable_rels
, left_state
->relids
))
1524 if (bms_overlap(nonnullable_rels
, right_state
->relids
))
1525 jointype
= JOIN_INNER
;
1527 jointype
= JOIN_LEFT
;
1531 if (bms_overlap(nonnullable_rels
, right_state
->relids
))
1532 jointype
= JOIN_RIGHT
;
1539 * These could only have been introduced by pull_up_sublinks,
1540 * so there's no way that upper quals could refer to their
1541 * righthand sides, and no point in checking.
1545 elog(ERROR
, "unrecognized join type: %d",
1551 * Convert JOIN_RIGHT to JOIN_LEFT. Note that in the case where we
1552 * reduced JOIN_FULL to JOIN_RIGHT, this will mean the JoinExpr no
1553 * longer matches the internal ordering of any CoalesceExpr's built to
1554 * represent merged join variables. We don't care about that at
1555 * present, but be wary of it ...
1557 if (jointype
== JOIN_RIGHT
)
1564 jointype
= JOIN_LEFT
;
1565 right_state
= linitial(state
->sub_states
);
1566 left_state
= lsecond(state
->sub_states
);
1570 * See if we can reduce JOIN_LEFT to JOIN_ANTI. This is the case if
1571 * the join's own quals are strict for any var that was forced null by
1572 * higher qual levels. NOTE: there are other ways that we could
1573 * detect an anti-join, in particular if we were to check whether Vars
1574 * coming from the RHS must be non-null because of table constraints.
1575 * That seems complicated and expensive though (in particular, one
1576 * would have to be wary of lower outer joins). For the moment this
1579 if (jointype
== JOIN_LEFT
)
1583 local_nonnullable_vars
= find_nonnullable_vars(j
->quals
);
1584 computed_local_nonnullable_vars
= true;
1587 * It's not sufficient to check whether local_nonnullable_vars and
1588 * forced_null_vars overlap: we need to know if the overlap
1589 * includes any RHS variables.
1591 overlap
= list_intersection(local_nonnullable_vars
,
1593 if (overlap
!= NIL
&&
1594 bms_overlap(pull_varnos((Node
*) overlap
),
1595 right_state
->relids
))
1596 jointype
= JOIN_ANTI
;
1599 /* Apply the jointype change, if any, to both jointree node and RTE */
1600 if (rtindex
&& jointype
!= j
->jointype
)
1602 RangeTblEntry
*rte
= rt_fetch(rtindex
, root
->parse
->rtable
);
1604 Assert(rte
->rtekind
== RTE_JOIN
);
1605 Assert(rte
->jointype
== j
->jointype
);
1606 rte
->jointype
= jointype
;
1608 j
->jointype
= jointype
;
1610 /* Only recurse if there's more to do below here */
1611 if (left_state
->contains_outer
|| right_state
->contains_outer
)
1613 Relids local_nonnullable_rels
;
1614 List
*local_forced_null_vars
;
1615 Relids pass_nonnullable_rels
;
1616 List
*pass_nonnullable_vars
;
1617 List
*pass_forced_null_vars
;
1620 * If this join is (now) inner, we can add any constraints its
1621 * quals provide to those we got from above. But if it is outer,
1622 * we can pass down the local constraints only into the nullable
1623 * side, because an outer join never eliminates any rows from its
1624 * non-nullable side. Also, there is no point in passing upper
1625 * constraints into the nullable side, since if there were any
1626 * we'd have been able to reduce the join. (In the case of upper
1627 * forced-null constraints, we *must not* pass them into the
1628 * nullable side --- they either applied here, or not.) The upshot
1629 * is that we pass either the local or the upper constraints,
1630 * never both, to the children of an outer join.
1632 * At a FULL join we just punt and pass nothing down --- is it
1633 * possible to be smarter?
1635 if (jointype
!= JOIN_FULL
)
1637 local_nonnullable_rels
= find_nonnullable_rels(j
->quals
);
1638 if (!computed_local_nonnullable_vars
)
1639 local_nonnullable_vars
= find_nonnullable_vars(j
->quals
);
1640 local_forced_null_vars
= find_forced_null_vars(j
->quals
);
1641 if (jointype
== JOIN_INNER
)
1643 /* OK to merge upper and local constraints */
1644 local_nonnullable_rels
= bms_add_members(local_nonnullable_rels
,
1646 local_nonnullable_vars
= list_concat(local_nonnullable_vars
,
1648 local_forced_null_vars
= list_concat(local_forced_null_vars
,
1654 /* no use in calculating these */
1655 local_nonnullable_rels
= NULL
;
1656 local_forced_null_vars
= NIL
;
1659 if (left_state
->contains_outer
)
1661 if (jointype
== JOIN_INNER
)
1663 /* pass union of local and upper constraints */
1664 pass_nonnullable_rels
= local_nonnullable_rels
;
1665 pass_nonnullable_vars
= local_nonnullable_vars
;
1666 pass_forced_null_vars
= local_forced_null_vars
;
1668 else if (jointype
!= JOIN_FULL
) /* ie, LEFT/SEMI/ANTI */
1670 /* can't pass local constraints to non-nullable side */
1671 pass_nonnullable_rels
= nonnullable_rels
;
1672 pass_nonnullable_vars
= nonnullable_vars
;
1673 pass_forced_null_vars
= forced_null_vars
;
1677 /* no constraints pass through JOIN_FULL */
1678 pass_nonnullable_rels
= NULL
;
1679 pass_nonnullable_vars
= NIL
;
1680 pass_forced_null_vars
= NIL
;
1682 reduce_outer_joins_pass2(j
->larg
, left_state
, root
,
1683 pass_nonnullable_rels
,
1684 pass_nonnullable_vars
,
1685 pass_forced_null_vars
);
1688 if (right_state
->contains_outer
)
1690 if (jointype
!= JOIN_FULL
) /* ie, INNER/LEFT/SEMI/ANTI */
1692 /* pass appropriate constraints, per comment above */
1693 pass_nonnullable_rels
= local_nonnullable_rels
;
1694 pass_nonnullable_vars
= local_nonnullable_vars
;
1695 pass_forced_null_vars
= local_forced_null_vars
;
1699 /* no constraints pass through JOIN_FULL */
1700 pass_nonnullable_rels
= NULL
;
1701 pass_nonnullable_vars
= NIL
;
1702 pass_forced_null_vars
= NIL
;
1704 reduce_outer_joins_pass2(j
->rarg
, right_state
, root
,
1705 pass_nonnullable_rels
,
1706 pass_nonnullable_vars
,
1707 pass_forced_null_vars
);
1709 bms_free(local_nonnullable_rels
);
1713 elog(ERROR
, "unrecognized node type: %d",
1714 (int) nodeTag(jtnode
));
1718 * substitute_multiple_relids - adjust node relid sets after pulling up
1721 * Find any PlaceHolderVar nodes in the given tree that reference the
1722 * pulled-up relid, and change them to reference the replacement relid(s).
1723 * We do not need to recurse into subqueries, since no subquery of the current
1724 * top query could (yet) contain such a reference.
1726 * NOTE: although this has the form of a walker, we cheat and modify the
1727 * nodes in-place. This should be OK since the tree was copied by ResolveNew
1728 * earlier. Avoid scribbling on the original values of the bitmapsets, though,
1729 * because expression_tree_mutator doesn't copy those.
1736 } substitute_multiple_relids_context
;
1739 substitute_multiple_relids_walker(Node
*node
,
1740 substitute_multiple_relids_context
*context
)
1744 if (IsA(node
, PlaceHolderVar
))
1746 PlaceHolderVar
*phv
= (PlaceHolderVar
*) node
;
1748 if (bms_is_member(context
->varno
, phv
->phrels
))
1750 phv
->phrels
= bms_union(phv
->phrels
,
1751 context
->subrelids
);
1752 phv
->phrels
= bms_del_member(phv
->phrels
,
1755 /* fall through to examine children */
1757 /* Shouldn't need to handle planner auxiliary nodes here */
1758 Assert(!IsA(node
, SpecialJoinInfo
));
1759 Assert(!IsA(node
, AppendRelInfo
));
1760 Assert(!IsA(node
, PlaceHolderInfo
));
1762 return expression_tree_walker(node
, substitute_multiple_relids_walker
,
1767 substitute_multiple_relids(Node
*node
, int varno
, Relids subrelids
)
1769 substitute_multiple_relids_context context
;
1771 context
.varno
= varno
;
1772 context
.subrelids
= subrelids
;
1775 * Must be prepared to start with a Query or a bare expression tree.
1777 query_or_expression_tree_walker(node
,
1778 substitute_multiple_relids_walker
,
1784 * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
1786 * When we pull up a subquery, any AppendRelInfo references to the subquery's
1787 * RT index have to be replaced by the substituted relid (and there had better
1788 * be only one). We also need to apply substitute_multiple_relids to their
1789 * translated_vars lists, since those might contain PlaceHolderVars.
1791 * We assume we may modify the AppendRelInfo nodes in-place.
1794 fix_append_rel_relids(List
*append_rel_list
, int varno
, Relids subrelids
)
1800 * We only want to extract the member relid once, but we mustn't fail
1801 * immediately if there are multiple members; it could be that none of the
1802 * AppendRelInfo nodes refer to it. So compute it on first use. Note that
1803 * bms_singleton_member will complain if set is not singleton.
1805 foreach(l
, append_rel_list
)
1807 AppendRelInfo
*appinfo
= (AppendRelInfo
*) lfirst(l
);
1809 /* The parent_relid shouldn't ever be a pullup target */
1810 Assert(appinfo
->parent_relid
!= varno
);
1812 if (appinfo
->child_relid
== varno
)
1815 subvarno
= bms_singleton_member(subrelids
);
1816 appinfo
->child_relid
= subvarno
;
1819 /* Also finish fixups for its translated vars */
1820 substitute_multiple_relids((Node
*) appinfo
->translated_vars
,
1826 * get_relids_in_jointree: get set of RT indexes present in a jointree
1828 * If include_joins is true, join RT indexes are included; if false,
1829 * only base rels are included.
1832 get_relids_in_jointree(Node
*jtnode
, bool include_joins
)
1834 Relids result
= NULL
;
1838 if (IsA(jtnode
, RangeTblRef
))
1840 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
1842 result
= bms_make_singleton(varno
);
1844 else if (IsA(jtnode
, FromExpr
))
1846 FromExpr
*f
= (FromExpr
*) jtnode
;
1849 foreach(l
, f
->fromlist
)
1851 result
= bms_join(result
,
1852 get_relids_in_jointree(lfirst(l
),
1856 else if (IsA(jtnode
, JoinExpr
))
1858 JoinExpr
*j
= (JoinExpr
*) jtnode
;
1860 result
= get_relids_in_jointree(j
->larg
, include_joins
);
1861 result
= bms_join(result
,
1862 get_relids_in_jointree(j
->rarg
, include_joins
));
1863 if (include_joins
&& j
->rtindex
)
1864 result
= bms_add_member(result
, j
->rtindex
);
1867 elog(ERROR
, "unrecognized node type: %d",
1868 (int) nodeTag(jtnode
));
1873 * get_relids_for_join: get set of base RT indexes making up a join
1876 get_relids_for_join(PlannerInfo
*root
, int joinrelid
)
1880 jtnode
= find_jointree_node_for_rel((Node
*) root
->parse
->jointree
,
1883 elog(ERROR
, "could not find join node %d", joinrelid
);
1884 return get_relids_in_jointree(jtnode
, false);
1888 * find_jointree_node_for_rel: locate jointree node for a base or join RT index
1890 * Returns NULL if not found
1893 find_jointree_node_for_rel(Node
*jtnode
, int relid
)
1897 if (IsA(jtnode
, RangeTblRef
))
1899 int varno
= ((RangeTblRef
*) jtnode
)->rtindex
;
1904 else if (IsA(jtnode
, FromExpr
))
1906 FromExpr
*f
= (FromExpr
*) jtnode
;
1909 foreach(l
, f
->fromlist
)
1911 jtnode
= find_jointree_node_for_rel(lfirst(l
), relid
);
1916 else if (IsA(jtnode
, JoinExpr
))
1918 JoinExpr
*j
= (JoinExpr
*) jtnode
;
1920 if (relid
== j
->rtindex
)
1922 jtnode
= find_jointree_node_for_rel(j
->larg
, relid
);
1925 jtnode
= find_jointree_node_for_rel(j
->rarg
, relid
);
1930 elog(ERROR
, "unrecognized node type: %d",
1931 (int) nodeTag(jtnode
));