65{
67 int result_relation =
parse->resultRelation;
74
75 /*
76 * If there is a result relation, open it so we can look for missing
77 * columns and so on. We assume that previous code already acquired at
78 * least AccessShareLock on the relation, so we need no lock here.
79 */
80 if (result_relation)
81 {
82 target_rte =
rt_fetch(result_relation, range_table);
83
84 /*
85 * Sanity check: it'd better be a real relation not, say, a subquery.
86 * Else parser or rewriter messed up.
87 */
89 elog(
ERROR,
"result relation must be a regular relation");
90
92 }
93 else
95
96 /*
97 * In an INSERT, the executor expects the targetlist to match the exact
98 * order of the target table's attributes, including entries for
99 * attributes not mentioned in the source query.
100 *
101 * In an UPDATE, we don't rearrange the tlist order, but we need to make a
102 * separate list of the target attribute numbers, in tlist order, and then
103 * renumber the processed_tlist entries to be consecutive.
104 */
105 tlist =
parse->targetList;
110
111 /*
112 * For non-inherited UPDATE/DELETE/MERGE, register any junk column(s)
113 * needed to allow the executor to identify the rows to be updated or
114 * deleted. In the inheritance case, we do nothing now, leaving this to
115 * be dealt with when expand_inherited_rtentry() makes the leaf target
116 * relations. (But there might not be any leaf target relations, in which
117 * case we must do this in distribute_row_identity_vars().)
118 */
122 {
123 /* row-identity logic expects to add stuff to processed_tlist */
124 root->processed_tlist = tlist;
126 target_rte, target_relation);
127 tlist =
root->processed_tlist;
128 }
129
130 /*
131 * For MERGE we also need to handle the target list for each INSERT and
132 * UPDATE action separately. In addition, we examine the qual of each
133 * action and add any Vars there (other than those of the target rel) to
134 * the subplan targetlist.
135 */
137 {
140
141 /*
142 * For MERGE, handle targetlist of each MergeAction separately. Give
143 * the same treatment to MergeAction->targetList as we would have
144 * given to a regular INSERT. For UPDATE, collect the column numbers
145 * being modified.
146 */
147 foreach(l,
parse->mergeActionList)
148 {
151
155 target_relation);
159
160 /*
161 * Add resjunk entries for any Vars and PlaceHolderVars used in
162 * each action's targetlist and WHEN condition that belong to
163 * relations other than the target. We don't expect to see any
164 * aggregates or window functions here.
165 */
171 {
174
175 if (
IsA(var,
Var) && var->
varno == result_relation)
176 continue; /* don't need it */
177
179 continue; /* already got it */
180
183 NULL, true);
185 }
187 }
188
189 /*
190 * Add resjunk entries for any Vars and PlaceHolderVars used in the
191 * join condition that belong to relations other than the target. We
192 * don't expect to see any aggregates or window functions here.
193 */
197 {
200
201 if (
IsA(var,
Var) && var->
varno == result_relation)
202 continue; /* don't need it */
203
205 continue; /* already got it */
206
209 NULL, true);
211 }
212 }
213
214 /*
215 * Add necessary junk columns for rowmarked rels. These values are needed
216 * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
217 * rechecking. See comments for PlanRowMark in plannodes.h. If you
218 * change this stanza, see also expand_inherited_rtentry(), which has to
219 * be able to add on junk columns equivalent to these.
220 *
221 * (Someday it might be useful to fold these resjunk columns into the
222 * row-identity-column management used for UPDATE/DELETE. Today is not
223 * that day, however. One notable issue is that it seems important that
224 * the whole-row Vars made here use the real table rowtype, not RECORD, so
225 * that conversion to/from child relations' rowtypes will happen. Also,
226 * since these entries don't potentially bloat with more and more child
227 * relations, there's not really much need for column sharing.)
228 */
229 foreach(lc,
root->rowMarks)
230 {
233 char resname[32];
235
236 /* child rels use the same junk attrs as their parents */
238 continue;
239
241 {
242 /* Need to fetch TID */
245 TIDOID,
246 -1,
248 0);
253 true);
255 }
257 {
258 /* Need the whole row as a junk var */
261 0,
262 false);
267 true);
269 }
270
271 /* If parent of inheritance tree, always fetch the tableoid too. */
273 {
276 OIDOID,
277 -1,
279 0);
284 true);
286 }
287 }
288
289 /*
290 * If the query has a RETURNING list, add resjunk entries for any Vars
291 * used in RETURNING that belong to other relations. We need to do this
292 * to make these Vars available for the RETURNING calculation. Vars that
293 * belong to the result rel don't need to be added, because they will be
294 * made to refer to the actual heap tuple.
295 */
297 {
300
306 {
309
311 var->
varno == result_relation)
312 continue; /* don't need it */
313
315 continue; /* already got it */
316
319 NULL,
320 true);
321
323 }
325 }
326
327 root->processed_tlist = tlist;
328
329 if (target_relation)
331}
void add_row_identity_columns(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
Assert(PointerIsAligned(start, uint64))
List * list_concat_copy(const List *list1, const List *list2)
void list_free(List *list)
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
#define PVC_RECURSE_AGGREGATES
#define PVC_RECURSE_WINDOWFUNCS
#define PVC_INCLUDE_PLACEHOLDERS
#define rt_fetch(rangetable_index, rangetable)
static int list_length(const List *l)
List * extract_update_targetlist_colnos(List *tlist)
static List * expand_insert_targetlist(PlannerInfo *root, List *tlist, Relation rel)
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
#define TableOidAttributeNumber
#define SelfItemPointerAttributeNumber
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TargetEntry * tlist_member(Expr *node, List *targetlist)
List * pull_var_clause(Node *node, int flags)