diff --git a/src/driver/mock.rs b/src/driver/mock.rs index ad0c35cf..3f271759 100644 --- a/src/driver/mock.rs +++ b/src/driver/mock.rs @@ -12,32 +12,43 @@ use std::{ }, }; +/// Defines a database driver for the [MockDatabase] #[derive(Debug)] pub struct MockDatabaseConnector; +/// Defines a connection for the [MockDatabase] #[derive(Debug)] pub struct MockDatabaseConnection { counter: AtomicUsize, mocker: Mutex>, } +/// A set of constraints for any type wanting to perform operations on the [MockDatabase] pub trait MockDatabaseTrait: Send + Debug { + /// Execute a statement in the [MockDatabase] fn execute(&mut self, counter: usize, stmt: Statement) -> Result; + /// Execute a SQL query in the [MockDatabase] fn query(&mut self, counter: usize, stmt: Statement) -> Result, DbErr>; + /// Create a transaction that can be committed atomically fn begin(&mut self); + /// Commit a successful transaction atomically into the [MockDatabase] fn commit(&mut self); + /// Roll back a transaction since errors were encountered fn rollback(&mut self); + /// Get all logs from a [MockDatabase] and return a [Transaction] fn drain_transaction_log(&mut self) -> Vec; + /// Get the backend being used in the [MockDatabase] fn get_database_backend(&self) -> DbBackend; } impl MockDatabaseConnector { + /// Check if the database URI given and the [DatabaseBackend](crate::DatabaseBackend) selected are the same #[allow(unused_variables)] pub fn accepts(string: &str) -> bool { #[cfg(feature = "sqlx-mysql")] @@ -55,6 +66,7 @@ impl MockDatabaseConnector { false } + /// Cpnnect to the [MockDatabase] #[allow(unused_variables)] pub async fn connect(string: &str) -> Result { macro_rules! connect_mock_db { @@ -82,6 +94,7 @@ impl MockDatabaseConnector { } impl MockDatabaseConnection { + /// Create a connection to the [MockDatabase] pub fn new(m: M) -> Self where M: MockDatabaseTrait, @@ -96,16 +109,19 @@ impl MockDatabaseConnection { &self.mocker } + /// Get the [DatabaseBackend](crate::DatabaseBackend) being used by the [MockDatabase] pub fn get_database_backend(&self) -> DbBackend { self.mocker.lock().unwrap().get_database_backend() } + /// Execute the SQL statement in the [MockDatabase] pub fn execute(&self, statement: Statement) -> Result { debug_print!("{}", statement); let counter = self.counter.fetch_add(1, Ordering::SeqCst); self.mocker.lock().unwrap().execute(counter, statement) } + /// Return one [QueryResult] if the query was successful pub fn query_one(&self, statement: Statement) -> Result, DbErr> { debug_print!("{}", statement); let counter = self.counter.fetch_add(1, Ordering::SeqCst); @@ -113,12 +129,14 @@ impl MockDatabaseConnection { Ok(result.into_iter().next()) } + /// Return all [QueryResult]s if the query was successful pub fn query_all(&self, statement: Statement) -> Result, DbErr> { debug_print!("{}", statement); let counter = self.counter.fetch_add(1, Ordering::SeqCst); self.mocker.lock().unwrap().query(counter, statement) } + /// Return [QueryResult]s from a multi-query operation pub fn fetch( &self, statement: &Statement, @@ -129,14 +147,17 @@ impl MockDatabaseConnection { } } + /// Create a statement block of SQL statements that execute together. pub fn begin(&self) { self.mocker.lock().unwrap().begin() } + /// Commit a transaction atomically to the database pub fn commit(&self) { self.mocker.lock().unwrap().commit() } + /// Roll back a faulty transaction pub fn rollback(&self) { self.mocker.lock().unwrap().rollback() } diff --git a/src/driver/sqlx_common.rs b/src/driver/sqlx_common.rs index 5b1f7b35..5e035c9c 100644 --- a/src/driver/sqlx_common.rs +++ b/src/driver/sqlx_common.rs @@ -1,9 +1,11 @@ use crate::DbErr; +/// Converts an [sqlx::error] execution error to a [DbErr] pub fn sqlx_error_to_exec_err(err: sqlx::Error) -> DbErr { DbErr::Exec(err.to_string()) } +/// Converts an [sqlx::error] query error to a [DbErr] pub fn sqlx_error_to_query_err(err: sqlx::Error) -> DbErr { DbErr::Query(err.to_string()) } diff --git a/src/driver/sqlx_mysql.rs b/src/driver/sqlx_mysql.rs index 895707d1..a861b8df 100644 --- a/src/driver/sqlx_mysql.rs +++ b/src/driver/sqlx_mysql.rs @@ -15,19 +15,23 @@ use crate::{ use super::sqlx_common::*; +/// Defines the [sqlx::mysql] connector #[derive(Debug)] pub struct SqlxMySqlConnector; +/// Defines a sqlx MySQL pool #[derive(Debug, Clone)] pub struct SqlxMySqlPoolConnection { pool: MySqlPool, } impl SqlxMySqlConnector { + /// Check if the URI provided corresponds to `mysql://` for a MySQL database pub fn accepts(string: &str) -> bool { string.starts_with("mysql://") && string.parse::().is_ok() } + /// Add configuration options for the MySQL database pub async fn connect(options: ConnectOptions) -> Result { let mut opt = options .url @@ -48,12 +52,14 @@ impl SqlxMySqlConnector { } impl SqlxMySqlConnector { + /// Instantiate a sqlx pool connection to a [DatabaseConnection] pub fn from_sqlx_mysql_pool(pool: MySqlPool) -> DatabaseConnection { DatabaseConnection::SqlxMySqlPoolConnection(SqlxMySqlPoolConnection { pool }) } } impl SqlxMySqlPoolConnection { + /// Execute a [Statement] on a MySQL backend pub async fn execute(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -70,6 +76,7 @@ impl SqlxMySqlPoolConnection { } } + /// Get one result from a SQL query. Returns [Option::None] if no match was found pub async fn query_one(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); @@ -89,6 +96,7 @@ impl SqlxMySqlPoolConnection { } } + /// Get the results of a query returning them as a Vec<[QueryResult]> pub async fn query_all(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); @@ -105,6 +113,7 @@ impl SqlxMySqlPoolConnection { } } + /// Stream the results of executing a SQL query pub async fn stream(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -117,6 +126,7 @@ impl SqlxMySqlPoolConnection { } } + /// Bundle a set of SQL statements that execute together. pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { DatabaseTransaction::new_mysql(conn).await @@ -127,6 +137,7 @@ impl SqlxMySqlPoolConnection { } } + /// Create a MySQL transaction pub async fn transaction(&self, callback: F) -> Result> where F: for<'b> FnOnce( diff --git a/src/driver/sqlx_postgres.rs b/src/driver/sqlx_postgres.rs index a9f138a4..84645a58 100644 --- a/src/driver/sqlx_postgres.rs +++ b/src/driver/sqlx_postgres.rs @@ -15,19 +15,23 @@ use crate::{ use super::sqlx_common::*; +/// Defines the [sqlx::postgres] connector #[derive(Debug)] pub struct SqlxPostgresConnector; +/// Defines a sqlx PostgreSQL pool #[derive(Debug, Clone)] pub struct SqlxPostgresPoolConnection { pool: PgPool, } impl SqlxPostgresConnector { + /// Check if the URI provided corresponds to `postgres://` for a PostgreSQL database pub fn accepts(string: &str) -> bool { string.starts_with("postgres://") && string.parse::().is_ok() } + /// Add configuration options for the MySQL database pub async fn connect(options: ConnectOptions) -> Result { let mut opt = options .url @@ -48,12 +52,14 @@ impl SqlxPostgresConnector { } impl SqlxPostgresConnector { + /// Instantiate a sqlx pool connection to a [DatabaseConnection] pub fn from_sqlx_postgres_pool(pool: PgPool) -> DatabaseConnection { DatabaseConnection::SqlxPostgresPoolConnection(SqlxPostgresPoolConnection { pool }) } } impl SqlxPostgresPoolConnection { + /// Execute a [Statement] on a PostgreSQL backend pub async fn execute(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -70,6 +76,7 @@ impl SqlxPostgresPoolConnection { } } + /// Get one result from a SQL query. Returns [Option::None] if no match was found pub async fn query_one(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); @@ -89,6 +96,7 @@ impl SqlxPostgresPoolConnection { } } + /// Get the results of a query returning them as a Vec<[QueryResult]> pub async fn query_all(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); @@ -105,6 +113,7 @@ impl SqlxPostgresPoolConnection { } } + /// Stream the results of executing a SQL query pub async fn stream(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -117,6 +126,7 @@ impl SqlxPostgresPoolConnection { } } + /// Bundle a set of SQL statements that execute together. pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { DatabaseTransaction::new_postgres(conn).await @@ -127,6 +137,7 @@ impl SqlxPostgresPoolConnection { } } + /// Create a PostgreSQL transaction pub async fn transaction(&self, callback: F) -> Result> where F: for<'b> FnOnce( diff --git a/src/driver/sqlx_sqlite.rs b/src/driver/sqlx_sqlite.rs index 2001fac1..4e95bbaa 100644 --- a/src/driver/sqlx_sqlite.rs +++ b/src/driver/sqlx_sqlite.rs @@ -15,19 +15,23 @@ use crate::{ use super::sqlx_common::*; +/// Defines the [sqlx::sqlite] connector #[derive(Debug)] pub struct SqlxSqliteConnector; +/// Defines a sqlx SQLite pool #[derive(Debug, Clone)] pub struct SqlxSqlitePoolConnection { pool: SqlitePool, } impl SqlxSqliteConnector { + /// Check if the URI provided corresponds to `sqlite:` for a SQLite database pub fn accepts(string: &str) -> bool { string.starts_with("sqlite:") && string.parse::().is_ok() } + /// Add configuration options for the SQLite database pub async fn connect(options: ConnectOptions) -> Result { let mut opt = options .url @@ -53,12 +57,14 @@ impl SqlxSqliteConnector { } impl SqlxSqliteConnector { + /// Instantiate a sqlx pool connection to a [DatabaseConnection] pub fn from_sqlx_sqlite_pool(pool: SqlitePool) -> DatabaseConnection { DatabaseConnection::SqlxSqlitePoolConnection(SqlxSqlitePoolConnection { pool }) } } impl SqlxSqlitePoolConnection { + /// Execute a [Statement] on a SQLite backend pub async fn execute(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -75,6 +81,7 @@ impl SqlxSqlitePoolConnection { } } + /// Get one result from a SQL query. Returns [Option::None] if no match was found pub async fn query_one(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); @@ -94,6 +101,7 @@ impl SqlxSqlitePoolConnection { } } + /// Get the results of a query returning them as a Vec<[QueryResult]> pub async fn query_all(&self, stmt: Statement) -> Result, DbErr> { debug_print!("{}", stmt); @@ -110,6 +118,7 @@ impl SqlxSqlitePoolConnection { } } + /// Stream the results of executing a SQL query pub async fn stream(&self, stmt: Statement) -> Result { debug_print!("{}", stmt); @@ -122,6 +131,7 @@ impl SqlxSqlitePoolConnection { } } + /// Bundle a set of SQL statements that execute together. pub async fn begin(&self) -> Result { if let Ok(conn) = self.pool.acquire().await { DatabaseTransaction::new_sqlite(conn).await @@ -132,6 +142,7 @@ impl SqlxSqlitePoolConnection { } } + /// Create a MySQL transaction pub async fn transaction(&self, callback: F) -> Result> where F: for<'b> FnOnce(