mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-02 07:21:08 +00:00
0.8.4 release (#3819)
* chore: prepare 0.8.4 release * fix(postgres): send `limit: 0` for all `Execute` messages fixes #3673 * fix: let `CertificateInput::from` infer any PEM-encoded document https://github.com/launchbadge/sqlx/pull/3809#issuecomment-2800293813 * doc: improve documentation of `PgConnectOptions` fixes #3740 * chore: update CHANGELOG from PR
This commit is contained in:
parent
154878547e
commit
f9084035d7
152
CHANGELOG.md
152
CHANGELOG.md
@ -5,6 +5,134 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 0.8.4 - 2025-04-13
|
||||
|
||||
50 pull requests were merged this release cycle.
|
||||
|
||||
As of this release, development of `0.9.0` has begun on `main`.
|
||||
Barring urgent hotfixes, this is expected to be the last release of `0.8.x`.
|
||||
|
||||
### Added
|
||||
* [[#3603]]: Added missing special casing for encoding embedded arrays of custom types [[@nico-incubiq]]
|
||||
* [[#3625]]: feat(sqlite): add preupdate hook [[@aschey]]
|
||||
* [[#3655]]: docs: add example for postgres enums with type TEXT [[@tisonkun]]
|
||||
* [[#3677]]: Add json(nullable) macro attribute [[@seanaye]]
|
||||
* [[#3687]]: Derive clone and debug for postgresql arguments [[@remysaissy]]
|
||||
* [[#3690]]: feat: add postres geometry line segment [[@jayy-lmao]]
|
||||
* [[#3707]]: feat(Sqlite): add LockedSqliteHandle::last_error [[@joeydewaal]]
|
||||
* [[#3710]]: feat: add ipnet support [[@BeauGieskens]]
|
||||
* [[#3711]]: feat(postgres): add geometry box [[@jayy-lmao]]
|
||||
* [[#3714]]: chore: expose bstr feature [[@joeydewaal]]
|
||||
* [[#3716]]: feat(postgres): add geometry path [[@jayy-lmao]]
|
||||
* [[#3724]]: feat(sqlx-cli): Add flag to disable automatic loading of .env files [[@benwilber]]
|
||||
* [[#3734]]: QueryBuilder: add debug_assert when `push_values` is passed an empty set of tuples [[@chanmaoganda]]
|
||||
* [[#3745]]: feat: sqlx sqlite expose de/serialize [[@mattrighetti]]
|
||||
* [[#3765]]: Merge of #3427 (by @mpyw) and #3614 (by @bonsairobo) [[@abonander]]
|
||||
* [[#3427]] Expose `transaction_depth` through `get_transaction_depth()` method [[@mpyw]]
|
||||
* Changed to `Connection::is_in_transaction` in [[#3765]]
|
||||
* [[#3614]] Add `begin_with` methods to support database-specific transaction options [[@bonsairobo]]
|
||||
* [[#3769]]: feat(postgres): add geometry polygon [[@jayy-lmao]]
|
||||
* [[#3773]]: feat(postgres): add geometry circle [[@jayy-lmao]]
|
||||
|
||||
### Changed
|
||||
* [[#3665]]: build(deps): bump semver compatible dependencies [[@paolobarbolini]]
|
||||
* [[#3669]]: refactor(cli): replace promptly with dialoguer [[@paolobarbolini]]
|
||||
* [[#3672]]: add `#[track_caller]` to `Row::get()` [[@karambarakat]]
|
||||
* [[#3708]]: chore(MySql): Remove unnecessary box [[@joeydewaal]]
|
||||
* [[#3715]]: chore: add pg_copy regression tests [[@joeydewaal]]
|
||||
* [[#3721]]: Replace some `futures-core` / `futures-util` APIs with `std` variants [[@paolobarbolini]]
|
||||
* [[#3725]]: chore: replace rustls-pemfile with rustls-pki-types [[@tottoto]]
|
||||
* [[#3754]]: chore(cli): remove unused async-trait crate from dependencies [[@tottoto]]
|
||||
* [[#3762]]: docs(pool): recommend actix-web ThinData over Data to avoid two Arcs [[@jonasmalacofilho]]
|
||||
|
||||
### Fixed
|
||||
* [[#3289]]: Always set `SQLITE_OPEN_URI` on in-memory sqlite [[@LecrisUT]]
|
||||
* [[#3334]]: Fix: nextest cleanup race condition [[@bonega]]
|
||||
* [[#3666]]: fix(cli): running tests on 32bit platforms [[@paolobarbolini]]
|
||||
* [[#3686]]: fix: handle nullable values by printing NULL instead of panicking [[@joeydewaal]]
|
||||
* [[#3700]]: fix(Sqlite): stop sending rows after first error [[@joeydewaal]]
|
||||
* [[#3701]]: fix(postgres) use signed int for length prefix in `PgCopyIn` [[@joeydewaal]]
|
||||
* [[#3703]]: fix(Postgres) chunk pg_copy data [[@joeydewaal]]
|
||||
* [[#3712]]: FromRow: Fix documentation order [[@Turbo87]]
|
||||
* [[#3720]]: Fix readme: uuid feature is gating for all repos [[@jthacker]]
|
||||
* [[#3728]]: postgres: Fix tracing span when dropping PgListener [[@chitoku-k]]
|
||||
* [[#3741]]: Fix example calculation in docs [[@dns2utf8]]
|
||||
* [[#3749]]: docs: add some missing backticks [[@soulwa]]
|
||||
* [[#3753]]: Avoid privilege requirements by using an advisory lock in test setup (postgres). [[@kildrens]]
|
||||
* [[#3755]]: Fix FromRow docs for tuples [[@xvapx]]
|
||||
* [[#3768]]: chore(Sqlite): remove ci.db from repo [[@joeydewaal]]
|
||||
* [[#3771]]: fix(ci): breakage from Rustup 1.28 [[@abonander]]
|
||||
* [[#3786]]: Fix a copy-paste error on get_username docs [[@sulami]]
|
||||
* [[#3801]]: Fix: Enable Json type when db feature isn't enabled [[@thriller08]]
|
||||
* [[#3809]]: fix: PgConnectOptions docs [[@mbj]]
|
||||
* [[#3811]]: Fix error message typo in PgPoint::from_str [[@TeCHiScy]]
|
||||
* [[#3812]]: mysql: Fix panic on invalid text row length field [[@0xdeafbeef]]
|
||||
* [[#3815]]: fix(macros): cache macro metadata based on `CARGO_MANIFEST_DIR` [[@joeydewaal]]
|
||||
* Fixes in release PR [[#3819]] [[@abonander]]:
|
||||
* fix(postgres): send `limit: 0` for all `Execute` messages
|
||||
* Addresses [[#3673]]: Parallel workers not used on Postgres
|
||||
* fix: let `CertificateInput::from` infer any PEM-encoded document
|
||||
* Fixes `PGSSLKEY` not being parsed correctly when containing a PEM-encoded private key.
|
||||
* doc: improve documentation of `PgConnectOptions`
|
||||
* `PGHOSTADDR` now can be used to override `PGHOST`.
|
||||
* Addresses [[#3740]]: Document the URL syntax for Unix-domain sockets when connecting to postgres
|
||||
|
||||
[#3819]: https://github.com/launchbadge/sqlx/pull/3819
|
||||
|
||||
[#3673]: https://github.com/launchbadge/sqlx/issues/3673
|
||||
[#3740]: https://github.com/launchbadge/sqlx/issues/3740
|
||||
|
||||
[#3289]: https://github.com/launchbadge/sqlx/pull/3289
|
||||
[#3334]: https://github.com/launchbadge/sqlx/pull/3334
|
||||
[#3427]: https://github.com/launchbadge/sqlx/pull/3427
|
||||
[#3603]: https://github.com/launchbadge/sqlx/pull/3603
|
||||
[#3614]: https://github.com/launchbadge/sqlx/pull/3614
|
||||
[#3625]: https://github.com/launchbadge/sqlx/pull/3625
|
||||
[#3655]: https://github.com/launchbadge/sqlx/pull/3655
|
||||
[#3665]: https://github.com/launchbadge/sqlx/pull/3665
|
||||
[#3666]: https://github.com/launchbadge/sqlx/pull/3666
|
||||
[#3669]: https://github.com/launchbadge/sqlx/pull/3669
|
||||
[#3672]: https://github.com/launchbadge/sqlx/pull/3672
|
||||
[#3677]: https://github.com/launchbadge/sqlx/pull/3677
|
||||
[#3686]: https://github.com/launchbadge/sqlx/pull/3686
|
||||
[#3687]: https://github.com/launchbadge/sqlx/pull/3687
|
||||
[#3690]: https://github.com/launchbadge/sqlx/pull/3690
|
||||
[#3700]: https://github.com/launchbadge/sqlx/pull/3700
|
||||
[#3701]: https://github.com/launchbadge/sqlx/pull/3701
|
||||
[#3703]: https://github.com/launchbadge/sqlx/pull/3703
|
||||
[#3707]: https://github.com/launchbadge/sqlx/pull/3707
|
||||
[#3708]: https://github.com/launchbadge/sqlx/pull/3708
|
||||
[#3710]: https://github.com/launchbadge/sqlx/pull/3710
|
||||
[#3711]: https://github.com/launchbadge/sqlx/pull/3711
|
||||
[#3712]: https://github.com/launchbadge/sqlx/pull/3712
|
||||
[#3714]: https://github.com/launchbadge/sqlx/pull/3714
|
||||
[#3715]: https://github.com/launchbadge/sqlx/pull/3715
|
||||
[#3716]: https://github.com/launchbadge/sqlx/pull/3716
|
||||
[#3720]: https://github.com/launchbadge/sqlx/pull/3720
|
||||
[#3721]: https://github.com/launchbadge/sqlx/pull/3721
|
||||
[#3724]: https://github.com/launchbadge/sqlx/pull/3724
|
||||
[#3725]: https://github.com/launchbadge/sqlx/pull/3725
|
||||
[#3728]: https://github.com/launchbadge/sqlx/pull/3728
|
||||
[#3734]: https://github.com/launchbadge/sqlx/pull/3734
|
||||
[#3741]: https://github.com/launchbadge/sqlx/pull/3741
|
||||
[#3745]: https://github.com/launchbadge/sqlx/pull/3745
|
||||
[#3749]: https://github.com/launchbadge/sqlx/pull/3749
|
||||
[#3753]: https://github.com/launchbadge/sqlx/pull/3753
|
||||
[#3754]: https://github.com/launchbadge/sqlx/pull/3754
|
||||
[#3755]: https://github.com/launchbadge/sqlx/pull/3755
|
||||
[#3762]: https://github.com/launchbadge/sqlx/pull/3762
|
||||
[#3765]: https://github.com/launchbadge/sqlx/pull/3765
|
||||
[#3768]: https://github.com/launchbadge/sqlx/pull/3768
|
||||
[#3769]: https://github.com/launchbadge/sqlx/pull/3769
|
||||
[#3771]: https://github.com/launchbadge/sqlx/pull/3771
|
||||
[#3773]: https://github.com/launchbadge/sqlx/pull/3773
|
||||
[#3786]: https://github.com/launchbadge/sqlx/pull/3786
|
||||
[#3801]: https://github.com/launchbadge/sqlx/pull/3801
|
||||
[#3809]: https://github.com/launchbadge/sqlx/pull/3809
|
||||
[#3811]: https://github.com/launchbadge/sqlx/pull/3811
|
||||
[#3812]: https://github.com/launchbadge/sqlx/pull/3812
|
||||
[#3815]: https://github.com/launchbadge/sqlx/pull/3815
|
||||
|
||||
## 0.8.3 - 2025-01-03
|
||||
|
||||
41 pull requests were merged this release cycle.
|
||||
@ -2700,3 +2828,27 @@ Fix docs.rs build by enabling a runtime feature in the docs.rs metadata in `Carg
|
||||
[@hsivonen]: https://github.com/hsivonen
|
||||
[@andreweggleston]: https://github.com/andreweggleston
|
||||
[@Suficio]: https://github.com/Suficio
|
||||
[@bonega]: https://github.com/bonega
|
||||
[@nico-incubiq]: https://github.com/nico-incubiq
|
||||
[@tisonkun]: https://github.com/tisonkun
|
||||
[@karambarakat]: https://github.com/karambarakat
|
||||
[@seanaye]: https://github.com/seanaye
|
||||
[@remysaissy]: https://github.com/remysaissy
|
||||
[@BeauGieskens]: https://github.com/BeauGieskens
|
||||
[@Turbo87]: https://github.com/Turbo87
|
||||
[@jthacker]: https://github.com/jthacker
|
||||
[@benwilber]: https://github.com/benwilber
|
||||
[@chitoku-k]: https://github.com/chitoku-k
|
||||
[@chanmaoganda]: https://github.com/chanmaoganda
|
||||
[@dns2utf8]: https://github.com/dns2utf8
|
||||
[@mattrighetti]: https://github.com/mattrighetti
|
||||
[@soulwa]: https://github.com/soulwa
|
||||
[@kildrens]: https://github.com/kildrens
|
||||
[@xvapx]: https://github.com/xvapx
|
||||
[@jonasmalacofilho]: https://github.com/jonasmalacofilho
|
||||
[@sulami]: https://github.com/sulami
|
||||
[@thriller08]: https://github.com/thriller08
|
||||
[@mbj]: https://github.com/mbj
|
||||
[@TeCHiScy]: https://github.com/TeCHiScy
|
||||
[@mpyw]: https://github.com/mpyw
|
||||
[@bonsairobo]: https://github.com/bonsairobo
|
16
Cargo.lock
generated
16
Cargo.lock
generated
@ -3374,7 +3374,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-std",
|
||||
@ -3404,7 +3404,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-cli"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
@ -3428,7 +3428,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-core"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"async-io 1.13.0",
|
||||
"async-std",
|
||||
@ -3604,7 +3604,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -3615,7 +3615,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros-core"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"dotenvy",
|
||||
@ -3640,7 +3640,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-mysql"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.22.1",
|
||||
@ -3686,7 +3686,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-postgres"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.22.1",
|
||||
@ -3732,7 +3732,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-sqlite"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"chrono",
|
||||
|
16
Cargo.toml
16
Cargo.toml
@ -23,7 +23,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
license = "MIT OR Apache-2.0"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/launchbadge/sqlx"
|
||||
@ -129,17 +129,17 @@ bstr = ["sqlx-core/bstr"]
|
||||
|
||||
[workspace.dependencies]
|
||||
# Core Crates
|
||||
sqlx-core = { version = "=0.8.3", path = "sqlx-core" }
|
||||
sqlx-macros-core = { version = "=0.8.3", path = "sqlx-macros-core" }
|
||||
sqlx-macros = { version = "=0.8.3", path = "sqlx-macros" }
|
||||
sqlx-core = { version = "=0.8.4", path = "sqlx-core" }
|
||||
sqlx-macros-core = { version = "=0.8.4", path = "sqlx-macros-core" }
|
||||
sqlx-macros = { version = "=0.8.4", path = "sqlx-macros" }
|
||||
|
||||
# Driver crates
|
||||
sqlx-mysql = { version = "=0.8.3", path = "sqlx-mysql" }
|
||||
sqlx-postgres = { version = "=0.8.3", path = "sqlx-postgres" }
|
||||
sqlx-sqlite = { version = "=0.8.3", path = "sqlx-sqlite" }
|
||||
sqlx-mysql = { version = "=0.8.4", path = "sqlx-mysql" }
|
||||
sqlx-postgres = { version = "=0.8.4", path = "sqlx-postgres" }
|
||||
sqlx-sqlite = { version = "=0.8.4", path = "sqlx-sqlite" }
|
||||
|
||||
# Facade crate (for reference from sqlx-cli)
|
||||
sqlx = { version = "=0.8.3", path = ".", default-features = false }
|
||||
sqlx = { version = "=0.8.4", path = ".", default-features = false }
|
||||
|
||||
# Common type integrations shared by multiple driver crates.
|
||||
# These are optional unless enabled in a workspace crate.
|
||||
|
@ -25,11 +25,12 @@ pub enum CertificateInput {
|
||||
|
||||
impl From<String> for CertificateInput {
|
||||
fn from(value: String) -> Self {
|
||||
// Leading and trailing whitespace/newlines
|
||||
let trimmed = value.trim();
|
||||
// Some heuristics according to https://tools.ietf.org/html/rfc7468
|
||||
if trimmed.starts_with("-----BEGIN CERTIFICATE-----")
|
||||
&& trimmed.contains("-----END CERTIFICATE-----")
|
||||
{
|
||||
|
||||
// Heuristic for PEM encoded inputs:
|
||||
// https://tools.ietf.org/html/rfc7468
|
||||
if trimmed.starts_with("-----BEGIN") && trimmed.ends_with("-----") {
|
||||
CertificateInput::Inline(value.as_bytes().to_vec())
|
||||
} else {
|
||||
CertificateInput::File(PathBuf::from(value))
|
||||
|
@ -97,7 +97,7 @@ impl AnyConnectionBackend for PgConnection {
|
||||
};
|
||||
|
||||
Box::pin(
|
||||
self.run(query, arguments, 0, persistent, None)
|
||||
self.run(query, arguments, persistent, None)
|
||||
.try_flatten_stream()
|
||||
.map(
|
||||
move |res: sqlx_core::Result<Either<PgQueryResult, PgRow>>| match res? {
|
||||
@ -123,7 +123,7 @@ impl AnyConnectionBackend for PgConnection {
|
||||
|
||||
Box::pin(async move {
|
||||
let arguments = arguments?;
|
||||
let mut stream = pin!(self.run(query, arguments, 1, persistent, None).await?);
|
||||
let mut stream = pin!(self.run(query, arguments, persistent, None).await?);
|
||||
|
||||
if let Some(Either::Right(row)) = stream.try_next().await? {
|
||||
return Ok(Some(AnyRow::try_from(&row)?));
|
||||
|
@ -194,7 +194,6 @@ impl PgConnection {
|
||||
&'c mut self,
|
||||
query: &'q str,
|
||||
arguments: Option<PgArguments>,
|
||||
limit: u8,
|
||||
persistent: bool,
|
||||
metadata_opt: Option<Arc<PgStatementMetadata>>,
|
||||
) -> Result<impl Stream<Item = Result<Either<PgQueryResult, PgRow>, Error>> + 'e, Error> {
|
||||
@ -247,7 +246,9 @@ impl PgConnection {
|
||||
// the protocol-level limit acts nearly identically to the `LIMIT` in SQL
|
||||
self.inner.stream.write_msg(message::Execute {
|
||||
portal: PortalId::UNNAMED,
|
||||
limit: limit.into(),
|
||||
// Non-zero limits cause query plan pessimization by disabling parallel workers:
|
||||
// https://github.com/launchbadge/sqlx/issues/3673
|
||||
limit: 0,
|
||||
})?;
|
||||
// From https://www.postgresql.org/docs/current/protocol-flow.html:
|
||||
//
|
||||
@ -393,7 +394,7 @@ impl<'c> Executor<'c> for &'c mut PgConnection {
|
||||
|
||||
Box::pin(try_stream! {
|
||||
let arguments = arguments?;
|
||||
let mut s = pin!(self.run(sql, arguments, 0, persistent, metadata).await?);
|
||||
let mut s = pin!(self.run(sql, arguments, persistent, metadata).await?);
|
||||
|
||||
while let Some(v) = s.try_next().await? {
|
||||
r#yield!(v);
|
||||
@ -419,7 +420,7 @@ impl<'c> Executor<'c> for &'c mut PgConnection {
|
||||
|
||||
Box::pin(async move {
|
||||
let arguments = arguments?;
|
||||
let mut s = pin!(self.run(sql, arguments, 1, persistent, metadata).await?);
|
||||
let mut s = pin!(self.run(sql, arguments, persistent, metadata).await?);
|
||||
|
||||
// With deferred constraints we need to check all responses as we
|
||||
// could get a OK response (with uncommitted data), only to get an
|
||||
|
@ -31,6 +31,8 @@ mod stream;
|
||||
mod tls;
|
||||
|
||||
/// A connection to a PostgreSQL database.
|
||||
///
|
||||
/// See [`PgConnectOptions`] for connection URL reference.
|
||||
pub struct PgConnection {
|
||||
pub(crate) inner: Box<PgConnectionInner>,
|
||||
}
|
||||
|
185
sqlx-postgres/src/options/doc.md
Normal file
185
sqlx-postgres/src/options/doc.md
Normal file
@ -0,0 +1,185 @@
|
||||
Options and flags which can be used to configure a PostgreSQL connection.
|
||||
|
||||
A value of `PgConnectOptions` can be parsed from a connection URL,
|
||||
as described by [libpq][libpq-connstring].
|
||||
|
||||
The general form for a connection URL is:
|
||||
|
||||
```text
|
||||
postgresql://[user[:password]@][host][:port][/dbname][?param1=value1&...]
|
||||
```
|
||||
|
||||
The URL scheme designator can be either `postgresql://` or `postgres://`.
|
||||
Each of the URL parts is optional. For defaults, see the next section.
|
||||
|
||||
This type also implements [`FromStr`][std::str::FromStr] so you can parse it from a string
|
||||
containing a connection URL and then further adjust options if necessary (see example below).
|
||||
|
||||
Note that characters not allowed in URLs must be [percent-encoded].
|
||||
|
||||
# Parameters
|
||||
|
||||
This API accepts many of the same parameters as [libpq][libpq-params];
|
||||
if a parameter is not passed in via URL, it is populated by reading
|
||||
[environment variables][libpq-envars] or choosing customary defaults.
|
||||
|
||||
| Parameter | Environment Variable | Default / Remarks |
|
||||
|--------------------|----------------------|-------------------------------------------------------------|
|
||||
| `user` | `PGUSER` | The `whoami` of the currently running process. |
|
||||
| `password` | `PGPASSWORD` | Read from [`passfile`], if it exists. |
|
||||
| [`passfile`] | `PGPASSFILE` | `~/.pgpass` or `%APPDATA%\postgresql\pgpass.conf` (Windows) |
|
||||
| `host` | `PGHOST` | See [Note: Default Host](#note-default-host). |
|
||||
| `hostaddr` | `PGHOSTADDR` | See [Note: Default Host](#note-default-host). |
|
||||
| `port` | `PGPORT` | `5432` |
|
||||
| `dbname` | `PGDATABASE` | Unset; defaults to the username server-side. |
|
||||
| `sslmode` | `PGSSLMODE` | `prefer`. See [`PgSslMode`] for details. |
|
||||
| `sslrootcert` | `PGSSLROOTCERT` | Unset. See [Note: SSL](#note-ssl). |
|
||||
| `sslcert` | `PGSSLCERT` | Unset. See [Note: SSL](#note-ssl). |
|
||||
| `sslkey` | `PGSSLKEY` | Unset. See [Note: SSL](#note-ssl). |
|
||||
| `options` | `PGOPTIONS` | Unset. |
|
||||
| `application_name` | `PGAPPNAME` | Unset. |
|
||||
|
||||
[`passfile`] handling may be bypassed using [`PgConnectOptions::new_without_pgpass()`].
|
||||
|
||||
## SQLx-Specific
|
||||
SQLx also parses some bespoke parameters. These are _not_ configurable by environment variable.
|
||||
Instead, the name is linked to the method to set the value.
|
||||
|
||||
| Parameter | Default |
|
||||
|--------------------------------------------------------------|-------------------------------|
|
||||
| [`statement-cache-capacity`][Self::statement_cache_capacity] | `100` |
|
||||
|
||||
# Example URLs
|
||||
```text
|
||||
postgresql://
|
||||
postgresql://:5433
|
||||
postgresql://localhost
|
||||
postgresql://localhost:5433
|
||||
postgresql://localhost/mydb
|
||||
postgresql://user@localhost
|
||||
postgresql://user:secret@localhost
|
||||
postgresql://user:correct%20horse%20battery%20staple@localhost
|
||||
postgresql://localhost?dbname=mydb&user=postgres&password=postgres
|
||||
```
|
||||
|
||||
See also [Note: Unix Domain Sockets](#note-unix-domain-sockets) below.
|
||||
|
||||
# Note: Default Host
|
||||
If the connection URL does not contain a hostname and `PGHOST` is not set,
|
||||
this constructor looks for an open Unix domain socket in one of a few standard locations
|
||||
(configured when Postgres is built):
|
||||
|
||||
* `/var/run/postgresql/.s.PGSQL.{port}` (Debian)
|
||||
* `/private/tmp/.s.PGSQL.{port}` (macOS when installed through Homebrew)
|
||||
* `/tmp/.s.PGSQL.{port}` (default otherwise)
|
||||
|
||||
This depends on the value of `port` being correct.
|
||||
If Postgres is using a port other than the default (`5432`), `port` must be set.
|
||||
|
||||
If no Unix domain socket is found, `localhost` is assumed.
|
||||
|
||||
Note: this description is updated on a best-effort basis.
|
||||
See `default_host()` in the same source file as this method for the current behavior.
|
||||
|
||||
# Note: SSL
|
||||
## Root Certs
|
||||
If `sslrootcert` is not set, the default root certificates used depends on Cargo features:
|
||||
|
||||
* If `tls-native-tls` is enabled, the system root certificates are used.
|
||||
* If `tls-rustls-native-roots` is enabled, the system root certificates are used.
|
||||
* Otherwise, TLS roots are populated using the [`webpki-roots`] crate.
|
||||
|
||||
## Environment Variables
|
||||
Unlike with `libpq`, the following environment variables may be _either_
|
||||
a path to a file _or_ a string value containing a [PEM-encoded value][rfc7468]:
|
||||
|
||||
* `PGSSLROOTCERT`
|
||||
* `PGSSLCERT`
|
||||
* `PGSSLKEY`
|
||||
|
||||
If the string begins with the standard `-----BEGIN <CERTIFICATE | PRIVATE KEY>-----` header
|
||||
and ends with the standard `-----END <CERTIFICATE | PRIVATE KEY>-----` footer,
|
||||
it is parsed directly.
|
||||
|
||||
This behavior is _only_ implemented for the environment variables, not the URL parameters.
|
||||
|
||||
Note: passing the SSL private key via environment variable may be a security risk.
|
||||
|
||||
# Note: Unix Domain Sockets
|
||||
If you want to connect to Postgres over a Unix domain socket, you can pass the path
|
||||
to the _directory_ containing the socket as the `host` parameter.
|
||||
|
||||
The final path to the socket will be `{host}/.s.PGSQL.{port}` as is standard for Postgres.
|
||||
|
||||
If you're passing the domain socket path as the host segment of the URL, forward slashes
|
||||
in the path must be [percent-encoded] (replacing `/` with `%2F`), e.g.:
|
||||
|
||||
```text
|
||||
postgres://%2Fvar%2Frun%2Fpostgresql/dbname
|
||||
|
||||
Different port:
|
||||
postgres://%2Fvar%2Frun%2Fpostgresql:5433/dbname
|
||||
|
||||
With username and password:
|
||||
postgres://user:password@%2Fvar%2Frun%2Fpostgresql/dbname
|
||||
|
||||
With username and password, and different port:
|
||||
postgres://user:password@%2Fvar%2Frun%2Fpostgresql:5432/dbname
|
||||
```
|
||||
|
||||
Instead, the hostname can be passed in the query segment of the URL,
|
||||
which does not require forward-slashes to be percent-encoded
|
||||
(however, [other characters are][percent-encoded]):
|
||||
|
||||
```text
|
||||
postgres:dbname?host=/var/run/postgresql
|
||||
|
||||
Different port:
|
||||
postgres://:5433/dbname?host=/var/run/postgresql
|
||||
|
||||
With username and password:
|
||||
postgres://user:password@/dbname?host=/var/run/postgresql
|
||||
|
||||
With username and password, and different port:
|
||||
postgres://user:password@:5433/dbname?host=/var/run/postgresql
|
||||
```
|
||||
|
||||
# Example
|
||||
|
||||
```rust,no_run
|
||||
use sqlx::{Connection, ConnectOptions};
|
||||
use sqlx::postgres::{PgConnectOptions, PgConnection, PgPool, PgSslMode};
|
||||
|
||||
# async fn example() -> sqlx::Result<()> {
|
||||
// URL connection string
|
||||
let conn = PgConnection::connect("postgres://localhost/mydb").await?;
|
||||
|
||||
// Manually-constructed options
|
||||
let conn = PgConnectOptions::new()
|
||||
.host("secret-host")
|
||||
.port(2525)
|
||||
.username("secret-user")
|
||||
.password("secret-password")
|
||||
.ssl_mode(PgSslMode::Require)
|
||||
.connect()
|
||||
.await?;
|
||||
|
||||
// Modifying options parsed from a string
|
||||
let mut opts: PgConnectOptions = "postgres://localhost/mydb".parse()?;
|
||||
|
||||
// Change the log verbosity level for queries.
|
||||
// Information about SQL queries is logged at `DEBUG` level by default.
|
||||
opts = opts.log_statements(log::LevelFilter::Trace);
|
||||
|
||||
let pool = PgPool::connect_with(opts).await?;
|
||||
# Ok(())
|
||||
# }
|
||||
```
|
||||
|
||||
[percent-encoded]: https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding
|
||||
[`passfile`]: https://www.postgresql.org/docs/current/libpq-pgpass.html
|
||||
[libpq-connstring]: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING
|
||||
[libpq-params]: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS
|
||||
[libpq-envars]: https://www.postgresql.org/docs/current/libpq-envars.html
|
||||
[rfc7468]: https://datatracker.ietf.org/doc/html/rfc7468
|
||||
[`webpki-roots`]: https://docs.rs/webpki-roots
|
@ -12,80 +12,7 @@ mod parse;
|
||||
mod pgpass;
|
||||
mod ssl_mode;
|
||||
|
||||
/// Options and flags which can be used to configure a PostgreSQL connection.
|
||||
///
|
||||
/// A value of `PgConnectOptions` can be parsed from a connection URL,
|
||||
/// as described by [libpq](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING).
|
||||
///
|
||||
/// The general form for a connection URL is:
|
||||
///
|
||||
/// ```text
|
||||
/// postgresql://[user[:password]@][host][:port][/dbname][?param1=value1&...]
|
||||
/// ```
|
||||
///
|
||||
/// This type also implements [`FromStr`][std::str::FromStr] so you can parse it from a string
|
||||
/// containing a connection URL and then further adjust options if necessary (see example below).
|
||||
///
|
||||
/// ## Parameters
|
||||
///
|
||||
/// |Parameter|Default|Description|
|
||||
/// |---------|-------|-----------|
|
||||
/// | `sslmode` | `prefer` | Determines whether or with what priority a secure SSL TCP/IP connection will be negotiated. See [`PgSslMode`]. |
|
||||
/// | `sslrootcert` | `None` | Sets the name of a file containing a list of trusted SSL Certificate Authorities. |
|
||||
/// | `statement-cache-capacity` | `100` | The maximum number of prepared statements stored in the cache. Set to `0` to disable. |
|
||||
/// | `host` | `None` | Path to the directory containing a PostgreSQL unix domain socket, which will be used instead of TCP if set. |
|
||||
/// | `hostaddr` | `None` | Same as `host`, but only accepts IP addresses. |
|
||||
/// | `application-name` | `None` | The name will be displayed in the pg_stat_activity view and included in CSV log entries. |
|
||||
/// | `user` | result of `whoami` | PostgreSQL user name to connect as. |
|
||||
/// | `password` | `None` | Password to be used if the server demands password authentication. |
|
||||
/// | `port` | `5432` | Port number to connect to at the server host, or socket file name extension for Unix-domain connections. |
|
||||
/// | `dbname` | `None` | The database name. |
|
||||
/// | `options` | `None` | The runtime parameters to send to the server at connection start. |
|
||||
///
|
||||
/// The URL scheme designator can be either `postgresql://` or `postgres://`.
|
||||
/// Each of the URL parts is optional.
|
||||
///
|
||||
/// ```text
|
||||
/// postgresql://
|
||||
/// postgresql://localhost
|
||||
/// postgresql://localhost:5433
|
||||
/// postgresql://localhost/mydb
|
||||
/// postgresql://user@localhost
|
||||
/// postgresql://user:secret@localhost
|
||||
/// postgresql://localhost?dbname=mydb&user=postgres&password=postgres
|
||||
/// ```
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use sqlx::{Connection, ConnectOptions};
|
||||
/// use sqlx::postgres::{PgConnectOptions, PgConnection, PgPool, PgSslMode};
|
||||
///
|
||||
/// # async fn example() -> sqlx::Result<()> {
|
||||
/// // URL connection string
|
||||
/// let conn = PgConnection::connect("postgres://localhost/mydb").await?;
|
||||
///
|
||||
/// // Manually-constructed options
|
||||
/// let conn = PgConnectOptions::new()
|
||||
/// .host("secret-host")
|
||||
/// .port(2525)
|
||||
/// .username("secret-user")
|
||||
/// .password("secret-password")
|
||||
/// .ssl_mode(PgSslMode::Require)
|
||||
/// .connect()
|
||||
/// .await?;
|
||||
///
|
||||
/// // Modifying options parsed from a string
|
||||
/// let mut opts: PgConnectOptions = "postgres://localhost/mydb".parse()?;
|
||||
///
|
||||
/// // Change the log verbosity level for queries.
|
||||
/// // Information about SQL queries is logged at `DEBUG` level by default.
|
||||
/// opts = opts.log_statements(log::LevelFilter::Trace);
|
||||
///
|
||||
/// let pool = PgPool::connect_with(opts).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[doc = include_str!("doc.md")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PgConnectOptions {
|
||||
pub(crate) host: String,
|
||||
@ -112,52 +39,30 @@ impl Default for PgConnectOptions {
|
||||
}
|
||||
|
||||
impl PgConnectOptions {
|
||||
/// Creates a new, default set of options ready for configuration.
|
||||
/// Create a default set of connection options populated from the current environment.
|
||||
///
|
||||
/// By default, this reads the following environment variables and sets their
|
||||
/// equivalent options.
|
||||
/// This behaves as if parsed from the connection string `postgres://`
|
||||
///
|
||||
/// * `PGHOST`
|
||||
/// * `PGPORT`
|
||||
/// * `PGUSER`
|
||||
/// * `PGPASSWORD`
|
||||
/// * `PGDATABASE`
|
||||
/// * `PGSSLROOTCERT`
|
||||
/// * `PGSSLCERT`
|
||||
/// * `PGSSLKEY`
|
||||
/// * `PGSSLMODE`
|
||||
/// * `PGAPPNAME`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # use sqlx_postgres::PgConnectOptions;
|
||||
/// let options = PgConnectOptions::new();
|
||||
/// ```
|
||||
///
|
||||
/// Note: that unlike `libpq` the environment variables:
|
||||
///
|
||||
/// * `PGSSLROOTCERT`
|
||||
/// * `PGSSLCERT`
|
||||
/// * `PGSSLKEY`
|
||||
///
|
||||
/// Must not exclusively be path, ´sqlx-postgres` supports these variables
|
||||
/// encode the certificates / keys directly. Content snooping is done via
|
||||
/// `CertificateInput::from`.
|
||||
///
|
||||
/// Note: Putting key material in environment variables can be subjected to risk as on
|
||||
/// some platforms environment variables can be recovered by other (non root) users.
|
||||
/// See the type-level documentation for details.
|
||||
pub fn new() -> Self {
|
||||
Self::new_without_pgpass().apply_pgpass()
|
||||
}
|
||||
|
||||
/// Create a default set of connection options _without_ reading from `passfile`.
|
||||
///
|
||||
/// Equivalent to [`PgConnectOptions::new()`] but `passfile` is ignored.
|
||||
///
|
||||
/// See the type-level documentation for details.
|
||||
pub fn new_without_pgpass() -> Self {
|
||||
let port = var("PGPORT")
|
||||
.ok()
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(5432);
|
||||
|
||||
let host = var("PGHOST").ok().unwrap_or_else(|| default_host(port));
|
||||
let host = var("PGHOSTADDR")
|
||||
.ok()
|
||||
.or_else(|| var("PGHOST").ok())
|
||||
.unwrap_or_else(|| default_host(port));
|
||||
|
||||
let username = var("PGUSER").ok().unwrap_or_else(whoami::username);
|
||||
|
||||
@ -172,6 +77,9 @@ impl PgConnectOptions {
|
||||
database,
|
||||
ssl_root_cert: var("PGSSLROOTCERT").ok().map(CertificateInput::from),
|
||||
ssl_client_cert: var("PGSSLCERT").ok().map(CertificateInput::from),
|
||||
// As of writing, the implementation of `From<String>` only looks for
|
||||
// `-----BEGIN CERTIFICATE-----` and so will not attempt to parse
|
||||
// a PEM-encoded private key.
|
||||
ssl_client_key: var("PGSSLKEY").ok().map(CertificateInput::from),
|
||||
ssl_mode: var("PGSSLMODE")
|
||||
.ok()
|
||||
|
Loading…
x
Reference in New Issue
Block a user