aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/executor/functions.c42
1 files changed, 20 insertions, 22 deletions
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 9f3a85dbf85..ec6ede2a544 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.91.4.3 2007/02/02 00:03:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.91.4.4 2007/04/02 18:49:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -848,9 +848,9 @@ ShutdownSQLFunction(Datum arg)
* 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
@@ -863,7 +863,6 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList,
JunkFilter **junkFilter)
{
Query *parse;
- int cmd;
List *tlist;
ListCell *tlistitem;
int tlistlen;
@@ -892,46 +891,45 @@ check_sql_fn_retval(Oid rettype, char fn_typtype, List *queryTreeList,
/* find the final query */
parse = (Query *) lfirst(list_tail(queryTreeList));
- cmd = parse->commandType;
- tlist = parse->targetList;
-
/*
- * 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.
*/
- if (rettype == VOIDOID)
+ if (!(parse->commandType == CMD_SELECT && parse->into == NULL))
{
- if (cmd == CMD_SELECT)
+ 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 (cmd != CMD_SELECT)
- 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.
*/
+ tlist = parse->targetList;
tlistlen = ExecCleanTargetListLength(tlist);
typerelid = typeidTypeRelid(rettype);
- if (fn_typtype == 'b' || fn_typtype == 'd')
+ if (fn_typtype == 'b' || fn_typtype == 'd' ||
+ rettype == VOIDOID)
{
/* Shouldn't have a typerelid */
Assert(typerelid == InvalidOid);
/*
- * 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.)
*/