PostgreSQL Source Code  git master
inherit.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * inherit.c
4  * Routines to process child relations in inheritance trees
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/optimizer/path/inherit.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/sysattr.h"
18 #include "access/table.h"
19 #include "catalog/partition.h"
20 #include "catalog/pg_inherits.h"
21 #include "catalog/pg_type.h"
22 #include "miscadmin.h"
23 #include "nodes/makefuncs.h"
24 #include "optimizer/appendinfo.h"
25 #include "optimizer/inherit.h"
26 #include "optimizer/optimizer.h"
27 #include "optimizer/pathnode.h"
28 #include "optimizer/planmain.h"
29 #include "optimizer/planner.h"
30 #include "optimizer/prep.h"
31 #include "optimizer/restrictinfo.h"
32 #include "parser/parsetree.h"
33 #include "partitioning/partdesc.h"
34 #include "partitioning/partprune.h"
35 #include "utils/rel.h"
36 
37 
38 static void expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo,
39  RangeTblEntry *parentrte,
40  Index parentRTindex, Relation parentrel,
41  PlanRowMark *top_parentrc, LOCKMODE lockmode);
43  RangeTblEntry *parentrte,
44  Index parentRTindex, Relation parentrel,
45  PlanRowMark *top_parentrc, Relation childrel,
46  RangeTblEntry **childrte_p,
47  Index *childRTindex_p);
48 static Bitmapset *translate_col_privs(const Bitmapset *parent_privs,
49  List *translated_vars);
50 static void expand_appendrel_subquery(PlannerInfo *root, RelOptInfo *rel,
51  RangeTblEntry *rte, Index rti);
52 
53 
54 /*
55  * expand_inherited_rtentry
56  * Expand a rangetable entry that has the "inh" bit set.
57  *
58  * "inh" is only allowed in two cases: RELATION and SUBQUERY RTEs.
59  *
60  * "inh" on a plain RELATION RTE means that it is a partitioned table or the
61  * parent of a traditional-inheritance set. In this case we must add entries
62  * for all the interesting child tables to the query's rangetable, and build
63  * additional planner data structures for them, including RelOptInfos,
64  * AppendRelInfos, and possibly PlanRowMarks.
65  *
66  * Note that the original RTE is considered to represent the whole inheritance
67  * set. In the case of traditional inheritance, the first of the generated
68  * RTEs is an RTE for the same table, but with inh = false, to represent the
69  * parent table in its role as a simple member of the inheritance set. For
70  * partitioning, we don't need a second RTE because the partitioned table
71  * itself has no data and need not be scanned.
72  *
73  * "inh" on a SUBQUERY RTE means that it's the parent of a UNION ALL group,
74  * which is treated as an appendrel similarly to inheritance cases; however,
75  * we already made RTEs and AppendRelInfos for the subqueries. We only need
76  * to build RelOptInfos for them, which is done by expand_appendrel_subquery.
77  */
78 void
80  RangeTblEntry *rte, Index rti)
81 {
82  Oid parentOID;
83  Relation oldrelation;
84  LOCKMODE lockmode;
85  PlanRowMark *oldrc;
86  bool old_isParent = false;
87  int old_allMarkTypes = 0;
88 
89  Assert(rte->inh); /* else caller error */
90 
91  if (rte->rtekind == RTE_SUBQUERY)
92  {
93  expand_appendrel_subquery(root, rel, rte, rti);
94  return;
95  }
96 
97  Assert(rte->rtekind == RTE_RELATION);
98 
99  parentOID = rte->relid;
100 
101  /*
102  * We used to check has_subclass() here, but there's no longer any need
103  * to, because subquery_planner already did.
104  */
105 
106  /*
107  * The rewriter should already have obtained an appropriate lock on each
108  * relation named in the query, so we can open the parent relation without
109  * locking it. However, for each child relation we add to the query, we
110  * must obtain an appropriate lock, because this will be the first use of
111  * those relations in the parse/rewrite/plan pipeline. Child rels should
112  * use the same lockmode as their parent.
113  */
114  oldrelation = table_open(parentOID, NoLock);
115  lockmode = rte->rellockmode;
116 
117  /*
118  * If parent relation is selected FOR UPDATE/SHARE, we need to mark its
119  * PlanRowMark as isParent = true, and generate a new PlanRowMark for each
120  * child.
121  */
122  oldrc = get_plan_rowmark(root->rowMarks, rti);
123  if (oldrc)
124  {
125  old_isParent = oldrc->isParent;
126  oldrc->isParent = true;
127  /* Save initial value of allMarkTypes before children add to it */
128  old_allMarkTypes = oldrc->allMarkTypes;
129  }
130 
131  /* Scan the inheritance set and expand it */
132  if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
133  {
134  /*
135  * Partitioned table, so set up for partitioning.
136  */
137  Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
138 
139  /*
140  * Recursively expand and lock the partitions. While at it, also
141  * extract the partition key columns of all the partitioned tables.
142  */
143  expand_partitioned_rtentry(root, rel, rte, rti,
144  oldrelation, oldrc, lockmode);
145  }
146  else
147  {
148  /*
149  * Ordinary table, so process traditional-inheritance children. (Note
150  * that partitioned tables are not allowed to have inheritance
151  * children, so it's not possible for both cases to apply.)
152  */
153  List *inhOIDs;
154  ListCell *l;
155 
156  /* Scan for all members of inheritance set, acquire needed locks */
157  inhOIDs = find_all_inheritors(parentOID, lockmode, NULL);
158 
159  /*
160  * We used to special-case the situation where the table no longer has
161  * any children, by clearing rte->inh and exiting. That no longer
162  * works, because this function doesn't get run until after decisions
163  * have been made that depend on rte->inh. We have to treat such
164  * situations as normal inheritance. The table itself should always
165  * have been found, though.
166  */
167  Assert(inhOIDs != NIL);
168  Assert(linitial_oid(inhOIDs) == parentOID);
169 
170  /* Expand simple_rel_array and friends to hold child objects. */
171  expand_planner_arrays(root, list_length(inhOIDs));
172 
173  /*
174  * Expand inheritance children in the order the OIDs were returned by
175  * find_all_inheritors.
176  */
177  foreach(l, inhOIDs)
178  {
179  Oid childOID = lfirst_oid(l);
180  Relation newrelation;
181  RangeTblEntry *childrte;
182  Index childRTindex;
183 
184  /* Open rel if needed; we already have required locks */
185  if (childOID != parentOID)
186  newrelation = table_open(childOID, NoLock);
187  else
188  newrelation = oldrelation;
189 
190  /*
191  * It is possible that the parent table has children that are temp
192  * tables of other backends. We cannot safely access such tables
193  * (because of buffering issues), and the best thing to do seems
194  * to be to silently ignore them.
195  */
196  if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation))
197  {
198  table_close(newrelation, lockmode);
199  continue;
200  }
201 
202  /* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
203  expand_single_inheritance_child(root, rte, rti, oldrelation,
204  oldrc, newrelation,
205  &childrte, &childRTindex);
206 
207  /* Create the otherrel RelOptInfo too. */
208  (void) build_simple_rel(root, childRTindex, rel);
209 
210  /* Close child relations, but keep locks */
211  if (childOID != parentOID)
212  table_close(newrelation, NoLock);
213  }
214  }
215 
216  /*
217  * Some children might require different mark types, which would've been
218  * reported into oldrc. If so, add relevant entries to the top-level
219  * targetlist and update parent rel's reltarget. This should match what
220  * preprocess_targetlist() would have added if the mark types had been
221  * requested originally.
222  *
223  * (Someday it might be useful to fold these resjunk columns into the
224  * row-identity-column management used for UPDATE/DELETE. Today is not
225  * that day, however.)
226  */
227  if (oldrc)
228  {
229  int new_allMarkTypes = oldrc->allMarkTypes;
230  Var *var;
231  TargetEntry *tle;
232  char resname[32];
233  List *newvars = NIL;
234 
235  /* The old PlanRowMark should already have necessitated adding TID */
236  Assert(old_allMarkTypes & ~(1 << ROW_MARK_COPY));
237 
238  /* Add whole-row junk Var if needed, unless we had it already */
239  if ((new_allMarkTypes & (1 << ROW_MARK_COPY)) &&
240  !(old_allMarkTypes & (1 << ROW_MARK_COPY)))
241  {
242  var = makeWholeRowVar(planner_rt_fetch(oldrc->rti, root),
243  oldrc->rti,
244  0,
245  false);
246  snprintf(resname, sizeof(resname), "wholerow%u", oldrc->rowmarkId);
247  tle = makeTargetEntry((Expr *) var,
248  list_length(root->processed_tlist) + 1,
249  pstrdup(resname),
250  true);
251  root->processed_tlist = lappend(root->processed_tlist, tle);
252  newvars = lappend(newvars, var);
253  }
254 
255  /* Add tableoid junk Var, unless we had it already */
256  if (!old_isParent)
257  {
258  var = makeVar(oldrc->rti,
260  OIDOID,
261  -1,
262  InvalidOid,
263  0);
264  snprintf(resname, sizeof(resname), "tableoid%u", oldrc->rowmarkId);
265  tle = makeTargetEntry((Expr *) var,
266  list_length(root->processed_tlist) + 1,
267  pstrdup(resname),
268  true);
269  root->processed_tlist = lappend(root->processed_tlist, tle);
270  newvars = lappend(newvars, var);
271  }
272 
273  /*
274  * Add the newly added Vars to parent's reltarget. We needn't worry
275  * about the children's reltargets, they'll be made later.
276  */
277  add_vars_to_targetlist(root, newvars, bms_make_singleton(0), false);
278  }
279 
280  table_close(oldrelation, NoLock);
281 }
282 
283 /*
284  * expand_partitioned_rtentry
285  * Recursively expand an RTE for a partitioned table.
286  */
287 static void
289  RangeTblEntry *parentrte,
290  Index parentRTindex, Relation parentrel,
291  PlanRowMark *top_parentrc, LOCKMODE lockmode)
292 {
293  PartitionDesc partdesc;
294  Bitmapset *live_parts;
295  int num_live_parts;
296  int i;
297 
299 
300  Assert(parentrte->inh);
301 
303  parentrel);
304 
305  /* A partitioned table should always have a partition descriptor. */
306  Assert(partdesc);
307 
308  /*
309  * Note down whether any partition key cols are being updated. Though it's
310  * the root partitioned table's updatedCols we are interested in, we
311  * instead use parentrte to get the updatedCols. This is convenient
312  * because parentrte already has the root partrel's updatedCols translated
313  * to match the attribute ordering of parentrel.
314  */
315  if (!root->partColsUpdated)
316  root->partColsUpdated =
317  has_partition_attrs(parentrel, parentrte->updatedCols, NULL);
318 
319  /*
320  * There shouldn't be any generated columns in the partition key.
321  */
322  Assert(!has_partition_attrs(parentrel, parentrte->extraUpdatedCols, NULL));
323 
324  /* Nothing further to do here if there are no partitions. */
325  if (partdesc->nparts == 0)
326  return;
327 
328  /*
329  * Perform partition pruning using restriction clauses assigned to parent
330  * relation. live_parts will contain PartitionDesc indexes of partitions
331  * that survive pruning. Below, we will initialize child objects for the
332  * surviving partitions.
333  */
334  live_parts = prune_append_rel_partitions(relinfo);
335 
336  /* Expand simple_rel_array and friends to hold child objects. */
337  num_live_parts = bms_num_members(live_parts);
338  if (num_live_parts > 0)
339  expand_planner_arrays(root, num_live_parts);
340 
341  /*
342  * We also store partition RelOptInfo pointers in the parent relation.
343  * Since we're palloc0'ing, slots corresponding to pruned partitions will
344  * contain NULL.
345  */
346  Assert(relinfo->part_rels == NULL);
347  relinfo->part_rels = (RelOptInfo **)
348  palloc0(relinfo->nparts * sizeof(RelOptInfo *));
349 
350  /*
351  * Create a child RTE for each live partition. Note that unlike
352  * traditional inheritance, we don't need a child RTE for the partitioned
353  * table itself, because it's not going to be scanned.
354  */
355  i = -1;
356  while ((i = bms_next_member(live_parts, i)) >= 0)
357  {
358  Oid childOID = partdesc->oids[i];
359  Relation childrel;
360  RangeTblEntry *childrte;
361  Index childRTindex;
362  RelOptInfo *childrelinfo;
363 
364  /* Open rel, acquiring required locks */
365  childrel = table_open(childOID, lockmode);
366 
367  /*
368  * Temporary partitions belonging to other sessions should have been
369  * disallowed at definition, but for paranoia's sake, let's double
370  * check.
371  */
372  if (RELATION_IS_OTHER_TEMP(childrel))
373  elog(ERROR, "temporary relation from another session found as partition");
374 
375  /* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
376  expand_single_inheritance_child(root, parentrte, parentRTindex,
377  parentrel, top_parentrc, childrel,
378  &childrte, &childRTindex);
379 
380  /* Create the otherrel RelOptInfo too. */
381  childrelinfo = build_simple_rel(root, childRTindex, relinfo);
382  relinfo->part_rels[i] = childrelinfo;
383  relinfo->all_partrels = bms_add_members(relinfo->all_partrels,
384  childrelinfo->relids);
385 
386  /* If this child is itself partitioned, recurse */
387  if (childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
388  expand_partitioned_rtentry(root, childrelinfo,
389  childrte, childRTindex,
390  childrel, top_parentrc, lockmode);
391 
392  /* Close child relation, but keep locks */
393  table_close(childrel, NoLock);
394  }
395 }
396 
397 /*
398  * expand_single_inheritance_child
399  * Build a RangeTblEntry and an AppendRelInfo, plus maybe a PlanRowMark.
400  *
401  * We now expand the partition hierarchy level by level, creating a
402  * corresponding hierarchy of AppendRelInfos and RelOptInfos, where each
403  * partitioned descendant acts as a parent of its immediate partitions.
404  * (This is a difference from what older versions of PostgreSQL did and what
405  * is still done in the case of table inheritance for unpartitioned tables,
406  * where the hierarchy is flattened during RTE expansion.)
407  *
408  * PlanRowMarks still carry the top-parent's RTI, and the top-parent's
409  * allMarkTypes field still accumulates values from all descendents.
410  *
411  * "parentrte" and "parentRTindex" are immediate parent's RTE and
412  * RTI. "top_parentrc" is top parent's PlanRowMark.
413  *
414  * The child RangeTblEntry and its RTI are returned in "childrte_p" and
415  * "childRTindex_p" resp.
416  */
417 static void
419  Index parentRTindex, Relation parentrel,
420  PlanRowMark *top_parentrc, Relation childrel,
421  RangeTblEntry **childrte_p,
422  Index *childRTindex_p)
423 {
424  Query *parse = root->parse;
425  Oid parentOID = RelationGetRelid(parentrel);
426  Oid childOID = RelationGetRelid(childrel);
427  RangeTblEntry *childrte;
428  Index childRTindex;
429  AppendRelInfo *appinfo;
430  TupleDesc child_tupdesc;
431  List *parent_colnames;
432  List *child_colnames;
433 
434  /*
435  * Build an RTE for the child, and attach to query's rangetable list. We
436  * copy most scalar fields of the parent's RTE, but replace relation OID,
437  * relkind, and inh for the child. Also, set requiredPerms to zero since
438  * all required permissions checks are done on the original RTE. Likewise,
439  * set the child's securityQuals to empty, because we only want to apply
440  * the parent's RLS conditions regardless of what RLS properties
441  * individual children may have. (This is an intentional choice to make
442  * inherited RLS work like regular permissions checks.) The parent
443  * securityQuals will be propagated to children along with other base
444  * restriction clauses, so we don't need to do it here. Other
445  * infrastructure of the parent RTE has to be translated to match the
446  * child table's column ordering, which we do below, so a "flat" copy is
447  * sufficient to start with.
448  */
449  childrte = makeNode(RangeTblEntry);
450  memcpy(childrte, parentrte, sizeof(RangeTblEntry));
451  Assert(parentrte->rtekind == RTE_RELATION); /* else this is dubious */
452  childrte->relid = childOID;
453  childrte->relkind = childrel->rd_rel->relkind;
454  /* A partitioned child will need to be expanded further. */
455  if (childrte->relkind == RELKIND_PARTITIONED_TABLE)
456  {
457  Assert(childOID != parentOID);
458  childrte->inh = true;
459  }
460  else
461  childrte->inh = false;
462  childrte->requiredPerms = 0;
463  childrte->securityQuals = NIL;
464 
465  /* Link not-yet-fully-filled child RTE into data structures */
466  parse->rtable = lappend(parse->rtable, childrte);
467  childRTindex = list_length(parse->rtable);
468  *childrte_p = childrte;
469  *childRTindex_p = childRTindex;
470 
471  /*
472  * Build an AppendRelInfo struct for each parent/child pair.
473  */
474  appinfo = make_append_rel_info(parentrel, childrel,
475  parentRTindex, childRTindex);
476  root->append_rel_list = lappend(root->append_rel_list, appinfo);
477 
478  /* tablesample is probably null, but copy it */
479  childrte->tablesample = copyObject(parentrte->tablesample);
480 
481  /*
482  * Construct an alias clause for the child, which we can also use as eref.
483  * This is important so that EXPLAIN will print the right column aliases
484  * for child-table columns. (Since ruleutils.c doesn't have any easy way
485  * to reassociate parent and child columns, we must get the child column
486  * aliases right to start with. Note that setting childrte->alias forces
487  * ruleutils.c to use these column names, which it otherwise would not.)
488  */
489  child_tupdesc = RelationGetDescr(childrel);
490  parent_colnames = parentrte->eref->colnames;
491  child_colnames = NIL;
492  for (int cattno = 0; cattno < child_tupdesc->natts; cattno++)
493  {
494  Form_pg_attribute att = TupleDescAttr(child_tupdesc, cattno);
495  const char *attname;
496 
497  if (att->attisdropped)
498  {
499  /* Always insert an empty string for a dropped column */
500  attname = "";
501  }
502  else if (appinfo->parent_colnos[cattno] > 0 &&
503  appinfo->parent_colnos[cattno] <= list_length(parent_colnames))
504  {
505  /* Duplicate the query-assigned name for the parent column */
506  attname = strVal(list_nth(parent_colnames,
507  appinfo->parent_colnos[cattno] - 1));
508  }
509  else
510  {
511  /* New column, just use its real name */
512  attname = NameStr(att->attname);
513  }
514  child_colnames = lappend(child_colnames, makeString(pstrdup(attname)));
515  }
516 
517  /*
518  * We just duplicate the parent's table alias name for each child. If the
519  * plan gets printed, ruleutils.c has to sort out unique table aliases to
520  * use, which it can handle.
521  */
522  childrte->alias = childrte->eref = makeAlias(parentrte->eref->aliasname,
523  child_colnames);
524 
525  /*
526  * Translate the column permissions bitmaps to the child's attnums (we
527  * have to build the translated_vars list before we can do this). But if
528  * this is the parent table, we can just duplicate the parent's bitmaps.
529  *
530  * Note: we need to do this even though the executor won't run any
531  * permissions checks on the child RTE. The insertedCols/updatedCols
532  * bitmaps may be examined for trigger-firing purposes.
533  */
534  if (childOID != parentOID)
535  {
536  childrte->selectedCols = translate_col_privs(parentrte->selectedCols,
537  appinfo->translated_vars);
538  childrte->insertedCols = translate_col_privs(parentrte->insertedCols,
539  appinfo->translated_vars);
540  childrte->updatedCols = translate_col_privs(parentrte->updatedCols,
541  appinfo->translated_vars);
543  appinfo->translated_vars);
544  }
545  else
546  {
547  childrte->selectedCols = bms_copy(parentrte->selectedCols);
548  childrte->insertedCols = bms_copy(parentrte->insertedCols);
549  childrte->updatedCols = bms_copy(parentrte->updatedCols);
550  childrte->extraUpdatedCols = bms_copy(parentrte->extraUpdatedCols);
551  }
552 
553  /*
554  * Store the RTE and appinfo in the respective PlannerInfo arrays, which
555  * the caller must already have allocated space for.
556  */
557  Assert(childRTindex < root->simple_rel_array_size);
558  Assert(root->simple_rte_array[childRTindex] == NULL);
559  root->simple_rte_array[childRTindex] = childrte;
560  Assert(root->append_rel_array[childRTindex] == NULL);
561  root->append_rel_array[childRTindex] = appinfo;
562 
563  /*
564  * Build a PlanRowMark if parent is marked FOR UPDATE/SHARE.
565  */
566  if (top_parentrc)
567  {
568  PlanRowMark *childrc = makeNode(PlanRowMark);
569 
570  childrc->rti = childRTindex;
571  childrc->prti = top_parentrc->rti;
572  childrc->rowmarkId = top_parentrc->rowmarkId;
573  /* Reselect rowmark type, because relkind might not match parent */
574  childrc->markType = select_rowmark_type(childrte,
575  top_parentrc->strength);
576  childrc->allMarkTypes = (1 << childrc->markType);
577  childrc->strength = top_parentrc->strength;
578  childrc->waitPolicy = top_parentrc->waitPolicy;
579 
580  /*
581  * We mark RowMarks for partitioned child tables as parent RowMarks so
582  * that the executor ignores them (except their existence means that
583  * the child tables will be locked using the appropriate mode).
584  */
585  childrc->isParent = (childrte->relkind == RELKIND_PARTITIONED_TABLE);
586 
587  /* Include child's rowmark type in top parent's allMarkTypes */
588  top_parentrc->allMarkTypes |= childrc->allMarkTypes;
589 
590  root->rowMarks = lappend(root->rowMarks, childrc);
591  }
592 
593  /*
594  * If we are creating a child of the query target relation (only possible
595  * in UPDATE/DELETE), add it to all_result_relids, as well as
596  * leaf_result_relids if appropriate, and make sure that we generate
597  * required row-identity data.
598  */
599  if (bms_is_member(parentRTindex, root->all_result_relids))
600  {
601  /* OK, record the child as a result rel too. */
603  childRTindex);
604 
605  /* Non-leaf partitions don't need any row identity info. */
606  if (childrte->relkind != RELKIND_PARTITIONED_TABLE)
607  {
608  Var *rrvar;
609 
611  childRTindex);
612 
613  /*
614  * If we have any child target relations, assume they all need to
615  * generate a junk "tableoid" column. (If only one child survives
616  * pruning, we wouldn't really need this, but it's not worth
617  * thrashing about to avoid it.)
618  */
619  rrvar = makeVar(childRTindex,
621  OIDOID,
622  -1,
623  InvalidOid,
624  0);
625  add_row_identity_var(root, rrvar, childRTindex, "tableoid");
626 
627  /* Register any row-identity columns needed by this child. */
628  add_row_identity_columns(root, childRTindex,
629  childrte, childrel);
630  }
631  }
632 }
633 
634 /*
635  * translate_col_privs
636  * Translate a bitmapset representing per-column privileges from the
637  * parent rel's attribute numbering to the child's.
638  *
639  * The only surprise here is that we don't translate a parent whole-row
640  * reference into a child whole-row reference. That would mean requiring
641  * permissions on all child columns, which is overly strict, since the
642  * query is really only going to reference the inherited columns. Instead
643  * we set the per-column bits for all inherited columns.
644  */
645 static Bitmapset *
646 translate_col_privs(const Bitmapset *parent_privs,
647  List *translated_vars)
648 {
649  Bitmapset *child_privs = NULL;
650  bool whole_row;
651  int attno;
652  ListCell *lc;
653 
654  /* System attributes have the same numbers in all tables */
655  for (attno = FirstLowInvalidHeapAttributeNumber + 1; attno < 0; attno++)
656  {
658  parent_privs))
659  child_privs = bms_add_member(child_privs,
661  }
662 
663  /* Check if parent has whole-row reference */
665  parent_privs);
666 
667  /* And now translate the regular user attributes, using the vars list */
668  attno = InvalidAttrNumber;
669  foreach(lc, translated_vars)
670  {
671  Var *var = lfirst_node(Var, lc);
672 
673  attno++;
674  if (var == NULL) /* ignore dropped columns */
675  continue;
676  if (whole_row ||
678  parent_privs))
679  child_privs = bms_add_member(child_privs,
681  }
682 
683  return child_privs;
684 }
685 
686 /*
687  * expand_appendrel_subquery
688  * Add "other rel" RelOptInfos for the children of an appendrel baserel
689  *
690  * "rel" is a subquery relation that has the rte->inh flag set, meaning it
691  * is a UNION ALL subquery that's been flattened into an appendrel, with
692  * child subqueries listed in root->append_rel_list. We need to build
693  * a RelOptInfo for each child relation so that we can plan scans on them.
694  */
695 static void
697  RangeTblEntry *rte, Index rti)
698 {
699  ListCell *l;
700 
701  foreach(l, root->append_rel_list)
702  {
703  AppendRelInfo *appinfo = (AppendRelInfo *) lfirst(l);
704  Index childRTindex = appinfo->child_relid;
705  RangeTblEntry *childrte;
706  RelOptInfo *childrel;
707 
708  /* append_rel_list contains all append rels; ignore others */
709  if (appinfo->parent_relid != rti)
710  continue;
711 
712  /* find the child RTE, which should already exist */
713  Assert(childRTindex < root->simple_rel_array_size);
714  childrte = root->simple_rte_array[childRTindex];
715  Assert(childrte != NULL);
716 
717  /* Build the child RelOptInfo. */
718  childrel = build_simple_rel(root, childRTindex, rel);
719 
720  /* Child may itself be an inherited rel, either table or subquery. */
721  if (childrte->inh)
722  expand_inherited_rtentry(root, childrel, childrte, childRTindex);
723  }
724 }
725 
726 
727 /*
728  * apply_child_basequals
729  * Populate childrel's base restriction quals from parent rel's quals,
730  * translating them using appinfo.
731  *
732  * If any of the resulting clauses evaluate to constant false or NULL, we
733  * return false and don't apply any quals. Caller should mark the relation as
734  * a dummy rel in this case, since it doesn't need to be scanned.
735  */
736 bool
738  RelOptInfo *childrel, RangeTblEntry *childRTE,
739  AppendRelInfo *appinfo)
740 {
741  List *childquals;
742  Index cq_min_security;
743  ListCell *lc;
744 
745  /*
746  * The child rel's targetlist might contain non-Var expressions, which
747  * means that substitution into the quals could produce opportunities for
748  * const-simplification, and perhaps even pseudoconstant quals. Therefore,
749  * transform each RestrictInfo separately to see if it reduces to a
750  * constant or pseudoconstant. (We must process them separately to keep
751  * track of the security level of each qual.)
752  */
753  childquals = NIL;
754  cq_min_security = UINT_MAX;
755  foreach(lc, parentrel->baserestrictinfo)
756  {
757  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
758  Node *childqual;
759  ListCell *lc2;
760 
761  Assert(IsA(rinfo, RestrictInfo));
762  childqual = adjust_appendrel_attrs(root,
763  (Node *) rinfo->clause,
764  1, &appinfo);
765  childqual = eval_const_expressions(root, childqual);
766  /* check for flat-out constant */
767  if (childqual && IsA(childqual, Const))
768  {
769  if (((Const *) childqual)->constisnull ||
770  !DatumGetBool(((Const *) childqual)->constvalue))
771  {
772  /* Restriction reduces to constant FALSE or NULL */
773  return false;
774  }
775  /* Restriction reduces to constant TRUE, so drop it */
776  continue;
777  }
778  /* might have gotten an AND clause, if so flatten it */
779  foreach(lc2, make_ands_implicit((Expr *) childqual))
780  {
781  Node *onecq = (Node *) lfirst(lc2);
782  bool pseudoconstant;
783 
784  /* check for pseudoconstant (no Vars or volatile functions) */
785  pseudoconstant =
786  !contain_vars_of_level(onecq, 0) &&
788  if (pseudoconstant)
789  {
790  /* tell createplan.c to check for gating quals */
791  root->hasPseudoConstantQuals = true;
792  }
793  /* reconstitute RestrictInfo with appropriate properties */
794  childquals = lappend(childquals,
795  make_restrictinfo(root,
796  (Expr *) onecq,
797  rinfo->is_pushed_down,
798  rinfo->outerjoin_delayed,
799  pseudoconstant,
800  rinfo->security_level,
801  NULL, NULL, NULL));
802  /* track minimum security level among child quals */
803  cq_min_security = Min(cq_min_security, rinfo->security_level);
804  }
805  }
806 
807  /*
808  * In addition to the quals inherited from the parent, we might have
809  * securityQuals associated with this particular child node. (Currently
810  * this can only happen in appendrels originating from UNION ALL;
811  * inheritance child tables don't have their own securityQuals, see
812  * expand_single_inheritance_child().) Pull any such securityQuals up
813  * into the baserestrictinfo for the child. This is similar to
814  * process_security_barrier_quals() for the parent rel, except that we
815  * can't make any general deductions from such quals, since they don't
816  * hold for the whole appendrel.
817  */
818  if (childRTE->securityQuals)
819  {
820  Index security_level = 0;
821 
822  foreach(lc, childRTE->securityQuals)
823  {
824  List *qualset = (List *) lfirst(lc);
825  ListCell *lc2;
826 
827  foreach(lc2, qualset)
828  {
829  Expr *qual = (Expr *) lfirst(lc2);
830 
831  /* not likely that we'd see constants here, so no check */
832  childquals = lappend(childquals,
833  make_restrictinfo(root, qual,
834  true, false, false,
835  security_level,
836  NULL, NULL, NULL));
837  cq_min_security = Min(cq_min_security, security_level);
838  }
839  security_level++;
840  }
841  Assert(security_level <= root->qual_security_level);
842  }
843 
844  /*
845  * OK, we've got all the baserestrictinfo quals for this child.
846  */
847  childrel->baserestrictinfo = childquals;
848  childrel->baserestrict_min_security = cq_min_security;
849 
850  return true;
851 }
static Bitmapset * translate_col_privs(const Bitmapset *parent_privs, List *translated_vars)
Definition: inherit.c:646
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:65
List * rowMarks
Definition: pathnodes.h:287
Relids all_result_relids
Definition: pathnodes.h:275
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Query * parse
Definition: pathnodes.h:161
Index security_level
Definition: pathnodes.h:2060
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
RowMarkType markType
Definition: plannodes.h:1120
Bitmapset * bms_copy(const Bitmapset *a)
Definition: bitmapset.c:74
Alias * alias
Definition: parsenodes.h:1140
List * colnames
Definition: primnodes.h:43
#define RelationGetDescr(relation)
Definition: rel.h:483
int LOCKMODE
Definition: lockdefs.h:26
AttrNumber * parent_colnos
Definition: pathnodes.h:2332
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
RowMarkType select_rowmark_type(RangeTblEntry *rte, LockClauseStrength strength)
Definition: planner.c:2230
List * securityQuals
Definition: parsenodes.h:1151
char * pstrdup(const char *in)
Definition: mcxt.c:1299
List * baserestrictinfo
Definition: pathnodes.h:740
#define Min(x, y)
Definition: c.h:986
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
Definition: nodes.h:539
#define strVal(v)
Definition: value.h:54
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:133
Index prti
Definition: plannodes.h:1118
AttrNumber varattno
Definition: primnodes.h:191
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2090
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
Index baserestrict_min_security
Definition: pathnodes.h:742
AclMode requiredPerms
Definition: parsenodes.h:1145
Relids all_partrels
Definition: pathnodes.h:765
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:448
static void expand_appendrel_subquery(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
Definition: inherit.c:696
Form_pg_class rd_rel
Definition: rel.h:110
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:186
Index rowmarkId
Definition: plannodes.h:1119
LockWaitPolicy waitPolicy
Definition: plannodes.h:1123
List * translated_vars
Definition: pathnodes.h:2323
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed, bool create_new_ph)
Definition: initsplan.c:230
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:387
bool apply_child_basequals(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, RangeTblEntry *childRTE, AppendRelInfo *appinfo)
Definition: inherit.c:737
Bitmapset * extraUpdatedCols
Definition: parsenodes.h:1150
Bitmapset * selectedCols
Definition: parsenodes.h:1147
static void expand_single_inheritance_child(PlannerInfo *root, RangeTblEntry *parentrte, Index parentRTindex, Relation parentrel, PlanRowMark *top_parentrc, Relation childrel, RangeTblEntry **childrte_p, Index *childRTindex_p)
Definition: inherit.c:418
List * rtable
Definition: parsenodes.h:147
#define ERROR
Definition: elog.h:46
NameData attname
Definition: pg_attribute.h:41
static void * list_nth(const List *list, int n)
Definition: pg_list.h:278
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:383
bool outerjoin_delayed
Definition: pathnodes.h:2049
#define lfirst_node(type, lc)
Definition: pg_list.h:172
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:646
bool has_partition_attrs(Relation rel, Bitmapset *attnums, bool *used_in_expr)
Definition: partition.c:253
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
#define NoLock
Definition: lockdefs.h:34
void check_stack_depth(void)
Definition: postgres.c:3441
PlannerGlobal * glob
Definition: pathnodes.h:163
bool partColsUpdated
Definition: pathnodes.h:374
int nparts
Definition: pathnodes.h:756
#define DatumGetBool(X)
Definition: postgres.h:437
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
#define TableOidAttributeNumber
Definition: sysattr.h:26
int allMarkTypes
Definition: plannodes.h:1121
Relids relids
Definition: pathnodes.h:676
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:194
RestrictInfo * make_restrictinfo(PlannerInfo *root, Expr *clause, bool is_pushed_down, bool outerjoin_delayed, bool pseudoconstant, Index security_level, Relids required_relids, Relids outer_relids, Relids nullable_relids)
Definition: restrictinfo.c:61
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
List * lappend(List *list, void *datum)
Definition: list.c:336
RangeTblEntry ** simple_rte_array
Definition: pathnodes.h:193
Expr * clause
Definition: pathnodes.h:2045
void * palloc0(Size size)
Definition: mcxt.c:1093
List * append_rel_list
Definition: pathnodes.h:283
struct AppendRelInfo ** append_rel_array
Definition: pathnodes.h:201
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:719
unsigned int Index
Definition: c.h:549
bool hasPseudoConstantQuals
Definition: pathnodes.h:348
#define InvalidOid
Definition: postgres_ext.h:36
Bitmapset * updatedCols
Definition: parsenodes.h:1149
bool is_pushed_down
Definition: pathnodes.h:2047
void expand_inherited_rtentry(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
Definition: inherit.c:79
#define makeNode(_type_)
Definition: nodes.h:587
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
char * aliasname
Definition: primnodes.h:42
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:600
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:396
LockClauseStrength strength
Definition: plannodes.h:1122
struct RelOptInfo ** part_rels
Definition: pathnodes.h:763
#define linitial_oid(l)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:149
void add_row_identity_var(PlannerInfo *root, Var *orig_var, Index rtindex, const char *rowid_name)
Definition: appendinfo.c:763
static void expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo, RangeTblEntry *parentrte, Index parentRTindex, Relation parentrel, PlanRowMark *top_parentrc, LOCKMODE lockmode)
Definition: inherit.c:288
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define InvalidAttrNumber
Definition: attnum.h:23
Bitmapset * prune_append_rel_partitions(RelOptInfo *rel)
Definition: partprune.c:753
RTEKind rtekind
Definition: parsenodes.h:995
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:201
void expand_planner_arrays(PlannerInfo *root, int add_size)
Definition: relnode.c:152
#define elog(elevel,...)
Definition: elog.h:232
Bitmapset * insertedCols
Definition: parsenodes.h:1148
int i
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:479
Relids leaf_result_relids
Definition: pathnodes.h:276
#define NameStr(name)
Definition: c.h:681
PartitionDesc PartitionDirectoryLookup(PartitionDirectory pdir, Relation rel)
Definition: partdesc.c:320
bool isParent
Definition: plannodes.h:1124
Index child_relid
Definition: pathnodes.h:2296
Alias * eref
Definition: parsenodes.h:1141
#define copyObject(obj)
Definition: nodes.h:655
Index parent_relid
Definition: pathnodes.h:2295
PartitionDirectory partition_directory
Definition: pathnodes.h:131
List * processed_tlist
Definition: pathnodes.h:320
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
#define snprintf
Definition: port.h:216
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:427
struct TableSampleClause * tablesample
Definition: parsenodes.h:1025
#define RelationGetRelid(relation)
Definition: rel.h:457
AppendRelInfo * make_append_rel_info(Relation parentrel, Relation childrel, Index parentRTindex, Index childRTindex)
Definition: appendinfo.c:50
void add_row_identity_columns(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
Definition: appendinfo.c:857
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:793
#define lfirst_oid(lc)
Definition: pg_list.h:171
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:666
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:195