Further cleanups for type coercion: treat the locution typename(argument)

as representing a type coercion request in more cases than we did before.
It will work now whenever no underlying function is required, ie if the
coercion is binary-compatible or if the argument is a previously untyped
string constant.  Otherwise, you still need a real function to exist.
This commit is contained in:
Tom Lane 2000-02-20 23:04:06 +00:00
parent 57b30e8e22
commit 07c495f5d8
1 changed files with 34 additions and 34 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.71 2000/02/20 21:32:10 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.72 2000/02/20 23:04:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -292,9 +292,9 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
/* Is it a plain Relation name from the parser? */ /* Is it a plain Relation name from the parser? */
if (IsA(first_arg, Ident) && ((Ident *) first_arg)->isRel) if (IsA(first_arg, Ident) && ((Ident *) first_arg)->isRel)
{ {
Ident *ident = (Ident *) first_arg;
RangeTblEntry *rte; RangeTblEntry *rte;
AttrNumber attnum; AttrNumber attnum;
Ident *ident = (Ident *) first_arg;
/* /*
* first arg is a relation. This could be a projection. * first arg is a relation. This could be a projection.
@ -479,11 +479,13 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
} }
/* /*
* See if this is a single argument function with the function * See if this is really a type-coercion request: single-argument
* name also a type name and the input argument and type name * function call where the function name is a type name. If so,
* binary compatible. If so, we do not need to do any real * and if we can do the coercion trivially, just go ahead and do it
* conversion, but we do need to build a RelabelType node * without requiring there to be a real function for it. "Trivial"
* so that exprType() sees the result as being of the output type. * coercions are ones that involve binary-compatible types and ones
* that are coercing a previously-unknown-type literal constant
* to a specific type.
*/ */
if (nargs == 1) if (nargs == 1)
{ {
@ -492,16 +494,21 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
tp = SearchSysCacheTuple(TYPENAME, tp = SearchSysCacheTuple(TYPENAME,
PointerGetDatum(funcname), PointerGetDatum(funcname),
0, 0, 0); 0, 0, 0);
if (HeapTupleIsValid(tp) && if (HeapTupleIsValid(tp))
IS_BINARY_COMPATIBLE(typeTypeId(tp), exprType(lfirst(fargs))))
{ {
RelabelType *relabel = makeNode(RelabelType); Oid targetType = typeTypeId(tp);
Node *arg1 = lfirst(fargs);
Oid sourceType = exprType(arg1);
relabel->arg = (Node *) lfirst(fargs); if ((sourceType == UNKNOWNOID && IsA(arg1, Const)) ||
relabel->resulttype = typeTypeId(tp); sourceType == targetType ||
relabel->resulttypmod = -1; IS_BINARY_COMPATIBLE(sourceType, targetType))
{
return (Node *) relabel; /*
* coerce_type can handle these cases, so why duplicate code...
*/
return coerce_type(pstate, arg1, sourceType, targetType, -1);
}
} }
} }
@ -516,17 +523,17 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
nargs = 0; nargs = 0;
foreach(i, fargs) foreach(i, fargs)
{ {
int vnum; Node *arg = lfirst(i);
RangeTblEntry *rte;
Node *pair = lfirst(i);
if (nodeTag(pair) == T_Ident && ((Ident *) pair)->isRel) if (IsA(arg, Ident) && ((Ident *) arg)->isRel)
{ {
RangeTblEntry *rte;
int vnum;
/* /*
* a relation * a relation
*/ */
refname = ((Ident *) pair)->name; refname = ((Ident *) arg)->name;
rte = refnameRangeTableEntry(pstate, refname); rte = refnameRangeTableEntry(pstate, refname);
if (rte == NULL) if (rte == NULL)
@ -554,22 +561,15 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
*/ */
toid = typeTypeId(typenameType(relname)); toid = typeTypeId(typenameType(relname));
/* replace it in the arg list */ /* replace it in the arg list */
lfirst(fargs) = makeVar(vnum, 0, toid, -1, 0); lfirst(i) = makeVar(vnum, 0, toid, -1, 0);
} }
else if (!attisset) else if (!attisset)
{ /* set functions don't have parameters */ {
toid = exprType(arg);
/* }
* any function args which are typed "unknown", but aren't else
* constants, we don't know what to do with, because we can't {
* cast them - jolly /* if attisset is true, we already set toid for the single arg */
*/
if (exprType(pair) == UNKNOWNOID && !IsA(pair, Const))
elog(ERROR, "There is no function '%s'"
" with argument #%d of type UNKNOWN",
funcname, nargs+1);
else
toid = exprType(pair);
} }
/* Most of the rest of the parser just assumes that functions do not /* Most of the rest of the parser just assumes that functions do not