PostgreSQL Source Code  git master
preptlist.c
Go to the documentation of this file.
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-2022, 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
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)
108 
109  /*
110  * For non-inherited UPDATE/DELETE/MERGE, register any junk column(s)
111  * needed to allow the executor to identify the rows to be updated or
112  * deleted. In the inheritance case, we do nothing now, leaving this to
113  * be dealt with when expand_inherited_rtentry() makes the leaf target
114  * relations. (But there might not be any leaf target relations, in which
115  * case we must do this in distribute_row_identity_vars().)
116  */
117  if ((command_type == CMD_UPDATE || command_type == CMD_DELETE ||
118  command_type == CMD_MERGE) &&
119  !target_rte->inh)
120  {
121  /* row-identity logic expects to add stuff to processed_tlist */
122  root->processed_tlist = tlist;
123  add_row_identity_columns(root, result_relation,
124  target_rte, target_relation);
125  tlist = root->processed_tlist;
126  }
127 
128  /*
129  * For MERGE we also need to handle the target list for each INSERT and
130  * UPDATE action separately. In addition, we examine the qual of each
131  * action and add any Vars there (other than those of the target rel) to
132  * the subplan targetlist.
133  */
134  if (command_type == CMD_MERGE)
135  {
136  ListCell *l;
137 
138  /*
139  * For MERGE, handle targetlist of each MergeAction separately. Give
140  * the same treatment to MergeAction->targetList as we would have
141  * given to a regular INSERT. For UPDATE, collect the column numbers
142  * being modified.
143  */
144  foreach(l, parse->mergeActionList)
145  {
147  List *vars;
148  ListCell *l2;
149 
150  if (action->commandType == CMD_INSERT)
151  action->targetList = expand_insert_targetlist(action->targetList,
152  target_relation);
153  else if (action->commandType == CMD_UPDATE)
154  action->updateColnos =
156 
157  /*
158  * Add resjunk entries for any Vars used in each action's
159  * targetlist and WHEN condition that belong to relations other
160  * than target. Note that aggregates, window functions and
161  * placeholder vars are not possible anywhere in MERGE's WHEN
162  * clauses. (PHVs may be added later, but they don't concern us
163  * here.)
164  */
166  list_concat_copy((List *) action->qual,
167  action->targetList),
168  0);
169  foreach(l2, vars)
170  {
171  Var *var = (Var *) lfirst(l2);
172  TargetEntry *tle;
173 
174  if (IsA(var, Var) && var->varno == result_relation)
175  continue; /* don't need it */
176 
177  if (tlist_member((Expr *) var, tlist))
178  continue; /* already got it */
179 
180  tle = makeTargetEntry((Expr *) var,
181  list_length(tlist) + 1,
182  NULL, true);
183  tlist = lappend(tlist, tle);
184  }
185  list_free(vars);
186  }
187  }
188 
189  /*
190  * Add necessary junk columns for rowmarked rels. These values are needed
191  * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
192  * rechecking. See comments for PlanRowMark in plannodes.h. If you
193  * change this stanza, see also expand_inherited_rtentry(), which has to
194  * be able to add on junk columns equivalent to these.
195  *
196  * (Someday it might be useful to fold these resjunk columns into the
197  * row-identity-column management used for UPDATE/DELETE. Today is not
198  * that day, however. One notable issue is that it seems important that
199  * the whole-row Vars made here use the real table rowtype, not RECORD, so
200  * that conversion to/from child relations' rowtypes will happen. Also,
201  * since these entries don't potentially bloat with more and more child
202  * relations, there's not really much need for column sharing.)
203  */
204  foreach(lc, root->rowMarks)
205  {
206  PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
207  Var *var;
208  char resname[32];
209  TargetEntry *tle;
210 
211  /* child rels use the same junk attrs as their parents */
212  if (rc->rti != rc->prti)
213  continue;
214 
215  if (rc->allMarkTypes & ~(1 << ROW_MARK_COPY))
216  {
217  /* Need to fetch TID */
218  var = makeVar(rc->rti,
220  TIDOID,
221  -1,
222  InvalidOid,
223  0);
224  snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
225  tle = makeTargetEntry((Expr *) var,
226  list_length(tlist) + 1,
227  pstrdup(resname),
228  true);
229  tlist = lappend(tlist, tle);
230  }
231  if (rc->allMarkTypes & (1 << ROW_MARK_COPY))
232  {
233  /* Need the whole row as a junk var */
234  var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
235  rc->rti,
236  0,
237  false);
238  snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
239  tle = makeTargetEntry((Expr *) var,
240  list_length(tlist) + 1,
241  pstrdup(resname),
242  true);
243  tlist = lappend(tlist, tle);
244  }
245 
246  /* If parent of inheritance tree, always fetch the tableoid too. */
247  if (rc->isParent)
248  {
249  var = makeVar(rc->rti,
251  OIDOID,
252  -1,
253  InvalidOid,
254  0);
255  snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
256  tle = makeTargetEntry((Expr *) var,
257  list_length(tlist) + 1,
258  pstrdup(resname),
259  true);
260  tlist = lappend(tlist, tle);
261  }
262  }
263 
264  /*
265  * If the query has a RETURNING list, add resjunk entries for any Vars
266  * used in RETURNING that belong to other relations. We need to do this
267  * to make these Vars available for the RETURNING calculation. Vars that
268  * belong to the result rel don't need to be added, because they will be
269  * made to refer to the actual heap tuple.
270  */
271  if (parse->returningList && list_length(parse->rtable) > 1)
272  {
273  List *vars;
274  ListCell *l;
275 
276  vars = pull_var_clause((Node *) parse->returningList,
280  foreach(l, vars)
281  {
282  Var *var = (Var *) lfirst(l);
283  TargetEntry *tle;
284 
285  if (IsA(var, Var) &&
286  var->varno == result_relation)
287  continue; /* don't need it */
288 
289  if (tlist_member((Expr *) var, tlist))
290  continue; /* already got it */
291 
292  tle = makeTargetEntry((Expr *) var,
293  list_length(tlist) + 1,
294  NULL,
295  true);
296 
297  tlist = lappend(tlist, tle);
298  }
299  list_free(vars);
300  }
301 
302  root->processed_tlist = tlist;
303 
304  if (target_relation)
305  table_close(target_relation, NoLock);
306 }
307 
308 /*
309  * extract_update_targetlist_colnos
310  * Extract a list of the target-table column numbers that
311  * an UPDATE's targetlist wants to assign to, then renumber.
312  *
313  * The convention in the parser and rewriter is that the resnos in an
314  * UPDATE's non-resjunk TLE entries are the target column numbers
315  * to assign to. Here, we extract that info into a separate list, and
316  * then convert the tlist to the sequential-numbering convention that's
317  * used by all other query types.
318  *
319  * This is also applied to the tlist associated with INSERT ... ON CONFLICT
320  * ... UPDATE, although not till much later in planning.
321  */
322 List *
324 {
325  List *update_colnos = NIL;
326  AttrNumber nextresno = 1;
327  ListCell *lc;
328 
329  foreach(lc, tlist)
330  {
331  TargetEntry *tle = (TargetEntry *) lfirst(lc);
332 
333  if (!tle->resjunk)
334  update_colnos = lappend_int(update_colnos, tle->resno);
335  tle->resno = nextresno++;
336  }
337  return update_colnos;
338 }
339 
340 
341 /*****************************************************************************
342  *
343  * TARGETLIST EXPANSION
344  *
345  *****************************************************************************/
346 
347 /*
348  * expand_insert_targetlist
349  * Given a target list as generated by the parser and a result relation,
350  * add targetlist entries for any missing attributes, and ensure the
351  * non-junk attributes appear in proper field order.
352  *
353  * Once upon a time we also did more or less this with UPDATE targetlists,
354  * but now this code is only applied to INSERT targetlists.
355  */
356 static List *
358 {
359  List *new_tlist = NIL;
360  ListCell *tlist_item;
361  int attrno,
362  numattrs;
363 
364  tlist_item = list_head(tlist);
365 
366  /*
367  * The rewriter should have already ensured that the TLEs are in correct
368  * order; but we have to insert TLEs for any missing attributes.
369  *
370  * Scan the tuple description in the relation's relcache entry to make
371  * sure we have all the user attributes in the right order.
372  */
373  numattrs = RelationGetNumberOfAttributes(rel);
374 
375  for (attrno = 1; attrno <= numattrs; attrno++)
376  {
377  Form_pg_attribute att_tup = TupleDescAttr(rel->rd_att, attrno - 1);
378  TargetEntry *new_tle = NULL;
379 
380  if (tlist_item != NULL)
381  {
382  TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
383 
384  if (!old_tle->resjunk && old_tle->resno == attrno)
385  {
386  new_tle = old_tle;
387  tlist_item = lnext(tlist, tlist_item);
388  }
389  }
390 
391  if (new_tle == NULL)
392  {
393  /*
394  * Didn't find a matching tlist entry, so make one.
395  *
396  * INSERTs should insert NULL in this case. (We assume the
397  * rewriter would have inserted any available non-NULL default
398  * value.) Also, if the column isn't dropped, apply any domain
399  * constraints that might exist --- this is to catch domain NOT
400  * NULL.
401  *
402  * When generating a NULL constant for a dropped column, we label
403  * it INT4 (any other guaranteed-to-exist datatype would do as
404  * well). We can't label it with the dropped column's datatype
405  * since that might not exist anymore. It does not really matter
406  * what we claim the type is, since NULL is NULL --- its
407  * representation is datatype-independent. This could perhaps
408  * confuse code comparing the finished plan to the target
409  * relation, however.
410  */
411  Oid atttype = att_tup->atttypid;
412  Oid attcollation = att_tup->attcollation;
413  Node *new_expr;
414 
415  if (!att_tup->attisdropped)
416  {
417  new_expr = (Node *) makeConst(atttype,
418  -1,
419  attcollation,
420  att_tup->attlen,
421  (Datum) 0,
422  true, /* isnull */
423  att_tup->attbyval);
424  new_expr = coerce_to_domain(new_expr,
425  InvalidOid, -1,
426  atttype,
429  -1,
430  false);
431  }
432  else
433  {
434  /* Insert NULL for dropped column */
435  new_expr = (Node *) makeConst(INT4OID,
436  -1,
437  InvalidOid,
438  sizeof(int32),
439  (Datum) 0,
440  true, /* isnull */
441  true /* byval */ );
442  }
443 
444  new_tle = makeTargetEntry((Expr *) new_expr,
445  attrno,
446  pstrdup(NameStr(att_tup->attname)),
447  false);
448  }
449 
450  new_tlist = lappend(new_tlist, new_tle);
451  }
452 
453  /*
454  * The remaining tlist entries should be resjunk; append them all to the
455  * end of the new tlist, making sure they have resnos higher than the last
456  * real attribute. (Note: although the rewriter already did such
457  * renumbering, we have to do it again here in case we added NULL entries
458  * above.)
459  */
460  while (tlist_item)
461  {
462  TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
463 
464  if (!old_tle->resjunk)
465  elog(ERROR, "targetlist is not sorted correctly");
466  /* Get the resno right, but don't copy unnecessarily */
467  if (old_tle->resno != attrno)
468  {
469  old_tle = flatCopyTargetEntry(old_tle);
470  old_tle->resno = attrno;
471  }
472  new_tlist = lappend(new_tlist, old_tle);
473  attrno++;
474  tlist_item = lnext(tlist, tlist_item);
475  }
476 
477  return new_tlist;
478 }
479 
480 
481 /*
482  * Locate PlanRowMark for given RT index, or return NULL if none
483  *
484  * This probably ought to be elsewhere, but there's no very good place
485  */
486 PlanRowMark *
487 get_plan_rowmark(List *rowmarks, Index rtindex)
488 {
489  ListCell *l;
490 
491  foreach(l, rowmarks)
492  {
493  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
494 
495  if (rc->rti == rtindex)
496  return rc;
497  }
498  return NULL;
499 }
void add_row_identity_columns(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
Definition: appendinfo.c:839
int16 AttrNumber
Definition: attnum.h:21
#define NameStr(name)
Definition: c.h:682
signed int int32
Definition: c.h:430
unsigned int Index
Definition: c.h:550
#define ERROR
Definition: elog.h:39
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
List * lappend_int(List *list, int datum)
Definition: list.c:356
void list_free(List *list)
Definition: list.c:1545
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:597
#define NoLock
Definition: lockdefs.h:34
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:133
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:271
char * pstrdup(const char *in)
Definition: mcxt.c:1483
#define IsA(nodeptr, _type_)
Definition: nodes.h:168
CmdType
Definition: nodes.h:263
@ CMD_MERGE
Definition: nodes.h:269
@ CMD_INSERT
Definition: nodes.h:267
@ CMD_DELETE
Definition: nodes.h:268
@ CMD_UPDATE
Definition: nodes.h:266
@ CMD_SELECT
Definition: nodes.h:265
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:184
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:186
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:187
Node * coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId, CoercionContext ccontext, CoercionForm cformat, int location, bool hideInputCoercion)
Definition: parse_coerce.c:676
@ RTE_RELATION
Definition: parsenodes.h:982
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
#define lfirst(lc)
Definition: pg_list.h:170
static int list_length(const List *l)
Definition: pg_list.h:150
#define NIL
Definition: pg_list.h:66
static ListCell * list_head(const List *l)
Definition: pg_list.h:126
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:341
@ ROW_MARK_COPY
Definition: plannodes.h:1333
#define snprintf
Definition: port.h:238
uintptr_t Datum
Definition: postgres.h:412
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:487
void preprocess_targetlist(PlannerInfo *root)
Definition: preptlist.c:62
static List * expand_insert_targetlist(List *tlist, Relation rel)
Definition: preptlist.c:357
List * extract_update_targetlist_colnos(List *tlist)
Definition: preptlist.c:323
@ COERCE_IMPLICIT_CAST
Definition: primnodes.h:588
@ COERCION_IMPLICIT
Definition: primnodes.h:566
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:507
Definition: pg_list.h:52
Definition: nodes.h:118
Index prti
Definition: plannodes.h:1382
bool isParent
Definition: plannodes.h:1388
Index rowmarkId
Definition: plannodes.h:1383
int allMarkTypes
Definition: plannodes.h:1385
List * processed_tlist
Definition: pathnodes.h:418
Query * parse
Definition: pathnodes.h:202
List * rowMarks
Definition: pathnodes.h:361
List * update_colnos
Definition: pathnodes.h:426
RTEKind rtekind
Definition: parsenodes.h:1001
TupleDesc rd_att
Definition: rel.h:111
AttrNumber resno
Definition: primnodes.h:1556
bool resjunk
Definition: primnodes.h:1562
Definition: primnodes.h:205
int varno
Definition: primnodes.h:212
Definition: regcomp.c:282
#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
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:79
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
List * pull_var_clause(Node *node, int flags)
Definition: var.c:597