1use crate::{
2 AccessMode, ConnectionTrait, DatabaseTransaction, ExecResult, IsolationLevel, QueryResult,
3 Statement, StatementBuilder, StreamTrait, TransactionError, TransactionTrait, error::*,
4};
5use sea_query::{MysqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder};
6use std::{fmt::Debug, future::Future, pin::Pin};
7use tracing::instrument;
8use url::Url;
9
10#[cfg(feature = "sqlx-dep")]
11use sqlx::pool::PoolConnection;
12
13#[cfg(any(feature = "mock", feature = "proxy"))]
14use std::sync::Arc;
15
16#[derive(Debug, Clone)]
20#[non_exhaustive]
21pub struct DatabaseConnection {
22 pub inner: DatabaseConnectionType,
25 #[cfg(feature = "rbac")]
26 rbac: crate::RbacEngineHolder,
27}
28
29#[derive(Clone)]
31pub enum DatabaseConnectionType {
32 #[cfg(feature = "sqlx-mysql")]
34 SqlxMySqlPoolConnection(crate::SqlxMySqlPoolConnection),
35
36 #[cfg(feature = "sqlx-postgres")]
38 SqlxPostgresPoolConnection(crate::SqlxPostgresPoolConnection),
39
40 #[cfg(feature = "sqlx-sqlite")]
42 SqlxSqlitePoolConnection(crate::SqlxSqlitePoolConnection),
43
44 #[cfg(feature = "mock")]
46 MockDatabaseConnection(Arc<crate::MockDatabaseConnection>),
47
48 #[cfg(feature = "proxy")]
50 ProxyDatabaseConnection(Arc<crate::ProxyDatabaseConnection>),
51
52 Disconnected,
54}
55
56pub type DbConn = DatabaseConnection;
58
59impl Default for DatabaseConnection {
60 fn default() -> Self {
61 DatabaseConnectionType::Disconnected.into()
62 }
63}
64
65impl From<DatabaseConnectionType> for DatabaseConnection {
66 fn from(inner: DatabaseConnectionType) -> Self {
67 Self {
68 inner,
69 #[cfg(feature = "rbac")]
70 rbac: Default::default(),
71 }
72 }
73}
74
75#[derive(Debug, Copy, Clone, PartialEq, Eq)]
78#[non_exhaustive]
79pub enum DatabaseBackend {
80 MySql,
82 Postgres,
84 Sqlite,
86}
87
88pub type DbBackend = DatabaseBackend;
90
91#[derive(Debug)]
92pub(crate) enum InnerConnection {
93 #[cfg(feature = "sqlx-mysql")]
94 MySql(PoolConnection<sqlx::MySql>),
95 #[cfg(feature = "sqlx-postgres")]
96 Postgres(PoolConnection<sqlx::Postgres>),
97 #[cfg(feature = "sqlx-sqlite")]
98 Sqlite(PoolConnection<sqlx::Sqlite>),
99 #[cfg(feature = "mock")]
100 Mock(Arc<crate::MockDatabaseConnection>),
101 #[cfg(feature = "proxy")]
102 Proxy(Arc<crate::ProxyDatabaseConnection>),
103}
104
105impl Debug for DatabaseConnectionType {
106 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
107 write!(
108 f,
109 "{}",
110 match self {
111 #[cfg(feature = "sqlx-mysql")]
112 Self::SqlxMySqlPoolConnection(_) => "SqlxMySqlPoolConnection",
113 #[cfg(feature = "sqlx-postgres")]
114 Self::SqlxPostgresPoolConnection(_) => "SqlxPostgresPoolConnection",
115 #[cfg(feature = "sqlx-sqlite")]
116 Self::SqlxSqlitePoolConnection(_) => "SqlxSqlitePoolConnection",
117 #[cfg(feature = "mock")]
118 Self::MockDatabaseConnection(_) => "MockDatabaseConnection",
119 #[cfg(feature = "proxy")]
120 Self::ProxyDatabaseConnection(_) => "ProxyDatabaseConnection",
121 Self::Disconnected => "Disconnected",
122 }
123 )
124 }
125}
126
127#[async_trait::async_trait]
128impl ConnectionTrait for DatabaseConnection {
129 fn get_database_backend(&self) -> DbBackend {
130 self.get_database_backend()
131 }
132
133 #[instrument(level = "trace")]
134 #[allow(unused_variables)]
135 async fn execute_raw(&self, stmt: Statement) -> Result<ExecResult, DbErr> {
136 match &self.inner {
137 #[cfg(feature = "sqlx-mysql")]
138 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.execute(stmt).await,
139 #[cfg(feature = "sqlx-postgres")]
140 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.execute(stmt).await,
141 #[cfg(feature = "sqlx-sqlite")]
142 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.execute(stmt).await,
143 #[cfg(feature = "mock")]
144 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.execute(stmt),
145 #[cfg(feature = "proxy")]
146 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.execute(stmt).await,
147 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
148 }
149 }
150
151 #[instrument(level = "trace")]
152 #[allow(unused_variables)]
153 async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr> {
154 match &self.inner {
155 #[cfg(feature = "sqlx-mysql")]
156 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
157 conn.execute_unprepared(sql).await
158 }
159 #[cfg(feature = "sqlx-postgres")]
160 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
161 conn.execute_unprepared(sql).await
162 }
163 #[cfg(feature = "sqlx-sqlite")]
164 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
165 conn.execute_unprepared(sql).await
166 }
167 #[cfg(feature = "mock")]
168 DatabaseConnectionType::MockDatabaseConnection(conn) => {
169 let db_backend = conn.get_database_backend();
170 let stmt = Statement::from_string(db_backend, sql);
171 conn.execute(stmt)
172 }
173 #[cfg(feature = "proxy")]
174 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
175 let db_backend = conn.get_database_backend();
176 let stmt = Statement::from_string(db_backend, sql);
177 conn.execute(stmt).await
178 }
179 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
180 }
181 }
182
183 #[instrument(level = "trace")]
184 #[allow(unused_variables)]
185 async fn query_one_raw(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
186 match &self.inner {
187 #[cfg(feature = "sqlx-mysql")]
188 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.query_one(stmt).await,
189 #[cfg(feature = "sqlx-postgres")]
190 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.query_one(stmt).await,
191 #[cfg(feature = "sqlx-sqlite")]
192 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.query_one(stmt).await,
193 #[cfg(feature = "mock")]
194 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.query_one(stmt),
195 #[cfg(feature = "proxy")]
196 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.query_one(stmt).await,
197 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
198 }
199 }
200
201 #[instrument(level = "trace")]
202 #[allow(unused_variables)]
203 async fn query_all_raw(&self, stmt: Statement) -> Result<Vec<QueryResult>, DbErr> {
204 match &self.inner {
205 #[cfg(feature = "sqlx-mysql")]
206 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.query_all(stmt).await,
207 #[cfg(feature = "sqlx-postgres")]
208 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.query_all(stmt).await,
209 #[cfg(feature = "sqlx-sqlite")]
210 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.query_all(stmt).await,
211 #[cfg(feature = "mock")]
212 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.query_all(stmt),
213 #[cfg(feature = "proxy")]
214 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.query_all(stmt).await,
215 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
216 }
217 }
218
219 #[cfg(feature = "mock")]
220 fn is_mock_connection(&self) -> bool {
221 matches!(
222 self,
223 DatabaseConnection {
224 inner: DatabaseConnectionType::MockDatabaseConnection(_),
225 ..
226 }
227 )
228 }
229}
230
231#[async_trait::async_trait]
232impl StreamTrait for DatabaseConnection {
233 type Stream<'a> = crate::QueryStream;
234
235 fn get_database_backend(&self) -> DbBackend {
236 self.get_database_backend()
237 }
238
239 #[instrument(level = "trace")]
240 #[allow(unused_variables)]
241 fn stream_raw<'a>(
242 &'a self,
243 stmt: Statement,
244 ) -> Pin<Box<dyn Future<Output = Result<Self::Stream<'a>, DbErr>> + 'a + Send>> {
245 Box::pin(async move {
246 match &self.inner {
247 #[cfg(feature = "sqlx-mysql")]
248 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.stream(stmt).await,
249 #[cfg(feature = "sqlx-postgres")]
250 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.stream(stmt).await,
251 #[cfg(feature = "sqlx-sqlite")]
252 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.stream(stmt).await,
253 #[cfg(feature = "mock")]
254 DatabaseConnectionType::MockDatabaseConnection(conn) => {
255 Ok(crate::QueryStream::from((Arc::clone(conn), stmt, None)))
256 }
257 #[cfg(feature = "proxy")]
258 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
259 Ok(crate::QueryStream::from((Arc::clone(conn), stmt, None)))
260 }
261 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
262 }
263 })
264 }
265}
266
267#[async_trait::async_trait]
268impl TransactionTrait for DatabaseConnection {
269 #[instrument(level = "trace")]
270 async fn begin(&self) -> Result<DatabaseTransaction, DbErr> {
271 match &self.inner {
272 #[cfg(feature = "sqlx-mysql")]
273 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.begin(None, None).await,
274 #[cfg(feature = "sqlx-postgres")]
275 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
276 conn.begin(None, None).await
277 }
278 #[cfg(feature = "sqlx-sqlite")]
279 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.begin(None, None).await,
280 #[cfg(feature = "mock")]
281 DatabaseConnectionType::MockDatabaseConnection(conn) => {
282 DatabaseTransaction::new_mock(Arc::clone(conn), None).await
283 }
284 #[cfg(feature = "proxy")]
285 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
286 DatabaseTransaction::new_proxy(conn.clone(), None).await
287 }
288 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
289 }
290 }
291
292 #[instrument(level = "trace")]
293 async fn begin_with_config(
294 &self,
295 _isolation_level: Option<IsolationLevel>,
296 _access_mode: Option<AccessMode>,
297 ) -> Result<DatabaseTransaction, DbErr> {
298 match &self.inner {
299 #[cfg(feature = "sqlx-mysql")]
300 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
301 conn.begin(_isolation_level, _access_mode).await
302 }
303 #[cfg(feature = "sqlx-postgres")]
304 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
305 conn.begin(_isolation_level, _access_mode).await
306 }
307 #[cfg(feature = "sqlx-sqlite")]
308 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
309 conn.begin(_isolation_level, _access_mode).await
310 }
311 #[cfg(feature = "mock")]
312 DatabaseConnectionType::MockDatabaseConnection(conn) => {
313 DatabaseTransaction::new_mock(Arc::clone(conn), None).await
314 }
315 #[cfg(feature = "proxy")]
316 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
317 DatabaseTransaction::new_proxy(conn.clone(), None).await
318 }
319 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
320 }
321 }
322
323 #[instrument(level = "trace", skip(_callback))]
326 async fn transaction<F, T, E>(&self, _callback: F) -> Result<T, TransactionError<E>>
327 where
328 F: for<'c> FnOnce(
329 &'c DatabaseTransaction,
330 ) -> Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'c>>
331 + Send,
332 T: Send,
333 E: std::fmt::Display + std::fmt::Debug + Send,
334 {
335 match &self.inner {
336 #[cfg(feature = "sqlx-mysql")]
337 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
338 conn.transaction(_callback, None, None).await
339 }
340 #[cfg(feature = "sqlx-postgres")]
341 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
342 conn.transaction(_callback, None, None).await
343 }
344 #[cfg(feature = "sqlx-sqlite")]
345 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
346 conn.transaction(_callback, None, None).await
347 }
348 #[cfg(feature = "mock")]
349 DatabaseConnectionType::MockDatabaseConnection(conn) => {
350 let transaction = DatabaseTransaction::new_mock(Arc::clone(conn), None)
351 .await
352 .map_err(TransactionError::Connection)?;
353 transaction.run(_callback).await
354 }
355 #[cfg(feature = "proxy")]
356 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
357 let transaction = DatabaseTransaction::new_proxy(conn.clone(), None)
358 .await
359 .map_err(TransactionError::Connection)?;
360 transaction.run(_callback).await
361 }
362 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected").into()),
363 }
364 }
365
366 #[instrument(level = "trace", skip(_callback))]
369 async fn transaction_with_config<F, T, E>(
370 &self,
371 _callback: F,
372 _isolation_level: Option<IsolationLevel>,
373 _access_mode: Option<AccessMode>,
374 ) -> Result<T, TransactionError<E>>
375 where
376 F: for<'c> FnOnce(
377 &'c DatabaseTransaction,
378 ) -> Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'c>>
379 + Send,
380 T: Send,
381 E: std::fmt::Display + std::fmt::Debug + Send,
382 {
383 match &self.inner {
384 #[cfg(feature = "sqlx-mysql")]
385 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
386 conn.transaction(_callback, _isolation_level, _access_mode)
387 .await
388 }
389 #[cfg(feature = "sqlx-postgres")]
390 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
391 conn.transaction(_callback, _isolation_level, _access_mode)
392 .await
393 }
394 #[cfg(feature = "sqlx-sqlite")]
395 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
396 conn.transaction(_callback, _isolation_level, _access_mode)
397 .await
398 }
399 #[cfg(feature = "mock")]
400 DatabaseConnectionType::MockDatabaseConnection(conn) => {
401 let transaction = DatabaseTransaction::new_mock(Arc::clone(conn), None)
402 .await
403 .map_err(TransactionError::Connection)?;
404 transaction.run(_callback).await
405 }
406 #[cfg(feature = "proxy")]
407 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
408 let transaction = DatabaseTransaction::new_proxy(conn.clone(), None)
409 .await
410 .map_err(TransactionError::Connection)?;
411 transaction.run(_callback).await
412 }
413 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected").into()),
414 }
415 }
416}
417
418#[cfg(feature = "mock")]
419impl DatabaseConnection {
420 pub fn as_mock_connection(&self) -> &crate::MockDatabaseConnection {
426 match &self.inner {
427 DatabaseConnectionType::MockDatabaseConnection(mock_conn) => mock_conn,
428 _ => panic!("Not mock connection"),
429 }
430 }
431
432 pub fn into_transaction_log(self) -> Vec<crate::Transaction> {
438 let mut mocker = self
439 .as_mock_connection()
440 .get_mocker_mutex()
441 .lock()
442 .expect("Fail to acquire mocker");
443 mocker.drain_transaction_log()
444 }
445}
446
447#[cfg(feature = "proxy")]
448impl DatabaseConnection {
449 pub fn as_proxy_connection(&self) -> &crate::ProxyDatabaseConnection {
455 match &self.inner {
456 DatabaseConnectionType::ProxyDatabaseConnection(proxy_conn) => proxy_conn,
457 _ => panic!("Not proxy connection"),
458 }
459 }
460}
461
462#[cfg(feature = "rbac")]
463impl DatabaseConnection {
464 pub async fn load_rbac(&self) -> Result<(), DbErr> {
467 self.load_rbac_from(self).await
468 }
469
470 pub async fn load_rbac_from(&self, db: &DbConn) -> Result<(), DbErr> {
473 let engine = crate::rbac::RbacEngine::load_from(db).await?;
474 self.rbac.replace(engine);
475 Ok(())
476 }
477
478 pub fn restricted_for(
480 &self,
481 user_id: crate::rbac::RbacUserId,
482 ) -> Result<crate::RestrictedConnection, DbErr> {
483 if self.rbac.is_some() {
484 Ok(crate::RestrictedConnection {
485 user_id,
486 conn: self.clone(),
487 engine: self.rbac.clone(),
488 })
489 } else {
490 Err(DbErr::RbacError("engine not set up".into()))
491 }
492 }
493}
494
495impl DatabaseConnection {
496 pub fn get_database_backend(&self) -> DbBackend {
502 match &self.inner {
503 #[cfg(feature = "sqlx-mysql")]
504 DatabaseConnectionType::SqlxMySqlPoolConnection(_) => DbBackend::MySql,
505 #[cfg(feature = "sqlx-postgres")]
506 DatabaseConnectionType::SqlxPostgresPoolConnection(_) => DbBackend::Postgres,
507 #[cfg(feature = "sqlx-sqlite")]
508 DatabaseConnectionType::SqlxSqlitePoolConnection(_) => DbBackend::Sqlite,
509 #[cfg(feature = "mock")]
510 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.get_database_backend(),
511 #[cfg(feature = "proxy")]
512 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.get_database_backend(),
513 DatabaseConnectionType::Disconnected => panic!("Disconnected"),
514 }
515 }
516
517 pub fn set_metric_callback<F>(&mut self, _callback: F)
519 where
520 F: Fn(&crate::metric::Info<'_>) + Send + Sync + 'static,
521 {
522 match &mut self.inner {
523 #[cfg(feature = "sqlx-mysql")]
524 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
525 conn.set_metric_callback(_callback)
526 }
527 #[cfg(feature = "sqlx-postgres")]
528 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
529 conn.set_metric_callback(_callback)
530 }
531 #[cfg(feature = "sqlx-sqlite")]
532 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
533 conn.set_metric_callback(_callback)
534 }
535 _ => {}
536 }
537 }
538
539 pub async fn ping(&self) -> Result<(), DbErr> {
541 match &self.inner {
542 #[cfg(feature = "sqlx-mysql")]
543 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.ping().await,
544 #[cfg(feature = "sqlx-postgres")]
545 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.ping().await,
546 #[cfg(feature = "sqlx-sqlite")]
547 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.ping().await,
548 #[cfg(feature = "mock")]
549 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.ping(),
550 #[cfg(feature = "proxy")]
551 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.ping().await,
552 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
553 }
554 }
555
556 pub async fn close(self) -> Result<(), DbErr> {
559 self.close_by_ref().await
560 }
561
562 pub async fn close_by_ref(&self) -> Result<(), DbErr> {
564 match &self.inner {
565 #[cfg(feature = "sqlx-mysql")]
566 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.close_by_ref().await,
567 #[cfg(feature = "sqlx-postgres")]
568 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.close_by_ref().await,
569 #[cfg(feature = "sqlx-sqlite")]
570 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.close_by_ref().await,
571 #[cfg(feature = "mock")]
572 DatabaseConnectionType::MockDatabaseConnection(_) => {
573 Ok(())
575 }
576 #[cfg(feature = "proxy")]
577 DatabaseConnectionType::ProxyDatabaseConnection(_) => {
578 Ok(())
580 }
581 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
582 }
583 }
584}
585
586impl DatabaseConnection {
587 #[cfg(feature = "sqlx-mysql")]
593 pub fn get_mysql_connection_pool(&self) -> &sqlx::MySqlPool {
594 match &self.inner {
595 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => &conn.pool,
596 _ => panic!("Not MySQL Connection"),
597 }
598 }
599
600 #[cfg(feature = "sqlx-postgres")]
606 pub fn get_postgres_connection_pool(&self) -> &sqlx::PgPool {
607 match &self.inner {
608 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => &conn.pool,
609 _ => panic!("Not Postgres Connection"),
610 }
611 }
612
613 #[cfg(feature = "sqlx-sqlite")]
619 pub fn get_sqlite_connection_pool(&self) -> &sqlx::SqlitePool {
620 match &self.inner {
621 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => &conn.pool,
622 _ => panic!("Not SQLite Connection"),
623 }
624 }
625}
626
627impl DbBackend {
628 pub fn is_prefix_of(self, base_url: &str) -> bool {
635 let base_url_parsed = Url::parse(base_url).expect("Fail to parse database URL");
636 match self {
637 Self::Postgres => {
638 base_url_parsed.scheme() == "postgres" || base_url_parsed.scheme() == "postgresql"
639 }
640 Self::MySql => base_url_parsed.scheme() == "mysql",
641 Self::Sqlite => base_url_parsed.scheme() == "sqlite",
642 }
643 }
644
645 pub fn build<S>(&self, statement: &S) -> Statement
647 where
648 S: StatementBuilder,
649 {
650 statement.build(self)
651 }
652
653 pub fn get_query_builder(&self) -> Box<dyn QueryBuilder> {
655 match self {
656 Self::MySql => Box::new(MysqlQueryBuilder),
657 Self::Postgres => Box::new(PostgresQueryBuilder),
658 Self::Sqlite => Box::new(SqliteQueryBuilder),
659 }
660 }
661
662 pub fn support_returning(&self) -> bool {
664 match self {
665 Self::Postgres => true,
666 Self::Sqlite if cfg!(feature = "sqlite-use-returning-for-3_35") => true,
667 _ => false,
668 }
669 }
670
671 pub fn boolean_value(&self, boolean: bool) -> sea_query::Value {
673 match self {
674 Self::MySql | Self::Postgres | Self::Sqlite => boolean.into(),
675 }
676 }
677}
678
679impl DatabaseBackend {
680 pub fn as_str(&self) -> &'static str {
682 match self {
683 DatabaseBackend::MySql => "MySql",
684 DatabaseBackend::Postgres => "Postgres",
685 DatabaseBackend::Sqlite => "Sqlite",
686 }
687 }
688}
689
690#[cfg(test)]
691mod tests {
692 use crate::DatabaseConnection;
693
694 #[test]
695 fn assert_database_connection_traits() {
696 fn assert_send_sync<T: Send + Sync>() {}
697
698 assert_send_sync::<DatabaseConnection>();
699 }
700}