mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
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
This commit is contained in:
@ -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++;
|
||||
}
|
||||
|
Reference in New Issue
Block a user