diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index ab2b6ca148..e6c6001f39 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -959,6 +959,7 @@ fmgr_sql_validator(PG_FUNCTION_ARGS) (void) check_sql_fn_retval(querytree_list, rettype, rettupdesc, + proc->prokind, false, NULL); } diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index a4b6e1effd..6e926ef4ee 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -746,6 +746,7 @@ init_sql_fcache(FunctionCallInfo fcinfo, Oid collation, bool lazyEvalOK) fcache->returnsTuple = check_sql_fn_retval(queryTree_list, rettype, rettupdesc, + procedureStruct->prokind, false, &resulttlist); @@ -1606,6 +1607,7 @@ check_sql_fn_statements(List *queryTreeLists) bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, + char prokind, bool insertDroppedCols, List **resultTargetList) { @@ -1625,7 +1627,7 @@ check_sql_fn_retval(List *queryTreeLists, /* * If it's declared to return VOID, we don't care what's in the function. - * (This takes care of the procedure case, as well.) + * (This takes care of procedures with no output parameters, as well.) */ if (rettype == VOIDOID) return false; @@ -1780,8 +1782,13 @@ check_sql_fn_retval(List *queryTreeLists, * or not the record type really matches. For the moment we rely on * runtime type checking to catch any discrepancy, but it'd be nice to * do better at parse time. + * + * We must *not* do this for a procedure, however. Procedures with + * output parameter(s) have rettype RECORD, and the CALL code expects + * to get results corresponding to the list of output parameters, even + * when there's just one parameter that's composite. */ - if (tlistlen == 1) + if (tlistlen == 1 && prokind != PROKIND_PROCEDURE) { TargetEntry *tle = (TargetEntry *) linitial(tlist); diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 62de0225fe..d09dde210f 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -4707,6 +4707,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid, querytree_list = list_make1(querytree); if (check_sql_fn_retval(list_make1(querytree_list), result_type, rettupdesc, + funcform->prokind, false, NULL)) goto fail; /* reject whole-tuple-result cases */ @@ -5253,6 +5254,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte) */ if (!check_sql_fn_retval(list_make1(querytree_list), fexpr->funcresulttype, rettupdesc, + funcform->prokind, true, NULL) && (functypclass == TYPEFUNC_COMPOSITE || functypclass == TYPEFUNC_COMPOSITE_DOMAIN || diff --git a/src/include/executor/functions.h b/src/include/executor/functions.h index 1590d1efa6..27f948c6f5 100644 --- a/src/include/executor/functions.h +++ b/src/include/executor/functions.h @@ -47,6 +47,7 @@ extern void check_sql_fn_statements(List *queryTreeLists); extern bool check_sql_fn_retval(List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, + char prokind, bool insertDroppedCols, List **resultTargetList); diff --git a/src/test/regress/expected/create_procedure.out b/src/test/regress/expected/create_procedure.out index f2a677fa55..6ab09d7ec8 100644 --- a/src/test/regress/expected/create_procedure.out +++ b/src/test/regress/expected/create_procedure.out @@ -148,7 +148,19 @@ CALL ptest4a(a, b); -- error, not supported $$; ERROR: calling procedures with output arguments is not supported in SQL functions CONTEXT: SQL function "ptest4b" -DROP PROCEDURE ptest4a; +-- we used to get confused by a single output argument that is composite +CREATE PROCEDURE ptest4c(INOUT comp int8_tbl) +LANGUAGE SQL +AS $$ +SELECT ROW(1, 2); +$$; +CALL ptest4c(NULL); + comp +------- + (1,2) +(1 row) + +DROP PROCEDURE ptest4a, ptest4c; -- named and default parameters CREATE OR REPLACE PROCEDURE ptest5(a int, b text, c int default 100) LANGUAGE SQL diff --git a/src/test/regress/sql/create_procedure.sql b/src/test/regress/sql/create_procedure.sql index 35b872779e..012cdf3628 100644 --- a/src/test/regress/sql/create_procedure.sql +++ b/src/test/regress/sql/create_procedure.sql @@ -90,7 +90,16 @@ AS $$ CALL ptest4a(a, b); -- error, not supported $$; -DROP PROCEDURE ptest4a; +-- we used to get confused by a single output argument that is composite +CREATE PROCEDURE ptest4c(INOUT comp int8_tbl) +LANGUAGE SQL +AS $$ +SELECT ROW(1, 2); +$$; + +CALL ptest4c(NULL); + +DROP PROCEDURE ptest4a, ptest4c; -- named and default parameters