Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9a527f1

Browse files
committed
Fix check_sql_fn_retval to allow the case where a SQL function declared to
return void ends with a SELECT, if that SELECT has a single result that is also of type void. Without this, it's hard to write a void function that calls another void function. Per gripe from Peter. Back-patch as far as 8.0.
1 parent cac01fc commit 9a527f1

File tree

1 file changed

+22
-24
lines changed

1 file changed

+22
-24
lines changed

src/backend/executor/functions.c

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.113 2007/04/02 03:49:38 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.114 2007/04/02 18:49:29 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -849,9 +849,9 @@ ShutdownSQLFunction(Datum arg)
849849
* ANYELEMENT as rettype. (This means we can't check the type during function
850850
* definition of a polymorphic function.)
851851
*
852-
* The return value is true if the function returns the entire tuple result
853-
* of its final SELECT, and false otherwise. Note that because we allow
854-
* "SELECT rowtype_expression", this may be false even when the declared
852+
* This function returns true if the sql function returns the entire tuple
853+
* result of its final SELECT, and false otherwise. Note that because we
854+
* allow "SELECT rowtype_expression", this may be false even when the declared
855855
* function return type is a rowtype.
856856
*
857857
* If junkFilter isn't NULL, then *junkFilter is set to a JunkFilter defined
@@ -864,7 +864,6 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
864864
JunkFilter **junkFilter)
865865
{
866866
Query *parse;
867-
bool isSelect;
868867
List *tlist;
869868
ListCell *tlistitem;
870869
int tlistlen;
@@ -890,32 +889,30 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
890889
parse = (Query *) lfirst(list_tail(queryTreeList));
891890

892891
/*
893-
* Note: eventually replace this with QueryReturnsTuples? We'd need a
894-
* more general method of determining the output type, though.
895-
*/
896-
isSelect = (parse->commandType == CMD_SELECT && parse->into == NULL);
897-
898-
/*
899-
* The last query must be a SELECT if and only if return type isn't VOID.
892+
* If the last query isn't a SELECT, the return type must be VOID.
893+
*
894+
* Note: eventually replace this test with QueryReturnsTuples? We'd need
895+
* a more general method of determining the output type, though.
900896
*/
901-
if (rettype == VOIDOID)
897+
if (!(parse->commandType == CMD_SELECT && parse->into == NULL))
902898
{
903-
if (isSelect)
899+
if (rettype != VOIDOID)
904900
ereport(ERROR,
905901
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
906902
errmsg("return type mismatch in function declared to return %s",
907903
format_type_be(rettype)),
908-
errdetail("Function's final statement must not be a SELECT.")));
904+
errdetail("Function's final statement must be a SELECT.")));
909905
return false;
910906
}
911907

912-
/* by here, the function is declared to return some type */
913-
if (!isSelect)
914-
ereport(ERROR,
915-
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
916-
errmsg("return type mismatch in function declared to return %s",
917-
format_type_be(rettype)),
918-
errdetail("Function's final statement must be a SELECT.")));
908+
/*
909+
* OK, it's a SELECT, so it must return something matching the declared
910+
* type. (We used to insist that the declared type not be VOID in this
911+
* case, but that makes it hard to write a void function that exits
912+
* after calling another void function. Instead, we insist that the
913+
* SELECT return void ... so void is treated as if it were a scalar type
914+
* below.)
915+
*/
919916

920917
/*
921918
* Count the non-junk entries in the result targetlist.
@@ -927,10 +924,11 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
927924

928925
if (fn_typtype == TYPTYPE_BASE ||
929926
fn_typtype == TYPTYPE_DOMAIN ||
930-
fn_typtype == TYPTYPE_ENUM)
927+
fn_typtype == TYPTYPE_ENUM ||
928+
rettype == VOIDOID)
931929
{
932930
/*
933-
* For base-type returns, the target list should have exactly one
931+
* For scalar-type returns, the target list should have exactly one
934932
* entry, and its type should agree with what the user declared. (As
935933
* of Postgres 7.2, we accept binary-compatible types too.)
936934
*/

0 commit comments

Comments
 (0)