sql_middleware/postgres/
config.rs1use super::typed::PgManager;
2use crate::middleware::{ConfigAndPool, DatabaseType, MiddlewarePool, SqlMiddlewareDbError};
3
4#[derive(Clone, Debug, Default)]
7pub struct PgConfig {
8 pub dbname: Option<String>,
9 pub host: Option<String>,
10 pub port: Option<u16>,
11 pub user: Option<String>,
12 pub password: Option<String>,
13}
14
15impl PgConfig {
16 #[must_use]
17 pub fn new() -> Self {
18 Self::default()
19 }
20
21 #[must_use]
22 pub fn to_tokio_config(&self) -> tokio_postgres::Config {
23 let mut cfg = tokio_postgres::Config::new();
24 if let Some(dbname) = &self.dbname {
25 cfg.dbname(dbname);
26 }
27 if let Some(host) = &self.host {
28 cfg.host(host);
29 }
30 if let Some(port) = self.port {
31 cfg.port(port);
32 }
33 if let Some(user) = &self.user {
34 cfg.user(user);
35 }
36 if let Some(password) = &self.password {
37 cfg.password(password);
38 }
39 cfg
40 }
41}
42
43#[derive(Clone)]
45pub struct PostgresOptions {
46 pub config: PgConfig,
47 pub translate_placeholders: bool,
48}
49
50impl PostgresOptions {
51 #[must_use]
52 pub fn new(config: PgConfig) -> Self {
53 Self {
54 config,
55 translate_placeholders: false,
56 }
57 }
58
59 #[must_use]
60 pub fn with_translation(mut self, translate_placeholders: bool) -> Self {
61 self.translate_placeholders = translate_placeholders;
62 self
63 }
64}
65
66#[derive(Clone)]
68pub struct PostgresOptionsBuilder {
69 opts: PostgresOptions,
70}
71
72impl PostgresOptionsBuilder {
73 #[must_use]
74 pub fn new(config: PgConfig) -> Self {
75 Self {
76 opts: PostgresOptions::new(config),
77 }
78 }
79
80 #[must_use]
81 pub fn translation(mut self, translate_placeholders: bool) -> Self {
82 self.opts.translate_placeholders = translate_placeholders;
83 self
84 }
85
86 #[must_use]
87 pub fn finish(self) -> PostgresOptions {
88 self.opts
89 }
90
91 pub async fn build(self) -> Result<ConfigAndPool, SqlMiddlewareDbError> {
97 ConfigAndPool::new_postgres(self.finish()).await
98 }
99}
100
101impl ConfigAndPool {
102 #[must_use]
103 pub fn postgres_builder(pg_config: PgConfig) -> PostgresOptionsBuilder {
104 PostgresOptionsBuilder::new(pg_config)
105 }
106
107 #[allow(clippy::unused_async)]
112 pub async fn new_postgres(opts: PostgresOptions) -> Result<Self, SqlMiddlewareDbError> {
113 let pg_config = opts.config;
114 let translate_placeholders = opts.translate_placeholders;
115
116 if pg_config.dbname.is_none() {
118 return Err(SqlMiddlewareDbError::ConfigError(
119 "dbname is required".to_string(),
120 ));
121 }
122
123 if pg_config.host.is_none() {
124 return Err(SqlMiddlewareDbError::ConfigError(
125 "host is required".to_string(),
126 ));
127 }
128 if pg_config.port.is_none() {
129 return Err(SqlMiddlewareDbError::ConfigError(
130 "port is required".to_string(),
131 ));
132 }
133 if pg_config.user.is_none() {
134 return Err(SqlMiddlewareDbError::ConfigError(
135 "user is required".to_string(),
136 ));
137 }
138 if pg_config.password.is_none() {
139 return Err(SqlMiddlewareDbError::ConfigError(
140 "password is required".to_string(),
141 ));
142 }
143
144 let manager = PgManager::new(pg_config.to_tokio_config());
146 let pg_pool = manager.build_pool().await?;
147
148 Ok(ConfigAndPool {
149 pool: MiddlewarePool::Postgres(pg_pool),
150 db_type: DatabaseType::Postgres,
151 translate_placeholders,
152 })
153 }
154}