Skip to content

fix(postgresql): include OUT params when matching CALL signatures#4427

Open
SAY-5 wants to merge 1 commit intosqlc-dev:mainfrom
SAY-5:fix-call-out-params-4216
Open

fix(postgresql): include OUT params when matching CALL signatures#4427
SAY-5 wants to merge 1 commit intosqlc-dev:mainfrom
SAY-5:fix-call-out-params-4216

Conversation

@SAY-5
Copy link
Copy Markdown
Contributor

@SAY-5 SAY-5 commented May 5, 2026

Fixes #4216.

PostgreSQL CALL requires positional placeholders for OUT parameters, but Catalog.ResolveFuncCall matched the supplied arg count against Function.InArgs(), which strips OUT and TABLE modes. A procedure declared as create_todo(IN p_task text, OUT p_id int) therefore had effective arity 1, and CALL create_todo($1, NULL) (arity 2) was rejected with function create_todo(unknown, unknown) does not exist.

This patch:

  • Adds Function.CallArgs(), which is identical to InArgs() but keeps OUT parameters (still excludes TABLE).
  • Adds Catalog.ResolveCallStmt, sharing the existing matcher via a private resolveFuncCall(call, isCallStmt bool) helper.
  • Updates the funcCallVisitor in internal/sql/validate/func_call.go to intercept *ast.CallStmt, dispatch to ResolveCallStmt, and skip the inner FuncCall walk so it isn't re-validated against the stricter IN-only path.

Plain SELECT function calls continue to use InArgs() and are unaffected.

Reproduction

A new endtoend fixture under internal/endtoend/testdata/stored_procedures_pg_out_args/postgresql/pgx/v5 mirrors the schema and queries in the issue (positional null, typed NULL::int, and sqlc.arg for the OUT slot). It fails on main with the issue's exact error and passes after the fix.

Tests

  • go test ./internal/compiler/... ./internal/sql/... — pass
  • go test ./internal/endtoend/... — pass (including ddl_create_procedure and sql_syntax_calling_funcs regression coverage)
  • go test -race ./internal/sql/... ./internal/compiler/... — pass

Resolves sqlc-dev#4216. PostgreSQL CALL requires positional
placeholders for OUT parameters, but ResolveFuncCall used InArgs() which
strips them, so the supplied arg count never matched the procedure's IN
arity and analysis failed with "function ... does not exist".

Add Function.CallArgs() and route ast.CallStmt through a new
ResolveCallStmt path that matches against IN+OUT arguments.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PostgreSQL: CALL fails analysis for procedures with OUT parameters (function does not exist)

1 participant