From dbd437e670b88ca67f6b2477e853412a0e82a8cc Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 3 Apr 2025 16:03:06 -0400 Subject: Fix oversight in commit 0dca5d68d. As coded, fmgr_sql() would get an assertion failure for a SQL function that has an empty body and is declared to return some type other than VOID. Typically you'd never get that far because fmgr_sql_validator() would reject such a definition (I suspect that's how come I managed to miss the bug). But if check_function_bodies is off or the function is polymorphic, the validation check wouldn't get made. Reported-by: Alexander Lakhin Author: Tom Lane Discussion: https://postgr.es/m/0fde377a-3870-4d18-946a-ce008ee5bb88@gmail.com --- src/backend/executor/functions.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/backend/executor/functions.c') diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 5509013521d..cff75b2f647 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -1116,6 +1116,19 @@ sql_compile_callback(FunctionCallInfo fcinfo, */ func->num_queries = list_length(source_list); + /* + * Edge case: empty function body is OK only if it returns VOID. Normally + * we validate that the last statement returns the right thing in + * check_sql_stmt_retval, but we'll never reach that if there's no last + * statement. + */ + if (func->num_queries == 0 && 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 be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING."))); + /* Save the source trees in pcontext for now. */ MemoryContextSwitchTo(pcontext); func->source_list = copyObject(source_list); @@ -2103,7 +2116,7 @@ check_sql_stmt_retval(List *queryTreeList, } else { - /* Empty function body, or last statement is a utility command */ + /* Last statement is a utility command, or it rewrote to nothing */ ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("return type mismatch in function declared to return %s", -- cgit v1.2.3