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 808 of file inherit.c.

811 {
812  List *childquals;
813  Index cq_min_security;
814  ListCell *lc;
815 
816  /*
817  * The child rel's targetlist might contain non-Var expressions, which
818  * means that substitution into the quals could produce opportunities for
819  * const-simplification, and perhaps even pseudoconstant quals. Therefore,
820  * transform each RestrictInfo separately to see if it reduces to a
821  * constant or pseudoconstant. (We must process them separately to keep
822  * track of the security level of each qual.)
823  */
824  childquals = NIL;
825  cq_min_security = UINT_MAX;
826  foreach(lc, parentrel->baserestrictinfo)
827  {
828  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
829  Node *childqual;
830  ListCell *lc2;
831 
832  Assert(IsA(rinfo, RestrictInfo));
833  childqual = adjust_appendrel_attrs(root,
834  (Node *) rinfo->clause,
835  1, &appinfo);
836  childqual = eval_const_expressions(root, childqual);
837  /* check for flat-out constant */
838  if (childqual && IsA(childqual, Const))
839  {
840  if (((Const *) childqual)->constisnull ||
841  !DatumGetBool(((Const *) childqual)->constvalue))
842  {
843  /* Restriction reduces to constant FALSE or NULL */
844  return false;
845  }
846  /* Restriction reduces to constant TRUE, so drop it */
847  continue;
848  }
849  /* might have gotten an AND clause, if so flatten it */
850  foreach(lc2, make_ands_implicit((Expr *) childqual))
851  {
852  Node *onecq = (Node *) lfirst(lc2);
853  bool pseudoconstant;
854 
855  /* check for pseudoconstant (no Vars or volatile functions) */
856  pseudoconstant =
857  !contain_vars_of_level(onecq, 0) &&
859  if (pseudoconstant)
860  {
861  /* tell createplan.c to check for gating quals */
862  root->hasPseudoConstantQuals = true;
863  }
864  /* reconstitute RestrictInfo with appropriate properties */
865  childquals = lappend(childquals,
866  make_restrictinfo(root,
867  (Expr *) onecq,
868  rinfo->is_pushed_down,
869  rinfo->outerjoin_delayed,
870  pseudoconstant,
871  rinfo->security_level,
872  NULL, NULL, NULL));
873  /* track minimum security level among child quals */
874  cq_min_security = Min(cq_min_security, rinfo->security_level);
875  }
876  }
877 
878  /*
879  * In addition to the quals inherited from the parent, we might have
880  * securityQuals associated with this particular child node. (Currently
881  * this can only happen in appendrels originating from UNION ALL;
882  * inheritance child tables don't have their own securityQuals, see
883  * expand_single_inheritance_child().) Pull any such securityQuals up
884  * into the baserestrictinfo for the child. This is similar to
885  * process_security_barrier_quals() for the parent rel, except that we
886  * can't make any general deductions from such quals, since they don't
887  * hold for the whole appendrel.
888  */
889  if (childRTE->securityQuals)
890  {
891  Index security_level = 0;
892 
893  foreach(lc, childRTE->securityQuals)
894  {
895  List *qualset = (List *) lfirst(lc);
896  ListCell *lc2;
897 
898  foreach(lc2, qualset)
899  {
900  Expr *qual = (Expr *) lfirst(lc2);
901 
902  /* not likely that we'd see constants here, so no check */
903  childquals = lappend(childquals,
904  make_restrictinfo(root, qual,
905  true, false, false,
906  security_level,
907  NULL, NULL, NULL));
908  cq_min_security = Min(cq_min_security, security_level);
909  }
910  security_level++;
911  }
912  Assert(security_level <= root->qual_security_level);
913  }
914 
915  /*
916  * OK, we've got all the baserestrictinfo quals for this child.
917  */
918  childrel->baserestrictinfo = childquals;
919  childrel->baserestrict_min_security = cq_min_security;
920 
921  return true;
922 }
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:195
#define Min(x, y)
Definition: c.h:937
unsigned int Index
Definition: c.h:550
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2132
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:448
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:719
#define IsA(nodeptr, _type_)
Definition: nodes.h:168
#define lfirst(lc)
Definition: pg_list.h:170
#define NIL
Definition: pg_list.h:66
static bool DatumGetBool(Datum X)
Definition: postgres.h:438
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
Definition: pg_list.h:52
Definition: nodes.h:118
bool hasPseudoConstantQuals
Definition: pathnodes.h:460
List * securityQuals
Definition: parsenodes.h:1157
List * baserestrictinfo
Definition: pathnodes.h:933
Index baserestrict_min_security
Definition: pathnodes.h:937
bool is_pushed_down
Definition: pathnodes.h:2438
Index security_level
Definition: pathnodes.h:2456
Expr * clause
Definition: pathnodes.h:2435
bool outerjoin_delayed
Definition: pathnodes.h:2441
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:431

References adjust_appendrel_attrs(), Assert(), RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictinfo, RestrictInfo::clause, contain_vars_of_level(), contain_volatile_functions(), DatumGetBool(), eval_const_expressions(), PlannerInfo::hasPseudoConstantQuals, RestrictInfo::is_pushed_down, IsA, lappend(), lfirst, make_ands_implicit(), make_restrictinfo(), Min, NIL, RestrictInfo::outerjoin_delayed, 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 85 of file inherit.c.

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

664 {
665  Index relid;
666  RangeTblEntry *rte;
667  RTEPermissionInfo *perminfo;
668  Bitmapset *updatedCols,
669  *extraUpdatedCols;
670 
671  Assert(root->parse->commandType == CMD_UPDATE);
672  Assert(IS_SIMPLE_REL(rel));
673 
674  /*
675  * We obtain updatedCols and extraUpdatedCols for the query's result
676  * relation. Then, if necessary, we map it to the column numbers of the
677  * relation for which they were requested.
678  */
679  relid = root->parse->resultRelation;
680  rte = planner_rt_fetch(relid, root);
681  perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
682 
683  updatedCols = perminfo->updatedCols;
684  extraUpdatedCols = rte->extraUpdatedCols;
685 
686  /*
687  * For "other" rels, we must look up the root parent relation mentioned in
688  * the query, and translate the column numbers.
689  */
690  if (rel->relid != relid)
691  {
692  RelOptInfo *top_parent_rel = find_base_rel(root, relid);
693 
694  Assert(IS_OTHER_REL(rel));
695 
696  updatedCols = translate_col_privs_multilevel(root, rel, top_parent_rel,
697  updatedCols);
698  extraUpdatedCols = translate_col_privs_multilevel(root, rel, top_parent_rel,
699  extraUpdatedCols);
700  }
701 
702  return bms_union(updatedCols, extraUpdatedCols);
703 }
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:226
static Bitmapset * translate_col_privs_multilevel(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *top_parent_rel, Bitmapset *top_parent_cols)
Definition: inherit.c:931
@ CMD_UPDATE
Definition: nodes.h:266
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:792
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:807
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:379
int resultRelation
Definition: parsenodes.h:138
CmdType commandType
Definition: parsenodes.h:124
Bitmapset * extraUpdatedCols
Definition: parsenodes.h:1156
Index relid
Definition: pathnodes.h:871

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

Referenced by postgresPlanForeignModify().