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-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 *extract_update_colnos(List *tlist);
50 static List *expand_targetlist(List *tlist, int command_type,
51  Index result_relation, Relation rel);
52 
53 
54 /*
55  * preprocess_targetlist
56  * Driver for preprocessing the parse tree targetlist.
57  *
58  * The preprocessed targetlist is returned in root->processed_tlist.
59  * Also, if this is an UPDATE, we return a list of target column numbers
60  * in root->update_colnos. (Resnos in processed_tlist will be consecutive,
61  * so do not look at that to find out which columns are targets!)
62  *
63  * As a side effect, if there's an ON CONFLICT UPDATE clause, its targetlist
64  * is also preprocessed (and updated in-place).
65  */
66 void
68 {
69  Query *parse = root->parse;
70  int result_relation = parse->resultRelation;
71  List *range_table = parse->rtable;
72  CmdType command_type = parse->commandType;
73  RangeTblEntry *target_rte = NULL;
74  Relation target_relation = NULL;
75  List *tlist;
76  ListCell *lc;
77 
78  /*
79  * If there is a result relation, open it so we can look for missing
80  * columns and so on. We assume that previous code already acquired at
81  * least AccessShareLock on the relation, so we need no lock here.
82  */
83  if (result_relation)
84  {
85  target_rte = rt_fetch(result_relation, range_table);
86 
87  /*
88  * Sanity check: it'd better be a real relation not, say, a subquery.
89  * Else parser or rewriter messed up.
90  */
91  if (target_rte->rtekind != RTE_RELATION)
92  elog(ERROR, "result relation must be a regular relation");
93 
94  target_relation = table_open(target_rte->relid, NoLock);
95  }
96  else
97  Assert(command_type == CMD_SELECT);
98 
99  /*
100  * In an INSERT, the executor expects the targetlist to match the exact
101  * order of the target table's attributes, including entries for
102  * attributes not mentioned in the source query.
103  *
104  * In an UPDATE, we don't rearrange the tlist order, but we need to make a
105  * separate list of the target attribute numbers, in tlist order, and then
106  * renumber the processed_tlist entries to be consecutive.
107  */
108  tlist = parse->targetList;
109  if (command_type == CMD_INSERT)
110  tlist = expand_targetlist(tlist, command_type,
111  result_relation, target_relation);
112  else if (command_type == CMD_UPDATE)
113  root->update_colnos = extract_update_colnos(tlist);
114 
115  /*
116  * For non-inherited UPDATE/DELETE, register any junk column(s) needed to
117  * allow the executor to identify the rows to be updated or deleted. In
118  * the inheritance case, we do nothing now, leaving this to be dealt with
119  * when expand_inherited_rtentry() makes the leaf target relations. (But
120  * there might not be any leaf target relations, in which case we must do
121  * this in distribute_row_identity_vars().)
122  */
123  if ((command_type == CMD_UPDATE || command_type == CMD_DELETE) &&
124  !target_rte->inh)
125  {
126  /* row-identity logic expects to add stuff to processed_tlist */
127  root->processed_tlist = tlist;
128  add_row_identity_columns(root, result_relation,
129  target_rte, target_relation);
130  tlist = root->processed_tlist;
131  }
132 
133  /*
134  * Add necessary junk columns for rowmarked rels. These values are needed
135  * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
136  * rechecking. See comments for PlanRowMark in plannodes.h. If you
137  * change this stanza, see also expand_inherited_rtentry(), which has to
138  * be able to add on junk columns equivalent to these.
139  *
140  * (Someday it might be useful to fold these resjunk columns into the
141  * row-identity-column management used for UPDATE/DELETE. Today is not
142  * that day, however. One notable issue is that it seems important that
143  * the whole-row Vars made here use the real table rowtype, not RECORD, so
144  * that conversion to/from child relations' rowtypes will happen. Also,
145  * since these entries don't potentially bloat with more and more child
146  * relations, there's not really much need for column sharing.)
147  */
148  foreach(lc, root->rowMarks)
149  {
150  PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
151  Var *var;
152  char resname[32];
153  TargetEntry *tle;
154 
155  /* child rels use the same junk attrs as their parents */
156  if (rc->rti != rc->prti)
157  continue;
158 
159  if (rc->allMarkTypes & ~(1 << ROW_MARK_COPY))
160  {
161  /* Need to fetch TID */
162  var = makeVar(rc->rti,
164  TIDOID,
165  -1,
166  InvalidOid,
167  0);
168  snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
169  tle = makeTargetEntry((Expr *) var,
170  list_length(tlist) + 1,
171  pstrdup(resname),
172  true);
173  tlist = lappend(tlist, tle);
174  }
175  if (rc->allMarkTypes & (1 << ROW_MARK_COPY))
176  {
177  /* Need the whole row as a junk var */
178  var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
179  rc->rti,
180  0,
181  false);
182  snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
183  tle = makeTargetEntry((Expr *) var,
184  list_length(tlist) + 1,
185  pstrdup(resname),
186  true);
187  tlist = lappend(tlist, tle);
188  }
189 
190  /* If parent of inheritance tree, always fetch the tableoid too. */
191  if (rc->isParent)
192  {
193  var = makeVar(rc->rti,
195  OIDOID,
196  -1,
197  InvalidOid,
198  0);
199  snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
200  tle = makeTargetEntry((Expr *) var,
201  list_length(tlist) + 1,
202  pstrdup(resname),
203  true);
204  tlist = lappend(tlist, tle);
205  }
206  }
207 
208  /*
209  * If the query has a RETURNING list, add resjunk entries for any Vars
210  * used in RETURNING that belong to other relations. We need to do this
211  * to make these Vars available for the RETURNING calculation. Vars that
212  * belong to the result rel don't need to be added, because they will be
213  * made to refer to the actual heap tuple.
214  */
215  if (parse->returningList && list_length(parse->rtable) > 1)
216  {
217  List *vars;
218  ListCell *l;
219 
220  vars = pull_var_clause((Node *) parse->returningList,
224  foreach(l, vars)
225  {
226  Var *var = (Var *) lfirst(l);
227  TargetEntry *tle;
228 
229  if (IsA(var, Var) &&
230  var->varno == result_relation)
231  continue; /* don't need it */
232 
233  if (tlist_member((Expr *) var, tlist))
234  continue; /* already got it */
235 
236  tle = makeTargetEntry((Expr *) var,
237  list_length(tlist) + 1,
238  NULL,
239  true);
240 
241  tlist = lappend(tlist, tle);
242  }
243  list_free(vars);
244  }
245 
246  root->processed_tlist = tlist;
247 
248  /*
249  * If there's an ON CONFLICT UPDATE clause, preprocess its targetlist too
250  * while we have the relation open.
251  */
252  if (parse->onConflict)
253  parse->onConflict->onConflictSet =
255  CMD_UPDATE,
256  result_relation,
257  target_relation);
258 
259  if (target_relation)
260  table_close(target_relation, NoLock);
261 }
262 
263 /*
264  * extract_update_colnos
265  * Extract a list of the target-table column numbers that
266  * an UPDATE's targetlist wants to assign to, then renumber.
267  *
268  * The convention in the parser and rewriter is that the resnos in an
269  * UPDATE's non-resjunk TLE entries are the target column numbers
270  * to assign to. Here, we extract that info into a separate list, and
271  * then convert the tlist to the sequential-numbering convention that's
272  * used by all other query types.
273  */
274 static List *
276 {
277  List *update_colnos = NIL;
278  AttrNumber nextresno = 1;
279  ListCell *lc;
280 
281  foreach(lc, tlist)
282  {
283  TargetEntry *tle = (TargetEntry *) lfirst(lc);
284 
285  if (!tle->resjunk)
286  update_colnos = lappend_int(update_colnos, tle->resno);
287  tle->resno = nextresno++;
288  }
289  return update_colnos;
290 }
291 
292 
293 /*****************************************************************************
294  *
295  * TARGETLIST EXPANSION
296  *
297  *****************************************************************************/
298 
299 /*
300  * expand_targetlist
301  * Given a target list as generated by the parser and a result relation,
302  * add targetlist entries for any missing attributes, and ensure the
303  * non-junk attributes appear in proper field order.
304  *
305  * command_type is a bit of an archaism now: it's CMD_INSERT when we're
306  * processing an INSERT, all right, but the only other use of this function
307  * is for ON CONFLICT UPDATE tlists, for which command_type is CMD_UPDATE.
308  */
309 static List *
310 expand_targetlist(List *tlist, int command_type,
311  Index result_relation, Relation rel)
312 {
313  List *new_tlist = NIL;
314  ListCell *tlist_item;
315  int attrno,
316  numattrs;
317 
318  tlist_item = list_head(tlist);
319 
320  /*
321  * The rewriter should have already ensured that the TLEs are in correct
322  * order; but we have to insert TLEs for any missing attributes.
323  *
324  * Scan the tuple description in the relation's relcache entry to make
325  * sure we have all the user attributes in the right order.
326  */
327  numattrs = RelationGetNumberOfAttributes(rel);
328 
329  for (attrno = 1; attrno <= numattrs; attrno++)
330  {
331  Form_pg_attribute att_tup = TupleDescAttr(rel->rd_att, attrno - 1);
332  TargetEntry *new_tle = NULL;
333 
334  if (tlist_item != NULL)
335  {
336  TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
337 
338  if (!old_tle->resjunk && old_tle->resno == attrno)
339  {
340  new_tle = old_tle;
341  tlist_item = lnext(tlist, tlist_item);
342  }
343  }
344 
345  if (new_tle == NULL)
346  {
347  /*
348  * Didn't find a matching tlist entry, so make one.
349  *
350  * For INSERT, generate a NULL constant. (We assume the rewriter
351  * would have inserted any available default value.) Also, if the
352  * column isn't dropped, apply any domain constraints that might
353  * exist --- this is to catch domain NOT NULL.
354  *
355  * For UPDATE, generate a Var reference to the existing value of
356  * the attribute, so that it gets copied to the new tuple. But
357  * generate a NULL for dropped columns (we want to drop any old
358  * values).
359  *
360  * When generating a NULL constant for a dropped column, we label
361  * it INT4 (any other guaranteed-to-exist datatype would do as
362  * well). We can't label it with the dropped column's datatype
363  * since that might not exist anymore. It does not really matter
364  * what we claim the type is, since NULL is NULL --- its
365  * representation is datatype-independent. This could perhaps
366  * confuse code comparing the finished plan to the target
367  * relation, however.
368  */
369  Oid atttype = att_tup->atttypid;
370  int32 atttypmod = att_tup->atttypmod;
371  Oid attcollation = att_tup->attcollation;
372  Node *new_expr;
373 
374  switch (command_type)
375  {
376  case CMD_INSERT:
377  if (!att_tup->attisdropped)
378  {
379  new_expr = (Node *) makeConst(atttype,
380  -1,
381  attcollation,
382  att_tup->attlen,
383  (Datum) 0,
384  true, /* isnull */
385  att_tup->attbyval);
386  new_expr = coerce_to_domain(new_expr,
387  InvalidOid, -1,
388  atttype,
391  -1,
392  false);
393  }
394  else
395  {
396  /* Insert NULL for dropped column */
397  new_expr = (Node *) makeConst(INT4OID,
398  -1,
399  InvalidOid,
400  sizeof(int32),
401  (Datum) 0,
402  true, /* isnull */
403  true /* byval */ );
404  }
405  break;
406  case CMD_UPDATE:
407  if (!att_tup->attisdropped)
408  {
409  new_expr = (Node *) makeVar(result_relation,
410  attrno,
411  atttype,
412  atttypmod,
413  attcollation,
414  0);
415  }
416  else
417  {
418  /* Insert NULL for dropped column */
419  new_expr = (Node *) makeConst(INT4OID,
420  -1,
421  InvalidOid,
422  sizeof(int32),
423  (Datum) 0,
424  true, /* isnull */
425  true /* byval */ );
426  }
427  break;
428  default:
429  elog(ERROR, "unrecognized command_type: %d",
430  (int) command_type);
431  new_expr = NULL; /* keep compiler quiet */
432  break;
433  }
434 
435  new_tle = makeTargetEntry((Expr *) new_expr,
436  attrno,
437  pstrdup(NameStr(att_tup->attname)),
438  false);
439  }
440 
441  new_tlist = lappend(new_tlist, new_tle);
442  }
443 
444  /*
445  * The remaining tlist entries should be resjunk; append them all to the
446  * end of the new tlist, making sure they have resnos higher than the last
447  * real attribute. (Note: although the rewriter already did such
448  * renumbering, we have to do it again here in case we are doing an UPDATE
449  * in a table with dropped columns, or an inheritance child table with
450  * extra columns.)
451  */
452  while (tlist_item)
453  {
454  TargetEntry *old_tle = (TargetEntry *) lfirst(tlist_item);
455 
456  if (!old_tle->resjunk)
457  elog(ERROR, "targetlist is not sorted correctly");
458  /* Get the resno right, but don't copy unnecessarily */
459  if (old_tle->resno != attrno)
460  {
461  old_tle = flatCopyTargetEntry(old_tle);
462  old_tle->resno = attrno;
463  }
464  new_tlist = lappend(new_tlist, old_tle);
465  attrno++;
466  tlist_item = lnext(tlist, tlist_item);
467  }
468 
469  return new_tlist;
470 }
471 
472 
473 /*
474  * Locate PlanRowMark for given RT index, or return NULL if none
475  *
476  * This probably ought to be elsewhere, but there's no very good place
477  */
478 PlanRowMark *
479 get_plan_rowmark(List *rowmarks, Index rtindex)
480 {
481  ListCell *l;
482 
483  foreach(l, rowmarks)
484  {
485  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
486 
487  if (rc->rti == rtindex)
488  return rc;
489  }
490  return NULL;
491 }
#define NIL
Definition: pg_list.h:65
List * rowMarks
Definition: pathnodes.h:287
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Query * parse
Definition: pathnodes.h:161
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
OnConflictExpr * onConflict
Definition: parsenodes.h:154
#define RelationGetNumberOfAttributes(relation)
Definition: rel.h:478
static List * extract_update_colnos(List *tlist)
Definition: preptlist.c:275
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
char * pstrdup(const char *in)
Definition: mcxt.c:1299
void preprocess_targetlist(PlannerInfo *root)
Definition: preptlist.c:67
int resultRelation
Definition: parsenodes.h:130
Definition: nodes.h:539
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:133
Index prti
Definition: plannodes.h:1118
List * pull_var_clause(Node *node, int flags)
Definition: var.c:562
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:186
Index rowmarkId
Definition: plannodes.h:1119
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Definition: makefuncs.c:299
signed int int32
Definition: c.h:429
List * targetList
Definition: parsenodes.h:150
bool resjunk
Definition: primnodes.h:1451
List * rtable
Definition: parsenodes.h:147
#define ERROR
Definition: elog.h:46
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
#define NoLock
Definition: lockdefs.h:34
AttrNumber resno
Definition: primnodes.h:1445
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:203
#define TableOidAttributeNumber
Definition: sysattr.h:26
int allMarkTypes
Definition: plannodes.h:1121
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:271
List * returningList
Definition: parsenodes.h:156
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
List * lappend_int(List *list, int datum)
Definition: list.c:354
List * lappend(List *list, void *datum)
Definition: list.c:336
Index varno
Definition: primnodes.h:189
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:189
uintptr_t Datum
Definition: postgres.h:411
unsigned int Index
Definition: c.h:549
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:68
TupleDesc rd_att
Definition: rel.h:111
static List * expand_targetlist(List *tlist, int command_type, Index result_relation, Relation rel)
Definition: preptlist.c:310
#define InvalidOid
Definition: postgres_ext.h:36
CmdType commandType
Definition: parsenodes.h:120
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
RTEKind rtekind
Definition: parsenodes.h:995
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:188
void list_free(List *list)
Definition: list.c:1391
#define elog(elevel,...)
Definition: elog.h:232
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:479
List * onConflictSet
Definition: primnodes.h:1578
#define NameStr(name)
Definition: c.h:681
bool isParent
Definition: plannodes.h:1124
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
List * processed_tlist
Definition: pathnodes.h:320
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: regcomp.c:237
Definition: pg_list.h:50
#define snprintf
Definition: port.h:216
int16 AttrNumber
Definition: attnum.h:21
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:186
CmdType
Definition: nodes.h:682
void add_row_identity_columns(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
Definition: appendinfo.c:857
List * update_colnos
Definition: pathnodes.h:328
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:665