Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .github/workflows/compatibility.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@ name: Postgres rustls compatibility
on:
push:
branches: [gitar-0.6.11]
pull_request:
branches: [gitar-0.6.11]
workflow_dispatch:
permissions:
contents: read
jobs:
postgres-tls:
runs-on: namespace-profile-gitar
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17
env:
POSTGRES_PASSWORD: fixture-password
ports: [5432:5432]
options: --health-cmd pg_isready --health-interval 5s --health-timeout 5s --health-retries 12
env:
TEST_PSQL: postgres://postgres:fixture-password@127.0.0.1:5432/postgres
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -19,6 +30,9 @@ jobs:
. -> target
tests/rustls -> target
- run: cargo check --locked --no-default-features --features postgresql,pooled,json,uuid,chrono,bigdecimal
- run: cargo fmt --check
- run: cargo test --locked --lib --no-default-features --features postgresql,pooled,json,uuid,chrono,bigdecimal startup_encoding_preserves_unicode_round_trips
- run: cargo test --locked --lib --no-default-features --features postgresql,pooled,json,uuid,chrono,bigdecimal test_custom_search_path
- run: cargo clippy --locked --manifest-path tests/rustls/Cargo.toml --all-targets
- run: python3 tests/rustls/run.py
- name: Verify Postgres dependency tree has no native TLS or OpenSSL
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
branches:
- main
pull_request:
branches: [main]
jobs:
clippy:
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions GITAR.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ System roots and PEM roots supplied with `sslcert` remain supported. `sslidentit

Consumers must repeat both Cargo patch tables from this manifest at their workspace root. Cargo ignores patches in dependencies. The registry patch makes `tokio-postgres-rustls` use the same driver source as Quaint.

PostgreSQL text encoding comes from tokio-postgres's UTF8 startup parameter. Connection initialization retains an explicit schema's search path and omits redundant `SET NAMES`, as that command pins sessions in RDS Proxy.

Run `python3 tests/rustls/run.py` with Docker and OpenSSL 3 to exercise certificate verification and SCRAM channel binding. The runner also covers client identities and TLS negotiation. Set `OPENSSL_BIN` if OpenSSL 3 is not the default executable.

Release tested source with immutable tags and pin consumers by commit. CLI binaries and checksums belong to the compatible `gitarcode/prisma-client-rust` release, which consumes this fork. Downloaded Prisma engine executables are separate artifacts and do not inherit this source change.
36 changes: 23 additions & 13 deletions src/connector/postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,19 +461,12 @@ impl PostgreSql {
}
}));

// SET NAMES sets the client text encoding. It needs to be explicitly set for automatic
// conversion to and from UTF-8 to happen server-side.
//
// Relevant docs: https://www.postgresql.org/docs/current/multibyte.html
let session_variables = format!(
r##"
{set_search_path}
SET NAMES 'UTF8';
"##,
set_search_path = SetSearchPath(url.query_params.schema.as_deref())
);

client.simple_query(session_variables.as_str()).await?;
// tokio-postgres requests UTF8 in the startup packet. Repeating it with
// SET NAMES pins every RDS Proxy session to one database connection.
let session_variables = SetSearchPath(url.query_params.schema.as_deref()).to_string();
if !session_variables.is_empty() {
client.simple_query(session_variables.as_str()).await?;
}

Ok(Self {
client: PostgresClient(client),
Expand Down Expand Up @@ -833,6 +826,23 @@ mod tests {
assert_eq!(Some("\"musti-test\""), row[0].as_str());
}

#[tokio::test]
async fn startup_encoding_preserves_unicode_round_trips() -> crate::Result<()> {
let client = Quaint::new(&CONN_STR).await?;
let encoding = client.query_raw("SHOW client_encoding", &[]).await?;
assert_eq!(
encoding.first().and_then(|row| row[0].as_str().map(str::to_owned)),
Some("UTF8".to_string())
);
let text = "caf\u{00e9} \u{65e5}\u{672c}\u{8a9e}";
let result = client.query_raw("SELECT $1::text", &[text.into()]).await?;
assert_eq!(
result.first().and_then(|row| row[0].as_str().map(str::to_owned)),
Some(text.to_string())
);
Ok(())
}

#[tokio::test]
async fn should_map_nonexisting_database_error() {
let mut url = Url::parse(&CONN_STR).unwrap();
Expand Down
Loading