1 /*-------------------------------------------------------------------------
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.42 1999/06/17 22:21:41 tgl Exp $
12 *-------------------------------------------------------------------------
19 #include "catalog/pg_type.h"
20 #include "nodes/makefuncs.h"
21 #include "nodes/primnodes.h"
22 #include "nodes/print.h"
23 #include "parser/parse_expr.h"
24 #include "parser/parse_func.h"
25 #include "parser/parse_node.h"
26 #include "parser/parse_relation.h"
27 #include "parser/parse_target.h"
28 #include "parser/parse_coerce.h"
29 #include "utils/builtins.h"
30 #include "utils/lsyscache.h"
31 #include "utils/syscache.h"
34 static List *ExpandAllTables(ParseState *pstate);
35 static char *FigureColname(Node *expr, Node *resval);
36 static Node *SizeTargetExpr(ParseState *pstate,
42 /* MakeTargetEntryIdent()
43 * Transforms an Ident Node to a Target Entry
44 * Created this function to allow the ORDER/GROUP BY clause to be able
45 * to construct a TargetEntry from an Ident.
47 * resjunk = TRUE will hide the target entry in the final result tuple.
48 * daveh@insightdist.com 5/20/98
50 * Added more conversion logic to match up types from source to target.
54 MakeTargetEntryIdent(ParseState *pstate,
63 TargetEntry *tent = makeNode(TargetEntry);
65 if (pstate->p_is_insert && !resjunk)
69 * Assign column name of destination column to the new TLE. XXX
70 * this is probably WRONG in INSERT ... SELECT case, since
71 * handling of GROUP BY and so forth probably should use the
72 * source table's names not the destination's names.
74 if (pstate->p_insert_columns != NIL)
76 Ident *id = lfirst(pstate->p_insert_columns);
79 pstate->p_insert_columns = lnext(pstate->p_insert_columns);
82 elog(ERROR, "INSERT has more expressions than target columns");
85 if ((pstate->p_is_insert || pstate->p_is_update) && !resjunk)
95 target_colname = *resname;
98 * this looks strange to me, returning an empty TargetEntry bjm
101 if (target_colname == NULL || colname == NULL)
105 rte = refnameRangeTableEntry(pstate, refname);
108 rte = colnameRangeTableEntry(pstate, colname);
109 if (rte == (RangeTblEntry *) NULL)
110 elog(ERROR, "Attribute %s not found", colname);
111 refname = rte->refname;
114 resdomno_id = get_attnum(rte->relid, colname);
115 attrtype_id = get_atttype(rte->relid, resdomno_id);
116 attrtypmod = get_atttypmod(rte->relid, resdomno_id);
118 resdomno_target = attnameAttNum(pstate->p_target_relation, target_colname);
119 attrtype_target = attnumTypeId(pstate->p_target_relation, resdomno_target);
120 attrtypmod_target = get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target);
122 if ((attrtype_id != attrtype_target)
123 || ((attrtypmod_target >= 0) && (attrtypmod_target != attrtypmod)))
125 if (can_coerce_type(1, &attrtype_id, &attrtype_target))
127 expr = coerce_type(pstate, node, attrtype_id,
129 get_atttypmod(pstate->p_target_relation->rd_id, resdomno_target));
130 expr = transformExpr(pstate, expr, EXPR_COLUMN_FIRST);
131 tent = MakeTargetEntryExpr(pstate, *resname, expr, false, false);
136 elog(ERROR, "Unable to convert %s to %s for column %s",
137 typeidTypeName(attrtype_id), typeidTypeName(attrtype_target),
144 * here we want to look for column names only, not relation names
145 * (even though they can be stored in Ident nodes, too)
152 name = ((*resname != NULL) ? *resname : colname);
154 expr = transformExpr(pstate, node, EXPR_COLUMN_FIRST);
156 attrtype_target = exprType(expr);
157 if (nodeTag(expr) == T_Var)
158 type_mod = ((Var *) expr)->vartypmod;
162 tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
163 (Oid) attrtype_target,
173 } /* MakeTargetEntryIdent() */
176 /* MakeTargetEntryExpr()
177 * Make a TargetEntry from an expression.
178 * arrayRef is a list of transformed A_Indices.
180 * For type mismatches between expressions and targets, use the same
181 * techniques as for function and operator type coersion.
182 * - thomas 1998-05-08
184 * Added resjunk flag and made extern so that it can be use by GROUP/
185 * ORDER BY a function or expression not in the target_list
186 * - daveh@insightdist.com 1998-07-31
189 MakeTargetEntryExpr(ParseState *pstate,
205 elog(ERROR, "Invalid use of NULL expression (internal error)");
207 type_id = exprType(expr);
208 if (nodeTag(expr) == T_Var)
209 type_mod = ((Var *) expr)->vartypmod;
213 /* Process target columns that will be receiving results */
214 if ((pstate->p_is_insert || pstate->p_is_update) && !resjunk)
218 * insert or update query -- insert, update work only on one
219 * relation, so multiple occurence of same resdomno is bogus
221 rd = pstate->p_target_relation;
223 resdomno = attnameAttNum(rd, colname);
225 elog(ERROR, "Cannot assign to system attribute '%s'", colname);
226 attrisset = attnameIsSet(rd, colname);
227 attrtype = attnumTypeId(rd, resdomno);
228 if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
229 attrtype = GetArrayElementType(attrtype);
230 attrtypmod = rd->rd_att->attrs[resdomno - 1]->atttypmod;
233 * Check for InvalidOid since that seems to indicate a NULL
236 if (type_id != InvalidOid)
238 /* Mismatch on types? then try to coerce to target... */
239 if (attrtype != type_id)
243 if (arrayRef && !(((A_Indices *) lfirst(arrayRef))->lidx))
244 typelem = typeTypElem(typeidType(attrtype));
248 expr = CoerceTargetExpr(pstate, expr, type_id, typelem);
250 if (!HeapTupleIsValid(expr))
251 elog(ERROR, "Attribute '%s' is of type '%s'"
252 " but expression is of type '%s'"
253 "\n\tYou will need to rewrite or cast the expression",
255 typeidTypeName(attrtype),
256 typeidTypeName(type_id));
260 * Apparently going to a fixed-length string? Then explicitly
261 * size for storage...
264 expr = SizeTargetExpr(pstate, expr, attrtype, attrtypmod);
270 Attr *att = makeNode(Attr);
272 List *upperIndexpr = NIL;
273 List *lowerIndexpr = NIL;
275 att->relname = pstrdup(RelationGetRelationName(rd)->data);
276 att->attrs = lcons(makeString(colname), NIL);
277 target_expr = (Expr *) ParseNestedFuncOrColumn(pstate, att,
278 &pstate->p_last_resno,
282 A_Indices *ind = lfirst(ar);
284 if (lowerIndexpr || (!upperIndexpr && ind->lidx))
288 * XXX assume all lowerIndexpr is non-null in this
291 lowerIndexpr = lappend(lowerIndexpr, ind->lidx);
293 upperIndexpr = lappend(upperIndexpr, ind->uidx);
297 expr = (Node *) make_array_set(target_expr,
301 attrtype = attnumTypeId(rd, resdomno);
302 attrtypmod = get_atttypmod(RelationGetRelid(rd), resdomno);
307 resdomno = pstate->p_last_resno++;
309 attrtypmod = type_mod;
312 resnode = makeResdom((AttrNumber) resdomno,
320 return makeTargetEntry(resnode, expr);
321 } /* MakeTargetEntryExpr() */
324 * MakeTargetEntryCase()
325 * Make a TargetEntry from a case node.
328 MakeTargetEntryCase(ParseState *pstate,
338 expr = (CaseExpr *) transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
340 type_id = expr->casetype;
342 handleTargetColname(pstate, &res->name, NULL, NULL);
343 if (res->name == NULL)
344 res->name = FigureColname((Node *) expr, res->val);
346 resdomno = pstate->p_last_resno++;
347 resnode = makeResdom((AttrNumber) resdomno,
355 tent = makeNode(TargetEntry);
356 tent->resdom = resnode;
357 tent->expr = (Node *) expr;
360 } /* MakeTargetEntryCase() */
363 * MakeTargetEntryComplex()
364 * Make a TargetEntry from a complex node.
367 MakeTargetEntryComplex(ParseState *pstate,
370 Node *expr = transformExpr(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
372 handleTargetColname(pstate, &res->name, NULL, NULL);
373 /* note indirection has not been transformed */
374 if (pstate->p_is_insert && res->indirection != NIL)
376 /* this is an array assignment */
389 if (exprType(expr) != UNKNOWNOID || !IsA(expr, Const))
390 elog(ERROR, "String constant expected (internal error)");
392 val = (char *) textout((struct varlena *)
393 ((Const *) expr)->constvalue);
394 str = save_str = (char *) palloc(strlen(val) + MAXDIM * 25 + 2);
395 foreach(elt, res->indirection)
397 A_Indices *aind = (A_Indices *) lfirst(elt);
399 aind->uidx = transformExpr(pstate, aind->uidx, EXPR_COLUMN_FIRST);
400 if (!IsA(aind->uidx, Const))
401 elog(ERROR, "Array Index for Append should be a constant");
403 uindx[i] = ((Const *) aind->uidx)->constvalue;
404 if (aind->lidx != NULL)
406 aind->lidx = transformExpr(pstate, aind->lidx, EXPR_COLUMN_FIRST);
407 if (!IsA(aind->lidx, Const))
408 elog(ERROR, "Array Index for Append should be a constant");
410 lindx[i] = ((Const *) aind->lidx)->constvalue;
414 if (lindx[i] > uindx[i])
415 elog(ERROR, "Lower index cannot be greater than upper index");
417 sprintf(str, "[%d:%d]", lindx[i], uindx[i]);
421 sprintf(str, "=%s", val);
422 rd = pstate->p_target_relation;
424 resdomno = attnameAttNum(rd, res->name);
425 ndims = attnumAttNelems(rd, resdomno);
427 elog(ERROR, "Array dimensions do not match");
429 constval = makeNode(Value);
430 constval->type = T_String;
431 constval->val.str = save_str;
432 return MakeTargetEntryExpr(pstate, res->name,
433 (Node *) make_const(constval),
439 /* this is not an array assignment */
440 char *colname = res->name;
446 * if you're wondering why this is here, look at the yacc
447 * grammar for why a name can be missing. -ay
449 colname = FigureColname(expr, res->val);
451 if (res->indirection)
453 List *ilist = res->indirection;
457 A_Indices *ind = lfirst(ilist);
459 ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
460 ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
461 ilist = lnext(ilist);
465 return MakeTargetEntryExpr(pstate, res->name, expr,
466 res->indirection, false);
471 * MakeTargetEntryAttr()
472 * Make a TargetEntry from a complex node.
475 MakeTargetEntryAttr(ParseState *pstate,
480 Attr *att = (Attr *) res->val;
486 List *attrs = att->attrs;
489 attrname = strVal(lfirst(att->attrs));
492 * Target item is fully specified: ie. relation.attribute
494 result = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno, EXPR_COLUMN_FIRST);
495 handleTargetColname(pstate, &res->name, att->relname, attrname);
496 if (att->indirection != NIL)
498 List *ilist = att->indirection;
502 A_Indices *ind = lfirst(ilist);
504 ind->lidx = transformExpr(pstate, ind->lidx, EXPR_COLUMN_FIRST);
505 ind->uidx = transformExpr(pstate, ind->uidx, EXPR_COLUMN_FIRST);
506 ilist = lnext(ilist);
508 result = (Node *) make_array_ref(result, att->indirection);
510 type_id = exprType(result);
511 if (nodeTag(result) == T_Var)
512 type_mod = ((Var *) result)->vartypmod;
515 /* move to last entry */
516 while (lnext(attrs) != NIL)
517 attrs = lnext(attrs);
518 resname = (res->name) ? res->name : strVal(lfirst(attrs));
519 if (pstate->p_is_insert || pstate->p_is_update)
524 * insert or update query -- insert, update work only on one
525 * relation, so multiple occurence of same resdomno is bogus
527 rd = pstate->p_target_relation;
529 resdomno = attnameAttNum(rd, res->name);
532 resdomno = pstate->p_last_resno++;
533 resnode = makeResdom((AttrNumber) resdomno,
540 tent = makeNode(TargetEntry);
541 tent->resdom = resnode;
547 /* transformTargetList()
548 * Turns a list of ResTarget's into a list of TargetEntry's.
551 transformTargetList(ParseState *pstate, List *targetlist)
553 List *p_target = NIL;
554 List *tail_p_target = NIL;
556 while (targetlist != NIL)
558 ResTarget *res = (ResTarget *) lfirst(targetlist);
559 TargetEntry *tent = NULL;
561 switch (nodeTag(res->val))
567 identname = ((Ident *) res->val)->name;
568 tent = MakeTargetEntryIdent(pstate,
569 (Node *) res->val, &res->name, NULL, identname, false);
577 tent = MakeTargetEntryComplex(pstate, res);
582 tent = MakeTargetEntryCase(pstate, res);
587 bool expand_star = false;
589 Attr *att = (Attr *) res->val;
592 * Target item is a single '*', expand all tables (eg.
595 if (att->relname != NULL && !strcmp(att->relname, "*"))
597 if (tail_p_target == NIL)
598 p_target = tail_p_target = ExpandAllTables(pstate);
600 lnext(tail_p_target) = ExpandAllTables(pstate);
607 * Target item is relation.*, expand the table
608 * (eg. SELECT emp.*, dname FROM emp, dept)
610 attrname = strVal(lfirst(att->attrs));
611 if (att->attrs != NIL && !strcmp(attrname, "*"))
615 * tail_p_target is the target list we're
616 * building in the while loop. Make sure we
617 * fix it after appending more nodes.
619 if (tail_p_target == NIL)
620 p_target = tail_p_target = expandAll(pstate, att->relname,
621 att->relname, &pstate->p_last_resno);
623 lnext(tail_p_target) = expandAll(pstate, att->relname, att->relname,
624 &pstate->p_last_resno);
630 while (lnext(tail_p_target) != NIL)
631 /* make sure we point to the last target entry */
632 tail_p_target = lnext(tail_p_target);
635 * skip rest of while loop
637 targetlist = lnext(targetlist);
642 tent = MakeTargetEntryAttr(pstate, res);
648 elog(ERROR, "Unable to transform targetlist (internal error)");
653 p_target = tail_p_target = lcons(tent, NIL);
656 lnext(tail_p_target) = lcons(tent, NIL);
657 tail_p_target = lnext(tail_p_target);
659 targetlist = lnext(targetlist);
663 } /* transformTargetList() */
667 CoerceTargetExpr(ParseState *pstate,
672 if (can_coerce_type(1, &type_id, &attrtype))
673 expr = coerce_type(pstate, expr, type_id, attrtype, -1);
675 #ifndef DISABLE_STRING_HACKS
678 * string hacks to get transparent conversions w/o explicit
681 else if ((attrtype == BPCHAROID) || (attrtype == VARCHAROID))
683 Oid text_id = TEXTOID;
685 if (type_id == TEXTOID)
688 else if (can_coerce_type(1, &type_id, &text_id))
689 expr = coerce_type(pstate, expr, type_id, text_id, -1);
699 } /* CoerceTargetExpr() */
703 * Apparently going to a fixed-length string?
704 * Then explicitly size for storage...
707 SizeTargetExpr(ParseState *pstate,
715 Oid oid_array[MAXFARGS];
720 funcname = typeidTypeName(attrtype);
721 oid_array[0] = attrtype;
722 oid_array[1] = INT4OID;
723 for (i = 2; i < MAXFARGS; i++)
724 oid_array[i] = InvalidOid;
726 /* attempt to find with arguments exactly as specified... */
727 ftup = SearchSysCacheTuple(PRONAME,
728 PointerGetDatum(funcname),
730 PointerGetDatum(oid_array),
733 if (HeapTupleIsValid(ftup))
735 func = makeNode(FuncCall);
736 func->funcname = funcname;
738 cons = makeNode(A_Const);
739 cons->val.type = T_Integer;
740 cons->val.val.ival = attrtypmod;
741 func->args = lappend(lcons(expr, NIL), cons);
743 expr = transformExpr(pstate, (Node *) func, EXPR_COLUMN_FIRST);
747 } /* SizeTargetExpr() */
752 * generate a list of column names if not supplied or
753 * test supplied column names to make sure they are in target table
754 * (used exclusively for inserts)
757 makeTargetNames(ParseState *pstate, List *cols)
761 /* Generate ResTarget if not supplied */
767 Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs;
769 numcol = pstate->p_target_relation->rd_rel->relnatts;
770 for (i = 0; i < numcol; i++)
772 Ident *id = makeNode(Ident);
774 id->name = palloc(NAMEDATALEN);
775 StrNCpy(id->name, attr[i]->attname.data, NAMEDATALEN);
776 id->indirection = NIL;
779 cols = tl = lcons(id, NIL);
782 lnext(tl) = lcons(id, NIL);
792 char *name = ((Ident *) lfirst(tl))->name;
794 /* elog on failure */
795 attnameAttNum(pstate->p_target_relation, name);
796 foreach(nxt, lnext(tl))
797 if (!strcmp(name, ((Ident *) lfirst(nxt))->name))
798 elog(ERROR, "Attribute '%s' should be specified only once", name);
807 * turns '*' (in the target list) into a list of attributes
808 * (of all relations in the range table)
811 ExpandAllTables(ParseState *pstate)
814 List *legit_rtable = NIL;
818 rtable = pstate->p_rtable;
819 if (pstate->p_is_rule)
823 * skip first two entries, "*new*" and "*current*"
825 rtable = lnext(lnext(pstate->p_rtable));
830 elog(ERROR, "Wildcard with no tables specified.");
833 * go through the range table and make a list of range table entries
834 * which we will expand.
838 RangeTblEntry *rte = lfirst(rt);
841 * we only expand those specify in the from clause. (This will
842 * also prevent us from using the wrong table in inserts: eg.
843 * tenk2 in "insert into tenk2 select * from tenk1;")
847 legit_rtable = lappend(legit_rtable, rte);
850 foreach(rt, legit_rtable)
852 RangeTblEntry *rte = lfirst(rt);
856 target = expandAll(pstate, rte->relname, rte->refname,
857 &pstate->p_last_resno);
860 while (temp != NIL && lnext(temp) != NIL)
862 lnext(temp) = expandAll(pstate, rte->relname, rte->refname,
863 &pstate->p_last_resno);
871 * if the name of the resulting column is not specified in the target
872 * list, we have to guess.
876 FigureColname(Node *expr, Node *resval)
878 switch (nodeTag(expr))
881 return (char *) ((Aggref *) expr)->aggname;
883 if (((Expr *) expr)->opType == FUNC_EXPR)
885 if (nodeTag(resval) == T_FuncCall)
886 return ((FuncCall *) resval)->funcname;
893 name = FigureColname(((CaseExpr *) expr)->defresult, resval);
894 if (!strcmp(name, "?column?"))