1 /*-------------------------------------------------------------------------
2  *
3  * prepunion.c
4  *	  Routines to plan set-operation queries.  The filename is a leftover
5  *	  from a time when only UNIONs were implemented.
6  *
7  * There are two code paths in the planner for set-operation queries.
8  * If a subquery consists entirely of simple UNION ALL operations, it
9  * is converted into an "append relation".  Otherwise, it is handled
10  * by the general code in this module (plan_set_operations and its
11  * subroutines).  There is some support code here for the append-relation
12  * case, but most of the heavy lifting for that is done elsewhere,
13  * notably in prepjointree.c and allpaths.c.
14  *
15  * There is also some code here to support planning of queries that use
16  * inheritance (SELECT FROM foo*).  Inheritance trees are converted into
17  * append relations, and thenceforth share code with the UNION ALL case.
18  *
19  *
20  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
21  * Portions Copyright (c) 1994, Regents of the University of California
22  *
23  *
24  * IDENTIFICATION
25  *	  src/backend/optimizer/prep/prepunion.c
26  *
27  *-------------------------------------------------------------------------
28  */
29 #include "postgres.h"
30 
31 #include <limits.h>
32 
33 #include "access/heapam.h"
34 #include "access/htup_details.h"
35 #include "access/sysattr.h"
36 #include "catalog/pg_inherits_fn.h"
37 #include "catalog/pg_type.h"
38 #include "miscadmin.h"
39 #include "nodes/makefuncs.h"
40 #include "nodes/nodeFuncs.h"
41 #include "optimizer/cost.h"
42 #include "optimizer/pathnode.h"
43 #include "optimizer/paths.h"
44 #include "optimizer/planmain.h"
45 #include "optimizer/planner.h"
46 #include "optimizer/prep.h"
47 #include "optimizer/tlist.h"
48 #include "parser/parse_coerce.h"
49 #include "parser/parsetree.h"
50 #include "utils/lsyscache.h"
51 #include "utils/rel.h"
52 #include "utils/selfuncs.h"
53 
54 
55 typedef struct
56 {
57 	PlannerInfo *root;
58 	AppendRelInfo *appinfo;
59 	int			sublevels_up;
60 } adjust_appendrel_attrs_context;
61 
62 static Path *recurse_set_operations(Node *setOp, PlannerInfo *root,
63 					   List *colTypes, List *colCollations,
64 					   bool junkOK,
65 					   int flag, List *refnames_tlist,
66 					   List **pTargetList,
67 					   double *pNumGroups);
68 static Path *generate_recursion_path(SetOperationStmt *setOp,
69 						PlannerInfo *root,
70 						List *refnames_tlist,
71 						List **pTargetList);
72 static Path *generate_union_path(SetOperationStmt *op, PlannerInfo *root,
73 					List *refnames_tlist,
74 					List **pTargetList,
75 					double *pNumGroups);
76 static Path *generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
77 					   List *refnames_tlist,
78 					   List **pTargetList,
79 					   double *pNumGroups);
80 static List *recurse_union_children(Node *setOp, PlannerInfo *root,
81 					   SetOperationStmt *top_union,
82 					   List *refnames_tlist,
83 					   List **tlist_list);
84 static Path *make_union_unique(SetOperationStmt *op, Path *path, List *tlist,
85 				  PlannerInfo *root);
86 static bool choose_hashed_setop(PlannerInfo *root, List *groupClauses,
87 					Path *input_path,
88 					double dNumGroups, double dNumOutputRows,
89 					const char *construct);
90 static List *generate_setop_tlist(List *colTypes, List *colCollations,
91 					 int flag,
92 					 Index varno,
93 					 bool hack_constants,
94 					 List *input_tlist,
95 					 List *refnames_tlist);
96 static List *generate_append_tlist(List *colTypes, List *colCollations,
97 					  bool flag,
98 					  List *input_tlists,
99 					  List *refnames_tlist);
100 static List *generate_setop_grouplist(SetOperationStmt *op, List *targetlist);
101 static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte,
102 						 Index rti);
103 static void make_inh_translation_list(Relation oldrelation,
104 						  Relation newrelation,
105 						  Index newvarno,
106 						  List **translated_vars);
107 static Bitmapset *translate_col_privs(const Bitmapset *parent_privs,
108 					List *translated_vars);
109 static Node *adjust_appendrel_attrs_mutator(Node *node,
110 							   adjust_appendrel_attrs_context *context);
111 static Relids adjust_relid_set(Relids relids, Index oldrelid, Index newrelid);
112 static List *adjust_inherited_tlist(List *tlist,
113 					   AppendRelInfo *context);
114 
115 
116 /*
117  * plan_set_operations
118  *
119  *	  Plans the queries for a tree of set operations (UNION/INTERSECT/EXCEPT)
120  *
121  * This routine only deals with the setOperations tree of the given query.
122  * Any top-level ORDER BY requested in root->parse->sortClause will be handled
123  * when we return to grouping_planner; likewise for LIMIT.
124  *
125  * What we return is an "upperrel" RelOptInfo containing at least one Path
126  * that implements the set-operation tree.  In addition, root->processed_tlist
127  * receives a targetlist representing the output of the topmost setop node.
128  */
129 RelOptInfo *
plan_set_operations(PlannerInfo * root)130 plan_set_operations(PlannerInfo *root)
131 {
132 	Query	   *parse = root->parse;
133 	SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations;
134 	Node	   *node;
135 	RangeTblEntry *leftmostRTE;
136 	Query	   *leftmostQuery;
137 	RelOptInfo *setop_rel;
138 	Path	   *path;
139 	List	   *top_tlist;
140 
141 	Assert(topop && IsA(topop, SetOperationStmt));
142 
143 	/* check for unsupported stuff */
144 	Assert(parse->jointree->fromlist == NIL);
145 	Assert(parse->jointree->quals == NULL);
146 	Assert(parse->groupClause == NIL);
147 	Assert(parse->havingQual == NULL);
148 	Assert(parse->windowClause == NIL);
149 	Assert(parse->distinctClause == NIL);
150 
151 	/*
152 	 * We'll need to build RelOptInfos for each of the leaf subqueries, which
153 	 * are RTE_SUBQUERY rangetable entries in this Query.  Prepare the index
154 	 * arrays for that.
155 	 */
156 	setup_simple_rel_arrays(root);
157 
158 	/*
159 	 * Find the leftmost component Query.  We need to use its column names for
160 	 * all generated tlists (else SELECT INTO won't work right).
161 	 */
162 	node = topop->larg;
163 	while (node && IsA(node, SetOperationStmt))
164 		node = ((SetOperationStmt *) node)->larg;
165 	Assert(node && IsA(node, RangeTblRef));
166 	leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];
167 	leftmostQuery = leftmostRTE->subquery;
168 	Assert(leftmostQuery != NULL);
169 
170 	/*
171 	 * We return our results in the (SETOP, NULL) upperrel.  For the moment,
172 	 * this is also the parent rel of all Paths in the setop tree; we may well
173 	 * change that in future.
174 	 */
175 	setop_rel = fetch_upper_rel(root, UPPERREL_SETOP, NULL);
176 
177 	/*
178 	 * We don't currently worry about setting setop_rel's consider_parallel
179 	 * flag, nor about allowing FDWs to contribute paths to it.
180 	 */
181 
182 	/*
183 	 * If the topmost node is a recursive union, it needs special processing.
184 	 */
185 	if (root->hasRecursion)
186 	{
187 		path = generate_recursion_path(topop, root,
188 									   leftmostQuery->targetList,
189 									   &top_tlist);
190 	}
191 	else
192 	{
193 		/*
194 		 * Recurse on setOperations tree to generate paths for set ops. The
195 		 * final output path should have just the column types shown as the
196 		 * output from the top-level node, plus possibly resjunk working
197 		 * columns (we can rely on upper-level nodes to deal with that).
198 		 */
199 		path = recurse_set_operations((Node *) topop, root,
200 									  topop->colTypes, topop->colCollations,
201 									  true, -1,
202 									  leftmostQuery->targetList,
203 									  &top_tlist,
204 									  NULL);
205 	}
206 
207 	/* Must return the built tlist into root->processed_tlist. */
208 	root->processed_tlist = top_tlist;
209 
210 	/* Add only the final path to the SETOP upperrel. */
211 	add_path(setop_rel, path);
212 
213 	/* Let extensions possibly add some more paths */
214 	if (create_upper_paths_hook)
215 		(*create_upper_paths_hook) (root, UPPERREL_SETOP,
216 									NULL, setop_rel);
217 
218 	/* Select cheapest path */
219 	set_cheapest(setop_rel);
220 
221 	return setop_rel;
222 }
223 
224 /*
225  * recurse_set_operations
226  *	  Recursively handle one step in a tree of set operations
227  *
228  * colTypes: OID list of set-op's result column datatypes
229  * colCollations: OID list of set-op's result column collations
230  * junkOK: if true, child resjunk columns may be left in the result
231  * flag: if >= 0, add a resjunk output column indicating value of flag
232  * refnames_tlist: targetlist to take column names from
233  *
234  * Returns a path for the subtree, as well as these output parameters:
235  * *pTargetList: receives the fully-fledged tlist for the subtree's top plan
236  * *pNumGroups: if not NULL, we estimate the number of distinct groups
237  *		in the result, and store it there
238  *
239  * The pTargetList output parameter is mostly redundant with the pathtarget
240  * of the returned path, but for the moment we need it because much of the
241  * logic in this file depends on flag columns being marked resjunk.  Pending
242  * a redesign of how that works, this is the easy way out.
243  *
244  * We don't have to care about typmods here: the only allowed difference
245  * between set-op input and output typmods is input is a specific typmod
246  * and output is -1, and that does not require a coercion.
247  */
248 static Path *
recurse_set_operations(Node * setOp,PlannerInfo * root,List * colTypes,List * colCollations,bool junkOK,int flag,List * refnames_tlist,List ** pTargetList,double * pNumGroups)249 recurse_set_operations(Node *setOp, PlannerInfo *root,
250 					   List *colTypes, List *colCollations,
251 					   bool junkOK,
252 					   int flag, List *refnames_tlist,
253 					   List **pTargetList,
254 					   double *pNumGroups)
255 {
256 	/* Guard against stack overflow due to overly complex setop nests */
257 	check_stack_depth();
258 
259 	if (IsA(setOp, RangeTblRef))
260 	{
261 		RangeTblRef *rtr = (RangeTblRef *) setOp;
262 		RangeTblEntry *rte = root->simple_rte_array[rtr->rtindex];
263 		Query	   *subquery = rte->subquery;
264 		RelOptInfo *rel;
265 		PlannerInfo *subroot;
266 		RelOptInfo *final_rel;
267 		Path	   *subpath;
268 		Path	   *path;
269 		List	   *tlist;
270 
271 		Assert(subquery != NULL);
272 
273 		/*
274 		 * We need to build a RelOptInfo for each leaf subquery.  This isn't
275 		 * used for much here, but it carries the subroot data structures
276 		 * forward to setrefs.c processing.
277 		 */
278 		rel = build_simple_rel(root, rtr->rtindex, RELOPT_BASEREL);
279 
280 		/* plan_params should not be in use in current query level */
281 		Assert(root->plan_params == NIL);
282 
283 		/* Generate a subroot and Paths for the subquery */
284 		subroot = rel->subroot = subquery_planner(root->glob, subquery,
285 												  root,
286 												  false,
287 												  root->tuple_fraction);
288 
289 		/*
290 		 * It should not be possible for the primitive query to contain any
291 		 * cross-references to other primitive queries in the setop tree.
292 		 */
293 		if (root->plan_params)
294 			elog(ERROR, "unexpected outer reference in set operation subquery");
295 
296 		/*
297 		 * Mark rel with estimated output rows, width, etc.  Note that we have
298 		 * to do this before generating outer-query paths, else
299 		 * cost_subqueryscan is not happy.
300 		 */
301 		set_subquery_size_estimates(root, rel);
302 
303 		/*
304 		 * For the moment, we consider only a single Path for the subquery.
305 		 * This should change soon (make it look more like
306 		 * set_subquery_pathlist).
307 		 */
308 		final_rel = fetch_upper_rel(subroot, UPPERREL_FINAL, NULL);
309 		subpath = get_cheapest_fractional_path(final_rel,
310 											   root->tuple_fraction);
311 
312 		/*
313 		 * Stick a SubqueryScanPath atop that.
314 		 *
315 		 * We don't bother to determine the subquery's output ordering since
316 		 * it won't be reflected in the set-op result anyhow; so just label
317 		 * the SubqueryScanPath with nil pathkeys.  (XXX that should change
318 		 * soon too, likely.)
319 		 */
320 		path = (Path *) create_subqueryscan_path(root, rel, subpath,
321 												 NIL, NULL);
322 
323 		/*
324 		 * Figure out the appropriate target list, and update the
325 		 * SubqueryScanPath with the PathTarget form of that.
326 		 */
327 		tlist = generate_setop_tlist(colTypes, colCollations,
328 									 flag,
329 									 rtr->rtindex,
330 									 true,
331 									 subroot->processed_tlist,
332 									 refnames_tlist);
333 
334 		path = apply_projection_to_path(root, rel, path,
335 										create_pathtarget(root, tlist));
336 
337 		/* Return the fully-fledged tlist to caller, too */
338 		*pTargetList = tlist;
339 
340 		/*
341 		 * Estimate number of groups if caller wants it.  If the subquery used
342 		 * grouping or aggregation, its output is probably mostly unique
343 		 * anyway; otherwise do statistical estimation.
344 		 *
345 		 * XXX you don't really want to know about this: we do the estimation
346 		 * using the subquery's original targetlist expressions, not the
347 		 * subroot->processed_tlist which might seem more appropriate.  The
348 		 * reason is that if the subquery is itself a setop, it may return a
349 		 * processed_tlist containing "varno 0" Vars generated by
350 		 * generate_append_tlist, and those would confuse estimate_num_groups
351 		 * mightily.  We ought to get rid of the "varno 0" hack, but that
352 		 * requires a redesign of the parsetree representation of setops, so
353 		 * that there can be an RTE corresponding to each setop's output.
354 		 */
355 		if (pNumGroups)
356 		{
357 			if (subquery->groupClause || subquery->groupingSets ||
358 				subquery->distinctClause ||
359 				subroot->hasHavingQual || subquery->hasAggs)
360 				*pNumGroups = subpath->rows;
361 			else
362 				*pNumGroups = estimate_num_groups(subroot,
363 								get_tlist_exprs(subquery->targetList, false),
364 												  subpath->rows,
365 												  NULL);
366 		}
367 
368 		return (Path *) path;
369 	}
370 	else if (IsA(setOp, SetOperationStmt))
371 	{
372 		SetOperationStmt *op = (SetOperationStmt *) setOp;
373 		Path	   *path;
374 
375 		/* UNIONs are much different from INTERSECT/EXCEPT */
376 		if (op->op == SETOP_UNION)
377 			path = generate_union_path(op, root,
378 									   refnames_tlist,
379 									   pTargetList,
380 									   pNumGroups);
381 		else
382 			path = generate_nonunion_path(op, root,
383 										  refnames_tlist,
384 										  pTargetList,
385 										  pNumGroups);
386 
387 		/*
388 		 * If necessary, add a Result node to project the caller-requested
389 		 * output columns.
390 		 *
391 		 * XXX you don't really want to know about this: setrefs.c will apply
392 		 * fix_upper_expr() to the Result node's tlist. This would fail if the
393 		 * Vars generated by generate_setop_tlist() were not exactly equal()
394 		 * to the corresponding tlist entries of the subplan. However, since
395 		 * the subplan was generated by generate_union_plan() or
396 		 * generate_nonunion_plan(), and hence its tlist was generated by
397 		 * generate_append_tlist(), this will work.  We just tell
398 		 * generate_setop_tlist() to use varno 0.
399 		 */
400 		if (flag >= 0 ||
401 			!tlist_same_datatypes(*pTargetList, colTypes, junkOK) ||
402 			!tlist_same_collations(*pTargetList, colCollations, junkOK))
403 		{
404 			*pTargetList = generate_setop_tlist(colTypes, colCollations,
405 												flag,
406 												0,
407 												false,
408 												*pTargetList,
409 												refnames_tlist);
410 			path = apply_projection_to_path(root,
411 											path->parent,
412 											path,
413 											create_pathtarget(root,
414 															  *pTargetList));
415 		}
416 		return path;
417 	}
418 	else
419 	{
420 		elog(ERROR, "unrecognized node type: %d",
421 			 (int) nodeTag(setOp));
422 		*pTargetList = NIL;
423 		return NULL;			/* keep compiler quiet */
424 	}
425 }
426 
427 /*
428  * Generate path for a recursive UNION node
429  */
430 static Path *
generate_recursion_path(SetOperationStmt * setOp,PlannerInfo * root,List * refnames_tlist,List ** pTargetList)431 generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root,
432 						List *refnames_tlist,
433 						List **pTargetList)
434 {
435 	RelOptInfo *result_rel = fetch_upper_rel(root, UPPERREL_SETOP, NULL);
436 	Path	   *path;
437 	Path	   *lpath;
438 	Path	   *rpath;
439 	List	   *lpath_tlist;
440 	List	   *rpath_tlist;
441 	List	   *tlist;
442 	List	   *groupList;
443 	double		dNumGroups;
444 
445 	/* Parser should have rejected other cases */
446 	if (setOp->op != SETOP_UNION)
447 		elog(ERROR, "only UNION queries can be recursive");
448 	/* Worktable ID should be assigned */
449 	Assert(root->wt_param_id >= 0);
450 
451 	/*
452 	 * Unlike a regular UNION node, process the left and right inputs
453 	 * separately without any intention of combining them into one Append.
454 	 */
455 	lpath = recurse_set_operations(setOp->larg, root,
456 								   setOp->colTypes, setOp->colCollations,
457 								   false, -1,
458 								   refnames_tlist,
459 								   &lpath_tlist,
460 								   NULL);
461 	/* The right path will want to look at the left one ... */
462 	root->non_recursive_path = lpath;
463 	rpath = recurse_set_operations(setOp->rarg, root,
464 								   setOp->colTypes, setOp->colCollations,
465 								   false, -1,
466 								   refnames_tlist,
467 								   &rpath_tlist,
468 								   NULL);
469 	root->non_recursive_path = NULL;
470 
471 	/*
472 	 * Generate tlist for RecursiveUnion path node --- same as in Append cases
473 	 */
474 	tlist = generate_append_tlist(setOp->colTypes, setOp->colCollations, false,
475 								  list_make2(lpath_tlist, rpath_tlist),
476 								  refnames_tlist);
477 
478 	*pTargetList = tlist;
479 
480 	/*
481 	 * If UNION, identify the grouping operators
482 	 */
483 	if (setOp->all)
484 	{
485 		groupList = NIL;
486 		dNumGroups = 0;
487 	}
488 	else
489 	{
490 		/* Identify the grouping semantics */
491 		groupList = generate_setop_grouplist(setOp, tlist);
492 
493 		/* We only support hashing here */
494 		if (!grouping_is_hashable(groupList))
495 			ereport(ERROR,
496 					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
497 					 errmsg("could not implement recursive UNION"),
498 					 errdetail("All column datatypes must be hashable.")));
499 
500 		/*
501 		 * For the moment, take the number of distinct groups as equal to the
502 		 * total input size, ie, the worst case.
503 		 */
504 		dNumGroups = lpath->rows + rpath->rows * 10;
505 	}
506 
507 	/*
508 	 * And make the path node.
509 	 */
510 	path = (Path *) create_recursiveunion_path(root,
511 											   result_rel,
512 											   lpath,
513 											   rpath,
514 											   create_pathtarget(root, tlist),
515 											   groupList,
516 											   root->wt_param_id,
517 											   dNumGroups);
518 
519 	return path;
520 }
521 
522 /*
523  * Generate path for a UNION or UNION ALL node
524  */
525 static Path *
generate_union_path(SetOperationStmt * op,PlannerInfo * root,List * refnames_tlist,List ** pTargetList,double * pNumGroups)526 generate_union_path(SetOperationStmt *op, PlannerInfo *root,
527 					List *refnames_tlist,
528 					List **pTargetList,
529 					double *pNumGroups)
530 {
531 	RelOptInfo *result_rel = fetch_upper_rel(root, UPPERREL_SETOP, NULL);
532 	double		save_fraction = root->tuple_fraction;
533 	List	   *pathlist;
534 	List	   *child_tlists1;
535 	List	   *child_tlists2;
536 	List	   *tlist_list;
537 	List	   *tlist;
538 	Path	   *path;
539 
540 	/*
541 	 * If plain UNION, tell children to fetch all tuples.
542 	 *
543 	 * Note: in UNION ALL, we pass the top-level tuple_fraction unmodified to
544 	 * each arm of the UNION ALL.  One could make a case for reducing the
545 	 * tuple fraction for later arms (discounting by the expected size of the
546 	 * earlier arms' results) but it seems not worth the trouble. The normal
547 	 * case where tuple_fraction isn't already zero is a LIMIT at top level,
548 	 * and passing it down as-is is usually enough to get the desired result
549 	 * of preferring fast-start plans.
550 	 */
551 	if (!op->all)
552 		root->tuple_fraction = 0.0;
553 
554 	/*
555 	 * If any of my children are identical UNION nodes (same op, all-flag, and
556 	 * colTypes) then they can be merged into this node so that we generate
557 	 * only one Append and unique-ification for the lot.  Recurse to find such
558 	 * nodes and compute their children's paths.
559 	 */
560 	pathlist = list_concat(recurse_union_children(op->larg, root,
561 												  op, refnames_tlist,
562 												  &child_tlists1),
563 						   recurse_union_children(op->rarg, root,
564 												  op, refnames_tlist,
565 												  &child_tlists2));
566 	tlist_list = list_concat(child_tlists1, child_tlists2);
567 
568 	/*
569 	 * Generate tlist for Append plan node.
570 	 *
571 	 * The tlist for an Append plan isn't important as far as the Append is
572 	 * concerned, but we must make it look real anyway for the benefit of the
573 	 * next plan level up.
574 	 */
575 	tlist = generate_append_tlist(op->colTypes, op->colCollations, false,
576 								  tlist_list, refnames_tlist);
577 
578 	*pTargetList = tlist;
579 
580 	/*
581 	 * Append the child results together.
582 	 */
583 	path = (Path *) create_append_path(result_rel, pathlist, NULL, 0);
584 
585 	/* We have to manually jam the right tlist into the path; ick */
586 	path->pathtarget = create_pathtarget(root, tlist);
587 
588 	/*
589 	 * For UNION ALL, we just need the Append path.  For UNION, need to add
590 	 * node(s) to remove duplicates.
591 	 */
592 	if (!op->all)
593 		path = make_union_unique(op, path, tlist, root);
594 
595 	/*
596 	 * Estimate number of groups if caller wants it.  For now we just assume
597 	 * the output is unique --- this is certainly true for the UNION case, and
598 	 * we want worst-case estimates anyway.
599 	 */
600 	if (pNumGroups)
601 		*pNumGroups = path->rows;
602 
603 	/* Undo effects of possibly forcing tuple_fraction to 0 */
604 	root->tuple_fraction = save_fraction;
605 
606 	return path;
607 }
608 
609 /*
610  * Generate path for an INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL node
611  */
612 static Path *
generate_nonunion_path(SetOperationStmt * op,PlannerInfo * root,List * refnames_tlist,List ** pTargetList,double * pNumGroups)613 generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
614 					   List *refnames_tlist,
615 					   List **pTargetList,
616 					   double *pNumGroups)
617 {
618 	RelOptInfo *result_rel = fetch_upper_rel(root, UPPERREL_SETOP, NULL);
619 	double		save_fraction = root->tuple_fraction;
620 	Path	   *lpath,
621 			   *rpath,
622 			   *path;
623 	List	   *lpath_tlist,
624 			   *rpath_tlist,
625 			   *tlist_list,
626 			   *tlist,
627 			   *groupList,
628 			   *pathlist;
629 	double		dLeftGroups,
630 				dRightGroups,
631 				dNumGroups,
632 				dNumOutputRows;
633 	bool		use_hash;
634 	SetOpCmd	cmd;
635 	int			firstFlag;
636 
637 	/*
638 	 * Tell children to fetch all tuples.
639 	 */
640 	root->tuple_fraction = 0.0;
641 
642 	/* Recurse on children, ensuring their outputs are marked */
643 	lpath = recurse_set_operations(op->larg, root,
644 								   op->colTypes, op->colCollations,
645 								   false, 0,
646 								   refnames_tlist,
647 								   &lpath_tlist,
648 								   &dLeftGroups);
649 	rpath = recurse_set_operations(op->rarg, root,
650 								   op->colTypes, op->colCollations,
651 								   false, 1,
652 								   refnames_tlist,
653 								   &rpath_tlist,
654 								   &dRightGroups);
655 
656 	/* Undo effects of forcing tuple_fraction to 0 */
657 	root->tuple_fraction = save_fraction;
658 
659 	/*
660 	 * For EXCEPT, we must put the left input first.  For INTERSECT, either
661 	 * order should give the same results, and we prefer to put the smaller
662 	 * input first in order to minimize the size of the hash table in the
663 	 * hashing case.  "Smaller" means the one with the fewer groups.
664 	 */
665 	if (op->op == SETOP_EXCEPT || dLeftGroups <= dRightGroups)
666 	{
667 		pathlist = list_make2(lpath, rpath);
668 		tlist_list = list_make2(lpath_tlist, rpath_tlist);
669 		firstFlag = 0;
670 	}
671 	else
672 	{
673 		pathlist = list_make2(rpath, lpath);
674 		tlist_list = list_make2(rpath_tlist, lpath_tlist);
675 		firstFlag = 1;
676 	}
677 
678 	/*
679 	 * Generate tlist for Append plan node.
680 	 *
681 	 * The tlist for an Append plan isn't important as far as the Append is
682 	 * concerned, but we must make it look real anyway for the benefit of the
683 	 * next plan level up.  In fact, it has to be real enough that the flag
684 	 * column is shown as a variable not a constant, else setrefs.c will get
685 	 * confused.
686 	 */
687 	tlist = generate_append_tlist(op->colTypes, op->colCollations, true,
688 								  tlist_list, refnames_tlist);
689 
690 	*pTargetList = tlist;
691 
692 	/*
693 	 * Append the child results together.
694 	 */
695 	path = (Path *) create_append_path(result_rel, pathlist, NULL, 0);
696 
697 	/* We have to manually jam the right tlist into the path; ick */
698 	path->pathtarget = create_pathtarget(root, tlist);
699 
700 	/* Identify the grouping semantics */
701 	groupList = generate_setop_grouplist(op, tlist);
702 
703 	/* punt if nothing to group on (not worth fixing in back branches) */
704 	if (groupList == NIL)
705 		ereport(ERROR,
706 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
707 				 /* translator: %s is UNION, INTERSECT, or EXCEPT */
708 				 errmsg("%s over no columns is not supported",
709 						(op->op == SETOP_INTERSECT) ? "INTERSECT" : "EXCEPT")));
710 
711 	/*
712 	 * Estimate number of distinct groups that we'll need hashtable entries
713 	 * for; this is the size of the left-hand input for EXCEPT, or the smaller
714 	 * input for INTERSECT.  Also estimate the number of eventual output rows.
715 	 * In non-ALL cases, we estimate each group produces one output row; in
716 	 * ALL cases use the relevant relation size.  These are worst-case
717 	 * estimates, of course, but we need to be conservative.
718 	 */
719 	if (op->op == SETOP_EXCEPT)
720 	{
721 		dNumGroups = dLeftGroups;
722 		dNumOutputRows = op->all ? lpath->rows : dNumGroups;
723 	}
724 	else
725 	{
726 		dNumGroups = Min(dLeftGroups, dRightGroups);
727 		dNumOutputRows = op->all ? Min(lpath->rows, rpath->rows) : dNumGroups;
728 	}
729 
730 	/*
731 	 * Decide whether to hash or sort, and add a sort node if needed.
732 	 */
733 	use_hash = choose_hashed_setop(root, groupList, path,
734 								   dNumGroups, dNumOutputRows,
735 					   (op->op == SETOP_INTERSECT) ? "INTERSECT" : "EXCEPT");
736 
737 	if (!use_hash)
738 		path = (Path *) create_sort_path(root,
739 										 result_rel,
740 										 path,
741 										 make_pathkeys_for_sortclauses(root,
742 																   groupList,
743 																	   tlist),
744 										 -1.0);
745 
746 	/*
747 	 * Finally, add a SetOp path node to generate the correct output.
748 	 */
749 	switch (op->op)
750 	{
751 		case SETOP_INTERSECT:
752 			cmd = op->all ? SETOPCMD_INTERSECT_ALL : SETOPCMD_INTERSECT;
753 			break;
754 		case SETOP_EXCEPT:
755 			cmd = op->all ? SETOPCMD_EXCEPT_ALL : SETOPCMD_EXCEPT;
756 			break;
757 		default:
758 			elog(ERROR, "unrecognized set op: %d", (int) op->op);
759 			cmd = SETOPCMD_INTERSECT;	/* keep compiler quiet */
760 			break;
761 	}
762 	path = (Path *) create_setop_path(root,
763 									  result_rel,
764 									  path,
765 									  cmd,
766 									  use_hash ? SETOP_HASHED : SETOP_SORTED,
767 									  groupList,
768 									  list_length(op->colTypes) + 1,
769 									  use_hash ? firstFlag : -1,
770 									  dNumGroups,
771 									  dNumOutputRows);
772 
773 	if (pNumGroups)
774 		*pNumGroups = dNumGroups;
775 
776 	return path;
777 }
778 
779 /*
780  * Pull up children of a UNION node that are identically-propertied UNIONs.
781  *
782  * NOTE: we can also pull a UNION ALL up into a UNION, since the distinct
783  * output rows will be lost anyway.
784  *
785  * NOTE: currently, we ignore collations while determining if a child has
786  * the same properties.  This is semantically sound only so long as all
787  * collations have the same notion of equality.  It is valid from an
788  * implementation standpoint because we don't care about the ordering of
789  * a UNION child's result: UNION ALL results are always unordered, and
790  * generate_union_path will force a fresh sort if the top level is a UNION.
791  */
792 static List *
recurse_union_children(Node * setOp,PlannerInfo * root,SetOperationStmt * top_union,List * refnames_tlist,List ** tlist_list)793 recurse_union_children(Node *setOp, PlannerInfo *root,
794 					   SetOperationStmt *top_union,
795 					   List *refnames_tlist,
796 					   List **tlist_list)
797 {
798 	List	   *result;
799 	List	   *child_tlist;
800 
801 	if (IsA(setOp, SetOperationStmt))
802 	{
803 		SetOperationStmt *op = (SetOperationStmt *) setOp;
804 
805 		if (op->op == top_union->op &&
806 			(op->all == top_union->all || op->all) &&
807 			equal(op->colTypes, top_union->colTypes))
808 		{
809 			/* Same UNION, so fold children into parent's subpath list */
810 			List	   *child_tlists1;
811 			List	   *child_tlists2;
812 
813 			result = list_concat(recurse_union_children(op->larg, root,
814 														top_union,
815 														refnames_tlist,
816 														&child_tlists1),
817 								 recurse_union_children(op->rarg, root,
818 														top_union,
819 														refnames_tlist,
820 														&child_tlists2));
821 			*tlist_list = list_concat(child_tlists1, child_tlists2);
822 			return result;
823 		}
824 	}
825 
826 	/*
827 	 * Not same, so plan this child separately.
828 	 *
829 	 * Note we disallow any resjunk columns in child results.  This is
830 	 * necessary since the Append node that implements the union won't do any
831 	 * projection, and upper levels will get confused if some of our output
832 	 * tuples have junk and some don't.  This case only arises when we have an
833 	 * EXCEPT or INTERSECT as child, else there won't be resjunk anyway.
834 	 */
835 	result = list_make1(recurse_set_operations(setOp, root,
836 											   top_union->colTypes,
837 											   top_union->colCollations,
838 											   false, -1,
839 											   refnames_tlist,
840 											   &child_tlist,
841 											   NULL));
842 	*tlist_list = list_make1(child_tlist);
843 	return result;
844 }
845 
846 /*
847  * Add nodes to the given path tree to unique-ify the result of a UNION.
848  */
849 static Path *
make_union_unique(SetOperationStmt * op,Path * path,List * tlist,PlannerInfo * root)850 make_union_unique(SetOperationStmt *op, Path *path, List *tlist,
851 				  PlannerInfo *root)
852 {
853 	RelOptInfo *result_rel = fetch_upper_rel(root, UPPERREL_SETOP, NULL);
854 	List	   *groupList;
855 	double		dNumGroups;
856 
857 	/* Identify the grouping semantics */
858 	groupList = generate_setop_grouplist(op, tlist);
859 
860 	/* punt if nothing to group on (not worth fixing in back branches) */
861 	if (groupList == NIL)
862 		ereport(ERROR,
863 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
864 				 /* translator: %s is UNION, INTERSECT, or EXCEPT */
865 				 errmsg("%s over no columns is not supported", "UNION")));
866 
867 	/*
868 	 * XXX for the moment, take the number of distinct groups as equal to the
869 	 * total input size, ie, the worst case.  This is too conservative, but we
870 	 * don't want to risk having the hashtable overrun memory; also, it's not
871 	 * clear how to get a decent estimate of the true size.  One should note
872 	 * as well the propensity of novices to write UNION rather than UNION ALL
873 	 * even when they don't expect any duplicates...
874 	 */
875 	dNumGroups = path->rows;
876 
877 	/* Decide whether to hash or sort */
878 	if (choose_hashed_setop(root, groupList, path,
879 							dNumGroups, dNumGroups,
880 							"UNION"))
881 	{
882 		/* Hashed aggregate plan --- no sort needed */
883 		path = (Path *) create_agg_path(root,
884 										result_rel,
885 										path,
886 										create_pathtarget(root, tlist),
887 										AGG_HASHED,
888 										AGGSPLIT_SIMPLE,
889 										groupList,
890 										NIL,
891 										NULL,
892 										dNumGroups);
893 	}
894 	else
895 	{
896 		/* Sort and Unique */
897 		path = (Path *) create_sort_path(root,
898 										 result_rel,
899 										 path,
900 										 make_pathkeys_for_sortclauses(root,
901 																   groupList,
902 																	   tlist),
903 										 -1.0);
904 		/* We have to manually jam the right tlist into the path; ick */
905 		path->pathtarget = create_pathtarget(root, tlist);
906 		path = (Path *) create_upper_unique_path(root,
907 												 result_rel,
908 												 path,
909 												 list_length(path->pathkeys),
910 												 dNumGroups);
911 	}
912 
913 	return path;
914 }
915 
916 /*
917  * choose_hashed_setop - should we use hashing for a set operation?
918  */
919 static bool
choose_hashed_setop(PlannerInfo * root,List * groupClauses,Path * input_path,double dNumGroups,double dNumOutputRows,const char * construct)920 choose_hashed_setop(PlannerInfo *root, List *groupClauses,
921 					Path *input_path,
922 					double dNumGroups, double dNumOutputRows,
923 					const char *construct)
924 {
925 	int			numGroupCols = list_length(groupClauses);
926 	bool		can_sort;
927 	bool		can_hash;
928 	Size		hashentrysize;
929 	Path		hashed_p;
930 	Path		sorted_p;
931 	double		tuple_fraction;
932 
933 	/* Check whether the operators support sorting or hashing */
934 	can_sort = grouping_is_sortable(groupClauses);
935 	can_hash = grouping_is_hashable(groupClauses);
936 	if (can_hash && can_sort)
937 	{
938 		/* we have a meaningful choice to make, continue ... */
939 	}
940 	else if (can_hash)
941 		return true;
942 	else if (can_sort)
943 		return false;
944 	else
945 		ereport(ERROR,
946 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
947 		/* translator: %s is UNION, INTERSECT, or EXCEPT */
948 				 errmsg("could not implement %s", construct),
949 				 errdetail("Some of the datatypes only support hashing, while others only support sorting.")));
950 
951 	/* Prefer sorting when enable_hashagg is off */
952 	if (!enable_hashagg)
953 		return false;
954 
955 	/*
956 	 * Don't do it if it doesn't look like the hashtable will fit into
957 	 * work_mem.
958 	 */
959 	hashentrysize = MAXALIGN(input_path->pathtarget->width) + MAXALIGN(SizeofMinimalTupleHeader);
960 
961 	if (hashentrysize * dNumGroups > work_mem * 1024L)
962 		return false;
963 
964 	/*
965 	 * See if the estimated cost is no more than doing it the other way.
966 	 *
967 	 * We need to consider input_plan + hashagg versus input_plan + sort +
968 	 * group.  Note that the actual result plan might involve a SetOp or
969 	 * Unique node, not Agg or Group, but the cost estimates for Agg and Group
970 	 * should be close enough for our purposes here.
971 	 *
972 	 * These path variables are dummies that just hold cost fields; we don't
973 	 * make actual Paths for these steps.
974 	 */
975 	cost_agg(&hashed_p, root, AGG_HASHED, NULL,
976 			 numGroupCols, dNumGroups,
977 			 input_path->startup_cost, input_path->total_cost,
978 			 input_path->rows);
979 
980 	/*
981 	 * Now for the sorted case.  Note that the input is *always* unsorted,
982 	 * since it was made by appending unrelated sub-relations together.
983 	 */
984 	sorted_p.startup_cost = input_path->startup_cost;
985 	sorted_p.total_cost = input_path->total_cost;
986 	/* XXX cost_sort doesn't actually look at pathkeys, so just pass NIL */
987 	cost_sort(&sorted_p, root, NIL, sorted_p.total_cost,
988 			  input_path->rows, input_path->pathtarget->width,
989 			  0.0, work_mem, -1.0);
990 	cost_group(&sorted_p, root, numGroupCols, dNumGroups,
991 			   sorted_p.startup_cost, sorted_p.total_cost,
992 			   input_path->rows);
993 
994 	/*
995 	 * Now make the decision using the top-level tuple fraction.  First we
996 	 * have to convert an absolute count (LIMIT) into fractional form.
997 	 */
998 	tuple_fraction = root->tuple_fraction;
999 	if (tuple_fraction >= 1.0)
1000 		tuple_fraction /= dNumOutputRows;
1001 
1002 	if (compare_fractional_path_costs(&hashed_p, &sorted_p,
1003 									  tuple_fraction) < 0)
1004 	{
1005 		/* Hashed is cheaper, so use it */
1006 		return true;
1007 	}
1008 	return false;
1009 }
1010 
1011 /*
1012  * Generate targetlist for a set-operation plan node
1013  *
1014  * colTypes: OID list of set-op's result column datatypes
1015  * colCollations: OID list of set-op's result column collations
1016  * flag: -1 if no flag column needed, 0 or 1 to create a const flag column
1017  * varno: varno to use in generated Vars
1018  * hack_constants: true to copy up constants (see comments in code)
1019  * input_tlist: targetlist of this node's input node
1020  * refnames_tlist: targetlist to take column names from
1021  */
1022 static List *
generate_setop_tlist(List * colTypes,List * colCollations,int flag,Index varno,bool hack_constants,List * input_tlist,List * refnames_tlist)1023 generate_setop_tlist(List *colTypes, List *colCollations,
1024 					 int flag,
1025 					 Index varno,
1026 					 bool hack_constants,
1027 					 List *input_tlist,
1028 					 List *refnames_tlist)
1029 {
1030 	List	   *tlist = NIL;
1031 	int			resno = 1;
1032 	ListCell   *ctlc,
1033 			   *cclc,
1034 			   *itlc,
1035 			   *rtlc;
1036 	TargetEntry *tle;
1037 	Node	   *expr;
1038 
1039 	/* there's no forfour() so we must chase one list manually */
1040 	rtlc = list_head(refnames_tlist);
1041 	forthree(ctlc, colTypes, cclc, colCollations, itlc, input_tlist)
1042 	{
1043 		Oid			colType = lfirst_oid(ctlc);
1044 		Oid			colColl = lfirst_oid(cclc);
1045 		TargetEntry *inputtle = (TargetEntry *) lfirst(itlc);
1046 		TargetEntry *reftle = (TargetEntry *) lfirst(rtlc);
1047 
1048 		rtlc = lnext(rtlc);
1049 
1050 		Assert(inputtle->resno == resno);
1051 		Assert(reftle->resno == resno);
1052 		Assert(!inputtle->resjunk);
1053 		Assert(!reftle->resjunk);
1054 
1055 		/*
1056 		 * Generate columns referencing input columns and having appropriate
1057 		 * data types and column names.  Insert datatype coercions where
1058 		 * necessary.
1059 		 *
1060 		 * HACK: constants in the input's targetlist are copied up as-is
1061 		 * rather than being referenced as subquery outputs.  This is mainly
1062 		 * to ensure that when we try to coerce them to the output column's
1063 		 * datatype, the right things happen for UNKNOWN constants.  But do
1064 		 * this only at the first level of subquery-scan plans; we don't want
1065 		 * phony constants appearing in the output tlists of upper-level
1066 		 * nodes!
1067 		 */
1068 		if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))
1069 			expr = (Node *) inputtle->expr;
1070 		else
1071 			expr = (Node *) makeVar(varno,
1072 									inputtle->resno,
1073 									exprType((Node *) inputtle->expr),
1074 									exprTypmod((Node *) inputtle->expr),
1075 									exprCollation((Node *) inputtle->expr),
1076 									0);
1077 
1078 		if (exprType(expr) != colType)
1079 		{
1080 			/*
1081 			 * Note: it's not really cool to be applying coerce_to_common_type
1082 			 * here; one notable point is that assign_expr_collations never
1083 			 * gets run on any generated nodes.  For the moment that's not a
1084 			 * problem because we force the correct exposed collation below.
1085 			 * It would likely be best to make the parser generate the correct
1086 			 * output tlist for every set-op to begin with, though.
1087 			 */
1088 			expr = coerce_to_common_type(NULL,	/* no UNKNOWNs here */
1089 										 expr,
1090 										 colType,
1091 										 "UNION/INTERSECT/EXCEPT");
1092 		}
1093 
1094 		/*
1095 		 * Ensure the tlist entry's exposed collation matches the set-op. This
1096 		 * is necessary because plan_set_operations() reports the result
1097 		 * ordering as a list of SortGroupClauses, which don't carry collation
1098 		 * themselves but just refer to tlist entries.  If we don't show the
1099 		 * right collation then planner.c might do the wrong thing in
1100 		 * higher-level queries.
1101 		 *
1102 		 * Note we use RelabelType, not CollateExpr, since this expression
1103 		 * will reach the executor without any further processing.
1104 		 */
1105 		if (exprCollation(expr) != colColl)
1106 		{
1107 			expr = (Node *) makeRelabelType((Expr *) expr,
1108 											exprType(expr),
1109 											exprTypmod(expr),
1110 											colColl,
1111 											COERCE_IMPLICIT_CAST);
1112 		}
1113 
1114 		tle = makeTargetEntry((Expr *) expr,
1115 							  (AttrNumber) resno++,
1116 							  pstrdup(reftle->resname),
1117 							  false);
1118 
1119 		/*
1120 		 * By convention, all non-resjunk columns in a setop tree have
1121 		 * ressortgroupref equal to their resno.  In some cases the ref isn't
1122 		 * needed, but this is a cleaner way than modifying the tlist later.
1123 		 */
1124 		tle->ressortgroupref = tle->resno;
1125 
1126 		tlist = lappend(tlist, tle);
1127 	}
1128 
1129 	if (flag >= 0)
1130 	{
1131 		/* Add a resjunk flag column */
1132 		/* flag value is the given constant */
1133 		expr = (Node *) makeConst(INT4OID,
1134 								  -1,
1135 								  InvalidOid,
1136 								  sizeof(int32),
1137 								  Int32GetDatum(flag),
1138 								  false,
1139 								  true);
1140 		tle = makeTargetEntry((Expr *) expr,
1141 							  (AttrNumber) resno++,
1142 							  pstrdup("flag"),
1143 							  true);
1144 		tlist = lappend(tlist, tle);
1145 	}
1146 
1147 	return tlist;
1148 }
1149 
1150 /*
1151  * Generate targetlist for a set-operation Append node
1152  *
1153  * colTypes: OID list of set-op's result column datatypes
1154  * colCollations: OID list of set-op's result column collations
1155  * flag: true to create a flag column copied up from subplans
1156  * input_tlists: list of tlists for sub-plans of the Append
1157  * refnames_tlist: targetlist to take column names from
1158  *
1159  * The entries in the Append's targetlist should always be simple Vars;
1160  * we just have to make sure they have the right datatypes/typmods/collations.
1161  * The Vars are always generated with varno 0.
1162  *
1163  * XXX a problem with the varno-zero approach is that set_pathtarget_cost_width
1164  * cannot figure out a realistic width for the tlist we make here.  But we
1165  * ought to refactor this code to produce a PathTarget directly, anyway.
1166  */
1167 static List *
generate_append_tlist(List * colTypes,List * colCollations,bool flag,List * input_tlists,List * refnames_tlist)1168 generate_append_tlist(List *colTypes, List *colCollations,
1169 					  bool flag,
1170 					  List *input_tlists,
1171 					  List *refnames_tlist)
1172 {
1173 	List	   *tlist = NIL;
1174 	int			resno = 1;
1175 	ListCell   *curColType;
1176 	ListCell   *curColCollation;
1177 	ListCell   *ref_tl_item;
1178 	int			colindex;
1179 	TargetEntry *tle;
1180 	Node	   *expr;
1181 	ListCell   *tlistl;
1182 	int32	   *colTypmods;
1183 
1184 	/*
1185 	 * First extract typmods to use.
1186 	 *
1187 	 * If the inputs all agree on type and typmod of a particular column, use
1188 	 * that typmod; else use -1.
1189 	 */
1190 	colTypmods = (int32 *) palloc(list_length(colTypes) * sizeof(int32));
1191 
1192 	foreach(tlistl, input_tlists)
1193 	{
1194 		List	   *subtlist = (List *) lfirst(tlistl);
1195 		ListCell   *subtlistl;
1196 
1197 		curColType = list_head(colTypes);
1198 		colindex = 0;
1199 		foreach(subtlistl, subtlist)
1200 		{
1201 			TargetEntry *subtle = (TargetEntry *) lfirst(subtlistl);
1202 
1203 			if (subtle->resjunk)
1204 				continue;
1205 			Assert(curColType != NULL);
1206 			if (exprType((Node *) subtle->expr) == lfirst_oid(curColType))
1207 			{
1208 				/* If first subplan, copy the typmod; else compare */
1209 				int32		subtypmod = exprTypmod((Node *) subtle->expr);
1210 
1211 				if (tlistl == list_head(input_tlists))
1212 					colTypmods[colindex] = subtypmod;
1213 				else if (subtypmod != colTypmods[colindex])
1214 					colTypmods[colindex] = -1;
1215 			}
1216 			else
1217 			{
1218 				/* types disagree, so force typmod to -1 */
1219 				colTypmods[colindex] = -1;
1220 			}
1221 			curColType = lnext(curColType);
1222 			colindex++;
1223 		}
1224 		Assert(curColType == NULL);
1225 	}
1226 
1227 	/*
1228 	 * Now we can build the tlist for the Append.
1229 	 */
1230 	colindex = 0;
1231 	forthree(curColType, colTypes, curColCollation, colCollations,
1232 			 ref_tl_item, refnames_tlist)
1233 	{
1234 		Oid			colType = lfirst_oid(curColType);
1235 		int32		colTypmod = colTypmods[colindex++];
1236 		Oid			colColl = lfirst_oid(curColCollation);
1237 		TargetEntry *reftle = (TargetEntry *) lfirst(ref_tl_item);
1238 
1239 		Assert(reftle->resno == resno);
1240 		Assert(!reftle->resjunk);
1241 		expr = (Node *) makeVar(0,
1242 								resno,
1243 								colType,
1244 								colTypmod,
1245 								colColl,
1246 								0);
1247 		tle = makeTargetEntry((Expr *) expr,
1248 							  (AttrNumber) resno++,
1249 							  pstrdup(reftle->resname),
1250 							  false);
1251 
1252 		/*
1253 		 * By convention, all non-resjunk columns in a setop tree have
1254 		 * ressortgroupref equal to their resno.  In some cases the ref isn't
1255 		 * needed, but this is a cleaner way than modifying the tlist later.
1256 		 */
1257 		tle->ressortgroupref = tle->resno;
1258 
1259 		tlist = lappend(tlist, tle);
1260 	}
1261 
1262 	if (flag)
1263 	{
1264 		/* Add a resjunk flag column */
1265 		/* flag value is shown as copied up from subplan */
1266 		expr = (Node *) makeVar(0,
1267 								resno,
1268 								INT4OID,
1269 								-1,
1270 								InvalidOid,
1271 								0);
1272 		tle = makeTargetEntry((Expr *) expr,
1273 							  (AttrNumber) resno++,
1274 							  pstrdup("flag"),
1275 							  true);
1276 		tlist = lappend(tlist, tle);
1277 	}
1278 
1279 	pfree(colTypmods);
1280 
1281 	return tlist;
1282 }
1283 
1284 /*
1285  * generate_setop_grouplist
1286  *		Build a SortGroupClause list defining the sort/grouping properties
1287  *		of the setop's output columns.
1288  *
1289  * Parse analysis already determined the properties and built a suitable
1290  * list, except that the entries do not have sortgrouprefs set because
1291  * the parser output representation doesn't include a tlist for each
1292  * setop.  So what we need to do here is copy that list and install
1293  * proper sortgrouprefs into it (copying those from the targetlist).
1294  */
1295 static List *
generate_setop_grouplist(SetOperationStmt * op,List * targetlist)1296 generate_setop_grouplist(SetOperationStmt *op, List *targetlist)
1297 {
1298 	List	   *grouplist = (List *) copyObject(op->groupClauses);
1299 	ListCell   *lg;
1300 	ListCell   *lt;
1301 
1302 	lg = list_head(grouplist);
1303 	foreach(lt, targetlist)
1304 	{
1305 		TargetEntry *tle = (TargetEntry *) lfirst(lt);
1306 		SortGroupClause *sgc;
1307 
1308 		if (tle->resjunk)
1309 		{
1310 			/* resjunk columns should not have sortgrouprefs */
1311 			Assert(tle->ressortgroupref == 0);
1312 			continue;			/* ignore resjunk columns */
1313 		}
1314 
1315 		/* non-resjunk columns should have sortgroupref = resno */
1316 		Assert(tle->ressortgroupref == tle->resno);
1317 
1318 		/* non-resjunk columns should have grouping clauses */
1319 		Assert(lg != NULL);
1320 		sgc = (SortGroupClause *) lfirst(lg);
1321 		lg = lnext(lg);
1322 		Assert(sgc->tleSortGroupRef == 0);
1323 
1324 		sgc->tleSortGroupRef = tle->ressortgroupref;
1325 	}
1326 	Assert(lg == NULL);
1327 	return grouplist;
1328 }
1329 
1330 
1331 /*
1332  * expand_inherited_tables
1333  *		Expand each rangetable entry that represents an inheritance set
1334  *		into an "append relation".  At the conclusion of this process,
1335  *		the "inh" flag is set in all and only those RTEs that are append
1336  *		relation parents.
1337  */
1338 void
expand_inherited_tables(PlannerInfo * root)1339 expand_inherited_tables(PlannerInfo *root)
1340 {
1341 	Index		nrtes;
1342 	Index		rti;
1343 	ListCell   *rl;
1344 
1345 	/*
1346 	 * expand_inherited_rtentry may add RTEs to parse->rtable; there is no
1347 	 * need to scan them since they can't have inh=true.  So just scan as far
1348 	 * as the original end of the rtable list.
1349 	 */
1350 	nrtes = list_length(root->parse->rtable);
1351 	rl = list_head(root->parse->rtable);
1352 	for (rti = 1; rti <= nrtes; rti++)
1353 	{
1354 		RangeTblEntry *rte = (RangeTblEntry *) lfirst(rl);
1355 
1356 		expand_inherited_rtentry(root, rte, rti);
1357 		rl = lnext(rl);
1358 	}
1359 }
1360 
1361 /*
1362  * expand_inherited_rtentry
1363  *		Check whether a rangetable entry represents an inheritance set.
1364  *		If so, add entries for all the child tables to the query's
1365  *		rangetable, and build AppendRelInfo nodes for all the child tables
1366  *		and add them to root->append_rel_list.  If not, clear the entry's
1367  *		"inh" flag to prevent later code from looking for AppendRelInfos.
1368  *
1369  * Note that the original RTE is considered to represent the whole
1370  * inheritance set.  The first of the generated RTEs is an RTE for the same
1371  * table, but with inh = false, to represent the parent table in its role
1372  * as a simple member of the inheritance set.
1373  *
1374  * A childless table is never considered to be an inheritance set; therefore
1375  * a parent RTE must always have at least two associated AppendRelInfos.
1376  */
1377 static void
expand_inherited_rtentry(PlannerInfo * root,RangeTblEntry * rte,Index rti)1378 expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
1379 {
1380 	Query	   *parse = root->parse;
1381 	Oid			parentOID;
1382 	PlanRowMark *oldrc;
1383 	Relation	oldrelation;
1384 	LOCKMODE	lockmode;
1385 	List	   *inhOIDs;
1386 	List	   *appinfos;
1387 	ListCell   *l;
1388 
1389 	/* Does RT entry allow inheritance? */
1390 	if (!rte->inh)
1391 		return;
1392 	/* Ignore any already-expanded UNION ALL nodes */
1393 	if (rte->rtekind != RTE_RELATION)
1394 	{
1395 		Assert(rte->rtekind == RTE_SUBQUERY);
1396 		return;
1397 	}
1398 	/* Fast path for common case of childless table */
1399 	parentOID = rte->relid;
1400 	if (!has_subclass(parentOID))
1401 	{
1402 		/* Clear flag before returning */
1403 		rte->inh = false;
1404 		return;
1405 	}
1406 
1407 	/*
1408 	 * The rewriter should already have obtained an appropriate lock on each
1409 	 * relation named in the query.  However, for each child relation we add
1410 	 * to the query, we must obtain an appropriate lock, because this will be
1411 	 * the first use of those relations in the parse/rewrite/plan pipeline.
1412 	 *
1413 	 * If the parent relation is the query's result relation, then we need
1414 	 * RowExclusiveLock.  Otherwise, if it's accessed FOR UPDATE/SHARE, we
1415 	 * need RowShareLock; otherwise AccessShareLock.  We can't just grab
1416 	 * AccessShareLock because then the executor would be trying to upgrade
1417 	 * the lock, leading to possible deadlocks.  (This code should match the
1418 	 * parser and rewriter.)
1419 	 */
1420 	oldrc = get_plan_rowmark(root->rowMarks, rti);
1421 	if (rti == parse->resultRelation)
1422 		lockmode = RowExclusiveLock;
1423 	else if (oldrc && RowMarkRequiresRowShareLock(oldrc->markType))
1424 		lockmode = RowShareLock;
1425 	else
1426 		lockmode = AccessShareLock;
1427 
1428 	/* Scan for all members of inheritance set, acquire needed locks */
1429 	inhOIDs = find_all_inheritors(parentOID, lockmode, NULL);
1430 
1431 	/*
1432 	 * Check that there's at least one descendant, else treat as no-child
1433 	 * case.  This could happen despite above has_subclass() check, if table
1434 	 * once had a child but no longer does.
1435 	 */
1436 	if (list_length(inhOIDs) < 2)
1437 	{
1438 		/* Clear flag before returning */
1439 		rte->inh = false;
1440 		return;
1441 	}
1442 
1443 	/*
1444 	 * If parent relation is selected FOR UPDATE/SHARE, we need to mark its
1445 	 * PlanRowMark as isParent = true, and generate a new PlanRowMark for each
1446 	 * child.
1447 	 */
1448 	if (oldrc)
1449 		oldrc->isParent = true;
1450 
1451 	/*
1452 	 * Must open the parent relation to examine its tupdesc.  We need not lock
1453 	 * it; we assume the rewriter already did.
1454 	 */
1455 	oldrelation = heap_open(parentOID, NoLock);
1456 
1457 	/* Scan the inheritance set and expand it */
1458 	appinfos = NIL;
1459 	foreach(l, inhOIDs)
1460 	{
1461 		Oid			childOID = lfirst_oid(l);
1462 		Relation	newrelation;
1463 		RangeTblEntry *childrte;
1464 		Index		childRTindex;
1465 		AppendRelInfo *appinfo;
1466 
1467 		/* Open rel if needed; we already have required locks */
1468 		if (childOID != parentOID)
1469 			newrelation = heap_open(childOID, NoLock);
1470 		else
1471 			newrelation = oldrelation;
1472 
1473 		/*
1474 		 * It is possible that the parent table has children that are temp
1475 		 * tables of other backends.  We cannot safely access such tables
1476 		 * (because of buffering issues), and the best thing to do seems to be
1477 		 * to silently ignore them.
1478 		 */
1479 		if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation))
1480 		{
1481 			heap_close(newrelation, lockmode);
1482 			continue;
1483 		}
1484 
1485 		/*
1486 		 * Build an RTE for the child, and attach to query's rangetable list.
1487 		 * We copy most fields of the parent's RTE, but replace relation OID
1488 		 * and relkind, and set inh = false.  Also, set requiredPerms to zero
1489 		 * since all required permissions checks are done on the original RTE.
1490 		 */
1491 		childrte = copyObject(rte);
1492 		childrte->relid = childOID;
1493 		childrte->relkind = newrelation->rd_rel->relkind;
1494 		childrte->inh = false;
1495 		childrte->requiredPerms = 0;
1496 		parse->rtable = lappend(parse->rtable, childrte);
1497 		childRTindex = list_length(parse->rtable);
1498 
1499 		/*
1500 		 * Build an AppendRelInfo for this parent and child.
1501 		 */
1502 		appinfo = makeNode(AppendRelInfo);
1503 		appinfo->parent_relid = rti;
1504 		appinfo->child_relid = childRTindex;
1505 		appinfo->parent_reltype = oldrelation->rd_rel->reltype;
1506 		appinfo->child_reltype = newrelation->rd_rel->reltype;
1507 		make_inh_translation_list(oldrelation, newrelation, childRTindex,
1508 								  &appinfo->translated_vars);
1509 		appinfo->parent_reloid = parentOID;
1510 		appinfos = lappend(appinfos, appinfo);
1511 
1512 		/*
1513 		 * Translate the column permissions bitmaps to the child's attnums (we
1514 		 * have to build the translated_vars list before we can do this). But
1515 		 * if this is the parent table, leave copyObject's result alone.
1516 		 *
1517 		 * Note: we need to do this even though the executor won't run any
1518 		 * permissions checks on the child RTE.  The insertedCols/updatedCols
1519 		 * bitmaps may be examined for trigger-firing purposes.
1520 		 */
1521 		if (childOID != parentOID)
1522 		{
1523 			childrte->selectedCols = translate_col_privs(rte->selectedCols,
1524 												   appinfo->translated_vars);
1525 			childrte->insertedCols = translate_col_privs(rte->insertedCols,
1526 												   appinfo->translated_vars);
1527 			childrte->updatedCols = translate_col_privs(rte->updatedCols,
1528 												   appinfo->translated_vars);
1529 		}
1530 
1531 		/*
1532 		 * Build a PlanRowMark if parent is marked FOR UPDATE/SHARE.
1533 		 */
1534 		if (oldrc)
1535 		{
1536 			PlanRowMark *newrc = makeNode(PlanRowMark);
1537 
1538 			newrc->rti = childRTindex;
1539 			newrc->prti = rti;
1540 			newrc->rowmarkId = oldrc->rowmarkId;
1541 			/* Reselect rowmark type, because relkind might not match parent */
1542 			newrc->markType = select_rowmark_type(childrte, oldrc->strength);
1543 			newrc->allMarkTypes = (1 << newrc->markType);
1544 			newrc->strength = oldrc->strength;
1545 			newrc->waitPolicy = oldrc->waitPolicy;
1546 			newrc->isParent = false;
1547 
1548 			/* Include child's rowmark type in parent's allMarkTypes */
1549 			oldrc->allMarkTypes |= newrc->allMarkTypes;
1550 
1551 			root->rowMarks = lappend(root->rowMarks, newrc);
1552 		}
1553 
1554 		/* Close child relations, but keep locks */
1555 		if (childOID != parentOID)
1556 			heap_close(newrelation, NoLock);
1557 	}
1558 
1559 	heap_close(oldrelation, NoLock);
1560 
1561 	/*
1562 	 * If all the children were temp tables, pretend it's a non-inheritance
1563 	 * situation.  The duplicate RTE we added for the parent table is
1564 	 * harmless, so we don't bother to get rid of it.
1565 	 */
1566 	if (list_length(appinfos) < 2)
1567 	{
1568 		/* Clear flag before returning */
1569 		rte->inh = false;
1570 		return;
1571 	}
1572 
1573 	/* Otherwise, OK to add to root->append_rel_list */
1574 	root->append_rel_list = list_concat(root->append_rel_list, appinfos);
1575 }
1576 
1577 /*
1578  * make_inh_translation_list
1579  *	  Build the list of translations from parent Vars to child Vars for
1580  *	  an inheritance child.
1581  *
1582  * For paranoia's sake, we match type/collation as well as attribute name.
1583  */
1584 static void
make_inh_translation_list(Relation oldrelation,Relation newrelation,Index newvarno,List ** translated_vars)1585 make_inh_translation_list(Relation oldrelation, Relation newrelation,
1586 						  Index newvarno,
1587 						  List **translated_vars)
1588 {
1589 	List	   *vars = NIL;
1590 	TupleDesc	old_tupdesc = RelationGetDescr(oldrelation);
1591 	TupleDesc	new_tupdesc = RelationGetDescr(newrelation);
1592 	int			oldnatts = old_tupdesc->natts;
1593 	int			newnatts = new_tupdesc->natts;
1594 	int			old_attno;
1595 
1596 	for (old_attno = 0; old_attno < oldnatts; old_attno++)
1597 	{
1598 		Form_pg_attribute att;
1599 		char	   *attname;
1600 		Oid			atttypid;
1601 		int32		atttypmod;
1602 		Oid			attcollation;
1603 		int			new_attno;
1604 
1605 		att = old_tupdesc->attrs[old_attno];
1606 		if (att->attisdropped)
1607 		{
1608 			/* Just put NULL into this list entry */
1609 			vars = lappend(vars, NULL);
1610 			continue;
1611 		}
1612 		attname = NameStr(att->attname);
1613 		atttypid = att->atttypid;
1614 		atttypmod = att->atttypmod;
1615 		attcollation = att->attcollation;
1616 
1617 		/*
1618 		 * When we are generating the "translation list" for the parent table
1619 		 * of an inheritance set, no need to search for matches.
1620 		 */
1621 		if (oldrelation == newrelation)
1622 		{
1623 			vars = lappend(vars, makeVar(newvarno,
1624 										 (AttrNumber) (old_attno + 1),
1625 										 atttypid,
1626 										 atttypmod,
1627 										 attcollation,
1628 										 0));
1629 			continue;
1630 		}
1631 
1632 		/*
1633 		 * Otherwise we have to search for the matching column by name.
1634 		 * There's no guarantee it'll have the same column position, because
1635 		 * of cases like ALTER TABLE ADD COLUMN and multiple inheritance.
1636 		 * However, in simple cases it will be the same column number, so try
1637 		 * that before we go groveling through all the columns.
1638 		 *
1639 		 * Note: the test for (att = ...) != NULL cannot fail, it's just a
1640 		 * notational device to include the assignment into the if-clause.
1641 		 */
1642 		if (old_attno < newnatts &&
1643 			(att = new_tupdesc->attrs[old_attno]) != NULL &&
1644 			!att->attisdropped &&
1645 			strcmp(attname, NameStr(att->attname)) == 0)
1646 			new_attno = old_attno;
1647 		else
1648 		{
1649 			for (new_attno = 0; new_attno < newnatts; new_attno++)
1650 			{
1651 				att = new_tupdesc->attrs[new_attno];
1652 				if (!att->attisdropped &&
1653 					strcmp(attname, NameStr(att->attname)) == 0)
1654 					break;
1655 			}
1656 			if (new_attno >= newnatts)
1657 				elog(ERROR, "could not find inherited attribute \"%s\" of relation \"%s\"",
1658 					 attname, RelationGetRelationName(newrelation));
1659 		}
1660 
1661 		/* Found it, check type and collation match */
1662 		if (atttypid != att->atttypid || atttypmod != att->atttypmod)
1663 			elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's type",
1664 				 attname, RelationGetRelationName(newrelation));
1665 		if (attcollation != att->attcollation)
1666 			elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's collation",
1667 				 attname, RelationGetRelationName(newrelation));
1668 
1669 		vars = lappend(vars, makeVar(newvarno,
1670 									 (AttrNumber) (new_attno + 1),
1671 									 atttypid,
1672 									 atttypmod,
1673 									 attcollation,
1674 									 0));
1675 	}
1676 
1677 	*translated_vars = vars;
1678 }
1679 
1680 /*
1681  * translate_col_privs
1682  *	  Translate a bitmapset representing per-column privileges from the
1683  *	  parent rel's attribute numbering to the child's.
1684  *
1685  * The only surprise here is that we don't translate a parent whole-row
1686  * reference into a child whole-row reference.  That would mean requiring
1687  * permissions on all child columns, which is overly strict, since the
1688  * query is really only going to reference the inherited columns.  Instead
1689  * we set the per-column bits for all inherited columns.
1690  */
1691 static Bitmapset *
translate_col_privs(const Bitmapset * parent_privs,List * translated_vars)1692 translate_col_privs(const Bitmapset *parent_privs,
1693 					List *translated_vars)
1694 {
1695 	Bitmapset  *child_privs = NULL;
1696 	bool		whole_row;
1697 	int			attno;
1698 	ListCell   *lc;
1699 
1700 	/* System attributes have the same numbers in all tables */
1701 	for (attno = FirstLowInvalidHeapAttributeNumber + 1; attno < 0; attno++)
1702 	{
1703 		if (bms_is_member(attno - FirstLowInvalidHeapAttributeNumber,
1704 						  parent_privs))
1705 			child_privs = bms_add_member(child_privs,
1706 								 attno - FirstLowInvalidHeapAttributeNumber);
1707 	}
1708 
1709 	/* Check if parent has whole-row reference */
1710 	whole_row = bms_is_member(InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber,
1711 							  parent_privs);
1712 
1713 	/* And now translate the regular user attributes, using the vars list */
1714 	attno = InvalidAttrNumber;
1715 	foreach(lc, translated_vars)
1716 	{
1717 		Var		   *var = (Var *) lfirst(lc);
1718 
1719 		attno++;
1720 		if (var == NULL)		/* ignore dropped columns */
1721 			continue;
1722 		Assert(IsA(var, Var));
1723 		if (whole_row ||
1724 			bms_is_member(attno - FirstLowInvalidHeapAttributeNumber,
1725 						  parent_privs))
1726 			child_privs = bms_add_member(child_privs,
1727 						 var->varattno - FirstLowInvalidHeapAttributeNumber);
1728 	}
1729 
1730 	return child_privs;
1731 }
1732 
1733 /*
1734  * adjust_appendrel_attrs
1735  *	  Copy the specified query or expression and translate Vars referring
1736  *	  to the parent rel of the specified AppendRelInfo to refer to the
1737  *	  child rel instead.  We also update rtindexes appearing outside Vars,
1738  *	  such as resultRelation and jointree relids.
1739  *
1740  * Note: this is applied after conversion of sublinks to subplans in the
1741  * query jointree, but there may still be sublinks in the security barrier
1742  * quals of RTEs, so we do need to cope with recursion into sub-queries.
1743  *
1744  * Note: this is not hugely different from what pullup_replace_vars() does;
1745  * maybe we should try to fold the two routines together.
1746  */
1747 Node *
adjust_appendrel_attrs(PlannerInfo * root,Node * node,AppendRelInfo * appinfo)1748 adjust_appendrel_attrs(PlannerInfo *root, Node *node, AppendRelInfo *appinfo)
1749 {
1750 	Node	   *result;
1751 	adjust_appendrel_attrs_context context;
1752 
1753 	context.root = root;
1754 	context.appinfo = appinfo;
1755 	context.sublevels_up = 0;
1756 
1757 	/*
1758 	 * Must be prepared to start with a Query or a bare expression tree; if
1759 	 * it's a Query, go straight to query_tree_walker to make sure that
1760 	 * sublevels_up doesn't get incremented prematurely.
1761 	 */
1762 	if (node && IsA(node, Query))
1763 	{
1764 		Query	   *newnode;
1765 
1766 		newnode = query_tree_mutator((Query *) node,
1767 									 adjust_appendrel_attrs_mutator,
1768 									 (void *) &context,
1769 									 QTW_IGNORE_RC_SUBQUERIES);
1770 		if (newnode->resultRelation == appinfo->parent_relid)
1771 		{
1772 			newnode->resultRelation = appinfo->child_relid;
1773 			/* Fix tlist resnos too, if it's inherited UPDATE */
1774 			if (newnode->commandType == CMD_UPDATE)
1775 				newnode->targetList =
1776 					adjust_inherited_tlist(newnode->targetList,
1777 										   appinfo);
1778 		}
1779 		result = (Node *) newnode;
1780 	}
1781 	else
1782 		result = adjust_appendrel_attrs_mutator(node, &context);
1783 
1784 	return result;
1785 }
1786 
1787 static Node *
adjust_appendrel_attrs_mutator(Node * node,adjust_appendrel_attrs_context * context)1788 adjust_appendrel_attrs_mutator(Node *node,
1789 							   adjust_appendrel_attrs_context *context)
1790 {
1791 	AppendRelInfo *appinfo = context->appinfo;
1792 
1793 	if (node == NULL)
1794 		return NULL;
1795 	if (IsA(node, Var))
1796 	{
1797 		Var		   *var = (Var *) copyObject(node);
1798 
1799 		if (var->varlevelsup == context->sublevels_up &&
1800 			var->varno == appinfo->parent_relid)
1801 		{
1802 			var->varno = appinfo->child_relid;
1803 			var->varnoold = appinfo->child_relid;
1804 			if (var->varattno > 0)
1805 			{
1806 				Node	   *newnode;
1807 
1808 				if (var->varattno > list_length(appinfo->translated_vars))
1809 					elog(ERROR, "attribute %d of relation \"%s\" does not exist",
1810 						 var->varattno, get_rel_name(appinfo->parent_reloid));
1811 				newnode = copyObject(list_nth(appinfo->translated_vars,
1812 											  var->varattno - 1));
1813 				if (newnode == NULL)
1814 					elog(ERROR, "attribute %d of relation \"%s\" does not exist",
1815 						 var->varattno, get_rel_name(appinfo->parent_reloid));
1816 				((Var *) newnode)->varlevelsup += context->sublevels_up;
1817 				return newnode;
1818 			}
1819 			else if (var->varattno == 0)
1820 			{
1821 				/*
1822 				 * Whole-row Var: if we are dealing with named rowtypes, we
1823 				 * can use a whole-row Var for the child table plus a coercion
1824 				 * step to convert the tuple layout to the parent's rowtype.
1825 				 * Otherwise we have to generate a RowExpr.
1826 				 */
1827 				if (OidIsValid(appinfo->child_reltype))
1828 				{
1829 					Assert(var->vartype == appinfo->parent_reltype);
1830 					if (appinfo->parent_reltype != appinfo->child_reltype)
1831 					{
1832 						ConvertRowtypeExpr *r = makeNode(ConvertRowtypeExpr);
1833 
1834 						r->arg = (Expr *) var;
1835 						r->resulttype = appinfo->parent_reltype;
1836 						r->convertformat = COERCE_IMPLICIT_CAST;
1837 						r->location = -1;
1838 						/* Make sure the Var node has the right type ID, too */
1839 						var->vartype = appinfo->child_reltype;
1840 						return (Node *) r;
1841 					}
1842 				}
1843 				else
1844 				{
1845 					/*
1846 					 * Build a RowExpr containing the translated variables.
1847 					 *
1848 					 * In practice var->vartype will always be RECORDOID here,
1849 					 * so we need to come up with some suitable column names.
1850 					 * We use the parent RTE's column names.
1851 					 *
1852 					 * Note: we can't get here for inheritance cases, so there
1853 					 * is no need to worry that translated_vars might contain
1854 					 * some dummy NULLs.
1855 					 */
1856 					RowExpr    *rowexpr;
1857 					List	   *fields;
1858 					RangeTblEntry *rte;
1859 					ListCell   *lc;
1860 
1861 					rte = rt_fetch(appinfo->parent_relid,
1862 								   context->root->parse->rtable);
1863 					fields = (List *) copyObject(appinfo->translated_vars);
1864 					foreach(lc, fields)
1865 					{
1866 						Var		   *field = (Var *) lfirst(lc);
1867 
1868 						field->varlevelsup += context->sublevels_up;
1869 					}
1870 					rowexpr = makeNode(RowExpr);
1871 					rowexpr->args = fields;
1872 					rowexpr->row_typeid = var->vartype;
1873 					rowexpr->row_format = COERCE_IMPLICIT_CAST;
1874 					rowexpr->colnames = copyObject(rte->eref->colnames);
1875 					rowexpr->location = -1;
1876 
1877 					return (Node *) rowexpr;
1878 				}
1879 			}
1880 			/* system attributes don't need any other translation */
1881 		}
1882 		return (Node *) var;
1883 	}
1884 	if (IsA(node, CurrentOfExpr))
1885 	{
1886 		CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
1887 
1888 		if (context->sublevels_up == 0 &&
1889 			cexpr->cvarno == appinfo->parent_relid)
1890 			cexpr->cvarno = appinfo->child_relid;
1891 		return (Node *) cexpr;
1892 	}
1893 	if (IsA(node, RangeTblRef))
1894 	{
1895 		RangeTblRef *rtr = (RangeTblRef *) copyObject(node);
1896 
1897 		if (context->sublevels_up == 0 &&
1898 			rtr->rtindex == appinfo->parent_relid)
1899 			rtr->rtindex = appinfo->child_relid;
1900 		return (Node *) rtr;
1901 	}
1902 	if (IsA(node, JoinExpr))
1903 	{
1904 		/* Copy the JoinExpr node with correct mutation of subnodes */
1905 		JoinExpr   *j;
1906 
1907 		j = (JoinExpr *) expression_tree_mutator(node,
1908 											  adjust_appendrel_attrs_mutator,
1909 												 (void *) context);
1910 		/* now fix JoinExpr's rtindex (probably never happens) */
1911 		if (context->sublevels_up == 0 &&
1912 			j->rtindex == appinfo->parent_relid)
1913 			j->rtindex = appinfo->child_relid;
1914 		return (Node *) j;
1915 	}
1916 	if (IsA(node, PlaceHolderVar))
1917 	{
1918 		/* Copy the PlaceHolderVar node with correct mutation of subnodes */
1919 		PlaceHolderVar *phv;
1920 
1921 		phv = (PlaceHolderVar *) expression_tree_mutator(node,
1922 											  adjust_appendrel_attrs_mutator,
1923 														 (void *) context);
1924 		/* now fix PlaceHolderVar's relid sets */
1925 		if (phv->phlevelsup == context->sublevels_up)
1926 			phv->phrels = adjust_relid_set(phv->phrels,
1927 										   appinfo->parent_relid,
1928 										   appinfo->child_relid);
1929 		return (Node *) phv;
1930 	}
1931 	/* Shouldn't need to handle planner auxiliary nodes here */
1932 	Assert(!IsA(node, SpecialJoinInfo));
1933 	Assert(!IsA(node, AppendRelInfo));
1934 	Assert(!IsA(node, PlaceHolderInfo));
1935 	Assert(!IsA(node, MinMaxAggInfo));
1936 
1937 	/*
1938 	 * We have to process RestrictInfo nodes specially.  (Note: although
1939 	 * set_append_rel_pathlist will hide RestrictInfos in the parent's
1940 	 * baserestrictinfo list from us, it doesn't hide those in joininfo.)
1941 	 */
1942 	if (IsA(node, RestrictInfo))
1943 	{
1944 		RestrictInfo *oldinfo = (RestrictInfo *) node;
1945 		RestrictInfo *newinfo = makeNode(RestrictInfo);
1946 
1947 		/* Copy all flat-copiable fields */
1948 		memcpy(newinfo, oldinfo, sizeof(RestrictInfo));
1949 
1950 		/* Recursively fix the clause itself */
1951 		newinfo->clause = (Expr *)
1952 			adjust_appendrel_attrs_mutator((Node *) oldinfo->clause, context);
1953 
1954 		/* and the modified version, if an OR clause */
1955 		newinfo->orclause = (Expr *)
1956 			adjust_appendrel_attrs_mutator((Node *) oldinfo->orclause, context);
1957 
1958 		/* adjust relid sets too */
1959 		newinfo->clause_relids = adjust_relid_set(oldinfo->clause_relids,
1960 												  appinfo->parent_relid,
1961 												  appinfo->child_relid);
1962 		newinfo->required_relids = adjust_relid_set(oldinfo->required_relids,
1963 													appinfo->parent_relid,
1964 													appinfo->child_relid);
1965 		newinfo->outer_relids = adjust_relid_set(oldinfo->outer_relids,
1966 												 appinfo->parent_relid,
1967 												 appinfo->child_relid);
1968 		newinfo->nullable_relids = adjust_relid_set(oldinfo->nullable_relids,
1969 													appinfo->parent_relid,
1970 													appinfo->child_relid);
1971 		newinfo->left_relids = adjust_relid_set(oldinfo->left_relids,
1972 												appinfo->parent_relid,
1973 												appinfo->child_relid);
1974 		newinfo->right_relids = adjust_relid_set(oldinfo->right_relids,
1975 												 appinfo->parent_relid,
1976 												 appinfo->child_relid);
1977 
1978 		/*
1979 		 * Reset cached derivative fields, since these might need to have
1980 		 * different values when considering the child relation.  Note we
1981 		 * don't reset left_ec/right_ec: each child variable is implicitly
1982 		 * equivalent to its parent, so still a member of the same EC if any.
1983 		 */
1984 		newinfo->eval_cost.startup = -1;
1985 		newinfo->norm_selec = -1;
1986 		newinfo->outer_selec = -1;
1987 		newinfo->left_em = NULL;
1988 		newinfo->right_em = NULL;
1989 		newinfo->scansel_cache = NIL;
1990 		newinfo->left_bucketsize = -1;
1991 		newinfo->right_bucketsize = -1;
1992 
1993 		return (Node *) newinfo;
1994 	}
1995 
1996 	if (IsA(node, Query))
1997 	{
1998 		/*
1999 		 * Recurse into sublink subqueries. This should only be possible in
2000 		 * security barrier quals of top-level RTEs. All other sublinks should
2001 		 * have already been converted to subplans during expression
2002 		 * preprocessing, but this doesn't happen for security barrier quals,
2003 		 * since they are destined to become quals of a subquery RTE, which
2004 		 * will be recursively planned, and so should not be preprocessed at
2005 		 * this stage.
2006 		 *
2007 		 * We don't explicitly Assert() for securityQuals here simply because
2008 		 * it's not trivial to do so.
2009 		 */
2010 		Query	   *newnode;
2011 
2012 		context->sublevels_up++;
2013 		newnode = query_tree_mutator((Query *) node,
2014 									 adjust_appendrel_attrs_mutator,
2015 									 (void *) context, 0);
2016 		context->sublevels_up--;
2017 		return (Node *) newnode;
2018 	}
2019 
2020 	return expression_tree_mutator(node, adjust_appendrel_attrs_mutator,
2021 								   (void *) context);
2022 }
2023 
2024 /*
2025  * Substitute newrelid for oldrelid in a Relid set
2026  */
2027 static Relids
adjust_relid_set(Relids relids,Index oldrelid,Index newrelid)2028 adjust_relid_set(Relids relids, Index oldrelid, Index newrelid)
2029 {
2030 	if (bms_is_member(oldrelid, relids))
2031 	{
2032 		/* Ensure we have a modifiable copy */
2033 		relids = bms_copy(relids);
2034 		/* Remove old, add new */
2035 		relids = bms_del_member(relids, oldrelid);
2036 		relids = bms_add_member(relids, newrelid);
2037 	}
2038 	return relids;
2039 }
2040 
2041 /*
2042  * Adjust the targetlist entries of an inherited UPDATE operation
2043  *
2044  * The expressions have already been fixed, but we have to make sure that
2045  * the target resnos match the child table (they may not, in the case of
2046  * a column that was added after-the-fact by ALTER TABLE).  In some cases
2047  * this can force us to re-order the tlist to preserve resno ordering.
2048  * (We do all this work in special cases so that preptlist.c is fast for
2049  * the typical case.)
2050  *
2051  * The given tlist has already been through expression_tree_mutator;
2052  * therefore the TargetEntry nodes are fresh copies that it's okay to
2053  * scribble on.
2054  *
2055  * Note that this is not needed for INSERT because INSERT isn't inheritable.
2056  */
2057 static List *
adjust_inherited_tlist(List * tlist,AppendRelInfo * context)2058 adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
2059 {
2060 	bool		changed_it = false;
2061 	ListCell   *tl;
2062 	List	   *new_tlist;
2063 	bool		more;
2064 	int			attrno;
2065 
2066 	/* This should only happen for an inheritance case, not UNION ALL */
2067 	Assert(OidIsValid(context->parent_reloid));
2068 
2069 	/* Scan tlist and update resnos to match attnums of child rel */
2070 	foreach(tl, tlist)
2071 	{
2072 		TargetEntry *tle = (TargetEntry *) lfirst(tl);
2073 		Var		   *childvar;
2074 
2075 		if (tle->resjunk)
2076 			continue;			/* ignore junk items */
2077 
2078 		/* Look up the translation of this column: it must be a Var */
2079 		if (tle->resno <= 0 ||
2080 			tle->resno > list_length(context->translated_vars))
2081 			elog(ERROR, "attribute %d of relation \"%s\" does not exist",
2082 				 tle->resno, get_rel_name(context->parent_reloid));
2083 		childvar = (Var *) list_nth(context->translated_vars, tle->resno - 1);
2084 		if (childvar == NULL || !IsA(childvar, Var))
2085 			elog(ERROR, "attribute %d of relation \"%s\" does not exist",
2086 				 tle->resno, get_rel_name(context->parent_reloid));
2087 
2088 		if (tle->resno != childvar->varattno)
2089 		{
2090 			tle->resno = childvar->varattno;
2091 			changed_it = true;
2092 		}
2093 	}
2094 
2095 	/*
2096 	 * If we changed anything, re-sort the tlist by resno, and make sure
2097 	 * resjunk entries have resnos above the last real resno.  The sort
2098 	 * algorithm is a bit stupid, but for such a seldom-taken path, small is
2099 	 * probably better than fast.
2100 	 */
2101 	if (!changed_it)
2102 		return tlist;
2103 
2104 	new_tlist = NIL;
2105 	more = true;
2106 	for (attrno = 1; more; attrno++)
2107 	{
2108 		more = false;
2109 		foreach(tl, tlist)
2110 		{
2111 			TargetEntry *tle = (TargetEntry *) lfirst(tl);
2112 
2113 			if (tle->resjunk)
2114 				continue;		/* ignore junk items */
2115 
2116 			if (tle->resno == attrno)
2117 				new_tlist = lappend(new_tlist, tle);
2118 			else if (tle->resno > attrno)
2119 				more = true;
2120 		}
2121 	}
2122 
2123 	foreach(tl, tlist)
2124 	{
2125 		TargetEntry *tle = (TargetEntry *) lfirst(tl);
2126 
2127 		if (!tle->resjunk)
2128 			continue;			/* here, ignore non-junk items */
2129 
2130 		tle->resno = attrno;
2131 		new_tlist = lappend(new_tlist, tle);
2132 		attrno++;
2133 	}
2134 
2135 	return new_tlist;
2136 }
2137 
2138 /*
2139  * adjust_appendrel_attrs_multilevel
2140  *	  Apply Var translations from a toplevel appendrel parent down to a child.
2141  *
2142  * In some cases we need to translate expressions referencing a baserel
2143  * to reference an appendrel child that's multiple levels removed from it.
2144  */
2145 Node *
adjust_appendrel_attrs_multilevel(PlannerInfo * root,Node * node,RelOptInfo * child_rel)2146 adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
2147 								  RelOptInfo *child_rel)
2148 {
2149 	AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, child_rel);
2150 	RelOptInfo *parent_rel = find_base_rel(root, appinfo->parent_relid);
2151 
2152 	/* If parent is also a child, first recurse to apply its translations */
2153 	if (parent_rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
2154 		node = adjust_appendrel_attrs_multilevel(root, node, parent_rel);
2155 	else
2156 		Assert(parent_rel->reloptkind == RELOPT_BASEREL);
2157 	/* Now translate for this child */
2158 	return adjust_appendrel_attrs(root, node, appinfo);
2159 }
2160