88{
93 bool old_isParent = false;
94 int old_allMarkTypes = 0;
95
97
99 {
101 return;
102 }
103
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 */
130 if (oldrc)
131 {
134 /* Save initial value of allMarkTypes before children add to it */
136 }
137
138 /* Scan the inheritance set and expand it */
139 if (oldrelation->
rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
140 {
142
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 */
155 oldrelation,
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 */
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 */
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
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 */
210 {
212 continue;
213 }
214
215 /* Create RTE and AppendRelInfo, plus PlanRowMark if needed. */
217 oldrc, newrelation,
218 &childrte, &childRTindex);
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 {
245 char resname[32];
247
248 /* Add TID junk Var if needed, unless we had it already */
251 {
252 /* Need to fetch TID */
255 TIDOID,
256 -1,
258 0);
263 true);
265 newvars =
lappend(newvars, var);
266 }
267
268 /* Add whole-row junk Var if needed, unless we had it already */
271 {
274 0,
275 false);
280 true);
282 newvars =
lappend(newvars, var);
283 }
284
285 /* Add tableoid junk Var, unless we had it already */
286 if (!old_isParent)
287 {
290 OIDOID,
291 -1,
293 0);
298 true);
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)
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_appendrel_subquery(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte, Index rti)
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)
void add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
char * pstrdup(const char *in)
RTEPermissionInfo * getRTEPermissionInfo(List *rteperminfos, RangeTblEntry *rte)
#define planner_rt_fetch(rti, root)
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
static int list_length(const List *l)
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
#define RELATION_IS_OTHER_TEMP(relation)
void expand_planner_arrays(PlannerInfo *root, int add_size)
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
#define TableOidAttributeNumber
#define SelfItemPointerAttributeNumber
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)