Skip to content

feat: support standard postgres env vars for db connection#674

Merged
psteinroe merged 15 commits intomainfrom
feat/db-connection-string
Feb 10, 2026
Merged

feat: support standard postgres env vars for db connection#674
psteinroe merged 15 commits intomainfrom
feat/db-connection-string

Conversation

@psteinroe
Copy link
Copy Markdown
Collaborator

@psteinroe psteinroe commented Feb 7, 2026

Support DATABASE_URL, PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE env vars for configuring the database connection with highest priority.

we use bpaf(env()) for the cli, and support loading the db config from_env for the lsp.

These env var names follow the standard libpq environment variables (PG*) and the widely adopted DATABASE_URL convention used by tools like sqlx, diesel, prisma, and dotenv.

Example

DATABASE_URL=postgres://user:pass@localhost:5432/mydb postgres-language-server check file.sql
# or individual vars
PGHOST=localhost PGPORT=5432 PGUSER=user PGPASSWORD=pass PGDATABASE=mydb postgres-language-server check file.sql

Precedence (highest to lowest)

  1. Environment variables
  2. CLI args / LSP client settings
  3. Config file
  4. Defaults

Closes #302

@psteinroe psteinroe force-pushed the feat/db-connection-string branch 2 times, most recently from ede9f8d to 3f539f1 Compare February 7, 2026 16:49
@psteinroe psteinroe changed the title feat: support standard Postgres env vars for db connection feat: support standard postgres env vars for db connection Feb 7, 2026
@psteinroe psteinroe force-pushed the feat/db-connection-string branch 2 times, most recently from 404a683 to 704f5e5 Compare February 8, 2026 01:40

/// The password to connect to the database.
#[partial(bpaf(long("password")))]
#[partial(bpaf(env("PGPASSWORD"), long("password")))]
Copy link
Copy Markdown

@pacak pacak Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might have an unexpected side effect of leaking password in the --help message. If that's not acceptable - I'd implement a separate function for obtaining the password and call it here with bpaf(external(get_password)).

This function would have a parser for password and a parser for env, hidden. Something like this:

fn get_password() -> impl Parser<String> {
    let pass = long("password")
           .help("The password to connect to the database")
           .argument("PASSWORD");
    let epass = env("PGPASSOWRD").argument("PASSWORD").hide();
    construct!([pass, epass])
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for noting this! super helpful, did not know that it leaks in --help.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I'm wondering. Are there any scenarios where you want to see the value of the variable in the --help message? I could make it to tell the variable name and indicate if it is set or not. Or even just the name...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mhh I think with just showing that it is set right now will cover the same use case that showing the actual value does today. Users could just echo it to reveal the value.

@psteinroe psteinroe force-pushed the feat/db-connection-string branch from 99cd97e to 2b49a04 Compare February 9, 2026 08:47
Comment thread crates/pgls_env/src/lib.rs Outdated
&self.pghost,
&self.pgport,
&self.pguser,
&self.pgpassword,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if we want to log the password somewhere?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could alternatively wrap it in a secret-string

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i opted for the easy way now because using any wrapper type would mean adding biomes merge partial to our repo to support the type... but it might make sense to bring all the biome deps in-house anyways. will note it as a follow up.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create a note to bring biome_deserialise in-house and replace all other biome_ dependencies with ocx - their lib apis are much better and well maintained.

{
let env_config = PartialConfiguration {
db: Some(env_db),
..Default::default()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm a little bit confused about the ..default::default().. shouldnt we marge the configuration here? or are the defaults all "None"?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i double checked and it does not overwrite

username: pguser,
password: pgpassword,
database: pgdatabase,
..Default::default()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

..Default::default() returns all None?
just wondering if we need to be careful about not overwriting everything with default values?

Support DATABASE_URL, PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE
environment variables for configuring the database connection. Env vars
take highest priority, overriding CLI args, LSP settings, and config file
values.

Closes #302
Support DATABASE_URL, PGHOST, PGPORT, PGUSER, PGPASSWORD, PGDATABASE
environment variables for configuring the database connection. Env vars
take highest priority, overriding CLI args, LSP settings, and config file
values.

Closes #302
Env config is computed once at ServerFactory creation and threaded
through to Session, which merges it as the highest-priority layer
during config loading. Tests use ServerFactory::default() which
provides None, avoiding DATABASE_URL interference from sqlx::test.
bpaf's env() renders the current env var value in --help, e.g.
[env:PGPASSWORD = "secret"]. Remove env() from sensitive fields
(password, connection_string) and use from_env() merge in the CLI
path instead, matching the LSP approach.
DATABASE_URL and PGPASSWORD now display "set" instead of their
actual values in the environment variable overview.
Custom Debug impls for DatabaseConfiguration and DatabaseSettings
mask password and connection_string fields to prevent accidental
credential exposure in logs or debug output.
Merge order: config file → env vars → CLI args. This ensures
explicit --connection-string flags take precedence over DATABASE_URL.
@psteinroe psteinroe force-pushed the feat/db-connection-string branch from 44b1bb1 to 42c1b77 Compare February 10, 2026 08:19
@psteinroe psteinroe merged commit d89118d into main Feb 10, 2026
9 checks passed
@psteinroe psteinroe deleted the feat/db-connection-string branch February 10, 2026 08:54
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.

Add support for running a command to get the database connection string in postgrestools.jsonc

3 participants