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