1 /*-------------------------------------------------------------------------
4 * Planner preprocessing for subqueries and join tree manipulation.
6 * NOTE: the intended sequence for invoking these operations is
9 * do expression preprocessing (including flattening JOIN alias vars)
13 * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
14 * Portions Copyright (c) 1994, Regents of the University of California
18 * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.45 2007/01/05 22:19:32 momjian Exp $
20 *-------------------------------------------------------------------------
24 #include "nodes/makefuncs.h"
25 #include "optimizer/clauses.h"
26 #include "optimizer/prep.h"
27 #include "optimizer/subselect.h"
28 #include "optimizer/tlist.h"
29 #include "optimizer/var.h"
30 #include "parser/parse_expr.h"
31 #include "parser/parsetree.h"
32 #include "rewrite/rewriteManip.h"
35 typedef struct reduce_outer_joins_state
37 Relids relids; /* base relids within this subtree */
38 bool contains_outer; /* does subtree contain outer join(s)? */
39 List *sub_states; /* List of states for subtree components */
40 } reduce_outer_joins_state;
42 static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
44 bool below_outer_join,
45 bool append_rel_member);
46 static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
48 static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
49 int parentRTindex, Query *setOpQuery);
50 static void make_setop_translation_lists(Query *query,
52 List **col_mappings, List **translated_vars);
53 static bool is_simple_subquery(Query *subquery);
54 static bool is_simple_union_all(Query *subquery);
55 static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
57 static bool has_nullable_targetlist(Query *subquery);
58 static bool is_safe_append_member(Query *subquery);
59 static void resolvenew_in_jointree(Node *jtnode, int varno,
60 RangeTblEntry *rte, List *subtlist);
61 static reduce_outer_joins_state *reduce_outer_joins_pass1(Node *jtnode);
62 static void reduce_outer_joins_pass2(Node *jtnode,
63 reduce_outer_joins_state *state,
65 Relids nonnullable_rels);
66 static void fix_in_clause_relids(List *in_info_list, int varno,
68 static void fix_append_rel_relids(List *append_rel_list, int varno,
70 static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
75 * Attempt to pull up top-level IN clauses to be treated like joins.
77 * A clause "foo IN (sub-SELECT)" appearing at the top level of WHERE can
78 * be processed by pulling the sub-SELECT up to become a rangetable entry
79 * and handling the implied equality comparisons as join operators (with
80 * special join rules).
81 * This optimization *only* works at the top level of WHERE, because
82 * it cannot distinguish whether the IN ought to return FALSE or NULL in
83 * cases involving NULL inputs. This routine searches for such clauses
84 * and does the necessary parsetree transformations if any are found.
86 * This routine has to run before preprocess_expression(), so the WHERE
87 * clause is not yet reduced to implicit-AND format. That means we need
88 * to recursively search through explicit AND clauses, which are
89 * probably only binary ANDs. We stop as soon as we hit a non-AND item.
91 * Returns the possibly-modified version of the given qual-tree node.
94 pull_up_IN_clauses(PlannerInfo *root, Node *node)
98 if (IsA(node, SubLink))
100 SubLink *sublink = (SubLink *) node;
103 /* Is it a convertible IN clause? If not, return it as-is */
104 subst = convert_IN_to_join(root, sublink);
109 if (and_clause(node))
111 List *newclauses = NIL;
114 foreach(l, ((BoolExpr *) node)->args)
116 Node *oldclause = (Node *) lfirst(l);
118 newclauses = lappend(newclauses,
119 pull_up_IN_clauses(root, oldclause));
121 return (Node *) make_andclause(newclauses);
123 /* Stop if not an AND */
129 * Look for subqueries in the rangetable that can be pulled up into
130 * the parent query. If the subquery has no special features like
131 * grouping/aggregation then we can merge it into the parent's jointree.
132 * Also, subqueries that are simple UNION ALL structures can be
133 * converted into "append relations".
135 * below_outer_join is true if this jointree node is within the nullable
136 * side of an outer join. This restricts what we can do.
138 * append_rel_member is true if we are looking at a member subquery of
139 * an append relation. This puts some different restrictions on what
142 * A tricky aspect of this code is that if we pull up a subquery we have
143 * to replace Vars that reference the subquery's outputs throughout the
144 * parent query, including quals attached to jointree nodes above the one
145 * we are currently processing! We handle this by being careful not to
146 * change the jointree structure while recursing: no nodes other than
147 * subquery RangeTblRef entries will be replaced. Also, we can't turn
148 * ResolveNew loose on the whole jointree, because it'll return a mutated
149 * copy of the tree; we have to invoke it just on the quals, instead.
152 pull_up_subqueries(PlannerInfo *root, Node *jtnode,
153 bool below_outer_join, bool append_rel_member)
157 if (IsA(jtnode, RangeTblRef))
159 int varno = ((RangeTblRef *) jtnode)->rtindex;
160 RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);
163 * Is this a subquery RTE, and if so, is the subquery simple enough to
164 * pull up? (If not, do nothing at this node.)
166 * If we are inside an outer join, only pull up subqueries whose
167 * targetlists are nullable --- otherwise substituting their tlist
168 * entries for upper Var references would do the wrong thing (the
169 * results wouldn't become NULL when they're supposed to).
171 * XXX This could be improved by generating pseudo-variables for such
172 * expressions; we'd have to figure out how to get the pseudo-
173 * variables evaluated at the right place in the modified plan tree.
176 * If we are looking at an append-relation member, we can't pull it up
177 * unless is_safe_append_member says so.
179 if (rte->rtekind == RTE_SUBQUERY &&
180 is_simple_subquery(rte->subquery) &&
181 (!below_outer_join || has_nullable_targetlist(rte->subquery)) &&
182 (!append_rel_member || is_safe_append_member(rte->subquery)))
183 return pull_up_simple_subquery(root, jtnode, rte,
188 * Alternatively, is it a simple UNION ALL subquery? If so, flatten
189 * into an "append relation". We can do this regardless of
190 * nullability considerations since this transformation does not
191 * result in propagating non-Var expressions into upper levels of the
194 * It's also safe to do this regardless of whether this query is
195 * itself an appendrel member. (If you're thinking we should try to
196 * flatten the two levels of appendrel together, you're right; but we
197 * handle that in set_append_rel_pathlist, not here.)
199 if (rte->rtekind == RTE_SUBQUERY &&
200 is_simple_union_all(rte->subquery))
201 return pull_up_simple_union_all(root, jtnode, rte);
203 else if (IsA(jtnode, FromExpr))
205 FromExpr *f = (FromExpr *) jtnode;
208 Assert(!append_rel_member);
209 foreach(l, f->fromlist)
210 lfirst(l) = pull_up_subqueries(root, lfirst(l),
211 below_outer_join, false);
213 else if (IsA(jtnode, JoinExpr))
215 JoinExpr *j = (JoinExpr *) jtnode;
217 Assert(!append_rel_member);
218 /* Recurse, being careful to tell myself when inside outer join */
222 j->larg = pull_up_subqueries(root, j->larg,
223 below_outer_join, false);
224 j->rarg = pull_up_subqueries(root, j->rarg,
225 below_outer_join, false);
228 j->larg = pull_up_subqueries(root, j->larg,
229 below_outer_join, false);
230 j->rarg = pull_up_subqueries(root, j->rarg,
234 j->larg = pull_up_subqueries(root, j->larg,
236 j->rarg = pull_up_subqueries(root, j->rarg,
240 j->larg = pull_up_subqueries(root, j->larg,
242 j->rarg = pull_up_subqueries(root, j->rarg,
243 below_outer_join, false);
246 elog(ERROR, "unrecognized join type: %d",
252 elog(ERROR, "unrecognized node type: %d",
253 (int) nodeTag(jtnode));
258 * pull_up_simple_subquery
259 * Attempt to pull up a single simple subquery.
261 * jtnode is a RangeTblRef that has been tentatively identified as a simple
262 * subquery by pull_up_subqueries. We return the replacement jointree node,
263 * or jtnode itself if we determine that the subquery can't be pulled up after
267 pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
268 bool below_outer_join, bool append_rel_member)
270 Query *parse = root->parse;
271 int varno = ((RangeTblRef *) jtnode)->rtindex;
273 PlannerInfo *subroot;
279 * Need a modifiable copy of the subquery to hack on. Even if we didn't
280 * sometimes choose not to pull up below, we must do this to avoid
281 * problems if the same subquery is referenced from multiple jointree
282 * items (which can't happen normally, but might after rule rewriting).
284 subquery = copyObject(rte->subquery);
287 * Create a PlannerInfo data structure for this subquery.
289 * NOTE: the next few steps should match the first processing in
290 * subquery_planner(). Can we refactor to avoid code duplication, or
291 * would that just make things uglier?
293 subroot = makeNode(PlannerInfo);
294 subroot->parse = subquery;
295 subroot->in_info_list = NIL;
296 subroot->append_rel_list = NIL;
299 * Pull up any IN clauses within the subquery's WHERE, so that we don't
300 * leave unoptimized INs behind.
302 if (subquery->hasSubLinks)
303 subquery->jointree->quals = pull_up_IN_clauses(subroot,
304 subquery->jointree->quals);
307 * Recursively pull up the subquery's subqueries, so that
308 * pull_up_subqueries' processing is complete for its jointree and
311 * Note: below_outer_join = false is correct here even if we are within an
312 * outer join in the upper query; the lower query starts with a clean
313 * slate for outer-join semantics. Likewise, we say we aren't handling an
316 subquery->jointree = (FromExpr *)
317 pull_up_subqueries(subroot, (Node *) subquery->jointree, false, false);
320 * Now we must recheck whether the subquery is still simple enough to pull
321 * up. If not, abandon processing it.
323 * We don't really need to recheck all the conditions involved, but it's
324 * easier just to keep this "if" looking the same as the one in
325 * pull_up_subqueries.
327 if (is_simple_subquery(subquery) &&
328 (!below_outer_join || has_nullable_targetlist(subquery)) &&
329 (!append_rel_member || is_safe_append_member(subquery)))
336 * Give up, return unmodified RangeTblRef.
338 * Note: The work we just did will be redone when the subquery gets
339 * planned on its own. Perhaps we could avoid that by storing the
340 * modified subquery back into the rangetable, but I'm not gonna risk
347 * Adjust level-0 varnos in subquery so that we can append its rangetable
348 * to upper query's. We have to fix the subquery's in_info_list and
349 * append_rel_list, as well.
351 rtoffset = list_length(parse->rtable);
352 OffsetVarNodes((Node *) subquery, rtoffset, 0);
353 OffsetVarNodes((Node *) subroot->in_info_list, rtoffset, 0);
354 OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
357 * Upper-level vars in subquery are now one level closer to their parent
360 IncrementVarSublevelsUp((Node *) subquery, -1, 1);
361 IncrementVarSublevelsUp((Node *) subroot->in_info_list, -1, 1);
362 IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
365 * Replace all of the top query's references to the subquery's outputs
366 * with copies of the adjusted subtlist items, being careful not to
367 * replace any of the jointree structure. (This'd be a lot cleaner if we
368 * could use query_tree_mutator.)
370 subtlist = subquery->targetList;
371 parse->targetList = (List *)
372 ResolveNew((Node *) parse->targetList,
374 subtlist, CMD_SELECT, 0);
375 parse->returningList = (List *)
376 ResolveNew((Node *) parse->returningList,
378 subtlist, CMD_SELECT, 0);
379 resolvenew_in_jointree((Node *) parse->jointree, varno,
381 Assert(parse->setOperations == NULL);
383 ResolveNew(parse->havingQual,
385 subtlist, CMD_SELECT, 0);
386 root->in_info_list = (List *)
387 ResolveNew((Node *) root->in_info_list,
389 subtlist, CMD_SELECT, 0);
390 root->append_rel_list = (List *)
391 ResolveNew((Node *) root->append_rel_list,
393 subtlist, CMD_SELECT, 0);
395 foreach(rt, parse->rtable)
397 RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(rt);
399 if (otherrte->rtekind == RTE_JOIN)
400 otherrte->joinaliasvars = (List *)
401 ResolveNew((Node *) otherrte->joinaliasvars,
403 subtlist, CMD_SELECT, 0);
407 * Now append the adjusted rtable entries to upper query. (We hold off
408 * until after fixing the upper rtable entries; no point in running that
409 * code on the subquery ones too.)
411 parse->rtable = list_concat(parse->rtable, subquery->rtable);
414 * Pull up any FOR UPDATE/SHARE markers, too. (OffsetVarNodes already
415 * adjusted the marker rtindexes, so just concat the lists.)
417 parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
420 * We also have to fix the relid sets of any parent InClauseInfo nodes.
421 * (This could perhaps be done by ResolveNew, but it would clutter that
422 * routine's API unreasonably.)
424 * Likewise, relids appearing in AppendRelInfo nodes have to be fixed (but
425 * we took care of their translated_vars lists above). We already checked
426 * that this won't require introducing multiple subrelids into the
427 * single-slot AppendRelInfo structs.
429 if (root->in_info_list || root->append_rel_list)
433 subrelids = get_relids_in_jointree((Node *) subquery->jointree);
434 fix_in_clause_relids(root->in_info_list, varno, subrelids);
435 fix_append_rel_relids(root->append_rel_list, varno, subrelids);
439 * And now add any subquery InClauseInfos and AppendRelInfos to our lists.
441 root->in_info_list = list_concat(root->in_info_list,
442 subroot->in_info_list);
443 root->append_rel_list = list_concat(root->append_rel_list,
444 subroot->append_rel_list);
447 * We don't have to do the equivalent bookkeeping for outer-join info,
448 * because that hasn't been set up yet.
450 Assert(root->oj_info_list == NIL);
451 Assert(subroot->oj_info_list == NIL);
454 * Miscellaneous housekeeping.
456 parse->hasSubLinks |= subquery->hasSubLinks;
457 /* subquery won't be pulled up if it hasAggs, so no work there */
460 * Return the adjusted subquery jointree to replace the RangeTblRef entry
461 * in parent's jointree.
463 return (Node *) subquery->jointree;
467 * pull_up_simple_union_all
468 * Pull up a single simple UNION ALL subquery.
470 * jtnode is a RangeTblRef that has been identified as a simple UNION ALL
471 * subquery by pull_up_subqueries. We pull up the leaf subqueries and
472 * build an "append relation" for the union set. The result value is just
473 * jtnode, since we don't actually need to change the query jointree.
476 pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
478 int varno = ((RangeTblRef *) jtnode)->rtindex;
479 Query *subquery = rte->subquery;
482 * Recursively scan the subquery's setOperations tree and copy the leaf
483 * subqueries into the parent rangetable. Add AppendRelInfo nodes for
484 * them to the parent's append_rel_list, too.
486 Assert(subquery->setOperations);
487 pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery);
490 * Mark the parent as an append relation.
498 * pull_up_union_leaf_queries -- recursive guts of pull_up_simple_union_all
500 * Note that setOpQuery is the Query containing the setOp node, whose rtable
501 * is where to look up the RTE if setOp is a RangeTblRef. This is *not* the
502 * same as root->parse, which is the top-level Query we are pulling up into.
503 * parentRTindex is the appendrel parent's index in root->parse->rtable.
506 pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
509 if (IsA(setOp, RangeTblRef))
511 RangeTblRef *rtr = (RangeTblRef *) setOp;
512 RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
515 AppendRelInfo *appinfo;
516 Query *parse = root->parse;
519 * Make a modifiable copy of the child RTE and contained query.
521 rte = copyObject(rte);
522 subquery = rte->subquery;
523 Assert(subquery != NULL);
526 * Upper-level vars in subquery are now one level closer to their
527 * parent than before. We don't have to worry about offsetting
528 * varnos, though, because any such vars must refer to stuff above the
529 * level of the query we are pulling into.
531 IncrementVarSublevelsUp((Node *) subquery, -1, 1);
534 * Attach child RTE to parent rtable.
536 parse->rtable = lappend(parse->rtable, rte);
537 childRTindex = list_length(parse->rtable);
540 * Build a suitable AppendRelInfo, and attach to parent's list.
542 appinfo = makeNode(AppendRelInfo);
543 appinfo->parent_relid = parentRTindex;
544 appinfo->child_relid = childRTindex;
545 appinfo->parent_reltype = InvalidOid;
546 appinfo->child_reltype = InvalidOid;
547 make_setop_translation_lists(setOpQuery, childRTindex,
548 &appinfo->col_mappings,
549 &appinfo->translated_vars);
550 appinfo->parent_reloid = InvalidOid;
551 root->append_rel_list = lappend(root->append_rel_list, appinfo);
554 * Recursively apply pull_up_subqueries to the new child RTE. (We
555 * must build the AppendRelInfo first, because this will modify it.)
556 * Note that we can pass below_outer_join = false even if we're
557 * actually under an outer join, because the child's expressions
558 * aren't going to propagate up above the join.
560 rtr = makeNode(RangeTblRef);
561 rtr->rtindex = childRTindex;
562 (void) pull_up_subqueries(root, (Node *) rtr, false, true);
564 else if (IsA(setOp, SetOperationStmt))
566 SetOperationStmt *op = (SetOperationStmt *) setOp;
568 /* Recurse to reach leaf queries */
569 pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery);
570 pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery);
574 elog(ERROR, "unrecognized node type: %d",
575 (int) nodeTag(setOp));
580 * make_setop_translation_lists
581 * Build the lists of translations from parent Vars to child Vars for
582 * a UNION ALL member. We need both a column number mapping list
583 * and a list of Vars representing the child columns.
586 make_setop_translation_lists(Query *query,
588 List **col_mappings, List **translated_vars)
594 foreach(l, query->targetList)
596 TargetEntry *tle = (TargetEntry *) lfirst(l);
601 numbers = lappend_int(numbers, tle->resno);
602 vars = lappend(vars, makeVar(newvarno,
604 exprType((Node *) tle->expr),
605 exprTypmod((Node *) tle->expr),
609 *col_mappings = numbers;
610 *translated_vars = vars;
615 * Check a subquery in the range table to see if it's simple enough
616 * to pull up into the parent query.
619 is_simple_subquery(Query *subquery)
622 * Let's just make sure it's a valid subselect ...
624 if (!IsA(subquery, Query) ||
625 subquery->commandType != CMD_SELECT ||
626 subquery->into != NULL)
627 elog(ERROR, "subquery is bogus");
630 * Can't currently pull up a query with setops (unless it's simple UNION
631 * ALL, which is handled by a different code path). Maybe after querytree
634 if (subquery->setOperations)
638 * Can't pull up a subquery involving grouping, aggregation, sorting, or
641 if (subquery->hasAggs ||
642 subquery->groupClause ||
643 subquery->havingQual ||
644 subquery->sortClause ||
645 subquery->distinctClause ||
646 subquery->limitOffset ||
647 subquery->limitCount)
651 * Don't pull up a subquery that has any set-returning functions in its
652 * targetlist. Otherwise we might well wind up inserting set-returning
653 * functions into places where they mustn't go, such as quals of higher
656 if (expression_returns_set((Node *) subquery->targetList))
660 * Don't pull up a subquery that has any volatile functions in its
661 * targetlist. Otherwise we might introduce multiple evaluations of these
662 * functions, if they get copied to multiple places in the upper query,
663 * leading to surprising results.
665 if (contain_volatile_functions((Node *) subquery->targetList))
669 * Hack: don't try to pull up a subquery with an empty jointree.
670 * query_planner() will correctly generate a Result plan for a jointree
671 * that's totally empty, but I don't think the right things happen if an
672 * empty FromExpr appears lower down in a jointree. Not worth working hard
673 * on this, just to collapse SubqueryScan/Result into Result...
675 if (subquery->jointree->fromlist == NIL)
682 * is_simple_union_all
683 * Check a subquery to see if it's a simple UNION ALL.
685 * We require all the setops to be UNION ALL (no mixing) and there can't be
686 * any datatype coercions involved, ie, all the leaf queries must emit the
690 is_simple_union_all(Query *subquery)
692 SetOperationStmt *topop;
694 /* Let's just make sure it's a valid subselect ... */
695 if (!IsA(subquery, Query) ||
696 subquery->commandType != CMD_SELECT ||
697 subquery->into != NULL)
698 elog(ERROR, "subquery is bogus");
700 /* Is it a set-operation query at all? */
701 topop = (SetOperationStmt *) subquery->setOperations;
704 Assert(IsA(topop, SetOperationStmt));
706 /* Can't handle ORDER BY, LIMIT/OFFSET, or locking */
707 if (subquery->sortClause ||
708 subquery->limitOffset ||
709 subquery->limitCount ||
713 /* Recursively check the tree of set operations */
714 return is_simple_union_all_recurse((Node *) topop, subquery,
719 is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
721 if (IsA(setOp, RangeTblRef))
723 RangeTblRef *rtr = (RangeTblRef *) setOp;
724 RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
725 Query *subquery = rte->subquery;
727 Assert(subquery != NULL);
729 /* Leaf nodes are OK if they match the toplevel column types */
730 /* We don't have to compare typmods here */
731 return tlist_same_datatypes(subquery->targetList, colTypes, true);
733 else if (IsA(setOp, SetOperationStmt))
735 SetOperationStmt *op = (SetOperationStmt *) setOp;
737 /* Must be UNION ALL */
738 if (op->op != SETOP_UNION || !op->all)
741 /* Recurse to check inputs */
742 return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) &&
743 is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes);
747 elog(ERROR, "unrecognized node type: %d",
748 (int) nodeTag(setOp));
749 return false; /* keep compiler quiet */
754 * has_nullable_targetlist
755 * Check a subquery in the range table to see if all the non-junk
756 * targetlist items are simple variables or strict functions of simple
757 * variables (and, hence, will correctly go to NULL when examined above
758 * the point of an outer join).
760 * NOTE: it would be correct (and useful) to ignore output columns that aren't
761 * actually referenced by the enclosing query ... but we do not have that
762 * information available at this point.
765 has_nullable_targetlist(Query *subquery)
769 foreach(l, subquery->targetList)
771 TargetEntry *tle = (TargetEntry *) lfirst(l);
773 /* ignore resjunk columns */
777 /* Must contain a Var of current level */
778 if (!contain_vars_of_level((Node *) tle->expr, 0))
781 /* Must not contain any non-strict constructs */
782 if (contain_nonstrict_functions((Node *) tle->expr))
785 /* This one's OK, keep scanning */
791 * is_safe_append_member
792 * Check a subquery that is a leaf of a UNION ALL appendrel to see if it's
796 is_safe_append_member(Query *subquery)
802 * It's only safe to pull up the child if its jointree contains exactly
803 * one RTE, else the AppendRelInfo data structure breaks. The one base RTE
804 * could be buried in several levels of FromExpr, however.
806 * Also, the child can't have any WHERE quals because there's no place to
807 * put them in an appendrel. (This is a bit annoying...) If we didn't
808 * need to check this, we'd just test whether get_relids_in_jointree()
809 * yields a singleton set, to be more consistent with the coding of
810 * fix_append_rel_relids().
812 jtnode = subquery->jointree;
813 while (IsA(jtnode, FromExpr))
815 if (jtnode->quals != NULL)
817 if (list_length(jtnode->fromlist) != 1)
819 jtnode = linitial(jtnode->fromlist);
821 if (!IsA(jtnode, RangeTblRef))
825 * XXX For the moment we also have to insist that the subquery's tlist
826 * includes only simple Vars. This is pretty annoying, but fixing it
827 * seems to require nontrivial changes --- mainly because joinrel tlists
828 * are presently assumed to contain only Vars. Perhaps a pseudo-variable
829 * mechanism similar to the one speculated about in pull_up_subqueries'
830 * comments would help? FIXME someday.
832 foreach(l, subquery->targetList)
834 TargetEntry *tle = (TargetEntry *) lfirst(l);
838 if (!(tle->expr && IsA(tle->expr, Var)))
846 * Helper routine for pull_up_subqueries: do ResolveNew on every expression
847 * in the jointree, without changing the jointree structure itself. Ugly,
848 * but there's no other way...
851 resolvenew_in_jointree(Node *jtnode, int varno,
852 RangeTblEntry *rte, List *subtlist)
856 if (IsA(jtnode, RangeTblRef))
858 /* nothing to do here */
860 else if (IsA(jtnode, FromExpr))
862 FromExpr *f = (FromExpr *) jtnode;
865 foreach(l, f->fromlist)
866 resolvenew_in_jointree(lfirst(l), varno, rte, subtlist);
867 f->quals = ResolveNew(f->quals,
869 subtlist, CMD_SELECT, 0);
871 else if (IsA(jtnode, JoinExpr))
873 JoinExpr *j = (JoinExpr *) jtnode;
875 resolvenew_in_jointree(j->larg, varno, rte, subtlist);
876 resolvenew_in_jointree(j->rarg, varno, rte, subtlist);
877 j->quals = ResolveNew(j->quals,
879 subtlist, CMD_SELECT, 0);
882 * We don't bother to update the colvars list, since it won't be used
887 elog(ERROR, "unrecognized node type: %d",
888 (int) nodeTag(jtnode));
893 * Attempt to reduce outer joins to plain inner joins.
895 * The idea here is that given a query like
896 * SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
897 * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
898 * is strict. The strict operator will always return NULL, causing the outer
899 * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
900 * columns. Therefore, there's no need for the join to produce null-extended
901 * rows in the first place --- which makes it a plain join not an outer join.
902 * (This scenario may not be very likely in a query written out by hand, but
903 * it's reasonably likely when pushing quals down into complex views.)
905 * More generally, an outer join can be reduced in strength if there is a
906 * strict qual above it in the qual tree that constrains a Var from the
907 * nullable side of the join to be non-null. (For FULL joins this applies
908 * to each side separately.)
910 * To ease recognition of strict qual clauses, we require this routine to be
911 * run after expression preprocessing (i.e., qual canonicalization and JOIN
912 * alias-var expansion).
915 reduce_outer_joins(PlannerInfo *root)
917 reduce_outer_joins_state *state;
920 * To avoid doing strictness checks on more quals than necessary, we want
921 * to stop descending the jointree as soon as there are no outer joins
922 * below our current point. This consideration forces a two-pass process.
923 * The first pass gathers information about which base rels appear below
924 * each side of each join clause, and about whether there are outer
925 * join(s) below each side of each join clause. The second pass examines
926 * qual clauses and changes join types as it descends the tree.
928 state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
930 /* planner.c shouldn't have called me if no outer joins */
931 if (state == NULL || !state->contains_outer)
932 elog(ERROR, "so where are the outer joins?");
934 reduce_outer_joins_pass2((Node *) root->parse->jointree,
939 * reduce_outer_joins_pass1 - phase 1 data collection
941 * Returns a state node describing the given jointree node.
943 static reduce_outer_joins_state *
944 reduce_outer_joins_pass1(Node *jtnode)
946 reduce_outer_joins_state *result;
948 result = (reduce_outer_joins_state *)
949 palloc(sizeof(reduce_outer_joins_state));
950 result->relids = NULL;
951 result->contains_outer = false;
952 result->sub_states = NIL;
956 if (IsA(jtnode, RangeTblRef))
958 int varno = ((RangeTblRef *) jtnode)->rtindex;
960 result->relids = bms_make_singleton(varno);
962 else if (IsA(jtnode, FromExpr))
964 FromExpr *f = (FromExpr *) jtnode;
967 foreach(l, f->fromlist)
969 reduce_outer_joins_state *sub_state;
971 sub_state = reduce_outer_joins_pass1(lfirst(l));
972 result->relids = bms_add_members(result->relids,
974 result->contains_outer |= sub_state->contains_outer;
975 result->sub_states = lappend(result->sub_states, sub_state);
978 else if (IsA(jtnode, JoinExpr))
980 JoinExpr *j = (JoinExpr *) jtnode;
981 reduce_outer_joins_state *sub_state;
983 /* join's own RT index is not wanted in result->relids */
984 if (IS_OUTER_JOIN(j->jointype))
985 result->contains_outer = true;
987 sub_state = reduce_outer_joins_pass1(j->larg);
988 result->relids = bms_add_members(result->relids,
990 result->contains_outer |= sub_state->contains_outer;
991 result->sub_states = lappend(result->sub_states, sub_state);
993 sub_state = reduce_outer_joins_pass1(j->rarg);
994 result->relids = bms_add_members(result->relids,
996 result->contains_outer |= sub_state->contains_outer;
997 result->sub_states = lappend(result->sub_states, sub_state);
1000 elog(ERROR, "unrecognized node type: %d",
1001 (int) nodeTag(jtnode));
1006 * reduce_outer_joins_pass2 - phase 2 processing
1008 * jtnode: current jointree node
1009 * state: state data collected by phase 1 for this node
1010 * root: toplevel planner state
1011 * nonnullable_rels: set of base relids forced non-null by upper quals
1014 reduce_outer_joins_pass2(Node *jtnode,
1015 reduce_outer_joins_state *state,
1017 Relids nonnullable_rels)
1020 * pass 2 should never descend as far as an empty subnode or base rel,
1021 * because it's only called on subtrees marked as contains_outer.
1024 elog(ERROR, "reached empty jointree");
1025 if (IsA(jtnode, RangeTblRef))
1026 elog(ERROR, "reached base rel");
1027 else if (IsA(jtnode, FromExpr))
1029 FromExpr *f = (FromExpr *) jtnode;
1032 Relids pass_nonnullable;
1034 /* Scan quals to see if we can add any nonnullability constraints */
1035 pass_nonnullable = find_nonnullable_rels(f->quals);
1036 pass_nonnullable = bms_add_members(pass_nonnullable,
1038 /* And recurse --- but only into interesting subtrees */
1039 Assert(list_length(f->fromlist) == list_length(state->sub_states));
1040 forboth(l, f->fromlist, s, state->sub_states)
1042 reduce_outer_joins_state *sub_state = lfirst(s);
1044 if (sub_state->contains_outer)
1045 reduce_outer_joins_pass2(lfirst(l), sub_state, root,
1048 bms_free(pass_nonnullable);
1050 else if (IsA(jtnode, JoinExpr))
1052 JoinExpr *j = (JoinExpr *) jtnode;
1053 int rtindex = j->rtindex;
1054 JoinType jointype = j->jointype;
1055 reduce_outer_joins_state *left_state = linitial(state->sub_states);
1056 reduce_outer_joins_state *right_state = lsecond(state->sub_states);
1058 /* Can we simplify this join? */
1062 if (bms_overlap(nonnullable_rels, right_state->relids))
1063 jointype = JOIN_INNER;
1066 if (bms_overlap(nonnullable_rels, left_state->relids))
1067 jointype = JOIN_INNER;
1070 if (bms_overlap(nonnullable_rels, left_state->relids))
1072 if (bms_overlap(nonnullable_rels, right_state->relids))
1073 jointype = JOIN_INNER;
1075 jointype = JOIN_LEFT;
1079 if (bms_overlap(nonnullable_rels, right_state->relids))
1080 jointype = JOIN_RIGHT;
1086 if (jointype != j->jointype)
1088 /* apply the change to both jointree node and RTE */
1089 RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
1091 Assert(rte->rtekind == RTE_JOIN);
1092 Assert(rte->jointype == j->jointype);
1093 rte->jointype = j->jointype = jointype;
1096 /* Only recurse if there's more to do below here */
1097 if (left_state->contains_outer || right_state->contains_outer)
1099 Relids local_nonnullable;
1100 Relids pass_nonnullable;
1103 * If this join is (now) inner, we can add any nonnullability
1104 * constraints its quals provide to those we got from above. But
1105 * if it is outer, we can only pass down the local constraints
1106 * into the nullable side, because an outer join never eliminates
1107 * any rows from its non-nullable side. If it's a FULL join then
1108 * it doesn't eliminate anything from either side.
1110 if (jointype != JOIN_FULL)
1112 local_nonnullable = find_nonnullable_rels(j->quals);
1113 local_nonnullable = bms_add_members(local_nonnullable,
1117 local_nonnullable = NULL; /* no use in calculating it */
1119 if (left_state->contains_outer)
1121 if (jointype == JOIN_INNER || jointype == JOIN_RIGHT)
1122 pass_nonnullable = local_nonnullable;
1124 pass_nonnullable = nonnullable_rels;
1125 reduce_outer_joins_pass2(j->larg, left_state, root,
1128 if (right_state->contains_outer)
1130 if (jointype == JOIN_INNER || jointype == JOIN_LEFT)
1131 pass_nonnullable = local_nonnullable;
1133 pass_nonnullable = nonnullable_rels;
1134 reduce_outer_joins_pass2(j->rarg, right_state, root,
1137 bms_free(local_nonnullable);
1141 elog(ERROR, "unrecognized node type: %d",
1142 (int) nodeTag(jtnode));
1146 * fix_in_clause_relids: update RT-index sets of InClauseInfo nodes
1148 * When we pull up a subquery, any InClauseInfo references to the subquery's
1149 * RT index have to be replaced by the set of substituted relids.
1151 * We assume we may modify the InClauseInfo nodes in-place.
1154 fix_in_clause_relids(List *in_info_list, int varno, Relids subrelids)
1158 foreach(l, in_info_list)
1160 InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);
1162 if (bms_is_member(varno, ininfo->lefthand))
1164 ininfo->lefthand = bms_del_member(ininfo->lefthand, varno);
1165 ininfo->lefthand = bms_add_members(ininfo->lefthand, subrelids);
1167 if (bms_is_member(varno, ininfo->righthand))
1169 ininfo->righthand = bms_del_member(ininfo->righthand, varno);
1170 ininfo->righthand = bms_add_members(ininfo->righthand, subrelids);
1176 * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
1178 * When we pull up a subquery, any AppendRelInfo references to the subquery's
1179 * RT index have to be replaced by the substituted relid (and there had better
1182 * We assume we may modify the AppendRelInfo nodes in-place.
1185 fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
1191 * We only want to extract the member relid once, but we mustn't fail
1192 * immediately if there are multiple members; it could be that none of the
1193 * AppendRelInfo nodes refer to it. So compute it on first use. Note that
1194 * bms_singleton_member will complain if set is not singleton.
1196 foreach(l, append_rel_list)
1198 AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
1200 /* The parent_relid shouldn't ever be a pullup target */
1201 Assert(appinfo->parent_relid != varno);
1203 if (appinfo->child_relid == varno)
1206 subvarno = bms_singleton_member(subrelids);
1207 appinfo->child_relid = subvarno;
1213 * get_relids_in_jointree: get set of base RT indexes present in a jointree
1216 get_relids_in_jointree(Node *jtnode)
1218 Relids result = NULL;
1222 if (IsA(jtnode, RangeTblRef))
1224 int varno = ((RangeTblRef *) jtnode)->rtindex;
1226 result = bms_make_singleton(varno);
1228 else if (IsA(jtnode, FromExpr))
1230 FromExpr *f = (FromExpr *) jtnode;
1233 foreach(l, f->fromlist)
1235 result = bms_join(result,
1236 get_relids_in_jointree(lfirst(l)));
1239 else if (IsA(jtnode, JoinExpr))
1241 JoinExpr *j = (JoinExpr *) jtnode;
1243 /* join's own RT index is not wanted in result */
1244 result = get_relids_in_jointree(j->larg);
1245 result = bms_join(result, get_relids_in_jointree(j->rarg));
1248 elog(ERROR, "unrecognized node type: %d",
1249 (int) nodeTag(jtnode));
1254 * get_relids_for_join: get set of base RT indexes making up a join
1257 get_relids_for_join(PlannerInfo *root, int joinrelid)
1261 jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree,
1264 elog(ERROR, "could not find join node %d", joinrelid);
1265 return get_relids_in_jointree(jtnode);
1269 * find_jointree_node_for_rel: locate jointree node for a base or join RT index
1271 * Returns NULL if not found
1274 find_jointree_node_for_rel(Node *jtnode, int relid)
1278 if (IsA(jtnode, RangeTblRef))
1280 int varno = ((RangeTblRef *) jtnode)->rtindex;
1285 else if (IsA(jtnode, FromExpr))
1287 FromExpr *f = (FromExpr *) jtnode;
1290 foreach(l, f->fromlist)
1292 jtnode = find_jointree_node_for_rel(lfirst(l), relid);
1297 else if (IsA(jtnode, JoinExpr))
1299 JoinExpr *j = (JoinExpr *) jtnode;
1301 if (relid == j->rtindex)
1303 jtnode = find_jointree_node_for_rel(j->larg, relid);
1306 jtnode = find_jointree_node_for_rel(j->rarg, relid);
1311 elog(ERROR, "unrecognized node type: %d",
1312 (int) nodeTag(jtnode));