Hi
The processing of named parameters inside CALL statement is not correct.
It is my code :-/. I am sorry
Attached patch fix it.
This still doesn't fix INOUT variables with default value - so is not fully
correct, but in this moment, it can show, where is a core of this issue.
Regards
Pavel
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 45526383f2..781963e32c 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -2171,7 +2171,6 @@ exec_stmt_call(PLpgSQL_execstate *estate, PLpgSQL_stmt_call *stmt)
Node *node;
ListCell *lc;
FuncExpr *funcexpr;
- int i;
HeapTuple tuple;
Oid *argtypes;
char **argnames;
@@ -2210,45 +2209,60 @@ exec_stmt_call(PLpgSQL_execstate *estate, PLpgSQL_stmt_call *stmt)
row->varnos = palloc(sizeof(int) * FUNC_MAX_ARGS);
nfields = 0;
- i = 0;
- foreach(lc, funcexpr->args)
+
+ /*
+ * The argmodes can be in different order than funcexpr->args due
+ * named args. When we should to check INOUT parameters and prepare
+ * target variable, we should to reorder a arguments first.
+ */
+ if (argmodes)
{
- Node *n = lfirst(lc);
+ Node **args;
+ int i = 0;
+ int nargs = list_length(funcexpr->args);
+
+ args = palloc0(sizeof(Node *) * FUNC_MAX_ARGS);
- if (argmodes && argmodes[i] == PROARGMODE_INOUT)
+ foreach(lc, funcexpr->args)
{
- if (IsA(n, Param))
+ Node *n = lfirst(lc);
+
+ if (IsA(n, NamedArgExpr))
{
- Param *param = castNode(Param, n);
+ NamedArgExpr *nexpr = castNode(NamedArgExpr, n);
+
+ Assert(nexpr->argnumber < nargs);
- /* paramid is offset by 1 (see make_datum_param()) */
- row->varnos[nfields++] = param->paramid - 1;
+ args[nexpr->argnumber] = (Node *) nexpr->arg;
}
- else if (IsA(n, NamedArgExpr))
+ else
+ args[i++] = n;
+ }
+
+ for (i = 0; i < nargs; i++)
+ {
+ Node *n = args[i];
+
+ Assert(n != NULL);
+
+ if (argmodes[i] == PROARGMODE_INOUT)
{
- NamedArgExpr *nexpr = castNode(NamedArgExpr, n);
- Param *param;
+ if (IsA(n, Param))
+ {
+ Param *param = castNode(Param, n);
+
+ /* paramid is offset by 1 (see make_datum_param()) */
- if (!IsA(nexpr->arg, Param))
+ row->varnos[nfields++] = param->paramid - 1;
+ }
+ else
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("argument %d is an output argument but is not writable", i + 1)));
-
- param = castNode(Param, nexpr->arg);
-
- /*
- * Named arguments must be after positional arguments,
- * so we can increase nfields.
- */
- row->varnos[nexpr->argnumber] = param->paramid - 1;
- nfields++;
}
- else
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("argument %d is an output argument but is not writable", i + 1)));
}
- i++;
+
+ pfree(args);
}
row->nfields = nfields;