1 /*-------------------------------------------------------------------------
4 * Routines to preprocess the parse tree target list
6 * This module takes care of altering the query targetlist as needed for
7 * INSERT, UPDATE, and DELETE queries. For INSERT and UPDATE queries,
8 * the targetlist must contain an entry for each attribute of the target
9 * relation in the correct order. For both UPDATE and DELETE queries,
10 * we need a junk targetlist entry holding the CTID attribute --- the
11 * executor relies on this to find the tuple to be replaced/deleted.
12 * We may also need junk tlist entries for Vars used in the RETURNING list.
15 * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
16 * Portions Copyright (c) 1994, Regents of the University of California
21 *-------------------------------------------------------------------------
26 #include "access/heapam.h"
27 #include "access/sysattr.h"
28 #include "catalog/pg_type.h"
29 #include "nodes/makefuncs.h"
30 #include "optimizer/prep.h"
31 #include "optimizer/subselect.h"
32 #include "optimizer/tlist.h"
33 #include "optimizer/var.h"
34 #include "parser/analyze.h"
35 #include "parser/parsetree.h"
36 #include "parser/parse_coerce.h"
37 #include "utils/rel.h"
40 static List
*expand_targetlist(List
*tlist
, int command_type
,
41 Index result_relation
, List
*range_table
);
45 * preprocess_targetlist
46 * Driver for preprocessing the parse tree targetlist.
48 * Returns the new targetlist.
51 preprocess_targetlist(PlannerInfo
*root
, List
*tlist
)
53 Query
*parse
= root
->parse
;
54 int result_relation
= parse
->resultRelation
;
55 List
*range_table
= parse
->rtable
;
56 CmdType command_type
= parse
->commandType
;
59 * Sanity check: if there is a result relation, it'd better be a real
60 * relation not a subquery. Else parser or rewriter messed up.
64 RangeTblEntry
*rte
= rt_fetch(result_relation
, range_table
);
66 if (rte
->subquery
!= NULL
|| rte
->relid
== InvalidOid
)
67 elog(ERROR
, "subquery cannot be result relation");
71 * for heap_form_tuple to work, the targetlist must match the exact order
72 * of the attributes. We also need to fill in any missing attributes. -ay
75 if (command_type
== CMD_INSERT
|| command_type
== CMD_UPDATE
)
76 tlist
= expand_targetlist(tlist
, command_type
,
77 result_relation
, range_table
);
80 * for "update" and "delete" queries, add ctid of the result relation into
81 * the target list so that the ctid will propagate through execution and
82 * ExecutePlan() will be able to identify the right tuple to replace or
83 * delete. This extra field is marked "junk" so that it is not stored
84 * back into the tuple.
86 if (command_type
== CMD_UPDATE
|| command_type
== CMD_DELETE
)
91 var
= makeVar(result_relation
, SelfItemPointerAttributeNumber
,
94 tle
= makeTargetEntry((Expr
*) var
,
95 list_length(tlist
) + 1,
100 * For an UPDATE, expand_targetlist already created a fresh tlist. For
101 * DELETE, better do a listCopy so that we don't destructively modify
102 * the original tlist (is this really necessary?).
104 if (command_type
== CMD_DELETE
)
105 tlist
= list_copy(tlist
);
107 tlist
= lappend(tlist
, tle
);
111 * Add TID targets for rels selected FOR UPDATE/SHARE. The executor uses
112 * the TID to know which rows to lock, much as for UPDATE or DELETE.
119 * We've got trouble if the FOR UPDATE/SHARE appears inside grouping,
120 * since grouping renders a reference to individual tuple CTIDs
121 * invalid. This is also checked at parse time, but that's
122 * insufficient because of rule substitution, query pullup, etc.
124 CheckSelectLocking(parse
);
127 * Currently the executor only supports FOR UPDATE/SHARE at top level
129 if (root
->query_level
> 1)
131 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
132 errmsg("SELECT FOR UPDATE/SHARE is not allowed in subqueries")));
134 foreach(l
, parse
->rowMarks
)
136 RowMarkClause
*rc
= (RowMarkClause
*) lfirst(l
);
141 /* ignore child rels */
142 if (rc
->rti
!= rc
->prti
)
145 /* always need the ctid */
146 var
= makeVar(rc
->rti
,
147 SelfItemPointerAttributeNumber
,
152 resname
= (char *) palloc(32);
153 snprintf(resname
, 32, "ctid%u", rc
->rti
);
155 tle
= makeTargetEntry((Expr
*) var
,
156 list_length(tlist
) + 1,
160 tlist
= lappend(tlist
, tle
);
162 /* if parent of inheritance tree, need the tableoid too */
165 var
= makeVar(rc
->rti
,
166 TableOidAttributeNumber
,
171 resname
= (char *) palloc(32);
172 snprintf(resname
, 32, "tableoid%u", rc
->rti
);
174 tle
= makeTargetEntry((Expr
*) var
,
175 list_length(tlist
) + 1,
179 tlist
= lappend(tlist
, tle
);
185 * If the query has a RETURNING list, add resjunk entries for any Vars
186 * used in RETURNING that belong to other relations. We need to do this
187 * to make these Vars available for the RETURNING calculation. Vars that
188 * belong to the result rel don't need to be added, because they will be
189 * made to refer to the actual heap tuple.
191 if (parse
->returningList
&& list_length(parse
->rtable
) > 1)
196 vars
= pull_var_clause((Node
*) parse
->returningList
,
197 PVC_INCLUDE_PLACEHOLDERS
);
200 Var
*var
= (Var
*) lfirst(l
);
204 var
->varno
== result_relation
)
205 continue; /* don't need it */
207 if (tlist_member((Node
*) var
, tlist
))
208 continue; /* already got it */
210 tle
= makeTargetEntry((Expr
*) var
,
211 list_length(tlist
) + 1,
215 tlist
= lappend(tlist
, tle
);
223 /*****************************************************************************
225 * TARGETLIST EXPANSION
227 *****************************************************************************/
231 * Given a target list as generated by the parser and a result relation,
232 * add targetlist entries for any missing attributes, and ensure the
233 * non-junk attributes appear in proper field order.
235 * NOTE: if you are tempted to put more processing here, consider whether
236 * it shouldn't go in the rewriter's rewriteTargetList() instead.
239 expand_targetlist(List
*tlist
, int command_type
,
240 Index result_relation
, List
*range_table
)
242 List
*new_tlist
= NIL
;
243 ListCell
*tlist_item
;
248 tlist_item
= list_head(tlist
);
251 * The rewriter should have already ensured that the TLEs are in correct
252 * order; but we have to insert TLEs for any missing attributes.
254 * Scan the tuple description in the relation's relcache entry to make
255 * sure we have all the user attributes in the right order. We assume
256 * that the rewriter already acquired at least AccessShareLock on the
257 * relation, so we need no lock here.
259 rel
= heap_open(getrelid(result_relation
, range_table
), NoLock
);
261 numattrs
= RelationGetNumberOfAttributes(rel
);
263 for (attrno
= 1; attrno
<= numattrs
; attrno
++)
265 Form_pg_attribute att_tup
= rel
->rd_att
->attrs
[attrno
- 1];
266 TargetEntry
*new_tle
= NULL
;
268 if (tlist_item
!= NULL
)
270 TargetEntry
*old_tle
= (TargetEntry
*) lfirst(tlist_item
);
272 if (!old_tle
->resjunk
&& old_tle
->resno
== attrno
)
275 tlist_item
= lnext(tlist_item
);
282 * Didn't find a matching tlist entry, so make one.
284 * For INSERT, generate a NULL constant. (We assume the rewriter
285 * would have inserted any available default value.) Also, if the
286 * column isn't dropped, apply any domain constraints that might
287 * exist --- this is to catch domain NOT NULL.
289 * For UPDATE, generate a Var reference to the existing value of
290 * the attribute, so that it gets copied to the new tuple. But
291 * generate a NULL for dropped columns (we want to drop any old
294 * When generating a NULL constant for a dropped column, we label
295 * it INT4 (any other guaranteed-to-exist datatype would do as
296 * well). We can't label it with the dropped column's datatype
297 * since that might not exist anymore. It does not really matter
298 * what we claim the type is, since NULL is NULL --- its
299 * representation is datatype-independent. This could perhaps
300 * confuse code comparing the finished plan to the target
303 Oid atttype
= att_tup
->atttypid
;
304 int32 atttypmod
= att_tup
->atttypmod
;
307 switch (command_type
)
310 if (!att_tup
->attisdropped
)
312 new_expr
= (Node
*) makeConst(atttype
,
318 new_expr
= coerce_to_domain(new_expr
,
321 COERCE_IMPLICIT_CAST
,
328 /* Insert NULL for dropped column */
329 new_expr
= (Node
*) makeConst(INT4OID
,
338 if (!att_tup
->attisdropped
)
340 new_expr
= (Node
*) makeVar(result_relation
,
348 /* Insert NULL for dropped column */
349 new_expr
= (Node
*) makeConst(INT4OID
,
358 elog(ERROR
, "unrecognized command_type: %d",
360 new_expr
= NULL
; /* keep compiler quiet */
364 new_tle
= makeTargetEntry((Expr
*) new_expr
,
366 pstrdup(NameStr(att_tup
->attname
)),
370 new_tlist
= lappend(new_tlist
, new_tle
);
374 * The remaining tlist entries should be resjunk; append them all to the
375 * end of the new tlist, making sure they have resnos higher than the last
376 * real attribute. (Note: although the rewriter already did such
377 * renumbering, we have to do it again here in case we are doing an UPDATE
378 * in a table with dropped columns, or an inheritance child table with
383 TargetEntry
*old_tle
= (TargetEntry
*) lfirst(tlist_item
);
385 if (!old_tle
->resjunk
)
386 elog(ERROR
, "targetlist is not sorted correctly");
387 /* Get the resno right, but don't copy unnecessarily */
388 if (old_tle
->resno
!= attrno
)
390 old_tle
= flatCopyTargetEntry(old_tle
);
391 old_tle
->resno
= attrno
;
393 new_tlist
= lappend(new_tlist
, old_tle
);
395 tlist_item
= lnext(tlist_item
);
398 heap_close(rel
, NoLock
);