aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/functions.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-04-02 18:49:29 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-04-02 18:49:29 +0000
commit9a527f18488cb336b39ce86520dd25e438a59144 (patch)
treee66e796d059b0c9cef93709f893875ba742344af /src/backend/executor/functions.c
parentcac01fc0380662a68264695b43870074d1257822 (diff)
downloadpostgresql-9a527f18488cb336b39ce86520dd25e438a59144.tar.gz
postgresql-9a527f18488cb336b39ce86520dd25e438a59144.zip
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.
Diffstat (limited to 'src/backend/executor/functions.c')
-rw-r--r--src/backend/executor/functions.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 4781bd903ab..1e1d450be57 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.113 2007/04/02 03:49:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.114 2007/04/02 18:49:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -849,9 +849,9 @@ ShutdownSQLFunction(Datum arg)
* ANYELEMENT as rettype. (This means we can't check the type during function
* definition of a polymorphic function.)
*
- * The return value is true if the function returns the entire tuple result
- * of its final SELECT, and false otherwise. Note that because we allow
- * "SELECT rowtype_expression", this may be false even when the declared
+ * This function returns true if the sql function returns the entire tuple
+ * result of its final SELECT, and false otherwise. Note that because we
+ * allow "SELECT rowtype_expression", this may be false even when the declared
* function return type is a rowtype.
*
* 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,
JunkFilter **junkFilter)
{
Query *parse;
- bool isSelect;
List *tlist;
ListCell *tlistitem;
int tlistlen;
@@ -890,32 +889,30 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
parse = (Query *) lfirst(list_tail(queryTreeList));
/*
- * Note: eventually replace this with QueryReturnsTuples? We'd need a
- * more general method of determining the output type, though.
- */
- isSelect = (parse->commandType == CMD_SELECT && parse->into == NULL);
-
- /*
- * The last query must be a SELECT if and only if return type isn't VOID.
+ * If the last query isn't a SELECT, the return type must be VOID.
+ *
+ * Note: eventually replace this test with QueryReturnsTuples? We'd need
+ * a more general method of determining the output type, though.
*/
- if (rettype == VOIDOID)
+ if (!(parse->commandType == CMD_SELECT && parse->into == NULL))
{
- if (isSelect)
+ if (rettype != VOIDOID)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
errmsg("return type mismatch in function declared to return %s",
format_type_be(rettype)),
- errdetail("Function's final statement must not be a SELECT.")));
+ errdetail("Function's final statement must be a SELECT.")));
return false;
}
- /* by here, the function is declared to return some type */
- if (!isSelect)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("return type mismatch in function declared to return %s",
- format_type_be(rettype)),
- errdetail("Function's final statement must be a SELECT.")));
+ /*
+ * OK, it's a SELECT, so it must return something matching the declared
+ * type. (We used to insist that the declared type not be VOID in this
+ * case, but that makes it hard to write a void function that exits
+ * after calling another void function. Instead, we insist that the
+ * SELECT return void ... so void is treated as if it were a scalar type
+ * below.)
+ */
/*
* Count the non-junk entries in the result targetlist.
@@ -927,10 +924,11 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
if (fn_typtype == TYPTYPE_BASE ||
fn_typtype == TYPTYPE_DOMAIN ||
- fn_typtype == TYPTYPE_ENUM)
+ fn_typtype == TYPTYPE_ENUM ||
+ rettype == VOIDOID)
{
/*
- * For base-type returns, the target list should have exactly one
+ * For scalar-type returns, the target list should have exactly one
* entry, and its type should agree with what the user declared. (As
* of Postgres 7.2, we accept binary-compatible types too.)
*/