PostgreSQL Source Code  git master
prepjointree.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * prepjointree.c
4  * Planner preprocessing for subqueries and join tree manipulation.
5  *
6  * NOTE: the intended sequence for invoking these operations is
7  * replace_empty_jointree
8  * pull_up_sublinks
9  * preprocess_function_rtes
10  * pull_up_subqueries
11  * flatten_simple_union_all
12  * do expression preprocessing (including flattening JOIN alias vars)
13  * reduce_outer_joins
14  * remove_useless_result_rtes
15  *
16  *
17  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
18  * Portions Copyright (c) 1994, Regents of the University of California
19  *
20  *
21  * IDENTIFICATION
22  * src/backend/optimizer/prep/prepjointree.c
23  *
24  *-------------------------------------------------------------------------
25  */
26 #include "postgres.h"
27 
28 #include "catalog/pg_type.h"
29 #include "funcapi.h"
30 #include "nodes/makefuncs.h"
31 #include "nodes/nodeFuncs.h"
32 #include "optimizer/clauses.h"
33 #include "optimizer/optimizer.h"
34 #include "optimizer/placeholder.h"
35 #include "optimizer/prep.h"
36 #include "optimizer/subselect.h"
37 #include "optimizer/tlist.h"
38 #include "parser/parse_relation.h"
39 #include "parser/parsetree.h"
40 #include "rewrite/rewriteManip.h"
41 
42 
44 {
46  List *targetlist; /* tlist of subquery being pulled up */
47  RangeTblEntry *target_rte; /* RTE of subquery */
48  Relids relids; /* relids within subquery, as numbered after
49  * pullup (set only if target_rte->lateral) */
50  bool *outer_hasSubLinks; /* -> outer query's hasSubLinks */
51  int varno; /* varno of subquery */
52  bool need_phvs; /* do we need PlaceHolderVars? */
53  bool wrap_non_vars; /* do we need 'em on *all* non-Vars? */
54  Node **rv_cache; /* cache for results with PHVs */
56 
58 {
59  Relids relids; /* base relids within this subtree */
60  bool contains_outer; /* does subtree contain outer join(s)? */
61  List *sub_states; /* List of states for subtree components */
63 
65  Relids *relids);
67  Node **jtlink1, Relids available_rels1,
68  Node **jtlink2, Relids available_rels2);
70  JoinExpr *lowest_outer_join,
71  JoinExpr *lowest_nulling_outer_join,
72  AppendRelInfo *containing_appendrel);
74  RangeTblEntry *rte,
75  JoinExpr *lowest_outer_join,
76  JoinExpr *lowest_nulling_outer_join,
77  AppendRelInfo *containing_appendrel);
79  RangeTblEntry *rte);
80 static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
81  int parentRTindex, Query *setOpQuery,
82  int childRToffset);
83 static void make_setop_translation_list(Query *query, Index newvarno,
84  AppendRelInfo *appinfo);
85 static bool is_simple_subquery(PlannerInfo *root, Query *subquery,
86  RangeTblEntry *rte,
87  JoinExpr *lowest_outer_join);
89  RangeTblEntry *rte);
92  RangeTblEntry *rte,
93  JoinExpr *lowest_nulling_outer_join,
94  AppendRelInfo *containing_appendrel);
95 static bool is_simple_union_all(Query *subquery);
96 static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
97  List *colTypes);
98 static bool is_safe_append_member(Query *subquery);
100  Node *jtnode, bool restricted,
101  Relids safe_upper_varnos);
103  pullup_replace_vars_context *rvcontext,
104  JoinExpr *lowest_nulling_outer_join,
105  AppendRelInfo *containing_appendrel);
106 static void replace_vars_in_jointree(Node *jtnode,
108  JoinExpr *lowest_nulling_outer_join);
109 static Node *pullup_replace_vars(Node *expr,
110  pullup_replace_vars_context *context);
114  pullup_replace_vars_context *context);
116 static void reduce_outer_joins_pass2(Node *jtnode,
118  PlannerInfo *root,
119  Relids nonnullable_rels,
120  List *nonnullable_vars,
121  List *forced_null_vars);
123 static int get_result_relid(PlannerInfo *root, Node *jtnode);
124 static void remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc);
125 static bool find_dependent_phvs(PlannerInfo *root, int varno);
127  Node *node, int varno);
128 static void substitute_phv_relids(Node *node,
129  int varno, Relids subrelids);
130 static void fix_append_rel_relids(List *append_rel_list, int varno,
131  Relids subrelids);
132 static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
133 
134 
135 /*
136  * replace_empty_jointree
137  * If the Query's jointree is empty, replace it with a dummy RTE_RESULT
138  * relation.
139  *
140  * By doing this, we can avoid a bunch of corner cases that formerly existed
141  * for SELECTs with omitted FROM clauses. An example is that a subquery
142  * with empty jointree previously could not be pulled up, because that would
143  * have resulted in an empty relid set, making the subquery not uniquely
144  * identifiable for join or PlaceHolderVar processing.
145  *
146  * Unlike most other functions in this file, this function doesn't recurse;
147  * we rely on other processing to invoke it on sub-queries at suitable times.
148  */
149 void
151 {
152  RangeTblEntry *rte;
153  Index rti;
154  RangeTblRef *rtr;
155 
156  /* Nothing to do if jointree is already nonempty */
157  if (parse->jointree->fromlist != NIL)
158  return;
159 
160  /* We mustn't change it in the top level of a setop tree, either */
161  if (parse->setOperations)
162  return;
163 
164  /* Create suitable RTE */
165  rte = makeNode(RangeTblEntry);
166  rte->rtekind = RTE_RESULT;
167  rte->eref = makeAlias("*RESULT*", NIL);
168 
169  /* Add it to rangetable */
170  parse->rtable = lappend(parse->rtable, rte);
171  rti = list_length(parse->rtable);
172 
173  /* And jam a reference into the jointree */
174  rtr = makeNode(RangeTblRef);
175  rtr->rtindex = rti;
176  parse->jointree->fromlist = list_make1(rtr);
177 }
178 
179 /*
180  * pull_up_sublinks
181  * Attempt to pull up ANY and EXISTS SubLinks to be treated as
182  * semijoins or anti-semijoins.
183  *
184  * A clause "foo op ANY (sub-SELECT)" can be processed by pulling the
185  * sub-SELECT up to become a rangetable entry and treating the implied
186  * comparisons as quals of a semijoin. However, this optimization *only*
187  * works at the top level of WHERE or a JOIN/ON clause, because we cannot
188  * distinguish whether the ANY ought to return FALSE or NULL in cases
189  * involving NULL inputs. Also, in an outer join's ON clause we can only
190  * do this if the sublink is degenerate (ie, references only the nullable
191  * side of the join). In that case it is legal to push the semijoin
192  * down into the nullable side of the join. If the sublink references any
193  * nonnullable-side variables then it would have to be evaluated as part
194  * of the outer join, which makes things way too complicated.
195  *
196  * Under similar conditions, EXISTS and NOT EXISTS clauses can be handled
197  * by pulling up the sub-SELECT and creating a semijoin or anti-semijoin.
198  *
199  * This routine searches for such clauses and does the necessary parsetree
200  * transformations if any are found.
201  *
202  * This routine has to run before preprocess_expression(), so the quals
203  * clauses are not yet reduced to implicit-AND format, and are not guaranteed
204  * to be AND/OR-flat either. That means we need to recursively search through
205  * explicit AND clauses. We stop as soon as we hit a non-AND item.
206  */
207 void
209 {
210  Node *jtnode;
211  Relids relids;
212 
213  /* Begin recursion through the jointree */
214  jtnode = pull_up_sublinks_jointree_recurse(root,
215  (Node *) root->parse->jointree,
216  &relids);
217 
218  /*
219  * root->parse->jointree must always be a FromExpr, so insert a dummy one
220  * if we got a bare RangeTblRef or JoinExpr out of the recursion.
221  */
222  if (IsA(jtnode, FromExpr))
223  root->parse->jointree = (FromExpr *) jtnode;
224  else
225  root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
226 }
227 
228 /*
229  * Recurse through jointree nodes for pull_up_sublinks()
230  *
231  * In addition to returning the possibly-modified jointree node, we return
232  * a relids set of the contained rels into *relids.
233  */
234 static Node *
236  Relids *relids)
237 {
238  if (jtnode == NULL)
239  {
240  *relids = NULL;
241  }
242  else if (IsA(jtnode, RangeTblRef))
243  {
244  int varno = ((RangeTblRef *) jtnode)->rtindex;
245 
246  *relids = bms_make_singleton(varno);
247  /* jtnode is returned unmodified */
248  }
249  else if (IsA(jtnode, FromExpr))
250  {
251  FromExpr *f = (FromExpr *) jtnode;
252  List *newfromlist = NIL;
253  Relids frelids = NULL;
254  FromExpr *newf;
255  Node *jtlink;
256  ListCell *l;
257 
258  /* First, recurse to process children and collect their relids */
259  foreach(l, f->fromlist)
260  {
261  Node *newchild;
262  Relids childrelids;
263 
264  newchild = pull_up_sublinks_jointree_recurse(root,
265  lfirst(l),
266  &childrelids);
267  newfromlist = lappend(newfromlist, newchild);
268  frelids = bms_join(frelids, childrelids);
269  }
270  /* Build the replacement FromExpr; no quals yet */
271  newf = makeFromExpr(newfromlist, NULL);
272  /* Set up a link representing the rebuilt jointree */
273  jtlink = (Node *) newf;
274  /* Now process qual --- all children are available for use */
275  newf->quals = pull_up_sublinks_qual_recurse(root, f->quals,
276  &jtlink, frelids,
277  NULL, NULL);
278 
279  /*
280  * Note that the result will be either newf, or a stack of JoinExprs
281  * with newf at the base. We rely on subsequent optimization steps to
282  * flatten this and rearrange the joins as needed.
283  *
284  * Although we could include the pulled-up subqueries in the returned
285  * relids, there's no need since upper quals couldn't refer to their
286  * outputs anyway.
287  */
288  *relids = frelids;
289  jtnode = jtlink;
290  }
291  else if (IsA(jtnode, JoinExpr))
292  {
293  JoinExpr *j;
294  Relids leftrelids;
295  Relids rightrelids;
296  Node *jtlink;
297 
298  /*
299  * Make a modifiable copy of join node, but don't bother copying its
300  * subnodes (yet).
301  */
302  j = (JoinExpr *) palloc(sizeof(JoinExpr));
303  memcpy(j, jtnode, sizeof(JoinExpr));
304  jtlink = (Node *) j;
305 
306  /* Recurse to process children and collect their relids */
308  &leftrelids);
310  &rightrelids);
311 
312  /*
313  * Now process qual, showing appropriate child relids as available,
314  * and attach any pulled-up jointree items at the right place. In the
315  * inner-join case we put new JoinExprs above the existing one (much
316  * as for a FromExpr-style join). In outer-join cases the new
317  * JoinExprs must go into the nullable side of the outer join. The
318  * point of the available_rels machinations is to ensure that we only
319  * pull up quals for which that's okay.
320  *
321  * We don't expect to see any pre-existing JOIN_SEMI or JOIN_ANTI
322  * nodes here.
323  */
324  switch (j->jointype)
325  {
326  case JOIN_INNER:
328  &jtlink,
329  bms_union(leftrelids,
330  rightrelids),
331  NULL, NULL);
332  break;
333  case JOIN_LEFT:
335  &j->rarg,
336  rightrelids,
337  NULL, NULL);
338  break;
339  case JOIN_FULL:
340  /* can't do anything with full-join quals */
341  break;
342  case JOIN_RIGHT:
344  &j->larg,
345  leftrelids,
346  NULL, NULL);
347  break;
348  default:
349  elog(ERROR, "unrecognized join type: %d",
350  (int) j->jointype);
351  break;
352  }
353 
354  /*
355  * Although we could include the pulled-up subqueries in the returned
356  * relids, there's no need since upper quals couldn't refer to their
357  * outputs anyway. But we *do* need to include the join's own rtindex
358  * because we haven't yet collapsed join alias variables, so upper
359  * levels would mistakenly think they couldn't use references to this
360  * join.
361  */
362  *relids = bms_join(leftrelids, rightrelids);
363  if (j->rtindex)
364  *relids = bms_add_member(*relids, j->rtindex);
365  jtnode = jtlink;
366  }
367  else
368  elog(ERROR, "unrecognized node type: %d",
369  (int) nodeTag(jtnode));
370  return jtnode;
371 }
372 
373 /*
374  * Recurse through top-level qual nodes for pull_up_sublinks()
375  *
376  * jtlink1 points to the link in the jointree where any new JoinExprs should
377  * be inserted if they reference available_rels1 (i.e., available_rels1
378  * denotes the relations present underneath jtlink1). Optionally, jtlink2 can
379  * point to a second link where new JoinExprs should be inserted if they
380  * reference available_rels2 (pass NULL for both those arguments if not used).
381  * Note that SubLinks referencing both sets of variables cannot be optimized.
382  * If we find multiple pull-up-able SubLinks, they'll get stacked onto jtlink1
383  * and/or jtlink2 in the order we encounter them. We rely on subsequent
384  * optimization to rearrange the stack if appropriate.
385  *
386  * Returns the replacement qual node, or NULL if the qual should be removed.
387  */
388 static Node *
390  Node **jtlink1, Relids available_rels1,
391  Node **jtlink2, Relids available_rels2)
392 {
393  if (node == NULL)
394  return NULL;
395  if (IsA(node, SubLink))
396  {
397  SubLink *sublink = (SubLink *) node;
398  JoinExpr *j;
399  Relids child_rels;
400 
401  /* Is it a convertible ANY or EXISTS clause? */
402  if (sublink->subLinkType == ANY_SUBLINK)
403  {
404  if ((j = convert_ANY_sublink_to_join(root, sublink,
405  available_rels1)) != NULL)
406  {
407  /* Yes; insert the new join node into the join tree */
408  j->larg = *jtlink1;
409  *jtlink1 = (Node *) j;
410  /* Recursively process pulled-up jointree nodes */
412  j->rarg,
413  &child_rels);
414 
415  /*
416  * Now recursively process the pulled-up quals. Any inserted
417  * joins can get stacked onto either j->larg or j->rarg,
418  * depending on which rels they reference.
419  */
421  j->quals,
422  &j->larg,
423  available_rels1,
424  &j->rarg,
425  child_rels);
426  /* Return NULL representing constant TRUE */
427  return NULL;
428  }
429  if (available_rels2 != NULL &&
430  (j = convert_ANY_sublink_to_join(root, sublink,
431  available_rels2)) != NULL)
432  {
433  /* Yes; insert the new join node into the join tree */
434  j->larg = *jtlink2;
435  *jtlink2 = (Node *) j;
436  /* Recursively process pulled-up jointree nodes */
438  j->rarg,
439  &child_rels);
440 
441  /*
442  * Now recursively process the pulled-up quals. Any inserted
443  * joins can get stacked onto either j->larg or j->rarg,
444  * depending on which rels they reference.
445  */
447  j->quals,
448  &j->larg,
449  available_rels2,
450  &j->rarg,
451  child_rels);
452  /* Return NULL representing constant TRUE */
453  return NULL;
454  }
455  }
456  else if (sublink->subLinkType == EXISTS_SUBLINK)
457  {
458  if ((j = convert_EXISTS_sublink_to_join(root, sublink, false,
459  available_rels1)) != NULL)
460  {
461  /* Yes; insert the new join node into the join tree */
462  j->larg = *jtlink1;
463  *jtlink1 = (Node *) j;
464  /* Recursively process pulled-up jointree nodes */
466  j->rarg,
467  &child_rels);
468 
469  /*
470  * Now recursively process the pulled-up quals. Any inserted
471  * joins can get stacked onto either j->larg or j->rarg,
472  * depending on which rels they reference.
473  */
475  j->quals,
476  &j->larg,
477  available_rels1,
478  &j->rarg,
479  child_rels);
480  /* Return NULL representing constant TRUE */
481  return NULL;
482  }
483  if (available_rels2 != NULL &&
484  (j = convert_EXISTS_sublink_to_join(root, sublink, false,
485  available_rels2)) != NULL)
486  {
487  /* Yes; insert the new join node into the join tree */
488  j->larg = *jtlink2;
489  *jtlink2 = (Node *) j;
490  /* Recursively process pulled-up jointree nodes */
492  j->rarg,
493  &child_rels);
494 
495  /*
496  * Now recursively process the pulled-up quals. Any inserted
497  * joins can get stacked onto either j->larg or j->rarg,
498  * depending on which rels they reference.
499  */
501  j->quals,
502  &j->larg,
503  available_rels2,
504  &j->rarg,
505  child_rels);
506  /* Return NULL representing constant TRUE */
507  return NULL;
508  }
509  }
510  /* Else return it unmodified */
511  return node;
512  }
513  if (is_notclause(node))
514  {
515  /* If the immediate argument of NOT is EXISTS, try to convert */
516  SubLink *sublink = (SubLink *) get_notclausearg((Expr *) node);
517  JoinExpr *j;
518  Relids child_rels;
519 
520  if (sublink && IsA(sublink, SubLink))
521  {
522  if (sublink->subLinkType == EXISTS_SUBLINK)
523  {
524  if ((j = convert_EXISTS_sublink_to_join(root, sublink, true,
525  available_rels1)) != NULL)
526  {
527  /* Yes; insert the new join node into the join tree */
528  j->larg = *jtlink1;
529  *jtlink1 = (Node *) j;
530  /* Recursively process pulled-up jointree nodes */
532  j->rarg,
533  &child_rels);
534 
535  /*
536  * Now recursively process the pulled-up quals. Because
537  * we are underneath a NOT, we can't pull up sublinks that
538  * reference the left-hand stuff, but it's still okay to
539  * pull up sublinks referencing j->rarg.
540  */
542  j->quals,
543  &j->rarg,
544  child_rels,
545  NULL, NULL);
546  /* Return NULL representing constant TRUE */
547  return NULL;
548  }
549  if (available_rels2 != NULL &&
550  (j = convert_EXISTS_sublink_to_join(root, sublink, true,
551  available_rels2)) != NULL)
552  {
553  /* Yes; insert the new join node into the join tree */
554  j->larg = *jtlink2;
555  *jtlink2 = (Node *) j;
556  /* Recursively process pulled-up jointree nodes */
558  j->rarg,
559  &child_rels);
560 
561  /*
562  * Now recursively process the pulled-up quals. Because
563  * we are underneath a NOT, we can't pull up sublinks that
564  * reference the left-hand stuff, but it's still okay to
565  * pull up sublinks referencing j->rarg.
566  */
568  j->quals,
569  &j->rarg,
570  child_rels,
571  NULL, NULL);
572  /* Return NULL representing constant TRUE */
573  return NULL;
574  }
575  }
576  }
577  /* Else return it unmodified */
578  return node;
579  }
580  if (is_andclause(node))
581  {
582  /* Recurse into AND clause */
583  List *newclauses = NIL;
584  ListCell *l;
585 
586  foreach(l, ((BoolExpr *) node)->args)
587  {
588  Node *oldclause = (Node *) lfirst(l);
589  Node *newclause;
590 
591  newclause = pull_up_sublinks_qual_recurse(root,
592  oldclause,
593  jtlink1,
594  available_rels1,
595  jtlink2,
596  available_rels2);
597  if (newclause)
598  newclauses = lappend(newclauses, newclause);
599  }
600  /* We might have got back fewer clauses than we started with */
601  if (newclauses == NIL)
602  return NULL;
603  else if (list_length(newclauses) == 1)
604  return (Node *) linitial(newclauses);
605  else
606  return (Node *) make_andclause(newclauses);
607  }
608  /* Stop if not an AND */
609  return node;
610 }
611 
612 /*
613  * preprocess_function_rtes
614  * Constant-simplify any FUNCTION RTEs in the FROM clause, and then
615  * attempt to "inline" any that are set-returning functions.
616  *
617  * If an RTE_FUNCTION rtable entry invokes a set-returning function that
618  * contains just a simple SELECT, we can convert the rtable entry to an
619  * RTE_SUBQUERY entry exposing the SELECT directly. This is especially
620  * useful if the subquery can then be "pulled up" for further optimization,
621  * but we do it even if not, to reduce executor overhead.
622  *
623  * This has to be done before we have started to do any optimization of
624  * subqueries, else any such steps wouldn't get applied to subqueries
625  * obtained via inlining. However, we do it after pull_up_sublinks
626  * so that we can inline any functions used in SubLink subselects.
627  *
628  * The reason for applying const-simplification at this stage is that
629  * (a) we'd need to do it anyway to inline a SRF, and (b) by doing it now,
630  * we can be sure that pull_up_constant_function() will see constants
631  * if there are constants to be seen. This approach also guarantees
632  * that every FUNCTION RTE has been const-simplified, allowing planner.c's
633  * preprocess_expression() to skip doing it again.
634  *
635  * Like most of the planner, this feels free to scribble on its input data
636  * structure.
637  */
638 void
640 {
641  ListCell *rt;
642 
643  foreach(rt, root->parse->rtable)
644  {
645  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
646 
647  if (rte->rtekind == RTE_FUNCTION)
648  {
649  Query *funcquery;
650 
651  /* Apply const-simplification */
652  rte->functions = (List *)
653  eval_const_expressions(root, (Node *) rte->functions);
654 
655  /* Check safety of expansion, and expand if possible */
656  funcquery = inline_set_returning_function(root, rte);
657  if (funcquery)
658  {
659  /* Successful expansion, convert the RTE to a subquery */
660  rte->rtekind = RTE_SUBQUERY;
661  rte->subquery = funcquery;
662  rte->security_barrier = false;
663  /* Clear fields that should not be set in a subquery RTE */
664  rte->functions = NIL;
665  rte->funcordinality = false;
666  }
667  }
668  }
669 }
670 
671 /*
672  * pull_up_subqueries
673  * Look for subqueries in the rangetable that can be pulled up into
674  * the parent query. If the subquery has no special features like
675  * grouping/aggregation then we can merge it into the parent's jointree.
676  * Also, subqueries that are simple UNION ALL structures can be
677  * converted into "append relations".
678  */
679 void
681 {
682  /* Top level of jointree must always be a FromExpr */
683  Assert(IsA(root->parse->jointree, FromExpr));
684  /* Recursion starts with no containing join nor appendrel */
685  root->parse->jointree = (FromExpr *)
687  NULL, NULL, NULL);
688  /* We should still have a FromExpr */
689  Assert(IsA(root->parse->jointree, FromExpr));
690 }
691 
692 /*
693  * pull_up_subqueries_recurse
694  * Recursive guts of pull_up_subqueries.
695  *
696  * This recursively processes the jointree and returns a modified jointree.
697  *
698  * If this jointree node is within either side of an outer join, then
699  * lowest_outer_join references the lowest such JoinExpr node; otherwise
700  * it is NULL. We use this to constrain the effects of LATERAL subqueries.
701  *
702  * If this jointree node is within the nullable side of an outer join, then
703  * lowest_nulling_outer_join references the lowest such JoinExpr node;
704  * otherwise it is NULL. This forces use of the PlaceHolderVar mechanism for
705  * references to non-nullable targetlist items, but only for references above
706  * that join.
707  *
708  * If we are looking at a member subquery of an append relation,
709  * containing_appendrel describes that relation; else it is NULL.
710  * This forces use of the PlaceHolderVar mechanism for all non-Var targetlist
711  * items, and puts some additional restrictions on what can be pulled up.
712  *
713  * A tricky aspect of this code is that if we pull up a subquery we have
714  * to replace Vars that reference the subquery's outputs throughout the
715  * parent query, including quals attached to jointree nodes above the one
716  * we are currently processing! We handle this by being careful to maintain
717  * validity of the jointree structure while recursing, in the following sense:
718  * whenever we recurse, all qual expressions in the tree must be reachable
719  * from the top level, in case the recursive call needs to modify them.
720  *
721  * Notice also that we can't turn pullup_replace_vars loose on the whole
722  * jointree, because it'd return a mutated copy of the tree; we have to
723  * invoke it just on the quals, instead. This behavior is what makes it
724  * reasonable to pass lowest_outer_join and lowest_nulling_outer_join as
725  * pointers rather than some more-indirect way of identifying the lowest
726  * OJs. Likewise, we don't replace append_rel_list members but only their
727  * substructure, so the containing_appendrel reference is safe to use.
728  */
729 static Node *
731  JoinExpr *lowest_outer_join,
732  JoinExpr *lowest_nulling_outer_join,
733  AppendRelInfo *containing_appendrel)
734 {
735  Assert(jtnode != NULL);
736  if (IsA(jtnode, RangeTblRef))
737  {
738  int varno = ((RangeTblRef *) jtnode)->rtindex;
739  RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);
740 
741  /*
742  * Is this a subquery RTE, and if so, is the subquery simple enough to
743  * pull up?
744  *
745  * If we are looking at an append-relation member, we can't pull it up
746  * unless is_safe_append_member says so.
747  */
748  if (rte->rtekind == RTE_SUBQUERY &&
749  is_simple_subquery(root, rte->subquery, rte, lowest_outer_join) &&
750  (containing_appendrel == NULL ||
752  return pull_up_simple_subquery(root, jtnode, rte,
753  lowest_outer_join,
754  lowest_nulling_outer_join,
755  containing_appendrel);
756 
757  /*
758  * Alternatively, is it a simple UNION ALL subquery? If so, flatten
759  * into an "append relation".
760  *
761  * It's safe to do this regardless of whether this query is itself an
762  * appendrel member. (If you're thinking we should try to flatten the
763  * two levels of appendrel together, you're right; but we handle that
764  * in set_append_rel_pathlist, not here.)
765  */
766  if (rte->rtekind == RTE_SUBQUERY &&
768  return pull_up_simple_union_all(root, jtnode, rte);
769 
770  /*
771  * Or perhaps it's a simple VALUES RTE?
772  *
773  * We don't allow VALUES pullup below an outer join nor into an
774  * appendrel (such cases are impossible anyway at the moment).
775  */
776  if (rte->rtekind == RTE_VALUES &&
777  lowest_outer_join == NULL &&
778  containing_appendrel == NULL &&
779  is_simple_values(root, rte))
780  return pull_up_simple_values(root, jtnode, rte);
781 
782  /*
783  * Or perhaps it's a FUNCTION RTE that we could inline?
784  */
785  if (rte->rtekind == RTE_FUNCTION)
786  return pull_up_constant_function(root, jtnode, rte,
787  lowest_nulling_outer_join,
788  containing_appendrel);
789 
790  /* Otherwise, do nothing at this node. */
791  }
792  else if (IsA(jtnode, FromExpr))
793  {
794  FromExpr *f = (FromExpr *) jtnode;
795  ListCell *l;
796 
797  Assert(containing_appendrel == NULL);
798  /* Recursively transform all the child nodes */
799  foreach(l, f->fromlist)
800  {
802  lowest_outer_join,
803  lowest_nulling_outer_join,
804  NULL);
805  }
806  }
807  else if (IsA(jtnode, JoinExpr))
808  {
809  JoinExpr *j = (JoinExpr *) jtnode;
810 
811  Assert(containing_appendrel == NULL);
812  /* Recurse, being careful to tell myself when inside outer join */
813  switch (j->jointype)
814  {
815  case JOIN_INNER:
816  j->larg = pull_up_subqueries_recurse(root, j->larg,
817  lowest_outer_join,
818  lowest_nulling_outer_join,
819  NULL);
820  j->rarg = pull_up_subqueries_recurse(root, j->rarg,
821  lowest_outer_join,
822  lowest_nulling_outer_join,
823  NULL);
824  break;
825  case JOIN_LEFT:
826  case JOIN_SEMI:
827  case JOIN_ANTI:
828  j->larg = pull_up_subqueries_recurse(root, j->larg,
829  j,
830  lowest_nulling_outer_join,
831  NULL);
832  j->rarg = pull_up_subqueries_recurse(root, j->rarg,
833  j,
834  j,
835  NULL);
836  break;
837  case JOIN_FULL:
838  j->larg = pull_up_subqueries_recurse(root, j->larg,
839  j,
840  j,
841  NULL);
842  j->rarg = pull_up_subqueries_recurse(root, j->rarg,
843  j,
844  j,
845  NULL);
846  break;
847  case JOIN_RIGHT:
848  j->larg = pull_up_subqueries_recurse(root, j->larg,
849  j,
850  j,
851  NULL);
852  j->rarg = pull_up_subqueries_recurse(root, j->rarg,
853  j,
854  lowest_nulling_outer_join,
855  NULL);
856  break;
857  default:
858  elog(ERROR, "unrecognized join type: %d",
859  (int) j->jointype);
860  break;
861  }
862  }
863  else
864  elog(ERROR, "unrecognized node type: %d",
865  (int) nodeTag(jtnode));
866  return jtnode;
867 }
868 
869 /*
870  * pull_up_simple_subquery
871  * Attempt to pull up a single simple subquery.
872  *
873  * jtnode is a RangeTblRef that has been tentatively identified as a simple
874  * subquery by pull_up_subqueries. We return the replacement jointree node,
875  * or jtnode itself if we determine that the subquery can't be pulled up
876  * after all.
877  *
878  * rte is the RangeTblEntry referenced by jtnode. Remaining parameters are
879  * as for pull_up_subqueries_recurse.
880  */
881 static Node *
883  JoinExpr *lowest_outer_join,
884  JoinExpr *lowest_nulling_outer_join,
885  AppendRelInfo *containing_appendrel)
886 {
887  Query *parse = root->parse;
888  int varno = ((RangeTblRef *) jtnode)->rtindex;
889  Query *subquery;
890  PlannerInfo *subroot;
891  int rtoffset;
892  pullup_replace_vars_context rvcontext;
893  ListCell *lc;
894 
895  /*
896  * Need a modifiable copy of the subquery to hack on. Even if we didn't
897  * sometimes choose not to pull up below, we must do this to avoid
898  * problems if the same subquery is referenced from multiple jointree
899  * items (which can't happen normally, but might after rule rewriting).
900  */
901  subquery = copyObject(rte->subquery);
902 
903  /*
904  * Create a PlannerInfo data structure for this subquery.
905  *
906  * NOTE: the next few steps should match the first processing in
907  * subquery_planner(). Can we refactor to avoid code duplication, or
908  * would that just make things uglier?
909  */
910  subroot = makeNode(PlannerInfo);
911  subroot->parse = subquery;
912  subroot->glob = root->glob;
913  subroot->query_level = root->query_level;
914  subroot->parent_root = root->parent_root;
915  subroot->plan_params = NIL;
916  subroot->outer_params = NULL;
918  subroot->init_plans = NIL;
919  subroot->cte_plan_ids = NIL;
920  subroot->multiexpr_params = NIL;
921  subroot->eq_classes = NIL;
922  subroot->ec_merging_done = false;
923  subroot->append_rel_list = NIL;
924  subroot->rowMarks = NIL;
925  memset(subroot->upper_rels, 0, sizeof(subroot->upper_rels));
926  memset(subroot->upper_targets, 0, sizeof(subroot->upper_targets));
927  subroot->processed_tlist = NIL;
928  subroot->grouping_map = NULL;
929  subroot->minmax_aggs = NIL;
930  subroot->qual_security_level = 0;
931  subroot->inhTargetKind = INHKIND_NONE;
932  subroot->hasRecursion = false;
933  subroot->wt_param_id = -1;
934  subroot->non_recursive_path = NULL;
935 
936  /* No CTEs to worry about */
937  Assert(subquery->cteList == NIL);
938 
939  /*
940  * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
941  * that we don't need so many special cases to deal with that situation.
942  */
943  replace_empty_jointree(subquery);
944 
945  /*
946  * Pull up any SubLinks within the subquery's quals, so that we don't
947  * leave unoptimized SubLinks behind.
948  */
949  if (subquery->hasSubLinks)
950  pull_up_sublinks(subroot);
951 
952  /*
953  * Similarly, preprocess its function RTEs to inline any set-returning
954  * functions in its rangetable.
955  */
956  preprocess_function_rtes(subroot);
957 
958  /*
959  * Recursively pull up the subquery's subqueries, so that
960  * pull_up_subqueries' processing is complete for its jointree and
961  * rangetable.
962  *
963  * Note: it's okay that the subquery's recursion starts with NULL for
964  * containing-join info, even if we are within an outer join in the upper
965  * query; the lower query starts with a clean slate for outer-join
966  * semantics. Likewise, we needn't pass down appendrel state.
967  */
968  pull_up_subqueries(subroot);
969 
970  /*
971  * Now we must recheck whether the subquery is still simple enough to pull
972  * up. If not, abandon processing it.
973  *
974  * We don't really need to recheck all the conditions involved, but it's
975  * easier just to keep this "if" looking the same as the one in
976  * pull_up_subqueries_recurse.
977  */
978  if (is_simple_subquery(root, subquery, rte, lowest_outer_join) &&
979  (containing_appendrel == NULL || is_safe_append_member(subquery)))
980  {
981  /* good to go */
982  }
983  else
984  {
985  /*
986  * Give up, return unmodified RangeTblRef.
987  *
988  * Note: The work we just did will be redone when the subquery gets
989  * planned on its own. Perhaps we could avoid that by storing the
990  * modified subquery back into the rangetable, but I'm not gonna risk
991  * it now.
992  */
993  return jtnode;
994  }
995 
996  /*
997  * We must flatten any join alias Vars in the subquery's targetlist,
998  * because pulling up the subquery's subqueries might have changed their
999  * expansions into arbitrary expressions, which could affect
1000  * pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
1001  * are needed for tlist entries. (Likely it'd be better to do
1002  * flatten_join_alias_vars on the whole query tree at some earlier stage,
1003  * maybe even in the rewriter; but for now let's just fix this case here.)
1004  */
1005  subquery->targetList = (List *)
1006  flatten_join_alias_vars(subroot->parse, (Node *) subquery->targetList);
1007 
1008  /*
1009  * Adjust level-0 varnos in subquery so that we can append its rangetable
1010  * to upper query's. We have to fix the subquery's append_rel_list as
1011  * well.
1012  */
1013  rtoffset = list_length(parse->rtable);
1014  OffsetVarNodes((Node *) subquery, rtoffset, 0);
1015  OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
1016 
1017  /*
1018  * Upper-level vars in subquery are now one level closer to their parent
1019  * than before.
1020  */
1021  IncrementVarSublevelsUp((Node *) subquery, -1, 1);
1022  IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
1023 
1024  /*
1025  * The subquery's targetlist items are now in the appropriate form to
1026  * insert into the top query, except that we may need to wrap them in
1027  * PlaceHolderVars. Set up required context data for pullup_replace_vars.
1028  */
1029  rvcontext.root = root;
1030  rvcontext.targetlist = subquery->targetList;
1031  rvcontext.target_rte = rte;
1032  if (rte->lateral)
1033  rvcontext.relids = get_relids_in_jointree((Node *) subquery->jointree,
1034  true);
1035  else /* won't need relids */
1036  rvcontext.relids = NULL;
1037  rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1038  rvcontext.varno = varno;
1039  /* these flags will be set below, if needed */
1040  rvcontext.need_phvs = false;
1041  rvcontext.wrap_non_vars = false;
1042  /* initialize cache array with indexes 0 .. length(tlist) */
1043  rvcontext.rv_cache = palloc0((list_length(subquery->targetList) + 1) *
1044  sizeof(Node *));
1045 
1046  /*
1047  * If we are under an outer join then non-nullable items and lateral
1048  * references may have to be turned into PlaceHolderVars.
1049  */
1050  if (lowest_nulling_outer_join != NULL)
1051  rvcontext.need_phvs = true;
1052 
1053  /*
1054  * If we are dealing with an appendrel member then anything that's not a
1055  * simple Var has to be turned into a PlaceHolderVar. We force this to
1056  * ensure that what we pull up doesn't get merged into a surrounding
1057  * expression during later processing and then fail to match the
1058  * expression actually available from the appendrel.
1059  */
1060  if (containing_appendrel != NULL)
1061  {
1062  rvcontext.need_phvs = true;
1063  rvcontext.wrap_non_vars = true;
1064  }
1065 
1066  /*
1067  * If the parent query uses grouping sets, we need a PlaceHolderVar for
1068  * anything that's not a simple Var. Again, this ensures that expressions
1069  * retain their separate identity so that they will match grouping set
1070  * columns when appropriate. (It'd be sufficient to wrap values used in
1071  * grouping set columns, and do so only in non-aggregated portions of the
1072  * tlist and havingQual, but that would require a lot of infrastructure
1073  * that pullup_replace_vars hasn't currently got.)
1074  */
1075  if (parse->groupingSets)
1076  {
1077  rvcontext.need_phvs = true;
1078  rvcontext.wrap_non_vars = true;
1079  }
1080 
1081  /*
1082  * Replace all of the top query's references to the subquery's outputs
1083  * with copies of the adjusted subtlist items, being careful not to
1084  * replace any of the jointree structure.
1085  */
1086  perform_pullup_replace_vars(root, &rvcontext,
1087  lowest_nulling_outer_join,
1088  containing_appendrel);
1089 
1090  /*
1091  * If the subquery had a LATERAL marker, propagate that to any of its
1092  * child RTEs that could possibly now contain lateral cross-references.
1093  * The children might or might not contain any actual lateral
1094  * cross-references, but we have to mark the pulled-up child RTEs so that
1095  * later planner stages will check for such.
1096  */
1097  if (rte->lateral)
1098  {
1099  foreach(lc, subquery->rtable)
1100  {
1101  RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(lc);
1102 
1103  switch (child_rte->rtekind)
1104  {
1105  case RTE_RELATION:
1106  if (child_rte->tablesample)
1107  child_rte->lateral = true;
1108  break;
1109  case RTE_SUBQUERY:
1110  case RTE_FUNCTION:
1111  case RTE_VALUES:
1112  case RTE_TABLEFUNC:
1113  child_rte->lateral = true;
1114  break;
1115  case RTE_JOIN:
1116  case RTE_CTE:
1117  case RTE_NAMEDTUPLESTORE:
1118  case RTE_RESULT:
1119  /* these can't contain any lateral references */
1120  break;
1121  }
1122  }
1123  }
1124 
1125  /*
1126  * Now append the adjusted rtable entries to upper query. (We hold off
1127  * until after fixing the upper rtable entries; no point in running that
1128  * code on the subquery ones too.)
1129  */
1130  parse->rtable = list_concat(parse->rtable, subquery->rtable);
1131 
1132  /*
1133  * Pull up any FOR UPDATE/SHARE markers, too. (OffsetVarNodes already
1134  * adjusted the marker rtindexes, so just concat the lists.)
1135  */
1136  parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
1137 
1138  /*
1139  * We also have to fix the relid sets of any PlaceHolderVar nodes in the
1140  * parent query. (This could perhaps be done by pullup_replace_vars(),
1141  * but it seems cleaner to use two passes.) Note in particular that any
1142  * PlaceHolderVar nodes just created by pullup_replace_vars() will be
1143  * adjusted, so having created them with the subquery's varno is correct.
1144  *
1145  * Likewise, relids appearing in AppendRelInfo nodes have to be fixed. We
1146  * already checked that this won't require introducing multiple subrelids
1147  * into the single-slot AppendRelInfo structs.
1148  */
1149  if (parse->hasSubLinks || root->glob->lastPHId != 0 ||
1150  root->append_rel_list)
1151  {
1152  Relids subrelids;
1153 
1154  subrelids = get_relids_in_jointree((Node *) subquery->jointree, false);
1155  substitute_phv_relids((Node *) parse, varno, subrelids);
1156  fix_append_rel_relids(root->append_rel_list, varno, subrelids);
1157  }
1158 
1159  /*
1160  * And now add subquery's AppendRelInfos to our list.
1161  */
1163  subroot->append_rel_list);
1164 
1165  /*
1166  * We don't have to do the equivalent bookkeeping for outer-join info,
1167  * because that hasn't been set up yet. placeholder_list likewise.
1168  */
1169  Assert(root->join_info_list == NIL);
1170  Assert(subroot->join_info_list == NIL);
1171  Assert(root->placeholder_list == NIL);
1172  Assert(subroot->placeholder_list == NIL);
1173 
1174  /*
1175  * Miscellaneous housekeeping.
1176  *
1177  * Although replace_rte_variables() faithfully updated parse->hasSubLinks
1178  * if it copied any SubLinks out of the subquery's targetlist, we still
1179  * could have SubLinks added to the query in the expressions of FUNCTION
1180  * and VALUES RTEs copied up from the subquery. So it's necessary to copy
1181  * subquery->hasSubLinks anyway. Perhaps this can be improved someday.
1182  */
1183  parse->hasSubLinks |= subquery->hasSubLinks;
1184 
1185  /* If subquery had any RLS conditions, now main query does too */
1186  parse->hasRowSecurity |= subquery->hasRowSecurity;
1187 
1188  /*
1189  * subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
1190  * hasTargetSRFs, so no work needed on those flags
1191  */
1192 
1193  /*
1194  * Return the adjusted subquery jointree to replace the RangeTblRef entry
1195  * in parent's jointree; or, if the FromExpr is degenerate, just return
1196  * its single member.
1197  */
1198  Assert(IsA(subquery->jointree, FromExpr));
1199  Assert(subquery->jointree->fromlist != NIL);
1200  if (subquery->jointree->quals == NULL &&
1201  list_length(subquery->jointree->fromlist) == 1)
1202  return (Node *) linitial(subquery->jointree->fromlist);
1203 
1204  return (Node *) subquery->jointree;
1205 }
1206 
1207 /*
1208  * pull_up_simple_union_all
1209  * Pull up a single simple UNION ALL subquery.
1210  *
1211  * jtnode is a RangeTblRef that has been identified as a simple UNION ALL
1212  * subquery by pull_up_subqueries. We pull up the leaf subqueries and
1213  * build an "append relation" for the union set. The result value is just
1214  * jtnode, since we don't actually need to change the query jointree.
1215  */
1216 static Node *
1218 {
1219  int varno = ((RangeTblRef *) jtnode)->rtindex;
1220  Query *subquery = rte->subquery;
1221  int rtoffset = list_length(root->parse->rtable);
1222  List *rtable;
1223 
1224  /*
1225  * Make a modifiable copy of the subquery's rtable, so we can adjust
1226  * upper-level Vars in it. There are no such Vars in the setOperations
1227  * tree proper, so fixing the rtable should be sufficient.
1228  */
1229  rtable = copyObject(subquery->rtable);
1230 
1231  /*
1232  * Upper-level vars in subquery are now one level closer to their parent
1233  * than before. We don't have to worry about offsetting varnos, though,
1234  * because the UNION leaf queries can't cross-reference each other.
1235  */
1236  IncrementVarSublevelsUp_rtable(rtable, -1, 1);
1237 
1238  /*
1239  * If the UNION ALL subquery had a LATERAL marker, propagate that to all
1240  * its children. The individual children might or might not contain any
1241  * actual lateral cross-references, but we have to mark the pulled-up
1242  * child RTEs so that later planner stages will check for such.
1243  */
1244  if (rte->lateral)
1245  {
1246  ListCell *rt;
1247 
1248  foreach(rt, rtable)
1249  {
1250  RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(rt);
1251 
1252  Assert(child_rte->rtekind == RTE_SUBQUERY);
1253  child_rte->lateral = true;
1254  }
1255  }
1256 
1257  /*
1258  * Append child RTEs to parent rtable.
1259  */
1260  root->parse->rtable = list_concat(root->parse->rtable, rtable);
1261 
1262  /*
1263  * Recursively scan the subquery's setOperations tree and add
1264  * AppendRelInfo nodes for leaf subqueries to the parent's
1265  * append_rel_list. Also apply pull_up_subqueries to the leaf subqueries.
1266  */
1267  Assert(subquery->setOperations);
1268  pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
1269  rtoffset);
1270 
1271  /*
1272  * Mark the parent as an append relation.
1273  */
1274  rte->inh = true;
1275 
1276  return jtnode;
1277 }
1278 
1279 /*
1280  * pull_up_union_leaf_queries -- recursive guts of pull_up_simple_union_all
1281  *
1282  * Build an AppendRelInfo for each leaf query in the setop tree, and then
1283  * apply pull_up_subqueries to the leaf query.
1284  *
1285  * Note that setOpQuery is the Query containing the setOp node, whose tlist
1286  * contains references to all the setop output columns. When called from
1287  * pull_up_simple_union_all, this is *not* the same as root->parse, which is
1288  * the parent Query we are pulling up into.
1289  *
1290  * parentRTindex is the appendrel parent's index in root->parse->rtable.
1291  *
1292  * The child RTEs have already been copied to the parent. childRToffset
1293  * tells us where in the parent's range table they were copied. When called
1294  * from flatten_simple_union_all, childRToffset is 0 since the child RTEs
1295  * were already in root->parse->rtable and no RT index adjustment is needed.
1296  */
1297 static void
1298 pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
1299  Query *setOpQuery, int childRToffset)
1300 {
1301  if (IsA(setOp, RangeTblRef))
1302  {
1303  RangeTblRef *rtr = (RangeTblRef *) setOp;
1304  int childRTindex;
1305  AppendRelInfo *appinfo;
1306 
1307  /*
1308  * Calculate the index in the parent's range table
1309  */
1310  childRTindex = childRToffset + rtr->rtindex;
1311 
1312  /*
1313  * Build a suitable AppendRelInfo, and attach to parent's list.
1314  */
1315  appinfo = makeNode(AppendRelInfo);
1316  appinfo->parent_relid = parentRTindex;
1317  appinfo->child_relid = childRTindex;
1318  appinfo->parent_reltype = InvalidOid;
1319  appinfo->child_reltype = InvalidOid;
1320  make_setop_translation_list(setOpQuery, childRTindex, appinfo);
1321  appinfo->parent_reloid = InvalidOid;
1322  root->append_rel_list = lappend(root->append_rel_list, appinfo);
1323 
1324  /*
1325  * Recursively apply pull_up_subqueries to the new child RTE. (We
1326  * must build the AppendRelInfo first, because this will modify it.)
1327  * Note that we can pass NULL for containing-join info even if we're
1328  * actually under an outer join, because the child's expressions
1329  * aren't going to propagate up to the join. Also, we ignore the
1330  * possibility that pull_up_subqueries_recurse() returns a different
1331  * jointree node than what we pass it; if it does, the important thing
1332  * is that it replaced the child relid in the AppendRelInfo node.
1333  */
1334  rtr = makeNode(RangeTblRef);
1335  rtr->rtindex = childRTindex;
1336  (void) pull_up_subqueries_recurse(root, (Node *) rtr,
1337  NULL, NULL, appinfo);
1338  }
1339  else if (IsA(setOp, SetOperationStmt))
1340  {
1341  SetOperationStmt *op = (SetOperationStmt *) setOp;
1342 
1343  /* Recurse to reach leaf queries */
1344  pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
1345  childRToffset);
1346  pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
1347  childRToffset);
1348  }
1349  else
1350  {
1351  elog(ERROR, "unrecognized node type: %d",
1352  (int) nodeTag(setOp));
1353  }
1354 }
1355 
1356 /*
1357  * make_setop_translation_list
1358  * Build the list of translations from parent Vars to child Vars for
1359  * a UNION ALL member. (At this point it's just a simple list of
1360  * referencing Vars, but if we succeed in pulling up the member
1361  * subquery, the Vars will get replaced by pulled-up expressions.)
1362  * Also create the rather trivial reverse-translation array.
1363  */
1364 static void
1366  AppendRelInfo *appinfo)
1367 {
1368  List *vars = NIL;
1369  AttrNumber *pcolnos;
1370  ListCell *l;
1371 
1372  /* Initialize reverse-translation array with all entries zero */
1373  /* (entries for resjunk columns will stay that way) */
1374  appinfo->num_child_cols = list_length(query->targetList);
1375  appinfo->parent_colnos = pcolnos =
1376  (AttrNumber *) palloc0(appinfo->num_child_cols * sizeof(AttrNumber));
1377 
1378  foreach(l, query->targetList)
1379  {
1380  TargetEntry *tle = (TargetEntry *) lfirst(l);
1381 
1382  if (tle->resjunk)
1383  continue;
1384 
1385  vars = lappend(vars, makeVarFromTargetEntry(newvarno, tle));
1386  pcolnos[tle->resno - 1] = tle->resno;
1387  }
1388 
1389  appinfo->translated_vars = vars;
1390 }
1391 
1392 /*
1393  * is_simple_subquery
1394  * Check a subquery in the range table to see if it's simple enough
1395  * to pull up into the parent query.
1396  *
1397  * rte is the RTE_SUBQUERY RangeTblEntry that contained the subquery.
1398  * (Note subquery is not necessarily equal to rte->subquery; it could be a
1399  * processed copy of that.)
1400  * lowest_outer_join is the lowest outer join above the subquery, or NULL.
1401  */
1402 static bool
1404  JoinExpr *lowest_outer_join)
1405 {
1406  /*
1407  * Let's just make sure it's a valid subselect ...
1408  */
1409  if (!IsA(subquery, Query) ||
1410  subquery->commandType != CMD_SELECT)
1411  elog(ERROR, "subquery is bogus");
1412 
1413  /*
1414  * Can't currently pull up a query with setops (unless it's simple UNION
1415  * ALL, which is handled by a different code path). Maybe after querytree
1416  * redesign...
1417  */
1418  if (subquery->setOperations)
1419  return false;
1420 
1421  /*
1422  * Can't pull up a subquery involving grouping, aggregation, SRFs,
1423  * sorting, limiting, or WITH. (XXX WITH could possibly be allowed later)
1424  *
1425  * We also don't pull up a subquery that has explicit FOR UPDATE/SHARE
1426  * clauses, because pullup would cause the locking to occur semantically
1427  * higher than it should. Implicit FOR UPDATE/SHARE is okay because in
1428  * that case the locking was originally declared in the upper query
1429  * anyway.
1430  */
1431  if (subquery->hasAggs ||
1432  subquery->hasWindowFuncs ||
1433  subquery->hasTargetSRFs ||
1434  subquery->groupClause ||
1435  subquery->groupingSets ||
1436  subquery->havingQual ||
1437  subquery->sortClause ||
1438  subquery->distinctClause ||
1439  subquery->limitOffset ||
1440  subquery->limitCount ||
1441  subquery->hasForUpdate ||
1442  subquery->cteList)
1443  return false;
1444 
1445  /*
1446  * Don't pull up if the RTE represents a security-barrier view; we
1447  * couldn't prevent information leakage once the RTE's Vars are scattered
1448  * about in the upper query.
1449  */
1450  if (rte->security_barrier)
1451  return false;
1452 
1453  /*
1454  * If the subquery is LATERAL, check for pullup restrictions from that.
1455  */
1456  if (rte->lateral)
1457  {
1458  bool restricted;
1459  Relids safe_upper_varnos;
1460 
1461  /*
1462  * The subquery's WHERE and JOIN/ON quals mustn't contain any lateral
1463  * references to rels outside a higher outer join (including the case
1464  * where the outer join is within the subquery itself). In such a
1465  * case, pulling up would result in a situation where we need to
1466  * postpone quals from below an outer join to above it, which is
1467  * probably completely wrong and in any case is a complication that
1468  * doesn't seem worth addressing at the moment.
1469  */
1470  if (lowest_outer_join != NULL)
1471  {
1472  restricted = true;
1473  safe_upper_varnos = get_relids_in_jointree((Node *) lowest_outer_join,
1474  true);
1475  }
1476  else
1477  {
1478  restricted = false;
1479  safe_upper_varnos = NULL; /* doesn't matter */
1480  }
1481 
1483  (Node *) subquery->jointree,
1484  restricted, safe_upper_varnos))
1485  return false;
1486 
1487  /*
1488  * If there's an outer join above the LATERAL subquery, also disallow
1489  * pullup if the subquery's targetlist has any references to rels
1490  * outside the outer join, since these might get pulled into quals
1491  * above the subquery (but in or below the outer join) and then lead
1492  * to qual-postponement issues similar to the case checked for above.
1493  * (We wouldn't need to prevent pullup if no such references appear in
1494  * outer-query quals, but we don't have enough info here to check
1495  * that. Also, maybe this restriction could be removed if we forced
1496  * such refs to be wrapped in PlaceHolderVars, even when they're below
1497  * the nearest outer join? But it's a pretty hokey usage, so not
1498  * clear this is worth sweating over.)
1499  */
1500  if (lowest_outer_join != NULL)
1501  {
1502  Relids lvarnos = pull_varnos_of_level(root,
1503  (Node *) subquery->targetList,
1504  1);
1505 
1506  if (!bms_is_subset(lvarnos, safe_upper_varnos))
1507  return false;
1508  }
1509  }
1510 
1511  /*
1512  * Don't pull up a subquery that has any volatile functions in its
1513  * targetlist. Otherwise we might introduce multiple evaluations of these
1514  * functions, if they get copied to multiple places in the upper query,
1515  * leading to surprising results. (Note: the PlaceHolderVar mechanism
1516  * doesn't quite guarantee single evaluation; else we could pull up anyway
1517  * and just wrap such items in PlaceHolderVars ...)
1518  */
1519  if (contain_volatile_functions((Node *) subquery->targetList))
1520  return false;
1521 
1522  return true;
1523 }
1524 
1525 /*
1526  * pull_up_simple_values
1527  * Pull up a single simple VALUES RTE.
1528  *
1529  * jtnode is a RangeTblRef that has been identified as a simple VALUES RTE
1530  * by pull_up_subqueries. We always return a RangeTblRef representing a
1531  * RESULT RTE to replace it (all failure cases should have been detected by
1532  * is_simple_values()). Actually, what we return is just jtnode, because
1533  * we replace the VALUES RTE in the rangetable with the RESULT RTE.
1534  *
1535  * rte is the RangeTblEntry referenced by jtnode. Because of the limited
1536  * possible usage of VALUES RTEs, we do not need the remaining parameters
1537  * of pull_up_subqueries_recurse.
1538  */
1539 static Node *
1541 {
1542  Query *parse = root->parse;
1543  int varno = ((RangeTblRef *) jtnode)->rtindex;
1544  List *values_list;
1545  List *tlist;
1546  AttrNumber attrno;
1547  pullup_replace_vars_context rvcontext;
1548  ListCell *lc;
1549 
1550  Assert(rte->rtekind == RTE_VALUES);
1551  Assert(list_length(rte->values_lists) == 1);
1552 
1553  /*
1554  * Need a modifiable copy of the VALUES list to hack on, just in case it's
1555  * multiply referenced.
1556  */
1557  values_list = copyObject(linitial(rte->values_lists));
1558 
1559  /*
1560  * The VALUES RTE can't contain any Vars of level zero, let alone any that
1561  * are join aliases, so no need to flatten join alias Vars.
1562  */
1563  Assert(!contain_vars_of_level((Node *) values_list, 0));
1564 
1565  /*
1566  * Set up required context data for pullup_replace_vars. In particular,
1567  * we have to make the VALUES list look like a subquery targetlist.
1568  */
1569  tlist = NIL;
1570  attrno = 1;
1571  foreach(lc, values_list)
1572  {
1573  tlist = lappend(tlist,
1574  makeTargetEntry((Expr *) lfirst(lc),
1575  attrno,
1576  NULL,
1577  false));
1578  attrno++;
1579  }
1580  rvcontext.root = root;
1581  rvcontext.targetlist = tlist;
1582  rvcontext.target_rte = rte;
1583  rvcontext.relids = NULL;
1584  rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1585  rvcontext.varno = varno;
1586  rvcontext.need_phvs = false;
1587  rvcontext.wrap_non_vars = false;
1588  /* initialize cache array with indexes 0 .. length(tlist) */
1589  rvcontext.rv_cache = palloc0((list_length(tlist) + 1) *
1590  sizeof(Node *));
1591 
1592  /*
1593  * Replace all of the top query's references to the RTE's outputs with
1594  * copies of the adjusted VALUES expressions, being careful not to replace
1595  * any of the jointree structure. We can assume there's no outer joins or
1596  * appendrels in the dummy Query that surrounds a VALUES RTE.
1597  */
1598  perform_pullup_replace_vars(root, &rvcontext, NULL, NULL);
1599 
1600  /*
1601  * There should be no appendrels to fix, nor any outer joins and hence no
1602  * PlaceHolderVars.
1603  */
1604  Assert(root->append_rel_list == NIL);
1605  Assert(root->join_info_list == NIL);
1606  Assert(root->placeholder_list == NIL);
1607 
1608  /*
1609  * Replace the VALUES RTE with a RESULT RTE. The VALUES RTE is the only
1610  * rtable entry in the current query level, so this is easy.
1611  */
1612  Assert(list_length(parse->rtable) == 1);
1613 
1614  /* Create suitable RTE */
1615  rte = makeNode(RangeTblEntry);
1616  rte->rtekind = RTE_RESULT;
1617  rte->eref = makeAlias("*RESULT*", NIL);
1618 
1619  /* Replace rangetable */
1620  parse->rtable = list_make1(rte);
1621 
1622  /* We could manufacture a new RangeTblRef, but the one we have is fine */
1623  Assert(varno == 1);
1624 
1625  return jtnode;
1626 }
1627 
1628 /*
1629  * is_simple_values
1630  * Check a VALUES RTE in the range table to see if it's simple enough
1631  * to pull up into the parent query.
1632  *
1633  * rte is the RTE_VALUES RangeTblEntry to check.
1634  */
1635 static bool
1637 {
1638  Assert(rte->rtekind == RTE_VALUES);
1639 
1640  /*
1641  * There must be exactly one VALUES list, else it's not semantically
1642  * correct to replace the VALUES RTE with a RESULT RTE, nor would we have
1643  * a unique set of expressions to substitute into the parent query.
1644  */
1645  if (list_length(rte->values_lists) != 1)
1646  return false;
1647 
1648  /*
1649  * Because VALUES can't appear under an outer join (or at least, we won't
1650  * try to pull it up if it does), we need not worry about LATERAL, nor
1651  * about validity of PHVs for the VALUES' outputs.
1652  */
1653 
1654  /*
1655  * Don't pull up a VALUES that contains any set-returning or volatile
1656  * functions. The considerations here are basically identical to the
1657  * restrictions on a pull-able subquery's targetlist.
1658  */
1659  if (expression_returns_set((Node *) rte->values_lists) ||
1661  return false;
1662 
1663  /*
1664  * Do not pull up a VALUES that's not the only RTE in its parent query.
1665  * This is actually the only case that the parser will generate at the
1666  * moment, and assuming this is true greatly simplifies
1667  * pull_up_simple_values().
1668  */
1669  if (list_length(root->parse->rtable) != 1 ||
1670  rte != (RangeTblEntry *) linitial(root->parse->rtable))
1671  return false;
1672 
1673  return true;
1674 }
1675 
1676 /*
1677  * pull_up_constant_function
1678  * Pull up an RTE_FUNCTION expression that was simplified to a constant.
1679  *
1680  * jtnode is a RangeTblRef that has been identified as a FUNCTION RTE by
1681  * pull_up_subqueries. If its expression is just a Const, hoist that value
1682  * up into the parent query, and replace the RTE_FUNCTION with RTE_RESULT.
1683  *
1684  * In principle we could pull up any immutable expression, but we don't.
1685  * That might result in multiple evaluations of the expression, which could
1686  * be costly if it's not just a Const. Also, the main value of this is
1687  * to let the constant participate in further const-folding, and of course
1688  * that won't happen for a non-Const.
1689  *
1690  * The pulled-up value might need to be wrapped in a PlaceHolderVar if the
1691  * RTE is below an outer join or is part of an appendrel; the extra
1692  * parameters show whether that's needed.
1693  */
1694 static Node *
1696  RangeTblEntry *rte,
1697  JoinExpr *lowest_nulling_outer_join,
1698  AppendRelInfo *containing_appendrel)
1699 {
1700  Query *parse = root->parse;
1701  RangeTblFunction *rtf;
1702  TypeFuncClass functypclass;
1703  Oid funcrettype;
1704  TupleDesc tupdesc;
1705  pullup_replace_vars_context rvcontext;
1706 
1707  /* Fail if the RTE has ORDINALITY - we don't implement that here. */
1708  if (rte->funcordinality)
1709  return jtnode;
1710 
1711  /* Fail if RTE isn't a single, simple Const expr */
1712  if (list_length(rte->functions) != 1)
1713  return jtnode;
1715  if (!IsA(rtf->funcexpr, Const))
1716  return jtnode;
1717 
1718  /*
1719  * If the function's result is not a scalar, we punt. In principle we
1720  * could break the composite constant value apart into per-column
1721  * constants, but for now it seems not worth the work.
1722  */
1723  if (rtf->funccolcount != 1)
1724  return jtnode; /* definitely composite */
1725 
1726  functypclass = get_expr_result_type(rtf->funcexpr,
1727  &funcrettype,
1728  &tupdesc);
1729  if (functypclass != TYPEFUNC_SCALAR)
1730  return jtnode; /* must be a one-column composite type */
1731 
1732  /* Create context for applying pullup_replace_vars */
1733  rvcontext.root = root;
1734  rvcontext.targetlist = list_make1(makeTargetEntry((Expr *) rtf->funcexpr,
1735  1, /* resno */
1736  NULL, /* resname */
1737  false)); /* resjunk */
1738  rvcontext.target_rte = rte;
1739 
1740  /*
1741  * Since this function was reduced to a Const, it doesn't contain any
1742  * lateral references, even if it's marked as LATERAL. This means we
1743  * don't need to fill relids.
1744  */
1745  rvcontext.relids = NULL;
1746 
1747  rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1748  rvcontext.varno = ((RangeTblRef *) jtnode)->rtindex;
1749  /* these flags will be set below, if needed */
1750  rvcontext.need_phvs = false;
1751  rvcontext.wrap_non_vars = false;
1752  /* initialize cache array with indexes 0 .. length(tlist) */
1753  rvcontext.rv_cache = palloc0((list_length(rvcontext.targetlist) + 1) *
1754  sizeof(Node *));
1755 
1756  /*
1757  * If we are under an outer join then non-nullable items and lateral
1758  * references may have to be turned into PlaceHolderVars.
1759  */
1760  if (lowest_nulling_outer_join != NULL)
1761  rvcontext.need_phvs = true;
1762 
1763  /*
1764  * If we are dealing with an appendrel member then anything that's not a
1765  * simple Var has to be turned into a PlaceHolderVar. (See comments in
1766  * pull_up_simple_subquery().)
1767  */
1768  if (containing_appendrel != NULL)
1769  {
1770  rvcontext.need_phvs = true;
1771  rvcontext.wrap_non_vars = true;
1772  }
1773 
1774  /*
1775  * If the parent query uses grouping sets, we need a PlaceHolderVar for
1776  * anything that's not a simple Var.
1777  */
1778  if (parse->groupingSets)
1779  {
1780  rvcontext.need_phvs = true;
1781  rvcontext.wrap_non_vars = true;
1782  }
1783 
1784  /*
1785  * Replace all of the top query's references to the RTE's output with
1786  * copies of the funcexpr, being careful not to replace any of the
1787  * jointree structure.
1788  */
1789  perform_pullup_replace_vars(root, &rvcontext,
1790  lowest_nulling_outer_join,
1791  containing_appendrel);
1792 
1793  /*
1794  * We don't need to bother with changing PlaceHolderVars in the parent
1795  * query. Their references to the RT index are still good for now, and
1796  * will get removed later if we're able to drop the RTE_RESULT.
1797  */
1798 
1799  /*
1800  * Convert the RTE to be RTE_RESULT type, signifying that we don't need to
1801  * scan it anymore, and zero out RTE_FUNCTION-specific fields.
1802  */
1803  rte->rtekind = RTE_RESULT;
1804  rte->functions = NIL;
1805 
1806  /*
1807  * We can reuse the RangeTblRef node.
1808  */
1809  return jtnode;
1810 }
1811 
1812 /*
1813  * is_simple_union_all
1814  * Check a subquery to see if it's a simple UNION ALL.
1815  *
1816  * We require all the setops to be UNION ALL (no mixing) and there can't be
1817  * any datatype coercions involved, ie, all the leaf queries must emit the
1818  * same datatypes.
1819  */
1820 static bool
1822 {
1823  SetOperationStmt *topop;
1824 
1825  /* Let's just make sure it's a valid subselect ... */
1826  if (!IsA(subquery, Query) ||
1827  subquery->commandType != CMD_SELECT)
1828  elog(ERROR, "subquery is bogus");
1829 
1830  /* Is it a set-operation query at all? */
1831  topop = castNode(SetOperationStmt, subquery->setOperations);
1832  if (!topop)
1833  return false;
1834 
1835  /* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */
1836  if (subquery->sortClause ||
1837  subquery->limitOffset ||
1838  subquery->limitCount ||
1839  subquery->rowMarks ||
1840  subquery->cteList)
1841  return false;
1842 
1843  /* Recursively check the tree of set operations */
1844  return is_simple_union_all_recurse((Node *) topop, subquery,
1845  topop->colTypes);
1846 }
1847 
1848 static bool
1849 is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
1850 {
1851  if (IsA(setOp, RangeTblRef))
1852  {
1853  RangeTblRef *rtr = (RangeTblRef *) setOp;
1854  RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
1855  Query *subquery = rte->subquery;
1856 
1857  Assert(subquery != NULL);
1858 
1859  /* Leaf nodes are OK if they match the toplevel column types */
1860  /* We don't have to compare typmods or collations here */
1861  return tlist_same_datatypes(subquery->targetList, colTypes, true);
1862  }
1863  else if (IsA(setOp, SetOperationStmt))
1864  {
1865  SetOperationStmt *op = (SetOperationStmt *) setOp;
1866 
1867  /* Must be UNION ALL */
1868  if (op->op != SETOP_UNION || !op->all)
1869  return false;
1870 
1871  /* Recurse to check inputs */
1872  return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) &&
1873  is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes);
1874  }
1875  else
1876  {
1877  elog(ERROR, "unrecognized node type: %d",
1878  (int) nodeTag(setOp));
1879  return false; /* keep compiler quiet */
1880  }
1881 }
1882 
1883 /*
1884  * is_safe_append_member
1885  * Check a subquery that is a leaf of a UNION ALL appendrel to see if it's
1886  * safe to pull up.
1887  */
1888 static bool
1890 {
1891  FromExpr *jtnode;
1892 
1893  /*
1894  * It's only safe to pull up the child if its jointree contains exactly
1895  * one RTE, else the AppendRelInfo data structure breaks. The one base RTE
1896  * could be buried in several levels of FromExpr, however. Also, if the
1897  * child's jointree is completely empty, we can pull up because
1898  * pull_up_simple_subquery will insert a single RTE_RESULT RTE instead.
1899  *
1900  * Also, the child can't have any WHERE quals because there's no place to
1901  * put them in an appendrel. (This is a bit annoying...) If we didn't
1902  * need to check this, we'd just test whether get_relids_in_jointree()
1903  * yields a singleton set, to be more consistent with the coding of
1904  * fix_append_rel_relids().
1905  */
1906  jtnode = subquery->jointree;
1907  Assert(IsA(jtnode, FromExpr));
1908  /* Check the completely-empty case */
1909  if (jtnode->fromlist == NIL && jtnode->quals == NULL)
1910  return true;
1911  /* Check the more general case */
1912  while (IsA(jtnode, FromExpr))
1913  {
1914  if (jtnode->quals != NULL)
1915  return false;
1916  if (list_length(jtnode->fromlist) != 1)
1917  return false;
1918  jtnode = linitial(jtnode->fromlist);
1919  }
1920  if (!IsA(jtnode, RangeTblRef))
1921  return false;
1922 
1923  return true;
1924 }
1925 
1926 /*
1927  * jointree_contains_lateral_outer_refs
1928  * Check for disallowed lateral references in a jointree's quals
1929  *
1930  * If restricted is false, all level-1 Vars are allowed (but we still must
1931  * search the jointree, since it might contain outer joins below which there
1932  * will be restrictions). If restricted is true, return true when any qual
1933  * in the jointree contains level-1 Vars coming from outside the rels listed
1934  * in safe_upper_varnos.
1935  */
1936 static bool
1938  bool restricted,
1939  Relids safe_upper_varnos)
1940 {
1941  if (jtnode == NULL)
1942  return false;
1943  if (IsA(jtnode, RangeTblRef))
1944  return false;
1945  else if (IsA(jtnode, FromExpr))
1946  {
1947  FromExpr *f = (FromExpr *) jtnode;
1948  ListCell *l;
1949 
1950  /* First, recurse to check child joins */
1951  foreach(l, f->fromlist)
1952  {
1954  lfirst(l),
1955  restricted,
1956  safe_upper_varnos))
1957  return true;
1958  }
1959 
1960  /* Then check the top-level quals */
1961  if (restricted &&
1963  safe_upper_varnos))
1964  return true;
1965  }
1966  else if (IsA(jtnode, JoinExpr))
1967  {
1968  JoinExpr *j = (JoinExpr *) jtnode;
1969 
1970  /*
1971  * If this is an outer join, we mustn't allow any upper lateral
1972  * references in or below it.
1973  */
1974  if (j->jointype != JOIN_INNER)
1975  {
1976  restricted = true;
1977  safe_upper_varnos = NULL;
1978  }
1979 
1980  /* Check the child joins */
1982  j->larg,
1983  restricted,
1984  safe_upper_varnos))
1985  return true;
1987  j->rarg,
1988  restricted,
1989  safe_upper_varnos))
1990  return true;
1991 
1992  /* Check the JOIN's qual clauses */
1993  if (restricted &&
1995  safe_upper_varnos))
1996  return true;
1997  }
1998  else
1999  elog(ERROR, "unrecognized node type: %d",
2000  (int) nodeTag(jtnode));
2001  return false;
2002 }
2003 
2004 /*
2005  * Perform pullup_replace_vars everyplace it's needed in the query tree.
2006  *
2007  * Caller has already filled *rvcontext with data describing what to
2008  * substitute for Vars referencing the target subquery. In addition
2009  * we need the identity of the lowest outer join that can null the
2010  * target subquery, and its containing appendrel if any.
2011  */
2012 static void
2014  pullup_replace_vars_context *rvcontext,
2015  JoinExpr *lowest_nulling_outer_join,
2016  AppendRelInfo *containing_appendrel)
2017 {
2018  Query *parse = root->parse;
2019  ListCell *lc;
2020 
2021  /*
2022  * Replace all of the top query's references to the subquery's outputs
2023  * with copies of the adjusted subtlist items, being careful not to
2024  * replace any of the jointree structure. (This'd be a lot cleaner if we
2025  * could use query_tree_mutator.) We have to use PHVs in the targetList,
2026  * returningList, and havingQual, since those are certainly above any
2027  * outer join. replace_vars_in_jointree tracks its location in the
2028  * jointree and uses PHVs or not appropriately.
2029  */
2030  parse->targetList = (List *)
2031  pullup_replace_vars((Node *) parse->targetList, rvcontext);
2032  parse->returningList = (List *)
2033  pullup_replace_vars((Node *) parse->returningList, rvcontext);
2034  if (parse->onConflict)
2035  {
2036  parse->onConflict->onConflictSet = (List *)
2038  rvcontext);
2039  parse->onConflict->onConflictWhere =
2041  rvcontext);
2042 
2043  /*
2044  * We assume ON CONFLICT's arbiterElems, arbiterWhere, exclRelTlist
2045  * can't contain any references to a subquery.
2046  */
2047  }
2048  replace_vars_in_jointree((Node *) parse->jointree, rvcontext,
2049  lowest_nulling_outer_join);
2050  Assert(parse->setOperations == NULL);
2051  parse->havingQual = pullup_replace_vars(parse->havingQual, rvcontext);
2052 
2053  /*
2054  * Replace references in the translated_vars lists of appendrels. When
2055  * pulling up an appendrel member, we do not need PHVs in the list of the
2056  * parent appendrel --- there isn't any outer join between. Elsewhere,
2057  * use PHVs for safety. (This analysis could be made tighter but it seems
2058  * unlikely to be worth much trouble.)
2059  */
2060  foreach(lc, root->append_rel_list)
2061  {
2062  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
2063  bool save_need_phvs = rvcontext->need_phvs;
2064 
2065  if (appinfo == containing_appendrel)
2066  rvcontext->need_phvs = false;
2067  appinfo->translated_vars = (List *)
2068  pullup_replace_vars((Node *) appinfo->translated_vars, rvcontext);
2069  rvcontext->need_phvs = save_need_phvs;
2070  }
2071 
2072  /*
2073  * Replace references in the joinaliasvars lists of join RTEs.
2074  *
2075  * You might think that we could avoid using PHVs for alias vars of joins
2076  * below lowest_nulling_outer_join, but that doesn't work because the
2077  * alias vars could be referenced above that join; we need the PHVs to be
2078  * present in such references after the alias vars get flattened. (It
2079  * might be worth trying to be smarter here, someday.)
2080  */
2081  foreach(lc, parse->rtable)
2082  {
2083  RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(lc);
2084 
2085  if (otherrte->rtekind == RTE_JOIN)
2086  otherrte->joinaliasvars = (List *)
2087  pullup_replace_vars((Node *) otherrte->joinaliasvars,
2088  rvcontext);
2089  }
2090 }
2091 
2092 /*
2093  * Helper routine for perform_pullup_replace_vars: do pullup_replace_vars on
2094  * every expression in the jointree, without changing the jointree structure
2095  * itself. Ugly, but there's no other way...
2096  *
2097  * If we are at or below lowest_nulling_outer_join, we can suppress use of
2098  * PlaceHolderVars wrapped around the replacement expressions.
2099  */
2100 static void
2102  pullup_replace_vars_context *context,
2103  JoinExpr *lowest_nulling_outer_join)
2104 {
2105  if (jtnode == NULL)
2106  return;
2107  if (IsA(jtnode, RangeTblRef))
2108  {
2109  /*
2110  * If the RangeTblRef refers to a LATERAL subquery (that isn't the
2111  * same subquery we're pulling up), it might contain references to the
2112  * target subquery, which we must replace. We drive this from the
2113  * jointree scan, rather than a scan of the rtable, for a couple of
2114  * reasons: we can avoid processing no-longer-referenced RTEs, and we
2115  * can use the appropriate setting of need_phvs depending on whether
2116  * the RTE is above possibly-nulling outer joins or not.
2117  */
2118  int varno = ((RangeTblRef *) jtnode)->rtindex;
2119 
2120  if (varno != context->varno) /* ignore target subquery itself */
2121  {
2122  RangeTblEntry *rte = rt_fetch(varno, context->root->parse->rtable);
2123 
2124  Assert(rte != context->target_rte);
2125  if (rte->lateral)
2126  {
2127  switch (rte->rtekind)
2128  {
2129  case RTE_RELATION:
2130  /* shouldn't be marked LATERAL unless tablesample */
2131  Assert(rte->tablesample);
2132  rte->tablesample = (TableSampleClause *)
2134  context);
2135  break;
2136  case RTE_SUBQUERY:
2137  rte->subquery =
2139  context);
2140  break;
2141  case RTE_FUNCTION:
2142  rte->functions = (List *)
2144  context);
2145  break;
2146  case RTE_TABLEFUNC:
2147  rte->tablefunc = (TableFunc *)
2149  context);
2150  break;
2151  case RTE_VALUES:
2152  rte->values_lists = (List *)
2154  context);
2155  break;
2156  case RTE_JOIN:
2157  case RTE_CTE:
2158  case RTE_NAMEDTUPLESTORE:
2159  case RTE_RESULT:
2160  /* these shouldn't be marked LATERAL */
2161  Assert(false);
2162  break;
2163  }
2164  }
2165  }
2166  }
2167  else if (IsA(jtnode, FromExpr))
2168  {
2169  FromExpr *f = (FromExpr *) jtnode;
2170  ListCell *l;
2171 
2172  foreach(l, f->fromlist)
2173  replace_vars_in_jointree(lfirst(l), context,
2174  lowest_nulling_outer_join);
2175  f->quals = pullup_replace_vars(f->quals, context);
2176  }
2177  else if (IsA(jtnode, JoinExpr))
2178  {
2179  JoinExpr *j = (JoinExpr *) jtnode;
2180  bool save_need_phvs = context->need_phvs;
2181 
2182  if (j == lowest_nulling_outer_join)
2183  {
2184  /* no more PHVs in or below this join */
2185  context->need_phvs = false;
2186  lowest_nulling_outer_join = NULL;
2187  }
2188  replace_vars_in_jointree(j->larg, context, lowest_nulling_outer_join);
2189  replace_vars_in_jointree(j->rarg, context, lowest_nulling_outer_join);
2190 
2191  /*
2192  * Use PHVs within the join quals of a full join, even when it's the
2193  * lowest nulling outer join. Otherwise, we cannot identify which
2194  * side of the join a pulled-up var-free expression came from, which
2195  * can lead to failure to make a plan at all because none of the quals
2196  * appear to be mergeable or hashable conditions. For this purpose we
2197  * don't care about the state of wrap_non_vars, so leave it alone.
2198  */
2199  if (j->jointype == JOIN_FULL)
2200  context->need_phvs = true;
2201 
2202  j->quals = pullup_replace_vars(j->quals, context);
2203 
2204  /*
2205  * We don't bother to update the colvars list, since it won't be used
2206  * again ...
2207  */
2208  context->need_phvs = save_need_phvs;
2209  }
2210  else
2211  elog(ERROR, "unrecognized node type: %d",
2212  (int) nodeTag(jtnode));
2213 }
2214 
2215 /*
2216  * Apply pullup variable replacement throughout an expression tree
2217  *
2218  * Returns a modified copy of the tree, so this can't be used where we
2219  * need to do in-place replacement.
2220  */
2221 static Node *
2223 {
2224  return replace_rte_variables(expr,
2225  context->varno, 0,
2227  (void *) context,
2228  context->outer_hasSubLinks);
2229 }
2230 
2231 static Node *
2234 {
2236  int varattno = var->varattno;
2237  Node *newnode;
2238 
2239  /*
2240  * If PlaceHolderVars are needed, we cache the modified expressions in
2241  * rcon->rv_cache[]. This is not in hopes of any material speed gain
2242  * within this function, but to avoid generating identical PHVs with
2243  * different IDs. That would result in duplicate evaluations at runtime,
2244  * and possibly prevent optimizations that rely on recognizing different
2245  * references to the same subquery output as being equal(). So it's worth
2246  * a bit of extra effort to avoid it.
2247  */
2248  if (rcon->need_phvs &&
2249  varattno >= InvalidAttrNumber &&
2250  varattno <= list_length(rcon->targetlist) &&
2251  rcon->rv_cache[varattno] != NULL)
2252  {
2253  /* Just copy the entry and fall through to adjust its varlevelsup */
2254  newnode = copyObject(rcon->rv_cache[varattno]);
2255  }
2256  else if (varattno == InvalidAttrNumber)
2257  {
2258  /* Must expand whole-tuple reference into RowExpr */
2259  RowExpr *rowexpr;
2260  List *colnames;
2261  List *fields;
2262  bool save_need_phvs = rcon->need_phvs;
2263  int save_sublevelsup = context->sublevels_up;
2264 
2265  /*
2266  * If generating an expansion for a var of a named rowtype (ie, this
2267  * is a plain relation RTE), then we must include dummy items for
2268  * dropped columns. If the var is RECORD (ie, this is a JOIN), then
2269  * omit dropped columns. Either way, attach column names to the
2270  * RowExpr for use of ruleutils.c.
2271  *
2272  * In order to be able to cache the results, we always generate the
2273  * expansion with varlevelsup = 0, and then adjust if needed.
2274  */
2275  expandRTE(rcon->target_rte,
2276  var->varno, 0 /* not varlevelsup */ , var->location,
2277  (var->vartype != RECORDOID),
2278  &colnames, &fields);
2279  /* Adjust the generated per-field Vars, but don't insert PHVs */
2280  rcon->need_phvs = false;
2281  context->sublevels_up = 0; /* to match the expandRTE output */
2282  fields = (List *) replace_rte_variables_mutator((Node *) fields,
2283  context);
2284  rcon->need_phvs = save_need_phvs;
2285  context->sublevels_up = save_sublevelsup;
2286 
2287  rowexpr = makeNode(RowExpr);
2288  rowexpr->args = fields;
2289  rowexpr->row_typeid = var->vartype;
2290  rowexpr->row_format = COERCE_IMPLICIT_CAST;
2291  rowexpr->colnames = colnames;
2292  rowexpr->location = var->location;
2293  newnode = (Node *) rowexpr;
2294 
2295  /*
2296  * Insert PlaceHolderVar if needed. Notice that we are wrapping one
2297  * PlaceHolderVar around the whole RowExpr, rather than putting one
2298  * around each element of the row. This is because we need the
2299  * expression to yield NULL, not ROW(NULL,NULL,...) when it is forced
2300  * to null by an outer join.
2301  */
2302  if (rcon->need_phvs)
2303  {
2304  /* RowExpr is certainly not strict, so always need PHV */
2305  newnode = (Node *)
2307  (Expr *) newnode,
2308  bms_make_singleton(rcon->varno));
2309  /* cache it with the PHV, and with varlevelsup still zero */
2310  rcon->rv_cache[InvalidAttrNumber] = copyObject(newnode);
2311  }
2312  }
2313  else
2314  {
2315  /* Normal case referencing one targetlist element */
2316  TargetEntry *tle = get_tle_by_resno(rcon->targetlist, varattno);
2317 
2318  if (tle == NULL) /* shouldn't happen */
2319  elog(ERROR, "could not find attribute %d in subquery targetlist",
2320  varattno);
2321 
2322  /* Make a copy of the tlist item to return */
2323  newnode = (Node *) copyObject(tle->expr);
2324 
2325  /* Insert PlaceHolderVar if needed */
2326  if (rcon->need_phvs)
2327  {
2328  bool wrap;
2329 
2330  if (newnode && IsA(newnode, Var) &&
2331  ((Var *) newnode)->varlevelsup == 0)
2332  {
2333  /*
2334  * Simple Vars always escape being wrapped, unless they are
2335  * lateral references to something outside the subquery being
2336  * pulled up. (Even then, we could omit the PlaceHolderVar if
2337  * the referenced rel is under the same lowest outer join, but
2338  * it doesn't seem worth the trouble to check that.)
2339  */
2340  if (rcon->target_rte->lateral &&
2341  !bms_is_member(((Var *) newnode)->varno, rcon->relids))
2342  wrap = true;
2343  else
2344  wrap = false;
2345  }
2346  else if (newnode && IsA(newnode, PlaceHolderVar) &&
2347  ((PlaceHolderVar *) newnode)->phlevelsup == 0)
2348  {
2349  /* No need to wrap a PlaceHolderVar with another one, either */
2350  wrap = false;
2351  }
2352  else if (rcon->wrap_non_vars)
2353  {
2354  /* Wrap all non-Vars in a PlaceHolderVar */
2355  wrap = true;
2356  }
2357  else
2358  {
2359  /*
2360  * If it contains a Var of the subquery being pulled up, and
2361  * does not contain any non-strict constructs, then it's
2362  * certainly nullable so we don't need to insert a
2363  * PlaceHolderVar.
2364  *
2365  * This analysis could be tighter: in particular, a non-strict
2366  * construct hidden within a lower-level PlaceHolderVar is not
2367  * reason to add another PHV. But for now it doesn't seem
2368  * worth the code to be more exact.
2369  *
2370  * Note: in future maybe we should insert a PlaceHolderVar
2371  * anyway, if the tlist item is expensive to evaluate?
2372  *
2373  * For a LATERAL subquery, we have to check the actual var
2374  * membership of the node, but if it's non-lateral then any
2375  * level-zero var must belong to the subquery.
2376  */
2377  if ((rcon->target_rte->lateral ?
2378  bms_overlap(pull_varnos(rcon->root, (Node *) newnode),
2379  rcon->relids) :
2380  contain_vars_of_level((Node *) newnode, 0)) &&
2381  !contain_nonstrict_functions((Node *) newnode))
2382  {
2383  /* No wrap needed */
2384  wrap = false;
2385  }
2386  else
2387  {
2388  /* Else wrap it in a PlaceHolderVar */
2389  wrap = true;
2390  }
2391  }
2392 
2393  if (wrap)
2394  newnode = (Node *)
2396  (Expr *) newnode,
2397  bms_make_singleton(rcon->varno));
2398 
2399  /*
2400  * Cache it if possible (ie, if the attno is in range, which it
2401  * probably always should be). We can cache the value even if we
2402  * decided we didn't need a PHV, since this result will be
2403  * suitable for any request that has need_phvs.
2404  */
2405  if (varattno > InvalidAttrNumber &&
2406  varattno <= list_length(rcon->targetlist))
2407  rcon->rv_cache[varattno] = copyObject(newnode);
2408  }
2409  }
2410 
2411  /* Must adjust varlevelsup if tlist item is from higher query */
2412  if (var->varlevelsup > 0)
2413  IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
2414 
2415  return newnode;
2416 }
2417 
2418 /*
2419  * Apply pullup variable replacement to a subquery
2420  *
2421  * This needs to be different from pullup_replace_vars() because
2422  * replace_rte_variables will think that it shouldn't increment sublevels_up
2423  * before entering the Query; so we need to call it with sublevels_up == 1.
2424  */
2425 static Query *
2427  pullup_replace_vars_context *context)
2428 {
2429  Assert(IsA(query, Query));
2430  return (Query *) replace_rte_variables((Node *) query,
2431  context->varno, 1,
2433  (void *) context,
2434  NULL);
2435 }
2436 
2437 
2438 /*
2439  * flatten_simple_union_all
2440  * Try to optimize top-level UNION ALL structure into an appendrel
2441  *
2442  * If a query's setOperations tree consists entirely of simple UNION ALL
2443  * operations, flatten it into an append relation, which we can process more
2444  * intelligently than the general setops case. Otherwise, do nothing.
2445  *
2446  * In most cases, this can succeed only for a top-level query, because for a
2447  * subquery in FROM, the parent query's invocation of pull_up_subqueries would
2448  * already have flattened the UNION via pull_up_simple_union_all. But there
2449  * are a few cases we can support here but not in that code path, for example
2450  * when the subquery also contains ORDER BY.
2451  */
2452 void
2454 {
2455  Query *parse = root->parse;
2456  SetOperationStmt *topop;
2457  Node *leftmostjtnode;
2458  int leftmostRTI;
2459  RangeTblEntry *leftmostRTE;
2460  int childRTI;
2461  RangeTblEntry *childRTE;
2462  RangeTblRef *rtr;
2463 
2464  /* Shouldn't be called unless query has setops */
2465  topop = castNode(SetOperationStmt, parse->setOperations);
2466  Assert(topop);
2467 
2468  /* Can't optimize away a recursive UNION */
2469  if (root->hasRecursion)
2470  return;
2471 
2472  /*
2473  * Recursively check the tree of set operations. If not all UNION ALL
2474  * with identical column types, punt.
2475  */
2476  if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2477  return;
2478 
2479  /*
2480  * Locate the leftmost leaf query in the setops tree. The upper query's
2481  * Vars all refer to this RTE (see transformSetOperationStmt).
2482  */
2483  leftmostjtnode = topop->larg;
2484  while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2485  leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2486  Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2487  leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2488  leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2489  Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2490 
2491  /*
2492  * Make a copy of the leftmost RTE and add it to the rtable. This copy
2493  * will represent the leftmost leaf query in its capacity as a member of
2494  * the appendrel. The original will represent the appendrel as a whole.
2495  * (We must do things this way because the upper query's Vars have to be
2496  * seen as referring to the whole appendrel.)
2497  */
2498  childRTE = copyObject(leftmostRTE);
2499  parse->rtable = lappend(parse->rtable, childRTE);
2500  childRTI = list_length(parse->rtable);
2501 
2502  /* Modify the setops tree to reference the child copy */
2503  ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2504 
2505  /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2506  leftmostRTE->inh = true;
2507 
2508  /*
2509  * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2510  * Query of a setops tree should have had an empty FromClause initially.
2511  */
2512  rtr = makeNode(RangeTblRef);
2513  rtr->rtindex = leftmostRTI;
2514  Assert(parse->jointree->fromlist == NIL);
2515  parse->jointree->fromlist = list_make1(rtr);
2516 
2517  /*
2518  * Now pretend the query has no setops. We must do this before trying to
2519  * do subquery pullup, because of Assert in pull_up_simple_subquery.
2520  */
2521  parse->setOperations = NULL;
2522 
2523  /*
2524  * Build AppendRelInfo information, and apply pull_up_subqueries to the
2525  * leaf queries of the UNION ALL. (We must do that now because they
2526  * weren't previously referenced by the jointree, and so were missed by
2527  * the main invocation of pull_up_subqueries.)
2528  */
2529  pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2530 }
2531 
2532 
2533 /*
2534  * reduce_outer_joins
2535  * Attempt to reduce outer joins to plain inner joins.
2536  *
2537  * The idea here is that given a query like
2538  * SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
2539  * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
2540  * is strict. The strict operator will always return NULL, causing the outer
2541  * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
2542  * columns. Therefore, there's no need for the join to produce null-extended
2543  * rows in the first place --- which makes it a plain join not an outer join.
2544  * (This scenario may not be very likely in a query written out by hand, but
2545  * it's reasonably likely when pushing quals down into complex views.)
2546  *
2547  * More generally, an outer join can be reduced in strength if there is a
2548  * strict qual above it in the qual tree that constrains a Var from the
2549  * nullable side of the join to be non-null. (For FULL joins this applies
2550  * to each side separately.)
2551  *
2552  * Another transformation we apply here is to recognize cases like
2553  * SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.y IS NULL;
2554  * If the join clause is strict for b.y, then only null-extended rows could
2555  * pass the upper WHERE, and we can conclude that what the query is really
2556  * specifying is an anti-semijoin. We change the join type from JOIN_LEFT
2557  * to JOIN_ANTI. The IS NULL clause then becomes redundant, and must be
2558  * removed to prevent bogus selectivity calculations, but we leave it to
2559  * distribute_qual_to_rels to get rid of such clauses.
2560  *
2561  * Also, we get rid of JOIN_RIGHT cases by flipping them around to become
2562  * JOIN_LEFT. This saves some code here and in some later planner routines,
2563  * but the main reason to do it is to not need to invent a JOIN_REVERSE_ANTI
2564  * join type.
2565  *
2566  * To ease recognition of strict qual clauses, we require this routine to be
2567  * run after expression preprocessing (i.e., qual canonicalization and JOIN
2568  * alias-var expansion).
2569  */
2570 void
2572 {
2574 
2575  /*
2576  * To avoid doing strictness checks on more quals than necessary, we want
2577  * to stop descending the jointree as soon as there are no outer joins
2578  * below our current point. This consideration forces a two-pass process.
2579  * The first pass gathers information about which base rels appear below
2580  * each side of each join clause, and about whether there are outer
2581  * join(s) below each side of each join clause. The second pass examines
2582  * qual clauses and changes join types as it descends the tree.
2583  */
2584  state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
2585 
2586  /* planner.c shouldn't have called me if no outer joins */
2587  if (state == NULL || !state->contains_outer)
2588  elog(ERROR, "so where are the outer joins?");
2589 
2591  state, root, NULL, NIL, NIL);
2592 }
2593 
2594 /*
2595  * reduce_outer_joins_pass1 - phase 1 data collection
2596  *
2597  * Returns a state node describing the given jointree node.
2598  */
2599 static reduce_outer_joins_state *
2601 {
2602  reduce_outer_joins_state *result;
2603 
2604  result = (reduce_outer_joins_state *)
2606  result->relids = NULL;
2607  result->contains_outer = false;
2608  result->sub_states = NIL;
2609 
2610  if (jtnode == NULL)
2611  return result;
2612  if (IsA(jtnode, RangeTblRef))
2613  {
2614  int varno = ((RangeTblRef *) jtnode)->rtindex;
2615 
2616  result->relids = bms_make_singleton(varno);
2617  }
2618  else if (IsA(jtnode, FromExpr))
2619  {
2620  FromExpr *f = (FromExpr *) jtnode;
2621  ListCell *l;
2622 
2623  foreach(l, f->fromlist)
2624  {
2625  reduce_outer_joins_state *sub_state;
2626 
2627  sub_state = reduce_outer_joins_pass1(lfirst(l));
2628  result->relids = bms_add_members(result->relids,
2629  sub_state->relids);
2630  result->contains_outer |= sub_state->contains_outer;
2631  result->sub_states = lappend(result->sub_states, sub_state);
2632  }
2633  }
2634  else if (IsA(jtnode, JoinExpr))
2635  {
2636  JoinExpr *j = (JoinExpr *) jtnode;
2637  reduce_outer_joins_state *sub_state;
2638 
2639  /* join's own RT index is not wanted in result->relids */
2640  if (IS_OUTER_JOIN(j->jointype))
2641  result->contains_outer = true;
2642 
2643  sub_state = reduce_outer_joins_pass1(j->larg);
2644  result->relids = bms_add_members(result->relids,
2645  sub_state->relids);
2646  result->contains_outer |= sub_state->contains_outer;
2647  result->sub_states = lappend(result->sub_states, sub_state);
2648 
2649  sub_state = reduce_outer_joins_pass1(j->rarg);
2650  result->relids = bms_add_members(result->relids,
2651  sub_state->relids);
2652  result->contains_outer |= sub_state->contains_outer;
2653  result->sub_states = lappend(result->sub_states, sub_state);
2654  }
2655  else
2656  elog(ERROR, "unrecognized node type: %d",
2657  (int) nodeTag(jtnode));
2658  return result;
2659 }
2660 
2661 /*
2662  * reduce_outer_joins_pass2 - phase 2 processing
2663  *
2664  * jtnode: current jointree node
2665  * state: state data collected by phase 1 for this node
2666  * root: toplevel planner state
2667  * nonnullable_rels: set of base relids forced non-null by upper quals
2668  * nonnullable_vars: list of Vars forced non-null by upper quals
2669  * forced_null_vars: list of Vars forced null by upper quals
2670  */
2671 static void
2674  PlannerInfo *root,
2675  Relids nonnullable_rels,
2676  List *nonnullable_vars,
2677  List *forced_null_vars)
2678 {
2679  /*
2680  * pass 2 should never descend as far as an empty subnode or base rel,
2681  * because it's only called on subtrees marked as contains_outer.
2682  */
2683  if (jtnode == NULL)
2684  elog(ERROR, "reached empty jointree");
2685  if (IsA(jtnode, RangeTblRef))
2686  elog(ERROR, "reached base rel");
2687  else if (IsA(jtnode, FromExpr))
2688  {
2689  FromExpr *f = (FromExpr *) jtnode;
2690  ListCell *l;
2691  ListCell *s;
2692  Relids pass_nonnullable_rels;
2693  List *pass_nonnullable_vars;
2694  List *pass_forced_null_vars;
2695 
2696  /* Scan quals to see if we can add any constraints */
2697  pass_nonnullable_rels = find_nonnullable_rels(f->quals);
2698  pass_nonnullable_rels = bms_add_members(pass_nonnullable_rels,
2699  nonnullable_rels);
2700  pass_nonnullable_vars = find_nonnullable_vars(f->quals);
2701  pass_nonnullable_vars = list_concat(pass_nonnullable_vars,
2702  nonnullable_vars);
2703  pass_forced_null_vars = find_forced_null_vars(f->quals);
2704  pass_forced_null_vars = list_concat(pass_forced_null_vars,
2705  forced_null_vars);
2706  /* And recurse --- but only into interesting subtrees */
2708  forboth(l, f->fromlist, s, state->sub_states)
2709  {
2710  reduce_outer_joins_state *sub_state = lfirst(s);
2711 
2712  if (sub_state->contains_outer)
2713  reduce_outer_joins_pass2(lfirst(l), sub_state, root,
2714  pass_nonnullable_rels,
2715  pass_nonnullable_vars,
2716  pass_forced_null_vars);
2717  }
2718  bms_free(pass_nonnullable_rels);
2719  /* can't so easily clean up var lists, unfortunately */
2720  }
2721  else if (IsA(jtnode, JoinExpr))
2722  {
2723  JoinExpr *j = (JoinExpr *) jtnode;
2724  int rtindex = j->rtindex;
2725  JoinType jointype = j->jointype;
2726  reduce_outer_joins_state *left_state = linitial(state->sub_states);
2727  reduce_outer_joins_state *right_state = lsecond(state->sub_states);
2728  List *local_nonnullable_vars = NIL;
2729  bool computed_local_nonnullable_vars = false;
2730 
2731  /* Can we simplify this join? */
2732  switch (jointype)
2733  {
2734  case JOIN_INNER:
2735  break;
2736  case JOIN_LEFT:
2737  if (bms_overlap(nonnullable_rels, right_state->relids))
2738  jointype = JOIN_INNER;
2739  break;
2740  case JOIN_RIGHT:
2741  if (bms_overlap(nonnullable_rels, left_state->relids))
2742  jointype = JOIN_INNER;
2743  break;
2744  case JOIN_FULL:
2745  if (bms_overlap(nonnullable_rels, left_state->relids))
2746  {
2747  if (bms_overlap(nonnullable_rels, right_state->relids))
2748  jointype = JOIN_INNER;
2749  else
2750  jointype = JOIN_LEFT;
2751  }
2752  else
2753  {
2754  if (bms_overlap(nonnullable_rels, right_state->relids))
2755  jointype = JOIN_RIGHT;
2756  }
2757  break;
2758  case JOIN_SEMI:
2759  case JOIN_ANTI:
2760 
2761  /*
2762  * These could only have been introduced by pull_up_sublinks,
2763  * so there's no way that upper quals could refer to their
2764  * righthand sides, and no point in checking.
2765  */
2766  break;
2767  default:
2768  elog(ERROR, "unrecognized join type: %d",
2769  (int) jointype);
2770  break;
2771  }
2772 
2773  /*
2774  * Convert JOIN_RIGHT to JOIN_LEFT. Note that in the case where we
2775  * reduced JOIN_FULL to JOIN_RIGHT, this will mean the JoinExpr no
2776  * longer matches the internal ordering of any CoalesceExpr's built to
2777  * represent merged join variables. We don't care about that at
2778  * present, but be wary of it ...
2779  */
2780  if (jointype == JOIN_RIGHT)
2781  {
2782  Node *tmparg;
2783 
2784  tmparg = j->larg;
2785  j->larg = j->rarg;
2786  j->rarg = tmparg;
2787  jointype = JOIN_LEFT;
2788  right_state = linitial(state->sub_states);
2789  left_state = lsecond(state->sub_states);
2790  }
2791 
2792  /*
2793  * See if we can reduce JOIN_LEFT to JOIN_ANTI. This is the case if
2794  * the join's own quals are strict for any var that was forced null by
2795  * higher qual levels. NOTE: there are other ways that we could
2796  * detect an anti-join, in particular if we were to check whether Vars
2797  * coming from the RHS must be non-null because of table constraints.
2798  * That seems complicated and expensive though (in particular, one
2799  * would have to be wary of lower outer joins). For the moment this
2800  * seems sufficient.
2801  */
2802  if (jointype == JOIN_LEFT)
2803  {
2804  List *overlap;
2805 
2806  local_nonnullable_vars = find_nonnullable_vars(j->quals);
2807  computed_local_nonnullable_vars = true;
2808 
2809  /*
2810  * It's not sufficient to check whether local_nonnullable_vars and
2811  * forced_null_vars overlap: we need to know if the overlap
2812  * includes any RHS variables.
2813  */
2814  overlap = list_intersection(local_nonnullable_vars,
2815  forced_null_vars);
2816  if (overlap != NIL &&
2817  bms_overlap(pull_varnos(root, (Node *) overlap),
2818  right_state->relids))
2819  jointype = JOIN_ANTI;
2820  }
2821 
2822  /* Apply the jointype change, if any, to both jointree node and RTE */
2823  if (rtindex && jointype != j->jointype)
2824  {
2825  RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
2826 
2827  Assert(rte->rtekind == RTE_JOIN);
2828  Assert(rte->jointype == j->jointype);
2829  rte->jointype = jointype;
2830  }
2831  j->jointype = jointype;
2832 
2833  /* Only recurse if there's more to do below here */
2834  if (left_state->contains_outer || right_state->contains_outer)
2835  {
2836  Relids local_nonnullable_rels;
2837  List *local_forced_null_vars;
2838  Relids pass_nonnullable_rels;
2839  List *pass_nonnullable_vars;
2840  List *pass_forced_null_vars;
2841 
2842  /*
2843  * If this join is (now) inner, we can add any constraints its
2844  * quals provide to those we got from above. But if it is outer,
2845  * we can pass down the local constraints only into the nullable
2846  * side, because an outer join never eliminates any rows from its
2847  * non-nullable side. Also, there is no point in passing upper
2848  * constraints into the nullable side, since if there were any
2849  * we'd have been able to reduce the join. (In the case of upper
2850  * forced-null constraints, we *must not* pass them into the
2851  * nullable side --- they either applied here, or not.) The upshot
2852  * is that we pass either the local or the upper constraints,
2853  * never both, to the children of an outer join.
2854  *
2855  * Note that a SEMI join works like an inner join here: it's okay
2856  * to pass down both local and upper constraints. (There can't be
2857  * any upper constraints affecting its inner side, but it's not
2858  * worth having a separate code path to avoid passing them.)
2859  *
2860  * At a FULL join we just punt and pass nothing down --- is it
2861  * possible to be smarter?
2862  */
2863  if (jointype != JOIN_FULL)
2864  {
2865  local_nonnullable_rels = find_nonnullable_rels(j->quals);
2866  if (!computed_local_nonnullable_vars)
2867  local_nonnullable_vars = find_nonnullable_vars(j->quals);
2868  local_forced_null_vars = find_forced_null_vars(j->quals);
2869  if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
2870  {
2871  /* OK to merge upper and local constraints */
2872  local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
2873  nonnullable_rels);
2874  local_nonnullable_vars = list_concat(local_nonnullable_vars,
2875  nonnullable_vars);
2876  local_forced_null_vars = list_concat(local_forced_null_vars,
2877  forced_null_vars);
2878  }
2879  }
2880  else
2881  {
2882  /* no use in calculating these */
2883  local_nonnullable_rels = NULL;
2884  local_forced_null_vars = NIL;
2885  }
2886 
2887  if (left_state->contains_outer)
2888  {
2889  if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
2890  {
2891  /* pass union of local and upper constraints */
2892  pass_nonnullable_rels = local_nonnullable_rels;
2893  pass_nonnullable_vars = local_nonnullable_vars;
2894  pass_forced_null_vars = local_forced_null_vars;
2895  }
2896  else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
2897  {
2898  /* can't pass local constraints to non-nullable side */
2899  pass_nonnullable_rels = nonnullable_rels;
2900  pass_nonnullable_vars = nonnullable_vars;
2901  pass_forced_null_vars = forced_null_vars;
2902  }
2903  else
2904  {
2905  /* no constraints pass through JOIN_FULL */
2906  pass_nonnullable_rels = NULL;
2907  pass_nonnullable_vars = NIL;
2908  pass_forced_null_vars = NIL;
2909  }
2910  reduce_outer_joins_pass2(j->larg, left_state, root,
2911  pass_nonnullable_rels,
2912  pass_nonnullable_vars,
2913  pass_forced_null_vars);
2914  }
2915 
2916  if (right_state->contains_outer)
2917  {
2918  if (jointype != JOIN_FULL) /* ie, INNER/LEFT/SEMI/ANTI */
2919  {
2920  /* pass appropriate constraints, per comment above */
2921  pass_nonnullable_rels = local_nonnullable_rels;
2922  pass_nonnullable_vars = local_nonnullable_vars;
2923  pass_forced_null_vars = local_forced_null_vars;
2924  }
2925  else
2926  {
2927  /* no constraints pass through JOIN_FULL */
2928  pass_nonnullable_rels = NULL;
2929  pass_nonnullable_vars = NIL;
2930  pass_forced_null_vars = NIL;
2931  }
2932  reduce_outer_joins_pass2(j->rarg, right_state, root,
2933  pass_nonnullable_rels,
2934  pass_nonnullable_vars,
2935  pass_forced_null_vars);
2936  }
2937  bms_free(local_nonnullable_rels);
2938  }
2939  }
2940  else
2941  elog(ERROR, "unrecognized node type: %d",
2942  (int) nodeTag(jtnode));
2943 }
2944 
2945 
2946 /*
2947  * remove_useless_result_rtes
2948  * Attempt to remove RTE_RESULT RTEs from the join tree.
2949  *
2950  * We can remove RTE_RESULT entries from the join tree using the knowledge
2951  * that RTE_RESULT returns exactly one row and has no output columns. Hence,
2952  * if one is inner-joined to anything else, we can delete it. Optimizations
2953  * are also possible for some outer-join cases, as detailed below.
2954  *
2955  * Some of these optimizations depend on recognizing empty (constant-true)
2956  * quals for FromExprs and JoinExprs. That makes it useful to apply this
2957  * optimization pass after expression preprocessing, since that will have
2958  * eliminated constant-true quals, allowing more cases to be recognized as
2959  * optimizable. What's more, the usual reason for an RTE_RESULT to be present
2960  * is that we pulled up a subquery or VALUES clause, thus very possibly
2961  * replacing Vars with constants, making it more likely that a qual can be
2962  * reduced to constant true. Also, because some optimizations depend on
2963  * the outer-join type, it's best to have done reduce_outer_joins() first.
2964  *
2965  * A PlaceHolderVar referencing an RTE_RESULT RTE poses an obstacle to this
2966  * process: we must remove the RTE_RESULT's relid from the PHV's phrels, but
2967  * we must not reduce the phrels set to empty. If that would happen, and
2968  * the RTE_RESULT is an immediate child of an outer join, we have to give up
2969  * and not remove the RTE_RESULT: there is noplace else to evaluate the
2970  * PlaceHolderVar. (That is, in such cases the RTE_RESULT *does* have output
2971  * columns.) But if the RTE_RESULT is an immediate child of an inner join,
2972  * we can usually change the PlaceHolderVar's phrels so as to evaluate it at
2973  * the inner join instead. This is OK because we really only care that PHVs
2974  * are evaluated above or below the correct outer joins. We can't, however,
2975  * postpone the evaluation of a PHV to above where it is used; so there are
2976  * some checks below on whether output PHVs are laterally referenced in the
2977  * other join input rel(s).
2978  *
2979  * We used to try to do this work as part of pull_up_subqueries() where the
2980  * potentially-optimizable cases get introduced; but it's way simpler, and
2981  * more effective, to do it separately.
2982  */
2983 void
2985 {
2986  ListCell *cell;
2987 
2988  /* Top level of jointree must always be a FromExpr */
2989  Assert(IsA(root->parse->jointree, FromExpr));
2990  /* Recurse ... */
2991  root->parse->jointree = (FromExpr *)
2993  /* We should still have a FromExpr */
2994  Assert(IsA(root->parse->jointree, FromExpr));
2995 
2996  /*
2997  * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
2998  * must do that for any RTE_RESULT that we just removed. But one for a
2999  * RTE that we did not remove can be dropped anyway: since the RTE has
3000  * only one possible output row, there is no need for EPQ to mark and
3001  * restore that row.
3002  *
3003  * It's necessary, not optional, to remove the PlanRowMark for a surviving
3004  * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
3005  * RTE_RESULT, which the executor has no support for.
3006  */
3007  foreach(cell, root->rowMarks)
3008  {
3009  PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3010 
3011  if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
3012  root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3013  }
3014 }
3015 
3016 /*
3017  * remove_useless_results_recurse
3018  * Recursive guts of remove_useless_result_rtes.
3019  *
3020  * This recursively processes the jointree and returns a modified jointree.
3021  */
3022 static Node *
3024 {
3025  Assert(jtnode != NULL);
3026  if (IsA(jtnode, RangeTblRef))
3027  {
3028  /* Can't immediately do anything with a RangeTblRef */
3029  }
3030  else if (IsA(jtnode, FromExpr))
3031  {
3032  FromExpr *f = (FromExpr *) jtnode;
3033  Relids result_relids = NULL;
3034  ListCell *cell;
3035 
3036  /*
3037  * We can drop RTE_RESULT rels from the fromlist so long as at least
3038  * one child remains, since joining to a one-row table changes
3039  * nothing. (But we can't drop a RTE_RESULT that computes PHV(s) that
3040  * are needed by some sibling. The cleanup transformation below would
3041  * reassign the PHVs to be computed at the join, which is too late for
3042  * the sibling's use.) The easiest way to mechanize this rule is to
3043  * modify the list in-place.
3044  */
3045  foreach(cell, f->fromlist)
3046  {
3047  Node *child = (Node *) lfirst(cell);
3048  int varno;
3049 
3050  /* Recursively transform child ... */
3051  child = remove_useless_results_recurse(root, child);
3052  /* ... and stick it back into the tree */
3053  lfirst(cell) = child;
3054 
3055  /*
3056  * If it's an RTE_RESULT with at least one sibling, and no sibling
3057  * references dependent PHVs, we can drop it. We don't yet know
3058  * what the inner join's final relid set will be, so postpone
3059  * cleanup of PHVs etc till after this loop.
3060  */
3061  if (list_length(f->fromlist) > 1 &&
3062  (varno = get_result_relid(root, child)) != 0 &&
3063  !find_dependent_phvs_in_jointree(root, (Node *) f, varno))
3064  {
3065  f->fromlist = foreach_delete_current(f->fromlist, cell);
3066  result_relids = bms_add_member(result_relids, varno);
3067  }
3068  }
3069 
3070  /*
3071  * Clean up if we dropped any RTE_RESULT RTEs. This is a bit
3072  * inefficient if there's more than one, but it seems better to
3073  * optimize the support code for the single-relid case.
3074  */
3075  if (result_relids)
3076  {
3077  int varno = -1;
3078 
3079  while ((varno = bms_next_member(result_relids, varno)) >= 0)
3080  remove_result_refs(root, varno, (Node *) f);
3081  }
3082 
3083  /*
3084  * If we're not at the top of the jointree, it's valid to simplify a
3085  * degenerate FromExpr into its single child. (At the top, we must
3086  * keep the FromExpr since Query.jointree is required to point to a
3087  * FromExpr.)
3088  */
3089  if (f != root->parse->jointree &&
3090  f->quals == NULL &&
3091  list_length(f->fromlist) == 1)
3092  return (Node *) linitial(f->fromlist);
3093  }
3094  else if (IsA(jtnode, JoinExpr))
3095  {
3096  JoinExpr *j = (JoinExpr *) jtnode;
3097  int varno;
3098 
3099  /* First, recurse */
3100  j->larg = remove_useless_results_recurse(root, j->larg);
3101  j->rarg = remove_useless_results_recurse(root, j->rarg);
3102 
3103  /* Apply join-type-specific optimization rules */
3104  switch (j->jointype)
3105  {
3106  case JOIN_INNER:
3107 
3108  /*
3109  * An inner join is equivalent to a FromExpr, so if either
3110  * side was simplified to an RTE_RESULT rel, we can replace
3111  * the join with a FromExpr with just the other side; and if
3112  * the qual is empty (JOIN ON TRUE) then we can omit the
3113  * FromExpr as well.
3114  *
3115  * Just as in the FromExpr case, we can't simplify if the
3116  * other input rel references any PHVs that are marked as to
3117  * be evaluated at the RTE_RESULT rel, because we can't
3118  * postpone their evaluation in that case. But we only have
3119  * to check this in cases where it's syntactically legal for
3120  * the other input to have a LATERAL reference to the
3121  * RTE_RESULT rel. Only RHSes of inner and left joins are
3122  * allowed to have such refs.
3123  */
3124  if ((varno = get_result_relid(root, j->larg)) != 0 &&
3125  !find_dependent_phvs_in_jointree(root, j->rarg, varno))
3126  {
3127  remove_result_refs(root, varno, j->rarg);
3128  if (j->quals)
3129  jtnode = (Node *)
3130  makeFromExpr(list_make1(j->rarg), j->quals);
3131  else
3132  jtnode = j->rarg;
3133  }
3134  else if ((varno = get_result_relid(root, j->rarg)) != 0)
3135  {
3136  remove_result_refs(root, varno, j->larg);
3137  if (j->quals)
3138  jtnode = (Node *)
3139  makeFromExpr(list_make1(j->larg), j->quals);
3140  else
3141  jtnode = j->larg;
3142  }
3143  break;
3144  case JOIN_LEFT:
3145 
3146  /*
3147  * We can simplify this case if the RHS is an RTE_RESULT, with
3148  * two different possibilities:
3149  *
3150  * If the qual is empty (JOIN ON TRUE), then the join can be
3151  * strength-reduced to a plain inner join, since each LHS row
3152  * necessarily has exactly one join partner. So we can always
3153  * discard the RHS, much as in the JOIN_INNER case above.
3154  * (Again, the LHS could not contain a lateral reference to
3155  * the RHS.)
3156  *
3157  * Otherwise, it's still true that each LHS row should be
3158  * returned exactly once, and since the RHS returns no columns
3159  * (unless there are PHVs that have to be evaluated there), we
3160  * don't much care if it's null-extended or not. So in this
3161  * case also, we can just ignore the qual and discard the left
3162  * join.
3163  */
3164  if ((varno = get_result_relid(root, j->rarg)) != 0 &&
3165  (j->quals == NULL ||
3166  !find_dependent_phvs(root, varno)))
3167  {
3168  remove_result_refs(root, varno, j->larg);
3169  jtnode = j->larg;
3170  }
3171  break;
3172  case JOIN_RIGHT:
3173  /* Mirror-image of the JOIN_LEFT case */
3174  if ((varno = get_result_relid(root, j->larg)) != 0 &&
3175  (j->quals == NULL ||
3176  !find_dependent_phvs(root, varno)))
3177  {
3178  remove_result_refs(root, varno, j->rarg);
3179  jtnode = j->rarg;
3180  }
3181  break;
3182  case JOIN_SEMI:
3183 
3184  /*
3185  * We may simplify this case if the RHS is an RTE_RESULT; the
3186  * join qual becomes effectively just a filter qual for the
3187  * LHS, since we should either return the LHS row or not. For
3188  * simplicity we inject the filter qual into a new FromExpr.
3189  *
3190  * Unlike the LEFT/RIGHT cases, we just Assert that there are
3191  * no PHVs that need to be evaluated at the semijoin's RHS,
3192  * since the rest of the query couldn't reference any outputs
3193  * of the semijoin's RHS.
3194  */
3195  if ((varno = get_result_relid(root, j->rarg)) != 0)
3196  {
3197  Assert(!find_dependent_phvs(root, varno));
3198  remove_result_refs(root, varno, j->larg);
3199  if (j->quals)
3200  jtnode = (Node *)
3201  makeFromExpr(list_make1(j->larg), j->quals);
3202  else
3203  jtnode = j->larg;
3204  }
3205  break;
3206  case JOIN_FULL:
3207  case JOIN_ANTI:
3208  /* We have no special smarts for these cases */
3209  break;
3210  default:
3211  elog(ERROR, "unrecognized join type: %d",
3212  (int) j->jointype);
3213  break;
3214  }
3215  }
3216  else
3217  elog(ERROR, "unrecognized node type: %d",
3218  (int) nodeTag(jtnode));
3219  return jtnode;
3220 }
3221 
3222 /*
3223  * get_result_relid
3224  * If jtnode is a RangeTblRef for an RTE_RESULT RTE, return its relid;
3225  * otherwise return 0.
3226  */
3227 static int
3229 {
3230  int varno;
3231 
3232  if (!IsA(jtnode, RangeTblRef))
3233  return 0;
3234  varno = ((RangeTblRef *) jtnode)->rtindex;
3235  if (rt_fetch(varno, root->parse->rtable)->rtekind != RTE_RESULT)
3236  return 0;
3237  return varno;
3238 }
3239 
3240 /*
3241  * remove_result_refs
3242  * Helper routine for dropping an unneeded RTE_RESULT RTE.
3243  *
3244  * This doesn't physically remove the RTE from the jointree, because that's
3245  * more easily handled in remove_useless_results_recurse. What it does do
3246  * is the necessary cleanup in the rest of the tree: we must adjust any PHVs
3247  * that may reference the RTE. Be sure to call this at a point where the
3248  * jointree is valid (no disconnected nodes).
3249  *
3250  * Note that we don't need to process the append_rel_list, since RTEs
3251  * referenced directly in the jointree won't be appendrel members.
3252  *
3253  * varno is the RTE_RESULT's relid.
3254  * newjtloc is the jointree location at which any PHVs referencing the
3255  * RTE_RESULT should be evaluated instead.
3256  */
3257 static void
3259 {
3260  /* Fix up PlaceHolderVars as needed */
3261  /* If there are no PHVs anywhere, we can skip this bit */
3262  if (root->glob->lastPHId != 0)
3263  {
3264  Relids subrelids;
3265 
3266  subrelids = get_relids_in_jointree(newjtloc, false);
3267  Assert(!bms_is_empty(subrelids));
3268  substitute_phv_relids((Node *) root->parse, varno, subrelids);
3269  fix_append_rel_relids(root->append_rel_list, varno, subrelids);
3270  }
3271 
3272  /*
3273  * We also need to remove any PlanRowMark referencing the RTE, but we
3274  * postpone that work until we return to remove_useless_result_rtes.
3275  */
3276 }
3277 
3278 
3279 /*
3280  * find_dependent_phvs - are there any PlaceHolderVars whose relids are
3281  * exactly the given varno?
3282  *
3283  * find_dependent_phvs should be used when we want to see if there are
3284  * any such PHVs anywhere in the Query. Another use-case is to see if
3285  * a subtree of the join tree contains such PHVs; but for that, we have
3286  * to look not only at the join tree nodes themselves but at the
3287  * referenced RTEs. For that, use find_dependent_phvs_in_jointree.
3288  */
3289 
3290 typedef struct
3291 {
3295 
3296 static bool
3298  find_dependent_phvs_context *context)
3299 {
3300  if (node == NULL)
3301  return false;
3302  if (IsA(node, PlaceHolderVar))
3303  {
3304  PlaceHolderVar *phv = (PlaceHolderVar *) node;
3305 
3306  if (phv->phlevelsup == context->sublevels_up &&
3307  bms_equal(context->relids, phv->phrels))
3308  return true;
3309  /* fall through to examine children */
3310  }
3311  if (IsA(node, Query))
3312  {
3313  /* Recurse into subselects */
3314  bool result;
3315 
3316  context->sublevels_up++;
3317  result = query_tree_walker((Query *) node,
3319  (void *) context, 0);
3320  context->sublevels_up--;
3321  return result;
3322  }
3323  /* Shouldn't need to handle planner auxiliary nodes here */
3324  Assert(!IsA(node, SpecialJoinInfo));
3325  Assert(!IsA(node, AppendRelInfo));
3326  Assert(!IsA(node, PlaceHolderInfo));
3327  Assert(!IsA(node, MinMaxAggInfo));
3328 
3330  (void *) context);
3331 }
3332 
3333 static bool
3335 {
3337 
3338  /* If there are no PHVs anywhere, we needn't work hard */
3339  if (root->glob->lastPHId == 0)
3340  return false;
3341 
3342  context.relids = bms_make_singleton(varno);
3343  context.sublevels_up = 0;
3344 
3345  return query_tree_walker(root->parse,
3347  (void *) &context,
3348  0);
3349 }
3350 
3351 static bool
3353 {
3355  Relids subrelids;
3356  int relid;
3357 
3358  /* If there are no PHVs anywhere, we needn't work hard */
3359  if (root->glob->lastPHId == 0)
3360  return false;
3361 
3362  context.relids = bms_make_singleton(varno);
3363  context.sublevels_up = 0;
3364 
3365  /*
3366  * See if the jointree fragment itself contains references (in join quals)
3367  */
3368  if (find_dependent_phvs_walker(node, &context))
3369  return true;
3370 
3371  /*
3372  * Otherwise, identify the set of referenced RTEs (we can ignore joins,
3373  * since they should be flattened already, so their join alias lists no
3374  * longer matter), and tediously check each RTE. We can ignore RTEs that
3375  * are not marked LATERAL, though, since they couldn't possibly contain
3376  * any cross-references to other RTEs.
3377  */
3378  subrelids = get_relids_in_jointree(node, false);
3379  relid = -1;
3380  while ((relid = bms_next_member(subrelids, relid)) >= 0)
3381  {
3382  RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
3383 
3384  if (rte->lateral &&
3387  (void *) &context,
3388  0))
3389  return true;
3390  }
3391 
3392  return false;
3393 }
3394 
3395 /*
3396  * substitute_phv_relids - adjust PlaceHolderVar relid sets after pulling up
3397  * a subquery or removing an RTE_RESULT jointree item
3398  *
3399  * Find any PlaceHolderVar nodes in the given tree that reference the
3400  * pulled-up relid, and change them to reference the replacement relid(s).
3401  *
3402  * NOTE: although this has the form of a walker, we cheat and modify the
3403  * nodes in-place. This should be OK since the tree was copied by
3404  * pullup_replace_vars earlier. Avoid scribbling on the original values of
3405  * the bitmapsets, though, because expression_tree_mutator doesn't copy those.
3406  */
3407 
3408 typedef struct
3409 {
3410  int varno;
3414 
3415 static bool
3418 {
3419  if (node == NULL)
3420  return false;
3421  if (IsA(node, PlaceHolderVar))
3422  {
3423  PlaceHolderVar *phv = (PlaceHolderVar *) node;
3424 
3425  if (phv->phlevelsup == context->sublevels_up &&
3426  bms_is_member(context->varno, phv->phrels))
3427  {
3428  phv->phrels = bms_union(phv->phrels,
3429  context->subrelids);
3430  phv->phrels = bms_del_member(phv->phrels,
3431  context->varno);
3432  /* Assert we haven't broken the PHV */
3433  Assert(!bms_is_empty(phv->phrels));
3434  }
3435  /* fall through to examine children */
3436  }
3437  if (IsA(node, Query))
3438  {
3439  /* Recurse into subselects */
3440  bool result;
3441 
3442  context->sublevels_up++;
3443  result = query_tree_walker((Query *) node,
3445  (void *) context, 0);
3446  context->sublevels_up--;
3447  return result;
3448  }
3449  /* Shouldn't need to handle planner auxiliary nodes here */
3450  Assert(!IsA(node, SpecialJoinInfo));
3451  Assert(!IsA(node, AppendRelInfo));
3452  Assert(!IsA(node, PlaceHolderInfo));
3453  Assert(!IsA(node, MinMaxAggInfo));
3454 
3456  (void *) context);
3457 }
3458 
3459 static void
3460 substitute_phv_relids(Node *node, int varno, Relids subrelids)
3461 {
3463 
3464  context.varno = varno;
3465  context.sublevels_up = 0;
3466  context.subrelids = subrelids;
3467 
3468  /*
3469  * Must be prepared to start with a Query or a bare expression tree.
3470  */
3473  (void *) &context,
3474  0);
3475 }
3476 
3477 /*
3478  * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
3479  *
3480  * When we pull up a subquery, any AppendRelInfo references to the subquery's
3481  * RT index have to be replaced by the substituted relid (and there had better
3482  * be only one). We also need to apply substitute_phv_relids to their
3483  * translated_vars lists, since those might contain PlaceHolderVars.
3484  *
3485  * We assume we may modify the AppendRelInfo nodes in-place.
3486  */
3487 static void
3488 fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
3489 {
3490  ListCell *l;
3491  int subvarno = -1;
3492 
3493  /*
3494  * We only want to extract the member relid once, but we mustn't fail
3495  * immediately if there are multiple members; it could be that none of the
3496  * AppendRelInfo nodes refer to it. So compute it on first use. Note that
3497  * bms_singleton_member will complain if set is not singleton.
3498  */
3499  foreach(l, append_rel_list)
3500  {
3501  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
3502 
3503  /* The parent_relid shouldn't ever be a pullup target */
3504  Assert(appinfo->parent_relid != varno);
3505 
3506  if (appinfo->child_relid == varno)
3507  {
3508  if (subvarno < 0)
3509  subvarno = bms_singleton_member(subrelids);
3510  appinfo->child_relid = subvarno;
3511  }
3512 
3513  /* Also fix up any PHVs in its translated vars */
3515  varno, subrelids);
3516  }
3517 }
3518 
3519 /*
3520  * get_relids_in_jointree: get set of RT indexes present in a jointree
3521  *
3522  * If include_joins is true, join RT indexes are included; if false,
3523  * only base rels are included.
3524  */
3525 Relids
3526 get_relids_in_jointree(Node *jtnode, bool include_joins)
3527 {
3528  Relids result = NULL;
3529 
3530  if (jtnode == NULL)
3531  return result;
3532  if (IsA(jtnode, RangeTblRef))
3533  {
3534  int varno = ((RangeTblRef *) jtnode)->rtindex;
3535 
3536  result = bms_make_singleton(varno);
3537  }
3538  else if (IsA(jtnode, FromExpr))
3539  {
3540  FromExpr *f = (FromExpr *) jtnode;
3541  ListCell *l;
3542 
3543  foreach(l, f->fromlist)
3544  {
3545  result = bms_join(result,
3547  include_joins));
3548  }
3549  }
3550  else if (IsA(jtnode, JoinExpr))
3551  {
3552  JoinExpr *j = (JoinExpr *) jtnode;
3553 
3554  result = get_relids_in_jointree(j->larg, include_joins);
3555  result = bms_join(result,
3556  get_relids_in_jointree(j->rarg, include_joins));
3557  if (include_joins && j->rtindex)
3558  result = bms_add_member(result, j->rtindex);
3559  }
3560  else
3561  elog(ERROR, "unrecognized node type: %d",
3562  (int) nodeTag(jtnode));
3563  return result;
3564 }
3565 
3566 /*
3567  * get_relids_for_join: get set of base RT indexes making up a join
3568  */
3569 Relids
3570 get_relids_for_join(Query *query, int joinrelid)
3571 {
3572  Node *jtnode;
3573 
3574  jtnode = find_jointree_node_for_rel((Node *) query->jointree,
3575  joinrelid);
3576  if (!jtnode)
3577  elog(ERROR, "could not find join node %d", joinrelid);
3578  return get_relids_in_jointree(jtnode, false);
3579 }
3580 
3581 /*
3582  * find_jointree_node_for_rel: locate jointree node for a base or join RT index
3583  *
3584  * Returns NULL if not found
3585  */
3586 static Node *
3588 {
3589  if (jtnode == NULL)
3590  return NULL;
3591  if (IsA(jtnode, RangeTblRef))
3592  {
3593  int varno = ((RangeTblRef *) jtnode)->rtindex;
3594 
3595  if (relid == varno)
3596  return jtnode;
3597  }
3598  else if (IsA(jtnode, FromExpr))
3599  {
3600  FromExpr *f = (FromExpr *) jtnode;
3601  ListCell *l;
3602 
3603  foreach(l, f->fromlist)
3604  {
3605  jtnode = find_jointree_node_for_rel(lfirst(l), relid);
3606  if (jtnode)
3607  return jtnode;
3608  }
3609  }
3610  else if (IsA(jtnode, JoinExpr))
3611  {
3612  JoinExpr *j = (JoinExpr *) jtnode;
3613 
3614  if (relid == j->rtindex)
3615  return jtnode;
3616  jtnode = find_jointree_node_for_rel(j->larg, relid);
3617  if (jtnode)
3618  return jtnode;
3619  jtnode = find_jointree_node_for_rel(j->rarg, relid);
3620  if (jtnode)
3621  return jtnode;
3622  }
3623  else
3624  elog(ERROR, "unrecognized node type: %d",
3625  (int) nodeTag(jtnode));
3626  return NULL;
3627 }
Node * limitOffset
Definition: parsenodes.h:160
#define NIL
Definition: pg_list.h:65
static void substitute_phv_relids(Node *node, int varno, Relids subrelids)
List * rowMarks
Definition: pathnodes.h:286
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:97
static Node * pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node, Node **jtlink1, Relids available_rels1, Node **jtlink2, Relids available_rels2)
Definition: prepjointree.c:389
void remove_useless_result_rtes(PlannerInfo *root)
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex, Query *setOpQuery, int childRToffset)
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2336
List * args
Definition: primnodes.h:1046
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:285
#define IsA(nodeptr, _type_)
Definition: nodes.h:584
Query * parse
Definition: pathnodes.h:173
void OffsetVarNodes(Node *node, int offset, int sublevels_up)
Definition: rewriteManip.c:425
List * joinaliasvars
Definition: parsenodes.h:1056
Index varlevelsup
Definition: primnodes.h:191
bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
Definition: tlist.c:265
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
List * plan_params
Definition: pathnodes.h:187
List * sortClause
Definition: parsenodes.h:158
static bool is_simple_values(PlannerInfo *root, RangeTblEntry *rte)
bool ec_merging_done
Definition: pathnodes.h:262
bool range_table_entry_walker(RangeTblEntry *rte, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2456
static int get_result_relid(PlannerInfo *root, Node *jtnode)
List * join_info_list
Definition: pathnodes.h:277
void IncrementVarSublevelsUp(Node *node, int delta_sublevels_up, int min_sublevels_up)
Definition: rewriteManip.c:776
void reduce_outer_joins(PlannerInfo *root)
int num_child_cols
Definition: pathnodes.h:2286
FromExpr * jointree
Definition: parsenodes.h:138
OnConflictExpr * onConflict
Definition: parsenodes.h:144
PlannerInfo * parent_root
Definition: pathnodes.h:179
#define castNode(_type_, nodeptr)
Definition: nodes.h:602
static Node * pullup_replace_vars_callback(Var *var, replace_rte_variables_context *context)
AttrNumber * parent_colnos
Definition: pathnodes.h:2287
bool hasAggs
Definition: parsenodes.h:125
static bool substitute_phv_relids_walker(Node *node, substitute_phv_relids_context *context)
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:709
static bool is_andclause(const void *clause)
Definition: nodeFuncs.h:97
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:103
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:749
static Node * pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode, JoinExpr *lowest_outer_join, JoinExpr *lowest_nulling_outer_join, AppendRelInfo *containing_appendrel)
Definition: prepjointree.c:730
List * groupingSets
Definition: parsenodes.h:150
static Node * pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, JoinExpr *lowest_outer_join, JoinExpr *lowest_nulling_outer_join, AppendRelInfo *containing_appendrel)
Definition: prepjointree.c:882
Definition: nodes.h:533
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:4589
static bool find_dependent_phvs_walker(Node *node, find_dependent_phvs_context *context)
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
AttrNumber varattno
Definition: primnodes.h:186
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2022
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
List * minmax_aggs
Definition: pathnodes.h:323
JoinExpr * convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink, Relids available_rels)
Definition: subselect.c:1276
List * fromlist
Definition: primnodes.h:1534
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:437
bool funcordinality
Definition: parsenodes.h:1069
static bool is_simple_union_all(Query *subquery)
unsigned int Oid
Definition: postgres_ext.h:31
List * rowMarks
Definition: parsenodes.h:164
static bool find_dependent_phvs(PlannerInfo *root, int varno)
Definition: primnodes.h:181
#define linitial_node(type, l)
Definition: pg_list.h:177
AttrNumber * grouping_map
Definition: pathnodes.h:322
TypeFuncClass get_expr_result_type(Node *expr, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:223
bool hasRecursion
Definition: pathnodes.h:345
static void remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
void pull_up_subqueries(PlannerInfo *root)
Definition: prepjointree.c:680
List * translated_vars
Definition: pathnodes.h:2278
void replace_empty_jointree(Query *parse)
Definition: prepjointree.c:150
List * values_lists
Definition: parsenodes.h:1079
Oid parent_reltype
Definition: pathnodes.h:2259
Node * quals
Definition: primnodes.h:1535
#define lsecond(l)
Definition: pg_list.h:179
static bool find_dependent_phvs_in_jointree(PlannerInfo *root, Node *node, int varno)
void IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up, int min_sublevels_up)
Definition: rewriteManip.c:799
JoinType
Definition: nodes.h:700
List * targetList
Definition: parsenodes.h:140
JoinExpr * convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink, bool under_not, Relids available_rels)
Definition: subselect.c:1383
List * multiexpr_params
Definition: pathnodes.h:257
Node * larg
Definition: primnodes.h:1514
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:369
List * find_forced_null_vars(Node *node)
Definition: clauses.c:1688
#define list_make1(x1)
Definition: pg_list.h:206
static Node * pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:387
PlaceHolderVar * make_placeholder_expr(PlannerInfo *root, Expr *expr, Relids phrels)
Definition: placeholder.c:39
void preprocess_function_rtes(PlannerInfo *root)
Definition: prepjointree.c:639
int wt_param_id
Definition: pathnodes.h:357
struct reduce_outer_joins_state reduce_outer_joins_state
bool resjunk
Definition: primnodes.h:1438
#define linitial(l)
Definition: pg_list.h:174
static Node * find_jointree_node_for_rel(Node *jtnode, int relid)
List * rtable
Definition: parsenodes.h:137
List * distinctClause
Definition: parsenodes.h:156
#define ERROR
Definition: elog.h:45
List * colnames
Definition: primnodes.h:1062
RangeTblEntry * target_rte
Definition: prepjointree.c:47
Node * replace_rte_variables_mutator(Node *node, replace_rte_variables_context *context)
TableFunc * tablefunc
Definition: parsenodes.h:1074
Oid vartype
Definition: primnodes.h:188
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:949
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:315
int location
Definition: primnodes.h:196
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
Node * limitCount
Definition: parsenodes.h:161
int location
Definition: primnodes.h:1063
Relids find_nonnullable_rels(Node *clause)
Definition: clauses.c:1270
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
Expr * make_andclause(List *andclauses)
Definition: makefuncs.c:636
PlannerGlobal * glob
Definition: pathnodes.h:175
JoinType jointype
Definition: parsenodes.h:1054
AttrNumber resno
Definition: primnodes.h:1432
List * list_intersection(const List *list1, const List *list2)
Definition: list.c:1033
Relids get_relids_for_join(Query *query, int joinrelid)
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
TypeFuncClass
Definition: funcapi.h:146
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
static Node * pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode, Relids *relids)
Definition: prepjointree.c:235
List * lappend(List *list, void *datum)
Definition: list.c:336
bool bms_is_empty(const Bitmapset *a)
Definition: bitmapset.c:701
bool query_or_expression_tree_walker(Node *node, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:3442
Index varno
Definition: primnodes.h:184
void expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, int location, bool include_dropped, List **colnames, List **colvars)
static bool is_notclause(const void *clause)
Definition: nodeFuncs.h:115
void * palloc0(Size size)
Definition: mcxt.c:981
Node * quals
Definition: primnodes.h:1517
List * append_rel_list
Definition: pathnodes.h:284
int bms_singleton_member(const Bitmapset *a)
Definition: bitmapset.c:577
Index lastPHId
Definition: pathnodes.h:127
List * cte_plan_ids
Definition: pathnodes.h:255
unsigned int Index
Definition: c.h:549
List * find_nonnullable_vars(Node *clause)
Definition: clauses.c:1495
List * init_plans
Definition: pathnodes.h:253
bool security_barrier
Definition: parsenodes.h:1017
#define InvalidOid
Definition: postgres_ext.h:36
Node * flatten_join_alias_vars(Query *query, Node *node)
Definition: var.c:697
static bool is_safe_append_member(Query *subquery)
static Expr * get_notclausearg(const void *notclause)
Definition: nodeFuncs.h:124
CmdType commandType
Definition: parsenodes.h:112
bool hasTargetSRFs
Definition: parsenodes.h:127
void bms_free(Bitmapset *a)
Definition: bitmapset.c:208
#define makeNode(_type_)
Definition: nodes.h:581
static void perform_pullup_replace_vars(PlannerInfo *root, pullup_replace_vars_context *rvcontext, JoinExpr *lowest_nulling_outer_join, AppendRelInfo *containing_appendrel)
Node * rarg
Definition: primnodes.h:1515
static reduce_outer_joins_state * reduce_outer_joins_pass1(Node *jtnode)
static void fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
JoinType jointype
Definition: primnodes.h:1512
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
bool hasWindowFuncs
Definition: parsenodes.h:126
List * eq_classes
Definition: pathnodes.h:260
Definition: regguts.h:317
List * functions
Definition: parsenodes.h:1068
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:396
InheritanceKind inhTargetKind
Definition: pathnodes.h:336
Expr * expr
Definition: primnodes.h:1431
void flatten_simple_union_all(PlannerInfo *root)
static void make_setop_translation_list(Query *query, Index newvarno, AppendRelInfo *appinfo)
Bitmapset * outer_params
Definition: pathnodes.h:188
struct Path * non_recursive_path
Definition: pathnodes.h:358
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:225
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1885
Oid row_typeid
Definition: primnodes.h:1047
static int list_length(const List *l)
Definition: pg_list.h:149
SetOperation op
Definition: parsenodes.h:1689
Index qual_security_level
Definition: pathnodes.h:333
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
Index query_level
Definition: pathnodes.h:177
#define InvalidAttrNumber
Definition: attnum.h:23
#define nodeTag(nodeptr)
Definition: nodes.h:538
void pull_up_sublinks(PlannerInfo *root)
Definition: prepjointree.c:208
RTEKind rtekind
Definition: parsenodes.h:981
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:494
static bool is_simple_subquery(PlannerInfo *root, Query *subquery, RangeTblEntry *rte, JoinExpr *lowest_outer_join)
static Node * pull_up_constant_function(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, JoinExpr *lowest_nulling_outer_join, AppendRelInfo *containing_appendrel)
List * cteList
Definition: parsenodes.h:135
Node * setOperations
Definition: parsenodes.h:166
static void replace_vars_in_jointree(Node *jtnode, pullup_replace_vars_context *context, JoinExpr *lowest_nulling_outer_join)
Query * subquery
Definition: parsenodes.h:1016
Index phlevelsup
Definition: pathnodes.h:2128
List * groupClause
Definition: parsenodes.h:148
void * palloc(Size size)
Definition: mcxt.c:950
static Query * pullup_replace_vars_subquery(Query *query, pullup_replace_vars_context *context)
bool hasSubLinks
Definition: parsenodes.h:128
Node * replace_rte_variables(Node *node, int target_varno, int sublevels_up, replace_rte_variables_callback callback, void *callback_arg, bool *outer_hasSubLinks)
#define elog(elevel,...)
Definition: elog.h:227
bool hasForUpdate
Definition: parsenodes.h:132
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
List * placeholder_list
Definition: pathnodes.h:288
List * onConflictSet
Definition: primnodes.h:1559
struct pullup_replace_vars_context pullup_replace_vars_context
static bool jointree_contains_lateral_outer_refs(PlannerInfo *root, Node *jtnode, bool restricted, Relids safe_upper_varnos)
MemoryContext planner_cxt
Definition: pathnodes.h:325
Index child_relid
Definition: pathnodes.h:2251
bool contain_nonstrict_functions(Node *clause)
Definition: clauses.c:807
Alias * eref
Definition: parsenodes.h:1120
#define copyObject(obj)
Definition: nodes.h:649
Node * havingQual
Definition: parsenodes.h:152
static Node * remove_useless_results_recurse(PlannerInfo *root, Node *jtnode)
Index parent_relid
Definition: pathnodes.h:2250
List * processed_tlist
Definition: pathnodes.h:319
CoercionForm row_format
Definition: primnodes.h:1061
Relids pull_varnos_of_level(PlannerInfo *root, Node *node, int levelsup)
Definition: var.c:123
Node * onConflictWhere
Definition: primnodes.h:1560
static void reduce_outer_joins_pass2(Node *jtnode, reduce_outer_joins_state *state, PlannerInfo *root, Relids nonnullable_rels, List *nonnullable_vars, List *forced_null_vars)
Definition: regcomp.c:238
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition: bitmapset.c:773
int rtindex
Definition: primnodes.h:1519
static Node * pullup_replace_vars(Node *expr, pullup_replace_vars_context *context)
Definition: pg_list.h:50
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
struct TableSampleClause * tablesample
Definition: parsenodes.h:1011
int16 AttrNumber
Definition: attnum.h:21
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:793
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:94
bool hasRowSecurity
Definition: parsenodes.h:133
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:666
static Node * pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
struct PathTarget * upper_targets[UPPERREL_FINAL+1]
Definition: pathnodes.h:308
List * upper_rels[UPPERREL_FINAL+1]
Definition: pathnodes.h:305