mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
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.
This commit is contained in:
@ -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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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++;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user