1 /*-------------------------------------------------------------------------
6 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.62 2000/09/12 21:07:02 tgl Exp $
13 *-------------------------------------------------------------------------
17 #include "nodes/makefuncs.h"
18 #include "parser/parsetree.h"
19 #include "parser/parse_coerce.h"
20 #include "parser/parse_expr.h"
21 #include "parser/parse_func.h"
22 #include "parser/parse_relation.h"
23 #include "parser/parse_target.h"
24 #include "parser/parse_type.h"
27 static List *ExpandAllTables(ParseState *pstate);
28 static char *FigureColname(Node *expr, Node *resval);
32 * transformTargetEntry()
33 * Transform any ordinary "expression-type" node into a targetlist entry.
34 * This is exported so that parse_clause.c can generate targetlist entries
35 * for ORDER/GROUP BY items that are not already in the targetlist.
37 * node the (untransformed) parse tree for the value expression.
38 * expr the transformed expression, or NULL if caller didn't do it yet.
39 * colname the column name to be assigned, or NULL if none yet set.
40 * resjunk true if the target should be marked resjunk, ie, it is not
41 * wanted in the final projected tuple.
44 transformTargetEntry(ParseState *pstate,
54 /* Transform the node if caller didn't do it already */
56 expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
58 type_id = exprType(expr);
59 type_mod = exprTypmod(expr);
65 * Generate a suitable column name for a column without any
66 * explicit 'AS ColumnName' clause.
68 colname = FigureColname(expr, node);
71 resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
77 return makeTargetEntry(resnode, expr);
82 * transformTargetList()
83 * Turns a list of ResTarget's into a list of TargetEntry's.
85 * At this point, we don't care whether we are doing SELECT, INSERT,
86 * or UPDATE; we just transform the given expressions.
89 transformTargetList(ParseState *pstate, List *targetlist)
93 while (targetlist != NIL)
95 ResTarget *res = (ResTarget *) lfirst(targetlist);
97 if (IsA(res->val, Attr))
99 Attr *att = (Attr *) res->val;
101 if (att->relname != NULL && strcmp(att->relname, "*") == 0)
105 * Target item is a single '*', expand all tables (eg.
108 p_target = nconc(p_target,
109 ExpandAllTables(pstate));
111 else if (att->attrs != NIL &&
112 strcmp(strVal(lfirst(att->attrs)), "*") == 0)
116 * Target item is relation.*, expand that table (eg.
117 * SELECT emp.*, dname FROM emp, dept)
122 rteorjoin = refnameRangeOrJoinEntry(pstate, att->relname,
125 if (rteorjoin == NULL)
127 rteorjoin = (Node *) addImplicitRTE(pstate, att->relname);
131 if (IsA(rteorjoin, RangeTblEntry))
132 p_target = nconc(p_target,
133 expandRelAttrs(pstate,
134 (RangeTblEntry *) rteorjoin));
135 else if (IsA(rteorjoin, JoinExpr))
136 p_target = nconc(p_target,
137 expandJoinAttrs(pstate,
138 (JoinExpr *) rteorjoin,
141 elog(ERROR, "transformTargetList: unexpected node type %d",
146 /* Plain Attr node, treat it as an expression */
147 p_target = lappend(p_target,
148 transformTargetEntry(pstate,
157 /* Everything else but Attr */
158 p_target = lappend(p_target,
159 transformTargetEntry(pstate,
166 targetlist = lnext(targetlist);
174 * updateTargetListEntry()
175 * This is used in INSERT and UPDATE statements only. It prepares a
176 * TargetEntry for assignment to a column of the target table.
177 * This includes coercing the given value to the target column's type
178 * (if necessary), and dealing with any subscripts attached to the target
182 * tle target list entry to be modified
183 * colname target column name (ie, name of attribute to be assigned to)
184 * attrno target attribute number
185 * indirection subscripts for target column, if any
188 updateTargetListEntry(ParseState *pstate,
194 Oid type_id = exprType(tle->expr); /* type of value provided */
195 Oid attrtype; /* type of target column */
197 Resdom *resnode = tle->resdom;
198 Relation rd = pstate->p_target_relation;
202 elog(ERROR, "Cannot assign to system attribute '%s'", colname);
203 attrtype = attnumTypeId(rd, attrno);
204 attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
207 * If there are subscripts on the target column, prepare an array
208 * assignment expression. This will generate an array value that the
209 * source value has been inserted into, which can then be placed in
210 * the new tuple constructed by INSERT or UPDATE. Note that
211 * transformArraySubscripts takes care of type coercion.
215 Attr *att = makeAttr(pstrdup(RelationGetRelationName(rd)),
220 arrayBase = ParseNestedFuncOrColumn(pstate, att, EXPR_COLUMN_FIRST);
221 aref = transformArraySubscripts(pstate, arrayBase,
225 if (pstate->p_is_insert)
229 * The command is INSERT INTO table (arraycol[subscripts]) ...
230 * so there is not really a source array value to work with.
231 * Let the executor do something reasonable, if it can. Notice
232 * that we forced transformArraySubscripts to treat the
233 * subscripting op as an array-slice op above, so the source
234 * data will have been coerced to array type.
236 aref->refexpr = NULL; /* signal there is no source array */
238 tle->expr = (Node *) aref;
244 * For normal non-subscripted target column, do type checking and
245 * coercion. But accept InvalidOid, which indicates the source is
248 if (type_id != InvalidOid)
250 if (type_id != attrtype)
252 tle->expr = CoerceTargetExpr(pstate, tle->expr, type_id,
253 attrtype, attrtypmod);
254 if (tle->expr == NULL)
255 elog(ERROR, "Attribute '%s' is of type '%s'"
256 " but expression is of type '%s'"
257 "\n\tYou will need to rewrite or cast the expression",
259 typeidTypeName(attrtype),
260 typeidTypeName(type_id));
264 * If the target is a fixed-length type, it may need a length
265 * coercion as well as a type coercion.
267 tle->expr = coerce_type_typmod(pstate, tle->expr,
268 attrtype, attrtypmod);
273 * The result of the target expression should now match the
274 * destination column's type. Also, reset the resname and resno to
275 * identify the destination column --- rewriter and planner depend on
278 resnode->restype = attrtype;
279 resnode->restypmod = attrtypmod;
280 resnode->resname = colname;
281 resnode->resno = (AttrNumber) attrno;
286 CoerceTargetExpr(ParseState *pstate,
292 if (can_coerce_type(1, &type_id, &attrtype))
293 expr = coerce_type(pstate, expr, type_id, attrtype, attrtypmod);
295 #ifndef DISABLE_STRING_HACKS
298 * string hacks to get transparent conversions w/o explicit
301 else if ((attrtype == BPCHAROID) || (attrtype == VARCHAROID))
303 Oid text_id = TEXTOID;
305 if (type_id == TEXTOID)
308 else if (can_coerce_type(1, &type_id, &text_id))
309 expr = coerce_type(pstate, expr, type_id, text_id, attrtypmod);
323 * checkInsertTargets -
324 * generate a list of column names if not supplied or
325 * test supplied column names to make sure they are in target table.
326 * Also return an integer list of the columns' attribute numbers.
327 * (used exclusively for inserts)
330 checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
338 * Generate default column list for INSERT.
340 Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs;
341 int numcol = pstate->p_target_relation->rd_rel->relnatts;
344 for (i = 0; i < numcol; i++)
346 Ident *id = makeNode(Ident);
348 #ifdef _DROP_COLUMN_HACK__
349 if (COLUMN_IS_DROPPED(attr[i]))
351 #endif /* _DROP_COLUMN_HACK__ */
352 id->name = palloc(NAMEDATALEN);
353 StrNCpy(id->name, NameStr(attr[i]->attname), NAMEDATALEN);
354 id->indirection = NIL;
356 cols = lappend(cols, id);
357 *attrnos = lappendi(*attrnos, i + 1);
364 * Do initial validation of user-supplied INSERT column list.
370 char *name = ((Ident *) lfirst(tl))->name;
373 /* Lookup column name, elog on failure */
374 attrno = attnameAttNum(pstate->p_target_relation, name);
375 /* Check for duplicates */
376 if (intMember(attrno, *attrnos))
377 elog(ERROR, "Attribute '%s' specified more than once", name);
378 *attrnos = lappendi(*attrnos, attrno);
386 * Turns '*' (in the target list) into a list of targetlist entries.
388 * tlist entries are generated for each relation appearing in the FROM list,
389 * which by now has been expanded into a join tree.
392 ExpandAllTables(ParseState *pstate)
398 if (pstate->p_jointree == NIL)
399 elog(ERROR, "Wildcard with no tables specified not allowed");
401 foreach(jt, pstate->p_jointree)
403 Node *n = (Node *) lfirst(jt);
405 if (IsA(n, RangeTblRef))
409 rte = rt_fetch(((RangeTblRef *) n)->rtindex,
413 * Ignore added-on relations that were not listed in the FROM
419 target = nconc(target, expandRelAttrs(pstate, rte));
421 else if (IsA(n, JoinExpr))
423 /* A newfangled join expression */
424 JoinExpr *j = (JoinExpr *) n;
426 /* Currently, a join expr could only have come from FROM. */
427 target = nconc(target, expandJoinAttrs(pstate, j, 0));
430 elog(ERROR, "ExpandAllTables: unexpected node (internal error)"
431 "\n\t%s", nodeToString(n));
439 * if the name of the resulting column is not specified in the target
440 * list, we have to guess a suitable name. The SQL spec provides some
441 * guidance, but not much...
445 FigureColname(Node *expr, Node *resval)
447 /* Some of these are easiest to do with the untransformed node */
448 switch (nodeTag(resval))
451 return ((Ident *) resval)->name;
454 List *attrs = ((Attr *) resval)->attrs;
458 while (lnext(attrs) != NIL)
459 attrs = lnext(attrs);
460 return strVal(lfirst(attrs));
467 /* Otherwise, work with the transformed node */
468 switch (nodeTag(expr))
471 if (((Expr *) expr)->opType == FUNC_EXPR && IsA(resval, FuncCall))
472 return ((FuncCall *) resval)->funcname;
475 return ((Aggref *) expr)->aggname;
480 name = FigureColname(((CaseExpr *) expr)->defresult, resval);
481 if (strcmp(name, "?column?") == 0)