8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.120 2008/01/01 19:45:49 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.121 2008/03/18 22:04:14 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
20
20
#include "commands/trigger.h"
21
21
#include "executor/functions.h"
22
22
#include "funcapi.h"
23
+ #include "nodes/makefuncs.h"
23
24
#include "parser/parse_coerce.h"
24
25
#include "parser/parse_expr.h"
25
26
#include "tcop/tcopprot.h"
@@ -269,6 +270,7 @@ init_sql_fcache(FmgrInfo *finfo)
269
270
fcache -> returnsTuple = check_sql_fn_retval (foid ,
270
271
rettype ,
271
272
queryTree_list ,
273
+ false,
272
274
& fcache -> junkFilter );
273
275
274
276
/* Finally, plan the queries */
@@ -856,7 +858,9 @@ ShutdownSQLFunction(Datum arg)
856
858
*
857
859
* The return value of a sql function is the value returned by
858
860
* the final query in the function. We do some ad-hoc type checking here
859
- * to be sure that the user is returning the type he claims.
861
+ * to be sure that the user is returning the type he claims. There are
862
+ * also a couple of strange-looking features to assist callers in dealing
863
+ * with allowed special cases, such as binary-compatible result types.
860
864
*
861
865
* For a polymorphic function the passed rettype must be the actual resolved
862
866
* output type of the function; we should never see a polymorphic pseudotype
@@ -868,13 +872,18 @@ ShutdownSQLFunction(Datum arg)
868
872
* allow "SELECT rowtype_expression", this may be false even when the declared
869
873
* function return type is a rowtype.
870
874
*
875
+ * If insertRelabels is true, then binary-compatible cases are dealt with
876
+ * by actually inserting RelabelType nodes into the final SELECT; obviously
877
+ * the caller must pass a parsetree that it's okay to modify in this case.
878
+ *
871
879
* If junkFilter isn't NULL, then *junkFilter is set to a JunkFilter defined
872
880
* to convert the function's tuple result to the correct output tuple type.
873
881
* Whenever the result value is false (ie, the function isn't returning a
874
882
* tuple result), *junkFilter is set to NULL.
875
883
*/
876
884
bool
877
885
check_sql_fn_retval (Oid func_id , Oid rettype , List * queryTreeList ,
886
+ bool insertRelabels ,
878
887
JunkFilter * * junkFilter )
879
888
{
880
889
Query * parse ;
@@ -945,25 +954,36 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
945
954
rettype == VOIDOID )
946
955
{
947
956
/*
948
- * For scalar-type returns, the target list should have exactly one
949
- * entry, and its type should agree with what the user declared. (As
950
- * of Postgres 7.2, we accept binary-compatible types too.)
957
+ * For scalar-type returns, the target list must have exactly one
958
+ * non-junk entry, and its type must agree with what the user
959
+ * declared; except we allow binary-compatible types too.
951
960
*/
961
+ TargetEntry * tle ;
962
+
952
963
if (tlistlen != 1 )
953
964
ereport (ERROR ,
954
965
(errcode (ERRCODE_INVALID_FUNCTION_DEFINITION ),
955
966
errmsg ("return type mismatch in function declared to return %s" ,
956
967
format_type_be (rettype )),
957
968
errdetail ("Final SELECT must return exactly one column." )));
958
969
959
- restype = exprType ((Node * ) ((TargetEntry * ) linitial (tlist ))-> expr );
970
+ /* We assume here that non-junk TLEs must come first in tlists */
971
+ tle = (TargetEntry * ) linitial (tlist );
972
+ Assert (!tle -> resjunk );
973
+
974
+ restype = exprType ((Node * ) tle -> expr );
960
975
if (!IsBinaryCoercible (restype , rettype ))
961
976
ereport (ERROR ,
962
977
(errcode (ERRCODE_INVALID_FUNCTION_DEFINITION ),
963
978
errmsg ("return type mismatch in function declared to return %s" ,
964
979
format_type_be (rettype )),
965
980
errdetail ("Actual return type is %s." ,
966
981
format_type_be (restype ))));
982
+ if (insertRelabels && restype != rettype )
983
+ tle -> expr = (Expr * ) makeRelabelType (tle -> expr ,
984
+ rettype ,
985
+ -1 ,
986
+ COERCE_DONTCARE );
967
987
}
968
988
else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID )
969
989
{
@@ -977,14 +997,24 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
977
997
* If the target list is of length 1, and the type of the varnode in
978
998
* the target list matches the declared return type, this is okay.
979
999
* This can happen, for example, where the body of the function is
980
- * 'SELECT func2()', where func2 has the same return type as the
981
- * function that's calling it.
1000
+ * 'SELECT func2()', where func2 has the same composite return type
1001
+ * as the function that's calling it.
982
1002
*/
983
1003
if (tlistlen == 1 )
984
1004
{
985
- restype = exprType ((Node * ) ((TargetEntry * ) linitial (tlist ))-> expr );
1005
+ TargetEntry * tle = (TargetEntry * ) linitial (tlist );
1006
+
1007
+ Assert (!tle -> resjunk );
1008
+ restype = exprType ((Node * ) tle -> expr );
986
1009
if (IsBinaryCoercible (restype , rettype ))
1010
+ {
1011
+ if (insertRelabels && restype != rettype )
1012
+ tle -> expr = (Expr * ) makeRelabelType (tle -> expr ,
1013
+ rettype ,
1014
+ -1 ,
1015
+ COERCE_DONTCARE );
987
1016
return false; /* NOT returning whole tuple */
1017
+ }
988
1018
}
989
1019
990
1020
/* Is the rowtype fixed, or determined only at runtime? */
@@ -1043,6 +1073,11 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
1043
1073
format_type_be (tletype ),
1044
1074
format_type_be (atttype ),
1045
1075
tuplogcols )));
1076
+ if (insertRelabels && tletype != atttype )
1077
+ tle -> expr = (Expr * ) makeRelabelType (tle -> expr ,
1078
+ atttype ,
1079
+ -1 ,
1080
+ COERCE_DONTCARE );
1046
1081
}
1047
1082
1048
1083
for (;;)
@@ -1070,14 +1105,6 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
1070
1105
/* Report that we are returning entire tuple result */
1071
1106
return true;
1072
1107
}
1073
- else if (IsPolymorphicType (rettype ))
1074
- {
1075
- /* This should already have been caught ... */
1076
- ereport (ERROR ,
1077
- (errcode (ERRCODE_INVALID_FUNCTION_DEFINITION ),
1078
- errmsg ("cannot determine result data type" ),
1079
- errdetail ("A function returning a polymorphic type must have at least one polymorphic argument." )));
1080
- }
1081
1108
else
1082
1109
ereport (ERROR ,
1083
1110
(errcode (ERRCODE_INVALID_FUNCTION_DEFINITION ),
0 commit comments