From 59a85323d9d5927a852939fa93f09d142c72c91a Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 9 Jul 2018 13:58:08 +0200 Subject: [PATCH] Add UtilityReturnsTuples() support for CALL This ensures that prepared statements for CALL can return tuples. --- src/backend/commands/functioncmds.c | 24 ++++++++++++++++++++++++ src/backend/tcop/utility.c | 9 +++++++++ src/include/commands/defrem.h | 1 + 3 files changed, 34 insertions(+) diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index acc08b1990..84daa19e06 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -51,6 +51,7 @@ #include "commands/proclang.h" #include "executor/execdesc.h" #include "executor/executor.h" +#include "funcapi.h" #include "miscadmin.h" #include "optimizer/clauses.h" #include "optimizer/var.h" @@ -2340,3 +2341,26 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver FreeExecutorState(estate); } + +/* + * Construct the tuple descriptor for a CALL statement return + */ +TupleDesc +CallStmtResultDesc(CallStmt *stmt) +{ + FuncExpr *fexpr; + HeapTuple tuple; + TupleDesc tupdesc; + + fexpr = stmt->funcexpr; + + tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fexpr->funcid)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for procedure %u", fexpr->funcid); + + tupdesc = build_function_result_tupdesc_t(tuple); + + ReleaseSysCache(tuple); + + return tupdesc; +} diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 4e1c21298e..b5804f64ad 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1744,6 +1744,12 @@ UtilityReturnsTuples(Node *parsetree) { switch (nodeTag(parsetree)) { + case T_CallStmt: + { + CallStmt *stmt = (CallStmt *) parsetree; + + return (stmt->funcexpr->funcresulttype == RECORDOID); + } case T_FetchStmt: { FetchStmt *stmt = (FetchStmt *) parsetree; @@ -1794,6 +1800,9 @@ UtilityTupleDescriptor(Node *parsetree) { switch (nodeTag(parsetree)) { + case T_CallStmt: + return CallStmtResultDesc((CallStmt *) parsetree); + case T_FetchStmt: { FetchStmt *stmt = (FetchStmt *) parsetree; diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index 8fc9e424cf..6b837236d4 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -64,6 +64,7 @@ extern void IsThereFunctionInNamespace(const char *proname, int pronargs, oidvector *proargtypes, Oid nspOid); extern void ExecuteDoStmt(DoStmt *stmt, bool atomic); extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest); +extern TupleDesc CallStmtResultDesc(CallStmt *stmt); extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok); extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok); extern void interpret_function_parameter_list(ParseState *pstate,