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

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().

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 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Index security_level
Definition: pathnodes.h:2060
List * securityQuals
Definition: parsenodes.h:1151
List * baserestrictinfo
Definition: pathnodes.h:740
#define Min(x, y)
Definition: c.h:986
Definition: nodes.h:539
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2090
Index baserestrict_min_security
Definition: pathnodes.h:742
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:448
bool outerjoin_delayed
Definition: pathnodes.h:2049
#define DatumGetBool(X)
Definition: postgres.h:437
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
List * lappend(List *list, void *datum)
Definition: list.c:336
Expr * clause
Definition: pathnodes.h:2045
List * make_ands_implicit(Expr *clause)
Definition: makefuncs.c:719
unsigned int Index
Definition: c.h:549
bool hasPseudoConstantQuals
Definition: pathnodes.h:348
bool is_pushed_down
Definition: pathnodes.h:2047
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:396
Definition: pg_list.h:50
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:195

◆ expand_inherited_rtentry()

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

Definition at line 79 of file inherit.c.

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(), RangeTblEntry::inh, InvalidOid, PlanRowMark::isParent, lappend(), lfirst_oid, linitial_oid, list_length(), makeTargetEntry(), makeVar(), makeWholeRowVar(), NIL, NoLock, 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, snprintf, table_close(), table_open(), and TableOidAttributeNumber.

Referenced by add_other_rels_to_query(), and expand_appendrel_subquery().

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 }
#define NIL
Definition: pg_list.h:65
List * rowMarks
Definition: pathnodes.h:287
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
int LOCKMODE
Definition: lockdefs.h:26
char * pstrdup(const char *in)
Definition: mcxt.c:1299
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:133
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:109
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:186
Index rowmarkId
Definition: plannodes.h:1120
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed, bool create_new_ph)
Definition: initsplan.c:230
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
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:383
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
#define NoLock
Definition: lockdefs.h:34
#define TableOidAttributeNumber
Definition: sysattr.h:26
int allMarkTypes
Definition: plannodes.h:1122
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:194
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
unsigned int Index
Definition: c.h:549
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:804
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:612
#define linitial_oid(l)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:149
static void expand_partitioned_rtentry(PlannerInfo *root, RelOptInfo *relinfo, RangeTblEntry *parentrte, Index parentRTindex, Relation parentrel, PlanRowMark *top_parentrc, LOCKMODE lockmode)
Definition: inherit.c:288
RTEKind rtekind
Definition: parsenodes.h:995
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:256
void expand_planner_arrays(PlannerInfo *root, int add_size)
Definition: relnode.c:152
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:425
bool isParent
Definition: plannodes.h:1125
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
#define lfirst_oid(lc)
Definition: pg_list.h:171