1use crate::{
2 AccessMode, ConnectionTrait, DatabaseTransaction, ExecResult, IsolationLevel, QueryResult,
3 Schema, SchemaBuilder, Statement, StatementBuilder, StreamTrait, TransactionError,
4 TransactionTrait, error::*,
5};
6use std::fmt::Debug;
7use tracing::instrument;
8use url::Url;
9
10#[cfg(feature = "sqlx-dep")]
11use sqlx::pool::PoolConnection;
12
13#[cfg(feature = "rusqlite")]
14use crate::driver::rusqlite::{RusqliteInnerConnection, RusqliteSharedConnection};
15
16#[cfg(any(feature = "mock", feature = "proxy"))]
17use std::sync::Arc;
18
19#[derive(Debug, Clone)]
23#[non_exhaustive]
24pub struct DatabaseConnection {
25 pub inner: DatabaseConnectionType,
28 #[cfg(feature = "rbac")]
29 pub(crate) rbac: crate::RbacEngineMount,
30}
31
32#[derive(Clone)]
34pub enum DatabaseConnectionType {
35 #[cfg(feature = "sqlx-mysql")]
37 SqlxMySqlPoolConnection(crate::SqlxMySqlPoolConnection),
38
39 #[cfg(feature = "sqlx-postgres")]
41 SqlxPostgresPoolConnection(crate::SqlxPostgresPoolConnection),
42
43 #[cfg(feature = "sqlx-sqlite")]
45 SqlxSqlitePoolConnection(crate::SqlxSqlitePoolConnection),
46
47 #[cfg(feature = "rusqlite")]
49 RusqliteSharedConnection(RusqliteSharedConnection),
50
51 #[cfg(feature = "mock")]
53 MockDatabaseConnection(Arc<crate::MockDatabaseConnection>),
54
55 #[cfg(feature = "proxy")]
57 ProxyDatabaseConnection(Arc<crate::ProxyDatabaseConnection>),
58
59 Disconnected,
61}
62
63pub type DbConn = DatabaseConnection;
65
66impl Default for DatabaseConnection {
67 fn default() -> Self {
68 DatabaseConnectionType::Disconnected.into()
69 }
70}
71
72impl From<DatabaseConnectionType> for DatabaseConnection {
73 fn from(inner: DatabaseConnectionType) -> Self {
74 Self {
75 inner,
76 #[cfg(feature = "rbac")]
77 rbac: Default::default(),
78 }
79 }
80}
81
82#[derive(Debug, Copy, Clone, PartialEq, Eq)]
85#[non_exhaustive]
86pub enum DatabaseBackend {
87 MySql,
89 Postgres,
91 Sqlite,
93}
94
95pub type DbBackend = DatabaseBackend;
97
98#[derive(Debug)]
99pub(crate) enum InnerConnection {
100 #[cfg(feature = "sqlx-mysql")]
101 MySql(PoolConnection<sqlx::MySql>),
102 #[cfg(feature = "sqlx-postgres")]
103 Postgres(PoolConnection<sqlx::Postgres>),
104 #[cfg(feature = "sqlx-sqlite")]
105 Sqlite(PoolConnection<sqlx::Sqlite>),
106 #[cfg(feature = "rusqlite")]
107 Rusqlite(RusqliteInnerConnection),
108 #[cfg(feature = "mock")]
109 Mock(Arc<crate::MockDatabaseConnection>),
110 #[cfg(feature = "proxy")]
111 Proxy(Arc<crate::ProxyDatabaseConnection>),
112}
113
114impl Debug for DatabaseConnectionType {
115 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
116 write!(
117 f,
118 "{}",
119 match self {
120 #[cfg(feature = "sqlx-mysql")]
121 Self::SqlxMySqlPoolConnection(_) => "SqlxMySqlPoolConnection",
122 #[cfg(feature = "sqlx-postgres")]
123 Self::SqlxPostgresPoolConnection(_) => "SqlxPostgresPoolConnection",
124 #[cfg(feature = "sqlx-sqlite")]
125 Self::SqlxSqlitePoolConnection(_) => "SqlxSqlitePoolConnection",
126 #[cfg(feature = "rusqlite")]
127 Self::RusqliteSharedConnection(_) => "RusqliteSharedConnection",
128 #[cfg(feature = "mock")]
129 Self::MockDatabaseConnection(_) => "MockDatabaseConnection",
130 #[cfg(feature = "proxy")]
131 Self::ProxyDatabaseConnection(_) => "ProxyDatabaseConnection",
132 Self::Disconnected => "Disconnected",
133 }
134 )
135 }
136}
137
138impl ConnectionTrait for DatabaseConnection {
139 fn get_database_backend(&self) -> DbBackend {
140 self.get_database_backend()
141 }
142
143 #[instrument(level = "trace")]
144 #[allow(unused_variables)]
145 fn execute_raw(&self, stmt: Statement) -> Result<ExecResult, DbErr> {
146 match &self.inner {
147 #[cfg(feature = "sqlx-mysql")]
148 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.execute(stmt),
149 #[cfg(feature = "sqlx-postgres")]
150 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.execute(stmt),
151 #[cfg(feature = "sqlx-sqlite")]
152 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.execute(stmt),
153 #[cfg(feature = "rusqlite")]
154 DatabaseConnectionType::RusqliteSharedConnection(conn) => conn.execute(stmt),
155 #[cfg(feature = "mock")]
156 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.execute(stmt),
157 #[cfg(feature = "proxy")]
158 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.execute(stmt),
159 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
160 }
161 }
162
163 #[instrument(level = "trace")]
164 #[allow(unused_variables)]
165 fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr> {
166 match &self.inner {
167 #[cfg(feature = "sqlx-mysql")]
168 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.execute_unprepared(sql),
169 #[cfg(feature = "sqlx-postgres")]
170 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
171 conn.execute_unprepared(sql)
172 }
173 #[cfg(feature = "sqlx-sqlite")]
174 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.execute_unprepared(sql),
175 #[cfg(feature = "rusqlite")]
176 DatabaseConnectionType::RusqliteSharedConnection(conn) => conn.execute_unprepared(sql),
177 #[cfg(feature = "mock")]
178 DatabaseConnectionType::MockDatabaseConnection(conn) => {
179 let db_backend = conn.get_database_backend();
180 let stmt = Statement::from_string(db_backend, sql);
181 conn.execute(stmt)
182 }
183 #[cfg(feature = "proxy")]
184 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
185 let db_backend = conn.get_database_backend();
186 let stmt = Statement::from_string(db_backend, sql);
187 conn.execute(stmt)
188 }
189 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
190 }
191 }
192
193 #[instrument(level = "trace")]
194 #[allow(unused_variables)]
195 fn query_one_raw(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr> {
196 match &self.inner {
197 #[cfg(feature = "sqlx-mysql")]
198 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.query_one(stmt),
199 #[cfg(feature = "sqlx-postgres")]
200 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.query_one(stmt),
201 #[cfg(feature = "sqlx-sqlite")]
202 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.query_one(stmt),
203 #[cfg(feature = "rusqlite")]
204 DatabaseConnectionType::RusqliteSharedConnection(conn) => conn.query_one(stmt),
205 #[cfg(feature = "mock")]
206 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.query_one(stmt),
207 #[cfg(feature = "proxy")]
208 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.query_one(stmt),
209 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
210 }
211 }
212
213 #[instrument(level = "trace")]
214 #[allow(unused_variables)]
215 fn query_all_raw(&self, stmt: Statement) -> Result<Vec<QueryResult>, DbErr> {
216 match &self.inner {
217 #[cfg(feature = "sqlx-mysql")]
218 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.query_all(stmt),
219 #[cfg(feature = "sqlx-postgres")]
220 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.query_all(stmt),
221 #[cfg(feature = "sqlx-sqlite")]
222 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.query_all(stmt),
223 #[cfg(feature = "rusqlite")]
224 DatabaseConnectionType::RusqliteSharedConnection(conn) => conn.query_all(stmt),
225 #[cfg(feature = "mock")]
226 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.query_all(stmt),
227 #[cfg(feature = "proxy")]
228 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.query_all(stmt),
229 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
230 }
231 }
232
233 #[cfg(feature = "mock")]
234 fn is_mock_connection(&self) -> bool {
235 matches!(
236 self,
237 DatabaseConnection {
238 inner: DatabaseConnectionType::MockDatabaseConnection(_),
239 ..
240 }
241 )
242 }
243}
244
245impl StreamTrait for DatabaseConnection {
246 type Stream<'a> = crate::QueryStream;
247
248 fn get_database_backend(&self) -> DbBackend {
249 self.get_database_backend()
250 }
251
252 #[instrument(level = "trace")]
253 #[allow(unused_variables)]
254 fn stream_raw<'a>(&'a self, stmt: Statement) -> Result<Self::Stream<'a>, DbErr> {
255 ({
256 match &self.inner {
257 #[cfg(feature = "sqlx-mysql")]
258 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.stream(stmt),
259 #[cfg(feature = "sqlx-postgres")]
260 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.stream(stmt),
261 #[cfg(feature = "sqlx-sqlite")]
262 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.stream(stmt),
263 #[cfg(feature = "rusqlite")]
264 DatabaseConnectionType::RusqliteSharedConnection(conn) => conn.stream(stmt),
265 #[cfg(feature = "mock")]
266 DatabaseConnectionType::MockDatabaseConnection(conn) => {
267 Ok(crate::QueryStream::from((Arc::clone(conn), stmt, None)))
268 }
269 #[cfg(feature = "proxy")]
270 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
271 Ok(crate::QueryStream::from((Arc::clone(conn), stmt, None)))
272 }
273 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
274 }
275 })
276 }
277}
278
279impl TransactionTrait for DatabaseConnection {
280 type Transaction = DatabaseTransaction;
281
282 #[instrument(level = "trace")]
283 fn begin(&self) -> Result<DatabaseTransaction, DbErr> {
284 match &self.inner {
285 #[cfg(feature = "sqlx-mysql")]
286 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.begin(None, None),
287 #[cfg(feature = "sqlx-postgres")]
288 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.begin(None, None),
289 #[cfg(feature = "sqlx-sqlite")]
290 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.begin(None, None),
291 #[cfg(feature = "rusqlite")]
292 DatabaseConnectionType::RusqliteSharedConnection(conn) => conn.begin(None, None),
293 #[cfg(feature = "mock")]
294 DatabaseConnectionType::MockDatabaseConnection(conn) => {
295 DatabaseTransaction::new_mock(Arc::clone(conn), None)
296 }
297 #[cfg(feature = "proxy")]
298 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
299 DatabaseTransaction::new_proxy(conn.clone(), None)
300 }
301 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
302 }
303 }
304
305 #[instrument(level = "trace")]
306 fn begin_with_config(
307 &self,
308 _isolation_level: Option<IsolationLevel>,
309 _access_mode: Option<AccessMode>,
310 ) -> Result<DatabaseTransaction, DbErr> {
311 match &self.inner {
312 #[cfg(feature = "sqlx-mysql")]
313 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
314 conn.begin(_isolation_level, _access_mode)
315 }
316 #[cfg(feature = "sqlx-postgres")]
317 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
318 conn.begin(_isolation_level, _access_mode)
319 }
320 #[cfg(feature = "sqlx-sqlite")]
321 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
322 conn.begin(_isolation_level, _access_mode)
323 }
324 #[cfg(feature = "rusqlite")]
325 DatabaseConnectionType::RusqliteSharedConnection(conn) => {
326 conn.begin(_isolation_level, _access_mode)
327 }
328 #[cfg(feature = "mock")]
329 DatabaseConnectionType::MockDatabaseConnection(conn) => {
330 DatabaseTransaction::new_mock(Arc::clone(conn), None)
331 }
332 #[cfg(feature = "proxy")]
333 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
334 DatabaseTransaction::new_proxy(conn.clone(), None)
335 }
336 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
337 }
338 }
339
340 #[instrument(level = "trace", skip(_callback))]
343 fn transaction<F, T, E>(&self, _callback: F) -> Result<T, TransactionError<E>>
344 where
345 F: for<'c> FnOnce(&'c DatabaseTransaction) -> Result<T, E>,
346 E: std::fmt::Display + std::fmt::Debug,
347 {
348 match &self.inner {
349 #[cfg(feature = "sqlx-mysql")]
350 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
351 conn.transaction(_callback, None, None)
352 }
353 #[cfg(feature = "sqlx-postgres")]
354 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
355 conn.transaction(_callback, None, None)
356 }
357 #[cfg(feature = "sqlx-sqlite")]
358 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
359 conn.transaction(_callback, None, None)
360 }
361 #[cfg(feature = "rusqlite")]
362 DatabaseConnectionType::RusqliteSharedConnection(conn) => {
363 conn.transaction(_callback, None, None)
364 }
365 #[cfg(feature = "mock")]
366 DatabaseConnectionType::MockDatabaseConnection(conn) => {
367 let transaction = DatabaseTransaction::new_mock(Arc::clone(conn), None)
368 .map_err(TransactionError::Connection)?;
369 transaction.run(_callback)
370 }
371 #[cfg(feature = "proxy")]
372 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
373 let transaction = DatabaseTransaction::new_proxy(conn.clone(), None)
374 .map_err(TransactionError::Connection)?;
375 transaction.run(_callback)
376 }
377 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected").into()),
378 }
379 }
380
381 #[instrument(level = "trace", skip(_callback))]
384 fn transaction_with_config<F, T, E>(
385 &self,
386 _callback: F,
387 _isolation_level: Option<IsolationLevel>,
388 _access_mode: Option<AccessMode>,
389 ) -> Result<T, TransactionError<E>>
390 where
391 F: for<'c> FnOnce(&'c DatabaseTransaction) -> Result<T, E>,
392 E: std::fmt::Display + std::fmt::Debug,
393 {
394 match &self.inner {
395 #[cfg(feature = "sqlx-mysql")]
396 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
397 conn.transaction(_callback, _isolation_level, _access_mode)
398 }
399 #[cfg(feature = "sqlx-postgres")]
400 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
401 conn.transaction(_callback, _isolation_level, _access_mode)
402 }
403 #[cfg(feature = "sqlx-sqlite")]
404 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
405 conn.transaction(_callback, _isolation_level, _access_mode)
406 }
407 #[cfg(feature = "rusqlite")]
408 DatabaseConnectionType::RusqliteSharedConnection(conn) => {
409 conn.transaction(_callback, _isolation_level, _access_mode)
410 }
411 #[cfg(feature = "mock")]
412 DatabaseConnectionType::MockDatabaseConnection(conn) => {
413 let transaction = DatabaseTransaction::new_mock(Arc::clone(conn), None)
414 .map_err(TransactionError::Connection)?;
415 transaction.run(_callback)
416 }
417 #[cfg(feature = "proxy")]
418 DatabaseConnectionType::ProxyDatabaseConnection(conn) => {
419 let transaction = DatabaseTransaction::new_proxy(conn.clone(), None)
420 .map_err(TransactionError::Connection)?;
421 transaction.run(_callback)
422 }
423 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected").into()),
424 }
425 }
426}
427
428#[cfg(feature = "mock")]
429impl DatabaseConnection {
430 pub fn as_mock_connection(&self) -> &crate::MockDatabaseConnection {
436 match &self.inner {
437 DatabaseConnectionType::MockDatabaseConnection(mock_conn) => mock_conn,
438 _ => panic!("Not mock connection"),
439 }
440 }
441
442 pub fn into_transaction_log(self) -> Vec<crate::Transaction> {
448 let mut mocker = self
449 .as_mock_connection()
450 .get_mocker_mutex()
451 .lock()
452 .expect("Fail to acquire mocker");
453 mocker.drain_transaction_log()
454 }
455}
456
457#[cfg(feature = "proxy")]
458impl DatabaseConnection {
459 pub fn as_proxy_connection(&self) -> &crate::ProxyDatabaseConnection {
465 match &self.inner {
466 DatabaseConnectionType::ProxyDatabaseConnection(proxy_conn) => proxy_conn,
467 _ => panic!("Not proxy connection"),
468 }
469 }
470}
471
472#[cfg(feature = "rbac")]
473impl DatabaseConnection {
474 pub fn load_rbac(&self) -> Result<(), DbErr> {
477 self.load_rbac_from(self)
478 }
479
480 pub fn load_rbac_from(&self, db: &DbConn) -> Result<(), DbErr> {
483 let engine = crate::rbac::RbacEngine::load_from(db)?;
484 self.rbac.replace(engine);
485 Ok(())
486 }
487
488 pub fn replace_rbac(&self, engine: crate::rbac::RbacEngine) {
490 self.rbac.replace(engine);
491 }
492
493 pub fn restricted_for(
495 &self,
496 user_id: crate::rbac::RbacUserId,
497 ) -> Result<crate::RestrictedConnection, DbErr> {
498 if self.rbac.is_some() {
499 Ok(crate::RestrictedConnection {
500 user_id,
501 conn: self.clone(),
502 })
503 } else {
504 Err(DbErr::RbacError("engine not set up".into()))
505 }
506 }
507}
508
509impl DatabaseConnection {
510 pub fn get_database_backend(&self) -> DbBackend {
516 match &self.inner {
517 #[cfg(feature = "sqlx-mysql")]
518 DatabaseConnectionType::SqlxMySqlPoolConnection(_) => DbBackend::MySql,
519 #[cfg(feature = "sqlx-postgres")]
520 DatabaseConnectionType::SqlxPostgresPoolConnection(_) => DbBackend::Postgres,
521 #[cfg(feature = "sqlx-sqlite")]
522 DatabaseConnectionType::SqlxSqlitePoolConnection(_) => DbBackend::Sqlite,
523 #[cfg(feature = "rusqlite")]
524 DatabaseConnectionType::RusqliteSharedConnection(_) => DbBackend::Sqlite,
525 #[cfg(feature = "mock")]
526 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.get_database_backend(),
527 #[cfg(feature = "proxy")]
528 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.get_database_backend(),
529 DatabaseConnectionType::Disconnected => panic!("Disconnected"),
530 }
531 }
532
533 pub fn get_schema_builder(&self) -> SchemaBuilder {
535 Schema::new(self.get_database_backend()).builder()
536 }
537
538 #[cfg(feature = "entity-registry")]
539 #[cfg_attr(docsrs, doc(cfg(feature = "entity-registry")))]
540 pub fn get_schema_registry(&self, prefix: &str) -> SchemaBuilder {
542 let schema = Schema::new(self.get_database_backend());
543 crate::EntityRegistry::build_schema(schema, prefix)
544 }
545
546 pub fn set_metric_callback<F>(&mut self, _callback: F)
548 where
549 F: Fn(&crate::metric::Info<'_>) + 'static,
550 {
551 match &mut self.inner {
552 #[cfg(feature = "sqlx-mysql")]
553 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => {
554 conn.set_metric_callback(_callback)
555 }
556 #[cfg(feature = "sqlx-postgres")]
557 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => {
558 conn.set_metric_callback(_callback)
559 }
560 #[cfg(feature = "sqlx-sqlite")]
561 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => {
562 conn.set_metric_callback(_callback)
563 }
564 #[cfg(feature = "rusqlite")]
565 DatabaseConnectionType::RusqliteSharedConnection(conn) => {
566 conn.set_metric_callback(_callback)
567 }
568 _ => {}
569 }
570 }
571
572 pub fn ping(&self) -> Result<(), DbErr> {
574 match &self.inner {
575 #[cfg(feature = "sqlx-mysql")]
576 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.ping(),
577 #[cfg(feature = "sqlx-postgres")]
578 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.ping(),
579 #[cfg(feature = "sqlx-sqlite")]
580 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.ping(),
581 #[cfg(feature = "rusqlite")]
582 DatabaseConnectionType::RusqliteSharedConnection(conn) => conn.ping(),
583 #[cfg(feature = "mock")]
584 DatabaseConnectionType::MockDatabaseConnection(conn) => conn.ping(),
585 #[cfg(feature = "proxy")]
586 DatabaseConnectionType::ProxyDatabaseConnection(conn) => conn.ping(),
587 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
588 }
589 }
590
591 pub fn close(self) -> Result<(), DbErr> {
594 self.close_by_ref()
595 }
596
597 pub fn close_by_ref(&self) -> Result<(), DbErr> {
599 match &self.inner {
600 #[cfg(feature = "sqlx-mysql")]
601 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => conn.close_by_ref(),
602 #[cfg(feature = "sqlx-postgres")]
603 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => conn.close_by_ref(),
604 #[cfg(feature = "sqlx-sqlite")]
605 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => conn.close_by_ref(),
606 #[cfg(feature = "rusqlite")]
607 DatabaseConnectionType::RusqliteSharedConnection(conn) => conn.close_by_ref(),
608 #[cfg(feature = "mock")]
609 DatabaseConnectionType::MockDatabaseConnection(_) => {
610 Ok(())
612 }
613 #[cfg(feature = "proxy")]
614 DatabaseConnectionType::ProxyDatabaseConnection(_) => {
615 Ok(())
617 }
618 DatabaseConnectionType::Disconnected => Err(conn_err("Disconnected")),
619 }
620 }
621}
622
623impl DatabaseConnection {
624 #[cfg(feature = "sqlx-mysql")]
630 pub fn get_mysql_connection_pool(&self) -> &sqlx::MySqlPool {
631 match &self.inner {
632 DatabaseConnectionType::SqlxMySqlPoolConnection(conn) => &conn.pool,
633 _ => panic!("Not MySQL Connection"),
634 }
635 }
636
637 #[cfg(feature = "sqlx-postgres")]
643 pub fn get_postgres_connection_pool(&self) -> &sqlx::PgPool {
644 match &self.inner {
645 DatabaseConnectionType::SqlxPostgresPoolConnection(conn) => &conn.pool,
646 _ => panic!("Not Postgres Connection"),
647 }
648 }
649
650 #[cfg(feature = "sqlx-sqlite")]
656 pub fn get_sqlite_connection_pool(&self) -> &sqlx::SqlitePool {
657 match &self.inner {
658 DatabaseConnectionType::SqlxSqlitePoolConnection(conn) => &conn.pool,
659 _ => panic!("Not SQLite Connection"),
660 }
661 }
662}
663
664impl DbBackend {
665 pub fn is_prefix_of(self, base_url: &str) -> bool {
672 let base_url_parsed = Url::parse(base_url).expect("Fail to parse database URL");
673 match self {
674 Self::Postgres => {
675 base_url_parsed.scheme() == "postgres" || base_url_parsed.scheme() == "postgresql"
676 }
677 Self::MySql => base_url_parsed.scheme() == "mysql",
678 Self::Sqlite => base_url_parsed.scheme() == "sqlite",
679 }
680 }
681
682 pub fn build<S>(&self, statement: &S) -> Statement
684 where
685 S: StatementBuilder,
686 {
687 statement.build(self)
688 }
689
690 pub fn support_returning(&self) -> bool {
692 match self {
693 Self::Postgres => true,
694 Self::Sqlite if cfg!(feature = "sqlite-use-returning-for-3_35") => true,
695 Self::MySql if cfg!(feature = "mariadb-use-returning") => true,
696 _ => false,
697 }
698 }
699
700 pub fn boolean_value(&self, boolean: bool) -> sea_query::Value {
702 match self {
703 Self::MySql | Self::Postgres | Self::Sqlite => boolean.into(),
704 }
705 }
706
707 pub fn as_str(&self) -> &'static str {
709 match self {
710 DatabaseBackend::MySql => "MySql",
711 DatabaseBackend::Postgres => "Postgres",
712 DatabaseBackend::Sqlite => "Sqlite",
713 }
714 }
715}
716
717#[cfg(test)]
718mod tests {
719 use crate::DatabaseConnection;
720
721 #[cfg(not(feature = "sync"))]
722 #[test]
723 fn assert_database_connection_traits() {
724 fn assert_send_sync<T: Send>() {}
725
726 assert_send_sync::<DatabaseConnection>();
727 }
728}