Documetation for the database modeule
This commit is contained in:
parent
06aa9e3175
commit
91b9e542af
@ -4,23 +4,34 @@ use crate::{
|
|||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use std::{future::Future, pin::Pin};
|
use std::{future::Future, pin::Pin};
|
||||||
|
|
||||||
|
/// Creates constraints for any structure that wants to create a database connection
|
||||||
|
/// and execute SQL statements
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
pub trait ConnectionTrait<'a>: Sync {
|
pub trait ConnectionTrait<'a>: Sync {
|
||||||
|
/// Create a stream for the [QueryResult]
|
||||||
type Stream: Stream<Item = Result<QueryResult, DbErr>>;
|
type Stream: Stream<Item = Result<QueryResult, DbErr>>;
|
||||||
|
|
||||||
|
/// Fetch the database backend as specified in [DbBackend].
|
||||||
|
/// This depends on feature flags enabled.
|
||||||
fn get_database_backend(&self) -> DbBackend;
|
fn get_database_backend(&self) -> DbBackend;
|
||||||
|
|
||||||
|
/// Execute a [Statement]
|
||||||
async fn execute(&self, stmt: Statement) -> Result<ExecResult, DbErr>;
|
async fn execute(&self, stmt: Statement) -> Result<ExecResult, DbErr>;
|
||||||
|
|
||||||
|
/// Execute a [Statement] and return a query
|
||||||
async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr>;
|
async fn query_one(&self, stmt: Statement) -> Result<Option<QueryResult>, DbErr>;
|
||||||
|
|
||||||
|
/// Execute a [Statement] and return a collection Vec<[QueryResult]> on success
|
||||||
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, DbErr>;
|
async fn query_all(&self, stmt: Statement) -> Result<Vec<QueryResult>, DbErr>;
|
||||||
|
|
||||||
|
/// Execute a [Statement] and return a stream of results
|
||||||
fn stream(
|
fn stream(
|
||||||
&'a self,
|
&'a self,
|
||||||
stmt: Statement,
|
stmt: Statement,
|
||||||
) -> Pin<Box<dyn Future<Output = Result<Self::Stream, DbErr>> + 'a>>;
|
) -> Pin<Box<dyn Future<Output = Result<Self::Stream, DbErr>> + 'a>>;
|
||||||
|
|
||||||
|
/// Execute SQL `BEGIN` transaction.
|
||||||
|
/// Returns a Transaction that can be committed or rolled back
|
||||||
async fn begin(&self) -> Result<DatabaseTransaction, DbErr>;
|
async fn begin(&self) -> Result<DatabaseTransaction, DbErr>;
|
||||||
|
|
||||||
/// Execute the function inside a transaction.
|
/// Execute the function inside a transaction.
|
||||||
@ -34,6 +45,7 @@ pub trait ConnectionTrait<'a>: Sync {
|
|||||||
T: Send,
|
T: Send,
|
||||||
E: std::error::Error + Send;
|
E: std::error::Error + Send;
|
||||||
|
|
||||||
|
/// Check if the connection is a test connection for the Mock database
|
||||||
fn is_mock_connection(&self) -> bool {
|
fn is_mock_connection(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -12,30 +12,43 @@ use sqlx::pool::PoolConnection;
|
|||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
/// Handle a database connection depending on the backend
|
||||||
|
/// enabled by the feature flags. This creates a database pool.
|
||||||
#[cfg_attr(not(feature = "mock"), derive(Clone))]
|
#[cfg_attr(not(feature = "mock"), derive(Clone))]
|
||||||
pub enum DatabaseConnection {
|
pub enum DatabaseConnection {
|
||||||
|
/// Create a MYSQL database connection and pool
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
SqlxMySqlPoolConnection(crate::SqlxMySqlPoolConnection),
|
SqlxMySqlPoolConnection(crate::SqlxMySqlPoolConnection),
|
||||||
|
/// Create a PostgreSQL database connection and pool
|
||||||
#[cfg(feature = "sqlx-postgres")]
|
#[cfg(feature = "sqlx-postgres")]
|
||||||
SqlxPostgresPoolConnection(crate::SqlxPostgresPoolConnection),
|
SqlxPostgresPoolConnection(crate::SqlxPostgresPoolConnection),
|
||||||
|
/// Create a SQLite database connection and pool
|
||||||
#[cfg(feature = "sqlx-sqlite")]
|
#[cfg(feature = "sqlx-sqlite")]
|
||||||
SqlxSqlitePoolConnection(crate::SqlxSqlitePoolConnection),
|
SqlxSqlitePoolConnection(crate::SqlxSqlitePoolConnection),
|
||||||
|
/// Create a Mock database connection useful for testing
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
MockDatabaseConnection(Arc<crate::MockDatabaseConnection>),
|
MockDatabaseConnection(Arc<crate::MockDatabaseConnection>),
|
||||||
|
/// The connection to the database has been severed
|
||||||
Disconnected,
|
Disconnected,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The same as a [DatabaseConnection]
|
||||||
pub type DbConn = DatabaseConnection;
|
pub type DbConn = DatabaseConnection;
|
||||||
|
|
||||||
|
/// The type of database backend for real world databases.
|
||||||
|
/// This is enabled by feature flags as specified in the crate documentation
|
||||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||||
pub enum DatabaseBackend {
|
pub enum DatabaseBackend {
|
||||||
|
/// A MySQL backend
|
||||||
MySql,
|
MySql,
|
||||||
|
/// A PostgreSQL backend
|
||||||
Postgres,
|
Postgres,
|
||||||
|
/// A SQLite backend
|
||||||
Sqlite,
|
Sqlite,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The same as [DatabaseBackend] just shorter :)
|
||||||
pub type DbBackend = DatabaseBackend;
|
pub type DbBackend = DatabaseBackend;
|
||||||
|
|
||||||
pub(crate) enum InnerConnection {
|
pub(crate) enum InnerConnection {
|
||||||
#[cfg(feature = "sqlx-mysql")]
|
#[cfg(feature = "sqlx-mysql")]
|
||||||
MySql(PoolConnection<sqlx::MySql>),
|
MySql(PoolConnection<sqlx::MySql>),
|
||||||
@ -209,6 +222,7 @@ impl<'a> ConnectionTrait<'a> for DatabaseConnection {
|
|||||||
|
|
||||||
#[cfg(feature = "mock")]
|
#[cfg(feature = "mock")]
|
||||||
impl DatabaseConnection {
|
impl DatabaseConnection {
|
||||||
|
/// Generate a database connection for testing the Mock database
|
||||||
pub fn as_mock_connection(&self) -> &crate::MockDatabaseConnection {
|
pub fn as_mock_connection(&self) -> &crate::MockDatabaseConnection {
|
||||||
match self {
|
match self {
|
||||||
DatabaseConnection::MockDatabaseConnection(mock_conn) => mock_conn,
|
DatabaseConnection::MockDatabaseConnection(mock_conn) => mock_conn,
|
||||||
@ -216,6 +230,7 @@ impl DatabaseConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the transaction log as a collection Vec<[crate::Transaction]>
|
||||||
pub fn into_transaction_log(self) -> Vec<crate::Transaction> {
|
pub fn into_transaction_log(self) -> Vec<crate::Transaction> {
|
||||||
let mut mocker = self.as_mock_connection().get_mocker_mutex().lock().unwrap();
|
let mut mocker = self.as_mock_connection().get_mocker_mutex().lock().unwrap();
|
||||||
mocker.drain_transaction_log()
|
mocker.drain_transaction_log()
|
||||||
@ -223,6 +238,8 @@ impl DatabaseConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DbBackend {
|
impl DbBackend {
|
||||||
|
/// Check if the URI is the same as the specified database backend.
|
||||||
|
/// Returns true if they match.
|
||||||
pub fn is_prefix_of(self, base_url: &str) -> bool {
|
pub fn is_prefix_of(self, base_url: &str) -> bool {
|
||||||
let base_url_parsed = Url::parse(base_url).unwrap();
|
let base_url_parsed = Url::parse(base_url).unwrap();
|
||||||
match self {
|
match self {
|
||||||
@ -234,6 +251,7 @@ impl DbBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Build an SQL [Statement]
|
||||||
pub fn build<S>(&self, statement: &S) -> Statement
|
pub fn build<S>(&self, statement: &S) -> Statement
|
||||||
where
|
where
|
||||||
S: StatementBuilder,
|
S: StatementBuilder,
|
||||||
@ -241,6 +259,7 @@ impl DbBackend {
|
|||||||
statement.build(self)
|
statement.build(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A helper for building SQL queries
|
||||||
pub fn get_query_builder(&self) -> Box<dyn QueryBuilder> {
|
pub fn get_query_builder(&self) -> Box<dyn QueryBuilder> {
|
||||||
match self {
|
match self {
|
||||||
Self::MySql => Box::new(MysqlQueryBuilder),
|
Self::MySql => Box::new(MysqlQueryBuilder),
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
use sea_query::{Value, ValueType, Values};
|
use sea_query::{Value, ValueType, Values};
|
||||||
use std::{collections::BTreeMap, sync::Arc};
|
use std::{collections::BTreeMap, sync::Arc};
|
||||||
|
|
||||||
|
/// Defines a Mock database suitable for testing
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MockDatabase {
|
pub struct MockDatabase {
|
||||||
db_backend: DbBackend,
|
db_backend: DbBackend,
|
||||||
@ -15,33 +16,44 @@ pub struct MockDatabase {
|
|||||||
query_results: Vec<Vec<MockRow>>,
|
query_results: Vec<Vec<MockRow>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the results obtained from a [MockDatabase]
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct MockExecResult {
|
pub struct MockExecResult {
|
||||||
|
/// The last inserted id on auto-increment
|
||||||
pub last_insert_id: u64,
|
pub last_insert_id: u64,
|
||||||
|
/// The number of rows affected by the database operation
|
||||||
pub rows_affected: u64,
|
pub rows_affected: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines the structure of a test Row for the [MockDatabase]
|
||||||
|
/// which is just a [BTreeMap]<[String], [Value]>
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MockRow {
|
pub struct MockRow {
|
||||||
values: BTreeMap<String, Value>,
|
values: BTreeMap<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait to get a [MockRow] from a type useful for testing in the [MockDatabase]
|
||||||
pub trait IntoMockRow {
|
pub trait IntoMockRow {
|
||||||
|
/// The method to perform this operation
|
||||||
fn into_mock_row(self) -> MockRow;
|
fn into_mock_row(self) -> MockRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a transaction that is has not been committed
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct OpenTransaction {
|
pub struct OpenTransaction {
|
||||||
stmts: Vec<Statement>,
|
stmts: Vec<Statement>,
|
||||||
transaction_depth: usize,
|
transaction_depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a database transaction as it holds a Vec<[Statement]>
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Transaction {
|
pub struct Transaction {
|
||||||
stmts: Vec<Statement>,
|
stmts: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MockDatabase {
|
impl MockDatabase {
|
||||||
|
/// Instantiate a mock database with a [DbBackend] to simulate real
|
||||||
|
/// world SQL databases
|
||||||
pub fn new(db_backend: DbBackend) -> Self {
|
pub fn new(db_backend: DbBackend) -> Self {
|
||||||
Self {
|
Self {
|
||||||
db_backend,
|
db_backend,
|
||||||
@ -52,15 +64,18 @@ impl MockDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a database connection
|
||||||
pub fn into_connection(self) -> DatabaseConnection {
|
pub fn into_connection(self) -> DatabaseConnection {
|
||||||
DatabaseConnection::MockDatabaseConnection(Arc::new(MockDatabaseConnection::new(self)))
|
DatabaseConnection::MockDatabaseConnection(Arc::new(MockDatabaseConnection::new(self)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add the [MockExecResult]s to the `exec_results` field for `Self`
|
||||||
pub fn append_exec_results(mut self, mut vec: Vec<MockExecResult>) -> Self {
|
pub fn append_exec_results(mut self, mut vec: Vec<MockExecResult>) -> Self {
|
||||||
self.exec_results.append(&mut vec);
|
self.exec_results.append(&mut vec);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add the [MockExecResult]s to the `exec_results` field for `Self`
|
||||||
pub fn append_query_results<T>(mut self, vec: Vec<Vec<T>>) -> Self
|
pub fn append_query_results<T>(mut self, vec: Vec<Vec<T>>) -> Self
|
||||||
where
|
where
|
||||||
T: IntoMockRow,
|
T: IntoMockRow,
|
||||||
@ -150,6 +165,7 @@ impl MockDatabaseTrait for MockDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl MockRow {
|
impl MockRow {
|
||||||
|
/// Try to get the values of a [MockRow] and fail gracefully on error
|
||||||
pub fn try_get<T>(&self, col: &str) -> Result<T, DbErr>
|
pub fn try_get<T>(&self, col: &str) -> Result<T, DbErr>
|
||||||
where
|
where
|
||||||
T: ValueType,
|
T: ValueType,
|
||||||
@ -157,6 +173,7 @@ impl MockRow {
|
|||||||
T::try_from(self.values.get(col).unwrap().clone()).map_err(|e| DbErr::Query(e.to_string()))
|
T::try_from(self.values.get(col).unwrap().clone()).map_err(|e| DbErr::Query(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator over the keys and values of a mock row
|
||||||
pub fn into_column_value_tuples(self) -> impl Iterator<Item = (String, Value)> {
|
pub fn into_column_value_tuples(self) -> impl Iterator<Item = (String, Value)> {
|
||||||
self.values.into_iter()
|
self.values.into_iter()
|
||||||
}
|
}
|
||||||
@ -190,6 +207,7 @@ impl IntoMockRow for BTreeMap<&str, Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
|
/// Get the [Value]s from s raw SQL statement depending on the [DatabaseBackend](crate::DatabaseBackend)
|
||||||
pub fn from_sql_and_values<I>(db_backend: DbBackend, sql: &str, values: I) -> Self
|
pub fn from_sql_and_values<I>(db_backend: DbBackend, sql: &str, values: I) -> Self
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = Value>,
|
I: IntoIterator<Item = Value>,
|
||||||
|
@ -18,20 +18,30 @@ pub use transaction::*;
|
|||||||
|
|
||||||
use crate::DbErr;
|
use crate::DbErr;
|
||||||
|
|
||||||
|
/// Defines a database
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Database;
|
pub struct Database;
|
||||||
|
|
||||||
|
/// Defines the configuration options of a database
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConnectOptions {
|
pub struct ConnectOptions {
|
||||||
|
/// The URI of the database
|
||||||
pub(crate) url: String,
|
pub(crate) url: String,
|
||||||
|
/// Maximum number of connections for a pool
|
||||||
pub(crate) max_connections: Option<u32>,
|
pub(crate) max_connections: Option<u32>,
|
||||||
|
/// Minimum number of connections for a pool
|
||||||
pub(crate) min_connections: Option<u32>,
|
pub(crate) min_connections: Option<u32>,
|
||||||
|
/// The connection timeout for a packet connection
|
||||||
pub(crate) connect_timeout: Option<Duration>,
|
pub(crate) connect_timeout: Option<Duration>,
|
||||||
|
/// Maximum idle time for a particular connection to prevent
|
||||||
|
/// network resource exhaustion
|
||||||
pub(crate) idle_timeout: Option<Duration>,
|
pub(crate) idle_timeout: Option<Duration>,
|
||||||
|
/// Enables or disables logging
|
||||||
pub(crate) sqlx_logging: bool,
|
pub(crate) sqlx_logging: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Database {
|
impl Database {
|
||||||
|
/// Method to create a [DatabaseConnection] on a database
|
||||||
pub async fn connect<C>(opt: C) -> Result<DatabaseConnection, DbErr>
|
pub async fn connect<C>(opt: C) -> Result<DatabaseConnection, DbErr>
|
||||||
where
|
where
|
||||||
C: Into<ConnectOptions>,
|
C: Into<ConnectOptions>,
|
||||||
@ -80,6 +90,7 @@ impl From<String> for ConnectOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ConnectOptions {
|
impl ConnectOptions {
|
||||||
|
/// Create new [ConnectOptions] for a [Database] by passing in a URI string
|
||||||
pub fn new(url: String) -> Self {
|
pub fn new(url: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
url,
|
url,
|
||||||
|
@ -3,18 +3,25 @@ use sea_query::{inject_parameters, MysqlQueryBuilder, PostgresQueryBuilder, Sqli
|
|||||||
pub use sea_query::{Value, Values};
|
pub use sea_query::{Value, Values};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
/// Defines an SQL statement
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Statement {
|
pub struct Statement {
|
||||||
|
/// The SQL query
|
||||||
pub sql: String,
|
pub sql: String,
|
||||||
|
/// The values for the SQL statement
|
||||||
pub values: Option<Values>,
|
pub values: Option<Values>,
|
||||||
|
/// The database backend to use
|
||||||
pub db_backend: DbBackend,
|
pub db_backend: DbBackend,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constraints for building a [Statement]
|
||||||
pub trait StatementBuilder {
|
pub trait StatementBuilder {
|
||||||
|
/// Method to call in order to build a [Statement]
|
||||||
fn build(&self, db_backend: &DbBackend) -> Statement;
|
fn build(&self, db_backend: &DbBackend) -> Statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Statement {
|
impl Statement {
|
||||||
|
/// Create a [Statement] from a [crate::DatabaseBackend] and a raw SQL statement
|
||||||
pub fn from_string(db_backend: DbBackend, stmt: String) -> Statement {
|
pub fn from_string(db_backend: DbBackend, stmt: String) -> Statement {
|
||||||
Statement {
|
Statement {
|
||||||
sql: stmt,
|
sql: stmt,
|
||||||
@ -23,6 +30,8 @@ impl Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a SQL statement from a [crate::DatabaseBackend], a
|
||||||
|
/// raw SQL statement and defined values
|
||||||
pub fn from_sql_and_values<I>(db_backend: DbBackend, sql: &str, values: I) -> Self
|
pub fn from_sql_and_values<I>(db_backend: DbBackend, sql: &str, values: I) -> Self
|
||||||
where
|
where
|
||||||
I: IntoIterator<Item = Value>,
|
I: IntoIterator<Item = Value>,
|
||||||
|
@ -10,6 +10,8 @@ use sqlx::{pool::PoolConnection, TransactionManager};
|
|||||||
use std::{future::Future, pin::Pin, sync::Arc};
|
use std::{future::Future, pin::Pin, sync::Arc};
|
||||||
|
|
||||||
// a Transaction is just a sugar for a connection where START TRANSACTION has been executed
|
// a Transaction is just a sugar for a connection where START TRANSACTION has been executed
|
||||||
|
/// Defines a database transaction, whether it is an open transaction and the type of
|
||||||
|
/// backend to use
|
||||||
pub struct DatabaseTransaction {
|
pub struct DatabaseTransaction {
|
||||||
conn: Arc<Mutex<InnerConnection>>,
|
conn: Arc<Mutex<InnerConnection>>,
|
||||||
backend: DbBackend,
|
backend: DbBackend,
|
||||||
@ -100,6 +102,8 @@ impl DatabaseTransaction {
|
|||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs a transaction to completion returning an rolling back the transaction on
|
||||||
|
/// encountering an error if it fails
|
||||||
pub(crate) async fn run<F, T, E>(self, callback: F) -> Result<T, TransactionError<E>>
|
pub(crate) async fn run<F, T, E>(self, callback: F) -> Result<T, TransactionError<E>>
|
||||||
where
|
where
|
||||||
F: for<'b> FnOnce(
|
F: for<'b> FnOnce(
|
||||||
@ -120,6 +124,7 @@ impl DatabaseTransaction {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Commit a transaction atomically
|
||||||
pub async fn commit(mut self) -> Result<(), DbErr> {
|
pub async fn commit(mut self) -> Result<(), DbErr> {
|
||||||
self.open = false;
|
self.open = false;
|
||||||
match *self.conn.lock().await {
|
match *self.conn.lock().await {
|
||||||
@ -149,6 +154,7 @@ impl DatabaseTransaction {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// rolls back a transaction in case error are encountered during the operation
|
||||||
pub async fn rollback(mut self) -> Result<(), DbErr> {
|
pub async fn rollback(mut self) -> Result<(), DbErr> {
|
||||||
self.open = false;
|
self.open = false;
|
||||||
match *self.conn.lock().await {
|
match *self.conn.lock().await {
|
||||||
@ -343,12 +349,15 @@ impl<'a> ConnectionTrait<'a> for DatabaseTransaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines errors for handling transaction failures
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum TransactionError<E>
|
pub enum TransactionError<E>
|
||||||
where
|
where
|
||||||
E: std::error::Error,
|
E: std::error::Error,
|
||||||
{
|
{
|
||||||
|
/// A Database connection error
|
||||||
Connection(DbErr),
|
Connection(DbErr),
|
||||||
|
/// An error occurring when doing database transactions
|
||||||
Transaction(E),
|
Transaction(E),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user