88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.57 2001/08/10 15 :49:39 petere Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.58 2001/08/23 00 :49:46 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
2222#include "catalog/pg_type.h"
2323#include "executor/executor.h"
2424#include "miscadmin.h"
25+ #include "parser/parse_coerce.h"
2526#include "parser/parse_expr.h"
2627#include "parser/parse_type.h"
2728#include "tcop/tcopprot.h"
@@ -332,7 +333,7 @@ checkretval(Oid rettype, List *queryTreeList)
332333List * tlistitem ;
333334int tlistlen ;
334335Oid typerelid ;
335- Resdom * resnode ;
336+ Oid restype ;
336337Relation reln ;
337338Oid relid ;
338339int relnatts ;
@@ -377,6 +378,7 @@ checkretval(Oid rettype, List *queryTreeList)
377378/*
378379 * For base-type returns, the target list should have exactly one
379380 * entry, and its type should agree with what the user declared.
381+ * (As of Postgres 7.2, we accept binary-compatible types too.)
380382 */
381383typerelid = typeidTypeRelid (rettype );
382384if (typerelid == InvalidOid )
@@ -385,25 +387,25 @@ checkretval(Oid rettype, List *queryTreeList)
385387elog (ERROR ,"function declared to return %s returns multiple columns in final SELECT" ,
386388format_type_be (rettype ));
387389
388- resnode = (Resdom * ) (( TargetEntry * )lfirst (tlist ))-> resdom ;
389- if (resnode -> restype != rettype )
390+ restype = (( TargetEntry * )lfirst (tlist ))-> resdom -> restype ;
391+ if (restype != rettype && ! IS_BINARY_COMPATIBLE ( restype , rettype ) )
390392elog (ERROR ,"return type mismatch in function: declared to return %s, returns %s" ,
391- format_type_be (rettype ),format_type_be (resnode -> restype ));
393+ format_type_be (rettype ),format_type_be (restype ));
392394
393395return ;
394396}
395397
396398/*
397399 * If the target list is of length 1, and the type of the varnode in
398- * the target listis thesame as the declared return type, this is
399- *okay. This can happen, for example, where the body of the function
400- * is 'SELECT(x = func2() )', where func2 has the same return type as
400+ * the target listmatches the declared return type, this is okay.
401+ * This can happen, for example, where the body of the function
402+ * is 'SELECT func2()', where func2 has the same return type as
401403 * the function that's calling it.
402404 */
403405if (tlistlen == 1 )
404406{
405- resnode = (Resdom * ) (( TargetEntry * )lfirst (tlist ))-> resdom ;
406- if (resnode -> restype == rettype )
407+ restype = (( TargetEntry * )lfirst (tlist ))-> resdom -> restype ;
408+ if (restype == rettype || IS_BINARY_COMPATIBLE ( restype , rettype ) )
407409return ;
408410}
409411
@@ -427,15 +429,17 @@ checkretval(Oid rettype, List *queryTreeList)
427429{
428430TargetEntry * tle = (TargetEntry * )lfirst (tlistitem );
429431Oid tletype ;
432+ Oid atttype ;
430433
431434if (tle -> resdom -> resjunk )
432435continue ;
433436tletype = exprType (tle -> expr );
434- if (tletype != reln -> rd_att -> attrs [i ]-> atttypid )
437+ atttype = reln -> rd_att -> attrs [i ]-> atttypid ;
438+ if (tletype != atttype && !IS_BINARY_COMPATIBLE (tletype ,atttype ))
435439elog (ERROR ,"function declared to return %s returns %s instead of %s at column %d" ,
436440format_type_be (rettype ),
437441format_type_be (tletype ),
438- format_type_be (reln -> rd_att -> attrs [ i ] -> atttypid ),
442+ format_type_be (atttype ),
439443i + 1 );
440444i ++ ;
441445}