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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy