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;