Commit 5b2208a8 authored by Tom Lane's avatar Tom Lane

Allow the return value of an SQL function to be binary-compatible with

the declared result type, rather than requiring exact type match as
before.  Per pghackers discusssion of 14-Aug.
parent 627c0d44
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.57 2001/08/10 15:49:39 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.58 2001/08/23 00:49:46 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
...@@ -332,7 +333,7 @@ checkretval(Oid rettype, List *queryTreeList) ...@@ -332,7 +333,7 @@ checkretval(Oid rettype, List *queryTreeList)
List *tlistitem; List *tlistitem;
int tlistlen; int tlistlen;
Oid typerelid; Oid typerelid;
Resdom *resnode; Oid restype;
Relation reln; Relation reln;
Oid relid; Oid relid;
int relnatts; int relnatts;
...@@ -377,6 +378,7 @@ checkretval(Oid rettype, List *queryTreeList) ...@@ -377,6 +378,7 @@ checkretval(Oid rettype, List *queryTreeList)
/* /*
* For base-type returns, the target list should have exactly one * For base-type returns, the target list should have exactly one
* entry, and its type should agree with what the user declared. * entry, and its type should agree with what the user declared.
* (As of Postgres 7.2, we accept binary-compatible types too.)
*/ */
typerelid = typeidTypeRelid(rettype); typerelid = typeidTypeRelid(rettype);
if (typerelid == InvalidOid) if (typerelid == InvalidOid)
...@@ -385,25 +387,25 @@ checkretval(Oid rettype, List *queryTreeList) ...@@ -385,25 +387,25 @@ checkretval(Oid rettype, List *queryTreeList)
elog(ERROR, "function declared to return %s returns multiple columns in final SELECT", elog(ERROR, "function declared to return %s returns multiple columns in final SELECT",
format_type_be(rettype)); format_type_be(rettype));
resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom; restype = ((TargetEntry *) lfirst(tlist))->resdom->restype;
if (resnode->restype != rettype) if (restype != rettype && !IS_BINARY_COMPATIBLE(restype, rettype))
elog(ERROR, "return type mismatch in function: declared to return %s, returns %s", elog(ERROR, "return type mismatch in function: declared to return %s, returns %s",
format_type_be(rettype), format_type_be(resnode->restype)); format_type_be(rettype), format_type_be(restype));
return; return;
} }
/* /*
* If the target list is of length 1, and the type of the varnode in * If the target list is of length 1, and the type of the varnode in
* the target list is the same as the declared return type, this is * the target list matches the declared return type, this is okay.
* okay. This can happen, for example, where the body of the function * This can happen, for example, where the body of the function
* is 'SELECT (x = func2())', where func2 has the same return type as * is 'SELECT func2()', where func2 has the same return type as
* the function that's calling it. * the function that's calling it.
*/ */
if (tlistlen == 1) if (tlistlen == 1)
{ {
resnode = (Resdom *) ((TargetEntry *) lfirst(tlist))->resdom; restype = ((TargetEntry *) lfirst(tlist))->resdom->restype;
if (resnode->restype == rettype) if (restype == rettype || IS_BINARY_COMPATIBLE(restype, rettype))
return; return;
} }
...@@ -427,15 +429,17 @@ checkretval(Oid rettype, List *queryTreeList) ...@@ -427,15 +429,17 @@ checkretval(Oid rettype, List *queryTreeList)
{ {
TargetEntry *tle = (TargetEntry *) lfirst(tlistitem); TargetEntry *tle = (TargetEntry *) lfirst(tlistitem);
Oid tletype; Oid tletype;
Oid atttype;
if (tle->resdom->resjunk) if (tle->resdom->resjunk)
continue; continue;
tletype = exprType(tle->expr); tletype = exprType(tle->expr);
if (tletype != reln->rd_att->attrs[i]->atttypid) atttype = reln->rd_att->attrs[i]->atttypid;
if (tletype != atttype && !IS_BINARY_COMPATIBLE(tletype, atttype))
elog(ERROR, "function declared to return %s returns %s instead of %s at column %d", elog(ERROR, "function declared to return %s returns %s instead of %s at column %d",
format_type_be(rettype), format_type_be(rettype),
format_type_be(tletype), format_type_be(tletype),
format_type_be(reln->rd_att->attrs[i]->atttypid), format_type_be(atttype),
i + 1); i + 1);
i++; i++;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment