PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/optimizer/util/inherit.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include <limits.h>
18
19#include "access/sysattr.h"
20#include "access/table.h"
21#include "catalog/partition.h"
22#include "catalog/pg_inherits.h"
23#include "catalog/pg_type.h"
24#include "miscadmin.h"
25#include "nodes/makefuncs.h"
27#include "optimizer/inherit.h"
28#include "optimizer/optimizer.h"
29#include "optimizer/pathnode.h"
30#include "optimizer/plancat.h"
31#include "optimizer/planmain.h"
32#include "optimizer/planner.h"
33#include "optimizer/prep.h"
35#include "parser/parsetree.h"
39#include "utils/rel.h"
40
41
54 List *translated_vars);
56 RelOptInfo *rel,
60 RangeTblEntry *rte, Index rti);
61
62
63/*
64 * expand_inherited_rtentry
65 * Expand a rangetable entry that has the "inh" bit set.
66 *
67 * "inh" is only allowed in two cases: RELATION and SUBQUERY RTEs.
68 *
69 * "inh" on a plain RELATION RTE means that it is a partitioned table or the
70 * parent of a traditional-inheritance set. In this case we must add entries
71 * for all the interesting child tables to the query's rangetable, and build
72 * additional planner data structures for them, including RelOptInfos,
73 * AppendRelInfos, and possibly PlanRowMarks.
74 *
75 * Note that the original RTE is considered to represent the whole inheritance
76 * set. In the case of traditional inheritance, the first of the generated
77 * RTEs is an RTE for the same table, but with inh = false, to represent the
78 * parent table in its role as a simple member of the inheritance set. For
79 * partitioning, we don't need a second RTE because the partitioned table
80 * itself has no data and need not be scanned.
81 *
82 * "inh" on a SUBQUERY RTE means that it's the parent of a UNION ALL group,
83 * which is treated as an appendrel similarly to inheritance cases; however,
84 * we already made RTEs and AppendRelInfos for the subqueries. We only need
85 * to build RelOptInfos for them, which is done by expand_appendrel_subquery.
86 */
87void
90{
93 LOCKMODE lockmode;
95 bool old_isParent = false;
96 int old_allMarkTypes = 0;
97
98 Assert(rte->inh); /* else caller error */
99
100 if (rte->rtekind == RTE_SUBQUERY)
101 {
103 return;
104 }
105
106 Assert(rte->rtekind == RTE_RELATION);
107
108 parentOID = rte->relid;
109
110 /*
111 * We used to check has_subclass() here, but there's no longer any need
112 * to, because subquery_planner already did.
113 */
114
115 /*
116 * The rewriter should already have obtained an appropriate lock on each
117 * relation named in the query, so we can open the parent relation without
118 * locking it. However, for each child relation we add to the query, we
119 * must obtain an appropriate lock, because this will be the first use of
120 * those relations in the parse/rewrite/plan pipeline. Child rels should
121 * use the same lockmode as their parent.
122 */
124 lockmode = rte->rellockmode;
125
126 /*
127 * If parent relation is selected FOR UPDATE/SHARE, we need to mark its
128 * PlanRowMark as isParent = true, and generate a new PlanRowMark for each
129 * child.
130 */
131 oldrc = get_plan_rowmark(root->rowMarks, rti);
132 if (oldrc)
133 {
134 old_isParent = oldrc->isParent;
135 oldrc->isParent = true;
136 /* Save initial value of allMarkTypes before children add to it */
137 old_allMarkTypes = oldrc->allMarkTypes;
138 }
139
140 /* Scan the inheritance set and expand it */
141 if (oldrelation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
142 {
144
145 perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
146
147 /*
148 * Partitioned table, so set up for partitioning.
149 */
151
152 /*
153 * Recursively expand and lock the partitions. While at it, also
154 * extract the partition key columns of all the partitioned tables.
155 */
158 perminfo->updatedCols,
159 oldrc, lockmode);
160 }
161 else
162 {
163 /*
164 * Ordinary table, so process traditional-inheritance children. (Note
165 * that partitioned tables are not allowed to have inheritance
166 * children, so it's not possible for both cases to apply.)
167 */
168 List *inhOIDs;
169 ListCell *l;
170
171 /* Scan for all members of inheritance set, acquire needed locks */
173
174 /*
175 * We used to special-case the situation where the table no longer has
176 * any children, by clearing rte->inh and exiting. That no longer
177 * works, because this function doesn't get run until after decisions
178 * have been made that depend on rte->inh. We have to treat such
179 * situations as normal inheritance. The table itself should always
180 * have been found, though.
181 */
182 Assert(inhOIDs != NIL);
184
185 /* Expand simple_rel_array and friends to hold child objects. */
187
188 /*
189 * Expand inheritance children in the order the OIDs were returned by
190 * find_all_inheritors.
191 */
192 foreach(l, inhOIDs)
193 {
198
199 /* Open rel if needed; we already have required locks */
200 if (childOID != parentOID)
202 else
204
205 /*
206 * It is possible that the parent table has children that are temp
207 * tables of other backends. We cannot safely access such tables
208 * (because of buffering issues), and the best thing to do seems
209 * to be to silently ignore them.
210 */
212 {
213 table_close(newrelation, lockmode);
214 continue;
215 }
216
217 /* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
221
222 /* Create the otherrel RelOptInfo too. */
224
225 /* Close child relations, but keep locks */
226 if (childOID != parentOID)
228 }
229 }
230
231 /*
232 * Some children might require different mark types, which would've been
233 * reported into oldrc. If so, add relevant entries to the top-level
234 * targetlist and update parent rel's reltarget. This should match what
235 * preprocess_targetlist() would have added if the mark types had been
236 * requested originally.
237 *
238 * (Someday it might be useful to fold these resjunk columns into the
239 * row-identity-column management used for UPDATE/DELETE. Today is not
240 * that day, however.)
241 */
242 if (oldrc)
243 {
244 int new_allMarkTypes = oldrc->allMarkTypes;
245 Var *var;
247 char resname[32];
248 List *newvars = NIL;
249
250 /* Add TID junk Var if needed, unless we had it already */
251 if (new_allMarkTypes & ~(1 << ROW_MARK_COPY) &&
252 !(old_allMarkTypes & ~(1 << ROW_MARK_COPY)))
253 {
254 /* Need to fetch TID */
255 var = makeVar(oldrc->rti,
257 TIDOID,
258 -1,
260 0);
261 snprintf(resname, sizeof(resname), "ctid%u", oldrc->rowmarkId);
262 tle = makeTargetEntry((Expr *) var,
263 list_length(root->processed_tlist) + 1,
265 true);
266 root->processed_tlist = lappend(root->processed_tlist, tle);
267 newvars = lappend(newvars, var);
268 }
269
270 /* Add whole-row junk Var if needed, unless we had it already */
271 if ((new_allMarkTypes & (1 << ROW_MARK_COPY)) &&
273 {
275 oldrc->rti,
276 0,
277 false);
278 snprintf(resname, sizeof(resname), "wholerow%u", oldrc->rowmarkId);
279 tle = makeTargetEntry((Expr *) var,
280 list_length(root->processed_tlist) + 1,
282 true);
283 root->processed_tlist = lappend(root->processed_tlist, tle);
284 newvars = lappend(newvars, var);
285 }
286
287 /* Add tableoid junk Var, unless we had it already */
288 if (!old_isParent)
289 {
290 var = makeVar(oldrc->rti,
292 OIDOID,
293 -1,
295 0);
296 snprintf(resname, sizeof(resname), "tableoid%u", oldrc->rowmarkId);
297 tle = makeTargetEntry((Expr *) var,
298 list_length(root->processed_tlist) + 1,
300 true);
301 root->processed_tlist = lappend(root->processed_tlist, tle);
302 newvars = lappend(newvars, var);
303 }
304
305 /*
306 * Add the newly added Vars to parent's reltarget. We needn't worry
307 * about the children's reltargets, they'll be made later.
308 */
310 }
311
313}
314
315/*
316 * expand_partitioned_rtentry
317 * Recursively expand an RTE for a partitioned table.
318 */
319static void
325{
326 PartitionDesc partdesc;
327 int num_live_parts;
328 int i;
329
331
332 Assert(parentrte->inh);
333
334 partdesc = PartitionDirectoryLookup(root->glob->partition_directory,
335 parentrel);
336
337 /* A partitioned table should always have a partition descriptor. */
338 Assert(partdesc);
339
340 /* Nothing further to do here if there are no partitions. */
341 if (partdesc->nparts == 0)
342 return;
343
344 /*
345 * Perform partition pruning using restriction clauses assigned to parent
346 * relation. live_parts will contain PartitionDesc indexes of partitions
347 * that survive pruning. Below, we will initialize child objects for the
348 * surviving partitions.
349 */
351
352 /* Expand simple_rel_array and friends to hold child objects. */
354 if (num_live_parts > 0)
356
357 /*
358 * We also store partition RelOptInfo pointers in the parent relation.
359 * Since we're palloc0'ing, slots corresponding to pruned partitions will
360 * contain NULL.
361 */
362 Assert(relinfo->part_rels == NULL);
363 relinfo->part_rels = (RelOptInfo **)
364 palloc0(relinfo->nparts * sizeof(RelOptInfo *));
365
366 /*
367 * Create a child RTE for each live partition. Note that unlike
368 * traditional inheritance, we don't need a child RTE for the partitioned
369 * table itself, because it's not going to be scanned.
370 */
371 i = -1;
372 while ((i = bms_next_member(relinfo->live_parts, i)) >= 0)
373 {
374 Oid childOID = partdesc->oids[i];
379
380 /*
381 * Open rel, acquiring required locks. If a partition was recently
382 * detached and subsequently dropped, then opening it will fail. In
383 * this case, behave as though the partition had been pruned.
384 */
385 childrel = try_table_open(childOID, lockmode);
386 if (childrel == NULL)
387 {
388 relinfo->live_parts = bms_del_member(relinfo->live_parts, i);
389 continue;
390 }
391
392 /*
393 * Temporary partitions belonging to other sessions should have been
394 * disallowed at definition, but for paranoia's sake, let's double
395 * check.
396 */
398 elog(ERROR, "temporary relation from another session found as partition");
399
400 /* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
404
405 /* Create the otherrel RelOptInfo too. */
407 relinfo->part_rels[i] = childrelinfo;
408 relinfo->all_partrels = bms_add_members(relinfo->all_partrels,
409 childrelinfo->relids);
410
411 /* If this child is itself partitioned, recurse */
412 if (childrel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
413 {
414 AppendRelInfo *appinfo = root->append_rel_array[childRTindex];
416
418 appinfo->translated_vars);
419
422 childrel,
424 top_parentrc, lockmode);
425 }
426
427 /* Close child relation, but keep locks */
429 }
430}
431
432/*
433 * expand_single_inheritance_child
434 * Build a RangeTblEntry and an AppendRelInfo, plus maybe a PlanRowMark.
435 *
436 * We now expand the partition hierarchy level by level, creating a
437 * corresponding hierarchy of AppendRelInfos and RelOptInfos, where each
438 * partitioned descendant acts as a parent of its immediate partitions.
439 * (This is a difference from what older versions of PostgreSQL did and what
440 * is still done in the case of table inheritance for unpartitioned tables,
441 * where the hierarchy is flattened during RTE expansion.)
442 *
443 * PlanRowMarks still carry the top-parent's RTI, and the top-parent's
444 * allMarkTypes field still accumulates values from all descendents.
445 *
446 * "parentrte" and "parentRTindex" are immediate parent's RTE and
447 * RTI. "top_parentrc" is top parent's PlanRowMark.
448 *
449 * The child RangeTblEntry and its RTI are returned in "childrte_p" and
450 * "childRTindex_p" resp.
451 */
452static void
458{
459 Query *parse = root->parse;
468
469 /*
470 * Build an RTE for the child, and attach to query's rangetable list. We
471 * copy most scalar fields of the parent's RTE, but replace relation OID,
472 * relkind, and inh for the child. Set the child's securityQuals to
473 * empty, because we only want to apply the parent's RLS conditions
474 * regardless of what RLS properties individual children may have. (This
475 * is an intentional choice to make inherited RLS work like regular
476 * permissions checks.) The parent securityQuals will be propagated to
477 * children along with other base restriction clauses, so we don't need to
478 * do it here. Other infrastructure of the parent RTE has to be
479 * translated to match the child table's column ordering, which we do
480 * below, so a "flat" copy is sufficient to start with.
481 */
484 Assert(parentrte->rtekind == RTE_RELATION); /* else this is dubious */
485 childrte->relid = childOID;
486 childrte->relkind = childrel->rd_rel->relkind;
487 /* A partitioned child will need to be expanded further. */
488 if (childrte->relkind == RELKIND_PARTITIONED_TABLE)
489 {
491 childrte->inh = true;
492 }
493 else
494 childrte->inh = false;
495 childrte->securityQuals = NIL;
496
497 /* No permission checking for child RTEs. */
498 childrte->perminfoindex = 0;
499
500 /* Link not-yet-fully-filled child RTE into data structures */
501 parse->rtable = lappend(parse->rtable, childrte);
502 childRTindex = list_length(parse->rtable);
505
506 /*
507 * Retrieve column not-null constraint information for the child relation
508 * if its relation OID is different from the parent's.
509 */
510 if (childOID != parentOID)
512
513 /*
514 * Build an AppendRelInfo struct for each parent/child pair.
515 */
518 root->append_rel_list = lappend(root->append_rel_list, appinfo);
519
520 /* tablesample is probably null, but copy it */
521 childrte->tablesample = copyObject(parentrte->tablesample);
522
523 /*
524 * Construct an alias clause for the child, which we can also use as eref.
525 * This is important so that EXPLAIN will print the right column aliases
526 * for child-table columns. (Since ruleutils.c doesn't have any easy way
527 * to reassociate parent and child columns, we must get the child column
528 * aliases right to start with. Note that setting childrte->alias forces
529 * ruleutils.c to use these column names, which it otherwise would not.)
530 */
532 parent_colnames = parentrte->eref->colnames;
534 for (int cattno = 0; cattno < child_tupdesc->natts; cattno++)
535 {
537 const char *attname;
538
539 if (att->attisdropped)
540 {
541 /* Always insert an empty string for a dropped column */
542 attname = "";
543 }
544 else if (appinfo->parent_colnos[cattno] > 0 &&
545 appinfo->parent_colnos[cattno] <= list_length(parent_colnames))
546 {
547 /* Duplicate the query-assigned name for the parent column */
549 appinfo->parent_colnos[cattno] - 1));
550 }
551 else
552 {
553 /* New column, just use its real name */
554 attname = NameStr(att->attname);
555 }
557 }
558
559 /*
560 * We just duplicate the parent's table alias name for each child. If the
561 * plan gets printed, ruleutils.c has to sort out unique table aliases to
562 * use, which it can handle.
563 */
564 childrte->alias = childrte->eref = makeAlias(parentrte->eref->aliasname,
566
567 /*
568 * Store the RTE and appinfo in the respective PlannerInfo arrays, which
569 * the caller must already have allocated space for.
570 */
571 Assert(childRTindex < root->simple_rel_array_size);
572 Assert(root->simple_rte_array[childRTindex] == NULL);
573 root->simple_rte_array[childRTindex] = childrte;
574 Assert(root->append_rel_array[childRTindex] == NULL);
575 root->append_rel_array[childRTindex] = appinfo;
576
577 /*
578 * Build a PlanRowMark if parent is marked FOR UPDATE/SHARE.
579 */
580 if (top_parentrc)
581 {
583
584 childrc->rti = childRTindex;
585 childrc->prti = top_parentrc->rti;
586 childrc->rowmarkId = top_parentrc->rowmarkId;
587 /* Reselect rowmark type, because relkind might not match parent */
589 top_parentrc->strength);
590 childrc->allMarkTypes = (1 << childrc->markType);
591 childrc->strength = top_parentrc->strength;
592 childrc->waitPolicy = top_parentrc->waitPolicy;
593
594 /*
595 * We mark RowMarks for partitioned child tables as parent RowMarks so
596 * that the executor ignores them (except their existence means that
597 * the child tables will be locked using the appropriate mode).
598 */
599 childrc->isParent = (childrte->relkind == RELKIND_PARTITIONED_TABLE);
600
601 /* Include child's rowmark type in top parent's allMarkTypes */
602 top_parentrc->allMarkTypes |= childrc->allMarkTypes;
603
604 root->rowMarks = lappend(root->rowMarks, childrc);
605 }
606
607 /*
608 * If we are creating a child of the query target relation (only possible
609 * in UPDATE/DELETE/MERGE), add it to all_result_relids, as well as
610 * leaf_result_relids if appropriate, and make sure that we generate
611 * required row-identity data.
612 */
613 if (bms_is_member(parentRTindex, root->all_result_relids))
614 {
615 /* OK, record the child as a result rel too. */
616 root->all_result_relids = bms_add_member(root->all_result_relids,
618
619 /* Non-leaf partitions don't need any row identity info. */
620 if (childrte->relkind != RELKIND_PARTITIONED_TABLE)
621 {
622 Var *rrvar;
623
624 root->leaf_result_relids = bms_add_member(root->leaf_result_relids,
626
627 /*
628 * If we have any child target relations, assume they all need to
629 * generate a junk "tableoid" column. (If only one child survives
630 * pruning, we wouldn't really need this, but it's not worth
631 * thrashing about to avoid it.)
632 */
635 OIDOID,
636 -1,
638 0);
640
641 /* Register any row-identity columns needed by this child. */
644 }
645 }
646}
647
648/*
649 * get_rel_all_updated_cols
650 * Returns the set of columns of a given "simple" relation that are
651 * updated by this query.
652 */
653Bitmapset *
655{
656 Index relid;
659 Bitmapset *updatedCols,
661
662 Assert(root->parse->commandType == CMD_UPDATE);
663 Assert(IS_SIMPLE_REL(rel));
664
665 /*
666 * We obtain updatedCols for the query's result relation. Then, if
667 * necessary, we map it to the column numbers of the relation for which
668 * they were requested.
669 */
670 relid = root->parse->resultRelation;
671 rte = planner_rt_fetch(relid, root);
672 perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
673
674 updatedCols = perminfo->updatedCols;
675
676 if (rel->relid != relid)
677 {
679
680 Assert(IS_OTHER_REL(rel));
681
683 updatedCols);
684 }
685
686 /*
687 * Now we must check to see if there are any generated columns that depend
688 * on the updatedCols, and add them to the result.
689 */
691 updatedCols);
692
693 return bms_union(updatedCols, extraUpdatedCols);
694}
695
696/*
697 * translate_col_privs
698 * Translate a bitmapset representing per-column privileges from the
699 * parent rel's attribute numbering to the child's.
700 *
701 * The only surprise here is that we don't translate a parent whole-row
702 * reference into a child whole-row reference. That would mean requiring
703 * permissions on all child columns, which is overly strict, since the
704 * query is really only going to reference the inherited columns. Instead
705 * we set the per-column bits for all inherited columns.
706 */
707static Bitmapset *
709 List *translated_vars)
710{
712 bool whole_row;
713 int attno;
714 ListCell *lc;
715
716 /* System attributes have the same numbers in all tables */
717 for (attno = FirstLowInvalidHeapAttributeNumber + 1; attno < 0; attno++)
718 {
723 }
724
725 /* Check if parent has whole-row reference */
728
729 /* And now translate the regular user attributes, using the vars list */
730 attno = InvalidAttrNumber;
731 foreach(lc, translated_vars)
732 {
733 Var *var = lfirst_node(Var, lc);
734
735 attno++;
736 if (var == NULL) /* ignore dropped columns */
737 continue;
738 if (whole_row ||
743 }
744
745 return child_privs;
746}
747
748/*
749 * translate_col_privs_multilevel
750 * Recursively translates the column numbers contained in 'parent_cols'
751 * to the column numbers of a descendant relation given by 'rel'
752 *
753 * Note that because this is based on translate_col_privs, it will expand
754 * a whole-row reference into all inherited columns. This is not an issue
755 * for current usages, but beware.
756 */
757static Bitmapset *
761{
763
764 /* Fast path for easy case. */
765 if (parent_cols == NULL)
766 return NULL;
767
768 /* Recurse if immediate parent is not the top parent. */
769 if (rel->parent != parent_rel)
770 {
771 if (rel->parent)
775 else
776 elog(ERROR, "rel with relid %u is not a child rel", rel->relid);
777 }
778
779 /* Now translate for this child. */
780 Assert(root->append_rel_array != NULL);
781 appinfo = root->append_rel_array[rel->relid];
782 Assert(appinfo != NULL);
783
784 return translate_col_privs(parent_cols, appinfo->translated_vars);
785}
786
787/*
788 * expand_appendrel_subquery
789 * Add "other rel" RelOptInfos for the children of an appendrel baserel
790 *
791 * "rel" is a subquery relation that has the rte->inh flag set, meaning it
792 * is a UNION ALL subquery that's been flattened into an appendrel, with
793 * child subqueries listed in root->append_rel_list. We need to build
794 * a RelOptInfo for each child relation so that we can plan scans on them.
795 */
796static void
798 RangeTblEntry *rte, Index rti)
799{
800 ListCell *l;
801
802 foreach(l, root->append_rel_list)
803 {
808
809 /* append_rel_list contains all append rels; ignore others */
810 if (appinfo->parent_relid != rti)
811 continue;
812
813 /* find the child RTE, which should already exist */
814 Assert(childRTindex < root->simple_rel_array_size);
815 childrte = root->simple_rte_array[childRTindex];
816 Assert(childrte != NULL);
817
818 /* Build the child RelOptInfo. */
820
821 /* Child may itself be an inherited rel, either table or subquery. */
822 if (childrte->inh)
824 }
825}
826
827
828/*
829 * apply_child_basequals
830 * Populate childrel's base restriction quals from parent rel's quals,
831 * translating them using appinfo.
832 *
833 * If any of the resulting clauses evaluate to constant false or NULL, we
834 * return false and don't apply any quals. Caller should mark the relation as
835 * a dummy rel in this case, since it doesn't need to be scanned. Constant
836 * true quals are ignored.
837 */
838bool
842{
845 ListCell *lc;
846
847 /*
848 * The child rel's targetlist might contain non-Var expressions, which
849 * means that substitution into the quals could produce opportunities for
850 * const-simplification, and perhaps even pseudoconstant quals. Therefore,
851 * transform each RestrictInfo separately to see if it reduces to a
852 * constant or pseudoconstant. (We must process them separately to keep
853 * track of the security level of each qual.)
854 */
855 childquals = NIL;
857 foreach(lc, parentrel->baserestrictinfo)
858 {
859 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
861 ListCell *lc2;
862
863 Assert(IsA(rinfo, RestrictInfo));
865 (Node *) rinfo->clause,
866 1, &appinfo);
868 /* check for flat-out constant */
869 if (childqual && IsA(childqual, Const))
870 {
871 if (((Const *) childqual)->constisnull ||
873 {
874 /* Restriction reduces to constant FALSE or NULL */
875 return false;
876 }
877 /* Restriction reduces to constant TRUE, so drop it */
878 continue;
879 }
880 /* might have gotten an AND clause, if so flatten it */
881 foreach(lc2, make_ands_implicit((Expr *) childqual))
882 {
883 Node *onecq = (Node *) lfirst(lc2);
884 bool pseudoconstant;
886
887 /* check for pseudoconstant (no Vars or volatile functions) */
891 if (pseudoconstant)
892 {
893 /* tell createplan.c to check for gating quals */
894 root->hasPseudoConstantQuals = true;
895 }
896 /* reconstitute RestrictInfo with appropriate properties */
898 (Expr *) onecq,
899 rinfo->is_pushed_down,
900 rinfo->has_clone,
901 rinfo->is_clone,
903 rinfo->security_level,
904 NULL, NULL, NULL);
905
907 /* track minimum security level among child quals */
908 cq_min_security = Min(cq_min_security, childrinfo->security_level);
909 }
910 }
911
912 /*
913 * In addition to the quals inherited from the parent, we might have
914 * securityQuals associated with this particular child node. (Currently
915 * this can only happen in appendrels originating from UNION ALL;
916 * inheritance child tables don't have their own securityQuals, see
917 * expand_single_inheritance_child().) Pull any such securityQuals up
918 * into the baserestrictinfo for the child. This is similar to
919 * process_security_barrier_quals() for the parent rel, except that we
920 * can't make any general deductions from such quals, since they don't
921 * hold for the whole appendrel.
922 */
923 if (childRTE->securityQuals)
924 {
925 Index security_level = 0;
926
927 foreach(lc, childRTE->securityQuals)
928 {
929 List *qualset = (List *) lfirst(lc);
930 ListCell *lc2;
931
932 foreach(lc2, qualset)
933 {
934 Expr *qual = (Expr *) lfirst(lc2);
935
936 /* not likely that we'd see constants here, so no check */
939 true,
940 false, false,
941 false,
942 security_level,
943 NULL, NULL, NULL));
944 cq_min_security = Min(cq_min_security, security_level);
945 }
946 security_level++;
947 }
948 Assert(security_level <= root->qual_security_level);
949 }
950
951 /*
952 * OK, we've got all the baserestrictinfo quals for this child.
953 */
954 childrel->baserestrictinfo = childquals;
955 childrel->baserestrict_min_security = cq_min_security;
956
957 return true;
958}
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition appendinfo.c:201
void add_row_identity_columns(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
Definition appendinfo.c:959
AppendRelInfo * make_append_rel_info(Relation parentrel, Relation childrel, Index parentRTindex, Index childRTindex)
Definition appendinfo.c:52
void add_row_identity_var(PlannerInfo *root, Var *orig_var, Index rtindex, const char *rowid_name)
Definition appendinfo.c:864
#define InvalidAttrNumber
Definition attnum.h:23
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:216
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1290
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:852
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:744
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:901
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
#define NameStr(name)
Definition c.h:837
#define Min(x, y)
Definition c.h:1093
#define Assert(condition)
Definition c.h:945
unsigned int Index
Definition c.h:700
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition clauses.c:2498
bool contain_volatile_functions(Node *clause)
Definition clauses.c:549
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
void parse(int)
Definition parse.c:49
static Bitmapset * translate_col_privs(const Bitmapset *parent_privs, List *translated_vars)
Definition inherit.c:708
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:320
bool apply_child_basequals(PlannerInfo *root, RelOptInfo *parentrel, RelOptInfo *childrel, RangeTblEntry *childRTE, AppendRelInfo *appinfo)
Definition inherit.c:839
static void expand_appendrel_subquery(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
Definition inherit.c:797
static Bitmapset * translate_col_privs_multilevel(PlannerInfo *root, RelOptInfo *rel, RelOptInfo *parent_rel, Bitmapset *parent_cols)
Definition inherit.c:758
Bitmapset * get_rel_all_updated_cols(PlannerInfo *root, RelOptInfo *rel)
Definition inherit.c:654
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 expand_inherited_rtentry(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
Definition inherit.c:88
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
Definition initsplan.c:290
int i
Definition isn.c:77
List * lappend(List *list, void *datum)
Definition list.c:339
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
Alias * makeAlias(const char *aliasname, List *colnames)
Definition makefuncs.c:438
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
List * make_ands_implicit(Expr *clause)
Definition makefuncs.c:810
char * pstrdup(const char *in)
Definition mcxt.c:1781
void * palloc0(Size size)
Definition mcxt.c:1417
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define copyObject(obj)
Definition nodes.h:232
@ CMD_UPDATE
Definition nodes.h:276
#define makeNode(_type_)
Definition nodes.h:161
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
@ RTE_SUBQUERY
@ RTE_RELATION
PartitionDesc PartitionDirectoryLookup(PartitionDirectory pdir, Relation rel)
Definition partdesc.c:456
Bitmapset * prune_append_rel_partitions(RelOptInfo *rel)
Definition partprune.c:779
#define IS_SIMPLE_REL(rel)
Definition pathnodes.h:989
#define planner_rt_fetch(rti, root)
Definition pathnodes.h:704
#define IS_OTHER_REL(rel)
Definition pathnodes.h:1004
NameData attname
FormData_pg_attribute * Form_pg_attribute
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
#define lfirst(lc)
Definition pg_list.h:172
#define lfirst_node(type, lc)
Definition pg_list.h:176
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
#define linitial_oid(l)
Definition pg_list.h:180
#define lfirst_oid(lc)
Definition pg_list.h:174
void get_relation_notnullatts(PlannerInfo *root, Relation relation)
Definition plancat.c:690
Bitmapset * get_dependent_generated_columns(PlannerInfo *root, Index rti, Bitmapset *target_cols)
Definition plancat.c:2637
RowMarkType select_rowmark_type(RangeTblEntry *rte, LockClauseStrength strength)
Definition planner.c:2597
@ ROW_MARK_COPY
Definition plannodes.h:1558
#define snprintf
Definition port.h:260
static bool DatumGetBool(Datum X)
Definition postgres.h:100
#define InvalidOid
unsigned int Oid
static int fb(int x)
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition preptlist.c:528
tree ctl root
Definition radixtree.h:1857
#define RelationGetRelid(relation)
Definition rel.h:514
#define RelationGetDescr(relation)
Definition rel.h:540
#define RELATION_IS_OTHER_TEMP(relation)
Definition rel.h:667
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition relnode.c:544
void expand_planner_arrays(PlannerInfo *root, int add_size)
Definition relnode.c:183
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition relnode.c:212
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)
void check_stack_depth(void)
Definition stack_depth.c:95
Index child_relid
Definition pathnodes.h:3301
Definition pg_list.h:54
Definition nodes.h:135
Index relid
Definition pathnodes.h:1069
bool is_pushed_down
Definition pathnodes.h:2903
Index security_level
Definition pathnodes.h:2922
Expr * clause
Definition pathnodes.h:2900
AttrNumber varattno
Definition primnodes.h:275
#define FirstLowInvalidHeapAttributeNumber
Definition sysattr.h:27
#define TableOidAttributeNumber
Definition sysattr.h:26
#define SelfItemPointerAttributeNumber
Definition sysattr.h:21
Relation try_table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:60
void table_close(Relation relation, LOCKMODE lockmode)
Definition table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition table.c:40
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
String * makeString(char *str)
Definition value.c:63
#define strVal(v)
Definition value.h:82
bool contain_vars_of_level(Node *node, int levelsup)
Definition var.c:444