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 #[cfg(feature = "sqlx-mysql")]
83 if DbBackend::MySql.is_prefix_of(&opt.url) {
84 return crate::SqlxMySqlConnector::connect(opt).await;
85 }
86 #[cfg(feature = "sqlx-postgres")]
87 if DbBackend::Postgres.is_prefix_of(&opt.url) {
88 return crate::SqlxPostgresConnector::connect(opt).await;
89 }
90 #[cfg(feature = "sqlx-sqlite")]
91 if DbBackend::Sqlite.is_prefix_of(&opt.url) {
92 return crate::SqlxSqliteConnector::connect(opt).await;
93 }
94 #[cfg(feature = "mock")]
95 if crate::MockDatabaseConnector::accepts(&opt.url) {
96 return crate::MockDatabaseConnector::connect(&opt.url).await;
97 }
98
99 Err(conn_err(format!(
100 "The connection string '{}' has no supporting driver.",
101 opt.url
102 )))
103 }
104
105 #[cfg(feature = "proxy")]
107 #[instrument(level = "trace", skip(proxy_func_arc))]
108 pub async fn connect_proxy(
109 db_type: DbBackend,
110 proxy_func_arc: std::sync::Arc<Box<dyn ProxyDatabaseTrait>>,
111 ) -> Result<DatabaseConnection, DbErr> {
112 match db_type {
113 DbBackend::MySql => {
114 return crate::ProxyDatabaseConnector::connect(
115 DbBackend::MySql,
116 proxy_func_arc.to_owned(),
117 );
118 }
119 DbBackend::Postgres => {
120 return crate::ProxyDatabaseConnector::connect(
121 DbBackend::Postgres,
122 proxy_func_arc.to_owned(),
123 );
124 }
125 DbBackend::Sqlite => {
126 return crate::ProxyDatabaseConnector::connect(
127 DbBackend::Sqlite,
128 proxy_func_arc.to_owned(),
129 );
130 }
131 }
132 }
133}
134
135impl<T> From<T> for ConnectOptions
136where
137 T: Into<String>,
138{
139 fn from(s: T) -> ConnectOptions {
140 ConnectOptions::new(s.into())
141 }
142}
143
144impl ConnectOptions {
145 pub fn new<T>(url: T) -> Self
147 where
148 T: Into<String>,
149 {
150 Self {
151 url: url.into(),
152 max_connections: None,
153 min_connections: None,
154 connect_timeout: None,
155 idle_timeout: None,
156 acquire_timeout: None,
157 max_lifetime: None,
158 sqlx_logging: true,
159 sqlx_logging_level: log::LevelFilter::Info,
160 sqlx_slow_statements_logging_level: log::LevelFilter::Off,
161 sqlx_slow_statements_logging_threshold: Duration::from_secs(1),
162 sqlcipher_key: None,
163 schema_search_path: None,
164 test_before_acquire: true,
165 connect_lazy: false,
166 }
167 }
168
169 pub fn get_url(&self) -> &str {
171 &self.url
172 }
173
174 pub fn max_connections(&mut self, value: u32) -> &mut Self {
176 self.max_connections = Some(value);
177 self
178 }
179
180 pub fn get_max_connections(&self) -> Option<u32> {
182 self.max_connections
183 }
184
185 pub fn min_connections(&mut self, value: u32) -> &mut Self {
187 self.min_connections = Some(value);
188 self
189 }
190
191 pub fn get_min_connections(&self) -> Option<u32> {
193 self.min_connections
194 }
195
196 pub fn connect_timeout(&mut self, value: Duration) -> &mut Self {
198 self.connect_timeout = Some(value);
199 self
200 }
201
202 pub fn get_connect_timeout(&self) -> Option<Duration> {
204 self.connect_timeout
205 }
206
207 pub fn idle_timeout(&mut self, value: Duration) -> &mut Self {
209 self.idle_timeout = Some(value);
210 self
211 }
212
213 pub fn get_idle_timeout(&self) -> Option<Duration> {
215 self.idle_timeout
216 }
217
218 pub fn acquire_timeout(&mut self, value: Duration) -> &mut Self {
220 self.acquire_timeout = Some(value);
221 self
222 }
223
224 pub fn get_acquire_timeout(&self) -> Option<Duration> {
226 self.acquire_timeout
227 }
228
229 pub fn max_lifetime(&mut self, lifetime: Duration) -> &mut Self {
231 self.max_lifetime = Some(lifetime);
232 self
233 }
234
235 pub fn get_max_lifetime(&self) -> Option<Duration> {
237 self.max_lifetime
238 }
239
240 pub fn sqlx_logging(&mut self, value: bool) -> &mut Self {
242 self.sqlx_logging = value;
243 self
244 }
245
246 pub fn get_sqlx_logging(&self) -> bool {
248 self.sqlx_logging
249 }
250
251 pub fn sqlx_logging_level(&mut self, level: log::LevelFilter) -> &mut Self {
254 self.sqlx_logging_level = level;
255 self
256 }
257
258 pub fn sqlx_slow_statements_logging_settings(
261 &mut self,
262 level: log::LevelFilter,
263 duration: Duration,
264 ) -> &mut Self {
265 self.sqlx_slow_statements_logging_level = level;
266 self.sqlx_slow_statements_logging_threshold = duration;
267 self
268 }
269
270 pub fn get_sqlx_logging_level(&self) -> log::LevelFilter {
272 self.sqlx_logging_level
273 }
274
275 pub fn get_sqlx_slow_statements_logging_settings(&self) -> (log::LevelFilter, Duration) {
277 (
278 self.sqlx_slow_statements_logging_level,
279 self.sqlx_slow_statements_logging_threshold,
280 )
281 }
282
283 pub fn sqlcipher_key<T>(&mut self, value: T) -> &mut Self
285 where
286 T: Into<Cow<'static, str>>,
287 {
288 self.sqlcipher_key = Some(value.into());
289 self
290 }
291
292 pub fn set_schema_search_path<T>(&mut self, schema_search_path: T) -> &mut Self
294 where
295 T: Into<String>,
296 {
297 self.schema_search_path = Some(schema_search_path.into());
298 self
299 }
300
301 pub fn test_before_acquire(&mut self, value: bool) -> &mut Self {
303 self.test_before_acquire = value;
304 self
305 }
306
307 pub fn connect_lazy(&mut self, value: bool) -> &mut Self {
310 self.connect_lazy = value;
311 self
312 }
313
314 pub fn get_connect_lazy(&self) -> bool {
316 self.connect_lazy
317 }
318}