1use std::{future::Future, pin::Pin};
2
3use futures_util::Stream;
4
5use crate::{
6 DbBackend, DbErr, ExecResult, QueryResult, Statement, StatementBuilder, TransactionError,
7};
8
9#[async_trait::async_trait]
12pub trait ConnectionTrait: Sync {
13 fn get_database_backend(&self) -> DbBackend;
15
16 async fn execute_raw(&self, stmt: Statement) -> Result<ExecResult, DbErr>;
18
19 async fn execute<S: StatementBuilder>(&self, stmt: &S) -> Result<ExecResult, DbErr> {
21 let db_backend = self.get_database_backend();
22 let stmt = db_backend.build(stmt);
23 self.execute_raw(stmt).await
24 }
25
26 async fn execute_unprepared(&self, sql: &str) -> Result<ExecResult, DbErr>;
28
29 async fn query_one_raw(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr>;
31
32 async fn query_one<S: StatementBuilder>(&self, stmt: &S) -> Result<Option<QueryResult>, DbErr> {
34 let db_backend = self.get_database_backend();
35 let stmt = db_backend.build(stmt);
36 self.query_one_raw(stmt).await
37 }
38
39 async fn query_all_raw(&self, stmt: Statement) -> Result<Vec<QueryResult>, DbErr>;
41
42 async fn query_all<S: StatementBuilder>(&self, stmt: &S) -> Result<Vec<QueryResult>, DbErr> {
44 let db_backend = self.get_database_backend();
45 let stmt = db_backend.build(stmt);
46 self.query_all_raw(stmt).await
47 }
48
49 fn support_returning(&self) -> bool {
51 let db_backend = self.get_database_backend();
52 db_backend.support_returning()
53 }
54
55 fn is_mock_connection(&self) -> bool {
57 false
58 }
59}
60
61pub trait StreamTrait: Send + Sync {
63 type Stream<'a>: Stream<Item = Result<QueryResult, DbErr>> + Send
65 where
66 Self: 'a;
67
68 fn get_database_backend(&self) -> DbBackend;
70
71 fn stream_raw<'a>(
73 &'a self,
74 stmt: Statement,
75 ) -> Pin<Box<dyn Future<Output = Result<Self::Stream<'a>, DbErr>> + 'a + Send>>;
76
77 fn stream<'a, S: StatementBuilder + Sync>(
79 &'a self,
80 stmt: &S,
81 ) -> Pin<Box<dyn Future<Output = Result<Self::Stream<'a>, DbErr>> + 'a + Send>> {
82 let db_backend = self.get_database_backend();
83 let stmt = db_backend.build(stmt);
84 self.stream_raw(stmt)
85 }
86}
87
88#[derive(Copy, Clone, Debug, PartialEq, Eq)]
89pub enum IsolationLevel {
91 RepeatableRead,
93 ReadCommitted,
95 ReadUncommitted,
97 Serializable,
99}
100
101impl std::fmt::Display for IsolationLevel {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 match self {
104 IsolationLevel::RepeatableRead => write!(f, "REPEATABLE READ"),
105 IsolationLevel::ReadCommitted => write!(f, "READ COMMITTED"),
106 IsolationLevel::ReadUncommitted => write!(f, "READ UNCOMMITTED"),
107 IsolationLevel::Serializable => write!(f, "SERIALIZABLE"),
108 }
109 }
110}
111
112#[derive(Copy, Clone, Debug, PartialEq, Eq)]
113pub enum AccessMode {
115 ReadOnly,
117 ReadWrite,
119}
120
121impl std::fmt::Display for AccessMode {
122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123 match self {
124 AccessMode::ReadOnly => write!(f, "READ ONLY"),
125 AccessMode::ReadWrite => write!(f, "READ WRITE"),
126 }
127 }
128}
129
130#[derive(Copy, Clone, Debug, PartialEq, Eq)]
131pub enum SqliteTransactionMode {
134 Deferred,
137 Immediate,
139 Exclusive,
143}
144
145impl SqliteTransactionMode {
146 pub fn sqlite_keyword(&self) -> &'static str {
148 match self {
149 SqliteTransactionMode::Deferred => "DEFERRED",
150 SqliteTransactionMode::Immediate => "IMMEDIATE",
151 SqliteTransactionMode::Exclusive => "EXCLUSIVE",
152 }
153 }
154}
155
156#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
158pub struct TransactionOptions {
159 pub isolation_level: Option<IsolationLevel>,
161 pub access_mode: Option<AccessMode>,
163 pub sqlite_transaction_mode: Option<SqliteTransactionMode>,
165}
166
167#[async_trait::async_trait]
169pub trait TransactionTrait {
170 type Transaction: ConnectionTrait + TransactionTrait + TransactionSession;
172
173 async fn begin(&self) -> Result<Self::Transaction, DbErr>;
176
177 async fn begin_with_config(
180 &self,
181 isolation_level: Option<IsolationLevel>,
182 access_mode: Option<AccessMode>,
183 ) -> Result<Self::Transaction, DbErr>;
184
185 async fn begin_with_options(
188 &self,
189 options: TransactionOptions,
190 ) -> Result<Self::Transaction, DbErr>;
191
192 async fn transaction<F, T, E>(&self, callback: F) -> Result<T, TransactionError<E>>
195 where
196 F: for<'c> FnOnce(
197 &'c Self::Transaction,
198 ) -> Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'c>>
199 + Send,
200 T: Send,
201 E: std::fmt::Display + std::fmt::Debug + Send;
202
203 async fn transaction_with_config<F, T, E>(
206 &self,
207 callback: F,
208 isolation_level: Option<IsolationLevel>,
209 access_mode: Option<AccessMode>,
210 ) -> Result<T, TransactionError<E>>
211 where
212 F: for<'c> FnOnce(
213 &'c Self::Transaction,
214 ) -> Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'c>>
215 + Send,
216 T: Send,
217 E: std::fmt::Display + std::fmt::Debug + Send;
218}
219
220#[async_trait::async_trait]
222pub trait TransactionSession {
223 async fn commit(self) -> Result<(), DbErr>;
225
226 async fn rollback(self) -> Result<(), DbErr>;
228}