1 /*-------------------------------------------------------------------------
2  *
3  * preptlist.c
4  *	  Routines to preprocess the parse tree target list
5  *
6  * For an INSERT, the targetlist must contain an entry for each attribute of
7  * the target relation in the correct order.
8  *
9  * For an UPDATE, the targetlist just contains the expressions for the new
10  * column values.
11  *
12  * For UPDATE and DELETE queries, the targetlist must also contain "junk"
13  * tlist entries needed to allow the executor to identify the rows to be
14  * updated or deleted; for example, the ctid of a heap row.  (The planner
15  * adds these; they're not in what we receive from the planner/rewriter.)
16  *
17  * For all query types, there can be additional junk tlist entries, such as
18  * sort keys, Vars needed for a RETURNING list, and row ID information needed
19  * for SELECT FOR UPDATE locking and/or EvalPlanQual checking.
20  *
21  * The query rewrite phase also does preprocessing of the targetlist (see
22  * rewriteTargetListIU).  The division of labor between here and there is
23  * partially historical, but it's not entirely arbitrary.  The stuff done
24  * here is closely connected to physical access to tables, whereas the
25  * rewriter's work is more concerned with SQL semantics.
26  *
27  *
28  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
29  * Portions Copyright (c) 1994, Regents of the University of California
30  *
31  * IDENTIFICATION
32  *	  src/backend/optimizer/prep/preptlist.c
33  *
34  *-------------------------------------------------------------------------
35  */
36 
37 #include "postgres.h"
38 
39 #include "access/table.h"
40 #include "nodes/makefuncs.h"
41 #include "optimizer/appendinfo.h"
42 #include "optimizer/optimizer.h"
43 #include "optimizer/prep.h"
44 #include "optimizer/tlist.h"
45 #include "parser/parse_coerce.h"
46 #include "parser/parsetree.h"
47 #include "utils/rel.h"
48 
49 static List *expand_insert_targetlist(List *tlist, Relation rel);
50 
51 
52 /*
53  * preprocess_targetlist
54  *	  Driver for preprocessing the parse tree targetlist.
55  *
56  * The preprocessed targetlist is returned in root->processed_tlist.
57  * Also, if this is an UPDATE, we return a list of target column numbers
58  * in root->update_colnos.  (Resnos in processed_tlist will be consecutive,
59  * so do not look at that to find out which columns are targets!)
60  */
61 void
preprocess_targetlist(PlannerInfo * root)62 preprocess_targetlist(PlannerInfo *root)
63 {
64 	Query	   *parse = root->parse;
65 	int			result_relation = parse->resultRelation;
66 	List	   *range_table = parse->rtable;
67 	CmdType		command_type = parse->commandType;
68 	RangeTblEntry *target_rte = NULL;
69 	Relation	target_relation = NULL;
70 	List	   *tlist;
71 	ListCell   *lc;
72 
73 	/*
74 	 * If there is a result relation, open it so we can look for missing
75 	 * columns and so on.  We assume that previous code already acquired at
76 	 * least AccessShareLock on the relation, so we need no lock here.
77 	 */
78 	if (result_relation)
79 	{
80 		target_rte = rt_fetch(result_relation, range_table);
81 
82 		/*
83 		 * Sanity check: it'd better be a real relation not, say, a subquery.
84 		 * Else parser or rewriter messed up.
85 		 */
86 		if (target_rte->rtekind != RTE_RELATION)
87 			elog(ERROR, "result relation must be a regular relation");
88 
89 		target_relation = table_open(target_rte->relid, NoLock);
90 	}
91 	else
92 		Assert(command_type == CMD_SELECT);
93 
94 	/*
95 	 * In an INSERT, the executor expects the targetlist to match the exact
96 	 * order of the target table's attributes, including entries for
97 	 * attributes not mentioned in the source query.
98 	 *
99 	 * In an UPDATE, we don't rearrange the tlist order, but we need to make a
100 	 * separate list of the target attribute numbers, in tlist order, and then
101 	 * renumber the processed_tlist entries to be consecutive.
102 	 */
103 	tlist = parse->targetList;
104 	if (command_type == CMD_INSERT)
105 		tlist = expand_insert_targetlist(tlist, target_relation);
106 	else if (command_type == CMD_UPDATE)
107 		root->update_colnos = extract_update_targetlist_colnos(tlist);
108 
109 	/*
110 	 * For non-inherited UPDATE/DELETE, register any junk column(s) needed to
111 	 * allow the executor to identify the rows to be updated or deleted.  In
112 	 * the inheritance case, we do nothing now, leaving this to be dealt with
113 	 * when expand_inherited_rtentry() makes the leaf target relations.  (But
114 	 * there might not be any leaf target relations, in which case we must do
115 	 * this in distribute_row_identity_vars().)
116 	 */
117 	if ((command_type == CMD_UPDATE || command_type == CMD_DELETE) &&
118 		!target_rte->inh)
119 	{
120 		/* row-identity logic expects to add stuff to processed_tlist */
121 		root->processed_tlist = tlist;
122 		add_row_identity_columns(root, result_relation,
123 								 target_rte, target_relation);
124 		tlist = root->processed_tlist;
125 	}
126 
127 	/*
128 	 * Add necessary junk columns for rowmarked rels.  These values are needed
129 	 * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
130 	 * rechecking.  See comments for PlanRowMark in plannodes.h.  If you
131 	 * change this stanza, see also expand_inherited_rtentry(), which has to
132 	 * be able to add on junk columns equivalent to these.
133 	 *
134 	 * (Someday it might be useful to fold these resjunk columns into the
135 	 * row-identity-column management used for UPDATE/DELETE.  Today is not
136 	 * that day, however.  One notable issue is that it seems important that
137 	 * the whole-row Vars made here use the real table rowtype, not RECORD, so
138 	 * that conversion to/from child relations' rowtypes will happen.  Also,
139 	 * since these entries don't potentially bloat with more and more child
140 	 * relations, there's not really much need for column sharing.)
141 	 */
142 	foreach(lc, root->rowMarks)
143 	{
144 		PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
145 		Var		   *var;
146 		char		resname[32];
147 		TargetEntry *tle;
148 
149 		/* child rels use the same junk attrs as their parents */
150 		if (rc->rti != rc->prti)
151 			continue;
152 
153 		if (rc->allMarkTypes & ~(1 << ROW_MARK_COPY))
154 		{
155 			/* Need to fetch TID */
156 			var = makeVar(rc->rti,
157 						  SelfItemPointerAttributeNumber,
158 						  TIDOID,
159 						  -1,
160 						  InvalidOid,
161 						  0);
162 			snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
163 			tle = makeTargetEntry((Expr *) var,
164 								  list_length(tlist) + 1,
165 								  pstrdup(resname),
166 								  true);
167 			tlist = lappend(tlist, tle);
168 		}
169 		if (rc->allMarkTypes & (1 << ROW_MARK_COPY))
170 		{
171 			/* Need the whole row as a junk var */
172 			var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
173 								  rc->rti,
174 								  0,
175 								  false);
176 			snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
177 			tle = makeTargetEntry((Expr *) var,
178 								  list_length(tlist) + 1,
179 								  pstrdup(resname),
180 								  true);
181 			tlist = lappend(tlist, tle);
182 		}
183 
184 		/* If parent of inheritance tree, always fetch the tableoid too. */
185 		if (rc->isParent)
186 		{
187 			var = makeVar(rc->rti,
188 						  TableOidAttributeNumber,
189 						  OIDOID,
190 						  -1,
191 						  InvalidOid,
192 						  0);
193 			snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
194 			tle = makeTargetEntry((Expr *) var,
195 								  list_length(tlist) + 1,
196 								  pstrdup(resname),
197 								  true);
198 			tlist = lappend(tlist, tle);
199 		}
200 	}
201 
202 	/*
203 	 * If the query has a RETURNING list, add resjunk entries for any Vars
204 	 * used in RETURNING that belong to other relations.  We need to do this
205 	 * to make these Vars available for the RETURNING calculation.  Vars that
206 	 * belong to the result rel don't need to be added, because they will be
207 	 * made to refer to the actual heap tuple.
208 	 */
209 	if (parse->returningList && list_length(parse->rtable) > 1)
210 	{
211 		List	   *vars;
212 		ListCell   *l;
213 
214 		vars = pull_var_clause((Node *) parse->returningList,
215 							   PVC_RECURSE_AGGREGATES |
216 							   PVC_RECURSE_WINDOWFUNCS |
217 							   PVC_INCLUDE_PLACEHOLDERS);
218 		foreach(l, vars)
219 		{
220 			Var		   *var = (Var *) lfirst(l);
221 			TargetEntry *tle;
222 
223 			if (IsA(var, Var) &&
224 				var->varno == result_relation)
225 				continue;		/* don't need it */
226 
227 			if (tlist_member((Expr *) var, tlist))
228 				continue;		/* already got it */
229 
230 			tle = makeTargetEntry((Expr *) var,
231 								  list_length(tlist) + 1,
232 								  NULL,
233 								  true);
234 
235 			tlist = lappend(tlist, tle);
236 		}
237 		list_free(vars);
238 	}
239 
240 	root->processed_tlist = tlist;
241 
242 	if (target_relation)
243 		table_close(target_relation, NoLock);
244 }
245 
246 /*
247  * extract_update_targetlist_colnos
248  * 		Extract a list of the target-table column numbers that
249  * 		an UPDATE's targetlist wants to assign to, then renumber.
250  *
251  * The convention in the parser and rewriter is that the resnos in an
252  * UPDATE's non-resjunk TLE entries are the target column numbers
253  * to assign to.  Here, we extract that info into a separate list, and
254  * then convert the tlist to the sequential-numbering convention that's
255  * used by all other query types.
256  *
257  * This is also applied to the tlist associated with INSERT ... ON CONFLICT
258  * ... UPDATE, although not till much later in planning.
259  */
260 List *
extract_update_targetlist_colnos(List * tlist)261 extract_update_targetlist_colnos(List *tlist)
262 {
263 	List	   *update_colnos = NIL;
264 	AttrNumber	nextresno = 1;
265 	ListCell   *lc;
266 
267 	foreach(lc, tlist)
268 	{
269 		TargetEntry *tle = (TargetEntry *) lfirst(lc);
270 
271 		if (!tle->resjunk)
272 			update_colnos = lappend_int(update_colnos, tle->resno);
273 		tle->resno = nextresno++;
274 	}
275 	return update_colnos;
276 }
277 
278 
279 /*****************************************************************************
280  *
281  *		TARGETLIST EXPANSION
282  *
283  *****************************************************************************/
284 
285 /*
286  * expand_insert_targetlist
287  *	  Given a target list as generated by the parser and a result relation,
288  *	  add targetlist entries for any missing attributes, and ensure the
289  *	  non-junk attributes appear in proper field order.
290  *
291  * Once upon a time we also did more or less this with UPDATE targetlists,
292  * but now this code is only applied to INSERT targetlists.
293  */
294 static List *
expand_insert_targetlist(List * tlist,Relation rel)295 expand_insert_targetlist(List *tlist, Relation rel)
296 {
297 	List	   *new_tlist = NIL;
298 	ListCell   *tlist_item;
299 	int			attrno,
300 				numattrs;
301 
302 	tlist_item = list_head(tlist);
303 
304 	/*
305 	 * The rewriter should have already ensured that the TLEs are in correct
306 	 * order; but we have to insert TLEs for any missing attributes.
307 	 *
308 	 * Scan the tuple description in the relation's relcache entry to make
309 	 * sure we have all the user attributes in the right order.
310 	 */
311 	numattrs = RelationGetNumberOfAttributes(rel);
312 
313 	for (attrno = 1; attrno <= numattrs; attrno++)
314 	{
315 		Form_pg_attribute att_tup = TupleDescAttr(rel->rd_att, attrno - 1);
316 		TargetEntry *new_tle = NULL;
317 
318 		if (tlist_item != NULL)
319 		{
320 			TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
321 
322 			if (!old_tle->resjunk && old_tle->resno == attrno)
323 			{
324 				new_tle = old_tle;
325 				tlist_item = lnext(tlist, tlist_item);
326 			}
327 		}
328 
329 		if (new_tle == NULL)
330 		{
331 			/*
332 			 * Didn't find a matching tlist entry, so make one.
333 			 *
334 			 * INSERTs should insert NULL in this case.  (We assume the
335 			 * rewriter would have inserted any available non-NULL default
336 			 * value.)  Also, if the column isn't dropped, apply any domain
337 			 * constraints that might exist --- this is to catch domain NOT
338 			 * NULL.
339 			 *
340 			 * When generating a NULL constant for a dropped column, we label
341 			 * it INT4 (any other guaranteed-to-exist datatype would do as
342 			 * well). We can't label it with the dropped column's datatype
343 			 * since that might not exist anymore.  It does not really matter
344 			 * what we claim the type is, since NULL is NULL --- its
345 			 * representation is datatype-independent.  This could perhaps
346 			 * confuse code comparing the finished plan to the target
347 			 * relation, however.
348 			 */
349 			Oid			atttype = att_tup->atttypid;
350 			Oid			attcollation = att_tup->attcollation;
351 			Node	   *new_expr;
352 
353 			if (!att_tup->attisdropped)
354 			{
355 				new_expr = (Node *) makeConst(atttype,
356 											  -1,
357 											  attcollation,
358 											  att_tup->attlen,
359 											  (Datum) 0,
360 											  true, /* isnull */
361 											  att_tup->attbyval);
362 				new_expr = coerce_to_domain(new_expr,
363 											InvalidOid, -1,
364 											atttype,
365 											COERCION_IMPLICIT,
366 											COERCE_IMPLICIT_CAST,
367 											-1,
368 											false);
369 			}
370 			else
371 			{
372 				/* Insert NULL for dropped column */
373 				new_expr = (Node *) makeConst(INT4OID,
374 											  -1,
375 											  InvalidOid,
376 											  sizeof(int32),
377 											  (Datum) 0,
378 											  true, /* isnull */
379 											  true /* byval */ );
380 			}
381 
382 			new_tle = makeTargetEntry((Expr *) new_expr,
383 									  attrno,
384 									  pstrdup(NameStr(att_tup->attname)),
385 									  false);
386 		}
387 
388 		new_tlist = lappend(new_tlist, new_tle);
389 	}
390 
391 	/*
392 	 * The remaining tlist entries should be resjunk; append them all to the
393 	 * end of the new tlist, making sure they have resnos higher than the last
394 	 * real attribute.  (Note: although the rewriter already did such
395 	 * renumbering, we have to do it again here in case we added NULL entries
396 	 * above.)
397 	 */
398 	while (tlist_item)
399 	{
400 		TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
401 
402 		if (!old_tle->resjunk)
403 			elog(ERROR, "targetlist is not sorted correctly");
404 		/* Get the resno right, but don't copy unnecessarily */
405 		if (old_tle->resno != attrno)
406 		{
407 			old_tle = flatCopyTargetEntry(old_tle);
408 			old_tle->resno = attrno;
409 		}
410 		new_tlist = lappend(new_tlist, old_tle);
411 		attrno++;
412 		tlist_item = lnext(tlist, tlist_item);
413 	}
414 
415 	return new_tlist;
416 }
417 
418 
419 /*
420  * Locate PlanRowMark for given RT index, or return NULL if none
421  *
422  * This probably ought to be elsewhere, but there's no very good place
423  */
424 PlanRowMark *
get_plan_rowmark(List * rowmarks,Index rtindex)425 get_plan_rowmark(List *rowmarks, Index rtindex)
426 {
427 	ListCell   *l;
428 
429 	foreach(l, rowmarks)
430 	{
431 		PlanRowMark *rc = (PlanRowMark *) lfirst(l);
432 
433 		if (rc->rti == rtindex)
434 			return rc;
435 	}
436 	return NULL;
437 }
438