The database name of a Postgres resource was the bare positional argument of
pg_dump and the value of psql's --dbname. Both forms are interpreted: as a
positional argument a name opening with `-` is read as an option of pg_dump
(`--file=`, `--restrict-key=`), and in both forms a name holding `=` is
expanded as a libpq connection string that overrides the host, port and user
Windmill passed before it. libpq reads PGDATABASE as a plain name, neither
parsed nor expanded, so the name now goes there.
The change is in the shared helpers, so it covers every caller:
import_pg_database, export_pg_schema, datatable_clone::make_copy,
generate_initial_datatable_migration and pg_import_dump. pg_dump's invocation
is extracted into pg_dump_command() beside the existing psql_command() so the
argument vector can be asserted on directly.
Beside that:
- resolve_pg_source_checked_with_kind() now refuses a name opening with `-`
for every source and target it resolves, where validate_dbname() only ever
reached a target. The check is deliberately narrower than validate_dbname():
a source is any database a user already has, and `2024_archive`, `my.db` or
a non-ASCII name are all names Postgres accepts and resources carry today.
- export_pg_schema and import_pg_database now require the `code` capability,
the one the data table migration endpoints next door already ask for. Both
make the API server run pg_dump/psql as children of its own process against
a database the request names, so the role that may not run code should not
reach them; they stay open to every author, who can run pg_dump in a job
anyway. The frontend offers both only from the database manager.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>