aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/functions.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2025-04-03 16:03:06 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2025-04-03 16:03:12 -0400
commitdbd437e670b88ca67f6b2477e853412a0e82a8cc (patch)
treeaddd72e99f1262b338e9d0f33f826a5fd024af6f /src/backend/executor/functions.c
parent46c4c7cbc6d562d5f1b784fea9527c998c190b99 (diff)
downloadpostgresql-dbd437e670b88ca67f6b2477e853412a0e82a8cc.tar.gz
postgresql-dbd437e670b88ca67f6b2477e853412a0e82a8cc.zip
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 <exclusion@gmail.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/0fde377a-3870-4d18-946a-ce008ee5bb88@gmail.com
Diffstat (limited to 'src/backend/executor/functions.c')
-rw-r--r--src/backend/executor/functions.c15
1 files changed, 14 insertions, 1 deletions
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",