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