]> granicus.if.org Git - postgresql/blob - src/backend/parser/parse_target.c
Removed obsolete DROP_COLUMN_HACK stuff.
[postgresql] / src / backend / parser / parse_target.c
1 /*-------------------------------------------------------------------------
2  *
3  * parse_target.c
4  *        handle target lists
5  *
6  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.81 2002/04/02 08:51:52 inoue Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "miscadmin.h"
18 #include "nodes/makefuncs.h"
19 #include "parser/parsetree.h"
20 #include "parser/parse_coerce.h"
21 #include "parser/parse_expr.h"
22 #include "parser/parse_func.h"
23 #include "parser/parse_relation.h"
24 #include "parser/parse_target.h"
25 #include "parser/parse_type.h"
26 #include "utils/builtins.h"
27
28
29 static List *ExpandAllTables(ParseState *pstate);
30 static char *FigureColname(Node *node);
31 static int      FigureColnameInternal(Node *node, char **name);
32
33
34 /*
35  * transformTargetEntry()
36  *      Transform any ordinary "expression-type" node into a targetlist entry.
37  *      This is exported so that parse_clause.c can generate targetlist entries
38  *      for ORDER/GROUP BY items that are not already in the targetlist.
39  *
40  * node         the (untransformed) parse tree for the value expression.
41  * expr         the transformed expression, or NULL if caller didn't do it yet.
42  * colname      the column name to be assigned, or NULL if none yet set.
43  * resjunk      true if the target should be marked resjunk, ie, it is not
44  *                      wanted in the final projected tuple.
45  */
46 TargetEntry *
47 transformTargetEntry(ParseState *pstate,
48                                          Node *node,
49                                          Node *expr,
50                                          char *colname,
51                                          bool resjunk)
52 {
53         Oid                     type_id;
54         int32           type_mod;
55         Resdom     *resnode;
56
57         /* Transform the node if caller didn't do it already */
58         if (expr == NULL)
59                 expr = transformExpr(pstate, node);
60
61         if (IsA(expr, RangeVar))
62                 elog(ERROR, "You can't use relation names alone in the target list, try relation.*.");
63
64         type_id = exprType(expr);
65         type_mod = exprTypmod(expr);
66
67         if (colname == NULL)
68         {
69                 /*
70                  * Generate a suitable column name for a column without any
71                  * explicit 'AS ColumnName' clause.
72                  */
73                 colname = FigureColname(node);
74         }
75
76         resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
77                                                  type_id,
78                                                  type_mod,
79                                                  colname,
80                                                  resjunk);
81
82         return makeTargetEntry(resnode, expr);
83 }
84
85
86 /*
87  * transformTargetList()
88  * Turns a list of ResTarget's into a list of TargetEntry's.
89  *
90  * At this point, we don't care whether we are doing SELECT, INSERT,
91  * or UPDATE; we just transform the given expressions.
92  */
93 List *
94 transformTargetList(ParseState *pstate, List *targetlist)
95 {
96         List       *p_target = NIL;
97
98         while (targetlist != NIL)
99         {
100                 ResTarget  *res = (ResTarget *) lfirst(targetlist);
101
102                 if (IsA(res->val, ColumnRef))
103                 {
104                         ColumnRef  *cref = (ColumnRef *) res->val;
105                         List       *fields = cref->fields;
106                         int                     numnames = length(fields);
107
108                         if (numnames == 1 && strcmp(strVal(lfirst(fields)), "*") == 0)
109                         {
110                                 /*
111                                  * Target item is a single '*', expand all tables (eg.
112                                  * SELECT * FROM emp)
113                                  */
114                                 p_target = nconc(p_target,
115                                                                  ExpandAllTables(pstate));
116                         }
117                         else if (strcmp(strVal(nth(numnames-1, fields)), "*") == 0)
118                         {
119                                 /*
120                                  * Target item is relation.*, expand that table (eg.
121                                  * SELECT emp.*, dname FROM emp, dept)
122                                  */
123                                 char       *schemaname;
124                                 char       *relname;
125                                 RangeTblEntry *rte;
126                                 int                     sublevels_up;
127
128                                 switch (numnames)
129                                 {
130                                         case 2:
131                                                 schemaname = NULL;
132                                                 relname = strVal(lfirst(fields));
133                                                 break;
134                                         case 3:
135                                                 schemaname = strVal(lfirst(fields));
136                                                 relname = strVal(lsecond(fields));
137                                                 break;
138                                         case 4:
139                                         {
140                                                 char   *name1 = strVal(lfirst(fields));
141
142                                                 /*
143                                                  * We check the catalog name and then ignore it.
144                                                  */
145                                                 if (strcmp(name1, DatabaseName) != 0)
146                                                         elog(ERROR, "Cross-database references are not implemented");
147                                                 schemaname = strVal(lsecond(fields));
148                                                 relname = strVal(lfirst(lnext(lnext(fields))));
149                                                 break;
150                                         }
151                                         default:
152                                                 elog(ERROR, "Invalid qualified name syntax (too many names)");
153                                                 schemaname = NULL; /* keep compiler quiet */
154                                                 relname = NULL;
155                                                 break;
156                                 }
157
158                                 /* XXX do something with schema name */
159                                 rte = refnameRangeTblEntry(pstate, relname,
160                                                                                    &sublevels_up);
161                                 if (rte == NULL)
162                                         rte = addImplicitRTE(pstate, makeRangeVar(NULL, relname));
163
164                                 p_target = nconc(p_target,
165                                                                  expandRelAttrs(pstate, rte));
166                         }
167                         else
168                         {
169                                 /* Plain ColumnRef node, treat it as an expression */
170                                 p_target = lappend(p_target,
171                                                                    transformTargetEntry(pstate,
172                                                                                                                 res->val,
173                                                                                                                 NULL,
174                                                                                                                 res->name,
175                                                                                                                 false));
176                         }
177                 }
178                 else
179                 {
180                         /* Everything else but ColumnRef */
181                         p_target = lappend(p_target,
182                                                            transformTargetEntry(pstate,
183                                                                                                         res->val,
184                                                                                                         NULL,
185                                                                                                         res->name,
186                                                                                                         false));
187                 }
188
189                 targetlist = lnext(targetlist);
190         }
191
192         return p_target;
193 }
194
195
196 /*
197  * updateTargetListEntry()
198  *      This is used in INSERT and UPDATE statements only.      It prepares a
199  *      TargetEntry for assignment to a column of the target table.
200  *      This includes coercing the given value to the target column's type
201  *      (if necessary), and dealing with any subscripts attached to the target
202  *      column itself.
203  *
204  * pstate               parse state
205  * tle                  target list entry to be modified
206  * colname              target column name (ie, name of attribute to be assigned to)
207  * attrno               target attribute number
208  * indirection  subscripts for target column, if any
209  */
210 void
211 updateTargetListEntry(ParseState *pstate,
212                                           TargetEntry *tle,
213                                           char *colname,
214                                           int attrno,
215                                           List *indirection)
216 {
217         Oid                     type_id = exprType(tle->expr);  /* type of value provided */
218         Oid                     attrtype;               /* type of target column */
219         int32           attrtypmod;
220         Resdom     *resnode = tle->resdom;
221         Relation        rd = pstate->p_target_relation;
222
223         Assert(rd != NULL);
224         if (attrno <= 0)
225                 elog(ERROR, "Cannot assign to system attribute '%s'", colname);
226         attrtype = attnumTypeId(rd, attrno);
227         attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod;
228
229         /*
230          * If there are subscripts on the target column, prepare an array
231          * assignment expression.  This will generate an array value that the
232          * source value has been inserted into, which can then be placed in
233          * the new tuple constructed by INSERT or UPDATE. Note that
234          * transformArraySubscripts takes care of type coercion.
235          */
236         if (indirection)
237         {
238                 Node       *arrayBase;
239                 ArrayRef   *aref;
240
241                 if (pstate->p_is_insert)
242                 {
243                         /*
244                          * The command is INSERT INTO table (arraycol[subscripts]) ...
245                          * so there is not really a source array value to work with.
246                          * Let the executor do something reasonable, if it can. Notice
247                          * that we force transformArraySubscripts to treat the
248                          * subscripting op as an array-slice op below, so the source
249                          * data will have been coerced to the array type.
250                          */
251                         arrayBase = NULL;       /* signal there is no source array */
252                 }
253                 else
254                 {
255                         /*
256                          * Build a Var for the array to be updated.
257                          */
258                         arrayBase = (Node *) make_var(pstate,
259                                                                                   pstate->p_target_rangetblentry,
260                                                                                   attrno);
261                 }
262
263                 aref = transformArraySubscripts(pstate,
264                                                                                 arrayBase,
265                                                                                 attrtype,
266                                                                                 indirection,
267                                                                                 pstate->p_is_insert,
268                                                                                 tle->expr);
269                 tle->expr = (Node *) aref;
270         }
271         else
272         {
273                 /*
274                  * For normal non-subscripted target column, do type checking and
275                  * coercion.  But accept InvalidOid, which indicates the source is
276                  * a NULL constant.
277                  */
278                 if (type_id != InvalidOid)
279                 {
280                         if (type_id != attrtype)
281                         {
282                                 tle->expr = CoerceTargetExpr(pstate, tle->expr, type_id,
283                                                                                          attrtype, attrtypmod);
284                                 if (tle->expr == NULL)
285                                         elog(ERROR, "column \"%s\" is of type '%s'"
286                                                  " but expression is of type '%s'"
287                                         "\n\tYou will need to rewrite or cast the expression",
288                                                  colname,
289                                                  format_type_be(attrtype),
290                                                  format_type_be(type_id));
291                         }
292
293                         /*
294                          * If the target is a fixed-length type, it may need a length
295                          * coercion as well as a type coercion.
296                          */
297                         tle->expr = coerce_type_typmod(pstate, tle->expr,
298                                                                                    attrtype, attrtypmod);
299                 }
300         }
301
302         /*
303          * The result of the target expression should now match the
304          * destination column's type.  Also, reset the resname and resno to
305          * identify the destination column --- rewriter and planner depend on
306          * that!
307          */
308         resnode->restype = attrtype;
309         resnode->restypmod = attrtypmod;
310         resnode->resname = colname;
311         resnode->resno = (AttrNumber) attrno;
312 }
313
314
315 Node *
316 CoerceTargetExpr(ParseState *pstate,
317                                  Node *expr,
318                                  Oid type_id,
319                                  Oid attrtype,
320                                  int32 attrtypmod)
321 {
322         if (can_coerce_type(1, &type_id, &attrtype))
323                 expr = coerce_type(pstate, expr, type_id, attrtype, attrtypmod);
324
325 #ifndef DISABLE_STRING_HACKS
326
327         /*
328          * string hacks to get transparent conversions w/o explicit
329          * conversions
330          */
331         else if ((attrtype == BPCHAROID) || (attrtype == VARCHAROID))
332         {
333                 Oid                     text_id = TEXTOID;
334
335                 if (type_id == TEXTOID)
336                 {
337                 }
338                 else if (can_coerce_type(1, &type_id, &text_id))
339                         expr = coerce_type(pstate, expr, type_id, text_id, attrtypmod);
340                 else
341                         expr = NULL;
342         }
343 #endif
344
345         else
346                 expr = NULL;
347
348         return expr;
349 }
350
351
352 /*
353  * checkInsertTargets -
354  *        generate a list of INSERT column targets if not supplied, or
355  *        test supplied column names to make sure they are in target table.
356  *        Also return an integer list of the columns' attribute numbers.
357  */
358 List *
359 checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
360 {
361         *attrnos = NIL;
362
363         if (cols == NIL)
364         {
365                 /*
366                  * Generate default column list for INSERT.
367                  */
368                 Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs;
369                 int                     numcol = pstate->p_target_relation->rd_rel->relnatts;
370                 int                     i;
371
372                 for (i = 0; i < numcol; i++)
373                 {
374                         ResTarget          *col = makeNode(ResTarget);
375
376                         col->name = pstrdup(NameStr(attr[i]->attname));
377                         col->indirection = NIL;
378                         col->val = NULL;
379                         cols = lappend(cols, col);
380                         *attrnos = lappendi(*attrnos, i + 1);
381                 }
382         }
383         else
384         {
385                 /*
386                  * Do initial validation of user-supplied INSERT column list.
387                  */
388                 List       *tl;
389
390                 foreach(tl, cols)
391                 {
392                         char       *name = ((ResTarget *) lfirst(tl))->name;
393                         int                     attrno;
394
395                         /* Lookup column name, elog on failure */
396                         attrno = attnameAttNum(pstate->p_target_relation, name);
397                         /* Check for duplicates */
398                         if (intMember(attrno, *attrnos))
399                                 elog(ERROR, "Attribute '%s' specified more than once", name);
400                         *attrnos = lappendi(*attrnos, attrno);
401                 }
402         }
403
404         return cols;
405 }
406
407 /* ExpandAllTables()
408  * Turns '*' (in the target list) into a list of targetlist entries.
409  *
410  * tlist entries are generated for each relation appearing at the top level
411  * of the query's namespace, except for RTEs marked not inFromCl.  (These
412  * may include NEW/OLD pseudo-entries, implicit RTEs, etc.)
413  */
414 static List *
415 ExpandAllTables(ParseState *pstate)
416 {
417         List       *target = NIL;
418         List       *ns;
419
420         foreach(ns, pstate->p_namespace)
421         {
422                 Node       *n = (Node *) lfirst(ns);
423                 RangeTblEntry *rte;
424
425                 if (IsA(n, RangeTblRef))
426                         rte = rt_fetch(((RangeTblRef *) n)->rtindex,
427                                                    pstate->p_rtable);
428                 else if (IsA(n, JoinExpr))
429                         rte = rt_fetch(((JoinExpr *) n)->rtindex,
430                                                    pstate->p_rtable);
431                 else
432                 {
433                         elog(ERROR, "ExpandAllTables: unexpected node (internal error)"
434                                  "\n\t%s", nodeToString(n));
435                         rte = NULL;                     /* keep compiler quiet */
436                 }
437
438                 /*
439                  * Ignore added-on relations that were not listed in the FROM
440                  * clause.
441                  */
442                 if (!rte->inFromCl)
443                         continue;
444
445                 target = nconc(target, expandRelAttrs(pstate, rte));
446         }
447
448         /* Check for SELECT *; */
449         if (target == NIL)
450                 elog(ERROR, "Wildcard with no tables specified not allowed");
451
452         return target;
453 }
454
455 /*
456  * FigureColname -
457  *        if the name of the resulting column is not specified in the target
458  *        list, we have to guess a suitable name.  The SQL spec provides some
459  *        guidance, but not much...
460  *
461  * Note that the argument is the *untransformed* parse tree for the target
462  * item.  This is a shade easier to work with than the transformed tree.
463  */
464 static char *
465 FigureColname(Node *node)
466 {
467         char       *name = NULL;
468
469         FigureColnameInternal(node, &name);
470         if (name != NULL)
471                 return name;
472         /* default result if we can't guess anything */
473         return "?column?";
474 }
475
476 static int
477 FigureColnameInternal(Node *node, char **name)
478 {
479         int                     strength = 0;
480
481         if (node == NULL)
482                 return strength;
483
484         switch (nodeTag(node))
485         {
486                 case T_Ident:
487                         *name = ((Ident *) node)->name;
488                         return 2;
489                 case T_ColumnRef:
490                         {
491                                 List       *fields = ((ColumnRef *) node)->fields;
492
493                                 while (lnext(fields) != NIL)
494                                         fields = lnext(fields);
495                                 if (strcmp(strVal(lfirst(fields)), "*") != 0)
496                                 {
497                                         *name = strVal(lfirst(fields));
498                                         return 2;
499                                 }
500                         }
501                         break;
502                 case T_ExprFieldSelect:
503                         {
504                                 List       *fields = ((ExprFieldSelect *) node)->fields;
505
506                                 if (fields)
507                                 {
508                                         while (lnext(fields) != NIL)
509                                                 fields = lnext(fields);
510                                         if (strcmp(strVal(lfirst(fields)), "*") != 0)
511                                         {
512                                                 *name = strVal(lfirst(fields));
513                                                 return 2;
514                                         }
515                                 }
516                         }
517                         break;
518                 case T_FuncCall:
519                         *name = ((FuncCall *) node)->funcname;
520                         return 2;
521                 case T_A_Const:
522                         if (((A_Const *) node)->typename != NULL)
523                         {
524                                 List       *names = ((A_Const *) node)->typename->names;
525
526                                 if (names != NIL)
527                                 {
528                                         while (lnext(names) != NIL)
529                                                 names = lnext(names);
530                                         *name = strVal(lfirst(names));
531                                         return 1;
532                                 }
533                         }
534                         break;
535                 case T_TypeCast:
536                         strength = FigureColnameInternal(((TypeCast *) node)->arg,
537                                                                                          name);
538                         if (strength <= 1)
539                         {
540                                 if (((TypeCast *) node)->typename != NULL)
541                                 {
542                                         List       *names = ((TypeCast *) node)->typename->names;
543
544                                         if (names != NIL)
545                                         {
546                                                 while (lnext(names) != NIL)
547                                                         names = lnext(names);
548                                                 *name = strVal(lfirst(names));
549                                                 return 1;
550                                         }
551                                 }
552                         }
553                         break;
554                 case T_CaseExpr:
555                         strength = FigureColnameInternal(((CaseExpr *) node)->defresult,
556                                                                                          name);
557                         if (strength <= 1)
558                         {
559                                 *name = "case";
560                                 return 1;
561                         }
562                         break;
563                 default:
564                         break;
565         }
566
567         return strength;
568 }