From 22d0a96a13c1f4704d4ece80f789000f145ab03d Mon Sep 17 00:00:00 2001 From: shihao zhong Date: Sat, 31 Oct 2026 20:18:30 -0400 Subject: [PATCH] plpython validator: check only input arguments for pseudotypes The previous commit moved the pseudotype check into the validator and let OUT and TABLE arguments of pseudotype through only when prorettype is RECORD. That rejects a single OUT void parameter, which worked before. With one output argument, prorettype is that argument's type and the result type check above already covers it, and with more than one, prorettype is RECORD. So only input arguments need checking, and those are exactly proargtypes, as in fmgr_sql_validator(). --- src/pl/plpython/expected/plpython_void.out | 10 ++++++ src/pl/plpython/plpy_main.c | 41 +++++++--------------- src/pl/plpython/sql/plpython_void.sql | 7 ++++ 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/src/pl/plpython/expected/plpython_void.out b/src/pl/plpython/expected/plpython_void.out index 07d0760783e..07ef6a4814e 100644 --- a/src/pl/plpython/expected/plpython_void.out +++ b/src/pl/plpython/expected/plpython_void.out @@ -28,3 +28,13 @@ SELECT test_return_none(), test_return_none() IS NULL AS "is null"; | t (1 row) +-- a single void OUT parameter works the same as RETURNS void +CREATE FUNCTION test_void_out(OUT v void) AS $$ +x = 10 +$$ LANGUAGE plpython3u; +SELECT test_void_out(); + test_void_out +--------------- + +(1 row) + diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c index ce0e7044d9d..a198166c956 100644 --- a/src/pl/plpython/plpy_main.c +++ b/src/pl/plpython/plpy_main.c @@ -10,7 +10,6 @@ #include "commands/event_trigger.h" #include "commands/trigger.h" #include "executor/spi.h" -#include "funcapi.h" #include "miscadmin.h" #include "plpy_elog.h" #include "plpy_exec.h" @@ -115,10 +114,6 @@ plpython3_validator(PG_FUNCTION_ARGS) HeapTuple tuple; Form_pg_proc procStruct; Oid rettype; - Oid *argtypes; - char **argnames, - *argmodes; - int nargs; PLyTrigType is_trigger; TriggerData trigdata; EventTriggerData etrigdata; @@ -149,30 +144,20 @@ plpython3_validator(PG_FUNCTION_ARGS) format_type_be(rettype)))); } - /* Disallow pseudotype arguments, except for output records */ - nargs = get_func_arg_info(tuple, &argtypes, &argnames, &argmodes); - for (int i = 0; i < nargs; i++) + /* + * Disallow pseudotype input arguments. Output arguments need no check: + * with one of them, prorettype is its type and was checked above, and + * with more than one, prorettype is RECORD. + */ + for (int i = 0; i < procStruct->pronargs; i++) { - if (get_typtype(argtypes[i]) == TYPTYPE_PSEUDO) - { - if (argmodes && - (argmodes[i] == PROARGMODE_OUT || - argmodes[i] == PROARGMODE_TABLE)) - { - if (rettype == RECORDOID) - /* okay */ ; - else - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("PL/Python functions cannot return type %s", - format_type_be(argtypes[i])))); - } - else - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("PL/Python functions cannot accept type %s", - format_type_be(argtypes[i])))); - } + Oid argtype = procStruct->proargtypes.values[i]; + + if (get_typtype(argtype) == TYPTYPE_PSEUDO) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("PL/Python functions cannot accept type %s", + format_type_be(argtype)))); } is_trigger = PLy_procedure_is_trigger(procStruct); diff --git a/src/pl/plpython/sql/plpython_void.sql b/src/pl/plpython/sql/plpython_void.sql index 5a1a6711fb0..0854d0c4740 100644 --- a/src/pl/plpython/sql/plpython_void.sql +++ b/src/pl/plpython/sql/plpython_void.sql @@ -20,3 +20,10 @@ $$ LANGUAGE plpython3u; SELECT test_void_func1(), test_void_func1() IS NULL AS "is null"; SELECT test_void_func2(); -- should fail SELECT test_return_none(), test_return_none() IS NULL AS "is null"; + +-- a single void OUT parameter works the same as RETURNS void +CREATE FUNCTION test_void_out(OUT v void) AS $$ +x = 10 +$$ LANGUAGE plpython3u; + +SELECT test_void_out();