datumesh_store/pg_unstable.rs
1//! Outside semver until 1.0: this module exposes the `postgres` driver's types, and any
2//! release may change it, including a patch release.
3//!
4//! For what [`PgStore::connect_with`] does not cover: a store whose connections come from
5//! any function returning a `postgres::Client` (client certificates, a custom TLS setup,
6//! session settings), and plain clients that connect exactly as the store does (the same
7//! TLS connector and roots). [`postgres`] is the driver this crate is built with, so a
8//! `Client` made with it is the type [`with_connector`] takes. Depend on an exact version
9//! of this crate (`datumesh-store = "=x.y.z"`) if you use this module.
10
11use std::fmt;
12
13use tokio_postgres_rustls::MakeRustlsConnect;
14
15pub use postgres;
16
17use crate::error::Result;
18use crate::pool::{Pool, PoolOptions};
19use crate::PgStore;
20
21/// A store whose pool opens connections with `connect` (any TLS setup, any configuration).
22/// One connection is opened at once, so a failing connector fails here.
23///
24/// Outside semver until 1.0: this function names the `postgres` driver's types, and any
25/// release may change it, including a patch release.
26pub fn with_connector<F>(connect: F, options: PoolOptions) -> Result<PgStore>
27where
28 F: Fn() -> core::result::Result<postgres::Client, postgres::Error> + Send + Sync + 'static,
29{
30 PgStore::from_pool(Pool::new(Box::new(connect), options))
31}
32
33/// Opens `postgres` clients the way [`PgStore::connect_with`] does: the configuration's
34/// `sslmode` decides whether TLS is used, and when it is, the server's certificate and host
35/// name are verified against the Mozilla roots and the roots of the [`PoolOptions`]
36/// (rustls, ring provider). Cheap to clone.
37///
38/// Outside semver until 1.0: this type names the `postgres` driver's types, and any release
39/// may change it, including a patch release.
40#[derive(Clone)]
41pub struct Connector {
42 config: postgres::Config,
43 tls: MakeRustlsConnect,
44}
45
46impl fmt::Debug for Connector {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 f.debug_struct("Connector").field("config", &self.config).finish_non_exhaustive()
49 }
50}
51
52impl Connector {
53 /// A connector for `config`, with the TLS roots of `options` (its pool settings are not
54 /// used). Fails with [`Error::Config`](crate::Error::Config) if a root does not parse.
55 pub fn new(config: postgres::Config, options: &PoolOptions) -> Result<Connector> {
56 Ok(Connector { config, tls: crate::tls::connector(options)? })
57 }
58
59 /// Opens a client.
60 pub fn connect(&self) -> core::result::Result<postgres::Client, postgres::Error> {
61 self.config.connect(self.tls.clone())
62 }
63}