1 /*-------------------------------------------------------------------------
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.52 2000/01/17 00:14:48 tgl Exp $
12 *-------------------------------------------------------------------------
16 #include "nodes/makefuncs.h"
17 #include "parser/parse_coerce.h"
18 #include "parser/parse_expr.h"
19 #include "parser/parse_func.h"
20 #include "parser/parse_relation.h"
21 #include "parser/parse_target.h"
22 #include "utils/builtins.h"
23 #include "utils/lsyscache.h"
24 #include "utils/syscache.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);
63 /* Generate a suitable column name for a column without any
64 * explicit 'AS ColumnName' clause.
66 colname = FigureColname(expr, node);
69 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)
104 * Target item is a single '*', expand all tables
105 * (eg. SELECT * FROM emp)
107 p_target = nconc(p_target,
108 ExpandAllTables(pstate));
110 else if (att->attrs != NIL &&
111 strcmp(strVal(lfirst(att->attrs)), "*") == 0)
114 * Target item is relation.*, expand that table
115 * (eg. SELECT emp.*, dname FROM emp, dept)
117 p_target = nconc(p_target,
121 &pstate->p_last_resno));
125 /* Plain Attr node, treat it as an expression */
126 p_target = lappend(p_target,
127 transformTargetEntry(pstate,
136 /* Everything else but Attr */
137 p_target = lappend(p_target,
138 transformTargetEntry(pstate,
145 targetlist = lnext(targetlist);
153 * updateTargetListEntry()
154 * This is used in INSERT and UPDATE statements only. It prepares a
155 * TargetEntry for assignment to a column of the target table.
156 * This includes coercing the given value to the target column's type
157 * (if necessary), and dealing with any subscripts attached to the target
161 * tle target list entry to be modified
162 * colname target column name (ie, name of attribute to be assigned to)
163 * attrno target attribute number
164 * indirection subscripts for target column, if any
167 updateTargetListEntry(ParseState *pstate,
173 Oid type_id = exprType(tle->expr); /* type of value provided */
174 Oid attrtype; /* type of target column */
176 Resdom *resnode = tle->resdom;
177 Relation rd = pstate->p_target_relation;
181 elog(ERROR, "Cannot assign to system attribute '%s'", colname);
182 attrtype = attnumTypeId(rd, attrno);
183 attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
186 * If there are subscripts on the target column, prepare an
187 * array assignment expression. This will generate an array value
188 * that the source value has been inserted into, which can then
189 * be placed in the new tuple constructed by INSERT or UPDATE.
190 * Note that transformArraySubscripts takes care of type coercion.
194 Attr *att = makeNode(Attr);
198 att->relname = pstrdup(RelationGetRelationName(rd));
199 att->attrs = lcons(makeString(colname), NIL);
200 arrayBase = ParseNestedFuncOrColumn(pstate, att,
201 &pstate->p_last_resno,
203 aref = transformArraySubscripts(pstate, arrayBase,
207 if (pstate->p_is_insert)
210 * The command is INSERT INTO table (arraycol[subscripts]) ...
211 * so there is not really a source array value to work with.
212 * Let the executor do something reasonable, if it can.
213 * Notice that we forced transformArraySubscripts to treat
214 * the subscripting op as an array-slice op above, so the
215 * source data will have been coerced to array type.
217 aref->refexpr = NULL; /* signal there is no source array */
219 tle->expr = (Node *) aref;
224 * For normal non-subscripted target column, do type checking
225 * and coercion. But accept InvalidOid, which indicates the
226 * source is a NULL constant.
228 if (type_id != InvalidOid)
230 if (type_id != attrtype)
232 tle->expr = CoerceTargetExpr(pstate, tle->expr,
234 if (tle->expr == NULL)
235 elog(ERROR, "Attribute '%s' is of type '%s'"
236 " but expression is of type '%s'"
237 "\n\tYou will need to rewrite or cast the expression",
239 typeidTypeName(attrtype),
240 typeidTypeName(type_id));
243 * If the target is a fixed-length type, it may need a length
244 * coercion as well as a type coercion.
246 tle->expr = coerce_type_typmod(pstate, tle->expr,
247 attrtype, attrtypmod);
252 * The result of the target expression should now match the destination
253 * column's type. Also, reset the resname and resno to identify
254 * the destination column --- rewriter and planner depend on that!
256 resnode->restype = attrtype;
257 resnode->restypmod = attrtypmod;
258 resnode->resname = colname;
259 resnode->resno = (AttrNumber) attrno;
264 CoerceTargetExpr(ParseState *pstate,
269 if (can_coerce_type(1, &type_id, &attrtype))
270 expr = coerce_type(pstate, expr, type_id, attrtype, -1);
272 #ifndef DISABLE_STRING_HACKS
275 * string hacks to get transparent conversions w/o explicit
278 else if ((attrtype == BPCHAROID) || (attrtype == VARCHAROID))
280 Oid text_id = TEXTOID;
282 if (type_id == TEXTOID)
285 else if (can_coerce_type(1, &type_id, &text_id))
286 expr = coerce_type(pstate, expr, type_id, text_id, -1);
300 * checkInsertTargets -
301 * generate a list of column names if not supplied or
302 * test supplied column names to make sure they are in target table.
303 * Also return an integer list of the columns' attribute numbers.
304 * (used exclusively for inserts)
307 checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
314 * Generate default column list for INSERT.
316 Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs;
317 int numcol = pstate->p_target_relation->rd_rel->relnatts;
320 for (i = 0; i < numcol; i++)
322 Ident *id = makeNode(Ident);
324 id->name = palloc(NAMEDATALEN);
325 StrNCpy(id->name, NameStr(attr[i]->attname), NAMEDATALEN);
326 id->indirection = NIL;
328 cols = lappend(cols, id);
329 *attrnos = lappendi(*attrnos, i+1);
335 * Do initial validation of user-supplied INSERT column list.
341 char *name = ((Ident *) lfirst(tl))->name;
344 /* Lookup column name, elog on failure */
345 attrno = attnameAttNum(pstate->p_target_relation, name);
346 /* Check for duplicates */
347 if (intMember(attrno, *attrnos))
348 elog(ERROR, "Attribute '%s' specified more than once", name);
349 *attrnos = lappendi(*attrnos, attrno);
358 * turns '*' (in the target list) into a list of attributes
359 * (of all relations in the range table)
362 ExpandAllTables(ParseState *pstate)
368 rtable = pstate->p_rtable;
369 if (pstate->p_is_rule)
372 * skip first two entries, "*new*" and "*current*"
374 rtable = lnext(lnext(rtable));
379 elog(ERROR, "Wildcard with no tables specified.");
383 RangeTblEntry *rte = lfirst(rt);
386 * we only expand those listed in the from clause. (This will
387 * also prevent us from using the wrong table in inserts: eg.
388 * tenk2 in "insert into tenk2 select * from tenk1;")
393 target = nconc(target,
394 expandAll(pstate, rte->relname, rte->refname,
395 &pstate->p_last_resno));
402 * if the name of the resulting column is not specified in the target
403 * list, we have to guess a suitable name. The SQL spec provides some
404 * guidance, but not much...
408 FigureColname(Node *expr, Node *resval)
410 /* Some of these are easiest to do with the untransformed node */
411 switch (nodeTag(resval))
414 return ((Ident *) resval)->name;
417 List *attrs = ((Attr *) resval)->attrs;
420 while (lnext(attrs) != NIL)
421 attrs = lnext(attrs);
422 return strVal(lfirst(attrs));
429 /* Otherwise, work with the transformed node */
430 switch (nodeTag(expr))
433 if (((Expr *) expr)->opType == FUNC_EXPR && IsA(resval, FuncCall))
434 return ((FuncCall *) resval)->funcname;
437 return ((Aggref *) expr)->aggname;
442 name = FigureColname(((CaseExpr *) expr)->defresult, resval);
443 if (strcmp(name, "?column?") == 0)