1use crate::command_executor::CommandExecutor;
2use crate::prelude::*;
3use crate::sql_executor::SqlExecutor;
4use crate::transaction::Transaction;
5use crate::LunaOrmResult;
6use std::ops::{Deref, DerefMut};
7use tracing::debug;
8
9pub trait Database: CommandExecutor + SqlExecutor + std::fmt::Debug {
10 fn get_type(&self) -> &DatabaseType;
11
12 async fn transaction<'a>(&'a self) -> LunaOrmResult<Transaction<'a, Self::G>> {
13 let trx = self.get_pool()?.begin().await?;
14 let generator = self.get_generator();
15 let transaction = Transaction::new(trx, generator);
16 return Ok(transaction);
17 }
18
19 async fn remove<SE>(
20 &mut self,
21 primary: &dyn Primary,
22 selection: &dyn Selection,
23 ) -> LunaOrmResult<Option<SE>>
24 where
25 SE: SelectedEntity + Send + Unpin,
26 {
27 debug!(target: "luna_orm", command = "remove", primary = ?primary, selection = ?selection);
28 let mut trx = self.get_pool()?.begin().await?;
29 let selected_entity: Option<SE> = self.select(primary, selection).await?;
30 let sql = self.get_generator().get_delete_sql(primary);
31 debug!(target: "luna_orm", command = "remove", sql = sql);
32 let args = primary.any_arguments();
33 let result = sqlx::query_with(&sql, args).execute(&mut *trx).await?;
34 trx.commit().await?;
35
36 debug!(target: "luna_orm", command = "remove", result = ?result);
37 if result.rows_affected() > 0 {
38 return Ok(selected_entity);
39 } else {
40 return Ok(None);
41 }
42 }
43
44 async fn transact(&mut self, commands: &[WriteCommand]) -> LunaOrmResult<bool> {
45 debug!(target: "luna_orm", command = "transact", commands = ?commands);
46 let trx = self.get_pool()?.begin().await?;
47 for command in commands {
48 match command {
49 WriteCommand::Insert { entity } => {
50 self.insert(entity.as_ref()).await?;
51 }
52 WriteCommand::Upsert { entity } => {
53 self.upsert(entity.as_ref()).await?;
54 }
55 WriteCommand::Update { mutation, primary } => {
56 self.update(mutation.as_ref(), primary.as_ref()).await?;
57 }
58 WriteCommand::Change { mutation, location } => {
59 self.change(mutation.as_ref(), location.as_ref()).await?;
60 }
61 WriteCommand::Delete { primary } => {
62 self.delete(primary.as_ref()).await?;
63 }
64 WriteCommand::Purify { location } => {
65 self.purify(location.as_ref()).await?;
66 }
67 }
68 }
69 trx.commit().await?;
70 debug!(target: "luna_orm", command = "transact", result = true);
71 Ok(true)
72 }
73}
74
75#[derive(Debug, Clone)]
76pub enum DatabaseType {
77 SqliteLocal,
78 MySql,
79 PostgreSql,
80}
81
82#[derive(Debug, Clone)]
83pub struct DB<T: Database>(pub T);
84
85impl<T> Deref for DB<T>
86where
87 T: Database,
88{
89 type Target = T;
90 fn deref(&self) -> &Self::Target {
91 &self.0
92 }
93}
94
95impl<T> DerefMut for DB<T>
96where
97 T: Database,
98{
99 fn deref_mut(&mut self) -> &mut Self::Target {
100 &mut self.0
101 }
102}