aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/functioncmds.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2020-10-05 09:09:09 +0200
committerPeter Eisentraut <peter@eisentraut.org>2020-10-05 09:21:43 +0200
commit2453ea142233ae57af452019c3b9a443dad1cdd0 (patch)
treec38325aa838a785924c9add942c17021e3e8098b /src/backend/commands/functioncmds.c
parente899742081fa24bf52d4a32103ef854a3a85865d (diff)
downloadpostgresql-2453ea142233ae57af452019c3b9a443dad1cdd0.tar.gz
postgresql-2453ea142233ae57af452019c3b9a443dad1cdd0.zip
Support for OUT parameters in procedures
Unlike for functions, OUT parameters for procedures are part of the signature. Therefore, they have to be listed in pg_proc.proargtypes as well as mentioned in ALTER PROCEDURE and DROP PROCEDURE. Reviewed-by: Andrew Dunstan <andrew.dunstan@2ndquadrant.com> Reviewed-by: Pavel Stehule <pavel.stehule@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/2b8490fe-51af-e671-c504-47359dc453c5@2ndquadrant.com
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r--src/backend/commands/functioncmds.c57
1 files changed, 33 insertions, 24 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index e236581a8e0..c3ce480c8f5 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -194,8 +194,8 @@ interpret_function_parameter_list(ParseState *pstate,
Oid *requiredResultType)
{
int parameterCount = list_length(parameters);
- Oid *inTypes;
- int inCount = 0;
+ Oid *sigArgTypes;
+ int sigArgCount = 0;
Datum *allTypes;
Datum *paramModes;
Datum *paramNames;
@@ -209,7 +209,7 @@ interpret_function_parameter_list(ParseState *pstate,
*variadicArgType = InvalidOid; /* default result */
*requiredResultType = InvalidOid; /* default result */
- inTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
+ sigArgTypes = (Oid *) palloc(parameterCount * sizeof(Oid));
allTypes = (Datum *) palloc(parameterCount * sizeof(Datum));
paramModes = (Datum *) palloc(parameterCount * sizeof(Datum));
paramNames = (Datum *) palloc0(parameterCount * sizeof(Datum));
@@ -281,25 +281,21 @@ interpret_function_parameter_list(ParseState *pstate,
errmsg("functions cannot accept set arguments")));
}
- if (objtype == OBJECT_PROCEDURE)
- {
- if (fp->mode == FUNC_PARAM_OUT)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("procedures cannot have OUT arguments"),
- errhint("INOUT arguments are permitted.")));
- }
-
/* handle input parameters */
if (fp->mode != FUNC_PARAM_OUT && fp->mode != FUNC_PARAM_TABLE)
+ isinput = true;
+
+ /* handle signature parameters */
+ if (fp->mode == FUNC_PARAM_IN || fp->mode == FUNC_PARAM_INOUT ||
+ (objtype == OBJECT_PROCEDURE && fp->mode == FUNC_PARAM_OUT) ||
+ fp->mode == FUNC_PARAM_VARIADIC)
{
- /* other input parameters can't follow a VARIADIC parameter */
+ /* other signature parameters can't follow a VARIADIC parameter */
if (varCount > 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
- errmsg("VARIADIC parameter must be the last input parameter")));
- inTypes[inCount++] = toid;
- isinput = true;
+ errmsg("VARIADIC parameter must be the last signature parameter")));
+ sigArgTypes[sigArgCount++] = toid;
}
/* handle output parameters */
@@ -429,7 +425,7 @@ interpret_function_parameter_list(ParseState *pstate,
}
/* Now construct the proper outputs as needed */
- *parameterTypes = buildoidvector(inTypes, inCount);
+ *parameterTypes = buildoidvector(sigArgTypes, sigArgCount);
if (outCount > 0 || varCount > 0)
{
@@ -2067,6 +2063,9 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
int nargs;
int i;
AclResult aclresult;
+ Oid *argtypes;
+ char **argnames;
+ char *argmodes;
FmgrInfo flinfo;
CallContext *callcontext;
EState *estate;
@@ -2127,6 +2126,8 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
tp);
nargs = list_length(fexpr->args);
+ get_func_arg_info(tp, &argtypes, &argnames, &argmodes);
+
ReleaseSysCache(tp);
/* safety check; see ExecInitFunc() */
@@ -2156,16 +2157,24 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
i = 0;
foreach(lc, fexpr->args)
{
- ExprState *exprstate;
- Datum val;
- bool isnull;
+ if (argmodes && argmodes[i] == PROARGMODE_OUT)
+ {
+ fcinfo->args[i].value = 0;
+ fcinfo->args[i].isnull = true;
+ }
+ else
+ {
+ ExprState *exprstate;
+ Datum val;
+ bool isnull;
- exprstate = ExecPrepareExpr(lfirst(lc), estate);
+ exprstate = ExecPrepareExpr(lfirst(lc), estate);
- val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
+ val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
- fcinfo->args[i].value = val;
- fcinfo->args[i].isnull = isnull;
+ fcinfo->args[i].value = val;
+ fcinfo->args[i].isnull = isnull;
+ }
i++;
}