PostgreSQL Source Code git master
Functions
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

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

Function Documentation

apply_child_basequals()

bool apply_child_basequals ( PlannerInforoot,
RelOptInfoparentrel,
RelOptInfochildrel,
RangeTblEntrychildRTE,
AppendRelInfoappinfo 
)

Definition at line 848 of file inherit.c.

851{
852 List *childquals;
853 Index cq_min_security;
854 ListCell *lc;
855
856 /*
857 * The child rel's targetlist might contain non-Var expressions, which
858 * means that substitution into the quals could produce opportunities for
859 * const-simplification, and perhaps even pseudoconstant quals. Therefore,
860 * transform each RestrictInfo separately to see if it reduces to a
861 * constant or pseudoconstant. (We must process them separately to keep
862 * track of the security level of each qual.)
863 */
864 childquals = NIL;
865 cq_min_security = UINT_MAX;
866 foreach(lc, parentrel->baserestrictinfo)
867 {
868 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
869 Node *childqual;
870 ListCell *lc2;
871
872 Assert(IsA(rinfo, RestrictInfo));
873 childqual = adjust_appendrel_attrs(root,
874 (Node *) rinfo->clause,
875 1, &appinfo);
876 childqual = eval_const_expressions(root, childqual);
877 /* check for flat-out constant */
878 if (childqual && IsA(childqual, Const))
879 {
880 if (((Const *) childqual)->constisnull ||
881 !DatumGetBool(((Const *) childqual)->constvalue))
882 {
883 /* Restriction reduces to constant FALSE or NULL */
884 return false;
885 }
886 /* Restriction reduces to constant TRUE, so drop it */
887 continue;
888 }
889 /* might have gotten an AND clause, if so flatten it */
890 foreach(lc2, make_ands_implicit((Expr *) childqual))
891 {
892 Node *onecq = (Node *) lfirst(lc2);
893 bool pseudoconstant;
894 RestrictInfo *childrinfo;
895
896 /* check for pseudoconstant (no Vars or volatile functions) */
897 pseudoconstant =
898 !contain_vars_of_level(onecq, 0) &&
900 if (pseudoconstant)
901 {
902 /* tell createplan.c to check for gating quals */
903 root->hasPseudoConstantQuals = true;
904 }
905 /* reconstitute RestrictInfo with appropriate properties */
906 childrinfo = make_restrictinfo(root,
907 (Expr *) onecq,
908 rinfo->is_pushed_down,
909 rinfo->has_clone,
910 rinfo->is_clone,
911 pseudoconstant,
912 rinfo->security_level,
913 NULL, NULL, NULL);
914
915 /* Restriction is proven always false */
916 if (restriction_is_always_false(root, childrinfo))
917 return false;
918 /* Restriction is proven always true, so drop it */
919 if (restriction_is_always_true(root, childrinfo))
920 continue;
921
922 childquals = lappend(childquals, childrinfo);
923 /* track minimum security level among child quals */
924 cq_min_security = Min(cq_min_security, rinfo->security_level);
925 }
926 }
927
928 /*
929 * In addition to the quals inherited from the parent, we might have
930 * securityQuals associated with this particular child node. (Currently
931 * this can only happen in appendrels originating from UNION ALL;
932 * inheritance child tables don't have their own securityQuals, see
933 * expand_single_inheritance_child().) Pull any such securityQuals up
934 * into the baserestrictinfo for the child. This is similar to
935 * process_security_barrier_quals() for the parent rel, except that we
936 * can't make any general deductions from such quals, since they don't
937 * hold for the whole appendrel.
938 */
939 if (childRTE->securityQuals)
940 {
941 Index security_level = 0;
942
943 foreach(lc, childRTE->securityQuals)
944 {
945 List *qualset = (List *) lfirst(lc);
946 ListCell *lc2;
947
948 foreach(lc2, qualset)
949 {
950 Expr *qual = (Expr *) lfirst(lc2);
951
952 /* not likely that we'd see constants here, so no check */
953 childquals = lappend(childquals,
955 true,
956 false, false,
957 false,
958 security_level,
959 NULL, NULL, NULL));
960 cq_min_security = Min(cq_min_security, security_level);
961 }
962 security_level++;
963 }
964 Assert(security_level <= root->qual_security_level);
965 }
966
967 /*
968 * OK, we've got all the baserestrictinfo quals for this child.
969 */
970 childrel->baserestrictinfo = childquals;
971 childrel->baserestrict_min_security = cq_min_security;
972
973 return true;
974}
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: appendinfo.c:200
#define Min(x, y)
Definition: c.h:1003
unsigned int Index
Definition: c.h:619
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2262
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:542
Assert(PointerIsAligned(start, uint64))
bool restriction_is_always_true(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: initsplan.c:3071
bool restriction_is_always_false(PlannerInfo *root, RestrictInfo *restrictinfo)
Definition: initsplan.c:3136
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
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: restrictinfo.c:52
Definition: primnodes.h:324
Definition: primnodes.h:189
Definition: pg_list.h:54
Definition: nodes.h:135
List * baserestrictinfo
Definition: pathnodes.h:1040
Index baserestrict_min_security
Definition: pathnodes.h:1044
bool is_pushed_down
Definition: pathnodes.h:2724
Index security_level
Definition: pathnodes.h:2743
bool is_clone
Definition: pathnodes.h:2734
Expr * clause
Definition: pathnodes.h:2721
bool has_clone
Definition: pathnodes.h:2733
Definition: pg_list.h:46
bool contain_vars_of_level(Node *node, int levelsup)
Definition: var.c:444

References adjust_appendrel_attrs(), Assert(), RelOptInfo::baserestrict_min_security, RelOptInfo::baserestrictinfo, RestrictInfo::clause, contain_vars_of_level(), contain_volatile_functions(), DatumGetBool(), eval_const_expressions(), RestrictInfo::has_clone, 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_inherited_rtentry()

void expand_inherited_rtentry ( PlannerInforoot,
RelOptInforel,
RangeTblEntryrte,
Index  rti 
)

Definition at line 86 of file inherit.c.

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

Referenced by add_other_rels_to_query(), and expand_appendrel_subquery().

get_rel_all_updated_cols()

Bitmapset * get_rel_all_updated_cols ( PlannerInforoot,
RelOptInforel 
)

Definition at line 662 of file inherit.c.

663{
664 Index relid;
665 RangeTblEntry *rte;
666 RTEPermissionInfo *perminfo;
667 Bitmapset *updatedCols,
668 *extraUpdatedCols;
669
670 Assert(root->parse->commandType == CMD_UPDATE);
671 Assert(IS_SIMPLE_REL(rel));
672
673 /*
674 * We obtain updatedCols for the query's result relation. Then, if
675 * necessary, we map it to the column numbers of the relation for which
676 * they were requested.
677 */
678 relid = root->parse->resultRelation;
679 rte = planner_rt_fetch(relid, root);
680 perminfo = getRTEPermissionInfo(root->parse->rteperminfos, rte);
681
682 updatedCols = perminfo->updatedCols;
683
684 if (rel->relid != relid)
685 {
686 RelOptInfo *top_parent_rel = find_base_rel(root, relid);
687
688 Assert(IS_OTHER_REL(rel));
689
690 updatedCols = translate_col_privs_multilevel(root, rel, top_parent_rel,
691 updatedCols);
692 }
693
694 /*
695 * Now we must check to see if there are any generated columns that depend
696 * on the updatedCols, and add them to the result.
697 */
698 extraUpdatedCols = get_dependent_generated_columns(root, rel->relid,
699 updatedCols);
700
701 return bms_union(updatedCols, extraUpdatedCols);
702}
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:766
@ CMD_UPDATE
Definition: nodes.h:276
#define IS_SIMPLE_REL(rel)
Definition: pathnodes.h:889
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:904
Bitmapset * get_dependent_generated_columns(PlannerInfo *root, Index rti, Bitmapset *target_cols)
Definition: plancat.c:2488
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:416
Index relid
Definition: pathnodes.h:967

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

Referenced by postgresPlanForeignModify().

AltStyle によって変換されたページ (->オリジナル) /