1use std::time::Duration;
2
3mod connection;
4mod db_connection;
5#[cfg(feature = "mock")]
6#[cfg_attr(docsrs, doc(cfg(feature = "mock")))]
7mod mock;
8#[cfg(feature = "proxy")]
9#[cfg_attr(docsrs, doc(cfg(feature = "proxy")))]
10mod proxy;
11mod statement;
12mod stream;
13mod transaction;
14
15pub use connection::*;
16pub use db_connection::*;
17#[cfg(feature = "mock")]
18#[cfg_attr(docsrs, doc(cfg(feature = "mock")))]
19pub use mock::*;
20#[cfg(feature = "proxy")]
21#[cfg_attr(docsrs, doc(cfg(feature = "proxy")))]
22pub use proxy::*;
23pub use statement::*;
24use std::borrow::Cow;
25pub use stream::*;
26use tracing::instrument;
27pub use transaction::*;
28
29use crate::error::*;
30
31#[derive(Debug, Default)]
33pub struct Database;
34
35#[derive(Debug, Clone)]
37pub struct ConnectOptions {
38 pub(crate) url: String,
40 pub(crate) max_connections: Option<u32>,
42 pub(crate) min_connections: Option<u32>,
44 pub(crate) connect_timeout: Option<Duration>,
46 pub(crate) idle_timeout: Option<Duration>,
49 pub(crate) acquire_timeout: Option<Duration>,
51 pub(crate) max_lifetime: Option<Duration>,
53 pub(crate) sqlx_logging: bool,
55 pub(crate) sqlx_logging_level: log::LevelFilter,
57 pub(crate) sqlx_slow_statements_logging_level: log::LevelFilter,
59 pub(crate) sqlx_slow_statements_logging_threshold: Duration,
61 pub(crate) sqlcipher_key: Option<Cow<'static, str>>,
63 pub(crate) schema_search_path: Option<String>,
65 pub(crate) test_before_acquire: bool,
66 pub(crate) connect_lazy: bool,
70}
71
72impl Database {
73 #[instrument(level = "trace", skip(opt))]
76 pub async fn connect<C>(opt: C) -> Result<DatabaseConnection, DbErr>
77 where
78 C: Into<ConnectOptions>,
79 {
80 let opt: ConnectOptions = opt.into();
81
82 if url::Url::parse(&opt.url).is_err() {
83 return Err(conn_err(format!(
84 "The connection string '{}' cannot be parsed.",
85 opt.url
86 )));
87 }
88
89 #[cfg(feature = "sqlx-mysql")]
90 if DbBackend::MySql.is_prefix_of(&opt.url) {
91 return crate::SqlxMySqlConnector::connect(opt).await;
92 }
93 #[cfg(feature = "sqlx-postgres")]
94 if DbBackend::Postgres.is_prefix_of(&opt.url) {
95 return crate::SqlxPostgresConnector::connect(opt).await;
96 }
97 #[cfg(feature = "sqlx-sqlite")]
98 if DbBackend::Sqlite.is_prefix_of(&opt.url) {
99 return crate::SqlxSqliteConnector::connect(opt).await;
100 }
101 #[cfg(feature = "mock")]
102 if crate::MockDatabaseConnector::accepts(&opt.url) {
103 return crate::MockDatabaseConnector::connect(&opt.url).await;
104 }
105
106 Err(conn_err(format!(
107 "The connection string '{}' has no supporting driver.",
108 opt.url
109 )))
110 }
111
112 #[cfg(feature = "proxy")]
114 #[instrument(level = "trace", skip(proxy_func_arc))]
115 pub async fn connect_proxy(
116 db_type: DbBackend,
117 proxy_func_arc: std::sync::Arc<Box<dyn ProxyDatabaseTrait>>,
118 ) -> Result<DatabaseConnection, DbErr> {
119 match db_type {
120 DbBackend::MySql => {
121 return crate::ProxyDatabaseConnector::connect(
122 DbBackend::MySql,
123 proxy_func_arc.to_owned(),
124 );
125 }
126 DbBackend::Postgres => {
127 return crate::ProxyDatabaseConnector::connect(
128 DbBackend::Postgres,
129 proxy_func_arc.to_owned(),
130 );
131 }
132 DbBackend::Sqlite => {
133 return crate::ProxyDatabaseConnector::connect(
134 DbBackend::Sqlite,
135 proxy_func_arc.to_owned(),
136 );
137 }
138 }
139 }
140}
141
142impl<T> From<T> for ConnectOptions
143where
144 T: Into<String>,
145{
146 fn from(s: T) -> ConnectOptions {
147 ConnectOptions::new(s.into())
148 }
149}
150
151impl ConnectOptions {
152 pub fn new<T>(url: T) -> Self
154 where
155 T: Into<String>,
156 {
157 Self {
158 url: url.into(),
159 max_connections: None,
160 min_connections: None,
161 connect_timeout: None,
162 idle_timeout: None,
163 acquire_timeout: None,
164 max_lifetime: None,
165 sqlx_logging: true,
166 sqlx_logging_level: log::LevelFilter::Info,
167 sqlx_slow_statements_logging_level: log::LevelFilter::Off,
168 sqlx_slow_statements_logging_threshold: Duration::from_secs(1),
169 sqlcipher_key: None,
170 schema_search_path: None,
171 test_before_acquire: true,
172 connect_lazy: false,
173 }
174 }
175
176 pub fn get_url(&self) -> &str {
178 &self.url
179 }
180
181 pub fn max_connections(&mut self, value: u32) -> &mut Self {
183 self.max_connections = Some(value);
184 self
185 }
186
187 pub fn get_max_connections(&self) -> Option<u32> {
189 self.max_connections
190 }
191
192 pub fn min_connections(&mut self, value: u32) -> &mut Self {
194 self.min_connections = Some(value);
195 self
196 }
197
198 pub fn get_min_connections(&self) -> Option<u32> {
200 self.min_connections
201 }
202
203 pub fn connect_timeout(&mut self, value: Duration) -> &mut Self {
205 self.connect_timeout = Some(value);
206 self
207 }
208
209 pub fn get_connect_timeout(&self) -> Option<Duration> {
211 self.connect_timeout
212 }
213
214 pub fn idle_timeout(&mut self, value: Duration) -> &mut Self {
216 self.idle_timeout = Some(value);
217 self
218 }
219
220 pub fn get_idle_timeout(&self) -> Option<Duration> {
222 self.idle_timeout
223 }
224
225 pub fn acquire_timeout(&mut self, value: Duration) -> &mut Self {
227 self.acquire_timeout = Some(value);
228 self
229 }
230
231 pub fn get_acquire_timeout(&self) -> Option<Duration> {
233 self.acquire_timeout
234 }
235
236 pub fn max_lifetime(&mut self, lifetime: Duration) -> &mut Self {
238 self.max_lifetime = Some(lifetime);
239 self
240 }
241
242 pub fn get_max_lifetime(&self) -> Option<Duration> {
244 self.max_lifetime
245 }
246
247 pub fn sqlx_logging(&mut self, value: bool) -> &mut Self {
249 self.sqlx_logging = value;
250 self
251 }
252
253 pub fn get_sqlx_logging(&self) -> bool {
255 self.sqlx_logging
256 }
257
258 pub fn sqlx_logging_level(&mut self, level: log::LevelFilter) -> &mut Self {
261 self.sqlx_logging_level = level;
262 self
263 }
264
265 pub fn sqlx_slow_statements_logging_settings(
268 &mut self,
269 level: log::LevelFilter,
270 duration: Duration,
271 ) -> &mut Self {
272 self.sqlx_slow_statements_logging_level = level;
273 self.sqlx_slow_statements_logging_threshold = duration;
274 self
275 }
276
277 pub fn get_sqlx_logging_level(&self) -> log::LevelFilter {
279 self.sqlx_logging_level
280 }
281
282 pub fn get_sqlx_slow_statements_logging_settings(&self) -> (log::LevelFilter, Duration) {
284 (
285 self.sqlx_slow_statements_logging_level,
286 self.sqlx_slow_statements_logging_threshold,
287 )
288 }
289
290 pub fn sqlcipher_key<T>(&mut self, value: T) -> &mut Self
292 where
293 T: Into<Cow<'static, str>>,
294 {
295 self.sqlcipher_key = Some(value.into());
296 self
297 }
298
299 pub fn set_schema_search_path<T>(&mut self, schema_search_path: T) -> &mut Self
301 where
302 T: Into<String>,
303 {
304 self.schema_search_path = Some(schema_search_path.into());
305 self
306 }
307
308 pub fn test_before_acquire(&mut self, value: bool) -> &mut Self {
310 self.test_before_acquire = value;
311 self
312 }
313
314 pub fn connect_lazy(&mut self, value: bool) -> &mut Self {
317 self.connect_lazy = value;
318 self
319 }
320
321 pub fn get_connect_lazy(&self) -> bool {
323 self.connect_lazy
324 }
325}