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 
43 typedef struct pullup_replace_vars_context
44 {
45 	PlannerInfo *root;
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 */
55 } pullup_replace_vars_context;
56 
57 typedef struct reduce_outer_joins_state
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 */
62 } reduce_outer_joins_state;
63 
64 static Node *pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
65 											   Relids *relids);
66 static Node *pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *node,
67 										   Node **jtlink1, Relids available_rels1,
68 										   Node **jtlink2, Relids available_rels2);
69 static Node *pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
70 										JoinExpr *lowest_outer_join,
71 										JoinExpr *lowest_nulling_outer_join,
72 										AppendRelInfo *containing_appendrel);
73 static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
74 									 RangeTblEntry *rte,
75 									 JoinExpr *lowest_outer_join,
76 									 JoinExpr *lowest_nulling_outer_join,
77 									 AppendRelInfo *containing_appendrel);
78 static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
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);
88 static Node *pull_up_simple_values(PlannerInfo *root, Node *jtnode,
89 								   RangeTblEntry *rte);
90 static bool is_simple_values(PlannerInfo *root, RangeTblEntry *rte);
91 static Node *pull_up_constant_function(PlannerInfo *root, Node *jtnode,
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);
99 static bool jointree_contains_lateral_outer_refs(PlannerInfo *root,
100 												 Node *jtnode, bool restricted,
101 												 Relids safe_upper_varnos);
102 static void perform_pullup_replace_vars(PlannerInfo *root,
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,
107 									 pullup_replace_vars_context *context,
108 									 JoinExpr *lowest_nulling_outer_join);
109 static Node *pullup_replace_vars(Node *expr,
110 								 pullup_replace_vars_context *context);
111 static Node *pullup_replace_vars_callback(Var *var,
112 										  replace_rte_variables_context *context);
113 static Query *pullup_replace_vars_subquery(Query *query,
114 										   pullup_replace_vars_context *context);
115 static reduce_outer_joins_state *reduce_outer_joins_pass1(Node *jtnode);
116 static void reduce_outer_joins_pass2(Node *jtnode,
117 									 reduce_outer_joins_state *state,
118 									 PlannerInfo *root,
119 									 Relids nonnullable_rels,
120 									 List *nonnullable_vars,
121 									 List *forced_null_vars);
122 static Node *remove_useless_results_recurse(PlannerInfo *root, Node *jtnode);
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);
126 static bool find_dependent_phvs_in_jointree(PlannerInfo *root,
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
replace_empty_jointree(Query * parse)150 replace_empty_jointree(Query *parse)
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
pull_up_sublinks(PlannerInfo * root)208 pull_up_sublinks(PlannerInfo *root)
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 *
pull_up_sublinks_jointree_recurse(PlannerInfo * root,Node * jtnode,Relids * relids)235 pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
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 */
307 		j->larg = pull_up_sublinks_jointree_recurse(root, j->larg,
308 													&leftrelids);
309 		j->rarg = pull_up_sublinks_jointree_recurse(root, j->rarg,
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:
327 				j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
328 														 &jtlink,
329 														 bms_union(leftrelids,
330 																   rightrelids),
331 														 NULL, NULL);
332 				break;
333 			case JOIN_LEFT:
334 				j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
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:
343 				j->quals = pull_up_sublinks_qual_recurse(root, j->quals,
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 *
pull_up_sublinks_qual_recurse(PlannerInfo * root,Node * node,Node ** jtlink1,Relids available_rels1,Node ** jtlink2,Relids available_rels2)389 pull_up_sublinks_qual_recurse(PlannerInfo *root, Node *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 */
411 				j->rarg = pull_up_sublinks_jointree_recurse(root,
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 				 */
420 				j->quals = pull_up_sublinks_qual_recurse(root,
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 */
437 				j->rarg = pull_up_sublinks_jointree_recurse(root,
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 				 */
446 				j->quals = pull_up_sublinks_qual_recurse(root,
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 */
465 				j->rarg = pull_up_sublinks_jointree_recurse(root,
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 				 */
474 				j->quals = pull_up_sublinks_qual_recurse(root,
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 */
491 				j->rarg = pull_up_sublinks_jointree_recurse(root,
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 				 */
500 				j->quals = pull_up_sublinks_qual_recurse(root,
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 */
531 					j->rarg = pull_up_sublinks_jointree_recurse(root,
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 					 */
541 					j->quals = pull_up_sublinks_qual_recurse(root,
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 */
557 					j->rarg = pull_up_sublinks_jointree_recurse(root,
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 					 */
567 					j->quals = pull_up_sublinks_qual_recurse(root,
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
preprocess_function_rtes(PlannerInfo * root)639 preprocess_function_rtes(PlannerInfo *root)
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
pull_up_subqueries(PlannerInfo * root)680 pull_up_subqueries(PlannerInfo *root)
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 *)
686 		pull_up_subqueries_recurse(root, (Node *) root->parse->jointree,
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 *
pull_up_subqueries_recurse(PlannerInfo * root,Node * jtnode,JoinExpr * lowest_outer_join,JoinExpr * lowest_nulling_outer_join,AppendRelInfo * containing_appendrel)730 pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
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 ||
751 			 is_safe_append_member(rte->subquery)))
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 &&
767 			is_simple_union_all(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 		{
801 			lfirst(l) = pull_up_subqueries_recurse(root, lfirst(l),
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 *
pull_up_simple_subquery(PlannerInfo * root,Node * jtnode,RangeTblEntry * rte,JoinExpr * lowest_outer_join,JoinExpr * lowest_nulling_outer_join,AppendRelInfo * containing_appendrel)882 pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
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;
917 	subroot->planner_cxt = CurrentMemoryContext;
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->all_result_relids = NULL;
924 	subroot->leaf_result_relids = NULL;
925 	subroot->append_rel_list = NIL;
926 	subroot->row_identity_vars = NIL;
927 	subroot->rowMarks = NIL;
928 	memset(subroot->upper_rels, 0, sizeof(subroot->upper_rels));
929 	memset(subroot->upper_targets, 0, sizeof(subroot->upper_targets));
930 	subroot->processed_tlist = NIL;
931 	subroot->update_colnos = NIL;
932 	subroot->grouping_map = NULL;
933 	subroot->minmax_aggs = NIL;
934 	subroot->qual_security_level = 0;
935 	subroot->hasRecursion = false;
936 	subroot->wt_param_id = -1;
937 	subroot->non_recursive_path = NULL;
938 
939 	/* No CTEs to worry about */
940 	Assert(subquery->cteList == NIL);
941 
942 	/*
943 	 * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
944 	 * that we don't need so many special cases to deal with that situation.
945 	 */
946 	replace_empty_jointree(subquery);
947 
948 	/*
949 	 * Pull up any SubLinks within the subquery's quals, so that we don't
950 	 * leave unoptimized SubLinks behind.
951 	 */
952 	if (subquery->hasSubLinks)
953 		pull_up_sublinks(subroot);
954 
955 	/*
956 	 * Similarly, preprocess its function RTEs to inline any set-returning
957 	 * functions in its rangetable.
958 	 */
959 	preprocess_function_rtes(subroot);
960 
961 	/*
962 	 * Recursively pull up the subquery's subqueries, so that
963 	 * pull_up_subqueries' processing is complete for its jointree and
964 	 * rangetable.
965 	 *
966 	 * Note: it's okay that the subquery's recursion starts with NULL for
967 	 * containing-join info, even if we are within an outer join in the upper
968 	 * query; the lower query starts with a clean slate for outer-join
969 	 * semantics.  Likewise, we needn't pass down appendrel state.
970 	 */
971 	pull_up_subqueries(subroot);
972 
973 	/*
974 	 * Now we must recheck whether the subquery is still simple enough to pull
975 	 * up.  If not, abandon processing it.
976 	 *
977 	 * We don't really need to recheck all the conditions involved, but it's
978 	 * easier just to keep this "if" looking the same as the one in
979 	 * pull_up_subqueries_recurse.
980 	 */
981 	if (is_simple_subquery(root, subquery, rte, lowest_outer_join) &&
982 		(containing_appendrel == NULL || is_safe_append_member(subquery)))
983 	{
984 		/* good to go */
985 	}
986 	else
987 	{
988 		/*
989 		 * Give up, return unmodified RangeTblRef.
990 		 *
991 		 * Note: The work we just did will be redone when the subquery gets
992 		 * planned on its own.  Perhaps we could avoid that by storing the
993 		 * modified subquery back into the rangetable, but I'm not gonna risk
994 		 * it now.
995 		 */
996 		return jtnode;
997 	}
998 
999 	/*
1000 	 * We must flatten any join alias Vars in the subquery's targetlist,
1001 	 * because pulling up the subquery's subqueries might have changed their
1002 	 * expansions into arbitrary expressions, which could affect
1003 	 * pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
1004 	 * are needed for tlist entries.  (Likely it'd be better to do
1005 	 * flatten_join_alias_vars on the whole query tree at some earlier stage,
1006 	 * maybe even in the rewriter; but for now let's just fix this case here.)
1007 	 */
1008 	subquery->targetList = (List *)
1009 		flatten_join_alias_vars(subroot->parse, (Node *) subquery->targetList);
1010 
1011 	/*
1012 	 * Adjust level-0 varnos in subquery so that we can append its rangetable
1013 	 * to upper query's.  We have to fix the subquery's append_rel_list as
1014 	 * well.
1015 	 */
1016 	rtoffset = list_length(parse->rtable);
1017 	OffsetVarNodes((Node *) subquery, rtoffset, 0);
1018 	OffsetVarNodes((Node *) subroot->append_rel_list, rtoffset, 0);
1019 
1020 	/*
1021 	 * Upper-level vars in subquery are now one level closer to their parent
1022 	 * than before.
1023 	 */
1024 	IncrementVarSublevelsUp((Node *) subquery, -1, 1);
1025 	IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
1026 
1027 	/*
1028 	 * The subquery's targetlist items are now in the appropriate form to
1029 	 * insert into the top query, except that we may need to wrap them in
1030 	 * PlaceHolderVars.  Set up required context data for pullup_replace_vars.
1031 	 */
1032 	rvcontext.root = root;
1033 	rvcontext.targetlist = subquery->targetList;
1034 	rvcontext.target_rte = rte;
1035 	if (rte->lateral)
1036 		rvcontext.relids = get_relids_in_jointree((Node *) subquery->jointree,
1037 												  true);
1038 	else						/* won't need relids */
1039 		rvcontext.relids = NULL;
1040 	rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1041 	rvcontext.varno = varno;
1042 	/* these flags will be set below, if needed */
1043 	rvcontext.need_phvs = false;
1044 	rvcontext.wrap_non_vars = false;
1045 	/* initialize cache array with indexes 0 .. length(tlist) */
1046 	rvcontext.rv_cache = palloc0((list_length(subquery->targetList) + 1) *
1047 								 sizeof(Node *));
1048 
1049 	/*
1050 	 * If we are under an outer join then non-nullable items and lateral
1051 	 * references may have to be turned into PlaceHolderVars.
1052 	 */
1053 	if (lowest_nulling_outer_join != NULL)
1054 		rvcontext.need_phvs = true;
1055 
1056 	/*
1057 	 * If we are dealing with an appendrel member then anything that's not a
1058 	 * simple Var has to be turned into a PlaceHolderVar.  We force this to
1059 	 * ensure that what we pull up doesn't get merged into a surrounding
1060 	 * expression during later processing and then fail to match the
1061 	 * expression actually available from the appendrel.
1062 	 */
1063 	if (containing_appendrel != NULL)
1064 	{
1065 		rvcontext.need_phvs = true;
1066 		rvcontext.wrap_non_vars = true;
1067 	}
1068 
1069 	/*
1070 	 * If the parent query uses grouping sets, we need a PlaceHolderVar for
1071 	 * anything that's not a simple Var.  Again, this ensures that expressions
1072 	 * retain their separate identity so that they will match grouping set
1073 	 * columns when appropriate.  (It'd be sufficient to wrap values used in
1074 	 * grouping set columns, and do so only in non-aggregated portions of the
1075 	 * tlist and havingQual, but that would require a lot of infrastructure
1076 	 * that pullup_replace_vars hasn't currently got.)
1077 	 */
1078 	if (parse->groupingSets)
1079 	{
1080 		rvcontext.need_phvs = true;
1081 		rvcontext.wrap_non_vars = true;
1082 	}
1083 
1084 	/*
1085 	 * Replace all of the top query's references to the subquery's outputs
1086 	 * with copies of the adjusted subtlist items, being careful not to
1087 	 * replace any of the jointree structure.
1088 	 */
1089 	perform_pullup_replace_vars(root, &rvcontext,
1090 								lowest_nulling_outer_join,
1091 								containing_appendrel);
1092 
1093 	/*
1094 	 * If the subquery had a LATERAL marker, propagate that to any of its
1095 	 * child RTEs that could possibly now contain lateral cross-references.
1096 	 * The children might or might not contain any actual lateral
1097 	 * cross-references, but we have to mark the pulled-up child RTEs so that
1098 	 * later planner stages will check for such.
1099 	 */
1100 	if (rte->lateral)
1101 	{
1102 		foreach(lc, subquery->rtable)
1103 		{
1104 			RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(lc);
1105 
1106 			switch (child_rte->rtekind)
1107 			{
1108 				case RTE_RELATION:
1109 					if (child_rte->tablesample)
1110 						child_rte->lateral = true;
1111 					break;
1112 				case RTE_SUBQUERY:
1113 				case RTE_FUNCTION:
1114 				case RTE_VALUES:
1115 				case RTE_TABLEFUNC:
1116 					child_rte->lateral = true;
1117 					break;
1118 				case RTE_JOIN:
1119 				case RTE_CTE:
1120 				case RTE_NAMEDTUPLESTORE:
1121 				case RTE_RESULT:
1122 					/* these can't contain any lateral references */
1123 					break;
1124 			}
1125 		}
1126 	}
1127 
1128 	/*
1129 	 * Now append the adjusted rtable entries to upper query. (We hold off
1130 	 * until after fixing the upper rtable entries; no point in running that
1131 	 * code on the subquery ones too.)
1132 	 */
1133 	parse->rtable = list_concat(parse->rtable, subquery->rtable);
1134 
1135 	/*
1136 	 * Pull up any FOR UPDATE/SHARE markers, too.  (OffsetVarNodes already
1137 	 * adjusted the marker rtindexes, so just concat the lists.)
1138 	 */
1139 	parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
1140 
1141 	/*
1142 	 * We also have to fix the relid sets of any PlaceHolderVar nodes in the
1143 	 * parent query.  (This could perhaps be done by pullup_replace_vars(),
1144 	 * but it seems cleaner to use two passes.)  Note in particular that any
1145 	 * PlaceHolderVar nodes just created by pullup_replace_vars() will be
1146 	 * adjusted, so having created them with the subquery's varno is correct.
1147 	 *
1148 	 * Likewise, relids appearing in AppendRelInfo nodes have to be fixed. We
1149 	 * already checked that this won't require introducing multiple subrelids
1150 	 * into the single-slot AppendRelInfo structs.
1151 	 */
1152 	if (parse->hasSubLinks || root->glob->lastPHId != 0 ||
1153 		root->append_rel_list)
1154 	{
1155 		Relids		subrelids;
1156 
1157 		subrelids = get_relids_in_jointree((Node *) subquery->jointree, false);
1158 		substitute_phv_relids((Node *) parse, varno, subrelids);
1159 		fix_append_rel_relids(root->append_rel_list, varno, subrelids);
1160 	}
1161 
1162 	/*
1163 	 * And now add subquery's AppendRelInfos to our list.
1164 	 */
1165 	root->append_rel_list = list_concat(root->append_rel_list,
1166 										subroot->append_rel_list);
1167 
1168 	/*
1169 	 * We don't have to do the equivalent bookkeeping for outer-join info,
1170 	 * because that hasn't been set up yet.  placeholder_list likewise.
1171 	 */
1172 	Assert(root->join_info_list == NIL);
1173 	Assert(subroot->join_info_list == NIL);
1174 	Assert(root->placeholder_list == NIL);
1175 	Assert(subroot->placeholder_list == NIL);
1176 
1177 	/*
1178 	 * Miscellaneous housekeeping.
1179 	 *
1180 	 * Although replace_rte_variables() faithfully updated parse->hasSubLinks
1181 	 * if it copied any SubLinks out of the subquery's targetlist, we still
1182 	 * could have SubLinks added to the query in the expressions of FUNCTION
1183 	 * and VALUES RTEs copied up from the subquery.  So it's necessary to copy
1184 	 * subquery->hasSubLinks anyway.  Perhaps this can be improved someday.
1185 	 */
1186 	parse->hasSubLinks |= subquery->hasSubLinks;
1187 
1188 	/* If subquery had any RLS conditions, now main query does too */
1189 	parse->hasRowSecurity |= subquery->hasRowSecurity;
1190 
1191 	/*
1192 	 * subquery won't be pulled up if it hasAggs, hasWindowFuncs, or
1193 	 * hasTargetSRFs, so no work needed on those flags
1194 	 */
1195 
1196 	/*
1197 	 * Return the adjusted subquery jointree to replace the RangeTblRef entry
1198 	 * in parent's jointree; or, if the FromExpr is degenerate, just return
1199 	 * its single member.
1200 	 */
1201 	Assert(IsA(subquery->jointree, FromExpr));
1202 	Assert(subquery->jointree->fromlist != NIL);
1203 	if (subquery->jointree->quals == NULL &&
1204 		list_length(subquery->jointree->fromlist) == 1)
1205 		return (Node *) linitial(subquery->jointree->fromlist);
1206 
1207 	return (Node *) subquery->jointree;
1208 }
1209 
1210 /*
1211  * pull_up_simple_union_all
1212  *		Pull up a single simple UNION ALL subquery.
1213  *
1214  * jtnode is a RangeTblRef that has been identified as a simple UNION ALL
1215  * subquery by pull_up_subqueries.  We pull up the leaf subqueries and
1216  * build an "append relation" for the union set.  The result value is just
1217  * jtnode, since we don't actually need to change the query jointree.
1218  */
1219 static Node *
pull_up_simple_union_all(PlannerInfo * root,Node * jtnode,RangeTblEntry * rte)1220 pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
1221 {
1222 	int			varno = ((RangeTblRef *) jtnode)->rtindex;
1223 	Query	   *subquery = rte->subquery;
1224 	int			rtoffset = list_length(root->parse->rtable);
1225 	List	   *rtable;
1226 
1227 	/*
1228 	 * Make a modifiable copy of the subquery's rtable, so we can adjust
1229 	 * upper-level Vars in it.  There are no such Vars in the setOperations
1230 	 * tree proper, so fixing the rtable should be sufficient.
1231 	 */
1232 	rtable = copyObject(subquery->rtable);
1233 
1234 	/*
1235 	 * Upper-level vars in subquery are now one level closer to their parent
1236 	 * than before.  We don't have to worry about offsetting varnos, though,
1237 	 * because the UNION leaf queries can't cross-reference each other.
1238 	 */
1239 	IncrementVarSublevelsUp_rtable(rtable, -1, 1);
1240 
1241 	/*
1242 	 * If the UNION ALL subquery had a LATERAL marker, propagate that to all
1243 	 * its children.  The individual children might or might not contain any
1244 	 * actual lateral cross-references, but we have to mark the pulled-up
1245 	 * child RTEs so that later planner stages will check for such.
1246 	 */
1247 	if (rte->lateral)
1248 	{
1249 		ListCell   *rt;
1250 
1251 		foreach(rt, rtable)
1252 		{
1253 			RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(rt);
1254 
1255 			Assert(child_rte->rtekind == RTE_SUBQUERY);
1256 			child_rte->lateral = true;
1257 		}
1258 	}
1259 
1260 	/*
1261 	 * Append child RTEs to parent rtable.
1262 	 */
1263 	root->parse->rtable = list_concat(root->parse->rtable, rtable);
1264 
1265 	/*
1266 	 * Recursively scan the subquery's setOperations tree and add
1267 	 * AppendRelInfo nodes for leaf subqueries to the parent's
1268 	 * append_rel_list.  Also apply pull_up_subqueries to the leaf subqueries.
1269 	 */
1270 	Assert(subquery->setOperations);
1271 	pull_up_union_leaf_queries(subquery->setOperations, root, varno, subquery,
1272 							   rtoffset);
1273 
1274 	/*
1275 	 * Mark the parent as an append relation.
1276 	 */
1277 	rte->inh = true;
1278 
1279 	return jtnode;
1280 }
1281 
1282 /*
1283  * pull_up_union_leaf_queries -- recursive guts of pull_up_simple_union_all
1284  *
1285  * Build an AppendRelInfo for each leaf query in the setop tree, and then
1286  * apply pull_up_subqueries to the leaf query.
1287  *
1288  * Note that setOpQuery is the Query containing the setOp node, whose tlist
1289  * contains references to all the setop output columns.  When called from
1290  * pull_up_simple_union_all, this is *not* the same as root->parse, which is
1291  * the parent Query we are pulling up into.
1292  *
1293  * parentRTindex is the appendrel parent's index in root->parse->rtable.
1294  *
1295  * The child RTEs have already been copied to the parent.  childRToffset
1296  * tells us where in the parent's range table they were copied.  When called
1297  * from flatten_simple_union_all, childRToffset is 0 since the child RTEs
1298  * were already in root->parse->rtable and no RT index adjustment is needed.
1299  */
1300 static void
pull_up_union_leaf_queries(Node * setOp,PlannerInfo * root,int parentRTindex,Query * setOpQuery,int childRToffset)1301 pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
1302 						   Query *setOpQuery, int childRToffset)
1303 {
1304 	if (IsA(setOp, RangeTblRef))
1305 	{
1306 		RangeTblRef *rtr = (RangeTblRef *) setOp;
1307 		int			childRTindex;
1308 		AppendRelInfo *appinfo;
1309 
1310 		/*
1311 		 * Calculate the index in the parent's range table
1312 		 */
1313 		childRTindex = childRToffset + rtr->rtindex;
1314 
1315 		/*
1316 		 * Build a suitable AppendRelInfo, and attach to parent's list.
1317 		 */
1318 		appinfo = makeNode(AppendRelInfo);
1319 		appinfo->parent_relid = parentRTindex;
1320 		appinfo->child_relid = childRTindex;
1321 		appinfo->parent_reltype = InvalidOid;
1322 		appinfo->child_reltype = InvalidOid;
1323 		make_setop_translation_list(setOpQuery, childRTindex, appinfo);
1324 		appinfo->parent_reloid = InvalidOid;
1325 		root->append_rel_list = lappend(root->append_rel_list, appinfo);
1326 
1327 		/*
1328 		 * Recursively apply pull_up_subqueries to the new child RTE.  (We
1329 		 * must build the AppendRelInfo first, because this will modify it.)
1330 		 * Note that we can pass NULL for containing-join info even if we're
1331 		 * actually under an outer join, because the child's expressions
1332 		 * aren't going to propagate up to the join.  Also, we ignore the
1333 		 * possibility that pull_up_subqueries_recurse() returns a different
1334 		 * jointree node than what we pass it; if it does, the important thing
1335 		 * is that it replaced the child relid in the AppendRelInfo node.
1336 		 */
1337 		rtr = makeNode(RangeTblRef);
1338 		rtr->rtindex = childRTindex;
1339 		(void) pull_up_subqueries_recurse(root, (Node *) rtr,
1340 										  NULL, NULL, appinfo);
1341 	}
1342 	else if (IsA(setOp, SetOperationStmt))
1343 	{
1344 		SetOperationStmt *op = (SetOperationStmt *) setOp;
1345 
1346 		/* Recurse to reach leaf queries */
1347 		pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,
1348 								   childRToffset);
1349 		pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,
1350 								   childRToffset);
1351 	}
1352 	else
1353 	{
1354 		elog(ERROR, "unrecognized node type: %d",
1355 			 (int) nodeTag(setOp));
1356 	}
1357 }
1358 
1359 /*
1360  * make_setop_translation_list
1361  *	  Build the list of translations from parent Vars to child Vars for
1362  *	  a UNION ALL member.  (At this point it's just a simple list of
1363  *	  referencing Vars, but if we succeed in pulling up the member
1364  *	  subquery, the Vars will get replaced by pulled-up expressions.)
1365  *	  Also create the rather trivial reverse-translation array.
1366  */
1367 static void
make_setop_translation_list(Query * query,Index newvarno,AppendRelInfo * appinfo)1368 make_setop_translation_list(Query *query, Index newvarno,
1369 							AppendRelInfo *appinfo)
1370 {
1371 	List	   *vars = NIL;
1372 	AttrNumber *pcolnos;
1373 	ListCell   *l;
1374 
1375 	/* Initialize reverse-translation array with all entries zero */
1376 	/* (entries for resjunk columns will stay that way) */
1377 	appinfo->num_child_cols = list_length(query->targetList);
1378 	appinfo->parent_colnos = pcolnos =
1379 		(AttrNumber *) palloc0(appinfo->num_child_cols * sizeof(AttrNumber));
1380 
1381 	foreach(l, query->targetList)
1382 	{
1383 		TargetEntry *tle = (TargetEntry *) lfirst(l);
1384 
1385 		if (tle->resjunk)
1386 			continue;
1387 
1388 		vars = lappend(vars, makeVarFromTargetEntry(newvarno, tle));
1389 		pcolnos[tle->resno - 1] = tle->resno;
1390 	}
1391 
1392 	appinfo->translated_vars = vars;
1393 }
1394 
1395 /*
1396  * is_simple_subquery
1397  *	  Check a subquery in the range table to see if it's simple enough
1398  *	  to pull up into the parent query.
1399  *
1400  * rte is the RTE_SUBQUERY RangeTblEntry that contained the subquery.
1401  * (Note subquery is not necessarily equal to rte->subquery; it could be a
1402  * processed copy of that.)
1403  * lowest_outer_join is the lowest outer join above the subquery, or NULL.
1404  */
1405 static bool
is_simple_subquery(PlannerInfo * root,Query * subquery,RangeTblEntry * rte,JoinExpr * lowest_outer_join)1406 is_simple_subquery(PlannerInfo *root, Query *subquery, RangeTblEntry *rte,
1407 				   JoinExpr *lowest_outer_join)
1408 {
1409 	/*
1410 	 * Let's just make sure it's a valid subselect ...
1411 	 */
1412 	if (!IsA(subquery, Query) ||
1413 		subquery->commandType != CMD_SELECT)
1414 		elog(ERROR, "subquery is bogus");
1415 
1416 	/*
1417 	 * Can't currently pull up a query with setops (unless it's simple UNION
1418 	 * ALL, which is handled by a different code path). Maybe after querytree
1419 	 * redesign...
1420 	 */
1421 	if (subquery->setOperations)
1422 		return false;
1423 
1424 	/*
1425 	 * Can't pull up a subquery involving grouping, aggregation, SRFs,
1426 	 * sorting, limiting, or WITH.  (XXX WITH could possibly be allowed later)
1427 	 *
1428 	 * We also don't pull up a subquery that has explicit FOR UPDATE/SHARE
1429 	 * clauses, because pullup would cause the locking to occur semantically
1430 	 * higher than it should.  Implicit FOR UPDATE/SHARE is okay because in
1431 	 * that case the locking was originally declared in the upper query
1432 	 * anyway.
1433 	 */
1434 	if (subquery->hasAggs ||
1435 		subquery->hasWindowFuncs ||
1436 		subquery->hasTargetSRFs ||
1437 		subquery->groupClause ||
1438 		subquery->groupingSets ||
1439 		subquery->havingQual ||
1440 		subquery->sortClause ||
1441 		subquery->distinctClause ||
1442 		subquery->limitOffset ||
1443 		subquery->limitCount ||
1444 		subquery->hasForUpdate ||
1445 		subquery->cteList)
1446 		return false;
1447 
1448 	/*
1449 	 * Don't pull up if the RTE represents a security-barrier view; we
1450 	 * couldn't prevent information leakage once the RTE's Vars are scattered
1451 	 * about in the upper query.
1452 	 */
1453 	if (rte->security_barrier)
1454 		return false;
1455 
1456 	/*
1457 	 * If the subquery is LATERAL, check for pullup restrictions from that.
1458 	 */
1459 	if (rte->lateral)
1460 	{
1461 		bool		restricted;
1462 		Relids		safe_upper_varnos;
1463 
1464 		/*
1465 		 * The subquery's WHERE and JOIN/ON quals mustn't contain any lateral
1466 		 * references to rels outside a higher outer join (including the case
1467 		 * where the outer join is within the subquery itself).  In such a
1468 		 * case, pulling up would result in a situation where we need to
1469 		 * postpone quals from below an outer join to above it, which is
1470 		 * probably completely wrong and in any case is a complication that
1471 		 * doesn't seem worth addressing at the moment.
1472 		 */
1473 		if (lowest_outer_join != NULL)
1474 		{
1475 			restricted = true;
1476 			safe_upper_varnos = get_relids_in_jointree((Node *) lowest_outer_join,
1477 													   true);
1478 		}
1479 		else
1480 		{
1481 			restricted = false;
1482 			safe_upper_varnos = NULL;	/* doesn't matter */
1483 		}
1484 
1485 		if (jointree_contains_lateral_outer_refs(root,
1486 												 (Node *) subquery->jointree,
1487 												 restricted, safe_upper_varnos))
1488 			return false;
1489 
1490 		/*
1491 		 * If there's an outer join above the LATERAL subquery, also disallow
1492 		 * pullup if the subquery's targetlist has any references to rels
1493 		 * outside the outer join, since these might get pulled into quals
1494 		 * above the subquery (but in or below the outer join) and then lead
1495 		 * to qual-postponement issues similar to the case checked for above.
1496 		 * (We wouldn't need to prevent pullup if no such references appear in
1497 		 * outer-query quals, but we don't have enough info here to check
1498 		 * that.  Also, maybe this restriction could be removed if we forced
1499 		 * such refs to be wrapped in PlaceHolderVars, even when they're below
1500 		 * the nearest outer join?	But it's a pretty hokey usage, so not
1501 		 * clear this is worth sweating over.)
1502 		 */
1503 		if (lowest_outer_join != NULL)
1504 		{
1505 			Relids		lvarnos = pull_varnos_of_level(root,
1506 													   (Node *) subquery->targetList,
1507 													   1);
1508 
1509 			if (!bms_is_subset(lvarnos, safe_upper_varnos))
1510 				return false;
1511 		}
1512 	}
1513 
1514 	/*
1515 	 * Don't pull up a subquery that has any volatile functions in its
1516 	 * targetlist.  Otherwise we might introduce multiple evaluations of these
1517 	 * functions, if they get copied to multiple places in the upper query,
1518 	 * leading to surprising results.  (Note: the PlaceHolderVar mechanism
1519 	 * doesn't quite guarantee single evaluation; else we could pull up anyway
1520 	 * and just wrap such items in PlaceHolderVars ...)
1521 	 */
1522 	if (contain_volatile_functions((Node *) subquery->targetList))
1523 		return false;
1524 
1525 	return true;
1526 }
1527 
1528 /*
1529  * pull_up_simple_values
1530  *		Pull up a single simple VALUES RTE.
1531  *
1532  * jtnode is a RangeTblRef that has been identified as a simple VALUES RTE
1533  * by pull_up_subqueries.  We always return a RangeTblRef representing a
1534  * RESULT RTE to replace it (all failure cases should have been detected by
1535  * is_simple_values()).  Actually, what we return is just jtnode, because
1536  * we replace the VALUES RTE in the rangetable with the RESULT RTE.
1537  *
1538  * rte is the RangeTblEntry referenced by jtnode.  Because of the limited
1539  * possible usage of VALUES RTEs, we do not need the remaining parameters
1540  * of pull_up_subqueries_recurse.
1541  */
1542 static Node *
pull_up_simple_values(PlannerInfo * root,Node * jtnode,RangeTblEntry * rte)1543 pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
1544 {
1545 	Query	   *parse = root->parse;
1546 	int			varno = ((RangeTblRef *) jtnode)->rtindex;
1547 	List	   *values_list;
1548 	List	   *tlist;
1549 	AttrNumber	attrno;
1550 	pullup_replace_vars_context rvcontext;
1551 	ListCell   *lc;
1552 
1553 	Assert(rte->rtekind == RTE_VALUES);
1554 	Assert(list_length(rte->values_lists) == 1);
1555 
1556 	/*
1557 	 * Need a modifiable copy of the VALUES list to hack on, just in case it's
1558 	 * multiply referenced.
1559 	 */
1560 	values_list = copyObject(linitial(rte->values_lists));
1561 
1562 	/*
1563 	 * The VALUES RTE can't contain any Vars of level zero, let alone any that
1564 	 * are join aliases, so no need to flatten join alias Vars.
1565 	 */
1566 	Assert(!contain_vars_of_level((Node *) values_list, 0));
1567 
1568 	/*
1569 	 * Set up required context data for pullup_replace_vars.  In particular,
1570 	 * we have to make the VALUES list look like a subquery targetlist.
1571 	 */
1572 	tlist = NIL;
1573 	attrno = 1;
1574 	foreach(lc, values_list)
1575 	{
1576 		tlist = lappend(tlist,
1577 						makeTargetEntry((Expr *) lfirst(lc),
1578 										attrno,
1579 										NULL,
1580 										false));
1581 		attrno++;
1582 	}
1583 	rvcontext.root = root;
1584 	rvcontext.targetlist = tlist;
1585 	rvcontext.target_rte = rte;
1586 	rvcontext.relids = NULL;
1587 	rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1588 	rvcontext.varno = varno;
1589 	rvcontext.need_phvs = false;
1590 	rvcontext.wrap_non_vars = false;
1591 	/* initialize cache array with indexes 0 .. length(tlist) */
1592 	rvcontext.rv_cache = palloc0((list_length(tlist) + 1) *
1593 								 sizeof(Node *));
1594 
1595 	/*
1596 	 * Replace all of the top query's references to the RTE's outputs with
1597 	 * copies of the adjusted VALUES expressions, being careful not to replace
1598 	 * any of the jointree structure.  We can assume there's no outer joins or
1599 	 * appendrels in the dummy Query that surrounds a VALUES RTE.
1600 	 */
1601 	perform_pullup_replace_vars(root, &rvcontext, NULL, NULL);
1602 
1603 	/*
1604 	 * There should be no appendrels to fix, nor any outer joins and hence no
1605 	 * PlaceHolderVars.
1606 	 */
1607 	Assert(root->append_rel_list == NIL);
1608 	Assert(root->join_info_list == NIL);
1609 	Assert(root->placeholder_list == NIL);
1610 
1611 	/*
1612 	 * Replace the VALUES RTE with a RESULT RTE.  The VALUES RTE is the only
1613 	 * rtable entry in the current query level, so this is easy.
1614 	 */
1615 	Assert(list_length(parse->rtable) == 1);
1616 
1617 	/* Create suitable RTE */
1618 	rte = makeNode(RangeTblEntry);
1619 	rte->rtekind = RTE_RESULT;
1620 	rte->eref = makeAlias("*RESULT*", NIL);
1621 
1622 	/* Replace rangetable */
1623 	parse->rtable = list_make1(rte);
1624 
1625 	/* We could manufacture a new RangeTblRef, but the one we have is fine */
1626 	Assert(varno == 1);
1627 
1628 	return jtnode;
1629 }
1630 
1631 /*
1632  * is_simple_values
1633  *	  Check a VALUES RTE in the range table to see if it's simple enough
1634  *	  to pull up into the parent query.
1635  *
1636  * rte is the RTE_VALUES RangeTblEntry to check.
1637  */
1638 static bool
is_simple_values(PlannerInfo * root,RangeTblEntry * rte)1639 is_simple_values(PlannerInfo *root, RangeTblEntry *rte)
1640 {
1641 	Assert(rte->rtekind == RTE_VALUES);
1642 
1643 	/*
1644 	 * There must be exactly one VALUES list, else it's not semantically
1645 	 * correct to replace the VALUES RTE with a RESULT RTE, nor would we have
1646 	 * a unique set of expressions to substitute into the parent query.
1647 	 */
1648 	if (list_length(rte->values_lists) != 1)
1649 		return false;
1650 
1651 	/*
1652 	 * Because VALUES can't appear under an outer join (or at least, we won't
1653 	 * try to pull it up if it does), we need not worry about LATERAL, nor
1654 	 * about validity of PHVs for the VALUES' outputs.
1655 	 */
1656 
1657 	/*
1658 	 * Don't pull up a VALUES that contains any set-returning or volatile
1659 	 * functions.  The considerations here are basically identical to the
1660 	 * restrictions on a pull-able subquery's targetlist.
1661 	 */
1662 	if (expression_returns_set((Node *) rte->values_lists) ||
1663 		contain_volatile_functions((Node *) rte->values_lists))
1664 		return false;
1665 
1666 	/*
1667 	 * Do not pull up a VALUES that's not the only RTE in its parent query.
1668 	 * This is actually the only case that the parser will generate at the
1669 	 * moment, and assuming this is true greatly simplifies
1670 	 * pull_up_simple_values().
1671 	 */
1672 	if (list_length(root->parse->rtable) != 1 ||
1673 		rte != (RangeTblEntry *) linitial(root->parse->rtable))
1674 		return false;
1675 
1676 	return true;
1677 }
1678 
1679 /*
1680  * pull_up_constant_function
1681  *		Pull up an RTE_FUNCTION expression that was simplified to a constant.
1682  *
1683  * jtnode is a RangeTblRef that has been identified as a FUNCTION RTE by
1684  * pull_up_subqueries.  If its expression is just a Const, hoist that value
1685  * up into the parent query, and replace the RTE_FUNCTION with RTE_RESULT.
1686  *
1687  * In principle we could pull up any immutable expression, but we don't.
1688  * That might result in multiple evaluations of the expression, which could
1689  * be costly if it's not just a Const.  Also, the main value of this is
1690  * to let the constant participate in further const-folding, and of course
1691  * that won't happen for a non-Const.
1692  *
1693  * The pulled-up value might need to be wrapped in a PlaceHolderVar if the
1694  * RTE is below an outer join or is part of an appendrel; the extra
1695  * parameters show whether that's needed.
1696  */
1697 static Node *
pull_up_constant_function(PlannerInfo * root,Node * jtnode,RangeTblEntry * rte,JoinExpr * lowest_nulling_outer_join,AppendRelInfo * containing_appendrel)1698 pull_up_constant_function(PlannerInfo *root, Node *jtnode,
1699 						  RangeTblEntry *rte,
1700 						  JoinExpr *lowest_nulling_outer_join,
1701 						  AppendRelInfo *containing_appendrel)
1702 {
1703 	Query	   *parse = root->parse;
1704 	RangeTblFunction *rtf;
1705 	TypeFuncClass functypclass;
1706 	Oid			funcrettype;
1707 	TupleDesc	tupdesc;
1708 	pullup_replace_vars_context rvcontext;
1709 
1710 	/* Fail if the RTE has ORDINALITY - we don't implement that here. */
1711 	if (rte->funcordinality)
1712 		return jtnode;
1713 
1714 	/* Fail if RTE isn't a single, simple Const expr */
1715 	if (list_length(rte->functions) != 1)
1716 		return jtnode;
1717 	rtf = linitial_node(RangeTblFunction, rte->functions);
1718 	if (!IsA(rtf->funcexpr, Const))
1719 		return jtnode;
1720 
1721 	/*
1722 	 * If the function's result is not a scalar, we punt.  In principle we
1723 	 * could break the composite constant value apart into per-column
1724 	 * constants, but for now it seems not worth the work.
1725 	 */
1726 	if (rtf->funccolcount != 1)
1727 		return jtnode;			/* definitely composite */
1728 
1729 	functypclass = get_expr_result_type(rtf->funcexpr,
1730 										&funcrettype,
1731 										&tupdesc);
1732 	if (functypclass != TYPEFUNC_SCALAR)
1733 		return jtnode;			/* must be a one-column composite type */
1734 
1735 	/* Create context for applying pullup_replace_vars */
1736 	rvcontext.root = root;
1737 	rvcontext.targetlist = list_make1(makeTargetEntry((Expr *) rtf->funcexpr,
1738 													  1,	/* resno */
1739 													  NULL, /* resname */
1740 													  false));	/* resjunk */
1741 	rvcontext.target_rte = rte;
1742 
1743 	/*
1744 	 * Since this function was reduced to a Const, it doesn't contain any
1745 	 * lateral references, even if it's marked as LATERAL.  This means we
1746 	 * don't need to fill relids.
1747 	 */
1748 	rvcontext.relids = NULL;
1749 
1750 	rvcontext.outer_hasSubLinks = &parse->hasSubLinks;
1751 	rvcontext.varno = ((RangeTblRef *) jtnode)->rtindex;
1752 	/* these flags will be set below, if needed */
1753 	rvcontext.need_phvs = false;
1754 	rvcontext.wrap_non_vars = false;
1755 	/* initialize cache array with indexes 0 .. length(tlist) */
1756 	rvcontext.rv_cache = palloc0((list_length(rvcontext.targetlist) + 1) *
1757 								 sizeof(Node *));
1758 
1759 	/*
1760 	 * If we are under an outer join then non-nullable items and lateral
1761 	 * references may have to be turned into PlaceHolderVars.
1762 	 */
1763 	if (lowest_nulling_outer_join != NULL)
1764 		rvcontext.need_phvs = true;
1765 
1766 	/*
1767 	 * If we are dealing with an appendrel member then anything that's not a
1768 	 * simple Var has to be turned into a PlaceHolderVar.  (See comments in
1769 	 * pull_up_simple_subquery().)
1770 	 */
1771 	if (containing_appendrel != NULL)
1772 	{
1773 		rvcontext.need_phvs = true;
1774 		rvcontext.wrap_non_vars = true;
1775 	}
1776 
1777 	/*
1778 	 * If the parent query uses grouping sets, we need a PlaceHolderVar for
1779 	 * anything that's not a simple Var.
1780 	 */
1781 	if (parse->groupingSets)
1782 	{
1783 		rvcontext.need_phvs = true;
1784 		rvcontext.wrap_non_vars = true;
1785 	}
1786 
1787 	/*
1788 	 * Replace all of the top query's references to the RTE's output with
1789 	 * copies of the funcexpr, being careful not to replace any of the
1790 	 * jointree structure.
1791 	 */
1792 	perform_pullup_replace_vars(root, &rvcontext,
1793 								lowest_nulling_outer_join,
1794 								containing_appendrel);
1795 
1796 	/*
1797 	 * We don't need to bother with changing PlaceHolderVars in the parent
1798 	 * query.  Their references to the RT index are still good for now, and
1799 	 * will get removed later if we're able to drop the RTE_RESULT.
1800 	 */
1801 
1802 	/*
1803 	 * Convert the RTE to be RTE_RESULT type, signifying that we don't need to
1804 	 * scan it anymore, and zero out RTE_FUNCTION-specific fields.  Also make
1805 	 * sure the RTE is not marked LATERAL, since elsewhere we don't expect
1806 	 * RTE_RESULTs to be LATERAL.
1807 	 */
1808 	rte->rtekind = RTE_RESULT;
1809 	rte->functions = NIL;
1810 	rte->lateral = false;
1811 
1812 	/*
1813 	 * We can reuse the RangeTblRef node.
1814 	 */
1815 	return jtnode;
1816 }
1817 
1818 /*
1819  * is_simple_union_all
1820  *	  Check a subquery to see if it's a simple UNION ALL.
1821  *
1822  * We require all the setops to be UNION ALL (no mixing) and there can't be
1823  * any datatype coercions involved, ie, all the leaf queries must emit the
1824  * same datatypes.
1825  */
1826 static bool
is_simple_union_all(Query * subquery)1827 is_simple_union_all(Query *subquery)
1828 {
1829 	SetOperationStmt *topop;
1830 
1831 	/* Let's just make sure it's a valid subselect ... */
1832 	if (!IsA(subquery, Query) ||
1833 		subquery->commandType != CMD_SELECT)
1834 		elog(ERROR, "subquery is bogus");
1835 
1836 	/* Is it a set-operation query at all? */
1837 	topop = castNode(SetOperationStmt, subquery->setOperations);
1838 	if (!topop)
1839 		return false;
1840 
1841 	/* Can't handle ORDER BY, LIMIT/OFFSET, locking, or WITH */
1842 	if (subquery->sortClause ||
1843 		subquery->limitOffset ||
1844 		subquery->limitCount ||
1845 		subquery->rowMarks ||
1846 		subquery->cteList)
1847 		return false;
1848 
1849 	/* Recursively check the tree of set operations */
1850 	return is_simple_union_all_recurse((Node *) topop, subquery,
1851 									   topop->colTypes);
1852 }
1853 
1854 static bool
is_simple_union_all_recurse(Node * setOp,Query * setOpQuery,List * colTypes)1855 is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
1856 {
1857 	if (IsA(setOp, RangeTblRef))
1858 	{
1859 		RangeTblRef *rtr = (RangeTblRef *) setOp;
1860 		RangeTblEntry *rte = rt_fetch(rtr->rtindex, setOpQuery->rtable);
1861 		Query	   *subquery = rte->subquery;
1862 
1863 		Assert(subquery != NULL);
1864 
1865 		/* Leaf nodes are OK if they match the toplevel column types */
1866 		/* We don't have to compare typmods or collations here */
1867 		return tlist_same_datatypes(subquery->targetList, colTypes, true);
1868 	}
1869 	else if (IsA(setOp, SetOperationStmt))
1870 	{
1871 		SetOperationStmt *op = (SetOperationStmt *) setOp;
1872 
1873 		/* Must be UNION ALL */
1874 		if (op->op != SETOP_UNION || !op->all)
1875 			return false;
1876 
1877 		/* Recurse to check inputs */
1878 		return is_simple_union_all_recurse(op->larg, setOpQuery, colTypes) &&
1879 			is_simple_union_all_recurse(op->rarg, setOpQuery, colTypes);
1880 	}
1881 	else
1882 	{
1883 		elog(ERROR, "unrecognized node type: %d",
1884 			 (int) nodeTag(setOp));
1885 		return false;			/* keep compiler quiet */
1886 	}
1887 }
1888 
1889 /*
1890  * is_safe_append_member
1891  *	  Check a subquery that is a leaf of a UNION ALL appendrel to see if it's
1892  *	  safe to pull up.
1893  */
1894 static bool
is_safe_append_member(Query * subquery)1895 is_safe_append_member(Query *subquery)
1896 {
1897 	FromExpr   *jtnode;
1898 
1899 	/*
1900 	 * It's only safe to pull up the child if its jointree contains exactly
1901 	 * one RTE, else the AppendRelInfo data structure breaks. The one base RTE
1902 	 * could be buried in several levels of FromExpr, however.  Also, if the
1903 	 * child's jointree is completely empty, we can pull up because
1904 	 * pull_up_simple_subquery will insert a single RTE_RESULT RTE instead.
1905 	 *
1906 	 * Also, the child can't have any WHERE quals because there's no place to
1907 	 * put them in an appendrel.  (This is a bit annoying...) If we didn't
1908 	 * need to check this, we'd just test whether get_relids_in_jointree()
1909 	 * yields a singleton set, to be more consistent with the coding of
1910 	 * fix_append_rel_relids().
1911 	 */
1912 	jtnode = subquery->jointree;
1913 	Assert(IsA(jtnode, FromExpr));
1914 	/* Check the completely-empty case */
1915 	if (jtnode->fromlist == NIL && jtnode->quals == NULL)
1916 		return true;
1917 	/* Check the more general case */
1918 	while (IsA(jtnode, FromExpr))
1919 	{
1920 		if (jtnode->quals != NULL)
1921 			return false;
1922 		if (list_length(jtnode->fromlist) != 1)
1923 			return false;
1924 		jtnode = linitial(jtnode->fromlist);
1925 	}
1926 	if (!IsA(jtnode, RangeTblRef))
1927 		return false;
1928 
1929 	return true;
1930 }
1931 
1932 /*
1933  * jointree_contains_lateral_outer_refs
1934  *		Check for disallowed lateral references in a jointree's quals
1935  *
1936  * If restricted is false, all level-1 Vars are allowed (but we still must
1937  * search the jointree, since it might contain outer joins below which there
1938  * will be restrictions).  If restricted is true, return true when any qual
1939  * in the jointree contains level-1 Vars coming from outside the rels listed
1940  * in safe_upper_varnos.
1941  */
1942 static bool
jointree_contains_lateral_outer_refs(PlannerInfo * root,Node * jtnode,bool restricted,Relids safe_upper_varnos)1943 jointree_contains_lateral_outer_refs(PlannerInfo *root, Node *jtnode,
1944 									 bool restricted,
1945 									 Relids safe_upper_varnos)
1946 {
1947 	if (jtnode == NULL)
1948 		return false;
1949 	if (IsA(jtnode, RangeTblRef))
1950 		return false;
1951 	else if (IsA(jtnode, FromExpr))
1952 	{
1953 		FromExpr   *f = (FromExpr *) jtnode;
1954 		ListCell   *l;
1955 
1956 		/* First, recurse to check child joins */
1957 		foreach(l, f->fromlist)
1958 		{
1959 			if (jointree_contains_lateral_outer_refs(root,
1960 													 lfirst(l),
1961 													 restricted,
1962 													 safe_upper_varnos))
1963 				return true;
1964 		}
1965 
1966 		/* Then check the top-level quals */
1967 		if (restricted &&
1968 			!bms_is_subset(pull_varnos_of_level(root, f->quals, 1),
1969 						   safe_upper_varnos))
1970 			return true;
1971 	}
1972 	else if (IsA(jtnode, JoinExpr))
1973 	{
1974 		JoinExpr   *j = (JoinExpr *) jtnode;
1975 
1976 		/*
1977 		 * If this is an outer join, we mustn't allow any upper lateral
1978 		 * references in or below it.
1979 		 */
1980 		if (j->jointype != JOIN_INNER)
1981 		{
1982 			restricted = true;
1983 			safe_upper_varnos = NULL;
1984 		}
1985 
1986 		/* Check the child joins */
1987 		if (jointree_contains_lateral_outer_refs(root,
1988 												 j->larg,
1989 												 restricted,
1990 												 safe_upper_varnos))
1991 			return true;
1992 		if (jointree_contains_lateral_outer_refs(root,
1993 												 j->rarg,
1994 												 restricted,
1995 												 safe_upper_varnos))
1996 			return true;
1997 
1998 		/* Check the JOIN's qual clauses */
1999 		if (restricted &&
2000 			!bms_is_subset(pull_varnos_of_level(root, j->quals, 1),
2001 						   safe_upper_varnos))
2002 			return true;
2003 	}
2004 	else
2005 		elog(ERROR, "unrecognized node type: %d",
2006 			 (int) nodeTag(jtnode));
2007 	return false;
2008 }
2009 
2010 /*
2011  * Perform pullup_replace_vars everyplace it's needed in the query tree.
2012  *
2013  * Caller has already filled *rvcontext with data describing what to
2014  * substitute for Vars referencing the target subquery.  In addition
2015  * we need the identity of the lowest outer join that can null the
2016  * target subquery, and its containing appendrel if any.
2017  */
2018 static void
perform_pullup_replace_vars(PlannerInfo * root,pullup_replace_vars_context * rvcontext,JoinExpr * lowest_nulling_outer_join,AppendRelInfo * containing_appendrel)2019 perform_pullup_replace_vars(PlannerInfo *root,
2020 							pullup_replace_vars_context *rvcontext,
2021 							JoinExpr *lowest_nulling_outer_join,
2022 							AppendRelInfo *containing_appendrel)
2023 {
2024 	Query	   *parse = root->parse;
2025 	ListCell   *lc;
2026 
2027 	/*
2028 	 * Replace all of the top query's references to the subquery's outputs
2029 	 * with copies of the adjusted subtlist items, being careful not to
2030 	 * replace any of the jointree structure.  (This'd be a lot cleaner if we
2031 	 * could use query_tree_mutator.)  We have to use PHVs in the targetList,
2032 	 * returningList, and havingQual, since those are certainly above any
2033 	 * outer join.  replace_vars_in_jointree tracks its location in the
2034 	 * jointree and uses PHVs or not appropriately.
2035 	 */
2036 	parse->targetList = (List *)
2037 		pullup_replace_vars((Node *) parse->targetList, rvcontext);
2038 	parse->returningList = (List *)
2039 		pullup_replace_vars((Node *) parse->returningList, rvcontext);
2040 	if (parse->onConflict)
2041 	{
2042 		parse->onConflict->onConflictSet = (List *)
2043 			pullup_replace_vars((Node *) parse->onConflict->onConflictSet,
2044 								rvcontext);
2045 		parse->onConflict->onConflictWhere =
2046 			pullup_replace_vars(parse->onConflict->onConflictWhere,
2047 								rvcontext);
2048 
2049 		/*
2050 		 * We assume ON CONFLICT's arbiterElems, arbiterWhere, exclRelTlist
2051 		 * can't contain any references to a subquery.
2052 		 */
2053 	}
2054 	replace_vars_in_jointree((Node *) parse->jointree, rvcontext,
2055 							 lowest_nulling_outer_join);
2056 	Assert(parse->setOperations == NULL);
2057 	parse->havingQual = pullup_replace_vars(parse->havingQual, rvcontext);
2058 
2059 	/*
2060 	 * Replace references in the translated_vars lists of appendrels.  When
2061 	 * pulling up an appendrel member, we do not need PHVs in the list of the
2062 	 * parent appendrel --- there isn't any outer join between.  Elsewhere,
2063 	 * use PHVs for safety.  (This analysis could be made tighter but it seems
2064 	 * unlikely to be worth much trouble.)
2065 	 */
2066 	foreach(lc, root->append_rel_list)
2067 	{
2068 		AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(lc);
2069 		bool		save_need_phvs = rvcontext->need_phvs;
2070 
2071 		if (appinfo == containing_appendrel)
2072 			rvcontext->need_phvs = false;
2073 		appinfo->translated_vars = (List *)
2074 			pullup_replace_vars((Node *) appinfo->translated_vars, rvcontext);
2075 		rvcontext->need_phvs = save_need_phvs;
2076 	}
2077 
2078 	/*
2079 	 * Replace references in the joinaliasvars lists of join RTEs.
2080 	 *
2081 	 * You might think that we could avoid using PHVs for alias vars of joins
2082 	 * below lowest_nulling_outer_join, but that doesn't work because the
2083 	 * alias vars could be referenced above that join; we need the PHVs to be
2084 	 * present in such references after the alias vars get flattened.  (It
2085 	 * might be worth trying to be smarter here, someday.)
2086 	 */
2087 	foreach(lc, parse->rtable)
2088 	{
2089 		RangeTblEntry *otherrte = (RangeTblEntry *) lfirst(lc);
2090 
2091 		if (otherrte->rtekind == RTE_JOIN)
2092 			otherrte->joinaliasvars = (List *)
2093 				pullup_replace_vars((Node *) otherrte->joinaliasvars,
2094 									rvcontext);
2095 	}
2096 }
2097 
2098 /*
2099  * Helper routine for perform_pullup_replace_vars: do pullup_replace_vars on
2100  * every expression in the jointree, without changing the jointree structure
2101  * itself.  Ugly, but there's no other way...
2102  *
2103  * If we are at or below lowest_nulling_outer_join, we can suppress use of
2104  * PlaceHolderVars wrapped around the replacement expressions.
2105  */
2106 static void
replace_vars_in_jointree(Node * jtnode,pullup_replace_vars_context * context,JoinExpr * lowest_nulling_outer_join)2107 replace_vars_in_jointree(Node *jtnode,
2108 						 pullup_replace_vars_context *context,
2109 						 JoinExpr *lowest_nulling_outer_join)
2110 {
2111 	if (jtnode == NULL)
2112 		return;
2113 	if (IsA(jtnode, RangeTblRef))
2114 	{
2115 		/*
2116 		 * If the RangeTblRef refers to a LATERAL subquery (that isn't the
2117 		 * same subquery we're pulling up), it might contain references to the
2118 		 * target subquery, which we must replace.  We drive this from the
2119 		 * jointree scan, rather than a scan of the rtable, for a couple of
2120 		 * reasons: we can avoid processing no-longer-referenced RTEs, and we
2121 		 * can use the appropriate setting of need_phvs depending on whether
2122 		 * the RTE is above possibly-nulling outer joins or not.
2123 		 */
2124 		int			varno = ((RangeTblRef *) jtnode)->rtindex;
2125 
2126 		if (varno != context->varno)	/* ignore target subquery itself */
2127 		{
2128 			RangeTblEntry *rte = rt_fetch(varno, context->root->parse->rtable);
2129 
2130 			Assert(rte != context->target_rte);
2131 			if (rte->lateral)
2132 			{
2133 				switch (rte->rtekind)
2134 				{
2135 					case RTE_RELATION:
2136 						/* shouldn't be marked LATERAL unless tablesample */
2137 						Assert(rte->tablesample);
2138 						rte->tablesample = (TableSampleClause *)
2139 							pullup_replace_vars((Node *) rte->tablesample,
2140 												context);
2141 						break;
2142 					case RTE_SUBQUERY:
2143 						rte->subquery =
2144 							pullup_replace_vars_subquery(rte->subquery,
2145 														 context);
2146 						break;
2147 					case RTE_FUNCTION:
2148 						rte->functions = (List *)
2149 							pullup_replace_vars((Node *) rte->functions,
2150 												context);
2151 						break;
2152 					case RTE_TABLEFUNC:
2153 						rte->tablefunc = (TableFunc *)
2154 							pullup_replace_vars((Node *) rte->tablefunc,
2155 												context);
2156 						break;
2157 					case RTE_VALUES:
2158 						rte->values_lists = (List *)
2159 							pullup_replace_vars((Node *) rte->values_lists,
2160 												context);
2161 						break;
2162 					case RTE_JOIN:
2163 					case RTE_CTE:
2164 					case RTE_NAMEDTUPLESTORE:
2165 					case RTE_RESULT:
2166 						/* these shouldn't be marked LATERAL */
2167 						Assert(false);
2168 						break;
2169 				}
2170 			}
2171 		}
2172 	}
2173 	else if (IsA(jtnode, FromExpr))
2174 	{
2175 		FromExpr   *f = (FromExpr *) jtnode;
2176 		ListCell   *l;
2177 
2178 		foreach(l, f->fromlist)
2179 			replace_vars_in_jointree(lfirst(l), context,
2180 									 lowest_nulling_outer_join);
2181 		f->quals = pullup_replace_vars(f->quals, context);
2182 	}
2183 	else if (IsA(jtnode, JoinExpr))
2184 	{
2185 		JoinExpr   *j = (JoinExpr *) jtnode;
2186 		bool		save_need_phvs = context->need_phvs;
2187 
2188 		if (j == lowest_nulling_outer_join)
2189 		{
2190 			/* no more PHVs in or below this join */
2191 			context->need_phvs = false;
2192 			lowest_nulling_outer_join = NULL;
2193 		}
2194 		replace_vars_in_jointree(j->larg, context, lowest_nulling_outer_join);
2195 		replace_vars_in_jointree(j->rarg, context, lowest_nulling_outer_join);
2196 
2197 		/*
2198 		 * Use PHVs within the join quals of a full join, even when it's the
2199 		 * lowest nulling outer join.  Otherwise, we cannot identify which
2200 		 * side of the join a pulled-up var-free expression came from, which
2201 		 * can lead to failure to make a plan at all because none of the quals
2202 		 * appear to be mergeable or hashable conditions.  For this purpose we
2203 		 * don't care about the state of wrap_non_vars, so leave it alone.
2204 		 */
2205 		if (j->jointype == JOIN_FULL)
2206 			context->need_phvs = true;
2207 
2208 		j->quals = pullup_replace_vars(j->quals, context);
2209 
2210 		/*
2211 		 * We don't bother to update the colvars list, since it won't be used
2212 		 * again ...
2213 		 */
2214 		context->need_phvs = save_need_phvs;
2215 	}
2216 	else
2217 		elog(ERROR, "unrecognized node type: %d",
2218 			 (int) nodeTag(jtnode));
2219 }
2220 
2221 /*
2222  * Apply pullup variable replacement throughout an expression tree
2223  *
2224  * Returns a modified copy of the tree, so this can't be used where we
2225  * need to do in-place replacement.
2226  */
2227 static Node *
pullup_replace_vars(Node * expr,pullup_replace_vars_context * context)2228 pullup_replace_vars(Node *expr, pullup_replace_vars_context *context)
2229 {
2230 	return replace_rte_variables(expr,
2231 								 context->varno, 0,
2232 								 pullup_replace_vars_callback,
2233 								 (void *) context,
2234 								 context->outer_hasSubLinks);
2235 }
2236 
2237 static Node *
pullup_replace_vars_callback(Var * var,replace_rte_variables_context * context)2238 pullup_replace_vars_callback(Var *var,
2239 							 replace_rte_variables_context *context)
2240 {
2241 	pullup_replace_vars_context *rcon = (pullup_replace_vars_context *) context->callback_arg;
2242 	int			varattno = var->varattno;
2243 	Node	   *newnode;
2244 
2245 	/*
2246 	 * If PlaceHolderVars are needed, we cache the modified expressions in
2247 	 * rcon->rv_cache[].  This is not in hopes of any material speed gain
2248 	 * within this function, but to avoid generating identical PHVs with
2249 	 * different IDs.  That would result in duplicate evaluations at runtime,
2250 	 * and possibly prevent optimizations that rely on recognizing different
2251 	 * references to the same subquery output as being equal().  So it's worth
2252 	 * a bit of extra effort to avoid it.
2253 	 */
2254 	if (rcon->need_phvs &&
2255 		varattno >= InvalidAttrNumber &&
2256 		varattno <= list_length(rcon->targetlist) &&
2257 		rcon->rv_cache[varattno] != NULL)
2258 	{
2259 		/* Just copy the entry and fall through to adjust its varlevelsup */
2260 		newnode = copyObject(rcon->rv_cache[varattno]);
2261 	}
2262 	else if (varattno == InvalidAttrNumber)
2263 	{
2264 		/* Must expand whole-tuple reference into RowExpr */
2265 		RowExpr    *rowexpr;
2266 		List	   *colnames;
2267 		List	   *fields;
2268 		bool		save_need_phvs = rcon->need_phvs;
2269 		int			save_sublevelsup = context->sublevels_up;
2270 
2271 		/*
2272 		 * If generating an expansion for a var of a named rowtype (ie, this
2273 		 * is a plain relation RTE), then we must include dummy items for
2274 		 * dropped columns.  If the var is RECORD (ie, this is a JOIN), then
2275 		 * omit dropped columns. Either way, attach column names to the
2276 		 * RowExpr for use of ruleutils.c.
2277 		 *
2278 		 * In order to be able to cache the results, we always generate the
2279 		 * expansion with varlevelsup = 0, and then adjust if needed.
2280 		 */
2281 		expandRTE(rcon->target_rte,
2282 				  var->varno, 0 /* not varlevelsup */ , var->location,
2283 				  (var->vartype != RECORDOID),
2284 				  &colnames, &fields);
2285 		/* Adjust the generated per-field Vars, but don't insert PHVs */
2286 		rcon->need_phvs = false;
2287 		context->sublevels_up = 0;	/* to match the expandRTE output */
2288 		fields = (List *) replace_rte_variables_mutator((Node *) fields,
2289 														context);
2290 		rcon->need_phvs = save_need_phvs;
2291 		context->sublevels_up = save_sublevelsup;
2292 
2293 		rowexpr = makeNode(RowExpr);
2294 		rowexpr->args = fields;
2295 		rowexpr->row_typeid = var->vartype;
2296 		rowexpr->row_format = COERCE_IMPLICIT_CAST;
2297 		rowexpr->colnames = colnames;
2298 		rowexpr->location = var->location;
2299 		newnode = (Node *) rowexpr;
2300 
2301 		/*
2302 		 * Insert PlaceHolderVar if needed.  Notice that we are wrapping one
2303 		 * PlaceHolderVar around the whole RowExpr, rather than putting one
2304 		 * around each element of the row.  This is because we need the
2305 		 * expression to yield NULL, not ROW(NULL,NULL,...) when it is forced
2306 		 * to null by an outer join.
2307 		 */
2308 		if (rcon->need_phvs)
2309 		{
2310 			/* RowExpr is certainly not strict, so always need PHV */
2311 			newnode = (Node *)
2312 				make_placeholder_expr(rcon->root,
2313 									  (Expr *) newnode,
2314 									  bms_make_singleton(rcon->varno));
2315 			/* cache it with the PHV, and with varlevelsup still zero */
2316 			rcon->rv_cache[InvalidAttrNumber] = copyObject(newnode);
2317 		}
2318 	}
2319 	else
2320 	{
2321 		/* Normal case referencing one targetlist element */
2322 		TargetEntry *tle = get_tle_by_resno(rcon->targetlist, varattno);
2323 
2324 		if (tle == NULL)		/* shouldn't happen */
2325 			elog(ERROR, "could not find attribute %d in subquery targetlist",
2326 				 varattno);
2327 
2328 		/* Make a copy of the tlist item to return */
2329 		newnode = (Node *) copyObject(tle->expr);
2330 
2331 		/* Insert PlaceHolderVar if needed */
2332 		if (rcon->need_phvs)
2333 		{
2334 			bool		wrap;
2335 
2336 			if (newnode && IsA(newnode, Var) &&
2337 				((Var *) newnode)->varlevelsup == 0)
2338 			{
2339 				/*
2340 				 * Simple Vars always escape being wrapped, unless they are
2341 				 * lateral references to something outside the subquery being
2342 				 * pulled up.  (Even then, we could omit the PlaceHolderVar if
2343 				 * the referenced rel is under the same lowest outer join, but
2344 				 * it doesn't seem worth the trouble to check that.)
2345 				 */
2346 				if (rcon->target_rte->lateral &&
2347 					!bms_is_member(((Var *) newnode)->varno, rcon->relids))
2348 					wrap = true;
2349 				else
2350 					wrap = false;
2351 			}
2352 			else if (newnode && IsA(newnode, PlaceHolderVar) &&
2353 					 ((PlaceHolderVar *) newnode)->phlevelsup == 0)
2354 			{
2355 				/* No need to wrap a PlaceHolderVar with another one, either */
2356 				wrap = false;
2357 			}
2358 			else if (rcon->wrap_non_vars)
2359 			{
2360 				/* Wrap all non-Vars in a PlaceHolderVar */
2361 				wrap = true;
2362 			}
2363 			else
2364 			{
2365 				/*
2366 				 * If it contains a Var of the subquery being pulled up, and
2367 				 * does not contain any non-strict constructs, then it's
2368 				 * certainly nullable so we don't need to insert a
2369 				 * PlaceHolderVar.
2370 				 *
2371 				 * This analysis could be tighter: in particular, a non-strict
2372 				 * construct hidden within a lower-level PlaceHolderVar is not
2373 				 * reason to add another PHV.  But for now it doesn't seem
2374 				 * worth the code to be more exact.
2375 				 *
2376 				 * Note: in future maybe we should insert a PlaceHolderVar
2377 				 * anyway, if the tlist item is expensive to evaluate?
2378 				 *
2379 				 * For a LATERAL subquery, we have to check the actual var
2380 				 * membership of the node, but if it's non-lateral then any
2381 				 * level-zero var must belong to the subquery.
2382 				 */
2383 				if ((rcon->target_rte->lateral ?
2384 					 bms_overlap(pull_varnos(rcon->root, (Node *) newnode),
2385 								 rcon->relids) :
2386 					 contain_vars_of_level((Node *) newnode, 0)) &&
2387 					!contain_nonstrict_functions((Node *) newnode))
2388 				{
2389 					/* No wrap needed */
2390 					wrap = false;
2391 				}
2392 				else
2393 				{
2394 					/* Else wrap it in a PlaceHolderVar */
2395 					wrap = true;
2396 				}
2397 			}
2398 
2399 			if (wrap)
2400 				newnode = (Node *)
2401 					make_placeholder_expr(rcon->root,
2402 										  (Expr *) newnode,
2403 										  bms_make_singleton(rcon->varno));
2404 
2405 			/*
2406 			 * Cache it if possible (ie, if the attno is in range, which it
2407 			 * probably always should be).  We can cache the value even if we
2408 			 * decided we didn't need a PHV, since this result will be
2409 			 * suitable for any request that has need_phvs.
2410 			 */
2411 			if (varattno > InvalidAttrNumber &&
2412 				varattno <= list_length(rcon->targetlist))
2413 				rcon->rv_cache[varattno] = copyObject(newnode);
2414 		}
2415 	}
2416 
2417 	/* Must adjust varlevelsup if tlist item is from higher query */
2418 	if (var->varlevelsup > 0)
2419 		IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
2420 
2421 	return newnode;
2422 }
2423 
2424 /*
2425  * Apply pullup variable replacement to a subquery
2426  *
2427  * This needs to be different from pullup_replace_vars() because
2428  * replace_rte_variables will think that it shouldn't increment sublevels_up
2429  * before entering the Query; so we need to call it with sublevels_up == 1.
2430  */
2431 static Query *
pullup_replace_vars_subquery(Query * query,pullup_replace_vars_context * context)2432 pullup_replace_vars_subquery(Query *query,
2433 							 pullup_replace_vars_context *context)
2434 {
2435 	Assert(IsA(query, Query));
2436 	return (Query *) replace_rte_variables((Node *) query,
2437 										   context->varno, 1,
2438 										   pullup_replace_vars_callback,
2439 										   (void *) context,
2440 										   NULL);
2441 }
2442 
2443 
2444 /*
2445  * flatten_simple_union_all
2446  *		Try to optimize top-level UNION ALL structure into an appendrel
2447  *
2448  * If a query's setOperations tree consists entirely of simple UNION ALL
2449  * operations, flatten it into an append relation, which we can process more
2450  * intelligently than the general setops case.  Otherwise, do nothing.
2451  *
2452  * In most cases, this can succeed only for a top-level query, because for a
2453  * subquery in FROM, the parent query's invocation of pull_up_subqueries would
2454  * already have flattened the UNION via pull_up_simple_union_all.  But there
2455  * are a few cases we can support here but not in that code path, for example
2456  * when the subquery also contains ORDER BY.
2457  */
2458 void
flatten_simple_union_all(PlannerInfo * root)2459 flatten_simple_union_all(PlannerInfo *root)
2460 {
2461 	Query	   *parse = root->parse;
2462 	SetOperationStmt *topop;
2463 	Node	   *leftmostjtnode;
2464 	int			leftmostRTI;
2465 	RangeTblEntry *leftmostRTE;
2466 	int			childRTI;
2467 	RangeTblEntry *childRTE;
2468 	RangeTblRef *rtr;
2469 
2470 	/* Shouldn't be called unless query has setops */
2471 	topop = castNode(SetOperationStmt, parse->setOperations);
2472 	Assert(topop);
2473 
2474 	/* Can't optimize away a recursive UNION */
2475 	if (root->hasRecursion)
2476 		return;
2477 
2478 	/*
2479 	 * Recursively check the tree of set operations.  If not all UNION ALL
2480 	 * with identical column types, punt.
2481 	 */
2482 	if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2483 		return;
2484 
2485 	/*
2486 	 * Locate the leftmost leaf query in the setops tree.  The upper query's
2487 	 * Vars all refer to this RTE (see transformSetOperationStmt).
2488 	 */
2489 	leftmostjtnode = topop->larg;
2490 	while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2491 		leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2492 	Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2493 	leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2494 	leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2495 	Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2496 
2497 	/*
2498 	 * Make a copy of the leftmost RTE and add it to the rtable.  This copy
2499 	 * will represent the leftmost leaf query in its capacity as a member of
2500 	 * the appendrel.  The original will represent the appendrel as a whole.
2501 	 * (We must do things this way because the upper query's Vars have to be
2502 	 * seen as referring to the whole appendrel.)
2503 	 */
2504 	childRTE = copyObject(leftmostRTE);
2505 	parse->rtable = lappend(parse->rtable, childRTE);
2506 	childRTI = list_length(parse->rtable);
2507 
2508 	/* Modify the setops tree to reference the child copy */
2509 	((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2510 
2511 	/* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2512 	leftmostRTE->inh = true;
2513 
2514 	/*
2515 	 * Form a RangeTblRef for the appendrel, and insert it into FROM.  The top
2516 	 * Query of a setops tree should have had an empty FromClause initially.
2517 	 */
2518 	rtr = makeNode(RangeTblRef);
2519 	rtr->rtindex = leftmostRTI;
2520 	Assert(parse->jointree->fromlist == NIL);
2521 	parse->jointree->fromlist = list_make1(rtr);
2522 
2523 	/*
2524 	 * Now pretend the query has no setops.  We must do this before trying to
2525 	 * do subquery pullup, because of Assert in pull_up_simple_subquery.
2526 	 */
2527 	parse->setOperations = NULL;
2528 
2529 	/*
2530 	 * Build AppendRelInfo information, and apply pull_up_subqueries to the
2531 	 * leaf queries of the UNION ALL.  (We must do that now because they
2532 	 * weren't previously referenced by the jointree, and so were missed by
2533 	 * the main invocation of pull_up_subqueries.)
2534 	 */
2535 	pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2536 }
2537 
2538 
2539 /*
2540  * reduce_outer_joins
2541  *		Attempt to reduce outer joins to plain inner joins.
2542  *
2543  * The idea here is that given a query like
2544  *		SELECT ... FROM a LEFT JOIN b ON (...) WHERE b.y = 42;
2545  * we can reduce the LEFT JOIN to a plain JOIN if the "=" operator in WHERE
2546  * is strict.  The strict operator will always return NULL, causing the outer
2547  * WHERE to fail, on any row where the LEFT JOIN filled in NULLs for b's
2548  * columns.  Therefore, there's no need for the join to produce null-extended
2549  * rows in the first place --- which makes it a plain join not an outer join.
2550  * (This scenario may not be very likely in a query written out by hand, but
2551  * it's reasonably likely when pushing quals down into complex views.)
2552  *
2553  * More generally, an outer join can be reduced in strength if there is a
2554  * strict qual above it in the qual tree that constrains a Var from the
2555  * nullable side of the join to be non-null.  (For FULL joins this applies
2556  * to each side separately.)
2557  *
2558  * Another transformation we apply here is to recognize cases like
2559  *		SELECT ... FROM a LEFT JOIN b ON (a.x = b.y) WHERE b.y IS NULL;
2560  * If the join clause is strict for b.y, then only null-extended rows could
2561  * pass the upper WHERE, and we can conclude that what the query is really
2562  * specifying is an anti-semijoin.  We change the join type from JOIN_LEFT
2563  * to JOIN_ANTI.  The IS NULL clause then becomes redundant, and must be
2564  * removed to prevent bogus selectivity calculations, but we leave it to
2565  * distribute_qual_to_rels to get rid of such clauses.
2566  *
2567  * Also, we get rid of JOIN_RIGHT cases by flipping them around to become
2568  * JOIN_LEFT.  This saves some code here and in some later planner routines,
2569  * but the main reason to do it is to not need to invent a JOIN_REVERSE_ANTI
2570  * join type.
2571  *
2572  * To ease recognition of strict qual clauses, we require this routine to be
2573  * run after expression preprocessing (i.e., qual canonicalization and JOIN
2574  * alias-var expansion).
2575  */
2576 void
reduce_outer_joins(PlannerInfo * root)2577 reduce_outer_joins(PlannerInfo *root)
2578 {
2579 	reduce_outer_joins_state *state;
2580 
2581 	/*
2582 	 * To avoid doing strictness checks on more quals than necessary, we want
2583 	 * to stop descending the jointree as soon as there are no outer joins
2584 	 * below our current point.  This consideration forces a two-pass process.
2585 	 * The first pass gathers information about which base rels appear below
2586 	 * each side of each join clause, and about whether there are outer
2587 	 * join(s) below each side of each join clause. The second pass examines
2588 	 * qual clauses and changes join types as it descends the tree.
2589 	 */
2590 	state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
2591 
2592 	/* planner.c shouldn't have called me if no outer joins */
2593 	if (state == NULL || !state->contains_outer)
2594 		elog(ERROR, "so where are the outer joins?");
2595 
2596 	reduce_outer_joins_pass2((Node *) root->parse->jointree,
2597 							 state, root, NULL, NIL, NIL);
2598 }
2599 
2600 /*
2601  * reduce_outer_joins_pass1 - phase 1 data collection
2602  *
2603  * Returns a state node describing the given jointree node.
2604  */
2605 static reduce_outer_joins_state *
reduce_outer_joins_pass1(Node * jtnode)2606 reduce_outer_joins_pass1(Node *jtnode)
2607 {
2608 	reduce_outer_joins_state *result;
2609 
2610 	result = (reduce_outer_joins_state *)
2611 		palloc(sizeof(reduce_outer_joins_state));
2612 	result->relids = NULL;
2613 	result->contains_outer = false;
2614 	result->sub_states = NIL;
2615 
2616 	if (jtnode == NULL)
2617 		return result;
2618 	if (IsA(jtnode, RangeTblRef))
2619 	{
2620 		int			varno = ((RangeTblRef *) jtnode)->rtindex;
2621 
2622 		result->relids = bms_make_singleton(varno);
2623 	}
2624 	else if (IsA(jtnode, FromExpr))
2625 	{
2626 		FromExpr   *f = (FromExpr *) jtnode;
2627 		ListCell   *l;
2628 
2629 		foreach(l, f->fromlist)
2630 		{
2631 			reduce_outer_joins_state *sub_state;
2632 
2633 			sub_state = reduce_outer_joins_pass1(lfirst(l));
2634 			result->relids = bms_add_members(result->relids,
2635 											 sub_state->relids);
2636 			result->contains_outer |= sub_state->contains_outer;
2637 			result->sub_states = lappend(result->sub_states, sub_state);
2638 		}
2639 	}
2640 	else if (IsA(jtnode, JoinExpr))
2641 	{
2642 		JoinExpr   *j = (JoinExpr *) jtnode;
2643 		reduce_outer_joins_state *sub_state;
2644 
2645 		/* join's own RT index is not wanted in result->relids */
2646 		if (IS_OUTER_JOIN(j->jointype))
2647 			result->contains_outer = true;
2648 
2649 		sub_state = reduce_outer_joins_pass1(j->larg);
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 		sub_state = reduce_outer_joins_pass1(j->rarg);
2656 		result->relids = bms_add_members(result->relids,
2657 										 sub_state->relids);
2658 		result->contains_outer |= sub_state->contains_outer;
2659 		result->sub_states = lappend(result->sub_states, sub_state);
2660 	}
2661 	else
2662 		elog(ERROR, "unrecognized node type: %d",
2663 			 (int) nodeTag(jtnode));
2664 	return result;
2665 }
2666 
2667 /*
2668  * reduce_outer_joins_pass2 - phase 2 processing
2669  *
2670  *	jtnode: current jointree node
2671  *	state: state data collected by phase 1 for this node
2672  *	root: toplevel planner state
2673  *	nonnullable_rels: set of base relids forced non-null by upper quals
2674  *	nonnullable_vars: list of Vars forced non-null by upper quals
2675  *	forced_null_vars: list of Vars forced null by upper quals
2676  */
2677 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)2678 reduce_outer_joins_pass2(Node *jtnode,
2679 						 reduce_outer_joins_state *state,
2680 						 PlannerInfo *root,
2681 						 Relids nonnullable_rels,
2682 						 List *nonnullable_vars,
2683 						 List *forced_null_vars)
2684 {
2685 	/*
2686 	 * pass 2 should never descend as far as an empty subnode or base rel,
2687 	 * because it's only called on subtrees marked as contains_outer.
2688 	 */
2689 	if (jtnode == NULL)
2690 		elog(ERROR, "reached empty jointree");
2691 	if (IsA(jtnode, RangeTblRef))
2692 		elog(ERROR, "reached base rel");
2693 	else if (IsA(jtnode, FromExpr))
2694 	{
2695 		FromExpr   *f = (FromExpr *) jtnode;
2696 		ListCell   *l;
2697 		ListCell   *s;
2698 		Relids		pass_nonnullable_rels;
2699 		List	   *pass_nonnullable_vars;
2700 		List	   *pass_forced_null_vars;
2701 
2702 		/* Scan quals to see if we can add any constraints */
2703 		pass_nonnullable_rels = find_nonnullable_rels(f->quals);
2704 		pass_nonnullable_rels = bms_add_members(pass_nonnullable_rels,
2705 												nonnullable_rels);
2706 		pass_nonnullable_vars = find_nonnullable_vars(f->quals);
2707 		pass_nonnullable_vars = list_concat(pass_nonnullable_vars,
2708 											nonnullable_vars);
2709 		pass_forced_null_vars = find_forced_null_vars(f->quals);
2710 		pass_forced_null_vars = list_concat(pass_forced_null_vars,
2711 											forced_null_vars);
2712 		/* And recurse --- but only into interesting subtrees */
2713 		Assert(list_length(f->fromlist) == list_length(state->sub_states));
2714 		forboth(l, f->fromlist, s, state->sub_states)
2715 		{
2716 			reduce_outer_joins_state *sub_state = lfirst(s);
2717 
2718 			if (sub_state->contains_outer)
2719 				reduce_outer_joins_pass2(lfirst(l), sub_state, root,
2720 										 pass_nonnullable_rels,
2721 										 pass_nonnullable_vars,
2722 										 pass_forced_null_vars);
2723 		}
2724 		bms_free(pass_nonnullable_rels);
2725 		/* can't so easily clean up var lists, unfortunately */
2726 	}
2727 	else if (IsA(jtnode, JoinExpr))
2728 	{
2729 		JoinExpr   *j = (JoinExpr *) jtnode;
2730 		int			rtindex = j->rtindex;
2731 		JoinType	jointype = j->jointype;
2732 		reduce_outer_joins_state *left_state = linitial(state->sub_states);
2733 		reduce_outer_joins_state *right_state = lsecond(state->sub_states);
2734 		List	   *local_nonnullable_vars = NIL;
2735 		bool		computed_local_nonnullable_vars = false;
2736 
2737 		/* Can we simplify this join? */
2738 		switch (jointype)
2739 		{
2740 			case JOIN_INNER:
2741 				break;
2742 			case JOIN_LEFT:
2743 				if (bms_overlap(nonnullable_rels, right_state->relids))
2744 					jointype = JOIN_INNER;
2745 				break;
2746 			case JOIN_RIGHT:
2747 				if (bms_overlap(nonnullable_rels, left_state->relids))
2748 					jointype = JOIN_INNER;
2749 				break;
2750 			case JOIN_FULL:
2751 				if (bms_overlap(nonnullable_rels, left_state->relids))
2752 				{
2753 					if (bms_overlap(nonnullable_rels, right_state->relids))
2754 						jointype = JOIN_INNER;
2755 					else
2756 						jointype = JOIN_LEFT;
2757 				}
2758 				else
2759 				{
2760 					if (bms_overlap(nonnullable_rels, right_state->relids))
2761 						jointype = JOIN_RIGHT;
2762 				}
2763 				break;
2764 			case JOIN_SEMI:
2765 			case JOIN_ANTI:
2766 
2767 				/*
2768 				 * These could only have been introduced by pull_up_sublinks,
2769 				 * so there's no way that upper quals could refer to their
2770 				 * righthand sides, and no point in checking.
2771 				 */
2772 				break;
2773 			default:
2774 				elog(ERROR, "unrecognized join type: %d",
2775 					 (int) jointype);
2776 				break;
2777 		}
2778 
2779 		/*
2780 		 * Convert JOIN_RIGHT to JOIN_LEFT.  Note that in the case where we
2781 		 * reduced JOIN_FULL to JOIN_RIGHT, this will mean the JoinExpr no
2782 		 * longer matches the internal ordering of any CoalesceExpr's built to
2783 		 * represent merged join variables.  We don't care about that at
2784 		 * present, but be wary of it ...
2785 		 */
2786 		if (jointype == JOIN_RIGHT)
2787 		{
2788 			Node	   *tmparg;
2789 
2790 			tmparg = j->larg;
2791 			j->larg = j->rarg;
2792 			j->rarg = tmparg;
2793 			jointype = JOIN_LEFT;
2794 			right_state = linitial(state->sub_states);
2795 			left_state = lsecond(state->sub_states);
2796 		}
2797 
2798 		/*
2799 		 * See if we can reduce JOIN_LEFT to JOIN_ANTI.  This is the case if
2800 		 * the join's own quals are strict for any var that was forced null by
2801 		 * higher qual levels.  NOTE: there are other ways that we could
2802 		 * detect an anti-join, in particular if we were to check whether Vars
2803 		 * coming from the RHS must be non-null because of table constraints.
2804 		 * That seems complicated and expensive though (in particular, one
2805 		 * would have to be wary of lower outer joins). For the moment this
2806 		 * seems sufficient.
2807 		 */
2808 		if (jointype == JOIN_LEFT)
2809 		{
2810 			List	   *overlap;
2811 
2812 			local_nonnullable_vars = find_nonnullable_vars(j->quals);
2813 			computed_local_nonnullable_vars = true;
2814 
2815 			/*
2816 			 * It's not sufficient to check whether local_nonnullable_vars and
2817 			 * forced_null_vars overlap: we need to know if the overlap
2818 			 * includes any RHS variables.
2819 			 */
2820 			overlap = list_intersection(local_nonnullable_vars,
2821 										forced_null_vars);
2822 			if (overlap != NIL &&
2823 				bms_overlap(pull_varnos(root, (Node *) overlap),
2824 							right_state->relids))
2825 				jointype = JOIN_ANTI;
2826 		}
2827 
2828 		/* Apply the jointype change, if any, to both jointree node and RTE */
2829 		if (rtindex && jointype != j->jointype)
2830 		{
2831 			RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
2832 
2833 			Assert(rte->rtekind == RTE_JOIN);
2834 			Assert(rte->jointype == j->jointype);
2835 			rte->jointype = jointype;
2836 		}
2837 		j->jointype = jointype;
2838 
2839 		/* Only recurse if there's more to do below here */
2840 		if (left_state->contains_outer || right_state->contains_outer)
2841 		{
2842 			Relids		local_nonnullable_rels;
2843 			List	   *local_forced_null_vars;
2844 			Relids		pass_nonnullable_rels;
2845 			List	   *pass_nonnullable_vars;
2846 			List	   *pass_forced_null_vars;
2847 
2848 			/*
2849 			 * If this join is (now) inner, we can add any constraints its
2850 			 * quals provide to those we got from above.  But if it is outer,
2851 			 * we can pass down the local constraints only into the nullable
2852 			 * side, because an outer join never eliminates any rows from its
2853 			 * non-nullable side.  Also, there is no point in passing upper
2854 			 * constraints into the nullable side, since if there were any
2855 			 * we'd have been able to reduce the join.  (In the case of upper
2856 			 * forced-null constraints, we *must not* pass them into the
2857 			 * nullable side --- they either applied here, or not.) The upshot
2858 			 * is that we pass either the local or the upper constraints,
2859 			 * never both, to the children of an outer join.
2860 			 *
2861 			 * Note that a SEMI join works like an inner join here: it's okay
2862 			 * to pass down both local and upper constraints.  (There can't be
2863 			 * any upper constraints affecting its inner side, but it's not
2864 			 * worth having a separate code path to avoid passing them.)
2865 			 *
2866 			 * At a FULL join we just punt and pass nothing down --- is it
2867 			 * possible to be smarter?
2868 			 */
2869 			if (jointype != JOIN_FULL)
2870 			{
2871 				local_nonnullable_rels = find_nonnullable_rels(j->quals);
2872 				if (!computed_local_nonnullable_vars)
2873 					local_nonnullable_vars = find_nonnullable_vars(j->quals);
2874 				local_forced_null_vars = find_forced_null_vars(j->quals);
2875 				if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
2876 				{
2877 					/* OK to merge upper and local constraints */
2878 					local_nonnullable_rels = bms_add_members(local_nonnullable_rels,
2879 															 nonnullable_rels);
2880 					local_nonnullable_vars = list_concat(local_nonnullable_vars,
2881 														 nonnullable_vars);
2882 					local_forced_null_vars = list_concat(local_forced_null_vars,
2883 														 forced_null_vars);
2884 				}
2885 			}
2886 			else
2887 			{
2888 				/* no use in calculating these */
2889 				local_nonnullable_rels = NULL;
2890 				local_forced_null_vars = NIL;
2891 			}
2892 
2893 			if (left_state->contains_outer)
2894 			{
2895 				if (jointype == JOIN_INNER || jointype == JOIN_SEMI)
2896 				{
2897 					/* pass union of local and upper constraints */
2898 					pass_nonnullable_rels = local_nonnullable_rels;
2899 					pass_nonnullable_vars = local_nonnullable_vars;
2900 					pass_forced_null_vars = local_forced_null_vars;
2901 				}
2902 				else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
2903 				{
2904 					/* can't pass local constraints to non-nullable side */
2905 					pass_nonnullable_rels = nonnullable_rels;
2906 					pass_nonnullable_vars = nonnullable_vars;
2907 					pass_forced_null_vars = forced_null_vars;
2908 				}
2909 				else
2910 				{
2911 					/* no constraints pass through JOIN_FULL */
2912 					pass_nonnullable_rels = NULL;
2913 					pass_nonnullable_vars = NIL;
2914 					pass_forced_null_vars = NIL;
2915 				}
2916 				reduce_outer_joins_pass2(j->larg, left_state, root,
2917 										 pass_nonnullable_rels,
2918 										 pass_nonnullable_vars,
2919 										 pass_forced_null_vars);
2920 			}
2921 
2922 			if (right_state->contains_outer)
2923 			{
2924 				if (jointype != JOIN_FULL)	/* ie, INNER/LEFT/SEMI/ANTI */
2925 				{
2926 					/* pass appropriate constraints, per comment above */
2927 					pass_nonnullable_rels = local_nonnullable_rels;
2928 					pass_nonnullable_vars = local_nonnullable_vars;
2929 					pass_forced_null_vars = local_forced_null_vars;
2930 				}
2931 				else
2932 				{
2933 					/* no constraints pass through JOIN_FULL */
2934 					pass_nonnullable_rels = NULL;
2935 					pass_nonnullable_vars = NIL;
2936 					pass_forced_null_vars = NIL;
2937 				}
2938 				reduce_outer_joins_pass2(j->rarg, right_state, root,
2939 										 pass_nonnullable_rels,
2940 										 pass_nonnullable_vars,
2941 										 pass_forced_null_vars);
2942 			}
2943 			bms_free(local_nonnullable_rels);
2944 		}
2945 	}
2946 	else
2947 		elog(ERROR, "unrecognized node type: %d",
2948 			 (int) nodeTag(jtnode));
2949 }
2950 
2951 
2952 /*
2953  * remove_useless_result_rtes
2954  *		Attempt to remove RTE_RESULT RTEs from the join tree.
2955  *
2956  * We can remove RTE_RESULT entries from the join tree using the knowledge
2957  * that RTE_RESULT returns exactly one row and has no output columns.  Hence,
2958  * if one is inner-joined to anything else, we can delete it.  Optimizations
2959  * are also possible for some outer-join cases, as detailed below.
2960  *
2961  * Some of these optimizations depend on recognizing empty (constant-true)
2962  * quals for FromExprs and JoinExprs.  That makes it useful to apply this
2963  * optimization pass after expression preprocessing, since that will have
2964  * eliminated constant-true quals, allowing more cases to be recognized as
2965  * optimizable.  What's more, the usual reason for an RTE_RESULT to be present
2966  * is that we pulled up a subquery or VALUES clause, thus very possibly
2967  * replacing Vars with constants, making it more likely that a qual can be
2968  * reduced to constant true.  Also, because some optimizations depend on
2969  * the outer-join type, it's best to have done reduce_outer_joins() first.
2970  *
2971  * A PlaceHolderVar referencing an RTE_RESULT RTE poses an obstacle to this
2972  * process: we must remove the RTE_RESULT's relid from the PHV's phrels, but
2973  * we must not reduce the phrels set to empty.  If that would happen, and
2974  * the RTE_RESULT is an immediate child of an outer join, we have to give up
2975  * and not remove the RTE_RESULT: there is noplace else to evaluate the
2976  * PlaceHolderVar.  (That is, in such cases the RTE_RESULT *does* have output
2977  * columns.)  But if the RTE_RESULT is an immediate child of an inner join,
2978  * we can usually change the PlaceHolderVar's phrels so as to evaluate it at
2979  * the inner join instead.  This is OK because we really only care that PHVs
2980  * are evaluated above or below the correct outer joins.  We can't, however,
2981  * postpone the evaluation of a PHV to above where it is used; so there are
2982  * some checks below on whether output PHVs are laterally referenced in the
2983  * other join input rel(s).
2984  *
2985  * We used to try to do this work as part of pull_up_subqueries() where the
2986  * potentially-optimizable cases get introduced; but it's way simpler, and
2987  * more effective, to do it separately.
2988  */
2989 void
remove_useless_result_rtes(PlannerInfo * root)2990 remove_useless_result_rtes(PlannerInfo *root)
2991 {
2992 	ListCell   *cell;
2993 
2994 	/* Top level of jointree must always be a FromExpr */
2995 	Assert(IsA(root->parse->jointree, FromExpr));
2996 	/* Recurse ... */
2997 	root->parse->jointree = (FromExpr *)
2998 		remove_useless_results_recurse(root, (Node *) root->parse->jointree);
2999 	/* We should still have a FromExpr */
3000 	Assert(IsA(root->parse->jointree, FromExpr));
3001 
3002 	/*
3003 	 * Remove any PlanRowMark referencing an RTE_RESULT RTE.  We obviously
3004 	 * must do that for any RTE_RESULT that we just removed.  But one for a
3005 	 * RTE that we did not remove can be dropped anyway: since the RTE has
3006 	 * only one possible output row, there is no need for EPQ to mark and
3007 	 * restore that row.
3008 	 *
3009 	 * It's necessary, not optional, to remove the PlanRowMark for a surviving
3010 	 * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
3011 	 * RTE_RESULT, which the executor has no support for.
3012 	 */
3013 	foreach(cell, root->rowMarks)
3014 	{
3015 		PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3016 
3017 		if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
3018 			root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3019 	}
3020 }
3021 
3022 /*
3023  * remove_useless_results_recurse
3024  *		Recursive guts of remove_useless_result_rtes.
3025  *
3026  * This recursively processes the jointree and returns a modified jointree.
3027  */
3028 static Node *
remove_useless_results_recurse(PlannerInfo * root,Node * jtnode)3029 remove_useless_results_recurse(PlannerInfo *root, Node *jtnode)
3030 {
3031 	Assert(jtnode != NULL);
3032 	if (IsA(jtnode, RangeTblRef))
3033 	{
3034 		/* Can't immediately do anything with a RangeTblRef */
3035 	}
3036 	else if (IsA(jtnode, FromExpr))
3037 	{
3038 		FromExpr   *f = (FromExpr *) jtnode;
3039 		Relids		result_relids = NULL;
3040 		ListCell   *cell;
3041 
3042 		/*
3043 		 * We can drop RTE_RESULT rels from the fromlist so long as at least
3044 		 * one child remains, since joining to a one-row table changes
3045 		 * nothing.  (But we can't drop a RTE_RESULT that computes PHV(s) that
3046 		 * are needed by some sibling.  The cleanup transformation below would
3047 		 * reassign the PHVs to be computed at the join, which is too late for
3048 		 * the sibling's use.)  The easiest way to mechanize this rule is to
3049 		 * modify the list in-place.
3050 		 */
3051 		foreach(cell, f->fromlist)
3052 		{
3053 			Node	   *child = (Node *) lfirst(cell);
3054 			int			varno;
3055 
3056 			/* Recursively transform child ... */
3057 			child = remove_useless_results_recurse(root, child);
3058 			/* ... and stick it back into the tree */
3059 			lfirst(cell) = child;
3060 
3061 			/*
3062 			 * If it's an RTE_RESULT with at least one sibling, and no sibling
3063 			 * references dependent PHVs, we can drop it.  We don't yet know
3064 			 * what the inner join's final relid set will be, so postpone
3065 			 * cleanup of PHVs etc till after this loop.
3066 			 */
3067 			if (list_length(f->fromlist) > 1 &&
3068 				(varno = get_result_relid(root, child)) != 0 &&
3069 				!find_dependent_phvs_in_jointree(root, (Node *) f, varno))
3070 			{
3071 				f->fromlist = foreach_delete_current(f->fromlist, cell);
3072 				result_relids = bms_add_member(result_relids, varno);
3073 			}
3074 		}
3075 
3076 		/*
3077 		 * Clean up if we dropped any RTE_RESULT RTEs.  This is a bit
3078 		 * inefficient if there's more than one, but it seems better to
3079 		 * optimize the support code for the single-relid case.
3080 		 */
3081 		if (result_relids)
3082 		{
3083 			int			varno = -1;
3084 
3085 			while ((varno = bms_next_member(result_relids, varno)) >= 0)
3086 				remove_result_refs(root, varno, (Node *) f);
3087 		}
3088 
3089 		/*
3090 		 * If we're not at the top of the jointree, it's valid to simplify a
3091 		 * degenerate FromExpr into its single child.  (At the top, we must
3092 		 * keep the FromExpr since Query.jointree is required to point to a
3093 		 * FromExpr.)
3094 		 */
3095 		if (f != root->parse->jointree &&
3096 			f->quals == NULL &&
3097 			list_length(f->fromlist) == 1)
3098 			return (Node *) linitial(f->fromlist);
3099 	}
3100 	else if (IsA(jtnode, JoinExpr))
3101 	{
3102 		JoinExpr   *j = (JoinExpr *) jtnode;
3103 		int			varno;
3104 
3105 		/* First, recurse */
3106 		j->larg = remove_useless_results_recurse(root, j->larg);
3107 		j->rarg = remove_useless_results_recurse(root, j->rarg);
3108 
3109 		/* Apply join-type-specific optimization rules */
3110 		switch (j->jointype)
3111 		{
3112 			case JOIN_INNER:
3113 
3114 				/*
3115 				 * An inner join is equivalent to a FromExpr, so if either
3116 				 * side was simplified to an RTE_RESULT rel, we can replace
3117 				 * the join with a FromExpr with just the other side; and if
3118 				 * the qual is empty (JOIN ON TRUE) then we can omit the
3119 				 * FromExpr as well.
3120 				 *
3121 				 * Just as in the FromExpr case, we can't simplify if the
3122 				 * other input rel references any PHVs that are marked as to
3123 				 * be evaluated at the RTE_RESULT rel, because we can't
3124 				 * postpone their evaluation in that case.  But we only have
3125 				 * to check this in cases where it's syntactically legal for
3126 				 * the other input to have a LATERAL reference to the
3127 				 * RTE_RESULT rel.  Only RHSes of inner and left joins are
3128 				 * allowed to have such refs.
3129 				 */
3130 				if ((varno = get_result_relid(root, j->larg)) != 0 &&
3131 					!find_dependent_phvs_in_jointree(root, j->rarg, varno))
3132 				{
3133 					remove_result_refs(root, varno, j->rarg);
3134 					if (j->quals)
3135 						jtnode = (Node *)
3136 							makeFromExpr(list_make1(j->rarg), j->quals);
3137 					else
3138 						jtnode = j->rarg;
3139 				}
3140 				else if ((varno = get_result_relid(root, j->rarg)) != 0)
3141 				{
3142 					remove_result_refs(root, varno, j->larg);
3143 					if (j->quals)
3144 						jtnode = (Node *)
3145 							makeFromExpr(list_make1(j->larg), j->quals);
3146 					else
3147 						jtnode = j->larg;
3148 				}
3149 				break;
3150 			case JOIN_LEFT:
3151 
3152 				/*
3153 				 * We can simplify this case if the RHS is an RTE_RESULT, with
3154 				 * two different possibilities:
3155 				 *
3156 				 * If the qual is empty (JOIN ON TRUE), then the join can be
3157 				 * strength-reduced to a plain inner join, since each LHS row
3158 				 * necessarily has exactly one join partner.  So we can always
3159 				 * discard the RHS, much as in the JOIN_INNER case above.
3160 				 * (Again, the LHS could not contain a lateral reference to
3161 				 * the RHS.)
3162 				 *
3163 				 * Otherwise, it's still true that each LHS row should be
3164 				 * returned exactly once, and since the RHS returns no columns
3165 				 * (unless there are PHVs that have to be evaluated there), we
3166 				 * don't much care if it's null-extended or not.  So in this
3167 				 * case also, we can just ignore the qual and discard the left
3168 				 * join.
3169 				 */
3170 				if ((varno = get_result_relid(root, j->rarg)) != 0 &&
3171 					(j->quals == NULL ||
3172 					 !find_dependent_phvs(root, varno)))
3173 				{
3174 					remove_result_refs(root, varno, j->larg);
3175 					jtnode = j->larg;
3176 				}
3177 				break;
3178 			case JOIN_RIGHT:
3179 				/* Mirror-image of the JOIN_LEFT case */
3180 				if ((varno = get_result_relid(root, j->larg)) != 0 &&
3181 					(j->quals == NULL ||
3182 					 !find_dependent_phvs(root, varno)))
3183 				{
3184 					remove_result_refs(root, varno, j->rarg);
3185 					jtnode = j->rarg;
3186 				}
3187 				break;
3188 			case JOIN_SEMI:
3189 
3190 				/*
3191 				 * We may simplify this case if the RHS is an RTE_RESULT; the
3192 				 * join qual becomes effectively just a filter qual for the
3193 				 * LHS, since we should either return the LHS row or not.  For
3194 				 * simplicity we inject the filter qual into a new FromExpr.
3195 				 *
3196 				 * Unlike the LEFT/RIGHT cases, we just Assert that there are
3197 				 * no PHVs that need to be evaluated at the semijoin's RHS,
3198 				 * since the rest of the query couldn't reference any outputs
3199 				 * of the semijoin's RHS.
3200 				 */
3201 				if ((varno = get_result_relid(root, j->rarg)) != 0)
3202 				{
3203 					Assert(!find_dependent_phvs(root, varno));
3204 					remove_result_refs(root, varno, j->larg);
3205 					if (j->quals)
3206 						jtnode = (Node *)
3207 							makeFromExpr(list_make1(j->larg), j->quals);
3208 					else
3209 						jtnode = j->larg;
3210 				}
3211 				break;
3212 			case JOIN_FULL:
3213 			case JOIN_ANTI:
3214 				/* We have no special smarts for these cases */
3215 				break;
3216 			default:
3217 				elog(ERROR, "unrecognized join type: %d",
3218 					 (int) j->jointype);
3219 				break;
3220 		}
3221 	}
3222 	else
3223 		elog(ERROR, "unrecognized node type: %d",
3224 			 (int) nodeTag(jtnode));
3225 	return jtnode;
3226 }
3227 
3228 /*
3229  * get_result_relid
3230  *		If jtnode is a RangeTblRef for an RTE_RESULT RTE, return its relid;
3231  *		otherwise return 0.
3232  */
3233 static int
get_result_relid(PlannerInfo * root,Node * jtnode)3234 get_result_relid(PlannerInfo *root, Node *jtnode)
3235 {
3236 	int			varno;
3237 
3238 	if (!IsA(jtnode, RangeTblRef))
3239 		return 0;
3240 	varno = ((RangeTblRef *) jtnode)->rtindex;
3241 	if (rt_fetch(varno, root->parse->rtable)->rtekind != RTE_RESULT)
3242 		return 0;
3243 	return varno;
3244 }
3245 
3246 /*
3247  * remove_result_refs
3248  *		Helper routine for dropping an unneeded RTE_RESULT RTE.
3249  *
3250  * This doesn't physically remove the RTE from the jointree, because that's
3251  * more easily handled in remove_useless_results_recurse.  What it does do
3252  * is the necessary cleanup in the rest of the tree: we must adjust any PHVs
3253  * that may reference the RTE.  Be sure to call this at a point where the
3254  * jointree is valid (no disconnected nodes).
3255  *
3256  * Note that we don't need to process the append_rel_list, since RTEs
3257  * referenced directly in the jointree won't be appendrel members.
3258  *
3259  * varno is the RTE_RESULT's relid.
3260  * newjtloc is the jointree location at which any PHVs referencing the
3261  * RTE_RESULT should be evaluated instead.
3262  */
3263 static void
remove_result_refs(PlannerInfo * root,int varno,Node * newjtloc)3264 remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
3265 {
3266 	/* Fix up PlaceHolderVars as needed */
3267 	/* If there are no PHVs anywhere, we can skip this bit */
3268 	if (root->glob->lastPHId != 0)
3269 	{
3270 		Relids		subrelids;
3271 
3272 		subrelids = get_relids_in_jointree(newjtloc, false);
3273 		Assert(!bms_is_empty(subrelids));
3274 		substitute_phv_relids((Node *) root->parse, varno, subrelids);
3275 		fix_append_rel_relids(root->append_rel_list, varno, subrelids);
3276 	}
3277 
3278 	/*
3279 	 * We also need to remove any PlanRowMark referencing the RTE, but we
3280 	 * postpone that work until we return to remove_useless_result_rtes.
3281 	 */
3282 }
3283 
3284 
3285 /*
3286  * find_dependent_phvs - are there any PlaceHolderVars whose relids are
3287  * exactly the given varno?
3288  *
3289  * find_dependent_phvs should be used when we want to see if there are
3290  * any such PHVs anywhere in the Query.  Another use-case is to see if
3291  * a subtree of the join tree contains such PHVs; but for that, we have
3292  * to look not only at the join tree nodes themselves but at the
3293  * referenced RTEs.  For that, use find_dependent_phvs_in_jointree.
3294  */
3295 
3296 typedef struct
3297 {
3298 	Relids		relids;
3299 	int			sublevels_up;
3300 } find_dependent_phvs_context;
3301 
3302 static bool
find_dependent_phvs_walker(Node * node,find_dependent_phvs_context * context)3303 find_dependent_phvs_walker(Node *node,
3304 						   find_dependent_phvs_context *context)
3305 {
3306 	if (node == NULL)
3307 		return false;
3308 	if (IsA(node, PlaceHolderVar))
3309 	{
3310 		PlaceHolderVar *phv = (PlaceHolderVar *) node;
3311 
3312 		if (phv->phlevelsup == context->sublevels_up &&
3313 			bms_equal(context->relids, phv->phrels))
3314 			return true;
3315 		/* fall through to examine children */
3316 	}
3317 	if (IsA(node, Query))
3318 	{
3319 		/* Recurse into subselects */
3320 		bool		result;
3321 
3322 		context->sublevels_up++;
3323 		result = query_tree_walker((Query *) node,
3324 								   find_dependent_phvs_walker,
3325 								   (void *) context, 0);
3326 		context->sublevels_up--;
3327 		return result;
3328 	}
3329 	/* Shouldn't need to handle planner auxiliary nodes here */
3330 	Assert(!IsA(node, SpecialJoinInfo));
3331 	Assert(!IsA(node, AppendRelInfo));
3332 	Assert(!IsA(node, PlaceHolderInfo));
3333 	Assert(!IsA(node, MinMaxAggInfo));
3334 
3335 	return expression_tree_walker(node, find_dependent_phvs_walker,
3336 								  (void *) context);
3337 }
3338 
3339 static bool
find_dependent_phvs(PlannerInfo * root,int varno)3340 find_dependent_phvs(PlannerInfo *root, int varno)
3341 {
3342 	find_dependent_phvs_context context;
3343 
3344 	/* If there are no PHVs anywhere, we needn't work hard */
3345 	if (root->glob->lastPHId == 0)
3346 		return false;
3347 
3348 	context.relids = bms_make_singleton(varno);
3349 	context.sublevels_up = 0;
3350 
3351 	return query_tree_walker(root->parse,
3352 							 find_dependent_phvs_walker,
3353 							 (void *) &context,
3354 							 0);
3355 }
3356 
3357 static bool
find_dependent_phvs_in_jointree(PlannerInfo * root,Node * node,int varno)3358 find_dependent_phvs_in_jointree(PlannerInfo *root, Node *node, int varno)
3359 {
3360 	find_dependent_phvs_context context;
3361 	Relids		subrelids;
3362 	int			relid;
3363 
3364 	/* If there are no PHVs anywhere, we needn't work hard */
3365 	if (root->glob->lastPHId == 0)
3366 		return false;
3367 
3368 	context.relids = bms_make_singleton(varno);
3369 	context.sublevels_up = 0;
3370 
3371 	/*
3372 	 * See if the jointree fragment itself contains references (in join quals)
3373 	 */
3374 	if (find_dependent_phvs_walker(node, &context))
3375 		return true;
3376 
3377 	/*
3378 	 * Otherwise, identify the set of referenced RTEs (we can ignore joins,
3379 	 * since they should be flattened already, so their join alias lists no
3380 	 * longer matter), and tediously check each RTE.  We can ignore RTEs that
3381 	 * are not marked LATERAL, though, since they couldn't possibly contain
3382 	 * any cross-references to other RTEs.
3383 	 */
3384 	subrelids = get_relids_in_jointree(node, false);
3385 	relid = -1;
3386 	while ((relid = bms_next_member(subrelids, relid)) >= 0)
3387 	{
3388 		RangeTblEntry *rte = rt_fetch(relid, root->parse->rtable);
3389 
3390 		if (rte->lateral &&
3391 			range_table_entry_walker(rte,
3392 									 find_dependent_phvs_walker,
3393 									 (void *) &context,
3394 									 0))
3395 			return true;
3396 	}
3397 
3398 	return false;
3399 }
3400 
3401 /*
3402  * substitute_phv_relids - adjust PlaceHolderVar relid sets after pulling up
3403  * a subquery or removing an RTE_RESULT jointree item
3404  *
3405  * Find any PlaceHolderVar nodes in the given tree that reference the
3406  * pulled-up relid, and change them to reference the replacement relid(s).
3407  *
3408  * NOTE: although this has the form of a walker, we cheat and modify the
3409  * nodes in-place.  This should be OK since the tree was copied by
3410  * pullup_replace_vars earlier.  Avoid scribbling on the original values of
3411  * the bitmapsets, though, because expression_tree_mutator doesn't copy those.
3412  */
3413 
3414 typedef struct
3415 {
3416 	int			varno;
3417 	int			sublevels_up;
3418 	Relids		subrelids;
3419 } substitute_phv_relids_context;
3420 
3421 static bool
substitute_phv_relids_walker(Node * node,substitute_phv_relids_context * context)3422 substitute_phv_relids_walker(Node *node,
3423 							 substitute_phv_relids_context *context)
3424 {
3425 	if (node == NULL)
3426 		return false;
3427 	if (IsA(node, PlaceHolderVar))
3428 	{
3429 		PlaceHolderVar *phv = (PlaceHolderVar *) node;
3430 
3431 		if (phv->phlevelsup == context->sublevels_up &&
3432 			bms_is_member(context->varno, phv->phrels))
3433 		{
3434 			phv->phrels = bms_union(phv->phrels,
3435 									context->subrelids);
3436 			phv->phrels = bms_del_member(phv->phrels,
3437 										 context->varno);
3438 			/* Assert we haven't broken the PHV */
3439 			Assert(!bms_is_empty(phv->phrels));
3440 		}
3441 		/* fall through to examine children */
3442 	}
3443 	if (IsA(node, Query))
3444 	{
3445 		/* Recurse into subselects */
3446 		bool		result;
3447 
3448 		context->sublevels_up++;
3449 		result = query_tree_walker((Query *) node,
3450 								   substitute_phv_relids_walker,
3451 								   (void *) context, 0);
3452 		context->sublevels_up--;
3453 		return result;
3454 	}
3455 	/* Shouldn't need to handle planner auxiliary nodes here */
3456 	Assert(!IsA(node, SpecialJoinInfo));
3457 	Assert(!IsA(node, AppendRelInfo));
3458 	Assert(!IsA(node, PlaceHolderInfo));
3459 	Assert(!IsA(node, MinMaxAggInfo));
3460 
3461 	return expression_tree_walker(node, substitute_phv_relids_walker,
3462 								  (void *) context);
3463 }
3464 
3465 static void
substitute_phv_relids(Node * node,int varno,Relids subrelids)3466 substitute_phv_relids(Node *node, int varno, Relids subrelids)
3467 {
3468 	substitute_phv_relids_context context;
3469 
3470 	context.varno = varno;
3471 	context.sublevels_up = 0;
3472 	context.subrelids = subrelids;
3473 
3474 	/*
3475 	 * Must be prepared to start with a Query or a bare expression tree.
3476 	 */
3477 	query_or_expression_tree_walker(node,
3478 									substitute_phv_relids_walker,
3479 									(void *) &context,
3480 									0);
3481 }
3482 
3483 /*
3484  * fix_append_rel_relids: update RT-index fields of AppendRelInfo nodes
3485  *
3486  * When we pull up a subquery, any AppendRelInfo references to the subquery's
3487  * RT index have to be replaced by the substituted relid (and there had better
3488  * be only one).  We also need to apply substitute_phv_relids to their
3489  * translated_vars lists, since those might contain PlaceHolderVars.
3490  *
3491  * We assume we may modify the AppendRelInfo nodes in-place.
3492  */
3493 static void
fix_append_rel_relids(List * append_rel_list,int varno,Relids subrelids)3494 fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
3495 {
3496 	ListCell   *l;
3497 	int			subvarno = -1;
3498 
3499 	/*
3500 	 * We only want to extract the member relid once, but we mustn't fail
3501 	 * immediately if there are multiple members; it could be that none of the
3502 	 * AppendRelInfo nodes refer to it.  So compute it on first use. Note that
3503 	 * bms_singleton_member will complain if set is not singleton.
3504 	 */
3505 	foreach(l, append_rel_list)
3506 	{
3507 		AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
3508 
3509 		/* The parent_relid shouldn't ever be a pullup target */
3510 		Assert(appinfo->parent_relid != varno);
3511 
3512 		if (appinfo->child_relid == varno)
3513 		{
3514 			if (subvarno < 0)
3515 				subvarno = bms_singleton_member(subrelids);
3516 			appinfo->child_relid = subvarno;
3517 		}
3518 
3519 		/* Also fix up any PHVs in its translated vars */
3520 		substitute_phv_relids((Node *) appinfo->translated_vars,
3521 							  varno, subrelids);
3522 	}
3523 }
3524 
3525 /*
3526  * get_relids_in_jointree: get set of RT indexes present in a jointree
3527  *
3528  * If include_joins is true, join RT indexes are included; if false,
3529  * only base rels are included.
3530  */
3531 Relids
get_relids_in_jointree(Node * jtnode,bool include_joins)3532 get_relids_in_jointree(Node *jtnode, bool include_joins)
3533 {
3534 	Relids		result = NULL;
3535 
3536 	if (jtnode == NULL)
3537 		return result;
3538 	if (IsA(jtnode, RangeTblRef))
3539 	{
3540 		int			varno = ((RangeTblRef *) jtnode)->rtindex;
3541 
3542 		result = bms_make_singleton(varno);
3543 	}
3544 	else if (IsA(jtnode, FromExpr))
3545 	{
3546 		FromExpr   *f = (FromExpr *) jtnode;
3547 		ListCell   *l;
3548 
3549 		foreach(l, f->fromlist)
3550 		{
3551 			result = bms_join(result,
3552 							  get_relids_in_jointree(lfirst(l),
3553 													 include_joins));
3554 		}
3555 	}
3556 	else if (IsA(jtnode, JoinExpr))
3557 	{
3558 		JoinExpr   *j = (JoinExpr *) jtnode;
3559 
3560 		result = get_relids_in_jointree(j->larg, include_joins);
3561 		result = bms_join(result,
3562 						  get_relids_in_jointree(j->rarg, include_joins));
3563 		if (include_joins && j->rtindex)
3564 			result = bms_add_member(result, j->rtindex);
3565 	}
3566 	else
3567 		elog(ERROR, "unrecognized node type: %d",
3568 			 (int) nodeTag(jtnode));
3569 	return result;
3570 }
3571 
3572 /*
3573  * get_relids_for_join: get set of base RT indexes making up a join
3574  */
3575 Relids
get_relids_for_join(Query * query,int joinrelid)3576 get_relids_for_join(Query *query, int joinrelid)
3577 {
3578 	Node	   *jtnode;
3579 
3580 	jtnode = find_jointree_node_for_rel((Node *) query->jointree,
3581 										joinrelid);
3582 	if (!jtnode)
3583 		elog(ERROR, "could not find join node %d", joinrelid);
3584 	return get_relids_in_jointree(jtnode, false);
3585 }
3586 
3587 /*
3588  * find_jointree_node_for_rel: locate jointree node for a base or join RT index
3589  *
3590  * Returns NULL if not found
3591  */
3592 static Node *
find_jointree_node_for_rel(Node * jtnode,int relid)3593 find_jointree_node_for_rel(Node *jtnode, int relid)
3594 {
3595 	if (jtnode == NULL)
3596 		return NULL;
3597 	if (IsA(jtnode, RangeTblRef))
3598 	{
3599 		int			varno = ((RangeTblRef *) jtnode)->rtindex;
3600 
3601 		if (relid == varno)
3602 			return jtnode;
3603 	}
3604 	else if (IsA(jtnode, FromExpr))
3605 	{
3606 		FromExpr   *f = (FromExpr *) jtnode;
3607 		ListCell   *l;
3608 
3609 		foreach(l, f->fromlist)
3610 		{
3611 			jtnode = find_jointree_node_for_rel(lfirst(l), relid);
3612 			if (jtnode)
3613 				return jtnode;
3614 		}
3615 	}
3616 	else if (IsA(jtnode, JoinExpr))
3617 	{
3618 		JoinExpr   *j = (JoinExpr *) jtnode;
3619 
3620 		if (relid == j->rtindex)
3621 			return jtnode;
3622 		jtnode = find_jointree_node_for_rel(j->larg, relid);
3623 		if (jtnode)
3624 			return jtnode;
3625 		jtnode = find_jointree_node_for_rel(j->rarg, relid);
3626 		if (jtnode)
3627 			return jtnode;
3628 	}
3629 	else
3630 		elog(ERROR, "unrecognized node type: %d",
3631 			 (int) nodeTag(jtnode));
3632 	return NULL;
3633 }
3634