PostgreSQL Source Code  git master
inherit.h File Reference
#include "nodes/pathnodes.h"
Include dependency graph for inherit.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void expand_inherited_rtentry (PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
 
Bitmapsetget_rel_all_updated_cols (PlannerInfo *root, RelOptInfo *rel)
 
bool apply_child_basequals (PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, RangeTblEntry *childRTE, AppendRelInfo *appinfo)
 

Function Documentation

◆ apply_child_basequals()

bool apply_child_basequals ( PlannerInfo root,
RelOptInfo parentrel,
RelOptInfo childrel,
RangeTblEntry childRTE,
AppendRelInfo appinfo 
)

Definition at line 836 of file inherit.c.

839 {
840  List *childquals;
841  Index cq_min_security;
842  ListCell *lc;
843 
844  /*
845  * The child rel's targetlist might contain non-Var expressions, which
846  * means that substitution into the quals could produce opportunities for
847  * const-simplification, and perhaps even pseudoconstant quals. Therefore,
848  * transform each RestrictInfo separately to see if it reduces to a
849  * constant or pseudoconstant. (We must process them separately to keep
850  * track of the security level of each qual.)
851  */
852  childquals = NIL;
853  cq_min_security = UINT_MAX;
854  foreach(lc, parentrel->baserestrictinfo)
855  {
856  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
857  Node *childqual;
858  ListCell *lc2;
859 
860  Assert(IsA(rinfo, RestrictInfo));
861  childqual = adjust_appendrel_attrs(root,
862  (Node *) rinfo->clause,
863  1, &appinfo);
864  childqual = eval_const_expressions(root, childqual);
865  /* check for flat-out constant */
866  if (childqual && IsA(childqual, Const))
867  {
868  if (((Const *) childqual)->constisnull ||
869  !DatumGetBool(((Const *) childqual)->constvalue))
870  {
871  /* Restriction reduces to constant FALSE or NULL */
872  return false;
873  }
874  /* Restriction reduces to constant TRUE, so drop it */
875  continue;
876  }
877  /* might have gotten an AND clause, if so flatten it */
878  foreach(lc2, make_ands_implicit((Expr *) childqual))
879  {
880  Node *onecq = (Node *) lfirst(lc2);
881  bool pseudoconstant;
882 
883  /* check for pseudoconstant (no Vars or volatile functions) */
884  pseudoconstant =
885  !contain_vars_of_level(onecq, 0) &&
887  if (pseudoconstant)
888  {
889  /* tell createplan.c to check for gating quals */
890  root->hasPseudoConstantQuals = true;
891  }
892  /* reconstitute RestrictInfo with appropriate properties */
893  childquals = lappend(childquals,
894  make_restrictinfo(root,
895  (Expr *) onecq,
896  rinfo->is_pushed_down,
897  rinfo->has_clone,
898  rinfo->is_clone,
899  pseudoconstant,
900  rinfo->security_level,
901  NULL, NULL, NULL));
902  /* track minimum security level among child quals */
903  cq_min_security = Min(cq_min_security, rinfo->security_level);
904  }
905  }
906 
907  /*
908  * In addition to the quals inherited from the parent, we might have
909  * securityQuals associated with this particular child node. (Currently
910  * this can only happen in appendrels originating from UNION ALL;
911  * inheritance child tables don't have their own securityQuals, see
912  * expand_single_inheritance_child().) Pull any such securityQuals up
913  * into the baserestrictinfo for the child. This is similar to
914  * process_security_barrier_quals() for the parent rel, except that we
915  * can't make any general deductions from such quals, since they don't
916  * hold for the whole appendrel.
917  */
918  if (childRTE->securityQuals)
919  {
920  Index security_level = 0;
921 
922  foreach(lc, childRTE->securityQuals)
923  {
924  List *qualset = (List *) lfirst(lc);
925  ListCell *lc2;
926 
927  foreach(lc2, qualset)
928  {
929  Expr *qual = (Expr *) lfirst(lc2);
930 
931  /* not likely that we'd see constants here, so no check */
932  childquals = lappend(childquals,
933  make_restrictinfo(root, qual,
934  true,
935  false, false,
936  false,
937  security_level,
938  NULL, NULL, NULL));
939  cq_min_security = Min(cq_min_security, security_level);
940  }
941  security_level++;
942  }
943  Assert(security_level <= root->qual_security_level);
944  }
945 
946  /*
947  * OK, we've got all the baserestrictinfo quals for this child.
948  */
949  childrel->baserestrictinfo = childquals;
950  childrel->baserestrict_min_security = cq_min_security;
951 
952  return true;
953 }
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:196
#define Min(x, y)
Definition: c.h:988
unsigned int Index
Definition: c.h:598
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2171
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:483
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:722
#define IsA(nodeptr, _type_)
Definition: nodes.h:179
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
RestrictInfo * make_restrictinfo(PlannerInfo *root, Expr *clause, bool is_pushed_down, bool has_clone, bool is_clone, bool pseudoconstant, Index security_level, Relids required_relids, Relids incompatible_relids, Relids outer_relids)
Definition: restrictinfo.c:63
Definition: pg_list.h:54
Definition: nodes.h:129
bool hasPseudoConstantQuals
Definition: pathnodes.h:495
List * securityQuals
Definition: parsenodes.h:1204
List * baserestrictinfo
Definition: pathnodes.h:964
Index baserestrict_min_security
Definition: pathnodes.h:968
bool is_pushed_down
Definition: pathnodes.h:2519
Index security_level
Definition: pathnodes.h:2538
Expr * clause
Definition: pathnodes.h:2516
bool has_clone
Definition: pathnodes.h:2528
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:441

References adjust_appendrel_attrs(), Assert(), RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictinfo, RestrictInfo::clause, contain_vars_of_level(), contain_volatile_functions(), DatumGetBool(), eval_const_expressions(), RestrictInfo::has_clone, PlannerInfo::hasPseudoConstantQuals, RestrictInfo::is_clone, RestrictInfo::is_pushed_down, IsA, lappend(), lfirst, make_ands_implicit(), make_restrictinfo(), Min, NIL, RestrictInfo::security_level, and RangeTblEntry::securityQuals.

Referenced by build_simple_rel().

◆ expand_inherited_rtentry()

void expand_inherited_rtentry ( PlannerInfo root,
RelOptInfo rel,
RangeTblEntry rte,
Index  rti 
)

Definition at line 86 of file inherit.c.

88 {
89  Oid parentOID;
90  Relation oldrelation;
91  LOCKMODE lockmode;
92  PlanRowMark *oldrc;
93  bool old_isParent = false;
94  int old_allMarkTypes = 0;
95 
96  Assert(rte->inh); /* else caller error */
97 
98  if (rte->rtekind == RTE_SUBQUERY)
99  {
100  expand_appendrel_subquery(root, rel, rte, rti);
101  return;
102  }
103 
104  Assert(rte->rtekind == RTE_RELATION);
105 
106  parentOID = rte->relid;
107 
108  /*
109  * We used to check has_subclass() here, but there's no longer any need
110  * to, because subquery_planner already did.
111  */
112 
113  /*
114  * The rewriter should already have obtained an appropriate lock on each
115  * relation named in the query, so we can open the parent relation without
116  * locking it. However, for each child relation we add to the query, we
117  * must obtain an appropriate lock, because this will be the first use of
118  * those relations in the parse/rewrite/plan pipeline. Child rels should
119  * use the same lockmode as their parent.
120  */
121  oldrelation = table_open(parentOID, NoLock);
122  lockmode = rte->rellockmode;
123 
124  /*
125  * If parent relation is selected FOR UPDATE/SHARE, we need to mark its
126  * PlanRowMark as isParent = true, and generate a new PlanRowMark for each
127  * child.
128  */
129  oldrc = get_plan_rowmark(root->rowMarks, rti);
130  if (oldrc)
131  {
132  old_isParent = oldrc->isParent;
133  oldrc->isParent = true;
134  /* Save initial value of allMarkTypes before children add to it */
135  old_allMarkTypes = oldrc->allMarkTypes;
136  }
137 
138  /* Scan the inheritance set and expand it */
139  if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
140  {
141  RTEPermissionInfo *perminfo;
142 
143  perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
144 
145  /*
146  * Partitioned table, so set up for partitioning.
147  */
148  Assert(rte->relkind == RELKIND_PARTITIONED_TABLE);
149 
150  /*
151  * Recursively expand and lock the partitions. While at it, also
152  * extract the partition key columns of all the partitioned tables.
153  */
154  expand_partitioned_rtentry(root, rel, rte, rti,
155  oldrelation,
156  perminfo->updatedCols,
157  oldrc, lockmode);
158  }
159  else
160  {
161  /*
162  * Ordinary table, so process traditional-inheritance children. (Note
163  * that partitioned tables are not allowed to have inheritance
164  * children, so it's not possible for both cases to apply.)
165  */
166  List *inhOIDs;
167  ListCell *l;
168 
169  /* Scan for all members of inheritance set, acquire needed locks */
170  inhOIDs = find_all_inheritors(parentOID, lockmode, NULL);
171 
172  /*
173  * We used to special-case the situation where the table no longer has
174  * any children, by clearing rte->inh and exiting. That no longer
175  * works, because this function doesn't get run until after decisions
176  * have been made that depend on rte->inh. We have to treat such
177  * situations as normal inheritance. The table itself should always
178  * have been found, though.
179  */
180  Assert(inhOIDs != NIL);
181  Assert(linitial_oid(inhOIDs) == parentOID);
182 
183  /* Expand simple_rel_array and friends to hold child objects. */
184  expand_planner_arrays(root, list_length(inhOIDs));
185 
186  /*
187  * Expand inheritance children in the order the OIDs were returned by
188  * find_all_inheritors.
189  */
190  foreach(l, inhOIDs)
191  {
192  Oid childOID = lfirst_oid(l);
193  Relation newrelation;
194  RangeTblEntry *childrte;
195  Index childRTindex;
196 
197  /* Open rel if needed; we already have required locks */
198  if (childOID != parentOID)
199  newrelation = table_open(childOID, NoLock);
200  else
201  newrelation = oldrelation;
202 
203  /*
204  * It is possible that the parent table has children that are temp
205  * tables of other backends. We cannot safely access such tables
206  * (because of buffering issues), and the best thing to do seems
207  * to be to silently ignore them.
208  */
209  if (childOID != parentOID && RELATION_IS_OTHER_TEMP(newrelation))
210  {
211  table_close(newrelation, lockmode);
212  continue;
213  }
214 
215  /* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
216  expand_single_inheritance_child(root, rte, rti, oldrelation,
217  oldrc, newrelation,
218  &childrte, &childRTindex);
219 
220  /* Create the otherrel RelOptInfo too. */
221  (void) build_simple_rel(root, childRTindex, rel);
222 
223  /* Close child relations, but keep locks */
224  if (childOID != parentOID)
225  table_close(newrelation, NoLock);
226  }
227  }
228 
229  /*
230  * Some children might require different mark types, which would've been
231  * reported into oldrc. If so, add relevant entries to the top-level
232  * targetlist and update parent rel's reltarget. This should match what
233  * preprocess_targetlist() would have added if the mark types had been
234  * requested originally.
235  *
236  * (Someday it might be useful to fold these resjunk columns into the
237  * row-identity-column management used for UPDATE/DELETE. Today is not
238  * that day, however.)
239  */
240  if (oldrc)
241  {
242  int new_allMarkTypes = oldrc->allMarkTypes;
243  Var *var;
244  TargetEntry *tle;
245  char resname[32];
246  List *newvars = NIL;
247 
248  /* Add TID junk Var if needed, unless we had it already */
249  if (new_allMarkTypes & ~(1 << ROW_MARK_COPY) &&
250  !(old_allMarkTypes & ~(1 << ROW_MARK_COPY)))
251  {
252  /* Need to fetch TID */
253  var = makeVar(oldrc->rti,
255  TIDOID,
256  -1,
257  InvalidOid,
258  0);
259  snprintf(resname, sizeof(resname), "ctid%u", oldrc->rowmarkId);
260  tle = makeTargetEntry((Expr *) var,
261  list_length(root->processed_tlist) + 1,
262  pstrdup(resname),
263  true);
264  root->processed_tlist = lappend(root->processed_tlist, tle);
265  newvars = lappend(newvars, var);
266  }
267 
268  /* Add whole-row junk Var if needed, unless we had it already */
269  if ((new_allMarkTypes & (1 << ROW_MARK_COPY)) &&
270  !(old_allMarkTypes & (1 << ROW_MARK_COPY)))
271  {
272  var = makeWholeRowVar(planner_rt_fetch(oldrc->rti, root),
273  oldrc->rti,
274  0,
275  false);
276  snprintf(resname, sizeof(resname), "wholerow%u", oldrc->rowmarkId);
277  tle = makeTargetEntry((Expr *) var,
278  list_length(root->processed_tlist) + 1,
279  pstrdup(resname),
280  true);
281  root->processed_tlist = lappend(root->processed_tlist, tle);
282  newvars = lappend(newvars, var);
283  }
284 
285  /* Add tableoid junk Var, unless we had it already */
286  if (!old_isParent)
287  {
288  var = makeVar(oldrc->rti,
290  OIDOID,
291  -1,
292  InvalidOid,
293  0);
294  snprintf(resname, sizeof(resname), "tableoid%u", oldrc->rowmarkId);
295  tle = makeTargetEntry((Expr *) var,
296  list_length(root->processed_tlist) + 1,
297  pstrdup(resname),
298  true);
299  root->processed_tlist = lappend(root->processed_tlist, tle);
300  newvars = lappend(newvars, var);
301  }
302 
303  /*
304  * Add the newly added Vars to parent's reltarget. We needn't worry
305  * about the children's reltargets, they'll be made later.
306  */
307  add_vars_to_targetlist(root, newvars, bms_make_singleton(0));
308  }
309 
310  table_close(oldrelation, NoLock);
311 }
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
static void expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo, RangeTblEntry *parentrte, Index parentRTindex, Relation parentrel, Bitmapset *parent_updatedCols, PlanRowMark *top_parentrc, LOCKMODE lockmode)
Definition: inherit.c:318
static void expand_appendrel_subquery(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
Definition: inherit.c:795
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:453
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
Definition: initsplan.c:280
int LOCKMODE
Definition: lockdefs.h:26
#define NoLock
Definition: lockdefs.h:34
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:136
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:241
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:67
char * pstrdup(const char *in)
Definition: mcxt.c:1644
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_SUBQUERY
Definition: parsenodes.h:1015
@ RTE_RELATION
Definition: parsenodes.h:1014
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:555
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:256
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_oid(l)
Definition: pg_list.h:180
#define lfirst_oid(lc)
Definition: pg_list.h:174
@ ROW_MARK_COPY
Definition: plannodes.h:1332
#define snprintf
Definition: port.h:238
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:485
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:659
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:191
void expand_planner_arrays(PlannerInfo *root, int add_size)
Definition: relnode.c:162
bool isParent
Definition: plannodes.h:1387
Index rowmarkId
Definition: plannodes.h:1382
int allMarkTypes
Definition: plannodes.h:1384
List * processed_tlist
Definition: pathnodes.h:453
Query * parse
Definition: pathnodes.h:199
List * rowMarks
Definition: pathnodes.h:368
Bitmapset * updatedCols
Definition: parsenodes.h:1250
RTEKind rtekind
Definition: parsenodes.h:1033
Form_pg_class rd_rel
Definition: rel.h:111
Definition: primnodes.h:226
#define TableOidAttributeNumber
Definition: sysattr.h:26
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40

References add_vars_to_targetlist(), PlanRowMark::allMarkTypes, Assert(), bms_make_singleton(), build_simple_rel(), expand_appendrel_subquery(), expand_partitioned_rtentry(), expand_planner_arrays(), expand_single_inheritance_child(), find_all_inheritors(), get_plan_rowmark(), getRTEPermissionInfo(), RangeTblEntry::inh, InvalidOid, PlanRowMark::isParent, lappend(), lfirst_oid, linitial_oid, list_length(), makeTargetEntry(), makeVar(), makeWholeRowVar(), NIL, NoLock, PlannerInfo::parse, planner_rt_fetch, PlannerInfo::processed_tlist, pstrdup(), RelationData::rd_rel, RELATION_IS_OTHER_TEMP, RangeTblEntry::relid, RangeTblEntry::relkind, RangeTblEntry::rellockmode, ROW_MARK_COPY, PlanRowMark::rowmarkId, PlannerInfo::rowMarks, RTE_RELATION, RTE_SUBQUERY, RangeTblEntry::rtekind, PlanRowMark::rti, SelfItemPointerAttributeNumber, snprintf, table_close(), table_open(), TableOidAttributeNumber, and RTEPermissionInfo::updatedCols.

Referenced by add_other_rels_to_query(), and expand_appendrel_subquery().

◆ get_rel_all_updated_cols()

Bitmapset* get_rel_all_updated_cols ( PlannerInfo root,
RelOptInfo rel 
)

Definition at line 652 of file inherit.c.

653 {
654  Index relid;
655  RangeTblEntry *rte;
656  RTEPermissionInfo *perminfo;
657  Bitmapset *updatedCols,
658  *extraUpdatedCols;
659 
660  Assert(root->parse->commandType == CMD_UPDATE);
661  Assert(IS_SIMPLE_REL(rel));
662 
663  /*
664  * We obtain updatedCols for the query's result relation. Then, if
665  * necessary, we map it to the column numbers of the relation for which
666  * they were requested.
667  */
668  relid = root->parse->resultRelation;
669  rte = planner_rt_fetch(relid, root);
670  perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
671 
672  updatedCols = perminfo->updatedCols;
673 
674  if (rel->relid != relid)
675  {
676  RelOptInfo *top_parent_rel = find_base_rel(root, relid);
677 
678  Assert(IS_OTHER_REL(rel));
679 
680  updatedCols = translate_col_privs_multilevel(root, rel, top_parent_rel,
681  updatedCols);
682  }
683 
684  /*
685  * Now we must check to see if there are any generated columns that depend
686  * on the updatedCols, and add them to the result.
687  */
688  extraUpdatedCols = get_dependent_generated_columns(root, rel->relid,
689  updatedCols);
690 
691  return bms_union(updatedCols, extraUpdatedCols);
692 }
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:226
static Bitmapset * translate_col_privs_multilevel(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *parent_rel, Bitmapset *parent_cols)
Definition: inherit.c:756
@ CMD_UPDATE
Definition: nodes.h:277
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:824
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:839
Bitmapset * get_dependent_generated_columns(PlannerInfo *root, Index rti, Bitmapset *target_cols)
Definition: plancat.c:2269
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:405
CmdType commandType
Definition: parsenodes.h:128
Index relid
Definition: pathnodes.h:903

References Assert(), bms_union(), CMD_UPDATE, Query::commandType, find_base_rel(), get_dependent_generated_columns(), getRTEPermissionInfo(), IS_OTHER_REL, IS_SIMPLE_REL, PlannerInfo::parse, planner_rt_fetch, RelOptInfo::relid, translate_col_privs_multilevel(), and RTEPermissionInfo::updatedCols.

Referenced by postgresPlanForeignModify().