PostgreSQL Source Code git master
Loading...
Searching...
No Matches
inherit.c File Reference
Include dependency graph for inherit.c:

Go to the source code of this file.

Functions

static void expand_partitioned_rtentry (PlannerInfo *root, RelOptInfo *relinfo, RangeTblEntry *parentrte, Index parentRTindex, Relation parentrel, Bitmapset *parent_updatedCols, PlanRowMark *top_parentrc, LOCKMODE lockmode)
 
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)
 
static Bitmapsettranslate_col_privs (const Bitmapset *parent_privs, List *translated_vars)
 
static Bitmapsettranslate_col_privs_multilevel (PlannerInfo *root, RelOptInfo *rel, RelOptInfo *parent_rel, Bitmapset *parent_cols)
 
static void expand_appendrel_subquery (PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
 
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 838 of file inherit.c.

841{
844 ListCell *lc;
845
846 /*
847 * The child rel's targetlist might contain non-Var expressions, which
848 * means that substitution into the quals could produce opportunities for
849 * const-simplification, and perhaps even pseudoconstant quals. Therefore,
850 * transform each RestrictInfo separately to see if it reduces to a
851 * constant or pseudoconstant. (We must process them separately to keep
852 * track of the security level of each qual.)
853 */
854 childquals = NIL;
856 foreach(lc, parentrel->baserestrictinfo)
857 {
858 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
860 ListCell *lc2;
861
862 Assert(IsA(rinfo, RestrictInfo));
864 (Node *) rinfo->clause,
865 1, &appinfo);
867 /* check for flat-out constant */
868 if (childqual && IsA(childqual, Const))
869 {
870 if (((Const *) childqual)->constisnull ||
872 {
873 /* Restriction reduces to constant FALSE or NULL */
874 return false;
875 }
876 /* Restriction reduces to constant TRUE, so drop it */
877 continue;
878 }
879 /* might have gotten an AND clause, if so flatten it */
880 foreach(lc2, make_ands_implicit((Expr *) childqual))
881 {
882 Node *onecq = (Node *) lfirst(lc2);
883 bool pseudoconstant;
885
886 /* check for pseudoconstant (no Vars or volatile functions) */
890 if (pseudoconstant)
891 {
892 /* tell createplan.c to check for gating quals */
893 root->hasPseudoConstantQuals = true;
894 }
895 /* reconstitute RestrictInfo with appropriate properties */
897 (Expr *) onecq,
898 rinfo->is_pushed_down,
899 rinfo->has_clone,
900 rinfo->is_clone,
902 rinfo->security_level,
903 NULL, NULL, NULL);
904
905 /* Restriction is proven always false */
907 return false;
908 /* Restriction is proven always true, so drop it */
910 continue;
911
913 /* track minimum security level among child quals */
915 }
916 }
917
918 /*
919 * In addition to the quals inherited from the parent, we might have
920 * securityQuals associated with this particular child node. (Currently
921 * this can only happen in appendrels originating from UNION ALL;
922 * inheritance child tables don't have their own securityQuals, see
923 * expand_single_inheritance_child().) Pull any such securityQuals up
924 * into the baserestrictinfo for the child. This is similar to
925 * process_security_barrier_quals() for the parent rel, except that we
926 * can't make any general deductions from such quals, since they don't
927 * hold for the whole appendrel.
928 */
929 if (childRTE->securityQuals)
930 {
931 Index security_level = 0;
932
933 foreach(lc, childRTE->securityQuals)
934 {
935 List *qualset = (List *) lfirst(lc);
936 ListCell *lc2;
937
938 foreach(lc2, qualset)
939 {
940 Expr *qual = (Expr *) lfirst(lc2);
941
942 /* not likely that we'd see constants here, so no check */
945 true,
946 false, false,
947 false,
948 security_level,
949 NULL, NULL, NULL));
950 cq_min_security = Min(cq_min_security, security_level);
951 }
952 security_level++;
953 }
954 Assert(security_level <= root->qual_security_level);
955 }
956
957 /*
958 * OK, we've got all the baserestrictinfo quals for this child.
959 */
960 childrel->baserestrictinfo = childquals;
961 childrel->baserestrict_min_security = cq_min_security;
962
963 return true;
964}
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition appendinfo.c:200
#define Min(x, y)
Definition c.h:997
#define Assert(condition)
Definition c.h:873
unsigned int Index
Definition c.h:628
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2267
bool contain_volatile_functions(Node *clause)
Definition clauses.c:547
bool restriction_is_always_true(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition initsplan.c:3422
bool restriction_is_always_false(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition initsplan.c:3487
List * lappend(List *list, void *datum)
Definition list.c:339
List * make_ands_implicit(Expr *clause)
Definition makefuncs.c:810
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define lfirst(lc)
Definition pg_list.h:172
#define NIL
Definition pg_list.h:68
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static int fb(int x)
tree ctl root
Definition radixtree.h:1857
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 pg_list.h:54
Definition nodes.h:135
bool is_pushed_down
Definition pathnodes.h:2873
Index security_level
Definition pathnodes.h:2892
Expr * clause
Definition pathnodes.h:2870
bool contain_vars_of_level(Node *node, int levelsup)
Definition var.c:444

References adjust_appendrel_attrs(), Assert, RestrictInfo::clause, contain_vars_of_level(), contain_volatile_functions(), DatumGetBool(), eval_const_expressions(), fb(), RestrictInfo::has_clone, RestrictInfo::is_clone, RestrictInfo::is_pushed_down, IsA, lappend(), lfirst, make_ands_implicit(), make_restrictinfo(), Min, NIL, restriction_is_always_false(), restriction_is_always_true(), root, and RestrictInfo::security_level.

Referenced by build_simple_rel().

◆ expand_appendrel_subquery()

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

Definition at line 795 of file inherit.c.

797{
798 ListCell *l;
799
800 foreach(l, root->append_rel_list)
801 {
806
807 /* append_rel_list contains all append rels; ignore others */
808 if (appinfo->parent_relid != rti)
809 continue;
810
811 /* find the child RTE, which should already exist */
812 Assert(childRTindex < root->simple_rel_array_size);
813 childrte = root->simple_rte_array[childRTindex];
814 Assert(childrte != NULL);
815
816 /* Build the child RelOptInfo. */
818
819 /* Child may itself be an inherited rel, either table or subquery. */
820 if (childrte->inh)
822 }
823}
void expand_inherited_rtentry(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
Definition inherit.c:86
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition relnode.c:209
Index child_relid
Definition pathnodes.h:3271

References Assert, build_simple_rel(), AppendRelInfo::child_relid, expand_inherited_rtentry(), fb(), lfirst, and root.

Referenced by expand_inherited_rtentry().

◆ expand_inherited_rtentry()

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

Definition at line 86 of file inherit.c.

88{
91 LOCKMODE lockmode;
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 {
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 */
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 {
142
143 perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
144
145 /*
146 * Partitioned table, so set up for partitioning.
147 */
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 */
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 */
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);
182
183 /* Expand simple_rel_array and friends to hold child objects. */
185
186 /*
187 * Expand inheritance children in the order the OIDs were returned by
188 * find_all_inheritors.
189 */
190 foreach(l, inhOIDs)
191 {
196
197 /* Open rel if needed; we already have required locks */
198 if (childOID != parentOID)
200 else
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 */
210 {
211 table_close(newrelation, lockmode);
212 continue;
213 }
214
215 /* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
219
220 /* Create the otherrel RelOptInfo too. */
222
223 /* Close child relations, but keep locks */
224 if (childOID != parentOID)
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;
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,
258 0);
259 snprintf(resname, sizeof(resname), "ctid%u", oldrc->rowmarkId);
260 tle = makeTargetEntry((Expr *) var,
261 list_length(root->processed_tlist) + 1,
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)) &&
271 {
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,
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,
293 0);
294 snprintf(resname, sizeof(resname), "tableoid%u", oldrc->rowmarkId);
295 tle = makeTargetEntry((Expr *) var,
296 list_length(root->processed_tlist) + 1,
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 */
308 }
309
311}
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:216
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:451
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
Definition initsplan.c:289
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition makefuncs.c:66
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
Definition makefuncs.c:137
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition makefuncs.c:289
char * pstrdup(const char *in)
Definition mcxt.c:1781
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_SUBQUERY
@ RTE_RELATION
#define planner_rt_fetch(rti, root)
Definition pathnodes.h:686
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
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:1541
#define snprintf
Definition port.h:260
#define InvalidOid
unsigned int Oid
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition preptlist.c:526
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:667
void expand_planner_arrays(PlannerInfo *root, int add_size)
Definition relnode.c:180
#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(), Assert, bms_make_singleton(), build_simple_rel(), expand_appendrel_subquery(), expand_partitioned_rtentry(), expand_planner_arrays(), expand_single_inheritance_child(), fb(), find_all_inheritors(), get_plan_rowmark(), getRTEPermissionInfo(), InvalidOid, lappend(), lfirst_oid, linitial_oid, list_length(), makeTargetEntry(), makeVar(), makeWholeRowVar(), NIL, NoLock, planner_rt_fetch, pstrdup(), RELATION_IS_OTHER_TEMP, root, ROW_MARK_COPY, RTE_RELATION, RTE_SUBQUERY, SelfItemPointerAttributeNumber, snprintf, table_close(), table_open(), and TableOidAttributeNumber.

Referenced by add_other_rels_to_query(), and expand_appendrel_subquery().

◆ expand_partitioned_rtentry()

static void expand_partitioned_rtentry ( PlannerInfo root,
RelOptInfo relinfo,
RangeTblEntry parentrte,
Index  parentRTindex,
Relation  parentrel,
Bitmapset parent_updatedCols,
PlanRowMark top_parentrc,
LOCKMODE  lockmode 
)
static

Definition at line 318 of file inherit.c.

323{
324 PartitionDesc partdesc;
325 int num_live_parts;
326 int i;
327
329
330 Assert(parentrte->inh);
331
332 partdesc = PartitionDirectoryLookup(root->glob->partition_directory,
333 parentrel);
334
335 /* A partitioned table should always have a partition descriptor. */
336 Assert(partdesc);
337
338 /* Nothing further to do here if there are no partitions. */
339 if (partdesc->nparts == 0)
340 return;
341
342 /*
343 * Perform partition pruning using restriction clauses assigned to parent
344 * relation. live_parts will contain PartitionDesc indexes of partitions
345 * that survive pruning. Below, we will initialize child objects for the
346 * surviving partitions.
347 */
349
350 /* Expand simple_rel_array and friends to hold child objects. */
352 if (num_live_parts > 0)
354
355 /*
356 * We also store partition RelOptInfo pointers in the parent relation.
357 * Since we're palloc0'ing, slots corresponding to pruned partitions will
358 * contain NULL.
359 */
360 Assert(relinfo->part_rels == NULL);
361 relinfo->part_rels = (RelOptInfo **)
362 palloc0(relinfo->nparts * sizeof(RelOptInfo *));
363
364 /*
365 * Create a child RTE for each live partition. Note that unlike
366 * traditional inheritance, we don't need a child RTE for the partitioned
367 * table itself, because it's not going to be scanned.
368 */
369 i = -1;
370 while ((i = bms_next_member(relinfo->live_parts, i)) >= 0)
371 {
372 Oid childOID = partdesc->oids[i];
377
378 /*
379 * Open rel, acquiring required locks. If a partition was recently
380 * detached and subsequently dropped, then opening it will fail. In
381 * this case, behave as though the partition had been pruned.
382 */
383 childrel = try_table_open(childOID, lockmode);
384 if (childrel == NULL)
385 {
386 relinfo->live_parts = bms_del_member(relinfo->live_parts, i);
387 continue;
388 }
389
390 /*
391 * Temporary partitions belonging to other sessions should have been
392 * disallowed at definition, but for paranoia's sake, let's double
393 * check.
394 */
396 elog(ERROR, "temporary relation from another session found as partition");
397
398 /* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
402
403 /* Create the otherrel RelOptInfo too. */
405 relinfo->part_rels[i] = childrelinfo;
406 relinfo->all_partrels = bms_add_members(relinfo->all_partrels,
407 childrelinfo->relids);
408
409 /* If this child is itself partitioned, recurse */
410 if (childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
411 {
412 AppendRelInfo *appinfo = root->append_rel_array[childRTindex];
414
416 appinfo->translated_vars);
417
420 childrel,
422 top_parentrc, lockmode);
423 }
424
425 /* Close child relation, but keep locks */
427 }
428}
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1305
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:867
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:750
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:916
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
static Bitmapset * translate_col_privs(const Bitmapset *parent_privs, List *translated_vars)
Definition inherit.c:706
int i
Definition isn.c:77
void * palloc0(Size size)
Definition mcxt.c:1417
PartitionDesc PartitionDirectoryLookup(PartitionDirectory pdir, Relation rel)
Definition partdesc.c:456
Bitmapset * prune_append_rel_partitions(RelOptInfo *rel)
Definition partprune.c:779
void check_stack_depth(void)
Definition stack_depth.c:95
Relation try_table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:60

References Assert, bms_add_members(), bms_del_member(), bms_next_member(), bms_num_members(), build_simple_rel(), check_stack_depth(), elog, ERROR, expand_partitioned_rtentry(), expand_planner_arrays(), expand_single_inheritance_child(), fb(), i, NoLock, PartitionDescData::nparts, PartitionDescData::oids, palloc0(), PartitionDirectoryLookup(), prune_append_rel_partitions(), RELATION_IS_OTHER_TEMP, root, table_close(), translate_col_privs(), and try_table_open().

Referenced by expand_inherited_rtentry(), and expand_partitioned_rtentry().

◆ expand_single_inheritance_child()

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 
)
static

Definition at line 451 of file inherit.c.

456{
457 Query *parse = root->parse;
466
467 /*
468 * Build an RTE for the child, and attach to query's rangetable list. We
469 * copy most scalar fields of the parent's RTE, but replace relation OID,
470 * relkind, and inh for the child. Set the child's securityQuals to
471 * empty, because we only want to apply the parent's RLS conditions
472 * regardless of what RLS properties individual children may have. (This
473 * is an intentional choice to make inherited RLS work like regular
474 * permissions checks.) The parent securityQuals will be propagated to
475 * children along with other base restriction clauses, so we don't need to
476 * do it here. Other infrastructure of the parent RTE has to be
477 * translated to match the child table's column ordering, which we do
478 * below, so a "flat" copy is sufficient to start with.
479 */
482 Assert(parentrte->rtekind == RTE_RELATION); /* else this is dubious */
483 childrte->relid = childOID;
484 childrte->relkind = childrel->rd_rel->relkind;
485 /* A partitioned child will need to be expanded further. */
486 if (childrte->relkind == RELKIND_PARTITIONED_TABLE)
487 {
489 childrte->inh = true;
490 }
491 else
492 childrte->inh = false;
493 childrte->securityQuals = NIL;
494
495 /* No permission checking for child RTEs. */
496 childrte->perminfoindex = 0;
497
498 /* Link not-yet-fully-filled child RTE into data structures */
499 parse->rtable = lappend(parse->rtable, childrte);
500 childRTindex = list_length(parse->rtable);
503
504 /*
505 * Retrieve column not-null constraint information for the child relation
506 * if its relation OID is different from the parent's.
507 */
508 if (childOID != parentOID)
510
511 /*
512 * Build an AppendRelInfo struct for each parent/child pair.
513 */
516 root->append_rel_list = lappend(root->append_rel_list, appinfo);
517
518 /* tablesample is probably null, but copy it */
519 childrte->tablesample = copyObject(parentrte->tablesample);
520
521 /*
522 * Construct an alias clause for the child, which we can also use as eref.
523 * This is important so that EXPLAIN will print the right column aliases
524 * for child-table columns. (Since ruleutils.c doesn't have any easy way
525 * to reassociate parent and child columns, we must get the child column
526 * aliases right to start with. Note that setting childrte->alias forces
527 * ruleutils.c to use these column names, which it otherwise would not.)
528 */
530 parent_colnames = parentrte->eref->colnames;
532 for (int cattno = 0; cattno < child_tupdesc->natts; cattno++)
533 {
535 const char *attname;
536
537 if (att->attisdropped)
538 {
539 /* Always insert an empty string for a dropped column */
540 attname = "";
541 }
542 else if (appinfo->parent_colnos[cattno] > 0 &&
543 appinfo->parent_colnos[cattno] <= list_length(parent_colnames))
544 {
545 /* Duplicate the query-assigned name for the parent column */
547 appinfo->parent_colnos[cattno] - 1));
548 }
549 else
550 {
551 /* New column, just use its real name */
552 attname = NameStr(att->attname);
553 }
555 }
556
557 /*
558 * We just duplicate the parent's table alias name for each child. If the
559 * plan gets printed, ruleutils.c has to sort out unique table aliases to
560 * use, which it can handle.
561 */
562 childrte->alias = childrte->eref = makeAlias(parentrte->eref->aliasname,
564
565 /*
566 * Store the RTE and appinfo in the respective PlannerInfo arrays, which
567 * the caller must already have allocated space for.
568 */
569 Assert(childRTindex < root->simple_rel_array_size);
570 Assert(root->simple_rte_array[childRTindex] == NULL);
571 root->simple_rte_array[childRTindex] = childrte;
572 Assert(root->append_rel_array[childRTindex] == NULL);
573 root->append_rel_array[childRTindex] = appinfo;
574
575 /*
576 * Build a PlanRowMark if parent is marked FOR UPDATE/SHARE.
577 */
578 if (top_parentrc)
579 {
581
582 childrc->rti = childRTindex;
583 childrc->prti = top_parentrc->rti;
584 childrc->rowmarkId = top_parentrc->rowmarkId;
585 /* Reselect rowmark type, because relkind might not match parent */
587 top_parentrc->strength);
588 childrc->allMarkTypes = (1 << childrc->markType);
589 childrc->strength = top_parentrc->strength;
590 childrc->waitPolicy = top_parentrc->waitPolicy;
591
592 /*
593 * We mark RowMarks for partitioned child tables as parent RowMarks so
594 * that the executor ignores them (except their existence means that
595 * the child tables will be locked using the appropriate mode).
596 */
597 childrc->isParent = (childrte->relkind == RELKIND_PARTITIONED_TABLE);
598
599 /* Include child's rowmark type in top parent's allMarkTypes */
600 top_parentrc->allMarkTypes |= childrc->allMarkTypes;
601
602 root->rowMarks = lappend(root->rowMarks, childrc);
603 }
604
605 /*
606 * If we are creating a child of the query target relation (only possible
607 * in UPDATE/DELETE/MERGE), add it to all_result_relids, as well as
608 * leaf_result_relids if appropriate, and make sure that we generate
609 * required row-identity data.
610 */
611 if (bms_is_member(parentRTindex, root->all_result_relids))
612 {
613 /* OK, record the child as a result rel too. */
614 root->all_result_relids = bms_add_member(root->all_result_relids,
616
617 /* Non-leaf partitions don't need any row identity info. */
618 if (childrte->relkind != RELKIND_PARTITIONED_TABLE)
619 {
620 Var *rrvar;
621
622 root->leaf_result_relids = bms_add_member(root->leaf_result_relids,
624
625 /*
626 * If we have any child target relations, assume they all need to
627 * generate a junk "tableoid" column. (If only one child survives
628 * pruning, we wouldn't really need this, but it's not worth
629 * thrashing about to avoid it.)
630 */
633 OIDOID,
634 -1,
636 0);
638
639 /* Register any row-identity columns needed by this child. */
642 }
643 }
644}
void add_row_identity_columns(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
Definition appendinfo.c:954
AppendRelInfo * make_append_rel_info(Relation parentrel, Relation childrel, Index parentRTindex, Index childRTindex)
Definition appendinfo.c:51
void add_row_identity_var(PlannerInfo *root, Var *orig_var, Index rtindex, const char *rowid_name)
Definition appendinfo.c:859
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:814
#define NameStr(name)
Definition c.h:765
void parse(int)
Definition parse.c:49
Alias * makeAlias(const char *aliasname, List *colnames)
Definition makefuncs.c:438
#define copyObject(obj)
Definition nodes.h:232
#define makeNode(_type_)
Definition nodes.h:161
NameData attname
FormData_pg_attribute * Form_pg_attribute
static void * list_nth(const List *list, int n)
Definition pg_list.h:299
void get_relation_notnullatts(PlannerInfo *root, Relation relation)
Definition plancat.c:704
RowMarkType select_rowmark_type(RangeTblEntry *rte, LockClauseStrength strength)
Definition planner.c:2587
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:160
String * makeString(char *str)
Definition value.c:63
#define strVal(v)
Definition value.h:82

References add_row_identity_columns(), add_row_identity_var(), Assert, attname, bms_add_member(), bms_is_member(), copyObject, fb(), get_relation_notnullatts(), InvalidOid, lappend(), list_length(), list_nth(), make_append_rel_info(), makeAlias(), makeNode, makeString(), makeVar(), NameStr, NIL, parse(), pstrdup(), RelationGetDescr, RelationGetRelid, root, RTE_RELATION, select_rowmark_type(), strVal, TableOidAttributeNumber, and TupleDescAttr().

Referenced by expand_inherited_rtentry(), and expand_partitioned_rtentry().

◆ 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;
657 Bitmapset *updatedCols,
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 {
677
678 Assert(IS_OTHER_REL(rel));
679
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 */
689 updatedCols);
690
691 return bms_union(updatedCols, extraUpdatedCols);
692}
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
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:276
#define IS_SIMPLE_REL(rel)
Definition pathnodes.h:971
#define IS_OTHER_REL(rel)
Definition pathnodes.h:986
Bitmapset * get_dependent_generated_columns(PlannerInfo *root, Index rti, Bitmapset *target_cols)
Definition plancat.c:2642
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition relnode.c:533
Index relid
Definition pathnodes.h:1051

References Assert, bms_union(), CMD_UPDATE, fb(), find_base_rel(), get_dependent_generated_columns(), getRTEPermissionInfo(), IS_OTHER_REL, IS_SIMPLE_REL, planner_rt_fetch, RelOptInfo::relid, root, and translate_col_privs_multilevel().

Referenced by postgresPlanForeignModify().

◆ translate_col_privs()

static Bitmapset * translate_col_privs ( const Bitmapset parent_privs,
List translated_vars 
)
static

Definition at line 706 of file inherit.c.

708{
710 bool whole_row;
711 int attno;
712 ListCell *lc;
713
714 /* System attributes have the same numbers in all tables */
715 for (attno = FirstLowInvalidHeapAttributeNumber + 1; attno < 0; attno++)
716 {
721 }
722
723 /* Check if parent has whole-row reference */
726
727 /* And now translate the regular user attributes, using the vars list */
728 attno = InvalidAttrNumber;
729 foreach(lc, translated_vars)
730 {
731 Var *var = lfirst_node(Var, lc);
732
733 attno++;
734 if (var == NULL) /* ignore dropped columns */
735 continue;
736 if (whole_row ||
741 }
742
743 return child_privs;
744}
#define InvalidAttrNumber
Definition attnum.h:23
#define lfirst_node(type, lc)
Definition pg_list.h:176
AttrNumber varattno
Definition primnodes.h:274
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27

References bms_add_member(), bms_is_member(), fb(), FirstLowInvalidHeapAttributeNumber, InvalidAttrNumber, lfirst_node, and Var::varattno.

Referenced by expand_partitioned_rtentry(), and translate_col_privs_multilevel().

◆ translate_col_privs_multilevel()

static Bitmapset * translate_col_privs_multilevel ( PlannerInfo root,
RelOptInfo rel,
RelOptInfo parent_rel,
Bitmapset parent_cols 
)
static

Definition at line 756 of file inherit.c.

759{
761
762 /* Fast path for easy case. */
763 if (parent_cols == NULL)
764 return NULL;
765
766 /* Recurse if immediate parent is not the top parent. */
767 if (rel->parent != parent_rel)
768 {
769 if (rel->parent)
773 else
774 elog(ERROR, "rel with relid %u is not a child rel", rel->relid);
775 }
776
777 /* Now translate for this child. */
778 Assert(root->append_rel_array != NULL);
779 appinfo = root->append_rel_array[rel->relid];
780 Assert(appinfo != NULL);
781
782 return translate_col_privs(parent_cols, appinfo->translated_vars);
783}

References Assert, elog, ERROR, fb(), RelOptInfo::relid, root, translate_col_privs(), and translate_col_privs_multilevel().

Referenced by get_rel_all_updated_cols(), and translate_col_privs_multilevel().