diff --git a/sea-orm-codegen/tests/mod.rs b/sea-orm-codegen/tests/mod.rs index 12c18066..b06d561d 100644 --- a/sea-orm-codegen/tests/mod.rs +++ b/sea-orm-codegen/tests/mod.rs @@ -2,7 +2,7 @@ mod entity; use entity::*; -use sea_orm::{entity::*, error::*, MockDatabase, MockExecResult, Transaction}; +use sea_orm::{entity::*, error::*, MockDatabase, MockExecResult, Syntax, Transaction}; #[async_std::test] async fn test_insert() -> Result<(), DbErr> { @@ -11,7 +11,7 @@ async fn test_insert() -> Result<(), DbErr> { rows_affected: 1, }; - let db = MockDatabase::new() + let db = MockDatabase::new(Syntax::Postgres) .append_exec_results(vec![exec_result.clone()]) .into_connection(); @@ -27,6 +27,7 @@ async fn test_insert() -> Result<(), DbErr> { assert_eq!( db.into_transaction_log(), vec![Transaction::from_sql_and_values( + Syntax::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1)"#, vec!["Apple Pie".into()] )] @@ -42,7 +43,7 @@ async fn test_select() -> Result<(), DbErr> { filling_id: 3, }]; - let db = MockDatabase::new() + let db = MockDatabase::new(Syntax::Postgres) .append_query_results(vec![query_results.clone()]) .into_connection(); @@ -52,7 +53,9 @@ async fn test_select() -> Result<(), DbErr> { assert_eq!( db.into_transaction_log(), - vec![Transaction::from_sql_and_values([ + vec![Transaction::from_sql_and_values( + Syntax::Postgres, + [ r#"SELECT "cake_filling"."cake_id", "cake_filling"."filling_id" FROM "cake_filling""#, r#"WHERE "cake_filling"."cake_id" = $1 AND "cake_filling"."filling_id" = $2"#, ].join(" ").as_str(), @@ -70,7 +73,7 @@ async fn test_update() -> Result<(), DbErr> { rows_affected: 1, }; - let db = MockDatabase::new() + let db = MockDatabase::new(Syntax::Postgres) .append_exec_results(vec![exec_result.clone()]) .into_connection(); @@ -87,6 +90,7 @@ async fn test_update() -> Result<(), DbErr> { assert_eq!( db.into_transaction_log(), vec![Transaction::from_sql_and_values( + Syntax::Postgres, r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2"#, vec!["Orange".into(), 1i32.into()] )] @@ -102,7 +106,7 @@ async fn test_delete() -> Result<(), DbErr> { rows_affected: 1, }; - let db = MockDatabase::new() + let db = MockDatabase::new(Syntax::Postgres) .append_exec_results(vec![exec_result.clone()]) .into_connection(); @@ -118,6 +122,7 @@ async fn test_delete() -> Result<(), DbErr> { assert_eq!( db.into_transaction_log(), vec![Transaction::from_sql_and_values( + Syntax::Postgres, r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#, vec![3i32.into()] )] diff --git a/src/database/connection.rs b/src/database/connection.rs index 4f880b7f..bd6a6d44 100644 --- a/src/database/connection.rs +++ b/src/database/connection.rs @@ -60,7 +60,7 @@ impl DatabaseConnection { #[cfg(feature = "sqlx-sqlite")] DatabaseConnection::SqlxSqlitePoolConnection(_) => QueryBuilderBackend::Sqlite, #[cfg(feature = "mock")] - DatabaseConnection::MockDatabaseConnection(_) => QueryBuilderBackend::Postgres, + DatabaseConnection::MockDatabaseConnection(conn) => conn.get_query_builder_backend(), DatabaseConnection::Disconnected => panic!("Disconnected"), } } @@ -72,7 +72,7 @@ impl DatabaseConnection { #[cfg(feature = "sqlx-sqlite")] DatabaseConnection::SqlxSqlitePoolConnection(_) => SchemaBuilderBackend::Sqlite, #[cfg(feature = "mock")] - DatabaseConnection::MockDatabaseConnection(_) => SchemaBuilderBackend::Postgres, + DatabaseConnection::MockDatabaseConnection(conn) => conn.get_schema_builder_backend(), DatabaseConnection::Disconnected => panic!("Disconnected"), } } diff --git a/src/database/mock.rs b/src/database/mock.rs index ab002acb..6aa5f6e6 100644 --- a/src/database/mock.rs +++ b/src/database/mock.rs @@ -1,13 +1,14 @@ use crate::{ error::*, DatabaseConnection, EntityTrait, ExecResult, ExecResultHolder, Iden, Iterable, MockDatabaseConnection, MockDatabaseTrait, ModelTrait, QueryResult, QueryResultRow, Statement, - Transaction, + Syntax, Transaction, }; use sea_query::{Value, ValueType}; use std::collections::BTreeMap; -#[derive(Debug, Default)] +#[derive(Debug)] pub struct MockDatabase { + syntax: Syntax, transaction_log: Vec, exec_results: Vec, query_results: Vec>, @@ -42,8 +43,13 @@ where } impl MockDatabase { - pub fn new() -> Self { - Default::default() + pub fn new(syntax: Syntax) -> Self { + Self { + syntax, + transaction_log: Vec::new(), + exec_results: Vec::new(), + query_results: Vec::new(), + } } pub fn into_connection(self) -> DatabaseConnection { @@ -96,6 +102,10 @@ impl MockDatabaseTrait for MockDatabase { fn drain_transaction_log(&mut self) -> Vec { std::mem::take(&mut self.transaction_log) } + + fn get_syntax(&self) -> Syntax { + self.syntax + } } impl MockRow { diff --git a/src/database/statement.rs b/src/database/statement.rs index 34ece553..2b19d59a 100644 --- a/src/database/statement.rs +++ b/src/database/statement.rs @@ -1,4 +1,4 @@ -use crate::QueryBuilderWithSyntax; +use crate::{QueryBuilderBackend, QueryBuilderWithSyntax, SchemaBuilderBackend}; use sea_query::{ inject_parameters, MysqlQueryBuilder, PostgresQueryBuilder, QueryBuilder, SqliteQueryBuilder, Values, @@ -63,6 +63,22 @@ impl Syntax { Self::Sqlite => Box::new(SqliteQueryBuilder), } } + + pub fn get_query_builder_backend(&self) -> QueryBuilderBackend { + match self { + Self::MySql => QueryBuilderBackend::MySql, + Self::Postgres => QueryBuilderBackend::Postgres, + Self::Sqlite => QueryBuilderBackend::Sqlite, + } + } + + pub fn get_schema_builder_backend(&self) -> SchemaBuilderBackend { + match self { + Self::MySql => SchemaBuilderBackend::MySql, + Self::Postgres => SchemaBuilderBackend::Postgres, + Self::Sqlite => SchemaBuilderBackend::Sqlite, + } + } } impl QueryBuilderWithSyntax for MysqlQueryBuilder { diff --git a/src/database/transaction.rs b/src/database/transaction.rs index 0c49a4e8..7c62da60 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -7,12 +7,12 @@ pub struct Transaction { } impl Transaction { - pub fn from_sql_and_values(sql: &str, values: I) -> Self + pub fn from_sql_and_values(syntax: Syntax, sql: &str, values: I) -> Self where I: IntoIterator, { Self::one(Statement::from_string_values_tuple( - Syntax::Postgres, + syntax, (sql.to_string(), Values(values.into_iter().collect())), )) } diff --git a/src/driver/mock.rs b/src/driver/mock.rs index 96224c38..7f6421e4 100644 --- a/src/driver/mock.rs +++ b/src/driver/mock.rs @@ -1,6 +1,6 @@ use crate::{ - debug_print, error::*, DatabaseConnection, ExecResult, MockDatabase, QueryResult, Statement, - Transaction, + debug_print, error::*, DatabaseConnection, ExecResult, MockDatabase, QueryBuilderBackend, + QueryResult, SchemaBuilderBackend, Statement, Syntax, Transaction, }; use std::sync::{ atomic::{AtomicUsize, Ordering}, @@ -20,17 +20,41 @@ pub trait MockDatabaseTrait: Send { fn query(&mut self, counter: usize, stmt: Statement) -> Result, DbErr>; fn drain_transaction_log(&mut self) -> Vec; + + fn get_syntax(&self) -> Syntax; } impl MockDatabaseConnector { pub fn accepts(string: &str) -> bool { - string.starts_with("mock://") + #[cfg(feature = "sqlx-mysql")] + if crate::SqlxMySqlConnector::accepts(string) { + return true; + } + #[cfg(feature = "sqlx-sqlite")] + if crate::SqlxSqliteConnector::accepts(string) { + return true; + } + false } - pub async fn connect(_string: &str) -> Result { - Ok(DatabaseConnection::MockDatabaseConnection( - MockDatabaseConnection::new(MockDatabase::new()), - )) + pub async fn connect(string: &str) -> Result { + macro_rules! connect_mock_db { + ( $syntax: expr ) => { + Ok(DatabaseConnection::MockDatabaseConnection( + MockDatabaseConnection::new(MockDatabase::new($syntax)), + )) + }; + } + + #[cfg(feature = "sqlx-mysql")] + if crate::SqlxMySqlConnector::accepts(string) { + return connect_mock_db!(Syntax::MySql); + } + #[cfg(feature = "sqlx-sqlite")] + if crate::SqlxSqliteConnector::accepts(string) { + return connect_mock_db!(Syntax::Sqlite); + } + connect_mock_db!(Syntax::Postgres) } } @@ -67,4 +91,20 @@ impl MockDatabaseConnection { let counter = self.counter.fetch_add(1, Ordering::SeqCst); self.mocker.lock().unwrap().query(counter, statement) } + + pub fn get_query_builder_backend(&self) -> QueryBuilderBackend { + self.mocker + .lock() + .unwrap() + .get_syntax() + .get_query_builder_backend() + } + + pub fn get_schema_builder_backend(&self) -> SchemaBuilderBackend { + self.mocker + .lock() + .unwrap() + .get_syntax() + .get_schema_builder_backend() + } } diff --git a/src/entity/base_entity.rs b/src/entity/base_entity.rs index bec0c854..b64e8310 100644 --- a/src/entity/base_entity.rs +++ b/src/entity/base_entity.rs @@ -70,9 +70,9 @@ pub trait EntityTrait: EntityName { /// /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_query_results(vec![ /// # vec![ /// # cake::Model { @@ -126,10 +126,10 @@ pub trait EntityTrait: EntityName { /// db.into_transaction_log(), /// vec![ /// Transaction::from_sql_and_values( - /// r#"SELECT "cake"."id", "cake"."name" FROM "cake" LIMIT $1"#, vec![1u64.into()] + /// Syntax::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake" LIMIT $1"#, vec![1u64.into()] /// ), /// Transaction::from_sql_and_values( - /// r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, vec![] + /// Syntax::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake""#, vec![] /// ), /// ]); /// ``` @@ -143,9 +143,9 @@ pub trait EntityTrait: EntityName { /// /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_query_results(vec![ /// # vec![ /// # cake::Model { @@ -174,15 +174,15 @@ pub trait EntityTrait: EntityName { /// assert_eq!( /// db.into_transaction_log(), /// vec![Transaction::from_sql_and_values( - /// r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "cake"."id" = $1"#, vec![11i32.into()] + /// Syntax::Postgres, r#"SELECT "cake"."id", "cake"."name" FROM "cake" WHERE "cake"."id" = $1"#, vec![11i32.into()] /// )]); /// ``` /// Find by composite key /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_query_results(vec![ /// # vec![ /// # cake_filling::Model { @@ -210,7 +210,9 @@ pub trait EntityTrait: EntityName { /// /// assert_eq!( /// db.into_transaction_log(), - /// vec![Transaction::from_sql_and_values([ + /// vec![Transaction::from_sql_and_values( + /// Syntax::Postgres, + /// [ /// r#"SELECT "cake_filling"."cake_id", "cake_filling"."filling_id" FROM "cake_filling""#, /// r#"WHERE "cake_filling"."cake_id" = $1 AND "cake_filling"."filling_id" = $2"#, /// ].join(" ").as_str(), @@ -243,9 +245,9 @@ pub trait EntityTrait: EntityName { /// /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_exec_results(vec![ /// # MockExecResult { /// # last_insert_id: 15, @@ -274,7 +276,7 @@ pub trait EntityTrait: EntityName { /// assert_eq!( /// db.into_transaction_log(), /// vec![Transaction::from_sql_and_values( - /// r#"INSERT INTO "cake" ("name") VALUES ($1)"#, vec!["Apple Pie".into()] + /// Syntax::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1)"#, vec!["Apple Pie".into()] /// )]); /// ``` fn insert(model: A) -> Insert @@ -290,9 +292,9 @@ pub trait EntityTrait: EntityName { /// /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_exec_results(vec![ /// # MockExecResult { /// # last_insert_id: 28, @@ -325,7 +327,7 @@ pub trait EntityTrait: EntityName { /// assert_eq!( /// db.into_transaction_log(), /// vec![Transaction::from_sql_and_values( - /// r#"INSERT INTO "cake" ("name") VALUES ($1), ($2)"#, + /// Syntax::Postgres, r#"INSERT INTO "cake" ("name") VALUES ($1), ($2)"#, /// vec!["Apple Pie".into(), "Orange Scone".into()] /// )]); /// ``` @@ -345,9 +347,9 @@ pub trait EntityTrait: EntityName { /// /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_exec_results(vec![ /// # MockExecResult { /// # last_insert_id: 0, @@ -377,7 +379,7 @@ pub trait EntityTrait: EntityName { /// assert_eq!( /// db.into_transaction_log(), /// vec![Transaction::from_sql_and_values( - /// r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2"#, vec!["Orange".into(), 1i32.into()] + /// Syntax::Postgres, r#"UPDATE "fruit" SET "name" = $1 WHERE "fruit"."id" = $2"#, vec!["Orange".into(), 1i32.into()] /// )]); /// ``` fn update(model: A) -> UpdateOne @@ -395,9 +397,9 @@ pub trait EntityTrait: EntityName { /// /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_exec_results(vec![ /// # MockExecResult { /// # last_insert_id: 0, @@ -424,7 +426,7 @@ pub trait EntityTrait: EntityName { /// assert_eq!( /// db.into_transaction_log(), /// vec![Transaction::from_sql_and_values( - /// r#"UPDATE "fruit" SET "cake_id" = $1 WHERE "fruit"."name" LIKE $2"#, vec![Value::Null, "%Apple%".into()] + /// Syntax::Postgres, r#"UPDATE "fruit" SET "cake_id" = $1 WHERE "fruit"."name" LIKE $2"#, vec![Value::Null, "%Apple%".into()] /// )]); /// ``` fn update_many() -> UpdateMany { @@ -439,9 +441,9 @@ pub trait EntityTrait: EntityName { /// /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_exec_results(vec![ /// # MockExecResult { /// # last_insert_id: 0, @@ -469,7 +471,7 @@ pub trait EntityTrait: EntityName { /// assert_eq!( /// db.into_transaction_log(), /// vec![Transaction::from_sql_and_values( - /// r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#, vec![3i32.into()] + /// Syntax::Postgres, r#"DELETE FROM "fruit" WHERE "fruit"."id" = $1"#, vec![3i32.into()] /// )]); /// ``` fn delete(model: A) -> DeleteOne @@ -487,9 +489,9 @@ pub trait EntityTrait: EntityName { /// /// ``` /// # #[cfg(feature = "mock")] - /// # use sea_orm::{error::*, MockDatabase, MockExecResult, Transaction, tests_cfg::*}; + /// # use sea_orm::{error::*, tests_cfg::*, MockDatabase, MockExecResult, Transaction, Syntax}; /// # - /// # let db = MockDatabase::new() + /// # let db = MockDatabase::new(Syntax::Postgres) /// # .append_exec_results(vec![ /// # MockExecResult { /// # last_insert_id: 0, @@ -515,7 +517,7 @@ pub trait EntityTrait: EntityName { /// assert_eq!( /// db.into_transaction_log(), /// vec![Transaction::from_sql_and_values( - /// r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE $1"#, vec!["%Apple%".into()] + /// Syntax::Postgres, r#"DELETE FROM "fruit" WHERE "fruit"."name" LIKE $1"#, vec!["%Apple%".into()] /// )]); /// ``` fn delete_many() -> DeleteMany { diff --git a/src/executor/paginator.rs b/src/executor/paginator.rs index 8ea2af9f..6b4459cc 100644 --- a/src/executor/paginator.rs +++ b/src/executor/paginator.rs @@ -103,7 +103,7 @@ where mod tests { use crate::entity::prelude::*; use crate::tests_cfg::*; - use crate::{DatabaseConnection, MockDatabase, Transaction}; + use crate::{DatabaseConnection, MockDatabase, Syntax, Transaction}; use futures::TryStreamExt; use sea_query::{Alias, Expr, SelectStatement, Value}; @@ -129,7 +129,7 @@ mod tests { let page3 = Vec::::new(); - let db = MockDatabase::new() + let db = MockDatabase::new(Syntax::Postgres) .append_query_results(vec![page1.clone(), page2.clone(), page3.clone()]) .into_connection(); @@ -138,7 +138,7 @@ mod tests { fn setup_num_rows() -> (DatabaseConnection, i32) { let num_rows = 3; - let db = MockDatabase::new() + let db = MockDatabase::new(Syntax::Postgres) .append_query_results(vec![vec![maplit::btreemap! { "num_rows" => Into::::into(num_rows), }]]) diff --git a/src/query/json.rs b/src/query/json.rs index 98cf49b9..8284427c 100644 --- a/src/query/json.rs +++ b/src/query/json.rs @@ -102,12 +102,12 @@ impl FromQueryResult for JsonValue { #[cfg(feature = "mock")] mod tests { use crate::tests_cfg::cake; - use crate::{entity::*, MockDatabase}; + use crate::{entity::*, MockDatabase, Syntax}; use sea_query::Value; #[async_std::test] async fn to_json_1() { - let db = MockDatabase::new() + let db = MockDatabase::new(Syntax::Postgres) .append_query_results(vec![vec![maplit::btreemap! { "id" => Into::::into(128), "name" => Into::::into("apple") }]])