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