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.
14 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
15 * Portions Copyright (c) 1994, Regents of the University of California
18 * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.51 2002/04/02 08:51:51 inoue Exp $
20 *-------------------------------------------------------------------------
25 #include "access/heapam.h"
26 #include "catalog/pg_type.h"
27 #include "nodes/makefuncs.h"
28 #include "optimizer/prep.h"
29 #include "parser/parsetree.h"
30 #include "parser/parse_coerce.h"
31 #include "parser/parse_expr.h"
32 #include "parser/parse_target.h"
33 #include "utils/builtins.h"
34 #include "utils/lsyscache.h"
37 static List *expand_targetlist(List *tlist, int command_type,
38 Index result_relation, List *range_table);
39 static TargetEntry *process_matched_tle(TargetEntry *src_tle,
40 TargetEntry *prior_tle,
42 static Node *build_column_default(Relation rel, int attrno);
46 * preprocess_targetlist
47 * Driver for preprocessing the parse tree targetlist.
49 * Returns the new targetlist.
52 preprocess_targetlist(List *tlist,
54 Index result_relation,
58 * Sanity check: if there is a result relation, it'd better be a real
59 * relation not a subquery. Else parser or rewriter messed up.
63 RangeTblEntry *rte = rt_fetch(result_relation, range_table);
65 if (rte->subquery != NULL || rte->relid == InvalidOid)
66 elog(ERROR, "preprocess_targetlist: subquery cannot be result relation");
70 * for heap_formtuple to work, the targetlist must match the exact
71 * order of the attributes. We also need to fill in any missing
72 * attributes. -ay 10/94
74 if (command_type == CMD_INSERT || command_type == CMD_UPDATE)
75 tlist = expand_targetlist(tlist, command_type,
76 result_relation, range_table);
79 * for "update" and "delete" queries, add ctid of the result relation
80 * into the target list so that the ctid will propagate through
81 * execution and ExecutePlan() will be able to identify the right
82 * tuple to replace or delete. This extra field is marked "junk" so
83 * that it is not stored back into the tuple.
85 if (command_type == CMD_UPDATE || command_type == CMD_DELETE)
90 resdom = makeResdom(length(tlist) + 1,
96 var = makeVar(result_relation, SelfItemPointerAttributeNumber,
100 * For an UPDATE, expand_targetlist already created a fresh tlist.
101 * For DELETE, better do a listCopy so that we don't destructively
102 * modify the original tlist (is this really necessary?).
104 if (command_type == CMD_DELETE)
105 tlist = listCopy(tlist);
107 tlist = lappend(tlist, makeTargetEntry(resdom, (Node *) var));
113 /*****************************************************************************
115 * TARGETLIST EXPANSION
117 *****************************************************************************/
121 * Given a target list as generated by the parser and a result relation,
122 * add targetlist entries for any missing attributes, and order the
123 * non-junk attributes in proper field order.
126 expand_targetlist(List *tlist, int command_type,
127 Index result_relation, List *range_table)
129 int old_tlist_len = length(tlist);
130 List *new_tlist = NIL;
131 bool *tlistentry_used;
139 * Keep a map of which tlist items we have transferred to new list.
141 * +1 here just keeps palloc from complaining if old_tlist_len==0.
143 tlistentry_used = (bool *) palloc((old_tlist_len + 1) * sizeof(bool));
144 memset(tlistentry_used, 0, (old_tlist_len + 1) * sizeof(bool));
147 * Scan the tuple description in the relation's relcache entry to make
148 * sure we have all the user attributes in the right order.
150 rel = heap_open(getrelid(result_relation, range_table), AccessShareLock);
152 numattrs = RelationGetNumberOfAttributes(rel);
154 for (attrno = 1; attrno <= numattrs; attrno++)
156 Form_pg_attribute att_tup = rel->rd_att->attrs[attrno - 1];
157 char *attrname = NameStr(att_tup->attname);
158 TargetEntry *new_tle = NULL;
161 * We match targetlist entries to attributes using the resname.
162 * Junk attributes are not candidates to be matched.
167 TargetEntry *old_tle = (TargetEntry *) lfirst(temp);
168 Resdom *resdom = old_tle->resdom;
170 if (!tlistentry_used[old_tlist_index] &&
172 strcmp(resdom->resname, attrname) == 0)
174 new_tle = process_matched_tle(old_tle, new_tle, attrno);
175 tlistentry_used[old_tlist_index] = true;
176 /* keep scanning to detect multiple assignments to attr */
184 * Didn't find a matching tlist entry, so make one.
186 * For INSERT, generate an appropriate default value.
188 * For UPDATE, generate a Var reference to the existing value of
189 * the attribute, so that it gets copied to the new tuple.
191 Oid atttype = att_tup->atttypid;
192 int32 atttypmod = att_tup->atttypmod;
195 switch (command_type)
198 new_expr = build_column_default(rel, attrno);
201 new_expr = (Node *) makeVar(result_relation,
208 elog(ERROR, "expand_targetlist: unexpected command_type");
209 new_expr = NULL; /* keep compiler quiet */
213 new_tle = makeTargetEntry(makeResdom(attrno,
221 new_tlist = lappend(new_tlist, new_tle);
225 * Copy all unprocessed tlist entries to the end of the new tlist,
226 * making sure they are marked resjunk = true. Typical junk entries
227 * include ORDER BY or GROUP BY expressions (are these actually
228 * possible in an INSERT or UPDATE?), system attribute references,
234 TargetEntry *old_tle = (TargetEntry *) lfirst(temp);
236 if (!tlistentry_used[old_tlist_index])
238 Resdom *resdom = old_tle->resdom;
240 if (!resdom->resjunk)
241 elog(ERROR, "Unexpected assignment to attribute \"%s\"",
243 /* Get the resno right, but don't copy unnecessarily */
244 if (resdom->resno != attrno)
246 resdom = (Resdom *) copyObject((Node *) resdom);
247 resdom->resno = attrno;
248 old_tle = makeTargetEntry(resdom, old_tle->expr);
250 new_tlist = lappend(new_tlist, old_tle);
256 heap_close(rel, AccessShareLock);
258 pfree(tlistentry_used);
265 * Convert a matched TLE from the original tlist into a correct new TLE.
267 * This routine checks for multiple assignments to the same target attribute,
268 * such as "UPDATE table SET foo = 42, foo = 43". This is OK only if they
269 * are array assignments, ie, "UPDATE table SET foo[2] = 42, foo[4] = 43".
270 * If so, we need to merge the operations into a single assignment op.
271 * Essentially, the expression we want to produce in this case is like
272 * foo = array_set(array_set(foo, 2, 42), 4, 43)
275 process_matched_tle(TargetEntry *src_tle,
276 TargetEntry *prior_tle,
279 Resdom *resdom = src_tle->resdom;
283 if (prior_tle == NULL)
286 * Normal case where this is the first assignment to the
289 * We can recycle the old TLE+resdom if right resno; else make a new
290 * one to avoid modifying the old tlist structure. (Is preserving
291 * old tlist actually necessary? Not sure, be safe.)
293 if (resdom->resno == attrno)
295 resdom = (Resdom *) copyObject((Node *) resdom);
296 resdom->resno = attrno;
297 return makeTargetEntry(resdom, src_tle->expr);
301 * Multiple assignments to same attribute. Allow only if all are
302 * array-assign operators with same bottom array object.
304 if (src_tle->expr == NULL || !IsA(src_tle->expr, ArrayRef) ||
305 ((ArrayRef *) src_tle->expr)->refassgnexpr == NULL ||
306 prior_tle->expr == NULL || !IsA(prior_tle->expr, ArrayRef) ||
307 ((ArrayRef *) prior_tle->expr)->refassgnexpr == NULL ||
308 ((ArrayRef *) src_tle->expr)->refelemtype !=
309 ((ArrayRef *) prior_tle->expr)->refelemtype)
310 elog(ERROR, "Multiple assignments to same attribute \"%s\"",
314 * Prior TLE could be a nest of ArrayRefs if we do this more than
317 priorbottom = ((ArrayRef *) prior_tle->expr)->refexpr;
318 while (priorbottom != NULL && IsA(priorbottom, ArrayRef) &&
319 ((ArrayRef *) priorbottom)->refassgnexpr != NULL)
320 priorbottom = ((ArrayRef *) priorbottom)->refexpr;
321 if (!equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr))
322 elog(ERROR, "Multiple assignments to same attribute \"%s\"",
326 * Looks OK to nest 'em.
328 newexpr = makeNode(ArrayRef);
329 memcpy(newexpr, src_tle->expr, sizeof(ArrayRef));
330 newexpr->refexpr = prior_tle->expr;
332 resdom = (Resdom *) copyObject((Node *) resdom);
333 resdom->resno = attrno;
334 return makeTargetEntry(resdom, (Node *) newexpr);
339 * Make an expression tree for the default value for a column.
341 * This is used to fill in missing attributes in an INSERT targetlist.
342 * We look first to see if the column has a default value expression.
343 * If not, generate a constant of the default value for the attribute type,
344 * or a NULL if the type has no default value either.
347 build_column_default(Relation rel, int attrno)
349 TupleDesc rd_att = rel->rd_att;
350 Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
351 Oid atttype = att_tup->atttypid;
352 int32 atttypmod = att_tup->atttypmod;
353 int16 typlen = att_tup->attlen;
354 bool typbyval = att_tup->attbyval;
358 * Scan to see if relation has a default for this column.
360 if (rd_att->constr && rd_att->constr->num_defval > 0)
362 AttrDefault *defval = rd_att->constr->defval;
363 int ndef = rd_att->constr->num_defval;
367 if (attrno == defval[ndef].adnum)
370 * Found it, convert string representation to node tree.
372 expr = stringToNode(defval[ndef].adbin);
381 * No per-column default, so look for a default for the type itself.
383 if (att_tup->attisset)
386 * Set attributes are represented as OIDs no matter what the set
387 * element type is, and the element type's default is irrelevant
390 typlen = sizeof(Oid);
395 expr = get_typdefault(atttype);
402 * No default anywhere, so generate a NULL constant.
404 expr = (Node *) makeConst(atttype,
409 false, /* not a set */
417 * Make sure the value is coerced to the target column
418 * type (might not be right type yet if it's not a
419 * constant!) This should match the parser's processing of
420 * non-defaulted expressions --- see
421 * updateTargetListEntry().
423 exprtype = exprType(expr);
425 if (exprtype != atttype)
427 expr = CoerceTargetExpr(NULL, expr, exprtype,
431 * This really shouldn't fail; should have checked the
432 * default's type when it was created ...
435 elog(ERROR, "Column \"%s\" is of type %s"
436 " but default expression is of type %s"
437 "\n\tYou will need to rewrite or cast the expression",
438 NameStr(att_tup->attname),
439 format_type_be(atttype),
440 format_type_be(exprtype));
444 * If the column is a fixed-length type, it may need a
445 * length coercion as well as a type coercion.
447 expr = coerce_type_typmod(NULL, expr, atttype, atttypmod);